Skip to content

Commit

Permalink
0.4.0 - Fixed geometry editing (#4)
Browse files Browse the repository at this point in the history
* Bumped

* Added editing placeholder

* Fixed start editing from between line segments.

* Updated changeslog

* Fixed autofocusing

* Updated changes log
  • Loading branch information
ponlawat-w authored Dec 15, 2023
1 parent 4aa9cdb commit 0a813e4
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 20 deletions.
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
Updated imports and exports
- Added sketch point for edit only mode.
- Fixed start editing from between line segments.
- Fixed autofocusing.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ol-osmwaysnap",
"type": "module",
"version": "0.3.2",
"version": "0.4.0",
"description": "OpenLayers Interaction Extension for Snapping Ways from OSM using Overpass API",
"keywords": [
"osm",
Expand All @@ -14,7 +14,7 @@
"main": "dist/index.js",
"scripts": {
"build": "npx tsc && npx webpack",
"test": "npm run build && npx vitest run --config ./vitest.config.ts"
"test": "npx vitest run --config ./vitest.config.ts"
},
"repository": {
"type": "git",
Expand Down
36 changes: 26 additions & 10 deletions src/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ export default class OSMWaySnap extends PointerInteraction {

/** Layer of snapping ways */
private wayLayer: VectorLayer<VectorSource<Feature<LineString>>>|undefined = undefined;
/** Snap interaction */
private snapInteraction: Snap;
/** Snap interaction to waySource */
private snapWayInteraction: Snap;
/** Snap interaction to source */
private snapSourceInteraction: Snap;

/**
* Constructor
Expand All @@ -118,7 +120,8 @@ export default class OSMWaySnap extends PointerInteraction {
overpassQuery: options.overpassQuery ?? '(way["highway"];>;);',
overpassEndpointURL: options.overpassEndpointURL ?? undefined
});
this.snapInteraction = new Snap({ source: this.waySource });
this.snapWayInteraction = new Snap({ source: this.waySource });
this.snapSourceInteraction = new Snap({ source: this.source });

if (options.createAndAddWayLayer ?? true) {
this.wayLayer = new VectorLayer({ source: this.waySource, style: OSMOverpassWaySource.getDefaultStyle() });
Expand Down Expand Up @@ -147,15 +150,19 @@ export default class OSMWaySnap extends PointerInteraction {
this.waySource.un('featuresloadend', this.waysFeaturesLoadEnded.bind(this));
this.wayLayer && this.map.removeLayer(this.wayLayer);
this.map.removeLayer(this.overlayLayer);
this.map.removeInteraction(this.snapInteraction);
this.map.removeInteraction(this.snapWayInteraction);
this.map.removeInteraction(this.snapSourceInteraction);
}
super.setMap(map);
this.map = map ?? undefined;
if (this.map) {
this.waySource.on('featuresloadend', this.waysFeaturesLoadEnded.bind(this));
this.wayLayer && this.map.getAllLayers().indexOf(this.wayLayer) < 0 && this.map.addLayer(this.wayLayer);
this.map.addLayer(this.overlayLayer);
this.map.getInteractions().getArray().indexOf(this.snapInteraction) < 0 && this.map.addInteraction(this.snapInteraction);
this.map.removeInteraction(this.snapWayInteraction);
this.map.addInteraction(this.snapWayInteraction);
this.map.removeInteraction(this.snapSourceInteraction);
this.map.addInteraction(this.snapSourceInteraction);
}
}

Expand Down Expand Up @@ -296,6 +303,7 @@ export default class OSMWaySnap extends PointerInteraction {
* @param fromCoordinate Coordinate on feature geometry to starts altering, the original vertices after this coordinate will go to draft in overlay layer
*/
private enterEditMode(feature: Feature<LineString>, fromCoordinate: Coordinate) {
feature.getGeometry()!.setCoordinates(LineStringUtils.split(feature.getGeometry()!, fromCoordinate).getCoordinates());
const originalCoordinates = feature.getGeometry()!.getCoordinates();
const fromCoordinateIdx = originalCoordinates.findIndex(c => c[0] === fromCoordinate[0] && c[1] === fromCoordinate[1]);
this.coordinates = originalCoordinates.slice(0, fromCoordinateIdx + 1);
Expand Down Expand Up @@ -396,10 +404,9 @@ export default class OSMWaySnap extends PointerInteraction {
p => (lastCoordinate[0] === p[0] && lastCoordinate[1] === p[1])
|| !this.activeFeature!.getGeometry()!.intersectsCoordinate(p)
);
if (fitCoordinates.length > 1) {
map.getView().fit(boundingExtent(fitCoordinates), {
padding: Array(4).fill(this.focusPadding)
});
const extent = boundingExtent(fitCoordinates);
if (fitCoordinates.length > 1 && extent[0] !== extent[2] && extent[1] !== extent[3]) {
map.getView().fit(extent, { padding: Array(4).fill(this.focusPadding) });
}
}
}
Expand Down Expand Up @@ -427,12 +434,21 @@ export default class OSMWaySnap extends PointerInteraction {
this.createOrUpdateSketchLine(lastFeatureCoors);
}

/**
* Test if the given coordinate falls on any feature geometries in the source.
* @param coordinate Coordinate
* @returns True if the given coordinate falls on any features in the source.
*/
private coordinateOnAnyFeatures(coordinate: Coordinate): boolean {
return this.source.getFeaturesAtCoordinate(coordinate).length > 0;
}

/**
* Create or move the sketch point to the specified coordinate
* @param coordinate Coordinate
*/
private createOrUpdateSketchPoint(coordinate: Coordinate) {
if (!this.allowCreate && !this.activeFeature) {
if (!this.allowCreate && this.allowEdit && !this.activeFeature && !this.coordinateOnAnyFeatures(coordinate)) {
return this.removeSketchPoint();
}
if (this.sketchPoint) {
Expand Down
2 changes: 1 addition & 1 deletion tests/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import EventType from 'ol/MapBrowserEventType'
import { MouseEvent } from 'happy-dom';
import type { Map } from 'ol';
import type { Coordinate } from 'ol/coordinate';
import type { OSMWaySnap } from '../dist';
import type { OSMWaySnap } from '../src';

/**
* Drawing a linestring network that looks more or less like this:
Expand Down
4 changes: 2 additions & 2 deletions tests/interaction.create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Projection } from 'ol/proj';
import { getDefaultWaySource, mouseClick, mouseMove } from './common';
import { OSMWaySnap, OSMWaySnapEventType } from '../dist';
import { OSMWaySnap, OSMWaySnapEventType } from '../src';
import { Feature } from 'ol';
import { LineString, Point } from 'ol/geom';

Expand Down Expand Up @@ -49,7 +49,7 @@ describe('Test OSMWaySnap Interaction: Line Creation', () => {
mouseMove(map, interaction, [-50, -75]);

const sketchPoint = (interaction as any).sketchPoint as Feature<Point>;
expect(sketchPoint).toBeTruthy();
expect(sketchPoint).toBeDefined();

const coor = sketchPoint.getGeometry()!.getFirstCoordinate();
expect(coor).toEqual([-50, -75]);
Expand Down
38 changes: 37 additions & 1 deletion tests/interaction.edit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { Projection } from 'ol/proj';
import { getDefaultWaySource, mouseClick, mouseMove } from './common';
import { OSMWaySnap, OSMWaySnapEventType } from '../dist';
import { OSMWaySnap, OSMWaySnapEventType } from '../src';
import { Feature } from 'ol';
import { LineString } from 'ol/geom';
import type { Point } from 'ol/geom';

describe('Test OSMWaySnap Interaction: Line Edition', () => {
let map: Map;
Expand Down Expand Up @@ -54,6 +55,20 @@ describe('Test OSMWaySnap Interaction: Line Edition', () => {
map.addInteraction(interaction);
});

it('shows sketch point when hovering on an editable line', () => {
interaction.allowCreate = false;
interaction.allowEdit = true;

const getSketchPoint = () => (interaction as any).sketchPoint as Feature<Point>|undefined;

mouseMove(map, interaction, [15, 15]);
expect(getSketchPoint()).toBeUndefined();

mouseMove(map, interaction, [10, 10]);
expect(getSketchPoint()).toBeDefined();
expect(getSketchPoint()!.getGeometry()!.getFirstCoordinate()).toEqual([10, 10]);
});

it('enables edit mode by spliting selected feature and displays the remaining as draft line after user clicks on an existing feature', () => {
mouseMove(map, interaction, [0, 0]);
mouseClick(map, interaction, [0, 0]);
Expand All @@ -74,6 +89,27 @@ describe('Test OSMWaySnap Interaction: Line Edition', () => {
expect(draftLine.getGeometry()!.getCoordinates()[5]).toEqual([0, 30]);
});

it('enables edit mode by spliting the selected feature on a line segment between vertices', () => {
mouseMove(map, interaction, [0, 5]);
mouseClick(map, interaction, [0, 5]);

const activeCoors = interaction.getActiveFeature()!.getGeometry()!.getCoordinates();
expect(activeCoors.length).toEqual(3);
expect(activeCoors[0]).toEqual([0, -50]);
expect(activeCoors[1]).toEqual([0, 0]);
expect(activeCoors[2]).toEqual([0, 5]);

const draftLine = (interaction as any).draftOriginalLine as Feature<LineString>;
expect(draftLine).toBeDefined();
expect(draftLine.getGeometry()!.getCoordinates().length).toEqual(6);
expect(draftLine.getGeometry()!.getCoordinates()[0]).toEqual([0, 5]);
expect(draftLine.getGeometry()!.getCoordinates()[1]).toEqual([0, 10]);
expect(draftLine.getGeometry()!.getCoordinates()[2]).toEqual([10, 10]);
expect(draftLine.getGeometry()!.getCoordinates()[3]).toEqual([10, 20]);
expect(draftLine.getGeometry()!.getCoordinates()[4]).toEqual([0, 20]);
expect(draftLine.getGeometry()!.getCoordinates()[5]).toEqual([0, 30]);
});

it('does not enable edit mode when not allowed', () => {
interaction.allowEdit = false;

Expand Down
2 changes: 1 addition & 1 deletion tests/osmoverpass.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, test } from 'vitest';
import VectorSource from 'ol/source/Vector';
import { OSMWaySnap } from '../dist';
import { OSMWaySnap } from '../src';
import { OSMOverpassWaySource } from 'ol-osmoverpass';
import type Feature from 'ol/Feature';
import type LineString from 'ol/geom/LineString';
Expand Down

0 comments on commit 0a813e4

Please sign in to comment.