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

feat: allow to modifiy circle geometry #270

Merged
merged 16 commits into from
May 10, 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
5 changes: 1 addition & 4 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
},
"plugins": ["cypress", "prettier"],
"rules": {
"prettier/prettier": "error",
"arrow-body-style": "off",
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off"
"prettier/prettier": "error"
}
}
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
3 changes: 2 additions & 1 deletion cypress/e2e/control/cad.spec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
const FORCE = { force: true };

const coordToFixed = (coordArray, decimals) => {
return [
const arr = [
parseFloat(coordArray[0].toFixed(decimals)),
parseFloat(coordArray[1].toFixed(decimals)),
];
return arr;
};

describe('CAD control', () => {
Expand Down
43 changes: 22 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,31 @@
"ol": "^7"
},
"devDependencies": {
"@commitlint/cli": "17.6.1",
"@commitlint/config-conventional": "17.6.1",
"cypress": "12.10.0",
"esbuild": "0.17.17",
"eslint": "8.38.0",
"@commitlint/cli": "19.3.0",
"@commitlint/config-conventional": "19.2.2",
"cypress": "13.9.0",
"esbuild": "0.21.1",
"eslint": "8",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-cypress": "2.13.2",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-prettier": "4.2.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-cypress": "3.2.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-prettier": "5.1.3",
"fixpack": "4.0.0",
"husky": "8.0.3",
"husky": "9.0.11",
"is-ci": "3.0.1",
"jsdoc": "4.0.2",
"jsdoc": "4.0.3",
"jsdoc-export-default-interop": "0.3.1",
"jsts": "2.9.3",
"lint-staged": "13.2.1",
"ol": "7.3.0",
"prettier": "2.8.7",
"jsts": "2.11.3",
"lint-staged": "15.2.2",
"ol": "8",
"prettier": "3.2.5",
"shx": "0.3.4",
"standard-version": "9.5.0",
"start-server-and-test": "2.0.0",
"stylelint": "15.5.0",
"stylelint-config-standard": "33.0.0",
"typescript": "5.0.4"
"start-server-and-test": "2.0.3",
"stylelint": "16.5.0",
"stylelint-config-standard": "36.0.0",
"typescript": "5.4.5"
},
"scripts": {
"build": "shx rm -rf build && tsc --project config/tsconfig-build.json && esbuild build/index.js --bundle --global-name=ole --loader:.svg=dataurl --minify --outfile=build/bundle.js",
Expand All @@ -43,14 +43,15 @@
"cy:test": "start-server-and-test start http://127.0.0.1:8000 cy:run",
"doc": "jsdoc -p -r -c jsdoc_conf.json src -d doc README.md && shx cp build/bundle.js index.js",
"format": "prettier --write 'cypress/integration/*.js' 'src/**/*.js' && eslint 'src/**/*.js' --fix && stylelint 'style/**/*.css' 'src/**/*.css' 'src/**/*.scss' --fix",
"lint": "eslint 'cypress/e2e/**/*.js' 'src/**/*.js' && stylelint 'style/**/*.css' 'src/**/*.css' 'src/**/*.scss'",
"lint": "ESLINT_USE_FLAT_CONFIG=false eslint 'cypress/e2e/**/*.js' 'src/**/*.js' && stylelint 'style/**/*.css' 'src/**/*.css' 'src/**/*.scss'",
"prepare": "is-ci || husky install",
"publish:beta": "yarn release -- --prerelease beta --skip.changelog && yarn build && git push origin HEAD && git push --tags && yarn publish --tag beta",
"publish:beta:dryrun": "yarn release -- --prerelease beta --dry-run --skip.changelog",
"publish:public": "yarn release && yarn build && git push origin HEAD && git push --tags && yarn publish",
"publish:public:dryrun": "yarn release --dry-run",
"release": "standard-version",
"start": "esbuild src/index.js --bundle --global-name=ole --loader:.svg=dataurl --minify --outfile=index.js --serve=localhost:8000 --servedir=. --sourcemap --watch=forever"
"start": "esbuild src/index.js --bundle --global-name=ole --loader:.svg=dataurl --minify --outfile=index.js --serve=localhost:8000 --servedir=. --sourcemap --watch=forever",
"up": "yarn upgrade-interactive --latest"
},
"keywords": [
"Editor",
Expand Down
85 changes: 39 additions & 46 deletions src/control/cad.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Style, Stroke } from 'ol/style';
import { Point, LineString, Polygon, MultiPoint } from 'ol/geom';
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 { OverlayOp } from 'jsts/org/locationtech/jts/operation/overlay';
import { getUid } from 'ol/util';
import Control from './control';
import cadSVG from '../../img/cad.svg';
import { SnapEvent, SnapEventType } from '../event';
Expand Down Expand Up @@ -143,7 +144,7 @@ class CadControl extends Control {
* @type {Function}
* @private
*/
this.filter = options.filter || null;
this.filter = options.filter || (() => true);

/**
* Interaction for snapping
Expand Down Expand Up @@ -246,47 +247,33 @@ class CadControl extends Control {
* to a given coordinate.
* @private
* @param {ol.Coordinate} coordinate Coordinate.
* @param {Number} numFeatures Number of features to search.
* @param {Number} nbFeatures Number of features to search.
* @returns {Array.<ol.Feature>} List of closest features.
*/
getClosestFeatures(coordinate, numFeatures) {
const num = numFeatures || 1;
const ext = [-Infinity, -Infinity, Infinity, Infinity];
const featureDict = {};

const pushSnapFeatures = (f) => {
const cCoord = f.getGeometry().getClosestPoint(coordinate);
const dx = cCoord[0] - coordinate[0];
const dy = cCoord[1] - coordinate[1];
const dist = dx * dx + dy * dy;
featureDict[dist] = f;
};

this.source.forEachFeatureInExtent(ext, (f) => {
if (!this.filter || (this.filter && this.filter(f))) {
pushSnapFeatures(f);
}
});

const dists = Object.keys(featureDict);
let features = [];
const count = Math.min(dists.length, num);

dists.sort((a, b) => a - b);

for (let i = 0; i < count; i += 1) {
features.push(featureDict[dists[i]]);
}

// Remove edit and draw feature for snapping list.
getClosestFeatures(coordinate, nbFeatures = 1) {
const editFeature = this.editor.getEditFeature();
const drawFeature = this.editor.getDrawFeature();
[editFeature, drawFeature].forEach((feature) => {
const index = features.indexOf(feature);
if (index > -1) {
features.splice(index, 1);
const currentFeatures = [editFeature, drawFeature].filter((f) => !!f);

const cacheDist = {};
const dist = (f) => {
const uid = getUid(f);
if (!cacheDist[uid]) {
const cCoord = f.getGeometry().getClosestPoint(coordinate);
const dx = cCoord[0] - coordinate[0];
const dy = cCoord[1] - coordinate[1];
cacheDist[uid] = dx * dx + dy * dy;
}
});
return cacheDist[uid];
};
const sortByDistance = (a, b) => dist(a) - dist(b);

let features = this.source
.getFeatures()
.filter(this.filter)
.filter((f) => !currentFeatures.includes(f))
.sort(sortByDistance)
.slice(0, nbFeatures);

// When using showSnapPoints, return all features except edit/draw features
if (this.properties.showSnapPoints) {
Expand All @@ -295,10 +282,10 @@ class CadControl extends Control {

// When using showSnapLines, return all features but edit/draw features are
// cloned to remove the node at the mouse position.
[editFeature, drawFeature]
.filter((f) => f)
.forEach((feature) => {
const geom = feature.getGeometry();
currentFeatures.filter(this.filter).forEach((feature) => {
const geom = feature.getGeometry();

if (!(geom instanceof Circle) && !(geom instanceof Point)) {
const snapGeom = getShiftedMultiPoint(geom, coordinate);
const isPolygon = geom instanceof Polygon;
const snapFeature = feature.clone();
Expand All @@ -308,7 +295,8 @@ class CadControl extends Control {
isPolygon ? [snapGeom.getCoordinates()] : snapGeom.getCoordinates(),
);
features = [snapFeature, ...features];
});
}
});

return features;
}
Expand Down Expand Up @@ -615,10 +603,15 @@ class CadControl extends Control {

for (let i = 0; i < features.length; i += 1) {
const geom = features[i].getGeometry();
const featureCoord = geom.getCoordinates();
let featureCoord = geom.getCoordinates();

if (!featureCoord && geom instanceof Circle) {
featureCoord = geom.getCenter();
}

// Polygons initially return a geometry with an empty coordinate array, so we need to catch it
if (featureCoord.length) {
if (geom instanceof Point) {
if (featureCoord?.length) {
if (geom instanceof Point || geom instanceof Circle) {
snapCoordsBefore.push();
snapCoords.push(featureCoord);
snapCoordsAfter.push();
Expand Down
2 changes: 1 addition & 1 deletion src/control/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DrawControl extends Control {
});

this.drawInteraction.on('drawend', () => {
this.editor.setDrawFeature(null);
this.editor.setDrawFeature();
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/control/modify.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class ModifyControl extends Control {
});

this.moveInteraction.on('moveend', () => {
this.editor.setEditFeature(null);
this.editor.setEditFeature();
this.isMoving = false;
});
this.moveInteraction.setActive(false);
Expand Down Expand Up @@ -198,7 +198,7 @@ class ModifyControl extends Control {
});

this.modifyInteraction.on('modifyend', () => {
this.editor.setEditFeature(null);
this.editor.setEditFeature();
this.isModifying = false;
});
this.modifyInteraction.setActive(false);
Expand Down
4 changes: 1 addition & 3 deletions src/helper/getEquationOfLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ const getEquationOfLine = (coordA, coordB) => {
}
const m = (yB - yA) / (xB - xA);
const b = yB - m * xB;
return (x) => {
return m * x + b;
};
return (x) => m * x + b;
};

export default getEquationOfLine;
4 changes: 1 addition & 3 deletions src/helper/getProjectedPoint.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
const dotProduct = (e1, e2) => {
return e1[0] * e2[0] + e1[1] * e2[1];
};
const dotProduct = (e1, e2) => e1[0] * e2[0] + e1[1] * e2[1];

/**
* Get projected point P' of P on line e1. Faster version.
Expand Down
6 changes: 3 additions & 3 deletions src/helper/getShiftedMultiPoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ const getShiftedMultipoint = (geometry, coordinate) => {

// Exclude the node being modified
shiftedMultipoint.setCoordinates(
shiftedMultipoint.getCoordinates().filter((coord) => {
return coord.toString() !== drawNodeCoordinate.toString();
}),
shiftedMultipoint
.getCoordinates()
.filter((coord) => coord.toString() !== drawNodeCoordinate.toString()),
);

return shiftedMultipoint;
Expand Down
6 changes: 3 additions & 3 deletions src/interaction/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ class Delete extends Interaction {
this.condition =
options.condition ||
((mapBrowserEvent) => {
return (
const bool =
noModifierKeys(mapBrowserEvent) &&
targetNotEditable(mapBrowserEvent) &&
(mapBrowserEvent.originalEvent.keyCode === 46 ||
mapBrowserEvent.originalEvent.keyCode === 8)
);
mapBrowserEvent.originalEvent.keyCode === 8);
return bool;
});
}

Expand Down
Loading
Loading