Skip to content

Commit

Permalink
feat: limit max guides generated per feature via an option
Browse files Browse the repository at this point in the history
  • Loading branch information
megawac committed Aug 27, 2024
1 parent c808a36 commit feb03ce
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 22 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"description": "OpenLayers Editor",
"version": "2.4.4",
"main": "build/index.js",
"dependencies": {},
"peerDependencies": {
"jsts": ">=2",
"lodash.throttle": ">=4",
Expand Down
75 changes: 55 additions & 20 deletions src/control/cad.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { times, sortedIndexBy } from 'lodash';
import { Style, Stroke } from 'ol/style';
import { Point, LineString, Polygon, MultiPoint, Circle } from 'ol/geom';
import Feature from 'ol/Feature';
import Vector from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Pointer, Snap } from 'ol/interaction';
import { distance as euclideanDistance } from 'ol/coordinate';
import { OverlayOp } from 'jsts/org/locationtech/jts/operation/overlay';
import { getUid } from 'ol/util';
import Control from './control';
Expand Down Expand Up @@ -40,6 +42,8 @@ class CadControl extends Control {
* @param {Function} [options.lineFilter] An optional filter for the generated snapping lines
* array (takes the lines and cursor coordinate as arguments and returns the new line array)
* @param {Number} [options.nbClosestFeatures] Number of features to use for snapping (closest first). Default is 5.
* @param {Number} [options.limitGuidesPerFeature] A feature with complex geometry may generate
* a large number of lines. This option can be used to limit the guides to the n closest segments. Deafult is 3.
* @param {Number} [options.snapTolerance] Snap tolerance in pixel
* for snap lines. Default is 10.
* @param {Boolean} [options.showSnapLines] Whether to show
Expand Down Expand Up @@ -134,6 +138,18 @@ class CadControl extends Control {
this.nbClosestFeatures =
options.nbClosestFeatures === undefined ? 5 : options.nbClosestFeatures;

/**
* Number of guide lines to limit cad to generate for a single feature.
* this.nbClosestFeatures * this.limitGuidesPerFeature will be the maximum
* number of guides shown at any time. Default is 3.
* @type {Number}
* @private
*/
this.limitGuidesPerFeature =
options.limitGuidesPerFeature === undefined
? 3
: options.limitGuidesPerFeature;

/**
* Snap tolerance in pixel.
* @type {Number}
Expand Down Expand Up @@ -505,7 +521,6 @@ class CadControl extends Control {
getSegmentLines(coordinate, snapCoords, snapCoordsBefore) {
const mousePx = this.map.getPixelFromCoordinate(coordinate);
const doubleTol = this.snapTolerance * 2;
const [mouseX, mouseY] = mousePx;
const lines = [];

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

// Calculate projected point
const projMousePx = getProjectedPoint(mousePx, snapPxBefore, snapPx);
const [projMouseX, projMouseY] = projMousePx;
const distance = Math.sqrt(
(projMouseX - mouseX) ** 2 + (projMouseY - mouseY) ** 2,
);
const distance = euclideanDistance(mousePx, projMousePx);

let newPt;

if (distance <= this.snapTolerance) {
const [projMouseX, projMouseY] = projMousePx;
// lineFunc is undefined when it's a vertical line
const lineFunc = getEquationOfLine(snapPxBefore, snapPx);
const newX = projMouseX + (projMouseX < snapX ? -doubleTol : doubleTol);
Expand Down Expand Up @@ -557,7 +571,6 @@ class CadControl extends Control {
getOrthoLines(coordinate, snapCoords, snapCoordsBefore) {
const mousePx = this.map.getPixelFromCoordinate(coordinate);
const doubleTol = this.snapTolerance * 2;
const [mouseX, mouseY] = mousePx;
const lines = [];

for (let i = 0; i < snapCoords.length; i += 1) {
Expand All @@ -579,13 +592,11 @@ class CadControl extends Control {
[orthoLine1, orthoLine2].forEach((line) => {
const [anchorPx, last] = line.getCoordinates();
const projMousePx = getProjectedPoint(mousePx, anchorPx, last);
const [projMouseX, projMouseY] = projMousePx;
const distance = Math.sqrt(
(projMouseX - mouseX) ** 2 + (projMouseY - mouseY) ** 2,
);
const distance = euclideanDistance(mousePx, projMousePx);

let newPt;
if (distance <= this.snapTolerance) {
const [projMouseX, projMouseY] = projMousePx;
// lineFunc is undefined when it's a vertical line
const lineFunc = getEquationOfLine(anchorPx, projMousePx);
const newX =
Expand Down Expand Up @@ -623,6 +634,38 @@ class CadControl extends Control {
const snapCoords = [];
const snapCoordsAfter = []; // store the direct next point in the coordinate array

// Parse the list of coords, we will add the ortho and segment lines which
// are closest to the users cursor up until the limit of `this.limitGuidesPerFeature`
const parseCoordList = (coords) => {
let includedCoords;
if (coords.length > this.limitGuidesPerFeature) {
includedCoords = [];
// Check the euclidean distance between coord at index and the
// included vertices so far. Create an array of `this.limitGuidesPerFeature`
// closest items.
for (let index = 0; index < coords.length; index += 1) {
const addIndex = sortedIndexBy(includedCoords, index, (i) =>
euclideanDistance(coords[i], coordinate),
);
if (addIndex < this.limitGuidesPerFeature) {
includedCoords.splice(
addIndex,
includedCoords.length === this.limitGuidesPerFeature ? 1 : 0,
index,
);
}
}
} else {
includedCoords = times(coords.length);
}

includedCoords.forEach((index) => {
snapCoordsBefore.push(coords[index - 1]);
snapCoords.push(coords[index]);
snapCoordsAfter.push(coords[index + 1]);
});
};

for (let i = 0; i < features.length; i += 1) {
const geom = features[i].getGeometry();
let featureCoord = geom.getCoordinates();
Expand All @@ -641,17 +684,9 @@ class CadControl extends Control {
// Add feature vertices
// eslint-disable-next-line no-lonely-if
if (geom instanceof LineString) {
for (let j = 0; j < featureCoord.length; j += 1) {
snapCoordsBefore.push(featureCoord[j - 1]);
snapCoords.push(featureCoord[j]);
snapCoordsAfter.push(featureCoord[j + 1]);
}
parseCoordList(featureCoord);
} else if (geom instanceof Polygon) {
for (let j = 0; j < featureCoord[0].length; j += 1) {
snapCoordsBefore.push(featureCoord[0][j - 1]);
snapCoords.push(featureCoord[0][j]);
snapCoordsAfter.push(featureCoord[0][j + 1]);
}
parseCoordList(featureCoord[0]);
}

// Add extent vertices
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3904,7 +3904,7 @@ lodash.upperfirst@^4.3.1:

lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
resolved "https://npm.clearpathrobotics.com:443/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

log-symbols@^4.0.0:
Expand Down

0 comments on commit feb03ce

Please sign in to comment.