@tldraw/editor 3.12.0-canary.3e2ed74b5e86 → 3.12.0-canary.423f9b4f2a86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist-cjs/index.d.ts +12 -78
  2. package/dist-cjs/index.js +1 -3
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/components/GeometryDebuggingView.js +2 -2
  5. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  6. package/dist-cjs/lib/editor/Editor.js +8 -39
  7. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  8. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +13 -1
  9. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +16 -133
  11. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +3 -3
  12. package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -54
  13. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  14. package/dist-cjs/lib/primitives/intersect.js +0 -20
  15. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  16. package/dist-cjs/lib/utils/reorderShapes.js +8 -2
  17. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  18. package/dist-cjs/version.js +3 -3
  19. package/dist-cjs/version.js.map +1 -1
  20. package/dist-esm/index.d.mts +12 -78
  21. package/dist-esm/index.mjs +2 -8
  22. package/dist-esm/index.mjs.map +2 -2
  23. package/dist-esm/lib/components/GeometryDebuggingView.mjs +3 -3
  24. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  25. package/dist-esm/lib/editor/Editor.mjs +8 -39
  26. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  27. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +13 -1
  28. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  29. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +14 -137
  30. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  31. package/dist-esm/lib/primitives/geometry/Group2d.mjs +12 -55
  32. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  33. package/dist-esm/lib/primitives/intersect.mjs +0 -20
  34. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  35. package/dist-esm/lib/utils/reorderShapes.mjs +8 -2
  36. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  37. package/dist-esm/version.mjs +3 -3
  38. package/dist-esm/version.mjs.map +1 -1
  39. package/package.json +7 -7
  40. package/src/index.ts +1 -6
  41. package/src/lib/components/GeometryDebuggingView.tsx +3 -3
  42. package/src/lib/editor/Editor.ts +15 -44
  43. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +15 -3
  44. package/src/lib/primitives/geometry/Geometry2d.ts +16 -196
  45. package/src/lib/primitives/geometry/Group2d.ts +13 -76
  46. package/src/lib/primitives/intersect.ts +0 -41
  47. package/src/lib/utils/reorderShapes.ts +9 -2
  48. package/src/version.ts +3 -3
@@ -25,6 +25,8 @@ var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_tlschema = require("@tldraw/tlschema");
26
26
  var import_SVGContainer = require("../../../components/SVGContainer");
27
27
  var import_Group2d = require("../../../primitives/geometry/Group2d");
28
+ var import_Polygon2d = require("../../../primitives/geometry/Polygon2d");
29
+ var import_Polyline2d = require("../../../primitives/geometry/Polyline2d");
28
30
  var import_Rectangle2d = require("../../../primitives/geometry/Rectangle2d");
29
31
  var import_ShapeUtil = require("../ShapeUtil");
30
32
  var import_DashedOutlineBox = require("./DashedOutlineBox");
@@ -49,7 +51,17 @@ class GroupShapeUtil extends import_ShapeUtil.ShapeUtil {
49
51
  return new import_Group2d.Group2d({
50
52
  children: children.map((childId) => {
51
53
  const shape2 = this.editor.getShape(childId);
52
- return this.editor.getShapeGeometry(childId).transform(this.editor.getShapeLocalTransform(shape2));
54
+ const geometry = this.editor.getShapeGeometry(childId);
55
+ const points = this.editor.getShapeLocalTransform(shape2).applyToPoints(geometry.vertices);
56
+ if (geometry.isClosed) {
57
+ return new import_Polygon2d.Polygon2d({
58
+ points,
59
+ isFilled: true
60
+ });
61
+ }
62
+ return new import_Polyline2d.Polyline2d({
63
+ points
64
+ });
53
65
  })
54
66
  });
55
67
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/shapes/group/GroupShapeUtil.tsx"],
4
- "sourcesContent": ["import { TLGroupShape, groupShapeMigrations, groupShapeProps } from '@tldraw/tlschema'\nimport { SVGContainer } from '../../../components/SVGContainer'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../../primitives/geometry/Group2d'\nimport { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'\nimport { ShapeUtil } from '../ShapeUtil'\nimport { DashedOutlineBox } from './DashedOutlineBox'\n\n/** @public */\nexport class GroupShapeUtil extends ShapeUtil<TLGroupShape> {\n\tstatic override type = 'group' as const\n\tstatic override props = groupShapeProps\n\tstatic override migrations = groupShapeMigrations\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride canBind() {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLGroupShape['props'] {\n\t\treturn {}\n\t}\n\n\tgetGeometry(shape: TLGroupShape): Geometry2d {\n\t\tconst children = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tif (children.length === 0) {\n\t\t\treturn new Rectangle2d({ width: 1, height: 1, isFilled: false })\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: children.map((childId) => {\n\t\t\t\tconst shape = this.editor.getShape(childId)!\n\t\t\t\treturn this.editor\n\t\t\t\t\t.getShapeGeometry(childId)\n\t\t\t\t\t.transform(this.editor.getShapeLocalTransform(shape)!)\n\t\t\t}),\n\t\t})\n\t}\n\n\tcomponent(shape: TLGroupShape) {\n\t\tconst isErasing = this.editor.getErasingShapeIds().includes(shape.id)\n\n\t\tconst { hintingShapeIds } = this.editor.getCurrentPageState()\n\t\tconst isHintingOtherGroup =\n\t\t\thintingShapeIds.length > 0 &&\n\t\t\thintingShapeIds.some(\n\t\t\t\t(id) =>\n\t\t\t\t\tid !== shape.id &&\n\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(this.editor.getShape(id)!, 'group')\n\t\t\t)\n\n\t\tconst isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id\n\n\t\tif (\n\t\t\t!isErasing && // always show the outline while we're erasing the group\n\t\t\t// show the outline while the group is focused unless something outside of the group is being hinted\n\t\t\t// this happens dropping shapes from a group onto some outside group\n\t\t\t(isFocused || isHintingOtherGroup)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DashedOutlineBox className=\"tl-group\" bounds={bounds} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLGroupShape) {\n\t\t// Not a class component, but eslint can't tell that :(\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\treturn <DashedOutlineBox className=\"\" bounds={bounds} />\n\t}\n\n\toverride onChildrenChange(group: TLGroupShape) {\n\t\tconst children = this.editor.getSortedChildIdsForParent(group.id)\n\t\tif (children.length === 0) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t} else if (children.length === 1) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.reparentShapes(children, group.parentId)\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t}\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqEI;AArEJ,sBAAoE;AACpE,0BAA6B;AAE7B,qBAAwB;AACxB,yBAA4B;AAC5B,uBAA0B;AAC1B,8BAAiC;AAG1B,MAAM,uBAAuB,2BAAwB;AAAA,EAC3D,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,wBAAwB;AAChC,WAAO;AAAA,EACR;AAAA,EAES,UAAU;AAClB,WAAO;AAAA,EACR;AAAA,EAEA,kBAAyC;AACxC,WAAO,CAAC;AAAA,EACT;AAAA,EAEA,YAAY,OAAiC;AAC5C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO,IAAI,+BAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,MAAM,CAAC;AAAA,IAChE;AAEA,WAAO,IAAI,uBAAQ;AAAA,MAClB,UAAU,SAAS,IAAI,CAAC,YAAY;AACnC,cAAMA,SAAQ,KAAK,OAAO,SAAS,OAAO;AAC1C,eAAO,KAAK,OACV,iBAAiB,OAAO,EACxB,UAAU,KAAK,OAAO,uBAAuBA,MAAK,CAAE;AAAA,MACvD,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AAAA,EAEA,UAAU,OAAqB;AAC9B,UAAM,YAAY,KAAK,OAAO,mBAAmB,EAAE,SAAS,MAAM,EAAE;AAEpE,UAAM,EAAE,gBAAgB,IAAI,KAAK,OAAO,oBAAoB;AAC5D,UAAM,sBACL,gBAAgB,SAAS,KACzB,gBAAgB;AAAA,MACf,CAAC,OACA,OAAO,MAAM,MACb,KAAK,OAAO,cAA4B,KAAK,OAAO,SAAS,EAAE,GAAI,OAAO;AAAA,IAC5E;AAED,UAAM,YAAY,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM;AAE7E,QACC,CAAC;AAAA;AAAA;AAAA,KAGA,aAAa,sBACb;AACD,aAAO;AAAA,IACR;AAEA,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AAEnD,WACC,4CAAC,oCACA,sDAAC,4CAAiB,WAAU,YAAW,QAAgB,GACxD;AAAA,EAEF;AAAA,EAEA,UAAU,OAAqB;AAE9B,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AACnD,WAAO,4CAAC,4CAAiB,WAAU,IAAG,QAAgB;AAAA,EACvD;AAAA,EAES,iBAAiB,OAAqB;AAC9C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD,WAAW,SAAS,WAAW,GAAG;AACjC,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,eAAe,UAAU,MAAM,QAAQ;AACnD,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import { TLGroupShape, groupShapeMigrations, groupShapeProps } from '@tldraw/tlschema'\nimport { SVGContainer } from '../../../components/SVGContainer'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport { Group2d } from '../../../primitives/geometry/Group2d'\nimport { Polygon2d } from '../../../primitives/geometry/Polygon2d'\nimport { Polyline2d } from '../../../primitives/geometry/Polyline2d'\nimport { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'\nimport { ShapeUtil } from '../ShapeUtil'\nimport { DashedOutlineBox } from './DashedOutlineBox'\n\n/** @public */\nexport class GroupShapeUtil extends ShapeUtil<TLGroupShape> {\n\tstatic override type = 'group' as const\n\tstatic override props = groupShapeProps\n\tstatic override migrations = groupShapeMigrations\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride canBind() {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLGroupShape['props'] {\n\t\treturn {}\n\t}\n\n\tgetGeometry(shape: TLGroupShape): Geometry2d {\n\t\tconst children = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tif (children.length === 0) {\n\t\t\treturn new Rectangle2d({ width: 1, height: 1, isFilled: false })\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: children.map((childId) => {\n\t\t\t\tconst shape = this.editor.getShape(childId)!\n\t\t\t\tconst geometry = this.editor.getShapeGeometry(childId)\n\t\t\t\tconst points = this.editor.getShapeLocalTransform(shape)!.applyToPoints(geometry.vertices)\n\n\t\t\t\tif (geometry.isClosed) {\n\t\t\t\t\treturn new Polygon2d({\n\t\t\t\t\t\tpoints,\n\t\t\t\t\t\tisFilled: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\treturn new Polyline2d({\n\t\t\t\t\tpoints,\n\t\t\t\t})\n\t\t\t}),\n\t\t})\n\t}\n\n\tcomponent(shape: TLGroupShape) {\n\t\tconst isErasing = this.editor.getErasingShapeIds().includes(shape.id)\n\n\t\tconst { hintingShapeIds } = this.editor.getCurrentPageState()\n\t\tconst isHintingOtherGroup =\n\t\t\thintingShapeIds.length > 0 &&\n\t\t\thintingShapeIds.some(\n\t\t\t\t(id) =>\n\t\t\t\t\tid !== shape.id &&\n\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(this.editor.getShape(id)!, 'group')\n\t\t\t)\n\n\t\tconst isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id\n\n\t\tif (\n\t\t\t!isErasing && // always show the outline while we're erasing the group\n\t\t\t// show the outline while the group is focused unless something outside of the group is being hinted\n\t\t\t// this happens dropping shapes from a group onto some outside group\n\t\t\t(isFocused || isHintingOtherGroup)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\n\t\treturn (\n\t\t\t<SVGContainer>\n\t\t\t\t<DashedOutlineBox className=\"tl-group\" bounds={bounds} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLGroupShape) {\n\t\t// Not a class component, but eslint can't tell that :(\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\treturn <DashedOutlineBox className=\"\" bounds={bounds} />\n\t}\n\n\toverride onChildrenChange(group: TLGroupShape) {\n\t\tconst children = this.editor.getSortedChildIdsForParent(group.id)\n\t\tif (children.length === 0) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t} else if (children.length === 1) {\n\t\t\tif (this.editor.getCurrentPageState().focusedGroupId === group.id) {\n\t\t\t\tthis.editor.popFocusedGroupId()\n\t\t\t}\n\t\t\tthis.editor.reparentShapes(children, group.parentId)\n\t\t\tthis.editor.deleteShapes([group.id])\n\t\t\treturn\n\t\t}\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiFI;AAjFJ,sBAAoE;AACpE,0BAA6B;AAE7B,qBAAwB;AACxB,uBAA0B;AAC1B,wBAA2B;AAC3B,yBAA4B;AAC5B,uBAA0B;AAC1B,8BAAiC;AAG1B,MAAM,uBAAuB,2BAAwB;AAAA,EAC3D,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,wBAAwB;AAChC,WAAO;AAAA,EACR;AAAA,EAES,UAAU;AAClB,WAAO;AAAA,EACR;AAAA,EAEA,kBAAyC;AACxC,WAAO,CAAC;AAAA,EACT;AAAA,EAEA,YAAY,OAAiC;AAC5C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO,IAAI,+BAAY,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,MAAM,CAAC;AAAA,IAChE;AAEA,WAAO,IAAI,uBAAQ;AAAA,MAClB,UAAU,SAAS,IAAI,CAAC,YAAY;AACnC,cAAMA,SAAQ,KAAK,OAAO,SAAS,OAAO;AAC1C,cAAM,WAAW,KAAK,OAAO,iBAAiB,OAAO;AACrD,cAAM,SAAS,KAAK,OAAO,uBAAuBA,MAAK,EAAG,cAAc,SAAS,QAAQ;AAEzF,YAAI,SAAS,UAAU;AACtB,iBAAO,IAAI,2BAAU;AAAA,YACpB;AAAA,YACA,UAAU;AAAA,UACX,CAAC;AAAA,QACF;AAEA,eAAO,IAAI,6BAAW;AAAA,UACrB;AAAA,QACD,CAAC;AAAA,MACF,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AAAA,EAEA,UAAU,OAAqB;AAC9B,UAAM,YAAY,KAAK,OAAO,mBAAmB,EAAE,SAAS,MAAM,EAAE;AAEpE,UAAM,EAAE,gBAAgB,IAAI,KAAK,OAAO,oBAAoB;AAC5D,UAAM,sBACL,gBAAgB,SAAS,KACzB,gBAAgB;AAAA,MACf,CAAC,OACA,OAAO,MAAM,MACb,KAAK,OAAO,cAA4B,KAAK,OAAO,SAAS,EAAE,GAAI,OAAO;AAAA,IAC5E;AAED,UAAM,YAAY,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM;AAE7E,QACC,CAAC;AAAA;AAAA;AAAA,KAGA,aAAa,sBACb;AACD,aAAO;AAAA,IACR;AAEA,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AAEnD,WACC,4CAAC,oCACA,sDAAC,4CAAiB,WAAU,YAAW,QAAgB,GACxD;AAAA,EAEF;AAAA,EAEA,UAAU,OAAqB;AAE9B,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AACnD,WAAO,4CAAC,4CAAiB,WAAU,IAAG,QAAgB;AAAA,EACvD;AAAA,EAES,iBAAiB,OAAqB;AAC9C,UAAM,WAAW,KAAK,OAAO,2BAA2B,MAAM,EAAE;AAChE,QAAI,SAAS,WAAW,GAAG;AAC1B,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD,WAAW,SAAS,WAAW,GAAG;AACjC,UAAI,KAAK,OAAO,oBAAoB,EAAE,mBAAmB,MAAM,IAAI;AAClE,aAAK,OAAO,kBAAkB;AAAA,MAC/B;AACA,WAAK,OAAO,eAAe,UAAU,MAAM,QAAQ;AACnD,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AACnC;AAAA,IACD;AAAA,EACD;AACD;",
6
6
  "names": ["shape"]
7
7
  }
@@ -18,59 +18,40 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var Geometry2d_exports = {};
20
20
  __export(Geometry2d_exports, {
21
- Geometry2d: () => Geometry2d,
22
- Geometry2dFilters: () => Geometry2dFilters,
23
- TransformedGeometry2d: () => TransformedGeometry2d
21
+ Geometry2d: () => Geometry2d
24
22
  });
25
23
  module.exports = __toCommonJS(Geometry2d_exports);
26
- var import_utils = require("@tldraw/utils");
27
24
  var import_Box = require("../Box");
28
- var import_Mat = require("../Mat");
29
25
  var import_Vec = require("../Vec");
30
- var import_intersect = require("../intersect");
31
- var import_utils2 = require("../utils");
32
- const Geometry2dFilters = {
33
- EXCLUDE_NON_STANDARD: {
34
- includeLabels: false,
35
- includeInternal: false
36
- },
37
- INCLUDE_ALL: { includeLabels: true, includeInternal: true },
38
- EXCLUDE_LABELS: { includeLabels: false, includeInternal: true },
39
- EXCLUDE_INTERNAL: { includeLabels: true, includeInternal: false }
40
- };
26
+ var import_utils = require("../utils");
41
27
  class Geometry2d {
42
28
  isFilled = false;
43
29
  isClosed = true;
44
30
  isLabel = false;
45
- isInternal = false;
46
31
  debugColor;
47
32
  ignore;
48
33
  constructor(opts) {
49
34
  this.isFilled = opts.isFilled;
50
35
  this.isClosed = opts.isClosed;
51
36
  this.isLabel = opts.isLabel ?? false;
52
- this.isInternal = opts.isInternal ?? false;
53
37
  this.debugColor = opts.debugColor;
54
38
  this.ignore = opts.ignore;
55
39
  }
56
- isExcludedByFilter(filters) {
57
- if (!filters) return false;
58
- if (this.isLabel && !filters.includeLabels) return true;
59
- if (this.isInternal && !filters.includeInternal) return true;
60
- return false;
61
- }
62
- hitTestPoint(point, margin = 0, hitInside = false, filters) {
63
- if (this.isExcludedByFilter(filters)) return false;
64
- if (this.isClosed && (this.isFilled || hitInside) && (0, import_utils2.pointInPolygon)(point, this.vertices)) {
40
+ // hitTestPoint(point: Vec, margin = 0, hitInside = false) {
41
+ // // We've removed the broad phase here; that should be done outside of the call
42
+ // return this.distanceToPoint(point, hitInside) <= margin
43
+ // }
44
+ hitTestPoint(point, margin = 0, hitInside = false) {
45
+ if (this.isClosed && (this.isFilled || hitInside) && (0, import_utils.pointInPolygon)(point, this.vertices)) {
65
46
  return true;
66
47
  }
67
48
  return import_Vec.Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin;
68
49
  }
69
- distanceToPoint(point, hitInside = false, filters) {
70
- return point.dist(this.nearestPoint(point, filters)) * (this.isClosed && (this.isFilled || hitInside) && (0, import_utils2.pointInPolygon)(point, this.vertices) ? -1 : 1);
50
+ distanceToPoint(point, hitInside = false) {
51
+ return point.dist(this.nearestPoint(point)) * (this.isClosed && (this.isFilled || hitInside) && (0, import_utils.pointInPolygon)(point, this.vertices) ? -1 : 1);
71
52
  }
72
- distanceToLineSegment(A, B, filters) {
73
- if (A.equals(B)) return this.distanceToPoint(A, false, filters);
53
+ distanceToLineSegment(A, B) {
54
+ if (A.equals(B)) return this.distanceToPoint(A);
74
55
  const { vertices } = this;
75
56
  let nearest;
76
57
  let dist = Infinity;
@@ -85,30 +66,11 @@ class Geometry2d {
85
66
  }
86
67
  }
87
68
  if (!nearest) throw Error("nearest point not found");
88
- return this.isClosed && this.isFilled && (0, import_utils2.pointInPolygon)(nearest, this.vertices) ? -dist : dist;
89
- }
90
- hitTestLineSegment(A, B, distance = 0, filters) {
91
- return this.distanceToLineSegment(A, B, filters) <= distance;
92
- }
93
- intersectLineSegment(A, B, filters) {
94
- if (this.isExcludedByFilter(filters)) return [];
95
- const intersections = this.isClosed ? (0, import_intersect.intersectLineSegmentPolygon)(A, B, this.vertices) : (0, import_intersect.intersectLineSegmentPolyline)(A, B, this.vertices);
96
- return intersections ?? [];
97
- }
98
- intersectCircle(center, radius, filters) {
99
- if (this.isExcludedByFilter(filters)) return [];
100
- const intersections = this.isClosed ? (0, import_intersect.intersectCirclePolygon)(center, radius, this.vertices) : (0, import_intersect.intersectCirclePolyline)(center, radius, this.vertices);
101
- return intersections ?? [];
102
- }
103
- intersectPolygon(polygon, filters) {
104
- if (this.isExcludedByFilter(filters)) return [];
105
- return (0, import_intersect.intersectPolys)(polygon, this.vertices, true, this.isClosed);
69
+ return this.isClosed && this.isFilled && (0, import_utils.pointInPolygon)(nearest, this.vertices) ? -dist : dist;
106
70
  }
107
- intersectPolyline(polyline, filters) {
108
- if (this.isExcludedByFilter(filters)) return [];
109
- return (0, import_intersect.intersectPolys)(polyline, this.vertices, false, this.isClosed);
71
+ hitTestLineSegment(A, B, distance = 0) {
72
+ return this.distanceToLineSegment(A, B) <= distance;
110
73
  }
111
- /** @deprecated Iterate the vertices instead. */
112
74
  nearestPointOnLineSegment(A, B) {
113
75
  const { vertices } = this;
114
76
  let nearest;
@@ -130,14 +92,11 @@ class Geometry2d {
130
92
  const { bounds } = this;
131
93
  return !(point.x < bounds.minX - margin || point.y < bounds.minY - margin || point.x > bounds.maxX + margin || point.y > bounds.maxY + margin);
132
94
  }
133
- transform(transform) {
134
- return new TransformedGeometry2d(this, transform);
135
- }
136
95
  _vertices;
137
96
  // eslint-disable-next-line no-restricted-syntax
138
97
  get vertices() {
139
98
  if (!this._vertices) {
140
- this._vertices = this.getVertices(Geometry2dFilters.EXCLUDE_LABELS);
99
+ this._vertices = this.getVertices();
141
100
  }
142
101
  return this._vertices;
143
102
  }
@@ -209,80 +168,4 @@ class Geometry2d {
209
168
  return Math.sqrt(length);
210
169
  }
211
170
  }
212
- class TransformedGeometry2d extends Geometry2d {
213
- constructor(geometry, matrix) {
214
- super(geometry);
215
- this.geometry = geometry;
216
- this.matrix = matrix;
217
- this.inverse = import_Mat.Mat.Inverse(matrix);
218
- this.decomposed = import_Mat.Mat.Decompose(matrix);
219
- (0, import_utils.assert)(
220
- (0, import_utils2.approximately)(this.decomposed.scaleX, this.decomposed.scaleY),
221
- "non-uniform scaling is not yet supported"
222
- );
223
- }
224
- inverse;
225
- decomposed;
226
- getVertices(filters) {
227
- return this.geometry.getVertices(filters).map((v) => import_Mat.Mat.applyToPoint(this.matrix, v));
228
- }
229
- nearestPoint(point, filters) {
230
- return import_Mat.Mat.applyToPoint(
231
- this.matrix,
232
- this.geometry.nearestPoint(import_Mat.Mat.applyToPoint(this.inverse, point), filters)
233
- );
234
- }
235
- hitTestPoint(point, margin = 0, hitInside, filters) {
236
- return this.geometry.hitTestPoint(
237
- import_Mat.Mat.applyToPoint(this.inverse, point),
238
- margin / this.decomposed.scaleX,
239
- hitInside,
240
- filters
241
- );
242
- }
243
- distanceToPoint(point, hitInside = false, filters) {
244
- return this.geometry.distanceToPoint(import_Mat.Mat.applyToPoint(this.inverse, point), hitInside, filters) * this.decomposed.scaleX;
245
- }
246
- distanceToLineSegment(A, B, filters) {
247
- return this.geometry.distanceToLineSegment(
248
- import_Mat.Mat.applyToPoint(this.inverse, A),
249
- import_Mat.Mat.applyToPoint(this.inverse, B),
250
- filters
251
- ) * this.decomposed.scaleX;
252
- }
253
- hitTestLineSegment(A, B, distance = 0, filters) {
254
- return this.geometry.hitTestLineSegment(
255
- import_Mat.Mat.applyToPoint(this.inverse, A),
256
- import_Mat.Mat.applyToPoint(this.inverse, B),
257
- distance / this.decomposed.scaleX,
258
- filters
259
- );
260
- }
261
- intersectLineSegment(A, B, filters) {
262
- return this.geometry.intersectLineSegment(
263
- import_Mat.Mat.applyToPoint(this.inverse, A),
264
- import_Mat.Mat.applyToPoint(this.inverse, B),
265
- filters
266
- );
267
- }
268
- intersectCircle(center, radius, filters) {
269
- return this.geometry.intersectCircle(
270
- import_Mat.Mat.applyToPoint(this.inverse, center),
271
- radius / this.decomposed.scaleX,
272
- filters
273
- );
274
- }
275
- intersectPolygon(polygon, filters) {
276
- return this.geometry.intersectPolygon(import_Mat.Mat.applyToPoints(this.inverse, polygon), filters);
277
- }
278
- intersectPolyline(polyline, filters) {
279
- return this.geometry.intersectPolyline(import_Mat.Mat.applyToPoints(this.inverse, polyline), filters);
280
- }
281
- transform(transform) {
282
- return new TransformedGeometry2d(this.geometry, import_Mat.Mat.Multiply(transform, this.matrix));
283
- }
284
- getSvgPathData() {
285
- throw new Error("Cannot get SVG path data for transformed geometry.");
286
- }
287
- }
288
171
  //# sourceMappingURL=Geometry2d.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/primitives/geometry/Geometry2d.ts"],
4
- "sourcesContent": ["import { assert } from '@tldraw/utils'\nimport { Box } from '../Box'\nimport { Mat, MatModel } from '../Mat'\nimport { Vec, VecLike } from '../Vec'\nimport {\n\tintersectCirclePolygon,\n\tintersectCirclePolyline,\n\tintersectLineSegmentPolygon,\n\tintersectLineSegmentPolyline,\n\tintersectPolys,\n} from '../intersect'\nimport { approximately, pointInPolygon } from '../utils'\n\n/** @public */\nexport interface Geometry2dFilters {\n\treadonly includeLabels?: boolean\n\treadonly includeInternal?: boolean\n}\n\n/** @public */\nexport const Geometry2dFilters: {\n\tEXCLUDE_NON_STANDARD: Geometry2dFilters\n\tINCLUDE_ALL: Geometry2dFilters\n\tEXCLUDE_LABELS: Geometry2dFilters\n\tEXCLUDE_INTERNAL: Geometry2dFilters\n} = {\n\tEXCLUDE_NON_STANDARD: {\n\t\tincludeLabels: false,\n\t\tincludeInternal: false,\n\t},\n\tINCLUDE_ALL: { includeLabels: true, includeInternal: true },\n\tEXCLUDE_LABELS: { includeLabels: false, includeInternal: true },\n\tEXCLUDE_INTERNAL: { includeLabels: true, includeInternal: false },\n}\n\n/** @public */\nexport interface Geometry2dOptions {\n\tisFilled: boolean\n\tisClosed: boolean\n\tisLabel?: boolean\n\tisInternal?: boolean\n\tdebugColor?: string\n\tignore?: boolean\n}\n\n/** @public */\nexport abstract class Geometry2d {\n\tisFilled = false\n\tisClosed = true\n\tisLabel = false\n\tisInternal = false\n\tdebugColor?: string\n\tignore?: boolean\n\n\tconstructor(opts: Geometry2dOptions) {\n\t\tthis.isFilled = opts.isFilled\n\t\tthis.isClosed = opts.isClosed\n\t\tthis.isLabel = opts.isLabel ?? false\n\t\tthis.isInternal = opts.isInternal ?? false\n\t\tthis.debugColor = opts.debugColor\n\t\tthis.ignore = opts.ignore\n\t}\n\n\tisExcludedByFilter(filters?: Geometry2dFilters) {\n\t\tif (!filters) return false\n\t\tif (this.isLabel && !filters.includeLabels) return true\n\t\tif (this.isInternal && !filters.includeInternal) return true\n\t\treturn false\n\t}\n\n\tabstract getVertices(filters: Geometry2dFilters): Vec[]\n\n\tabstract nearestPoint(point: Vec, filters?: Geometry2dFilters): Vec\n\n\thitTestPoint(point: Vec, margin = 0, hitInside = false, filters?: Geometry2dFilters) {\n\t\tif (this.isExcludedByFilter(filters)) return false\n\t\t// First check whether the point is inside\n\t\tif (this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)) {\n\t\t\treturn true\n\t\t}\n\t\t// Then check whether the distance is within the margin\n\t\treturn Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin\n\t}\n\n\tdistanceToPoint(point: Vec, hitInside = false, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tpoint.dist(this.nearestPoint(point, filters)) *\n\t\t\t(this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)\n\t\t\t\t? -1\n\t\t\t\t: 1)\n\t\t)\n\t}\n\n\tdistanceToLineSegment(A: Vec, B: Vec, filters?: Geometry2dFilters) {\n\t\tif (A.equals(B)) return this.distanceToPoint(A, false, filters)\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn this.isClosed && this.isFilled && pointInPolygon(nearest, this.vertices) ? -dist : dist\n\t}\n\n\thitTestLineSegment(A: Vec, B: Vec, distance = 0, filters?: Geometry2dFilters): boolean {\n\t\treturn this.distanceToLineSegment(A, B, filters) <= distance\n\t}\n\n\tintersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\n\t\tconst intersections = this.isClosed\n\t\t\t? intersectLineSegmentPolygon(A, B, this.vertices)\n\t\t\t: intersectLineSegmentPolyline(A, B, this.vertices)\n\n\t\treturn intersections ?? []\n\t}\n\n\tintersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\tconst intersections = this.isClosed\n\t\t\t? intersectCirclePolygon(center, radius, this.vertices)\n\t\t\t: intersectCirclePolyline(center, radius, this.vertices)\n\n\t\treturn intersections ?? []\n\t}\n\n\tintersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\n\t\treturn intersectPolys(polygon, this.vertices, true, this.isClosed)\n\t}\n\n\tintersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\treturn intersectPolys(polyline, this.vertices, false, this.isClosed)\n\t}\n\n\t/** @deprecated Iterate the vertices instead. */\n\tnearestPointOnLineSegment(A: Vec, B: Vec): Vec {\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\tisPointInBounds(point: Vec, margin = 0) {\n\t\tconst { bounds } = this\n\t\treturn !(\n\t\t\tpoint.x < bounds.minX - margin ||\n\t\t\tpoint.y < bounds.minY - margin ||\n\t\t\tpoint.x > bounds.maxX + margin ||\n\t\t\tpoint.y > bounds.maxY + margin\n\t\t)\n\t}\n\n\ttransform(transform: MatModel): Geometry2d {\n\t\treturn new TransformedGeometry2d(this, transform)\n\t}\n\n\tprivate _vertices: Vec[] | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget vertices(): Vec[] {\n\t\tif (!this._vertices) {\n\t\t\tthis._vertices = this.getVertices(Geometry2dFilters.EXCLUDE_LABELS)\n\t\t}\n\n\t\treturn this._vertices\n\t}\n\n\tgetBounds() {\n\t\treturn Box.FromPoints(this.vertices)\n\t}\n\n\tprivate _bounds: Box | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bounds(): Box {\n\t\tif (!this._bounds) {\n\t\t\tthis._bounds = this.getBounds()\n\t\t}\n\t\treturn this._bounds\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn this.bounds.center\n\t}\n\n\tprivate _area: number | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget area() {\n\t\tif (!this._area) {\n\t\t\tthis._area = this.getArea()\n\t\t}\n\t\treturn this._area\n\t}\n\n\tgetArea() {\n\t\tif (!this.isClosed) {\n\t\t\treturn 0\n\t\t}\n\t\tconst { vertices } = this\n\t\tlet area = 0\n\t\tfor (let i = 0, n = vertices.length; i < n; i++) {\n\t\t\tconst curr = vertices[i]\n\t\t\tconst next = vertices[(i + 1) % n]\n\t\t\tarea += curr.x * next.y - next.x * curr.y\n\t\t}\n\t\treturn area / 2\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\n\t\tconst { vertices } = this\n\t\tconst n = vertices.length\n\n\t\tif (n === 0) return path\n\n\t\tpath += `M${vertices[0].x},${vertices[0].y}`\n\n\t\tfor (let i = 1; i < n; i++) {\n\t\t\tpath += `L${vertices[i].x},${vertices[i].y}`\n\t\t}\n\n\t\tif (this.isClosed) {\n\t\t\tpath += 'Z'\n\t\t}\n\n\t\treturn path\n\t}\n\n\tprivate _length?: number\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget length() {\n\t\tif (this._length) return this._length\n\t\tthis._length = this.getLength()\n\t\treturn this._length\n\t}\n\n\tgetLength() {\n\t\tconst { vertices } = this\n\t\tlet n1: Vec,\n\t\t\tp1 = vertices[0],\n\t\t\tlength = 0\n\t\tfor (let i = 1; i < vertices.length; i++) {\n\t\t\tn1 = vertices[i]\n\t\t\tlength += Vec.Dist2(p1, n1)\n\t\t\tp1 = n1\n\t\t}\n\t\treturn Math.sqrt(length)\n\t}\n\n\tabstract getSvgPathData(first: boolean): string\n}\n\n// =================================================================================================\n// Because Geometry2d.transform depends on TransformedGeometry2d, we need to define it here instead\n// of in its own files. This prevents a circular import error.\n// =================================================================================================\n\n/** @public */\nexport class TransformedGeometry2d extends Geometry2d {\n\tprivate readonly inverse: MatModel\n\tprivate readonly decomposed\n\n\tconstructor(\n\t\tprivate readonly geometry: Geometry2d,\n\t\tprivate readonly matrix: MatModel\n\t) {\n\t\tsuper(geometry)\n\t\tthis.inverse = Mat.Inverse(matrix)\n\t\tthis.decomposed = Mat.Decompose(matrix)\n\n\t\tassert(\n\t\t\tapproximately(this.decomposed.scaleX, this.decomposed.scaleY),\n\t\t\t'non-uniform scaling is not yet supported'\n\t\t)\n\t}\n\n\tgetVertices(filters: Geometry2dFilters): Vec[] {\n\t\treturn this.geometry.getVertices(filters).map((v) => Mat.applyToPoint(this.matrix, v))\n\t}\n\n\tnearestPoint(point: Vec, filters?: Geometry2dFilters): Vec {\n\t\treturn Mat.applyToPoint(\n\t\t\tthis.matrix,\n\t\t\tthis.geometry.nearestPoint(Mat.applyToPoint(this.inverse, point), filters)\n\t\t)\n\t}\n\n\toverride hitTestPoint(\n\t\tpoint: Vec,\n\t\tmargin = 0,\n\t\thitInside?: boolean,\n\t\tfilters?: Geometry2dFilters\n\t): boolean {\n\t\treturn this.geometry.hitTestPoint(\n\t\t\tMat.applyToPoint(this.inverse, point),\n\t\t\tmargin / this.decomposed.scaleX,\n\t\t\thitInside,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride distanceToPoint(point: Vec, hitInside = false, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tthis.geometry.distanceToPoint(Mat.applyToPoint(this.inverse, point), hitInside, filters) *\n\t\t\tthis.decomposed.scaleX\n\t\t)\n\t}\n\n\toverride distanceToLineSegment(A: Vec, B: Vec, filters?: Geometry2dFilters) {\n\t\treturn (\n\t\t\tthis.geometry.distanceToLineSegment(\n\t\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\t\tfilters\n\t\t\t) * this.decomposed.scaleX\n\t\t)\n\t}\n\n\toverride hitTestLineSegment(A: Vec, B: Vec, distance = 0, filters?: Geometry2dFilters): boolean {\n\t\treturn this.geometry.hitTestLineSegment(\n\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\tdistance / this.decomposed.scaleX,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {\n\t\treturn this.geometry.intersectLineSegment(\n\t\t\tMat.applyToPoint(this.inverse, A),\n\t\t\tMat.applyToPoint(this.inverse, B),\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {\n\t\treturn this.geometry.intersectCircle(\n\t\t\tMat.applyToPoint(this.inverse, center),\n\t\t\tradius / this.decomposed.scaleX,\n\t\t\tfilters\n\t\t)\n\t}\n\n\toverride intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\treturn this.geometry.intersectPolygon(Mat.applyToPoints(this.inverse, polygon), filters)\n\t}\n\n\toverride intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters): VecLike[] {\n\t\treturn this.geometry.intersectPolyline(Mat.applyToPoints(this.inverse, polyline), filters)\n\t}\n\n\toverride transform(transform: MatModel): Geometry2d {\n\t\treturn new TransformedGeometry2d(this.geometry, Mat.Multiply(transform, this.matrix))\n\t}\n\n\tgetSvgPathData(): string {\n\t\tthrow new Error('Cannot get SVG path data for transformed geometry.')\n\t}\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_utils"]
4
+ "sourcesContent": ["import { Box } from '../Box'\nimport { Vec } from '../Vec'\nimport { pointInPolygon } from '../utils'\n\n/** @public */\nexport interface Geometry2dOptions {\n\tisFilled: boolean\n\tisClosed: boolean\n\tisLabel?: boolean\n\tdebugColor?: string\n\tignore?: boolean\n}\n\n/** @public */\nexport abstract class Geometry2d {\n\tisFilled = false\n\tisClosed = true\n\tisLabel = false\n\tdebugColor?: string\n\tignore?: boolean\n\n\tconstructor(opts: Geometry2dOptions) {\n\t\tthis.isFilled = opts.isFilled\n\t\tthis.isClosed = opts.isClosed\n\t\tthis.isLabel = opts.isLabel ?? false\n\t\tthis.debugColor = opts.debugColor\n\t\tthis.ignore = opts.ignore\n\t}\n\n\tabstract getVertices(): Vec[]\n\n\tabstract nearestPoint(point: Vec): Vec\n\n\t// hitTestPoint(point: Vec, margin = 0, hitInside = false) {\n\t// \t// We've removed the broad phase here; that should be done outside of the call\n\t// \treturn this.distanceToPoint(point, hitInside) <= margin\n\t// }\n\n\thitTestPoint(point: Vec, margin = 0, hitInside = false) {\n\t\t// First check whether the point is inside\n\t\tif (this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)) {\n\t\t\treturn true\n\t\t}\n\t\t// Then check whether the distance is within the margin\n\t\treturn Vec.Dist2(point, this.nearestPoint(point)) <= margin * margin\n\t}\n\n\tdistanceToPoint(point: Vec, hitInside = false) {\n\t\treturn (\n\t\t\tpoint.dist(this.nearestPoint(point)) *\n\t\t\t(this.isClosed && (this.isFilled || hitInside) && pointInPolygon(point, this.vertices)\n\t\t\t\t? -1\n\t\t\t\t: 1)\n\t\t)\n\t}\n\n\tdistanceToLineSegment(A: Vec, B: Vec) {\n\t\tif (A.equals(B)) return this.distanceToPoint(A)\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn this.isClosed && this.isFilled && pointInPolygon(nearest, this.vertices) ? -dist : dist\n\t}\n\n\thitTestLineSegment(A: Vec, B: Vec, distance = 0): boolean {\n\t\treturn this.distanceToLineSegment(A, B) <= distance\n\t}\n\n\tnearestPointOnLineSegment(A: Vec, B: Vec): Vec {\n\t\tconst { vertices } = this\n\t\tlet nearest: Vec | undefined\n\t\tlet dist = Infinity\n\t\tlet d: number, p: Vec, q: Vec\n\t\tfor (let i = 0; i < vertices.length; i++) {\n\t\t\tp = vertices[i]\n\t\t\tq = Vec.NearestPointOnLineSegment(A, B, p, true)\n\t\t\td = Vec.Dist2(p, q)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = q\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\tisPointInBounds(point: Vec, margin = 0) {\n\t\tconst { bounds } = this\n\t\treturn !(\n\t\t\tpoint.x < bounds.minX - margin ||\n\t\t\tpoint.y < bounds.minY - margin ||\n\t\t\tpoint.x > bounds.maxX + margin ||\n\t\t\tpoint.y > bounds.maxY + margin\n\t\t)\n\t}\n\n\tprivate _vertices: Vec[] | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget vertices(): Vec[] {\n\t\tif (!this._vertices) {\n\t\t\tthis._vertices = this.getVertices()\n\t\t}\n\n\t\treturn this._vertices\n\t}\n\n\tgetBounds() {\n\t\treturn Box.FromPoints(this.vertices)\n\t}\n\n\tprivate _bounds: Box | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget bounds(): Box {\n\t\tif (!this._bounds) {\n\t\t\tthis._bounds = this.getBounds()\n\t\t}\n\t\treturn this._bounds\n\t}\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget center() {\n\t\treturn this.bounds.center\n\t}\n\n\tprivate _area: number | undefined\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget area() {\n\t\tif (!this._area) {\n\t\t\tthis._area = this.getArea()\n\t\t}\n\t\treturn this._area\n\t}\n\n\tgetArea() {\n\t\tif (!this.isClosed) {\n\t\t\treturn 0\n\t\t}\n\t\tconst { vertices } = this\n\t\tlet area = 0\n\t\tfor (let i = 0, n = vertices.length; i < n; i++) {\n\t\t\tconst curr = vertices[i]\n\t\t\tconst next = vertices[(i + 1) % n]\n\t\t\tarea += curr.x * next.y - next.x * curr.y\n\t\t}\n\t\treturn area / 2\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\n\t\tconst { vertices } = this\n\t\tconst n = vertices.length\n\n\t\tif (n === 0) return path\n\n\t\tpath += `M${vertices[0].x},${vertices[0].y}`\n\n\t\tfor (let i = 1; i < n; i++) {\n\t\t\tpath += `L${vertices[i].x},${vertices[i].y}`\n\t\t}\n\n\t\tif (this.isClosed) {\n\t\t\tpath += 'Z'\n\t\t}\n\n\t\treturn path\n\t}\n\n\tprivate _length?: number\n\n\t// eslint-disable-next-line no-restricted-syntax\n\tget length() {\n\t\tif (this._length) return this._length\n\t\tthis._length = this.getLength()\n\t\treturn this._length\n\t}\n\n\tgetLength() {\n\t\tconst { vertices } = this\n\t\tlet n1: Vec,\n\t\t\tp1 = vertices[0],\n\t\t\tlength = 0\n\t\tfor (let i = 1; i < vertices.length; i++) {\n\t\t\tn1 = vertices[i]\n\t\t\tlength += Vec.Dist2(p1, n1)\n\t\t\tp1 = n1\n\t\t}\n\t\treturn Math.sqrt(length)\n\t}\n\n\tabstract getSvgPathData(first: boolean): string\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
7
  }
@@ -21,7 +21,6 @@ __export(Group2d_exports, {
21
21
  Group2d: () => Group2d
22
22
  });
23
23
  module.exports = __toCommonJS(Group2d_exports);
24
- var import_state = require("@tldraw/state");
25
24
  var import_Box = require("../Box");
26
25
  var import_Vec = require("../Vec");
27
26
  var import_Geometry2d = require("./Geometry2d");
@@ -39,11 +38,10 @@ class Group2d extends import_Geometry2d.Geometry2d {
39
38
  }
40
39
  if (this.children.length === 0) throw Error("Group2d must have at least one child");
41
40
  }
42
- getVertices(filters) {
43
- if (this.isExcludedByFilter(filters)) return [];
44
- return this.children.filter((c) => !c.isExcludedByFilter(filters)).flatMap((c) => c.getVertices(filters));
41
+ getVertices() {
42
+ return this.children.filter((c) => !c.isLabel).flatMap((c) => c.vertices);
45
43
  }
46
- nearestPoint(point, filters) {
44
+ nearestPoint(point) {
47
45
  let dist = Infinity;
48
46
  let nearest;
49
47
  const { children } = this;
@@ -53,8 +51,7 @@ class Group2d extends import_Geometry2d.Geometry2d {
53
51
  let p;
54
52
  let d;
55
53
  for (const child of children) {
56
- if (child.isExcludedByFilter(filters)) continue;
57
- p = child.nearestPoint(point, filters);
54
+ p = child.nearestPoint(point);
58
55
  d = import_Vec.Vec.Dist2(p, point);
59
56
  if (d < dist) {
60
57
  dist = d;
@@ -64,54 +61,14 @@ class Group2d extends import_Geometry2d.Geometry2d {
64
61
  if (!nearest) throw Error("nearest point not found");
65
62
  return nearest;
66
63
  }
67
- distanceToPoint(point, hitInside = false, filters) {
68
- let smallestDistance = Infinity;
69
- for (const child of this.children) {
70
- if (child.isExcludedByFilter(filters)) continue;
71
- const distance = child.distanceToPoint(point, hitInside, filters);
72
- if (distance < smallestDistance) {
73
- smallestDistance = distance;
74
- }
75
- }
76
- return smallestDistance;
77
- }
78
- hitTestPoint(point, margin, hitInside, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
79
- return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestPoint(point, margin, hitInside));
80
- }
81
- hitTestLineSegment(A, B, zoom, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
82
- return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestLineSegment(A, B, zoom));
83
- }
84
- intersectLineSegment(A, B, filters) {
85
- return this.children.flatMap((child) => {
86
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
87
- return child.intersectLineSegment(A, B, filters);
88
- });
89
- }
90
- intersectCircle(center, radius, filters) {
91
- return this.children.flatMap((child) => {
92
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
93
- return child.intersectCircle(center, radius, filters);
94
- });
95
- }
96
- intersectPolygon(polygon, filters) {
97
- return this.children.flatMap((child) => {
98
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
99
- return child.intersectPolygon(polygon, filters);
100
- });
64
+ distanceToPoint(point, hitInside = false) {
65
+ return Math.min(...this.children.map((c, i) => c.distanceToPoint(point, hitInside || i > 0)));
101
66
  }
102
- intersectPolyline(polyline, filters) {
103
- return this.children.flatMap((child) => {
104
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
105
- return child.intersectPolyline(polyline, filters);
106
- });
67
+ hitTestPoint(point, margin, hitInside) {
68
+ return !!this.children.filter((c) => !c.isLabel).find((c) => c.hitTestPoint(point, margin, hitInside));
107
69
  }
108
- transform(transform) {
109
- return new Group2d({
110
- children: this.children.map((c) => c.transform(transform)),
111
- isLabel: this.isLabel,
112
- debugColor: this.debugColor,
113
- ignore: this.ignore
114
- });
70
+ hitTestLineSegment(A, B, zoom) {
71
+ return !!this.children.filter((c) => !c.isLabel).find((c) => c.hitTestLineSegment(A, B, zoom));
115
72
  }
116
73
  getArea() {
117
74
  return this.children[0].area;
@@ -139,7 +96,7 @@ class Group2d extends import_Geometry2d.Geometry2d {
139
96
  return this.children.reduce((a, c) => c.isLabel ? a : a + c.length, 0);
140
97
  }
141
98
  getSvgPathData() {
142
- return this.children.map((c, i) => c.isLabel ? "" : c.getSvgPathData(i === 0)).join(" ");
99
+ return this.children.map((c) => c.isLabel ? "" : c.getSvgPathData(true)).join(" ");
143
100
  }
144
101
  }
145
102
  //# sourceMappingURL=Group2d.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/primitives/geometry/Group2d.ts"],
4
- "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\nimport { Box } from '../Box'\nimport { Mat } from '../Mat'\nimport { Vec, VecLike } from '../Vec'\nimport { Geometry2d, Geometry2dFilters, Geometry2dOptions } from './Geometry2d'\n\n/** @public */\nexport class Group2d extends Geometry2d {\n\tchildren: Geometry2d[] = []\n\tignoredChildren: Geometry2d[] = []\n\n\tconstructor(\n\t\tconfig: Omit<Geometry2dOptions, 'isClosed' | 'isFilled'> & {\n\t\t\tchildren: Geometry2d[]\n\t\t}\n\t) {\n\t\tsuper({ ...config, isClosed: true, isFilled: false })\n\n\t\tfor (const child of config.children) {\n\t\t\tif (child.ignore) {\n\t\t\t\tthis.ignoredChildren.push(child)\n\t\t\t} else {\n\t\t\t\tthis.children.push(child)\n\t\t\t}\n\t\t}\n\n\t\tif (this.children.length === 0) throw Error('Group2d must have at least one child')\n\t}\n\n\toverride getVertices(filters: Geometry2dFilters): Vec[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\treturn this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.flatMap((c) => c.getVertices(filters))\n\t}\n\n\toverride nearestPoint(point: Vec, filters?: Geometry2dFilters): Vec {\n\t\tlet dist = Infinity\n\t\tlet nearest: Vec | undefined\n\n\t\tconst { children } = this\n\n\t\tif (children.length === 0) {\n\t\t\tthrow Error('no children')\n\t\t}\n\n\t\tlet p: Vec\n\t\tlet d: number\n\t\tfor (const child of children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tp = child.nearestPoint(point, filters)\n\t\t\td = Vec.Dist2(p, point)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = p\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\toverride distanceToPoint(point: Vec, hitInside = false, filters?: Geometry2dFilters) {\n\t\tlet smallestDistance = Infinity\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst distance = child.distanceToPoint(point, hitInside, filters)\n\t\t\tif (distance < smallestDistance) {\n\t\t\t\tsmallestDistance = distance\n\t\t\t}\n\t\t}\n\t\treturn smallestDistance\n\t}\n\n\toverride hitTestPoint(\n\t\tpoint: Vec,\n\t\tmargin: number,\n\t\thitInside: boolean,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\treturn !!this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.find((c) => c.hitTestPoint(point, margin, hitInside))\n\t}\n\n\toverride hitTestLineSegment(\n\t\tA: Vec,\n\t\tB: Vec,\n\t\tzoom: number,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\treturn !!this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.find((c) => c.hitTestLineSegment(A, B, zoom))\n\t}\n\n\toverride intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectLineSegment(A, B, filters)\n\t\t})\n\t}\n\n\toverride intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectCircle(center, radius, filters)\n\t\t})\n\t}\n\n\toverride intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectPolygon(polygon, filters)\n\t\t})\n\t}\n\n\toverride intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectPolyline(polyline, filters)\n\t\t})\n\t}\n\n\toverride transform(transform: Mat): Geometry2d {\n\t\treturn new Group2d({\n\t\t\tchildren: this.children.map((c) => c.transform(transform)),\n\t\t\tisLabel: this.isLabel,\n\t\t\tdebugColor: this.debugColor,\n\t\t\tignore: this.ignore,\n\t\t})\n\t}\n\n\tgetArea() {\n\t\t// todo: this is a temporary solution, assuming that the first child defines the group size; we would want to flatten the group and then find the area of the hull polygon\n\t\treturn this.children[0].area\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\t\tfor (const child of this.children) {\n\t\t\tpath += child.toSimpleSvgPath()\n\t\t}\n\n\t\tconst corners = Box.FromPoints(this.vertices).corners\n\t\t// draw just a few pixels around each corner, e.g. an L shape for the bottom left\n\n\t\tfor (let i = 0, n = corners.length; i < n; i++) {\n\t\t\tconst corner = corners[i]\n\t\t\tconst prevCorner = corners[(i - 1 + n) % n]\n\t\t\tconst prevDist = corner.dist(prevCorner)\n\t\t\tconst nextCorner = corners[(i + 1) % n]\n\t\t\tconst nextDist = corner.dist(nextCorner)\n\n\t\t\tconst A = corner.clone().lrp(prevCorner, 4 / prevDist)\n\t\t\tconst B = corner\n\t\t\tconst C = corner.clone().lrp(nextCorner, 4 / nextDist)\n\n\t\t\tpath += `M${A.x},${A.y} L${B.x},${B.y} L${C.x},${C.y} `\n\t\t}\n\t\treturn path\n\t}\n\n\tgetLength(): number {\n\t\treturn this.children.reduce((a, c) => (c.isLabel ? a : a + c.length), 0)\n\t}\n\n\tgetSvgPathData(): string {\n\t\treturn this.children.map((c, i) => (c.isLabel ? '' : c.getSvgPathData(i === 0))).join(' ')\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box } from '../Box'\nimport { Vec } from '../Vec'\nimport { Geometry2d, Geometry2dOptions } from './Geometry2d'\n\n/** @public */\nexport class Group2d extends Geometry2d {\n\tchildren: Geometry2d[] = []\n\tignoredChildren: Geometry2d[] = []\n\n\tconstructor(\n\t\tconfig: Omit<Geometry2dOptions, 'isClosed' | 'isFilled'> & {\n\t\t\tchildren: Geometry2d[]\n\t\t}\n\t) {\n\t\tsuper({ ...config, isClosed: true, isFilled: false })\n\n\t\tfor (const child of config.children) {\n\t\t\tif (child.ignore) {\n\t\t\t\tthis.ignoredChildren.push(child)\n\t\t\t} else {\n\t\t\t\tthis.children.push(child)\n\t\t\t}\n\t\t}\n\n\t\tif (this.children.length === 0) throw Error('Group2d must have at least one child')\n\t}\n\n\toverride getVertices(): Vec[] {\n\t\treturn this.children.filter((c) => !c.isLabel).flatMap((c) => c.vertices)\n\t}\n\n\toverride nearestPoint(point: Vec): Vec {\n\t\tlet dist = Infinity\n\t\tlet nearest: Vec | undefined\n\n\t\tconst { children } = this\n\n\t\tif (children.length === 0) {\n\t\t\tthrow Error('no children')\n\t\t}\n\n\t\tlet p: Vec\n\t\tlet d: number\n\t\tfor (const child of children) {\n\t\t\tp = child.nearestPoint(point)\n\t\t\td = Vec.Dist2(p, point)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = p\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\toverride distanceToPoint(point: Vec, hitInside = false) {\n\t\treturn Math.min(...this.children.map((c, i) => c.distanceToPoint(point, hitInside || i > 0)))\n\t}\n\n\toverride hitTestPoint(point: Vec, margin: number, hitInside: boolean): boolean {\n\t\treturn !!this.children\n\t\t\t.filter((c) => !c.isLabel)\n\t\t\t.find((c) => c.hitTestPoint(point, margin, hitInside))\n\t}\n\n\toverride hitTestLineSegment(A: Vec, B: Vec, zoom: number): boolean {\n\t\treturn !!this.children.filter((c) => !c.isLabel).find((c) => c.hitTestLineSegment(A, B, zoom))\n\t}\n\n\tgetArea() {\n\t\t// todo: this is a temporary solution, assuming that the first child defines the group size; we would want to flatten the group and then find the area of the hull polygon\n\t\treturn this.children[0].area\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\t\tfor (const child of this.children) {\n\t\t\tpath += child.toSimpleSvgPath()\n\t\t}\n\n\t\tconst corners = Box.FromPoints(this.vertices).corners\n\t\t// draw just a few pixels around each corner, e.g. an L shape for the bottom left\n\n\t\tfor (let i = 0, n = corners.length; i < n; i++) {\n\t\t\tconst corner = corners[i]\n\t\t\tconst prevCorner = corners[(i - 1 + n) % n]\n\t\t\tconst prevDist = corner.dist(prevCorner)\n\t\t\tconst nextCorner = corners[(i + 1) % n]\n\t\t\tconst nextDist = corner.dist(nextCorner)\n\n\t\t\tconst A = corner.clone().lrp(prevCorner, 4 / prevDist)\n\t\t\tconst B = corner\n\t\t\tconst C = corner.clone().lrp(nextCorner, 4 / nextDist)\n\n\t\t\tpath += `M${A.x},${A.y} L${B.x},${B.y} L${C.x},${C.y} `\n\t\t}\n\t\treturn path\n\t}\n\n\tgetLength(): number {\n\t\treturn this.children.reduce((a, c) => (c.isLabel ? a : a + c.length), 0)\n\t}\n\n\tgetSvgPathData(): string {\n\t\treturn this.children.map((c) => (c.isLabel ? '' : c.getSvgPathData(true))).join(' ')\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAoB;AACpB,iBAAoB;AACpB,wBAA8C;AAGvC,MAAM,gBAAgB,6BAAW;AAAA,EACvC,WAAyB,CAAC;AAAA,EAC1B,kBAAgC,CAAC;AAAA,EAEjC,YACC,QAGC;AACD,UAAM,EAAE,GAAG,QAAQ,UAAU,MAAM,UAAU,MAAM,CAAC;AAEpD,eAAW,SAAS,OAAO,UAAU;AACpC,UAAI,MAAM,QAAQ;AACjB,aAAK,gBAAgB,KAAK,KAAK;AAAA,MAChC,OAAO;AACN,aAAK,SAAS,KAAK,KAAK;AAAA,MACzB;AAAA,IACD;AAEA,QAAI,KAAK,SAAS,WAAW,EAAG,OAAM,MAAM,sCAAsC;AAAA,EACnF;AAAA,EAES,cAAqB;AAC7B,WAAO,KAAK,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ;AAAA,EACzE;AAAA,EAES,aAAa,OAAiB;AACtC,QAAI,OAAO;AACX,QAAI;AAEJ,UAAM,EAAE,SAAS,IAAI;AAErB,QAAI,SAAS,WAAW,GAAG;AAC1B,YAAM,MAAM,aAAa;AAAA,IAC1B;AAEA,QAAI;AACJ,QAAI;AACJ,eAAW,SAAS,UAAU;AAC7B,UAAI,MAAM,aAAa,KAAK;AAC5B,UAAI,eAAI,MAAM,GAAG,KAAK;AACtB,UAAI,IAAI,MAAM;AACb,eAAO;AACP,kBAAU;AAAA,MACX;AAAA,IACD;AACA,QAAI,CAAC,QAAS,OAAM,MAAM,yBAAyB;AACnD,WAAO;AAAA,EACR;AAAA,EAES,gBAAgB,OAAY,YAAY,OAAO;AACvD,WAAO,KAAK,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,MAAM,EAAE,gBAAgB,OAAO,aAAa,IAAI,CAAC,CAAC,CAAC;AAAA,EAC7F;AAAA,EAES,aAAa,OAAY,QAAgB,WAA6B;AAC9E,WAAO,CAAC,CAAC,KAAK,SACZ,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EACxB,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO,QAAQ,SAAS,CAAC;AAAA,EACvD;AAAA,EAES,mBAAmB,GAAQ,GAAQ,MAAuB;AAClE,WAAO,CAAC,CAAC,KAAK,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,GAAG,IAAI,CAAC;AAAA,EAC9F;AAAA,EAEA,UAAU;AAET,WAAO,KAAK,SAAS,CAAC,EAAE;AAAA,EACzB;AAAA,EAEA,kBAAkB;AACjB,QAAI,OAAO;AACX,eAAW,SAAS,KAAK,UAAU;AAClC,cAAQ,MAAM,gBAAgB;AAAA,IAC/B;AAEA,UAAM,UAAU,eAAI,WAAW,KAAK,QAAQ,EAAE;AAG9C,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAC/C,YAAM,SAAS,QAAQ,CAAC;AACxB,YAAM,aAAa,SAAS,IAAI,IAAI,KAAK,CAAC;AAC1C,YAAM,WAAW,OAAO,KAAK,UAAU;AACvC,YAAM,aAAa,SAAS,IAAI,KAAK,CAAC;AACtC,YAAM,WAAW,OAAO,KAAK,UAAU;AAEvC,YAAM,IAAI,OAAO,MAAM,EAAE,IAAI,YAAY,IAAI,QAAQ;AACrD,YAAM,IAAI;AACV,YAAM,IAAI,OAAO,MAAM,EAAE,IAAI,YAAY,IAAI,QAAQ;AAErD,cAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,IACrD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,YAAoB;AACnB,WAAO,KAAK,SAAS,OAAO,CAAC,GAAG,MAAO,EAAE,UAAU,IAAI,IAAI,EAAE,QAAS,CAAC;AAAA,EACxE;AAAA,EAEA,iBAAyB;AACxB,WAAO,KAAK,SAAS,IAAI,CAAC,MAAO,EAAE,UAAU,KAAK,EAAE,eAAe,IAAI,CAAE,EAAE,KAAK,GAAG;AAAA,EACpF;AACD;",
6
6
  "names": []
7
7
  }
@@ -27,7 +27,6 @@ __export(intersect_exports, {
27
27
  intersectLineSegmentPolyline: () => intersectLineSegmentPolyline,
28
28
  intersectPolygonBounds: () => intersectPolygonBounds,
29
29
  intersectPolygonPolygon: () => intersectPolygonPolygon,
30
- intersectPolys: () => intersectPolys,
31
30
  linesIntersect: () => linesIntersect,
32
31
  polygonIntersectsPolyline: () => polygonIntersectsPolyline,
33
32
  polygonsIntersect: () => polygonsIntersect
@@ -190,25 +189,6 @@ function intersectPolygonPolygon(polygonA, polygonB) {
190
189
  if (result.size === 0) return null;
191
190
  return orderClockwise([...result.values()]);
192
191
  }
193
- function intersectPolys(polyA, polyB, isAClosed, isBClosed) {
194
- const result = /* @__PURE__ */ new Map();
195
- for (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {
196
- const currentA = polyA[i];
197
- const nextA = polyA[(i + 1) % polyA.length];
198
- for (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {
199
- const currentB = polyB[j];
200
- const nextB = polyB[(j + 1) % polyB.length];
201
- const intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB);
202
- if (intersection !== null) {
203
- const id = getPointId(intersection);
204
- if (!result.has(id)) {
205
- result.set(id, intersection);
206
- }
207
- }
208
- }
209
- }
210
- return [...result.values()];
211
- }
212
192
  function getPointId(point) {
213
193
  return `${point.x},${point.y}`;
214
194
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/primitives/intersect.ts"],
4
- "sourcesContent": ["import { Box } from './Box'\nimport { pointInPolygon } from './utils'\nimport { Vec, VecLike } from './Vec'\n\n// need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52\n\n/**\n * Find the intersection between a line segment and a line segment.\n *\n * @param a1 - The first segment's first point.\n * @param a2 - The first segment's second point.\n * @param b1 - The second segment's first point.\n * @param b2 - The second segment's second point.\n * @public\n */\nexport function intersectLineSegmentLineSegment(\n\ta1: VecLike,\n\ta2: VecLike,\n\tb1: VecLike,\n\tb2: VecLike\n) {\n\tconst ABx = a1.x - b1.x\n\tconst ABy = a1.y - b1.y\n\tconst BVx = b2.x - b1.x\n\tconst BVy = b2.y - b1.y\n\tconst AVx = a2.x - a1.x\n\tconst AVy = a2.y - a1.y\n\tconst ua_t = BVx * ABy - BVy * ABx\n\tconst ub_t = AVx * ABy - AVy * ABx\n\tconst u_b = BVy * AVx - BVx * AVy\n\n\tif (ua_t === 0 || ub_t === 0) return null // coincident\n\n\tif (u_b === 0) return null // parallel\n\n\tif (u_b !== 0) {\n\t\tconst ua = ua_t / u_b\n\t\tconst ub = ub_t / u_b\n\t\tif (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n\t\t\treturn Vec.AddXY(a1, ua * AVx, ua * AVy)\n\t\t}\n\t}\n\n\treturn null // no intersection\n}\n\n/**\n * Find the intersections between a line segment and a circle.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @public\n */\nexport function intersectLineSegmentCircle(a1: VecLike, a2: VecLike, c: VecLike, r: number) {\n\tconst a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y)\n\tconst b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y))\n\tconst cc =\n\t\tc.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r\n\tconst deter = b * b - 4 * a * cc\n\n\tif (deter < 0) return null // outside\n\tif (deter === 0) return null // tangent\n\n\tconst e = Math.sqrt(deter)\n\tconst u1 = (-b + e) / (2 * a)\n\tconst u2 = (-b - e) / (2 * a)\n\n\tif ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {\n\t\treturn null // outside or inside\n\t\t// if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {\n\t\t// \treturn null // outside\n\t\t// } else return null // inside'\n\t}\n\n\tconst result: VecLike[] = []\n\n\tif (0 <= u1 && u1 <= 1) result.push(Vec.Lrp(a1, a2, u1))\n\tif (0 <= u2 && u2 <= 1) result.push(Vec.Lrp(a1, a2, u2))\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a polyline.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectLineSegmentPolyline(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 0, n = points.length - 1; i < n; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(a1, a2, points[i], points[i + 1])\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a closed polygon.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectLineSegmentPolygon(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 1, n = points.length; i < n + 1; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(\n\t\t\ta1,\n\t\t\ta2,\n\t\t\tpoints[i - 1],\n\t\t\tpoints[i % points.length]\n\t\t)\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a circle.\n *\n * @param c1 - The first circle's center.\n * @param r1 - The first circle's radius.\n * @param c2 - The second circle's center.\n * @param r2 - The second circle's radius.\n * @public\n */\nexport function intersectCircleCircle(c1: VecLike, r1: number, c2: VecLike, r2: number) {\n\tlet dx = c2.x - c1.x\n\tlet dy = c2.y - c1.y\n\tconst d = Math.sqrt(dx * dx + dy * dy),\n\t\tx = (d * d - r2 * r2 + r1 * r1) / (2 * d),\n\t\ty = Math.sqrt(r1 * r1 - x * x)\n\tdx /= d\n\tdy /= d\n\treturn [\n\t\tnew Vec(c1.x + dx * x - dy * y, c1.y + dy * x + dx * y),\n\t\tnew Vec(c1.x + dx * x + dy * y, c1.y + dy * x - dx * y),\n\t]\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectCirclePolygon(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\ta = points[i]\n\t\tb = points[(i + 1) % points.length]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectCirclePolyline(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 1, n = points.length; i < n; i++) {\n\t\ta = points[i - 1]\n\t\tb = points[i]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a polygon and a bounding box.\n *\n * @public\n */\nexport function intersectPolygonBounds(points: VecLike[], bounds: Box) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike[] | null\n\n\tfor (const side of bounds.sides) {\n\t\tsegmentIntersection = intersectLineSegmentPolygon(side[0], side[1], points)\n\t\tif (segmentIntersection) result.push(...segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\nfunction ccw(A: VecLike, B: VecLike, C: VecLike) {\n\treturn (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x)\n}\n\n/** @public */\nexport function linesIntersect(A: VecLike, B: VecLike, C: VecLike, D: VecLike) {\n\treturn ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D)\n}\n\n/**\n * Create a new convex polygon as the intersection of two convex polygons.\n *\n * @param polygonA - An array of points representing the first polygon.\n * @param polygonB - An array of points representing the second polygon.\n * @public\n */\nexport function intersectPolygonPolygon(\n\tpolygonA: VecLike[],\n\tpolygonB: VecLike[]\n): VecLike[] | null {\n\t// Create an empty polygon as result\n\tconst result: Map<string, VecLike> = new Map()\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\n\t// Add all corners of PolygonA that is inside PolygonB to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tif (pointInPolygon(a, polygonB)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\t// Add all corners of PolygonB that is inside PolygonA to result\n\tfor (let i = 0, n = polygonB.length; i < n; i++) {\n\t\ta = polygonB[i]\n\t\tif (pointInPolygon(a, polygonA)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tb = polygonA[(i + 1) % polygonA.length]\n\n\t\tfor (let j = 0, m = polygonB.length; j < m; j++) {\n\t\t\tc = polygonB[j]\n\t\t\td = polygonB[(j + 1) % polygonB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(a, b, c, d)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (result.size === 0) return null // no intersection\n\n\t// Order all points in the result counter-clockwise.\n\treturn orderClockwise([...result.values()])\n}\n\n/**\n * Find all the points where `polyA` and `polyB` intersect and returns them in an undefined order.\n * To find the polygon that's the intersection of polyA and polyB, use `intersectPolygonPolygon`\n * instead, which orders the points and includes internal points.\n *\n * @param polyA - The first polygon.\n * @param polyB - The second polygon.\n * @param isAClosed - Whether `polyA` is a closed polygon or a polyline.\n * @param isBClosed - Whether `polyB` is a closed polygon or a polyline.\n * @public\n */\nexport function intersectPolys(\n\tpolyA: VecLike[],\n\tpolyB: VecLike[],\n\tisAClosed: boolean,\n\tisBClosed: boolean\n): VecLike[] {\n\tconst result: Map<string, VecLike> = new Map()\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = isAClosed ? polyA.length : polyA.length - 1; i < n; i++) {\n\t\tconst currentA = polyA[i]\n\t\tconst nextA = polyA[(i + 1) % polyA.length]\n\n\t\tfor (let j = 0, m = isBClosed ? polyB.length : polyB.length - 1; j < m; j++) {\n\t\t\tconst currentB = polyB[j]\n\t\t\tconst nextB = polyB[(j + 1) % polyB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(currentA, nextA, currentB, nextB)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn [...result.values()]\n}\n\nfunction getPointId(point: VecLike) {\n\treturn `${point.x},${point.y}`\n}\n\nfunction orderClockwise(points: VecLike[]): VecLike[] {\n\tconst C = Vec.Average(points)\n\treturn points.sort((A, B) => Vec.Angle(C, A) - Vec.Angle(C, B))\n}\n\n/** @public */\nexport function polygonsIntersect(a: VecLike[], b: VecLike[]) {\n\tlet a0: VecLike, a1: VecLike, b0: VecLike, b1: VecLike\n\tfor (let i = 0, n = a.length; i < n; i++) {\n\t\ta0 = a[i]\n\t\ta1 = a[(i + 1) % n]\n\t\tfor (let j = 0, m = b.length; j < m; j++) {\n\t\t\tb0 = b[j]\n\t\t\tb1 = b[(j + 1) % m]\n\t\t\tif (linesIntersect(a0, a1, b0, b1)) return true\n\t\t}\n\t}\n\treturn false\n}\n\n/** @public */\nexport function polygonIntersectsPolyline(polygon: VecLike[], polyline: VecLike[]) {\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\tfor (let i = 0, n = polygon.length; i < n; i++) {\n\t\ta = polygon[i]\n\t\tb = polygon[(i + 1) % n]\n\n\t\tfor (let j = 1, m = polyline.length; j < m; j++) {\n\t\t\tc = polyline[j - 1]\n\t\t\td = polyline[j]\n\t\t\tif (linesIntersect(a, b, c, d)) return true\n\t\t}\n\t}\n\treturn false\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Box } from './Box'\nimport { pointInPolygon } from './utils'\nimport { Vec, VecLike } from './Vec'\n\n// need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52\n\n/**\n * Find the intersection between a line segment and a line segment.\n *\n * @param a1 - The first segment's first point.\n * @param a2 - The first segment's second point.\n * @param b1 - The second segment's first point.\n * @param b2 - The second segment's second point.\n * @public\n */\nexport function intersectLineSegmentLineSegment(\n\ta1: VecLike,\n\ta2: VecLike,\n\tb1: VecLike,\n\tb2: VecLike\n) {\n\tconst ABx = a1.x - b1.x\n\tconst ABy = a1.y - b1.y\n\tconst BVx = b2.x - b1.x\n\tconst BVy = b2.y - b1.y\n\tconst AVx = a2.x - a1.x\n\tconst AVy = a2.y - a1.y\n\tconst ua_t = BVx * ABy - BVy * ABx\n\tconst ub_t = AVx * ABy - AVy * ABx\n\tconst u_b = BVy * AVx - BVx * AVy\n\n\tif (ua_t === 0 || ub_t === 0) return null // coincident\n\n\tif (u_b === 0) return null // parallel\n\n\tif (u_b !== 0) {\n\t\tconst ua = ua_t / u_b\n\t\tconst ub = ub_t / u_b\n\t\tif (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {\n\t\t\treturn Vec.AddXY(a1, ua * AVx, ua * AVy)\n\t\t}\n\t}\n\n\treturn null // no intersection\n}\n\n/**\n * Find the intersections between a line segment and a circle.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @public\n */\nexport function intersectLineSegmentCircle(a1: VecLike, a2: VecLike, c: VecLike, r: number) {\n\tconst a = (a2.x - a1.x) * (a2.x - a1.x) + (a2.y - a1.y) * (a2.y - a1.y)\n\tconst b = 2 * ((a2.x - a1.x) * (a1.x - c.x) + (a2.y - a1.y) * (a1.y - c.y))\n\tconst cc =\n\t\tc.x * c.x + c.y * c.y + a1.x * a1.x + a1.y * a1.y - 2 * (c.x * a1.x + c.y * a1.y) - r * r\n\tconst deter = b * b - 4 * a * cc\n\n\tif (deter < 0) return null // outside\n\tif (deter === 0) return null // tangent\n\n\tconst e = Math.sqrt(deter)\n\tconst u1 = (-b + e) / (2 * a)\n\tconst u2 = (-b - e) / (2 * a)\n\n\tif ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {\n\t\treturn null // outside or inside\n\t\t// if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {\n\t\t// \treturn null // outside\n\t\t// } else return null // inside'\n\t}\n\n\tconst result: VecLike[] = []\n\n\tif (0 <= u1 && u1 <= 1) result.push(Vec.Lrp(a1, a2, u1))\n\tif (0 <= u2 && u2 <= 1) result.push(Vec.Lrp(a1, a2, u2))\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a polyline.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectLineSegmentPolyline(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 0, n = points.length - 1; i < n; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(a1, a2, points[i], points[i + 1])\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a line segment and a closed polygon.\n *\n * @param a1 - The segment's first point.\n * @param a2 - The segment's second point.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectLineSegmentPolygon(a1: VecLike, a2: VecLike, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike | null\n\n\tfor (let i = 1, n = points.length; i < n + 1; i++) {\n\t\tsegmentIntersection = intersectLineSegmentLineSegment(\n\t\t\ta1,\n\t\t\ta2,\n\t\t\tpoints[i - 1],\n\t\t\tpoints[i % points.length]\n\t\t)\n\t\tif (segmentIntersection) result.push(segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a circle.\n *\n * @param c1 - The first circle's center.\n * @param r1 - The first circle's radius.\n * @param c2 - The second circle's center.\n * @param r2 - The second circle's radius.\n * @public\n */\nexport function intersectCircleCircle(c1: VecLike, r1: number, c2: VecLike, r2: number) {\n\tlet dx = c2.x - c1.x\n\tlet dy = c2.y - c1.y\n\tconst d = Math.sqrt(dx * dx + dy * dy),\n\t\tx = (d * d - r2 * r2 + r1 * r1) / (2 * d),\n\t\ty = Math.sqrt(r1 * r1 - x * x)\n\tdx /= d\n\tdy /= d\n\treturn [\n\t\tnew Vec(c1.x + dx * x - dy * y, c1.y + dy * x + dx * y),\n\t\tnew Vec(c1.x + dx * x + dy * y, c1.y + dy * x - dx * y),\n\t]\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polygon.\n * @public\n */\nexport function intersectCirclePolygon(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 0, n = points.length; i < n; i++) {\n\t\ta = points[i]\n\t\tb = points[(i + 1) % points.length]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a circle and a bounding box.\n *\n * @param c - The circle's center.\n * @param r - The circle's radius.\n * @param points - The points in the polyline.\n * @public\n */\nexport function intersectCirclePolyline(c: VecLike, r: number, points: VecLike[]) {\n\tconst result: VecLike[] = []\n\tlet a: VecLike, b: VecLike, int: VecLike[] | null\n\n\tfor (let i = 1, n = points.length; i < n; i++) {\n\t\ta = points[i - 1]\n\t\tb = points[i]\n\t\tint = intersectLineSegmentCircle(a, b, c, r)\n\t\tif (int) result.push(...int)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\n/**\n * Find the intersections between a polygon and a bounding box.\n *\n * @public\n */\nexport function intersectPolygonBounds(points: VecLike[], bounds: Box) {\n\tconst result: VecLike[] = []\n\tlet segmentIntersection: VecLike[] | null\n\n\tfor (const side of bounds.sides) {\n\t\tsegmentIntersection = intersectLineSegmentPolygon(side[0], side[1], points)\n\t\tif (segmentIntersection) result.push(...segmentIntersection)\n\t}\n\n\tif (result.length === 0) return null // no intersection\n\n\treturn result\n}\n\nfunction ccw(A: VecLike, B: VecLike, C: VecLike) {\n\treturn (C.y - A.y) * (B.x - A.x) > (B.y - A.y) * (C.x - A.x)\n}\n\n/** @public */\nexport function linesIntersect(A: VecLike, B: VecLike, C: VecLike, D: VecLike) {\n\treturn ccw(A, C, D) !== ccw(B, C, D) && ccw(A, B, C) !== ccw(A, B, D)\n}\n\n/**\n * Create a new convex polygon as the intersection of two convex polygons.\n *\n * @param polygonA - An array of points representing the first polygon.\n * @param polygonB - An array of points representing the second polygon.\n * @public\n */\nexport function intersectPolygonPolygon(\n\tpolygonA: VecLike[],\n\tpolygonB: VecLike[]\n): VecLike[] | null {\n\t// Create an empty polygon as result\n\tconst result: Map<string, VecLike> = new Map()\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\n\t// Add all corners of PolygonA that is inside PolygonB to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tif (pointInPolygon(a, polygonB)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\t// Add all corners of PolygonB that is inside PolygonA to result\n\tfor (let i = 0, n = polygonB.length; i < n; i++) {\n\t\ta = polygonB[i]\n\t\tif (pointInPolygon(a, polygonA)) {\n\t\t\tconst id = getPointId(a)\n\t\t\tif (!result.has(id)) {\n\t\t\t\tresult.set(id, a)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add all intersection points to result\n\tfor (let i = 0, n = polygonA.length; i < n; i++) {\n\t\ta = polygonA[i]\n\t\tb = polygonA[(i + 1) % polygonA.length]\n\n\t\tfor (let j = 0, m = polygonB.length; j < m; j++) {\n\t\t\tc = polygonB[j]\n\t\t\td = polygonB[(j + 1) % polygonB.length]\n\t\t\tconst intersection = intersectLineSegmentLineSegment(a, b, c, d)\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tconst id = getPointId(intersection)\n\t\t\t\tif (!result.has(id)) {\n\t\t\t\t\tresult.set(id, intersection)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (result.size === 0) return null // no intersection\n\n\t// Order all points in the result counter-clockwise.\n\treturn orderClockwise([...result.values()])\n}\n\nfunction getPointId(point: VecLike) {\n\treturn `${point.x},${point.y}`\n}\n\nfunction orderClockwise(points: VecLike[]): VecLike[] {\n\tconst C = Vec.Average(points)\n\treturn points.sort((A, B) => Vec.Angle(C, A) - Vec.Angle(C, B))\n}\n\n/** @public */\nexport function polygonsIntersect(a: VecLike[], b: VecLike[]) {\n\tlet a0: VecLike, a1: VecLike, b0: VecLike, b1: VecLike\n\tfor (let i = 0, n = a.length; i < n; i++) {\n\t\ta0 = a[i]\n\t\ta1 = a[(i + 1) % n]\n\t\tfor (let j = 0, m = b.length; j < m; j++) {\n\t\t\tb0 = b[j]\n\t\t\tb1 = b[(j + 1) % m]\n\t\t\tif (linesIntersect(a0, a1, b0, b1)) return true\n\t\t}\n\t}\n\treturn false\n}\n\n/** @public */\nexport function polygonIntersectsPolyline(polygon: VecLike[], polyline: VecLike[]) {\n\tlet a: VecLike, b: VecLike, c: VecLike, d: VecLike\n\tfor (let i = 0, n = polygon.length; i < n; i++) {\n\t\ta = polygon[i]\n\t\tb = polygon[(i + 1) % n]\n\n\t\tfor (let j = 1, m = polyline.length; j < m; j++) {\n\t\t\tc = polyline[j - 1]\n\t\t\td = polyline[j]\n\t\t\tif (linesIntersect(a, b, c, d)) return true\n\t\t}\n\t}\n\treturn false\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA+B;AAC/B,iBAA6B;AAatB,SAAS,gCACf,IACA,IACA,IACA,IACC;AACD,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,MAAM,GAAG,IAAI,GAAG;AACtB,QAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,QAAM,OAAO,MAAM,MAAM,MAAM;AAC/B,QAAM,MAAM,MAAM,MAAM,MAAM;AAE9B,MAAI,SAAS,KAAK,SAAS,EAAG,QAAO;AAErC,MAAI,QAAQ,EAAG,QAAO;AAEtB,MAAI,QAAQ,GAAG;AACd,UAAM,KAAK,OAAO;AAClB,UAAM,KAAK,OAAO;AAClB,QAAI,KAAK,MAAM,MAAM,KAAK,KAAK,MAAM,MAAM,GAAG;AAC7C,aAAO,eAAI,MAAM,IAAI,KAAK,KAAK,KAAK,GAAG;AAAA,IACxC;AAAA,EACD;AAEA,SAAO;AACR;AAWO,SAAS,2BAA2B,IAAa,IAAa,GAAY,GAAW;AAC3F,QAAM,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG;AACrE,QAAM,IAAI,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,EAAE;AACxE,QAAM,KACL,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,GAAG,KAAK,IAAI;AACzF,QAAM,QAAQ,IAAI,IAAI,IAAI,IAAI;AAE9B,MAAI,QAAQ,EAAG,QAAO;AACtB,MAAI,UAAU,EAAG,QAAO;AAExB,QAAM,IAAI,KAAK,KAAK,KAAK;AACzB,QAAM,MAAM,CAAC,IAAI,MAAM,IAAI;AAC3B,QAAM,MAAM,CAAC,IAAI,MAAM,IAAI;AAE3B,OAAK,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,KAAK,IAAI;AAC7C,WAAO;AAAA,EAIR;AAEA,QAAM,SAAoB,CAAC;AAE3B,MAAI,KAAK,MAAM,MAAM,EAAG,QAAO,KAAK,eAAI,IAAI,IAAI,IAAI,EAAE,CAAC;AACvD,MAAI,KAAK,MAAM,MAAM,EAAG,QAAO,KAAK,eAAI,IAAI,IAAI,IAAI,EAAE,CAAC;AAEvD,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAUO,SAAS,6BAA6B,IAAa,IAAa,QAAmB;AACzF,QAAM,SAAoB,CAAC;AAC3B,MAAI;AAEJ,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAClD,0BAAsB,gCAAgC,IAAI,IAAI,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACtF,QAAI,oBAAqB,QAAO,KAAK,mBAAmB;AAAA,EACzD;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAUO,SAAS,4BAA4B,IAAa,IAAa,QAAmB;AACxF,QAAM,SAAoB,CAAC;AAC3B,MAAI;AAEJ,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,IAAI,GAAG,KAAK;AAClD,0BAAsB;AAAA,MACrB;AAAA,MACA;AAAA,MACA,OAAO,IAAI,CAAC;AAAA,MACZ,OAAO,IAAI,OAAO,MAAM;AAAA,IACzB;AACA,QAAI,oBAAqB,QAAO,KAAK,mBAAmB;AAAA,EACzD;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAWO,SAAS,sBAAsB,IAAa,IAAY,IAAa,IAAY;AACvF,MAAI,KAAK,GAAG,IAAI,GAAG;AACnB,MAAI,KAAK,GAAG,IAAI,GAAG;AACnB,QAAM,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,GACpC,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,OAAO,IAAI,IACvC,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,CAAC;AAC9B,QAAM;AACN,QAAM;AACN,SAAO;AAAA,IACN,IAAI,eAAI,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,IACtD,IAAI,eAAI,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,IAAI,KAAK,CAAC;AAAA,EACvD;AACD;AAUO,SAAS,uBAAuB,GAAY,GAAW,QAAmB;AAChF,QAAM,SAAoB,CAAC;AAC3B,MAAI,GAAY,GAAY;AAE5B,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC9C,QAAI,OAAO,CAAC;AACZ,QAAI,QAAQ,IAAI,KAAK,OAAO,MAAM;AAClC,UAAM,2BAA2B,GAAG,GAAG,GAAG,CAAC;AAC3C,QAAI,IAAK,QAAO,KAAK,GAAG,GAAG;AAAA,EAC5B;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAUO,SAAS,wBAAwB,GAAY,GAAW,QAAmB;AACjF,QAAM,SAAoB,CAAC;AAC3B,MAAI,GAAY,GAAY;AAE5B,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,GAAG,KAAK;AAC9C,QAAI,OAAO,IAAI,CAAC;AAChB,QAAI,OAAO,CAAC;AACZ,UAAM,2BAA2B,GAAG,GAAG,GAAG,CAAC;AAC3C,QAAI,IAAK,QAAO,KAAK,GAAG,GAAG;AAAA,EAC5B;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAOO,SAAS,uBAAuB,QAAmB,QAAa;AACtE,QAAM,SAAoB,CAAC;AAC3B,MAAI;AAEJ,aAAW,QAAQ,OAAO,OAAO;AAChC,0BAAsB,4BAA4B,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,MAAM;AAC1E,QAAI,oBAAqB,QAAO,KAAK,GAAG,mBAAmB;AAAA,EAC5D;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO;AACR;AAEA,SAAS,IAAI,GAAY,GAAY,GAAY;AAChD,UAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAC3D;AAGO,SAAS,eAAe,GAAY,GAAY,GAAY,GAAY;AAC9E,SAAO,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC;AACrE;AASO,SAAS,wBACf,UACA,UACmB;AAEnB,QAAM,SAA+B,oBAAI,IAAI;AAC7C,MAAI,GAAY,GAAY,GAAY;AAGxC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,QAAI,SAAS,CAAC;AACd,YAAI,6BAAe,GAAG,QAAQ,GAAG;AAChC,YAAM,KAAK,WAAW,CAAC;AACvB,UAAI,CAAC,OAAO,IAAI,EAAE,GAAG;AACpB,eAAO,IAAI,IAAI,CAAC;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAEA,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,QAAI,SAAS,CAAC;AACd,YAAI,6BAAe,GAAG,QAAQ,GAAG;AAChC,YAAM,KAAK,WAAW,CAAC;AACvB,UAAI,CAAC,OAAO,IAAI,EAAE,GAAG;AACpB,eAAO,IAAI,IAAI,CAAC;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAGA,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,QAAI,SAAS,CAAC;AACd,QAAI,UAAU,IAAI,KAAK,SAAS,MAAM;AAEtC,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,UAAI,SAAS,CAAC;AACd,UAAI,UAAU,IAAI,KAAK,SAAS,MAAM;AACtC,YAAM,eAAe,gCAAgC,GAAG,GAAG,GAAG,CAAC;AAE/D,UAAI,iBAAiB,MAAM;AAC1B,cAAM,KAAK,WAAW,YAAY;AAClC,YAAI,CAAC,OAAO,IAAI,EAAE,GAAG;AACpB,iBAAO,IAAI,IAAI,YAAY;AAAA,QAC5B;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,MAAI,OAAO,SAAS,EAAG,QAAO;AAG9B,SAAO,eAAe,CAAC,GAAG,OAAO,OAAO,CAAC,CAAC;AAC3C;AAEA,SAAS,WAAW,OAAgB;AACnC,SAAO,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC;AAC7B;AAEA,SAAS,eAAe,QAA8B;AACrD,QAAM,IAAI,eAAI,QAAQ,MAAM;AAC5B,SAAO,OAAO,KAAK,CAAC,GAAG,MAAM,eAAI,MAAM,GAAG,CAAC,IAAI,eAAI,MAAM,GAAG,CAAC,CAAC;AAC/D;AAGO,SAAS,kBAAkB,GAAc,GAAc;AAC7D,MAAI,IAAa,IAAa,IAAa;AAC3C,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAI,GAAG,KAAK;AACzC,SAAK,EAAE,CAAC;AACR,SAAK,GAAG,IAAI,KAAK,CAAC;AAClB,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAI,GAAG,KAAK;AACzC,WAAK,EAAE,CAAC;AACR,WAAK,GAAG,IAAI,KAAK,CAAC;AAClB,UAAI,eAAe,IAAI,IAAI,IAAI,EAAE,EAAG,QAAO;AAAA,IAC5C;AAAA,EACD;AACA,SAAO;AACR;AAGO,SAAS,0BAA0B,SAAoB,UAAqB;AAClF,MAAI,GAAY,GAAY,GAAY;AACxC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAC/C,QAAI,QAAQ,CAAC;AACb,QAAI,SAAS,IAAI,KAAK,CAAC;AAEvB,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,IAAI,GAAG,KAAK;AAChD,UAAI,SAAS,IAAI,CAAC;AAClB,UAAI,SAAS,CAAC;AACd,UAAI,eAAe,GAAG,GAAG,GAAG,CAAC,EAAG,QAAO;AAAA,IACxC;AAAA,EACD;AACA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -111,14 +111,20 @@ function reorderToFront(moving, children, changes) {
111
111
  );
112
112
  }
113
113
  }
114
+ function getVerticesInPageSpace(editor, shape) {
115
+ const geo = editor.getShapeGeometry(shape);
116
+ const pageTransform = editor.getShapePageTransform(shape);
117
+ if (!geo || !pageTransform) return null;
118
+ return pageTransform.applyToPoints(geo.vertices);
119
+ }
114
120
  function getOverlapChecker(editor, moving) {
115
121
  const movingVertices = Array.from(moving).map((shape) => {
116
- const vertices = editor.getShapePageGeometry(shape).vertices;
122
+ const vertices = getVerticesInPageSpace(editor, shape);
117
123
  if (!vertices) return null;
118
124
  return { shape, vertices };
119
125
  }).filter(Boolean);
120
126
  const isOverlapping = (child) => {
121
- const vertices = editor.getShapePageGeometry(child).vertices;
127
+ const vertices = getVerticesInPageSpace(editor, child);
122
128
  if (!vertices) return false;
123
129
  return movingVertices.some((other) => {
124
130
  return (0, import_intersect.polygonsIntersect)(other.vertices, vertices);