Skip to content

Commit 8ae233f

Browse files
committed
feat: limit max guides generated per feature via an option
1 parent c808a36 commit 8ae233f

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

src/control/cad.js

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Feature from 'ol/Feature';
44
import Vector from 'ol/layer/Vector';
55
import VectorSource from 'ol/source/Vector';
66
import { Pointer, Snap } from 'ol/interaction';
7+
import { distance as euclideanDistance } from 'ol/coordinate';
78
import { OverlayOp } from 'jsts/org/locationtech/jts/operation/overlay';
89
import { getUid } from 'ol/util';
910
import Control from './control';
@@ -40,6 +41,8 @@ class CadControl extends Control {
4041
* @param {Function} [options.lineFilter] An optional filter for the generated snapping lines
4142
* array (takes the lines and cursor coordinate as arguments and returns the new line array)
4243
* @param {Number} [options.nbClosestFeatures] Number of features to use for snapping (closest first). Default is 5.
44+
* @param {Number} [options.limitGuidesPerFeature] A feature with complex geometry may generate
45+
* a large number of lines. This option can be used to limit the guides to the n closest segments. Deafult is 3.
4346
* @param {Number} [options.snapTolerance] Snap tolerance in pixel
4447
* for snap lines. Default is 10.
4548
* @param {Boolean} [options.showSnapLines] Whether to show
@@ -134,6 +137,18 @@ class CadControl extends Control {
134137
this.nbClosestFeatures =
135138
options.nbClosestFeatures === undefined ? 5 : options.nbClosestFeatures;
136139

140+
/**
141+
* Number of guide lines to limit cad to generate for a single feature.
142+
* this.nbClosestFeatures * this.limitGuidesPerFeature will be the maximum
143+
* number of guides shown at any time. Default is 3.
144+
* @type {Number}
145+
* @private
146+
*/
147+
this.limitGuidesPerFeature =
148+
options.limitGuidesPerFeature === undefined
149+
? 3
150+
: options.limitGuidesPerFeature;
151+
137152
/**
138153
* Snap tolerance in pixel.
139154
* @type {Number}
@@ -505,7 +520,6 @@ class CadControl extends Control {
505520
getSegmentLines(coordinate, snapCoords, snapCoordsBefore) {
506521
const mousePx = this.map.getPixelFromCoordinate(coordinate);
507522
const doubleTol = this.snapTolerance * 2;
508-
const [mouseX, mouseY] = mousePx;
509523
const lines = [];
510524

511525
for (let i = 0; i < snapCoords.length; i += 1) {
@@ -522,13 +536,12 @@ class CadControl extends Control {
522536

523537
// Calculate projected point
524538
const projMousePx = getProjectedPoint(mousePx, snapPxBefore, snapPx);
525-
const [projMouseX, projMouseY] = projMousePx;
526-
const distance = Math.sqrt(
527-
(projMouseX - mouseX) ** 2 + (projMouseY - mouseY) ** 2,
528-
);
539+
const distance = euclideanDistance(mousePx, projMousePx);
540+
529541
let newPt;
530542

531543
if (distance <= this.snapTolerance) {
544+
const [projMouseX, projMouseY] = projMousePx;
532545
// lineFunc is undefined when it's a vertical line
533546
const lineFunc = getEquationOfLine(snapPxBefore, snapPx);
534547
const newX = projMouseX + (projMouseX < snapX ? -doubleTol : doubleTol);
@@ -557,7 +570,6 @@ class CadControl extends Control {
557570
getOrthoLines(coordinate, snapCoords, snapCoordsBefore) {
558571
const mousePx = this.map.getPixelFromCoordinate(coordinate);
559572
const doubleTol = this.snapTolerance * 2;
560-
const [mouseX, mouseY] = mousePx;
561573
const lines = [];
562574

563575
for (let i = 0; i < snapCoords.length; i += 1) {
@@ -579,13 +591,11 @@ class CadControl extends Control {
579591
[orthoLine1, orthoLine2].forEach((line) => {
580592
const [anchorPx, last] = line.getCoordinates();
581593
const projMousePx = getProjectedPoint(mousePx, anchorPx, last);
582-
const [projMouseX, projMouseY] = projMousePx;
583-
const distance = Math.sqrt(
584-
(projMouseX - mouseX) ** 2 + (projMouseY - mouseY) ** 2,
585-
);
594+
const distance = euclideanDistance(mousePx, projMousePx);
586595

587596
let newPt;
588597
if (distance <= this.snapTolerance) {
598+
const [projMouseX, projMouseY] = projMousePx;
589599
// lineFunc is undefined when it's a vertical line
590600
const lineFunc = getEquationOfLine(anchorPx, projMousePx);
591601
const newX =
@@ -623,6 +633,27 @@ class CadControl extends Control {
623633
const snapCoords = [];
624634
const snapCoordsAfter = []; // store the direct next point in the coordinate array
625635

636+
// Parse the list of coords, we will add the ortho and segment lines which
637+
// are closest to the users cursor up until the limit of `this.limitGuidesPerFeature`
638+
const parseCoordList = (coords) => {
639+
// Check the euclidean distance between coord at index and the
640+
// included vertices so far. Create an array of `this.limitGuidesPerFeature`
641+
// closest items.
642+
const sortedCoords = coords
643+
.slice()
644+
.sort(
645+
(a, b) =>
646+
euclideanDistance(a, coordinate) - euclideanDistance(b, coordinate),
647+
);
648+
const includedCoords = sortedCoords.slice(0, this.limitGuidesPerFeature);
649+
650+
includedCoords.forEach((index) => {
651+
snapCoordsBefore.push(coords[index - 1]);
652+
snapCoords.push(coords[index]);
653+
snapCoordsAfter.push(coords[index + 1]);
654+
});
655+
};
656+
626657
for (let i = 0; i < features.length; i += 1) {
627658
const geom = features[i].getGeometry();
628659
let featureCoord = geom.getCoordinates();
@@ -641,17 +672,9 @@ class CadControl extends Control {
641672
// Add feature vertices
642673
// eslint-disable-next-line no-lonely-if
643674
if (geom instanceof LineString) {
644-
for (let j = 0; j < featureCoord.length; j += 1) {
645-
snapCoordsBefore.push(featureCoord[j - 1]);
646-
snapCoords.push(featureCoord[j]);
647-
snapCoordsAfter.push(featureCoord[j + 1]);
648-
}
675+
parseCoordList(featureCoord);
649676
} else if (geom instanceof Polygon) {
650-
for (let j = 0; j < featureCoord[0].length; j += 1) {
651-
snapCoordsBefore.push(featureCoord[0][j - 1]);
652-
snapCoords.push(featureCoord[0][j]);
653-
snapCoordsAfter.push(featureCoord[0][j + 1]);
654-
}
677+
parseCoordList(featureCoord[0]);
655678
}
656679

657680
// Add extent vertices

0 commit comments

Comments
 (0)