@immugio/three-math-extensions 0.2.31 → 0.2.33

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.
package/CHANGELOG.md CHANGED
@@ -7,7 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
9
9
 
10
- ## [0.2.31](https://github.com/Immugio/three-math-extensions/compare/0.2.30...0.2.31)
10
+ ## [0.2.33](https://github.com/Immugio/three-math-extensions/compare/0.2.32...0.2.33)
11
+
12
+ ### Commits
13
+
14
+ - Line2D.groupConnectedLines improve sort [`fa56c1e`](https://github.com/Immugio/three-math-extensions/commit/fa56c1e13b2b49f369034224985f31f069e3079f)
15
+
16
+ ## [0.2.32](https://github.com/Immugio/three-math-extensions/compare/0.2.31...0.2.32) - 2024-10-18
17
+
18
+ ### Commits
19
+
20
+ - Improve offsetPolyline to correctly handle open polylines [`4c5a003`](https://github.com/Immugio/three-math-extensions/commit/4c5a003e9d46fc1ef8a63ec765941232d2dda933)
21
+ - Line2D.groupConnectedLines sorts each group based on connection order [`16e22f9`](https://github.com/Immugio/three-math-extensions/commit/16e22f9adb7df290e36381b198d7f0381dfb1f5c)
22
+
23
+ ## [0.2.31](https://github.com/Immugio/three-math-extensions/compare/0.2.30...0.2.31) - 2024-09-17
11
24
 
12
25
  ### Commits
13
26
 
@@ -267,29 +280,48 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
267
280
 
268
281
  - Add Vec2 documentation [`f625e66`](https://github.com/Immugio/three-math-extensions/commit/f625e66b60ee0d90c5c788a80989f64013d60265)
269
282
 
270
- ## [0.0.11](https://github.com/Immugio/three-math-extensions/compare/0.0.6...0.0.11) - 2022-12-20
283
+ ## [0.0.11](https://github.com/Immugio/three-math-extensions/compare/0.0.10...0.0.11) - 2022-12-20
271
284
 
272
285
  ### Commits
273
286
 
287
+ - Improve API, minor bug fix, improve test coverage [`881a5f0`](https://github.com/Immugio/three-math-extensions/commit/881a5f096823f0d5fd90faa76cd602f076291bc5)
274
288
  - Add Line2D.extendToOrTrimAtIntersection [`ab82a36`](https://github.com/Immugio/three-math-extensions/commit/ab82a36db52b9ae83cf8bfb848362d295140d073)
275
289
  - Added "isNear" to Vec2 & Vec3 as a shorthand for distanceTo <= maxDistance [`a27cff8`](https://github.com/Immugio/three-math-extensions/commit/a27cff8421472f625ed240439b9e6a7d2c430db8)
290
+ - Add .npmignore [`f58329a`](https://github.com/Immugio/three-math-extensions/commit/f58329a86b96589bb574d6ebed37d4cc4474663a)
276
291
  - Add Vec2.moveTowards [`b46ba12`](https://github.com/Immugio/three-math-extensions/commit/b46ba1286f9924cd9bfecfb37200664202e964ba)
277
292
  - Add Line2D.extendToOrTrimAtIntersection [`b22aa12`](https://github.com/Immugio/three-math-extensions/commit/b22aa120b5eb02562cebc4573374ebb61e2dba14)
293
+ - Correct change log version [`c6244bf`](https://github.com/Immugio/three-math-extensions/commit/c6244bf1488ad21bcc5589d1dff62c41d8182d48)
294
+
295
+ ## [0.0.10](https://github.com/Immugio/three-math-extensions/compare/0.0.9...0.0.10) - 2022-11-21
296
+
297
+ ### Commits
298
+
299
+ - Release 0.0.4 - tag pattern 6 [`c1c5454`](https://github.com/Immugio/three-math-extensions/commit/c1c54541ed400e1ad49bf42fe8926cd5293efefd)
300
+
301
+ ## [0.0.9](https://github.com/Immugio/three-math-extensions/compare/0.0.8...0.0.9) - 2022-11-21
302
+
303
+ ### Commits
304
+
305
+ - Release 0.0.4 - tag pattern 5 [`5245eed`](https://github.com/Immugio/three-math-extensions/commit/5245eed60195103e989c0fadf9bd642f39ef4589)
306
+
307
+ ## [0.0.8](https://github.com/Immugio/three-math-extensions/compare/0.0.7...0.0.8) - 2022-11-21
308
+
309
+ ### Commits
310
+
311
+ - Release 0.0.4 - tag pattern 4 [`ab9ad4e`](https://github.com/Immugio/three-math-extensions/commit/ab9ad4e49477a991482ed6d4d3a3ca4687a70b44)
312
+
313
+ ## [0.0.7](https://github.com/Immugio/three-math-extensions/compare/0.0.6...0.0.7) - 2022-11-21
278
314
 
279
315
  ## [0.0.6](https://github.com/Immugio/three-math-extensions/compare/0.0.5...0.0.6) - 2022-11-24
280
316
 
281
- ## 0.0.5 - 2023-09-01
317
+ ## [0.0.5](https://github.com/Immugio/three-math-extensions/compare/0.0.4...0.0.5) - 2023-09-01
282
318
 
283
319
  ### Commits
284
320
 
285
- - Automatic publish with change log [`a70c99d`](https://github.com/Immugio/three-math-extensions/commit/a70c99d0d42e60411ce01bcdb8dd4f3f489bb949)
286
- - Switch to npm [`ed47a17`](https://github.com/Immugio/three-math-extensions/commit/ed47a1787522db3bde5a2112bfd02480fe2edc54)
287
- - Initial commit [`3d1bf9e`](https://github.com/Immugio/three-math-extensions/commit/3d1bf9ef015570830007c9be99140c8c8d760d7f)
288
321
  - Generate documentation using TSDoc [`304c3a8`](https://github.com/Immugio/three-math-extensions/commit/304c3a84b5dcc49183db57083f550d134ae641b2)
289
322
  - Add eslint [`98e4912`](https://github.com/Immugio/three-math-extensions/commit/98e4912d637b42ba80e2f3267638b43296113019)
290
323
  - Update jest packages [`af23b4f`](https://github.com/Immugio/three-math-extensions/commit/af23b4f08154bba3407f05b773865215e7e1cba8)
291
324
  - Add Rectangle, update Polygon [`58ee875`](https://github.com/Immugio/three-math-extensions/commit/58ee87539af8f9ade186e5250cba9e01926da514)
292
- - Add Line2D [`9a1dd0f`](https://github.com/Immugio/three-math-extensions/commit/9a1dd0f58352b7b25828693c688aa4770e95c174)
293
325
  - Add isPointInPolygon [`a59eb4b`](https://github.com/Immugio/three-math-extensions/commit/a59eb4be026f17a3106070ae626a0588cd4f4411)
294
326
  - Improve Line2D.closestPointToPoint, add Vec2.signedAngle [`151f214`](https://github.com/Immugio/three-math-extensions/commit/151f21462e0358057ad8e9d75d5782563a1061f6)
295
327
  - Improve documentation [`d0fcb51`](https://github.com/Immugio/three-math-extensions/commit/d0fcb5132f127b4382ac5f7291575a061b8ec121)
@@ -303,7 +335,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
303
335
  - Add Vec2.signedAngle [`863c8f2`](https://github.com/Immugio/three-math-extensions/commit/863c8f27f11288cbda535e21bb688206259269ed)
304
336
  - Add intersect method to Line3D [`6fe47de`](https://github.com/Immugio/three-math-extensions/commit/6fe47de7caaa1807b47a4363e551510c463757d7)
305
337
  - Add Line2D.extendToOrTrimAtIntersection [`ab82a36`](https://github.com/Immugio/three-math-extensions/commit/ab82a36db52b9ae83cf8bfb848362d295140d073)
306
- - Readme, npm info [`dda4a28`](https://github.com/Immugio/three-math-extensions/commit/dda4a282a71a00308dcae858ffe53d67d4185be8)
307
338
  - Add Vec2.fromPoints to accept multiple points [`a261402`](https://github.com/Immugio/three-math-extensions/commit/a2614027cf5fb8263189b48f7e0bb9a23a552c15)
308
339
  - Improve documentation for Vec2 and Vec3 [`6a2373d`](https://github.com/Immugio/three-math-extensions/commit/6a2373d8b6754a87720dcaea5d98336bfa7bc5b5)
309
340
  - Add Vec2.parallelTo [`989874d`](https://github.com/Immugio/three-math-extensions/commit/989874dcfe122d3ee84d8d56d79cb88e4e441736)
@@ -315,11 +346,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
315
346
  - Add .npmignore [`f58329a`](https://github.com/Immugio/three-math-extensions/commit/f58329a86b96589bb574d6ebed37d4cc4474663a)
316
347
  - Polygon from bounding size [`eae6701`](https://github.com/Immugio/three-math-extensions/commit/eae67012f57f426f8b5259b765000447ce06d608)
317
348
  - Add Vec2 documentation [`f625e66`](https://github.com/Immugio/three-math-extensions/commit/f625e66b60ee0d90c5c788a80989f64013d60265)
318
- - Run tests in CI on commit [`e3f77ca`](https://github.com/Immugio/three-math-extensions/commit/e3f77ca76e25f4d99eef0130e5779b5e7c5aec6b)
319
349
  - Clean up documentation [`70c8d5e`](https://github.com/Immugio/three-math-extensions/commit/70c8d5efe8b7095d7a03af637df3af5d46615293)
320
- - Remove babel.config.js [`c9a1e16`](https://github.com/Immugio/three-math-extensions/commit/c9a1e1607cffec8a3d74adcca644320a79ca4c43)
321
350
  - Line2D and Line3D to return this instead of specific type [`761ef6a`](https://github.com/Immugio/three-math-extensions/commit/761ef6a9d8cc4e35120b666576794e521aa3b991)
322
- - Initial changelog [`6c98aa6`](https://github.com/Immugio/three-math-extensions/commit/6c98aa6ad631cf5e73d32dd76276f99b3ba5089f)
323
351
  - Line2D.in3DSpace added [`a6ce0ec`](https://github.com/Immugio/three-math-extensions/commit/a6ce0ecb67f5c7b2a75fcc283c28af626153a4af)
324
352
  - Line3D.connectsTo added [`6d2cfa0`](https://github.com/Immugio/three-math-extensions/commit/6d2cfa0f5335c665f325a694a32c57b574ec326d)
325
353
  - Line2D.hasIntersectionWithAngle to support optional tolerance [`b313bbe`](https://github.com/Immugio/three-math-extensions/commit/b313bbe118d435d53750deefd9a9e29ba6ec5c71)
@@ -328,21 +356,36 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
328
356
  - Use Vec2 instead of Vector2 [`7e6a6ea`](https://github.com/Immugio/three-math-extensions/commit/7e6a6ea272f4441ef4bc78b3fdec23fc783fa1db)
329
357
  - Add release instructions into README.md [`03653b1`](https://github.com/Immugio/three-math-extensions/commit/03653b1ffa55be606d3f9cd588e28a6084462c2e)
330
358
  - Documentation improvements [`160db8b`](https://github.com/Immugio/three-math-extensions/commit/160db8ba6d6e5eb63a4e91ed9c40efd6fa70181a)
331
- - Release 0.0.4 [`bdac840`](https://github.com/Immugio/three-math-extensions/commit/bdac840f33261a3f39ef33bc05c80772169cfe87)
332
359
  - Update release instructions [`5b41a2e`](https://github.com/Immugio/three-math-extensions/commit/5b41a2ed7e15450dbb6088a7f7ed0031a013badc)
333
- - Add test badge [`37c62e8`](https://github.com/Immugio/three-math-extensions/commit/37c62e809bdcdfc63f7fe135469fd131f190f950)
334
360
  - Add Polygon to exports [`ed66775`](https://github.com/Immugio/three-math-extensions/commit/ed66775c33e961835b23843222b822cfd9c16b1d)
335
361
  - Vec2.fromPoint and Vec3.fromPoint should accept null [`4b871af`](https://github.com/Immugio/three-math-extensions/commit/4b871af297bdcbe8584f1e2b99d602247b77687c)
336
362
  - Documentation improvements [`2f3e676`](https://github.com/Immugio/three-math-extensions/commit/2f3e6768b3b0139b60688fc151a4084f15566f8d)
337
- - Edit publish script condition [`dc77d89`](https://github.com/Immugio/three-math-extensions/commit/dc77d8978d87daab8732d6429ad1b01ba0ca6f97)
338
- - CI to use node version 16 [`dc42650`](https://github.com/Immugio/three-math-extensions/commit/dc426508939de922cc0316b7652bbd09aeed4610)
339
- - Action rename [`26a1f01`](https://github.com/Immugio/three-math-extensions/commit/26a1f014827faab2c02d30ca8ed18dac8f9ff8af)
340
363
  - Documentation update [`d5c7a07`](https://github.com/Immugio/three-math-extensions/commit/d5c7a0765f6097f5d3a3be01967d4059f19682fb)
341
364
  - Fix peer dependency version [`00dd116`](https://github.com/Immugio/three-math-extensions/commit/00dd1169f578d5769207031fa625f29c96a38c31)
342
365
  - Add Line2D.extendToOrTrimAtIntersection [`b22aa12`](https://github.com/Immugio/three-math-extensions/commit/b22aa120b5eb02562cebc4573374ebb61e2dba14)
343
366
  - Correct change log version [`c6244bf`](https://github.com/Immugio/three-math-extensions/commit/c6244bf1488ad21bcc5589d1dff62c41d8182d48)
344
367
  - Release 0.0.4 - tag pattern 6 [`c1c5454`](https://github.com/Immugio/three-math-extensions/commit/c1c54541ed400e1ad49bf42fe8926cd5293efefd)
345
368
  - Release 0.0.4 - tag pattern 5 [`5245eed`](https://github.com/Immugio/three-math-extensions/commit/5245eed60195103e989c0fadf9bd642f39ef4589)
369
+ - Excluded files from build [`ec70614`](https://github.com/Immugio/three-math-extensions/commit/ec70614bc7df7a98f854c7a6693365118e04faf7)
370
+ - Revert npm ignore [`590b26a`](https://github.com/Immugio/three-math-extensions/commit/590b26a9e57fc41466b51e711f3f5c648e2d56ed)
371
+
372
+ ## 0.0.4 - 2022-11-21
373
+
374
+ ### Commits
375
+
376
+ - Automatic publish with change log [`a70c99d`](https://github.com/Immugio/three-math-extensions/commit/a70c99d0d42e60411ce01bcdb8dd4f3f489bb949)
377
+ - Switch to npm [`ed47a17`](https://github.com/Immugio/three-math-extensions/commit/ed47a1787522db3bde5a2112bfd02480fe2edc54)
378
+ - Initial commit [`3d1bf9e`](https://github.com/Immugio/three-math-extensions/commit/3d1bf9ef015570830007c9be99140c8c8d760d7f)
379
+ - Add Line2D [`9a1dd0f`](https://github.com/Immugio/three-math-extensions/commit/9a1dd0f58352b7b25828693c688aa4770e95c174)
380
+ - Readme, npm info [`dda4a28`](https://github.com/Immugio/three-math-extensions/commit/dda4a282a71a00308dcae858ffe53d67d4185be8)
381
+ - Run tests in CI on commit [`e3f77ca`](https://github.com/Immugio/three-math-extensions/commit/e3f77ca76e25f4d99eef0130e5779b5e7c5aec6b)
382
+ - Remove babel.config.js [`c9a1e16`](https://github.com/Immugio/three-math-extensions/commit/c9a1e1607cffec8a3d74adcca644320a79ca4c43)
383
+ - Initial changelog [`6c98aa6`](https://github.com/Immugio/three-math-extensions/commit/6c98aa6ad631cf5e73d32dd76276f99b3ba5089f)
384
+ - Release 0.0.4 [`bdac840`](https://github.com/Immugio/three-math-extensions/commit/bdac840f33261a3f39ef33bc05c80772169cfe87)
385
+ - Add test badge [`37c62e8`](https://github.com/Immugio/three-math-extensions/commit/37c62e809bdcdfc63f7fe135469fd131f190f950)
386
+ - Edit publish script condition [`dc77d89`](https://github.com/Immugio/three-math-extensions/commit/dc77d8978d87daab8732d6429ad1b01ba0ca6f97)
387
+ - CI to use node version 16 [`dc42650`](https://github.com/Immugio/three-math-extensions/commit/dc426508939de922cc0316b7652bbd09aeed4610)
388
+ - Action rename [`26a1f01`](https://github.com/Immugio/three-math-extensions/commit/26a1f014827faab2c02d30ca8ed18dac8f9ff8af)
346
389
  - Release 0.0.4 - tag pattern 4 [`ab9ad4e`](https://github.com/Immugio/three-math-extensions/commit/ab9ad4e49477a991482ed6d4d3a3ca4687a70b44)
347
390
  - Release 0.0.4 - tag pattern 3 [`d7d4c8f`](https://github.com/Immugio/three-math-extensions/commit/d7d4c8f546e6550868ddd06a5213fdec6c68bcd2)
348
391
  - Release 0.0.4 - tag pattern 2 [`0dcf801`](https://github.com/Immugio/three-math-extensions/commit/0dcf80190bd67a3ca93d45131a403201ab39e00f)
@@ -350,6 +393,4 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
350
393
  - Release 0.0.5 [`c80d6bd`](https://github.com/Immugio/three-math-extensions/commit/c80d6bd12c25ddad0f67610cdf5c804d5759f084)
351
394
  - Status badge update [`370843e`](https://github.com/Immugio/three-math-extensions/commit/370843ed0a28b024761555572b7d51ccbdb4b77d)
352
395
  - Run tests in CI on commit [`aee8c55`](https://github.com/Immugio/three-math-extensions/commit/aee8c556ae1cab9025dbe0984dd17278fe6275a1)
353
- - Excluded files from build [`ec70614`](https://github.com/Immugio/three-math-extensions/commit/ec70614bc7df7a98f854c7a6693365118e04faf7)
354
- - Revert npm ignore [`590b26a`](https://github.com/Immugio/three-math-extensions/commit/590b26a9e57fc41466b51e711f3f5c648e2d56ed)
355
396
  - Add Line2D to index [`a5fb6bd`](https://github.com/Immugio/three-math-extensions/commit/a5fb6bdeee5d9f07f325bfffc31ef96f0ce167d1)
package/cjs/Line2D.js CHANGED
@@ -6,6 +6,7 @@ const Vec2_1 = require("./Vec2");
6
6
  const MathConstants_1 = require("./MathConstants");
7
7
  const Line3D_1 = require("./Line3D");
8
8
  const directions2d_1 = require("./directions2d");
9
+ const sortLinesByConnections_1 = require("./sortLinesByConnections");
9
10
  const _startP = /*@__PURE__*/ new Vec2_1.Vec2();
10
11
  const _startEnd = /*@__PURE__*/ new Vec2_1.Vec2();
11
12
  class Line2D {
@@ -658,7 +659,7 @@ class Line2D {
658
659
  * Accepts an array of Line2D and groups them into arrays of connected lines
659
660
  * @param lines Lines to be grouped
660
661
  * @param tolerance Tolerance for considering lines as connected
661
- * @param breakpoints
662
+ * @param breakpoints Endpoints on breakpoints are not considered as connected
662
663
  */
663
664
  static groupConnectedLines(lines, tolerance = 0, breakpoints = []) {
664
665
  const visited = new Set();
@@ -682,7 +683,7 @@ class Line2D {
682
683
  if (!visited.has(line)) {
683
684
  const group = [];
684
685
  dfs(line, group);
685
- connectedLines.push(group);
686
+ connectedLines.push((0, sortLinesByConnections_1.sortLinesByConnections)(group, 1));
686
687
  }
687
688
  });
688
689
  return connectedLines;
package/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.extendOrTrimPolylinesAtIntersections = exports.offsetPolyline = exports.polygonPerimeter = exports.isContinuousClosedShape = exports.directions2d = exports.directions = exports.isPointInPolygon = exports.HalfPI = exports.TwoPI = exports.normalizeAngleRadians = exports.normalizeAngleDegrees = exports.Rectangle = exports.BoundingBox = exports.Polygon = exports.Size2 = exports.Line3D = exports.Line2D = exports.Vec3 = exports.Vec2 = void 0;
3
+ exports.sortLinesByConnections = exports.extendOrTrimPolylinesAtIntersections = exports.offsetPolyline = exports.polygonPerimeter = exports.isContinuousClosedShape = exports.directions2d = exports.directions = exports.isPointInPolygon = exports.HalfPI = exports.TwoPI = exports.normalizeAngleRadians = exports.normalizeAngleDegrees = exports.Rectangle = exports.BoundingBox = exports.Polygon = exports.Size2 = exports.Line3D = exports.Line2D = exports.Vec3 = exports.Vec2 = void 0;
4
4
  var Vec2_1 = require("./Vec2");
5
5
  Object.defineProperty(exports, "Vec2", { enumerable: true, get: function () { return Vec2_1.Vec2; } });
6
6
  var Vec3_1 = require("./Vec3");
@@ -38,3 +38,5 @@ var offsetPolyline_1 = require("./offsetPolyline");
38
38
  Object.defineProperty(exports, "offsetPolyline", { enumerable: true, get: function () { return offsetPolyline_1.offsetPolyline; } });
39
39
  var extendOrTrimPolylinesAtIntersections_1 = require("./extendOrTrimPolylinesAtIntersections");
40
40
  Object.defineProperty(exports, "extendOrTrimPolylinesAtIntersections", { enumerable: true, get: function () { return extendOrTrimPolylinesAtIntersections_1.extendOrTrimPolylinesAtIntersections; } });
41
+ var sortLinesByConnections_1 = require("./sortLinesByConnections");
42
+ Object.defineProperty(exports, "sortLinesByConnections", { enumerable: true, get: function () { return sortLinesByConnections_1.sortLinesByConnections; } });
@@ -1,16 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.offsetPolyline = void 0;
4
- function offsetPolyline(lines, offset) {
4
+ function offsetPolyline(lines, offset, tolerance = 0) {
5
+ const isClosed = lines[0].start.isNear(lines.at(-1).end, tolerance);
5
6
  for (let i = 0; i < lines.length; i++) {
7
+ const isFirst = i === 0;
8
+ const isLast = i === lines.length - 1;
6
9
  const line = lines[i];
7
10
  line.translateLeft(offset);
8
11
  const next = lines[(i + 1) % lines.length];
9
- line.extendToOrTrimAtIntersection(next);
10
- next.extendToOrTrimAtIntersection(line);
12
+ if (!isLast || isClosed) {
13
+ line.extendToOrTrimAtIntersection(next);
14
+ next.extendToOrTrimAtIntersection(line);
15
+ }
11
16
  const previous = lines[(i + lines.length - 1) % lines.length];
12
- line.extendToOrTrimAtIntersection(previous);
13
- previous.extendToOrTrimAtIntersection(line);
17
+ if (!isFirst || isClosed) {
18
+ line.extendToOrTrimAtIntersection(previous);
19
+ previous.extendToOrTrimAtIntersection(line);
20
+ }
14
21
  }
15
22
  return lines;
16
23
  }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortLinesByConnections = void 0;
4
+ /**
5
+ * Sort connected lines by their connections.
6
+ * When the polygon is open, the first line must be the line that has no connection at the start.
7
+ * When the polygon is open, the last line must be the line that has no connection at the end.
8
+ * If the lines form a closed polygon, any line can be the first line.
9
+ */
10
+ function sortLinesByConnections(lines, tolerance = 0) {
11
+ const remainingLines = [...lines];
12
+ const startLineIndex = findStartLineIndex(remainingLines, tolerance);
13
+ const sortedLines = [remainingLines.splice(startLineIndex, 1)[0]];
14
+ while (remainingLines.length > 0) {
15
+ const lastLine = sortedLines[sortedLines.length - 1];
16
+ const nextLineIndex = remainingLines.findIndex(line => lastLine.end.isNear(line.start, tolerance));
17
+ if (nextLineIndex === -1) {
18
+ console.log("Lines do not form a connected path");
19
+ return [...sortedLines, ...remainingLines];
20
+ }
21
+ sortedLines.push(remainingLines.splice(nextLineIndex, 1)[0]);
22
+ }
23
+ return sortedLines;
24
+ }
25
+ exports.sortLinesByConnections = sortLinesByConnections;
26
+ /**
27
+ * Find the index of the starting line.
28
+ * A starting line is defined as a line that has no other line connected to its start.
29
+ * If such a line does not exist, it means that the lines form a closed polygon, return 0.
30
+ * @param lines
31
+ * @param tolerance
32
+ */
33
+ function findStartLineIndex(lines, tolerance) {
34
+ for (let i = 0; i < lines.length; i++) {
35
+ const startLine = lines[i];
36
+ const isStartLine = !lines.some(line => line.end.isNear(startLine.start, tolerance));
37
+ if (isStartLine) {
38
+ return i;
39
+ }
40
+ }
41
+ return 0;
42
+ }
package/esm/Line2D.js CHANGED
@@ -3,6 +3,7 @@ import { Vec2 } from "./Vec2";
3
3
  import { TwoPI } from "./MathConstants";
4
4
  import { Line3D } from "./Line3D";
5
5
  import { directions2d } from "./directions2d";
6
+ import { sortLinesByConnections } from "./sortLinesByConnections";
6
7
  const _startP = /*@__PURE__*/ new Vec2();
7
8
  const _startEnd = /*@__PURE__*/ new Vec2();
8
9
  export class Line2D {
@@ -655,7 +656,7 @@ export class Line2D {
655
656
  * Accepts an array of Line2D and groups them into arrays of connected lines
656
657
  * @param lines Lines to be grouped
657
658
  * @param tolerance Tolerance for considering lines as connected
658
- * @param breakpoints
659
+ * @param breakpoints Endpoints on breakpoints are not considered as connected
659
660
  */
660
661
  static groupConnectedLines(lines, tolerance = 0, breakpoints = []) {
661
662
  const visited = new Set();
@@ -679,7 +680,7 @@ export class Line2D {
679
680
  if (!visited.has(line)) {
680
681
  const group = [];
681
682
  dfs(line, group);
682
- connectedLines.push(group);
683
+ connectedLines.push(sortLinesByConnections(group, 1));
683
684
  }
684
685
  });
685
686
  return connectedLines;
package/esm/index.js CHANGED
@@ -16,3 +16,4 @@ export { isContinuousClosedShape } from "./isContinuousClosedShape";
16
16
  export { polygonPerimeter } from "./polygonPerimeter";
17
17
  export { offsetPolyline } from "./offsetPolyline";
18
18
  export { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
19
+ export { sortLinesByConnections } from "./sortLinesByConnections";
@@ -1,13 +1,20 @@
1
- export function offsetPolyline(lines, offset) {
1
+ export function offsetPolyline(lines, offset, tolerance = 0) {
2
+ const isClosed = lines[0].start.isNear(lines.at(-1).end, tolerance);
2
3
  for (let i = 0; i < lines.length; i++) {
4
+ const isFirst = i === 0;
5
+ const isLast = i === lines.length - 1;
3
6
  const line = lines[i];
4
7
  line.translateLeft(offset);
5
8
  const next = lines[(i + 1) % lines.length];
6
- line.extendToOrTrimAtIntersection(next);
7
- next.extendToOrTrimAtIntersection(line);
9
+ if (!isLast || isClosed) {
10
+ line.extendToOrTrimAtIntersection(next);
11
+ next.extendToOrTrimAtIntersection(line);
12
+ }
8
13
  const previous = lines[(i + lines.length - 1) % lines.length];
9
- line.extendToOrTrimAtIntersection(previous);
10
- previous.extendToOrTrimAtIntersection(line);
14
+ if (!isFirst || isClosed) {
15
+ line.extendToOrTrimAtIntersection(previous);
16
+ previous.extendToOrTrimAtIntersection(line);
17
+ }
11
18
  }
12
19
  return lines;
13
20
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Sort connected lines by their connections.
3
+ * When the polygon is open, the first line must be the line that has no connection at the start.
4
+ * When the polygon is open, the last line must be the line that has no connection at the end.
5
+ * If the lines form a closed polygon, any line can be the first line.
6
+ */
7
+ export function sortLinesByConnections(lines, tolerance = 0) {
8
+ const remainingLines = [...lines];
9
+ const startLineIndex = findStartLineIndex(remainingLines, tolerance);
10
+ const sortedLines = [remainingLines.splice(startLineIndex, 1)[0]];
11
+ while (remainingLines.length > 0) {
12
+ const lastLine = sortedLines[sortedLines.length - 1];
13
+ const nextLineIndex = remainingLines.findIndex(line => lastLine.end.isNear(line.start, tolerance));
14
+ if (nextLineIndex === -1) {
15
+ console.log("Lines do not form a connected path");
16
+ return [...sortedLines, ...remainingLines];
17
+ }
18
+ sortedLines.push(remainingLines.splice(nextLineIndex, 1)[0]);
19
+ }
20
+ return sortedLines;
21
+ }
22
+ /**
23
+ * Find the index of the starting line.
24
+ * A starting line is defined as a line that has no other line connected to its start.
25
+ * If such a line does not exist, it means that the lines form a closed polygon, return 0.
26
+ * @param lines
27
+ * @param tolerance
28
+ */
29
+ function findStartLineIndex(lines, tolerance) {
30
+ for (let i = 0; i < lines.length; i++) {
31
+ const startLine = lines[i];
32
+ const isStartLine = !lines.some(line => line.end.isNear(startLine.start, tolerance));
33
+ if (isStartLine) {
34
+ return i;
35
+ }
36
+ }
37
+ return 0;
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immugio/three-math-extensions",
3
- "version": "0.2.31",
3
+ "version": "0.2.33",
4
4
  "description": "Set of utilities for 2d and 3d line math built on top of three.js",
5
5
  "author": "Jan Mikeska <janmikeska@gmail.com>",
6
6
  "license": "ISC",
package/src/Line2D.ts CHANGED
@@ -4,6 +4,7 @@ import { Vec2 } from "./Vec2";
4
4
  import { TwoPI } from "./MathConstants";
5
5
  import { Line3D } from "./Line3D";
6
6
  import { directions2d } from "./directions2d";
7
+ import { sortLinesByConnections } from "./sortLinesByConnections";
7
8
 
8
9
  const _startP = /*@__PURE__*/ new Vec2();
9
10
  const _startEnd = /*@__PURE__*/ new Vec2();
@@ -776,7 +777,7 @@ export class Line2D {
776
777
  * Accepts an array of Line2D and groups them into arrays of connected lines
777
778
  * @param lines Lines to be grouped
778
779
  * @param tolerance Tolerance for considering lines as connected
779
- * @param breakpoints
780
+ * @param breakpoints Endpoints on breakpoints are not considered as connected
780
781
  */
781
782
  public static groupConnectedLines(lines: Line2D[], tolerance: number = 0, breakpoints: Vec2[] = []): Line2D[][] {
782
783
  const visited: Set<Line2D> = new Set();
@@ -790,9 +791,7 @@ export class Line2D {
790
791
 
791
792
  lines.forEach((neighbor) => {
792
793
  if (!visited.has(neighbor)) {
793
- if (
794
- line.connectsTo(neighbor, tolerance, breakpoints)
795
- ) {
794
+ if (line.connectsTo(neighbor, tolerance, breakpoints)) {
796
795
  dfs(neighbor, group);
797
796
  }
798
797
  }
@@ -805,7 +804,7 @@ export class Line2D {
805
804
  if (!visited.has(line)) {
806
805
  const group: Line2D[] = [];
807
806
  dfs(line, group);
808
- connectedLines.push(group);
807
+ connectedLines.push(sortLinesByConnections(group, 1));
809
808
  }
810
809
  });
811
810
 
package/src/index.ts CHANGED
@@ -17,4 +17,5 @@ export { directions2d } from "./directions2d";
17
17
  export { isContinuousClosedShape } from "./isContinuousClosedShape";
18
18
  export { polygonPerimeter } from "./polygonPerimeter";
19
19
  export { offsetPolyline } from "./offsetPolyline";
20
- export { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
20
+ export { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
21
+ export { sortLinesByConnections } from "./sortLinesByConnections";
@@ -1,17 +1,26 @@
1
1
  import { Line2D } from "./Line2D";
2
2
 
3
- export function offsetPolyline(lines: Line2D[], offset: number): Line2D[] {
4
- for (let i = 0; i < lines.length; i++){
3
+ export function offsetPolyline(lines: Line2D[], offset: number, tolerance: number = 0): Line2D[] {
4
+ const isClosed = lines[0].start.isNear(lines.at(-1).end, tolerance);
5
+
6
+ for (let i = 0; i < lines.length; i++) {
7
+ const isFirst = i === 0;
8
+ const isLast = i === lines.length - 1;
9
+
5
10
  const line = lines[i];
6
11
  line.translateLeft(offset);
7
12
 
8
13
  const next = lines[(i + 1) % lines.length];
9
- line.extendToOrTrimAtIntersection(next);
10
- next.extendToOrTrimAtIntersection(line);
14
+ if (!isLast || isClosed) {
15
+ line.extendToOrTrimAtIntersection(next);
16
+ next.extendToOrTrimAtIntersection(line);
17
+ }
11
18
 
12
19
  const previous = lines[(i + lines.length - 1) % lines.length];
13
- line.extendToOrTrimAtIntersection(previous);
14
- previous.extendToOrTrimAtIntersection(line);
20
+ if (!isFirst || isClosed) {
21
+ line.extendToOrTrimAtIntersection(previous);
22
+ previous.extendToOrTrimAtIntersection(line);
23
+ }
15
24
  }
16
25
 
17
26
  return lines;
@@ -0,0 +1,46 @@
1
+ import { Line2D } from "./Line2D";
2
+
3
+ /**
4
+ * Sort connected lines by their connections.
5
+ * When the polygon is open, the first line must be the line that has no connection at the start.
6
+ * When the polygon is open, the last line must be the line that has no connection at the end.
7
+ * If the lines form a closed polygon, any line can be the first line.
8
+ */
9
+ export function sortLinesByConnections(lines: Line2D[], tolerance: number = 0): Line2D[] {
10
+ const remainingLines = [...lines];
11
+ const startLineIndex = findStartLineIndex(remainingLines, tolerance);
12
+
13
+ const sortedLines: Line2D[] = [remainingLines.splice(startLineIndex, 1)[0]];
14
+
15
+ while (remainingLines.length > 0) {
16
+ const lastLine = sortedLines[sortedLines.length - 1];
17
+ const nextLineIndex = remainingLines.findIndex(line => lastLine.end.isNear(line.start, tolerance));
18
+
19
+ if (nextLineIndex === -1) {
20
+ console.log("Lines do not form a connected path");
21
+ return [...sortedLines, ...remainingLines];
22
+ }
23
+
24
+ sortedLines.push(remainingLines.splice(nextLineIndex, 1)[0]);
25
+ }
26
+
27
+ return sortedLines;
28
+ }
29
+
30
+ /**
31
+ * Find the index of the starting line.
32
+ * A starting line is defined as a line that has no other line connected to its start.
33
+ * If such a line does not exist, it means that the lines form a closed polygon, return 0.
34
+ * @param lines
35
+ * @param tolerance
36
+ */
37
+ function findStartLineIndex(lines: Line2D[], tolerance: number): number {
38
+ for (let i = 0; i < lines.length; i++) {
39
+ const startLine = lines[i];
40
+ const isStartLine = !lines.some(line => line.end.isNear(startLine.start, tolerance));
41
+ if (isStartLine) {
42
+ return i;
43
+ }
44
+ }
45
+ return 0;
46
+ }
package/types/Line2D.d.ts CHANGED
@@ -251,7 +251,7 @@ export declare class Line2D {
251
251
  * Accepts an array of Line2D and groups them into arrays of connected lines
252
252
  * @param lines Lines to be grouped
253
253
  * @param tolerance Tolerance for considering lines as connected
254
- * @param breakpoints
254
+ * @param breakpoints Endpoints on breakpoints are not considered as connected
255
255
  */
256
256
  static groupConnectedLines(lines: Line2D[], tolerance?: number, breakpoints?: Vec2[]): Line2D[][];
257
257
  /**
package/types/index.d.ts CHANGED
@@ -18,3 +18,4 @@ export { isContinuousClosedShape } from "./isContinuousClosedShape";
18
18
  export { polygonPerimeter } from "./polygonPerimeter";
19
19
  export { offsetPolyline } from "./offsetPolyline";
20
20
  export { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
21
+ export { sortLinesByConnections } from "./sortLinesByConnections";
@@ -1,2 +1,2 @@
1
1
  import { Line2D } from "./Line2D";
2
- export declare function offsetPolyline(lines: Line2D[], offset: number): Line2D[];
2
+ export declare function offsetPolyline(lines: Line2D[], offset: number, tolerance?: number): Line2D[];
@@ -0,0 +1,8 @@
1
+ import { Line2D } from "./Line2D";
2
+ /**
3
+ * Sort connected lines by their connections.
4
+ * When the polygon is open, the first line must be the line that has no connection at the start.
5
+ * When the polygon is open, the last line must be the line that has no connection at the end.
6
+ * If the lines form a closed polygon, any line can be the first line.
7
+ */
8
+ export declare function sortLinesByConnections(lines: Line2D[], tolerance?: number): Line2D[];