Skip to content

Commit

Permalink
Add new option to disable vertex snapping - snapVertex (#1539) (minor)
Browse files Browse the repository at this point in the history
* Add new option to disable vertex snapping

* Add snapVertex to TypeScript

* add missing snap option to default Edit options
  • Loading branch information
Falke-Design authored Nov 24, 2024
1 parent 408b197 commit 480f490
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 46 deletions.
43 changes: 43 additions & 0 deletions cypress/e2e/line.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,4 +407,47 @@ describe('Draw & Edit Line', () => {

cy.hasVertexMarkers(2);
});

it("doesn't snap to the vertex", () => {
cy.window().then(({ map }) => {
map.pm.setGlobalOptions({ snapVertex: false });
});

// activate polyline drawing
cy.toolbarButton('polyline')
.click()
.closest('.button-container')
.should('have.class', 'active');

// draw a polyline
cy.get(mapSelector).click(90, 250).click(150, 50).click(150, 50);

// activate polyline drawing
cy.toolbarButton('polyline')
.click()
.closest('.button-container')
.should('have.class', 'active');

// draw a polyline
cy.get(mapSelector).click(150, 60).click(250, 50).click(250, 50);

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0].lat).to.eq(51.52538802368748);
expect(layer.getLatLngs()[0].lng).to.eq(-0.15050450596240997);
});

cy.toolbarButton('edit').click();

cy.get(mapSelector)
.trigger('mousedown', 150, 60, { which: 1 })
.trigger('mousemove', 150, 55, { which: 1 })
.trigger('mouseup', 150, 55, { which: 1 });

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0].lat).to.eq(51.5258877375718);
expect(layer.getLatLngs()[0].lng).to.eq(-0.15026355008465944);
});
});
});
47 changes: 47 additions & 0 deletions cypress/e2e/polygon.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1418,4 +1418,51 @@ describe('Draw & Edit Poly', () => {

cy.hasVertexMarkers(3);
});

it("doesn't snap to the vertex", () => {
cy.window().then(({ map }) => {
map.pm.setGlobalOptions({ snapVertex: false });
});

cy.toolbarButton('polygon')
.click()
.closest('.button-container')
.should('have.class', 'active');

cy.get(mapSelector)
.click(50, 250)
.click(150, 50)
.click(250, 50)
.click(50, 250);

cy.toolbarButton('polygon')
.click()
.closest('.button-container')
.should('have.class', 'active');

cy.get(mapSelector)
.click(150, 60)
.click(250, 90)
.click(200, 90)
.click(150, 60);

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0][0].lat).to.eq(51.5255134425896);
expect(layer.getLatLngs()[0][0].lng).to.eq(-0.15071868896484378);
});

cy.toolbarButton('edit').click();

cy.get(mapSelector)
.trigger('mousedown', 150, 60, { which: 1 })
.trigger('mousemove', 150, 55, { which: 1 })
.trigger('mouseup', 150, 55, { which: 1 });

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0][0].lat).to.eq(51.52594064813257);
expect(layer.getLatLngs()[0][0].lng).to.eq(-0.15037536621093753);
});
});
});
39 changes: 39 additions & 0 deletions cypress/e2e/rectangle.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1040,4 +1040,43 @@ describe('Draw Rectangle', () => {
expect(map.pm.getGeomanDrawLayers().length).to.eql(0);
});
});

it("doesn't snap to the vertex", () => {
cy.window().then(({ map }) => {
map.pm.setGlobalOptions({ snapVertex: false });
});

cy.toolbarButton('rectangle')
.click()
.closest('.button-container')
.should('have.class', 'active');

cy.get(mapSelector).click(90, 250).click(150, 50);

cy.toolbarButton('rectangle')
.click()
.closest('.button-container')
.should('have.class', 'active');

cy.get(mapSelector).click(150, 60).click(250, 90);

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0][1].lat).to.eq(51.52529983831507);
expect(layer.getLatLngs()[0][1].lng).to.eq(-0.15003204345703128);
});

cy.toolbarButton('edit').click();

cy.get(mapSelector)
.trigger('mousedown', 150, 60, { which: 1 })
.trigger('mousemove', 150, 55, { which: 1 })
.trigger('mouseup', 150, 55, { which: 1 });

cy.window().then(({ map }) => {
const layer = map.pm.getGeomanDrawLayers()[1];
expect(layer.getLatLngs()[0][1].lat).to.eq(51.525833847122584);
expect(layer.getLatLngs()[0][1].lng).to.eq(-0.13286590576171878);
});
});
});
37 changes: 19 additions & 18 deletions leaflet-geoman.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1132,12 +1132,7 @@ declare module 'leaflet' {
event: any;
}) => boolean;

interface EditModeOptions {
/** Enable snapping to other layers vertices for precision drawing. Can be disabled by holding the ALT key (default:true). */
snappable?: boolean;

/** The distance to another vertex when a snap should happen (default:20). */
snapDistance?: number;
interface EditModeOptions extends SnappingOptions {

/** Allow self intersections (default:true). */
allowSelfIntersection?: boolean;
Expand Down Expand Up @@ -1229,18 +1224,7 @@ declare module 'leaflet' {
className?: string;
}

interface DrawModeOptions {
/** Enable snapping to other layers vertices for precision drawing. Can be disabled by holding the ALT key (default:true). */
snappable?: boolean;

/** The distance to another vertex when a snap should happen (default:20). */
snapDistance?: number;

/** Allow snapping in the middle of two vertices (middleMarker)(default:false). */
snapMiddle?: boolean;

/** Allow snapping between two vertices. (default: true)*/
snapSegment?: boolean;
interface DrawModeOptions extends SnappingOptions {

/** Require the last point of a shape to be snapped. (default: false). */
requireSnapToFinish?: boolean;
Expand Down Expand Up @@ -1318,6 +1302,23 @@ declare module 'leaflet' {
textOptions?: TextOptions;
}

interface SnappingOptions {
/** Enable snapping to other layers vertices for precision drawing. Can be disabled by holding the ALT key (default:true). */
snappable?: boolean;

/** The distance to another vertex when a snap should happen (default:20). */
snapDistance?: number;

/** Allow snapping in the middle of two vertices (middleMarker)(default:false). */
snapMiddle?: boolean;

/** Allow snapping between two vertices. (default: true)*/
snapSegment?: boolean;

/** Allow snapping to vertices. (default: true)*/
snapVertex?: boolean;
}

/**
* PM toolbar options.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/js/Draw/L.PM.Draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ const Draw = L.Class.extend({
text: null,
focusAfterDraw: null,
removeIfEmpty: null,
className: null
className: null,
},
snapVertex: true,
},
setOptions(options) {
L.Util.setOptions(this, options);
Expand Down
2 changes: 2 additions & 0 deletions src/js/Edit/L.PM.Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const Edit = L.Class.extend({
moveVertexValidation: undefined,
resizeableCircleMarker: false,
resizeableCircle: true,
snapMiddle: false,
snapVertex: true,
},
setOptions(options) {
L.Util.setOptions(this, options);
Expand Down
54 changes: 27 additions & 27 deletions src/js/Mixins/Snapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -490,40 +490,40 @@ const SnapMixin = {
// The closest point on the closest segment of the closest polygon to P. That's right.
const C = closestLayer.latlng;

// distances from A to C and B to C to check which one is closer to C
const distanceAC = this._getDistance(map, A, C);
const distanceBC = this._getDistance(map, B, C);
// the latlng we ultemately want to snap to
let snapLatlng = C;

// closest latlng of A and B to C
let closestVertexLatLng = distanceAC < distanceBC ? A : B;
if (this.options.snapVertex) {
// distances from A to C and B to C to check which one is closer to C
const distanceAC = this._getDistance(map, A, C);
const distanceBC = this._getDistance(map, B, C);

// distance between closestVertexLatLng and C
let shortestDistance = distanceAC < distanceBC ? distanceAC : distanceBC;
// closest latlng of A and B to C
let closestVertexLatLng = distanceAC < distanceBC ? A : B;

// snap to middle (M) of segment if option is enabled
if (this.options.snapMiddle) {
const M = L.PM.Utils.calcMiddleLatLng(map, A, B);
const distanceMC = this._getDistance(map, M, C);
// distance between closestVertexLatLng and C
let shortestDistance = distanceAC < distanceBC ? distanceAC : distanceBC;

if (distanceMC < distanceAC && distanceMC < distanceBC) {
// M is the nearest vertex
closestVertexLatLng = M;
shortestDistance = distanceMC;
}
}
// snap to middle (M) of segment if option is enabled
if (this.options.snapMiddle) {
const M = L.PM.Utils.calcMiddleLatLng(map, A, B);
const distanceMC = this._getDistance(map, M, C);

// the distance that needs to be undercut to trigger priority
const priorityDistance = this.options.snapDistance;
if (distanceMC < distanceAC && distanceMC < distanceBC) {
// M is the nearest vertex
closestVertexLatLng = M;
shortestDistance = distanceMC;
}
}

// the latlng we ultemately want to snap to
let snapLatlng;
// the distance that needs to be undercut to trigger priority
const priorityDistance = this.options.snapDistance;

// if C is closer to the closestVertexLatLng (A, B or M) than the snapDistance,
// the closestVertexLatLng has priority over C as the snapping point.
if (shortestDistance < priorityDistance) {
snapLatlng = closestVertexLatLng;
} else {
snapLatlng = C;
// if C is closer to the closestVertexLatLng (A, B or M) than the snapDistance,
// the closestVertexLatLng has priority over C as the snapping point.
if (shortestDistance < priorityDistance) {
snapLatlng = closestVertexLatLng;
}
}

// return the copy of snapping point
Expand Down

0 comments on commit 480f490

Please sign in to comment.