Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new option to disable vertex snapping #1539

Merged
merged 3 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading