@eturnity/eturnity_maths 8.46.2 → 9.7.0
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/package.json +1 -1
- package/src/geometry.js +59 -9
package/package.json
CHANGED
package/src/geometry.js
CHANGED
|
@@ -29,8 +29,19 @@ export function getPolylineLength(outline) {
|
|
|
29
29
|
)
|
|
30
30
|
}, 0)
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Gets the concave outlines of the selected panels.
|
|
34
|
+
* @param {Array} selectedPanels - Array of selected panels
|
|
35
|
+
* @param {Array} onePanelOutline - Outline of one panel
|
|
36
|
+
* @param {Function} customAdjacentFn - Optional callback (objA, objB) => boolean for additional adjacency checks (e.g., cross-grid)
|
|
37
|
+
* @returns {Object} Object with outlines and buckets
|
|
38
|
+
*/
|
|
39
|
+
export function getConcaveOutlines(
|
|
40
|
+
selectedPanels,
|
|
41
|
+
onePanelOutline,
|
|
42
|
+
customAdjacentFn = null
|
|
43
|
+
) {
|
|
44
|
+
let buckets = groupAdjacentObjects(selectedPanels, customAdjacentFn)
|
|
34
45
|
const outlines = []
|
|
35
46
|
for (let bucketIndex = 0; bucketIndex < buckets.length; bucketIndex++) {
|
|
36
47
|
outlines.push(
|
|
@@ -898,7 +909,13 @@ export function isClockWise(outline) {
|
|
|
898
909
|
}
|
|
899
910
|
return sum > 0
|
|
900
911
|
}
|
|
901
|
-
|
|
912
|
+
/**
|
|
913
|
+
* Groups objects into buckets of adjacent objects based on row_index and col_index.
|
|
914
|
+
* @param {Array} objects - Array of objects with row_index, col_index, and optionally moduleField.id and gridIndex
|
|
915
|
+
* @param {Function} customAdjacentFn - Optional callback (objA, objB) => boolean for additional adjacency checks (e.g., cross-grid)
|
|
916
|
+
* @returns {Array} Array of buckets, where each bucket is an array of indices into the original objects array
|
|
917
|
+
*/
|
|
918
|
+
export function groupAdjacentObjects(objects, customAdjacentFn = null) {
|
|
902
919
|
if (!objects || objects.length == 0) return []
|
|
903
920
|
// objects with 2D indexes
|
|
904
921
|
// Check if the objects form an adjacent group
|
|
@@ -906,6 +923,23 @@ export function groupAdjacentObjects(objects) {
|
|
|
906
923
|
let indexList = Array.from({ length: numberOfObjects }, (e, i) => i)
|
|
907
924
|
let buckets = []
|
|
908
925
|
let inBucket = 0
|
|
926
|
+
|
|
927
|
+
// Pre-compute custom adjacency pairs if callback provided
|
|
928
|
+
const customAdjacentPairs = new Map()
|
|
929
|
+
if (customAdjacentFn) {
|
|
930
|
+
for (let i = 0; i < numberOfObjects; i++) {
|
|
931
|
+
customAdjacentPairs.set(i, [])
|
|
932
|
+
}
|
|
933
|
+
for (let i = 0; i < numberOfObjects; i++) {
|
|
934
|
+
for (let j = i + 1; j < numberOfObjects; j++) {
|
|
935
|
+
if (customAdjacentFn(objects[i], objects[j])) {
|
|
936
|
+
customAdjacentPairs.get(i).push(j)
|
|
937
|
+
customAdjacentPairs.get(j).push(i)
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
909
943
|
while (inBucket < objects.length) {
|
|
910
944
|
let detatchedIndex = indexList.find((i) => !buckets.flat().includes(i))
|
|
911
945
|
if (detatchedIndex == null) break
|
|
@@ -916,24 +950,40 @@ export function groupAdjacentObjects(objects) {
|
|
|
916
950
|
if (visited.indexOf(currentObjectIndex) == -1) {
|
|
917
951
|
//if next queued index hasn't been visited, we mark it as visited and we collect all neighbourg to queue
|
|
918
952
|
visited.push(currentObjectIndex)
|
|
919
|
-
|
|
920
|
-
let
|
|
953
|
+
const currentObject = objects[currentObjectIndex]
|
|
954
|
+
let x = currentObject.row_index
|
|
955
|
+
let y = currentObject.col_index
|
|
956
|
+
const moduleFieldId = currentObject.moduleField?.id
|
|
957
|
+
const gridIndex = currentObject.gridIndex
|
|
958
|
+
const isSameGrid = (o) =>
|
|
959
|
+
o.moduleField?.id == moduleFieldId && o.gridIndex == gridIndex
|
|
960
|
+
|
|
961
|
+
// Same-grid neighbors (index-based)
|
|
921
962
|
const left = objects.findIndex(
|
|
922
|
-
(o) => o.row_index == x - 1 && o.col_index == y
|
|
963
|
+
(o) => o.row_index == x - 1 && o.col_index == y && isSameGrid(o)
|
|
923
964
|
)
|
|
924
965
|
const right = objects.findIndex(
|
|
925
|
-
(o) => o.row_index == x + 1 && o.col_index == y
|
|
966
|
+
(o) => o.row_index == x + 1 && o.col_index == y && isSameGrid(o)
|
|
926
967
|
)
|
|
927
968
|
const top = objects.findIndex(
|
|
928
|
-
(o) => o.row_index == x && o.col_index == y - 1
|
|
969
|
+
(o) => o.row_index == x && o.col_index == y - 1 && isSameGrid(o)
|
|
929
970
|
)
|
|
930
971
|
const bottom = objects.findIndex(
|
|
931
|
-
(o) => o.row_index == x && o.col_index == y + 1
|
|
972
|
+
(o) => o.row_index == x && o.col_index == y + 1 && isSameGrid(o)
|
|
932
973
|
)
|
|
933
974
|
if (left != -1 && visited.indexOf(left) == -1) queue.push(left)
|
|
934
975
|
if (right != -1 && visited.indexOf(right) == -1) queue.push(right)
|
|
935
976
|
if (top != -1 && visited.indexOf(top) == -1) queue.push(top)
|
|
936
977
|
if (bottom != -1 && visited.indexOf(bottom) == -1) queue.push(bottom)
|
|
978
|
+
|
|
979
|
+
// Custom adjacency (e.g., cross-grid)
|
|
980
|
+
if (customAdjacentFn) {
|
|
981
|
+
for (const neighborIndex of customAdjacentPairs.get(
|
|
982
|
+
currentObjectIndex
|
|
983
|
+
)) {
|
|
984
|
+
if (visited.indexOf(neighborIndex) == -1) queue.push(neighborIndex)
|
|
985
|
+
}
|
|
986
|
+
}
|
|
937
987
|
}
|
|
938
988
|
}
|
|
939
989
|
inBucket += visited.length
|