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

New polygon snap tool #143

Merged
merged 3 commits into from
Apr 27, 2023
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
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@turf/nearest-point-on-line": "^6.5.0",
"@types/geojson": "^7946.0.10",
"maplibre-gl": "^2.4.0",
"route-snapper": "^0.1.12",
"route-snapper": "^0.1.13",
"svelte": "^3.54.0"
}
}
42 changes: 36 additions & 6 deletions src/lib/draw/GeometryMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import type { Feature, FeatureUnion } from "../../types";
import PointControls from "./point/PointControls.svelte";
import PolygonControls from "./polygon/PolygonControls.svelte";
import SnapPolygonControls from "./snap_polygon/SnapPolygonControls.svelte";
import RouteControls from "./route/RouteControls.svelte";

const thisMode = "edit-geometry";
Expand All @@ -20,7 +21,12 @@

// An optional ID of what we're currently editing in this mode
let currentlyEditing: number | null = null;
let currentlyEditingControls: "point" | "polygon" | "route" | null = null;
let currentlyEditingControls:
| "point"
| "free-polygon"
| "snap-polygon"
| "route"
| null = null;

export function start() {}
export function stop() {
Expand Down Expand Up @@ -55,7 +61,7 @@
});

// Handle successful edits
routeTool.addEventListenerSuccess((editedRoute) => {
routeTool.addEventListenerSuccessRoute((editedRoute) => {
if (mode == thisMode) {
gjScheme.update((gj) => {
let feature = gj.features.find((f) => f.id == currentlyEditing)!;
Expand All @@ -73,6 +79,23 @@
currentlyEditingControls = null;
}
});
routeTool.addEventListenerSuccessArea((editedArea) => {
if (mode == thisMode) {
gjScheme.update((gj) => {
let feature = gj.features.find((f) => f.id == currentlyEditing)!;
// Keep the ID and any properties. Just copy over stuff from routeSnapper.
// TODO We're depending on implementation details here and knowing what to copy...
feature.properties.waypoints = editedArea.properties.waypoints;
delete feature.properties.hide_while_editing;
feature.geometry = editedArea.geometry;
return gj;
});

// Stay in this mode
currentlyEditing = null;
currentlyEditingControls = null;
}
});
for (let tool of [pointTool, polygonTool]) {
tool.addEventListenerSuccess((feature) => {
if (mode == thisMode) {
Expand Down Expand Up @@ -159,11 +182,16 @@
currentlyEditing = id;

if (feature.geometry.type == "LineString") {
routeTool.editExisting(feature as Feature<LineString>);
routeTool.editExistingRoute(feature as Feature<LineString>);
currentlyEditingControls = "route";
} else if (feature.geometry.type == "Polygon") {
polygonTool.editExisting(feature as Feature<Polygon>);
currentlyEditingControls = "polygon";
if (feature.properties.waypoints) {
routeTool.editExistingArea(feature as Feature<Polygon>);
currentlyEditingControls = "snap-polygon";
} else {
polygonTool.editExisting(feature as Feature<Polygon>);
currentlyEditingControls = "free-polygon";
}
} else if (feature.geometry.type == "Point") {
// No need to pass in the existing feature.geometry; it's the same as
// where the cursor is anyway
Expand All @@ -176,8 +204,10 @@
{#if mode == thisMode}
{#if currentlyEditingControls == "point"}
<PointControls {pointTool} editingExisting={true} />
{:else if currentlyEditingControls == "polygon"}
{:else if currentlyEditingControls == "free-polygon"}
<PolygonControls {polygonTool} />
{:else if currentlyEditingControls == "snap-polygon"}
<SnapPolygonControls {routeTool} />
{:else if currentlyEditingControls == "route"}
<RouteControls {routeTool} />
{:else}
Expand Down
28 changes: 23 additions & 5 deletions src/lib/draw/Toolbox.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
import RouteMode from "./route/RouteMode.svelte";
import PointMode from "./point/PointMode.svelte";
import PolygonMode from "./polygon/PolygonMode.svelte";
import SnapPolygonMode from "./snap_polygon/SnapPolygonMode.svelte";
import SplitRouteMode from "./route/SplitRouteMode.svelte";

export let routeUrl: string;
export let planningMode: boolean;
// Plumbed up from RouteMode, so we can pass it down to GeometryMode
// TODO Reconsider
// TODO Create this here too?
let routeTool: RouteTool;

// Create and manage these here, then pass down to modes as needed.
// TODO Teardown too
let pointTool = new PointTool($map);
let polygonTool = new PolygonTool($map);

Expand All @@ -30,6 +30,7 @@
let routeMode: RouteMode;
let pointMode: PointMode;
let polygonMode: PolygonMode;
let snapPolygonMode: SnapPolygonMode;
let splitRouteMode: SplitRouteMode;

// This must be used; don't manually change mode
Expand All @@ -39,7 +40,8 @@
"edit-geometry": geometryMode,
route: routeMode,
point: pointMode,
polygon: polygonMode,
"free-polygon": polygonMode,
"snap-polygon": snapPolygonMode,
"split-route": splitRouteMode,
};

Expand All @@ -57,6 +59,7 @@
onDestroy(() => {
pointTool?.tearDown();
polygonTool?.tearDown();
routeTool?.tearDown();
});
</script>

Expand Down Expand Up @@ -98,11 +101,26 @@
<div>
<button
type="button"
on:click={() => changeMode("polygon")}
disabled={mode == "polygon"}>New polygon</button
on:click={() => changeMode("free-polygon")}
disabled={mode == "free-polygon"}>New polygon (freehand)</button
>
<PolygonMode bind:this={polygonMode} {mode} {changeMode} {polygonTool} />
</div>
<div>
<button
type="button"
on:click={() => changeMode("snap-polygon")}
disabled={mode == "snap-polygon"}>New polygon (snapped)</button
>
{#if routeTool}
<SnapPolygonMode
bind:this={snapPolygonMode}
{mode}
{changeMode}
{routeTool}
/>
{/if}
</div>
<div>
{#if !planningMode}
<button
Expand Down
2 changes: 1 addition & 1 deletion src/lib/draw/polygon/PolygonMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { gjScheme, newFeatureId, formOpen } from "../../../stores";
import PolygonControls from "./PolygonControls.svelte";

const thisMode = "polygon";
const thisMode = "free-polygon";

export let mode: string;
export let changeMode: (m: Mode) => void;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/draw/route/RouteControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

// TODO Save this in the route
let avoidDoublingBack = false;
$: routeTool.setConfig({
$: routeTool.setRouteConfig({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sliiight bug here. If we make a snapped area, then make a snapped route, avoid doubling back will be true from the last call, but the checkbox won't be ticked. I think we need to add a property to the output geojson feature to indicate this option and keep it synced.

avoid_doubling_back: avoidDoublingBack,
});

Expand Down
10 changes: 3 additions & 7 deletions src/lib/draw/route/RouteMode.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import type { Mode } from "../types";
import { onMount, onDestroy } from "svelte";
import { onMount } from "svelte";
import init from "route-snapper";
import { fetchWithProgress } from "route-snapper/lib.js";
import { RouteTool } from "./route_tool";
Expand All @@ -24,7 +24,7 @@
// When we enter this mode by clicking the button from edit-geometry, we
// call routeTool.stop(). Re-activate it if so.
if (!routeTool.isActive()) {
routeTool.start();
routeTool.startRoute();
}
}
export function stop() {
Expand All @@ -49,7 +49,7 @@
changeMode("edit-attribute");
}
});
routeTool.addEventListenerSuccess((feature) => {
routeTool.addEventListenerSuccessRoute((feature) => {
if (mode == thisMode) {
gjScheme.update((gj) => {
feature.id = newFeatureId(gj);
Expand All @@ -63,10 +63,6 @@
}
});
});

onDestroy(() => {
routeTool?.tearDown();
});
</script>

{#if !routeTool}
Expand Down
Loading