@eturnity/eturnity_maths 7.48.2 → 7.51.1
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/SHPSolver.js +342 -0
- package/src/geometry.js +26 -13
- package/src/index.js +3 -0
- package/src/intersectionPolygon.js +11 -0
- package/src/objects/Polygon.js +11 -7
- package/src/objects/hydrate.js +4 -2
- package/src/panelFunctions.js +51 -0
- package/src/stringPatchMatching.js +140 -0
- package/src/tests/SHPSolver/SHPSolver.spec.js +71 -0
- package/src/tests/SHPSolver/SHPSolverDebugCase.spec.js +26 -0
- package/src/tests/SHPSolver/scenarios/index.js +17 -0
- package/src/tests/SHPSolver/scenarios/scenario_1.json +58 -0
- package/src/tests/SHPSolver/scenarios/scenario_1_row.json +159 -0
- package/src/tests/SHPSolver/scenarios/scenario_1b.json +35 -0
- package/src/tests/SHPSolver/scenarios/scenario_1b_row.json +51 -0
- package/src/tests/SHPSolver/scenarios/scenario_2_row.json +175 -0
- package/src/tests/SHPSolver/scenarios/scenario_3.json +207 -0
- package/src/tests/SHPSolver/scenarios/scenario_3_simplify.json +151 -0
- package/src/tests/SHPSolver/scenarios/scenario_4.json +198 -0
- package/src/tests/panelFunctions/arePanelsAdjacent.spec.js +68 -0
- package/src/tests/panelFunctions/dividePanelsIntoAdjacentPatches.spec.js +59 -0
- package/src/tests/panelFunctions/stringPatchMatching.spec.js +72 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export function solveStringPatchMatching(stringList, patchList) {
|
|
2
|
+
// Problem Setup
|
|
3
|
+
const n = patchList.length // Number of rows
|
|
4
|
+
const m = stringList.length // Number of columns
|
|
5
|
+
const R = patchList.slice() // Row sum constraints
|
|
6
|
+
const C = stringList.slice() // Column sum constraints
|
|
7
|
+
|
|
8
|
+
// Initialize matrix with zeros
|
|
9
|
+
const matrix = Array.from({ length: n }, () => Array(m).fill(0))
|
|
10
|
+
|
|
11
|
+
// Function to find combinations of columns to satisfy a row sum
|
|
12
|
+
//each row represent a patch, each column represent a string
|
|
13
|
+
//we try to find matches to complete one patch with one or multiple strings
|
|
14
|
+
function findCombinationMatchesForRow(rowSum, colSums) {
|
|
15
|
+
const matches = []
|
|
16
|
+
const colsData = colSums.map((colSum, index) => {
|
|
17
|
+
return { value: colSum, index }
|
|
18
|
+
})
|
|
19
|
+
function findCombinations(
|
|
20
|
+
currentColsData,
|
|
21
|
+
currentSum,
|
|
22
|
+
target,
|
|
23
|
+
availableColsData
|
|
24
|
+
) {
|
|
25
|
+
const stack = [
|
|
26
|
+
{
|
|
27
|
+
currentColsData,
|
|
28
|
+
currentSum,
|
|
29
|
+
availableColsData,
|
|
30
|
+
index: 0,
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
let iterations = 0
|
|
35
|
+
while (stack.length > 0 && iterations < 1000 && matches.length < 5) {
|
|
36
|
+
iterations++
|
|
37
|
+
const current = stack[stack.length - 1]
|
|
38
|
+
|
|
39
|
+
if (current.currentSum === target) {
|
|
40
|
+
matches.push(current.currentColsData.map((col) => col.index))
|
|
41
|
+
stack.pop()
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (current.availableColsData.length === 0) {
|
|
46
|
+
stack.pop()
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Filter once per stack frame
|
|
51
|
+
if (!current.filtered) {
|
|
52
|
+
current.availableColsData = current.availableColsData.filter(
|
|
53
|
+
(colData) => colData.value <= target - current.currentSum
|
|
54
|
+
)
|
|
55
|
+
current.filtered = true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (current.index >= current.availableColsData.length) {
|
|
59
|
+
stack.pop()
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const selectedCol = current.availableColsData[current.index]
|
|
64
|
+
current.index++
|
|
65
|
+
|
|
66
|
+
const nextColsData = current.currentColsData.concat(selectedCol)
|
|
67
|
+
const nextSum = current.currentSum + selectedCol.value
|
|
68
|
+
const nextAvailableColsData = current.availableColsData.filter(
|
|
69
|
+
(colData) => colData.index > selectedCol.index
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
stack.push({
|
|
73
|
+
currentColsData: nextColsData,
|
|
74
|
+
currentSum: nextSum,
|
|
75
|
+
availableColsData: nextAvailableColsData,
|
|
76
|
+
index: 0,
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
findCombinations([], 0, rowSum, colsData)
|
|
81
|
+
return matches
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Function to assign values to matrix for matched rows and columns
|
|
85
|
+
function assignCombinationPerRowMatches(matches, rowSums, colSums) {
|
|
86
|
+
matches.forEach(({ row, cols }) => {
|
|
87
|
+
if (rowSums[row] && cols.every((col) => colSums[col])) {
|
|
88
|
+
cols.forEach((col) => {
|
|
89
|
+
matrix[row][col] = colSums[col]
|
|
90
|
+
colSums[col] = null // Mark column as completed
|
|
91
|
+
})
|
|
92
|
+
rowSums[row] = null // Mark row as completed
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
// Main greedy decomposition function
|
|
97
|
+
function greedyDecomposition(rowSums, colSums) {
|
|
98
|
+
// Step 1: Try to decompose rows (patch) using column (string) combinations
|
|
99
|
+
const matches = []
|
|
100
|
+
for (let i = 0; i < rowSums.length; i++) {
|
|
101
|
+
if (rowSums[i] !== null) {
|
|
102
|
+
const colCombinations = findCombinationMatchesForRow(
|
|
103
|
+
rowSums[i],
|
|
104
|
+
colSums
|
|
105
|
+
)
|
|
106
|
+
colCombinations.forEach((cols) => {
|
|
107
|
+
matches.push({
|
|
108
|
+
row: i,
|
|
109
|
+
cols,
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//sort the matchs by biggest string first
|
|
115
|
+
matches.sort(
|
|
116
|
+
(a, b) =>
|
|
117
|
+
Math.max(...b.cols.map((col) => colSums[col])) -
|
|
118
|
+
Math.max(...a.cols.map((col) => colSums[col]))
|
|
119
|
+
)
|
|
120
|
+
//sort the matchs by patch in descending order
|
|
121
|
+
matches.sort((a, b) => rowSums[b.row] - rowSums[a.row])
|
|
122
|
+
assignCombinationPerRowMatches(matches, rowSums, colSums)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Run the greedy decomposition algorithm
|
|
126
|
+
greedyDecomposition(R, C)
|
|
127
|
+
|
|
128
|
+
// Output the resulting matrix
|
|
129
|
+
return {
|
|
130
|
+
matrix,
|
|
131
|
+
R,
|
|
132
|
+
C,
|
|
133
|
+
rowsWithSolution: R.map((r, index) => (r == null ? index : null)).filter(
|
|
134
|
+
(r) => r !== null
|
|
135
|
+
),
|
|
136
|
+
colsWithSolution: C.map((c, index) => (c == null ? index : null)).filter(
|
|
137
|
+
(c) => c !== null
|
|
138
|
+
),
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shortestHamiltonianPathSolver,
|
|
3
|
+
vectorLength,
|
|
4
|
+
substractVector,
|
|
5
|
+
} from '../../index'
|
|
6
|
+
describe('ShortestHamiltonianPathSolver', () => {
|
|
7
|
+
let solver = shortestHamiltonianPathSolver
|
|
8
|
+
it('should return empty array for empty input', () => {
|
|
9
|
+
const result = solver.solve([])
|
|
10
|
+
expect(result.indexOrder).toEqual([])
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should handle single node input', () => {
|
|
14
|
+
const nodes = [{ x: 1, y: 1, z: 1 }]
|
|
15
|
+
const result = solver.solve(nodes)
|
|
16
|
+
expect(result.sortedNodes).toEqual(nodes)
|
|
17
|
+
expect(result.indexOrder).toEqual([0])
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should find optimal path for two nodes', () => {
|
|
21
|
+
const nodes = [
|
|
22
|
+
{ x: 0, y: 0, z: 0 },
|
|
23
|
+
{ x: 1, y: 1, z: 1 },
|
|
24
|
+
]
|
|
25
|
+
const result = solver.solve(nodes)
|
|
26
|
+
expect(result.sortedNodes).toEqual(nodes)
|
|
27
|
+
expect(result.indexOrder).toEqual([0, 1])
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should find optimal path for square', () => {
|
|
31
|
+
const input = [
|
|
32
|
+
{ x: 0, y: 0, z: 0 },
|
|
33
|
+
{ x: 100, y: 100, z: 0 },
|
|
34
|
+
{ x: 0, y: 100, z: 0 },
|
|
35
|
+
{ x: 100, y: 0, z: 0 },
|
|
36
|
+
]
|
|
37
|
+
solver.isVerbose = true
|
|
38
|
+
const expectedIndexOrder = []
|
|
39
|
+
const result = solver.solve(input)
|
|
40
|
+
expect(result.cost).toBe(300)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should find optimal path for line', () => {
|
|
44
|
+
const A = { x: 0, y: 0, z: 0 }
|
|
45
|
+
const B = { x: 0, y: 100, z: 0 }
|
|
46
|
+
const C = { x: 0, y: 200, z: 0 }
|
|
47
|
+
const D = { x: 0, y: 300, z: 0 }
|
|
48
|
+
const E = { x: 0, y: 400, z: 0 }
|
|
49
|
+
|
|
50
|
+
let result = solver.solve([A, B, C, D, E])
|
|
51
|
+
expect(result.cost).toBe(400)
|
|
52
|
+
result = solver.solve([E, B, C, D, A])
|
|
53
|
+
expect(result.cost).toBe(400)
|
|
54
|
+
result = solver.solve([B, C, A, E, D])
|
|
55
|
+
expect(result.cost).toBe(400)
|
|
56
|
+
result = solver.solve([E, D, C, B, A])
|
|
57
|
+
expect(result.cost).toBe(400)
|
|
58
|
+
result = solver.solve([D, E, C, A, B])
|
|
59
|
+
expect(result.cost).toBe(400)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('should handle nodes with same coordinates', () => {
|
|
63
|
+
const nodes = [
|
|
64
|
+
{ x: 1, y: 1, z: 1 },
|
|
65
|
+
{ x: 1, y: 1, z: 1 },
|
|
66
|
+
]
|
|
67
|
+
const result = solver.solve(nodes)
|
|
68
|
+
expect(result.sortedNodes.length).toBe(2)
|
|
69
|
+
expect(result.indexOrder.length).toBe(2)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { shortestHamiltonianPathSolver } from '../../index'
|
|
2
|
+
import { scenario_4 } from './scenarios'
|
|
3
|
+
|
|
4
|
+
describe('ShortestHamiltonianPathSolver', () => {
|
|
5
|
+
let solver = shortestHamiltonianPathSolver
|
|
6
|
+
it('should be return shortestHamiltonianPath from real scenario 3', () => {
|
|
7
|
+
// const input = scenario_4.inputData.panels.map((p) => p.center)
|
|
8
|
+
// const N = scenario_4.inputData.panels.length
|
|
9
|
+
// const initialCost = solver.computePathCost(
|
|
10
|
+
// Array(N)
|
|
11
|
+
// .fill()
|
|
12
|
+
// .map((_, i) => i),
|
|
13
|
+
// input,
|
|
14
|
+
// false
|
|
15
|
+
// )
|
|
16
|
+
// const result = solver.solve(input, {
|
|
17
|
+
// hasVirtualNode: true,
|
|
18
|
+
// proximityMatrix: null,
|
|
19
|
+
// preventIntersection: true,
|
|
20
|
+
// })
|
|
21
|
+
// const sortedNodes = result.sortedNodes
|
|
22
|
+
// const areSelfIntersect = solver.isPathValid(result.indexOrder, input, false)
|
|
23
|
+
//console.log('result', initialCost, areSelfIntersect, result)
|
|
24
|
+
//expect(areSelfIntersect).toBe(false)
|
|
25
|
+
})
|
|
26
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import scenario_1 from './scenario_1.json'
|
|
2
|
+
import scenario_1b from './scenario_1b.json'
|
|
3
|
+
import scenario_1_row from './scenario_1_row.json'
|
|
4
|
+
import scenario_2_row from './scenario_2_row.json'
|
|
5
|
+
import scenario_3 from './scenario_3.json'
|
|
6
|
+
import scenario_4 from './scenario_4.json'
|
|
7
|
+
import scenario_3_simplify from './scenario_3_simplify.json'
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
scenario_1,
|
|
11
|
+
scenario_1b,
|
|
12
|
+
scenario_1_row,
|
|
13
|
+
scenario_2_row,
|
|
14
|
+
scenario_3,
|
|
15
|
+
scenario_3_simplify,
|
|
16
|
+
scenario_4,
|
|
17
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputData": {
|
|
3
|
+
"panelsIndexes": [
|
|
4
|
+
[4, 13],
|
|
5
|
+
[5, 13],
|
|
6
|
+
[4, 12],
|
|
7
|
+
[5, 12],
|
|
8
|
+
[3, 12]
|
|
9
|
+
],
|
|
10
|
+
"panels": [
|
|
11
|
+
{
|
|
12
|
+
"center": {
|
|
13
|
+
"x": 100,
|
|
14
|
+
"y": 100,
|
|
15
|
+
"z": 0
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"center": {
|
|
20
|
+
"x": 100,
|
|
21
|
+
"y": 200,
|
|
22
|
+
"z": 0
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"center": {
|
|
27
|
+
"x": 200,
|
|
28
|
+
"y": 100,
|
|
29
|
+
"z": 0
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"center": {
|
|
34
|
+
"x": 200,
|
|
35
|
+
"y": 200,
|
|
36
|
+
"z": 0
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"center": {
|
|
41
|
+
"x": 200,
|
|
42
|
+
"y": 0,
|
|
43
|
+
"z": 0
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"outputData": {
|
|
49
|
+
"panelsIndexes": [
|
|
50
|
+
[4, 13],
|
|
51
|
+
[5, 13],
|
|
52
|
+
[4, 12],
|
|
53
|
+
[5, 12],
|
|
54
|
+
[3, 12]
|
|
55
|
+
],
|
|
56
|
+
"indexOrder": [0, 1, 2, 3, 4]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputData": {
|
|
3
|
+
"panelsIndexes": [
|
|
4
|
+
[3, 13],
|
|
5
|
+
[4, 13],
|
|
6
|
+
[5, 13],
|
|
7
|
+
[4, 12],
|
|
8
|
+
[5, 12],
|
|
9
|
+
[3, 12],
|
|
10
|
+
[2, 12],
|
|
11
|
+
[1, 12],
|
|
12
|
+
[0, 12]
|
|
13
|
+
],
|
|
14
|
+
"panels": [
|
|
15
|
+
{
|
|
16
|
+
"center": {
|
|
17
|
+
"x": -201592.9454132333,
|
|
18
|
+
"y": -145757.73980606598,
|
|
19
|
+
"z": 3992.2558982478513
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"center": {
|
|
24
|
+
"x": -201387.29671194102,
|
|
25
|
+
"y": -144876.38822909922,
|
|
26
|
+
"z": 4442.865495832077
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"center": {
|
|
31
|
+
"x": -201181.6480106488,
|
|
32
|
+
"y": -143995.03665213246,
|
|
33
|
+
"z": 4893.475093416302
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"center": {
|
|
38
|
+
"x": -199760.98189167224,
|
|
39
|
+
"y": -145255.8616871619,
|
|
40
|
+
"z": 4442.865495832069
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"center": {
|
|
45
|
+
"x": -199555.33319038,
|
|
46
|
+
"y": -144374.51011019514,
|
|
47
|
+
"z": 4893.475093416295
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"center": {
|
|
52
|
+
"x": -199966.63059296447,
|
|
53
|
+
"y": -146137.21326412866,
|
|
54
|
+
"z": 3992.255898247844
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"center": {
|
|
59
|
+
"x": -200172.2792942567,
|
|
60
|
+
"y": -147018.56484109542,
|
|
61
|
+
"z": 3541.6463006636186
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"center": {
|
|
66
|
+
"x": -200377.927995549,
|
|
67
|
+
"y": -147899.91641806217,
|
|
68
|
+
"z": 3091.036703079393
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"center": {
|
|
73
|
+
"x": -200583.57669684122,
|
|
74
|
+
"y": -148781.26799502896,
|
|
75
|
+
"z": 2640.4271054951605
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"outputData": {
|
|
81
|
+
"panelsIndexes": [
|
|
82
|
+
[3, 13],
|
|
83
|
+
[4, 13],
|
|
84
|
+
[5, 13],
|
|
85
|
+
[4, 12],
|
|
86
|
+
[5, 12],
|
|
87
|
+
[3, 12],
|
|
88
|
+
[2, 12],
|
|
89
|
+
[1, 12],
|
|
90
|
+
[0, 12]
|
|
91
|
+
],
|
|
92
|
+
"panels": [
|
|
93
|
+
{
|
|
94
|
+
"center": {
|
|
95
|
+
"x": -201592.9454132333,
|
|
96
|
+
"y": -145757.73980606598,
|
|
97
|
+
"z": 3992.2558982478513
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"center": {
|
|
102
|
+
"x": -201387.29671194102,
|
|
103
|
+
"y": -144876.38822909922,
|
|
104
|
+
"z": 4442.865495832077
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"center": {
|
|
109
|
+
"x": -201181.6480106488,
|
|
110
|
+
"y": -143995.03665213246,
|
|
111
|
+
"z": 4893.475093416302
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"center": {
|
|
116
|
+
"x": -199760.98189167224,
|
|
117
|
+
"y": -145255.8616871619,
|
|
118
|
+
"z": 4442.865495832069
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"center": {
|
|
123
|
+
"x": -199555.33319038,
|
|
124
|
+
"y": -144374.51011019514,
|
|
125
|
+
"z": 4893.475093416295
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"center": {
|
|
130
|
+
"x": -199966.63059296447,
|
|
131
|
+
"y": -146137.21326412866,
|
|
132
|
+
"z": 3992.255898247844
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"center": {
|
|
137
|
+
"x": -200172.2792942567,
|
|
138
|
+
"y": -147018.56484109542,
|
|
139
|
+
"z": 3541.6463006636186
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"center": {
|
|
144
|
+
"x": -200377.927995549,
|
|
145
|
+
"y": -147899.91641806217,
|
|
146
|
+
"z": 3091.036703079393
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"center": {
|
|
151
|
+
"x": -200583.57669684122,
|
|
152
|
+
"y": -148781.26799502896,
|
|
153
|
+
"z": 2640.4271054951605
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
],
|
|
157
|
+
"indexOrder": [0, 1, 2, 3, 4, 5, 6, 7, 8]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputData": {
|
|
3
|
+
"panelsIndexes": [
|
|
4
|
+
[0, 4],
|
|
5
|
+
[1, 3],
|
|
6
|
+
[0, 3]
|
|
7
|
+
],
|
|
8
|
+
"panels": [
|
|
9
|
+
{
|
|
10
|
+
"center": {
|
|
11
|
+
"x": 0,
|
|
12
|
+
"y": 0,
|
|
13
|
+
"z": 0
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"center": {
|
|
18
|
+
"x": 200,
|
|
19
|
+
"y": 100,
|
|
20
|
+
"z": 0
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"center": {
|
|
25
|
+
"x": 200,
|
|
26
|
+
"y": 0,
|
|
27
|
+
"z": 0
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"outputData": {
|
|
33
|
+
"indexOrder": [0, 2, 1]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"inputData": {
|
|
3
|
+
"panelsIndexes": [
|
|
4
|
+
[1, 4],
|
|
5
|
+
[0, 4],
|
|
6
|
+
[1, 3],
|
|
7
|
+
[0, 3],
|
|
8
|
+
[2, 3]
|
|
9
|
+
],
|
|
10
|
+
"panels": [
|
|
11
|
+
{
|
|
12
|
+
"center": {
|
|
13
|
+
"x": 5815.287972158337,
|
|
14
|
+
"y": -3592.857582161817,
|
|
15
|
+
"z": 3000
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"center": {
|
|
20
|
+
"x": 5835.303850225924,
|
|
21
|
+
"y": -4603.659424574653,
|
|
22
|
+
"z": 3000
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"center": {
|
|
27
|
+
"x": 7484.9606495366115,
|
|
28
|
+
"y": -3559.794756867186,
|
|
29
|
+
"z": 3000
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"center": {
|
|
34
|
+
"x": 7504.9765276042,
|
|
35
|
+
"y": -4570.596599280022,
|
|
36
|
+
"z": 3000
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"center": {
|
|
41
|
+
"x": 7464.944771469023,
|
|
42
|
+
"y": -2548.9929144543503,
|
|
43
|
+
"z": 3000
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"outputData": {
|
|
49
|
+
"indexOrder": [0, 1, 3, 2, 4]
|
|
50
|
+
}
|
|
51
|
+
}
|