Skip to content

Commit

Permalink
fix(polygon): merge overlapping polygons better
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulHax committed Jul 8, 2024
1 parent c351d64 commit 50d897f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 47 deletions.
42 changes: 0 additions & 42 deletions package-lock.json

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

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
"mitt": "^3.0.0",
"nanoid": "^4.0.1",
"pinia": "^2.0.34",
"polyclip-ts": "^0.16.5",
"socket.io-client": "^4.7.1",
"socket.io-parser": "^4.2.4",
"vue": "^3.3.4",
Expand Down
45 changes: 41 additions & 4 deletions src/store/tools/polygons.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import polybool, { Polygon } from '@velipso/polybool';
import type { Vector3 } from '@kitware/vtk.js/types';
import polybool, { Polygon as LibPolygon } from '@velipso/polybool';
import type { Vector3, Vector2 } from '@kitware/vtk.js/types';
import { computed } from 'vue';
import {
ToolSelection,
Expand Down Expand Up @@ -48,8 +48,45 @@ export const usePolygonStore = defineAnnotationToolStore('polygon', () => {
return polybool.intersect(aGeo, bGeo).regions.length > 0;
};

const pointEquals = (a: Vector2, b: Vector2) =>
a[0] === b[0] && a[1] === b[1];

// After union, regions will have shared points because we require overlap to union.
// Create one region/ring by splicing in the next region at the common point.
const mergeRegions = (regions: Array<Array<Vector2>>) => {
const [mergedRegion, ...candidates] = regions;

while (candidates.length > 0) {
let regionIndex = 0;
let mergedCommonPointIndex = 0;
let candidateCommonPointIndex = 0;
for (let i = 0; i < candidates.length; i++) {
const candidate = candidates[i];
let candidatePointIndex = 0;
const commonPointIndex = mergedRegion.findIndex((point) =>
candidate.some((nextPoint, index) => {
candidatePointIndex = index;
return pointEquals(point, nextPoint);
})
);
if (commonPointIndex !== -1) {
regionIndex = i;
mergedCommonPointIndex = commonPointIndex;
candidateCommonPointIndex = candidatePointIndex;
break;
}
}
const [toMerge] = candidates.splice(regionIndex, 1);
const oldStart = toMerge.splice(0, candidateCommonPointIndex);
const startWithCommonPoint = [...toMerge, ...oldStart];
mergedRegion.splice(mergedCommonPointIndex, 0, ...startWithCommonPoint);
}

return mergedRegion;
};

const mergePolygons = (polygons: Array<Tool>) => {
const libPolygons = polygons.map(toPolyLibStructure) as Array<Polygon>;
const libPolygons = polygons.map(toPolyLibStructure) as Array<LibPolygon>;
if (libPolygons.some((p) => p === undefined))
throw new Error('Trying to merge invalid polygons');

Expand All @@ -64,7 +101,7 @@ export const usePolygonStore = defineAnnotationToolStore('polygon', () => {
const firstTool = polygons[0];
const { to3D } = getPlaneTransforms(firstTool.frameOfReference);

const points = unionPoly.regions[0].map(to3D);
const points = mergeRegions(unionPoly.regions).map(to3D);

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id: _, ...toolProps } = polygons[0];
Expand Down

0 comments on commit 50d897f

Please sign in to comment.