calculate-packing 0.0.29 → 0.0.30
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/dist/index.d.ts +70 -3
- package/dist/index.js +287 -21
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ interface PackedComponent extends InputComponent {
|
|
|
43
43
|
ccwRotationDegrees?: number;
|
|
44
44
|
pads: OutputPad[];
|
|
45
45
|
}
|
|
46
|
-
type PackPlacementStrategy = "shortest_connection_along_outline" | "minimum_sum_distance_to_network" | "minimum_sum_squared_distance_to_network";
|
|
46
|
+
type PackPlacementStrategy = "shortest_connection_along_outline" | "minimum_sum_distance_to_network" | "minimum_sum_squared_distance_to_network" | "minimum_closest_sum_squared_distance";
|
|
47
47
|
interface PackInput {
|
|
48
48
|
components: InputComponent[];
|
|
49
49
|
minGap: number;
|
|
@@ -304,6 +304,72 @@ declare class MultiOffsetIrlsSolver extends BaseSolver {
|
|
|
304
304
|
visualize(): GraphicsObject;
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
interface TwoPhaseIrlsSolverParams extends Omit<MultiOffsetIrlsSolverParams, "useSquaredDistance"> {
|
|
308
|
+
/** Phase 1 convergence tolerance */
|
|
309
|
+
phase1Epsilon?: number;
|
|
310
|
+
/** Phase 2 convergence tolerance */
|
|
311
|
+
phase2Epsilon?: number;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Two-Phase IRLS Solver that implements the "minimum_closest_sum_squared_distance" strategy.
|
|
315
|
+
*
|
|
316
|
+
* Phase 1: Solves for minimum sum squared distance (like regular squared distance optimization)
|
|
317
|
+
* Phase 2: From the Phase 1 solution, finds the closest point to any target and optimizes
|
|
318
|
+
* to minimize JUST the distance to that single closest point
|
|
319
|
+
*/
|
|
320
|
+
declare class TwoPhaseIrlsSolver extends BaseSolver {
|
|
321
|
+
offsetPadPoints: MultiOffsetIrlsSolverParams["offsetPadPoints"];
|
|
322
|
+
targetPointMap: MultiOffsetIrlsSolverParams["targetPointMap"];
|
|
323
|
+
constraintFn?: MultiOffsetIrlsSolverParams["constraintFn"];
|
|
324
|
+
currentPosition: {
|
|
325
|
+
x: number;
|
|
326
|
+
y: number;
|
|
327
|
+
};
|
|
328
|
+
optimalPosition?: {
|
|
329
|
+
x: number;
|
|
330
|
+
y: number;
|
|
331
|
+
};
|
|
332
|
+
private readonly initialPosition;
|
|
333
|
+
private readonly phase1Epsilon;
|
|
334
|
+
private readonly phase2Epsilon;
|
|
335
|
+
private readonly maxIterations;
|
|
336
|
+
private phase1Solver?;
|
|
337
|
+
private phase2Solver?;
|
|
338
|
+
private currentPhase;
|
|
339
|
+
private phase1Position?;
|
|
340
|
+
private closestTargetPadId?;
|
|
341
|
+
private closestTargetPoint?;
|
|
342
|
+
constructor(params: TwoPhaseIrlsSolverParams);
|
|
343
|
+
getConstructorParams(): TwoPhaseIrlsSolverParams;
|
|
344
|
+
_setup(): void;
|
|
345
|
+
_step(): void;
|
|
346
|
+
private stepPhase1;
|
|
347
|
+
private setupPhase2;
|
|
348
|
+
private stepPhase2;
|
|
349
|
+
/**
|
|
350
|
+
* Get the current best position
|
|
351
|
+
*/
|
|
352
|
+
getBestPosition(): {
|
|
353
|
+
x: number;
|
|
354
|
+
y: number;
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* Get the current absolute positions for all offset pad points
|
|
358
|
+
*/
|
|
359
|
+
getOffsetPadPositions(): Map<string, {
|
|
360
|
+
x: number;
|
|
361
|
+
y: number;
|
|
362
|
+
}>;
|
|
363
|
+
/**
|
|
364
|
+
* Calculate total distance from current position to all assigned target points
|
|
365
|
+
*/
|
|
366
|
+
getTotalDistance(position?: {
|
|
367
|
+
x: number;
|
|
368
|
+
y: number;
|
|
369
|
+
}): number;
|
|
370
|
+
visualize(): GraphicsObject;
|
|
371
|
+
}
|
|
372
|
+
|
|
307
373
|
/**
|
|
308
374
|
* Given a single segment on the outline, the component's rotation, compute the
|
|
309
375
|
* optimal position for the rotated component (the position that minimizes the
|
|
@@ -319,18 +385,19 @@ declare class OutlineSegmentCandidatePointSolver extends BaseSolver {
|
|
|
319
385
|
viableOutlineSegment: [Point$3, Point$3] | null;
|
|
320
386
|
fullOutline: [Point$3, Point$3][];
|
|
321
387
|
componentRotationDegrees: number;
|
|
322
|
-
packStrategy: "minimum_sum_squared_distance_to_network" | "minimum_sum_distance_to_network";
|
|
388
|
+
packStrategy: "minimum_sum_squared_distance_to_network" | "minimum_sum_distance_to_network" | "minimum_closest_sum_squared_distance";
|
|
323
389
|
minGap: number;
|
|
324
390
|
packedComponents: PackedComponent[];
|
|
325
391
|
componentToPack: InputComponent;
|
|
326
392
|
viableBounds?: Bounds;
|
|
327
393
|
optimalPosition?: Point$3;
|
|
328
394
|
irlsSolver?: MultiOffsetIrlsSolver;
|
|
395
|
+
twoPhaseIrlsSolver?: TwoPhaseIrlsSolver;
|
|
329
396
|
constructor(params: {
|
|
330
397
|
outlineSegment: [Point$3, Point$3];
|
|
331
398
|
fullOutline: [Point$3, Point$3][];
|
|
332
399
|
componentRotationDegrees: number;
|
|
333
|
-
packStrategy: "minimum_sum_squared_distance_to_network" | "minimum_sum_distance_to_network";
|
|
400
|
+
packStrategy: "minimum_sum_squared_distance_to_network" | "minimum_sum_distance_to_network" | "minimum_closest_sum_squared_distance";
|
|
334
401
|
minGap: number;
|
|
335
402
|
packedComponents: PackedComponent[];
|
|
336
403
|
componentToPack: InputComponent;
|
package/dist/index.js
CHANGED
|
@@ -2165,6 +2165,258 @@ var MultiOffsetIrlsSolver = class extends BaseSolver {
|
|
|
2165
2165
|
}
|
|
2166
2166
|
};
|
|
2167
2167
|
|
|
2168
|
+
// lib/solver-utils/TwoPhaseIrlsSolver.ts
|
|
2169
|
+
var TwoPhaseIrlsSolver = class extends BaseSolver {
|
|
2170
|
+
offsetPadPoints;
|
|
2171
|
+
targetPointMap;
|
|
2172
|
+
constraintFn;
|
|
2173
|
+
currentPosition;
|
|
2174
|
+
optimalPosition;
|
|
2175
|
+
initialPosition;
|
|
2176
|
+
phase1Epsilon;
|
|
2177
|
+
phase2Epsilon;
|
|
2178
|
+
maxIterations;
|
|
2179
|
+
phase1Solver;
|
|
2180
|
+
phase2Solver;
|
|
2181
|
+
currentPhase = 1;
|
|
2182
|
+
phase1Position;
|
|
2183
|
+
closestTargetPadId;
|
|
2184
|
+
closestTargetPoint;
|
|
2185
|
+
constructor(params) {
|
|
2186
|
+
super();
|
|
2187
|
+
this.offsetPadPoints = [...params.offsetPadPoints];
|
|
2188
|
+
this.targetPointMap = new Map(params.targetPointMap);
|
|
2189
|
+
this.initialPosition = { ...params.initialPosition };
|
|
2190
|
+
this.currentPosition = { ...params.initialPosition };
|
|
2191
|
+
this.constraintFn = params.constraintFn;
|
|
2192
|
+
this.phase1Epsilon = params.phase1Epsilon ?? params.epsilon ?? 1e-6;
|
|
2193
|
+
this.phase2Epsilon = params.phase2Epsilon ?? params.epsilon ?? 1e-6;
|
|
2194
|
+
this.maxIterations = params.maxIterations ?? 100;
|
|
2195
|
+
}
|
|
2196
|
+
getConstructorParams() {
|
|
2197
|
+
return {
|
|
2198
|
+
offsetPadPoints: this.offsetPadPoints.map((pad) => ({ ...pad })),
|
|
2199
|
+
targetPointMap: new Map(this.targetPointMap),
|
|
2200
|
+
initialPosition: this.initialPosition,
|
|
2201
|
+
constraintFn: this.constraintFn,
|
|
2202
|
+
phase1Epsilon: this.phase1Epsilon,
|
|
2203
|
+
phase2Epsilon: this.phase2Epsilon,
|
|
2204
|
+
maxIterations: this.maxIterations
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
_setup() {
|
|
2208
|
+
this.currentPosition = { ...this.initialPosition };
|
|
2209
|
+
this.optimalPosition = void 0;
|
|
2210
|
+
this.currentPhase = 1;
|
|
2211
|
+
this.phase1Position = void 0;
|
|
2212
|
+
this.closestTargetPadId = void 0;
|
|
2213
|
+
this.closestTargetPoint = void 0;
|
|
2214
|
+
const hasTargets = Array.from(this.targetPointMap.values()).some(
|
|
2215
|
+
(targets) => targets.length > 0
|
|
2216
|
+
);
|
|
2217
|
+
if (!hasTargets || this.offsetPadPoints.length === 0) {
|
|
2218
|
+
this.optimalPosition = { ...this.currentPosition };
|
|
2219
|
+
this.solved = true;
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
this.phase1Solver = new MultiOffsetIrlsSolver({
|
|
2223
|
+
offsetPadPoints: this.offsetPadPoints,
|
|
2224
|
+
targetPointMap: this.targetPointMap,
|
|
2225
|
+
initialPosition: this.initialPosition,
|
|
2226
|
+
constraintFn: this.constraintFn,
|
|
2227
|
+
epsilon: this.phase1Epsilon,
|
|
2228
|
+
maxIterations: this.maxIterations,
|
|
2229
|
+
useSquaredDistance: true
|
|
2230
|
+
// Phase 1 uses squared distance
|
|
2231
|
+
});
|
|
2232
|
+
this.phase1Solver.setup();
|
|
2233
|
+
}
|
|
2234
|
+
_step() {
|
|
2235
|
+
if (this.currentPhase === 1) {
|
|
2236
|
+
this.stepPhase1();
|
|
2237
|
+
} else {
|
|
2238
|
+
this.stepPhase2();
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
stepPhase1() {
|
|
2242
|
+
if (!this.phase1Solver) return;
|
|
2243
|
+
this.phase1Solver.step();
|
|
2244
|
+
this.currentPosition = this.phase1Solver.getBestPosition();
|
|
2245
|
+
if (this.phase1Solver.solved) {
|
|
2246
|
+
this.phase1Position = this.phase1Solver.getBestPosition();
|
|
2247
|
+
this.setupPhase2();
|
|
2248
|
+
} else if (this.phase1Solver.failed) {
|
|
2249
|
+
this.failed = true;
|
|
2250
|
+
this.error = `Phase 1 failed: ${this.phase1Solver.error}`;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
setupPhase2() {
|
|
2254
|
+
if (!this.phase1Position) return;
|
|
2255
|
+
let minDistance = Infinity;
|
|
2256
|
+
let closestPadId;
|
|
2257
|
+
let closestTarget;
|
|
2258
|
+
for (const pad of this.offsetPadPoints) {
|
|
2259
|
+
const targetPoints = this.targetPointMap.get(pad.id) || [];
|
|
2260
|
+
if (targetPoints.length === 0) continue;
|
|
2261
|
+
const padX = this.phase1Position.x + pad.offsetX;
|
|
2262
|
+
const padY = this.phase1Position.y + pad.offsetY;
|
|
2263
|
+
for (const targetPoint of targetPoints) {
|
|
2264
|
+
const dx = padX - targetPoint.x;
|
|
2265
|
+
const dy = padY - targetPoint.y;
|
|
2266
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
2267
|
+
if (distance < minDistance) {
|
|
2268
|
+
minDistance = distance;
|
|
2269
|
+
closestPadId = pad.id;
|
|
2270
|
+
closestTarget = targetPoint;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
this.closestTargetPadId = closestPadId;
|
|
2275
|
+
this.closestTargetPoint = closestTarget;
|
|
2276
|
+
if (!closestPadId || !closestTarget) {
|
|
2277
|
+
this.optimalPosition = this.phase1Position;
|
|
2278
|
+
this.solved = true;
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
const phase2TargetMap = /* @__PURE__ */ new Map();
|
|
2282
|
+
phase2TargetMap.set(closestPadId, [closestTarget]);
|
|
2283
|
+
this.phase2Solver = new MultiOffsetIrlsSolver({
|
|
2284
|
+
offsetPadPoints: this.offsetPadPoints,
|
|
2285
|
+
targetPointMap: phase2TargetMap,
|
|
2286
|
+
initialPosition: this.phase1Position,
|
|
2287
|
+
constraintFn: this.constraintFn,
|
|
2288
|
+
epsilon: this.phase2Epsilon,
|
|
2289
|
+
maxIterations: this.maxIterations,
|
|
2290
|
+
useSquaredDistance: false
|
|
2291
|
+
// Phase 2 uses regular distance
|
|
2292
|
+
});
|
|
2293
|
+
this.phase2Solver.setup();
|
|
2294
|
+
this.currentPhase = 2;
|
|
2295
|
+
}
|
|
2296
|
+
stepPhase2() {
|
|
2297
|
+
if (!this.phase2Solver) return;
|
|
2298
|
+
this.phase2Solver.step();
|
|
2299
|
+
this.currentPosition = this.phase2Solver.getBestPosition();
|
|
2300
|
+
if (this.phase2Solver.solved) {
|
|
2301
|
+
this.optimalPosition = this.phase2Solver.getBestPosition();
|
|
2302
|
+
this.solved = true;
|
|
2303
|
+
} else if (this.phase2Solver.failed) {
|
|
2304
|
+
this.failed = true;
|
|
2305
|
+
this.error = `Phase 2 failed: ${this.phase2Solver.error}`;
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* Get the current best position
|
|
2310
|
+
*/
|
|
2311
|
+
getBestPosition() {
|
|
2312
|
+
return this.optimalPosition || this.currentPosition;
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Get the current absolute positions for all offset pad points
|
|
2316
|
+
*/
|
|
2317
|
+
getOffsetPadPositions() {
|
|
2318
|
+
const currentPos = this.getBestPosition();
|
|
2319
|
+
const padPositions = /* @__PURE__ */ new Map();
|
|
2320
|
+
for (const pad of this.offsetPadPoints) {
|
|
2321
|
+
padPositions.set(pad.id, {
|
|
2322
|
+
x: currentPos.x + pad.offsetX,
|
|
2323
|
+
y: currentPos.y + pad.offsetY
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
return padPositions;
|
|
2327
|
+
}
|
|
2328
|
+
/**
|
|
2329
|
+
* Calculate total distance from current position to all assigned target points
|
|
2330
|
+
*/
|
|
2331
|
+
getTotalDistance(position) {
|
|
2332
|
+
const pos = position || this.getBestPosition();
|
|
2333
|
+
let totalDistance = 0;
|
|
2334
|
+
for (const pad of this.offsetPadPoints) {
|
|
2335
|
+
const padPosition = {
|
|
2336
|
+
x: pos.x + pad.offsetX,
|
|
2337
|
+
y: pos.y + pad.offsetY
|
|
2338
|
+
};
|
|
2339
|
+
const targetPoints = this.targetPointMap.get(pad.id) || [];
|
|
2340
|
+
for (const target of targetPoints) {
|
|
2341
|
+
const dx = padPosition.x - target.x;
|
|
2342
|
+
const dy = padPosition.y - target.y;
|
|
2343
|
+
totalDistance += dx * dx + dy * dy;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
return totalDistance;
|
|
2347
|
+
}
|
|
2348
|
+
visualize() {
|
|
2349
|
+
const graphics = {
|
|
2350
|
+
lines: [],
|
|
2351
|
+
points: [],
|
|
2352
|
+
rects: [],
|
|
2353
|
+
circles: []
|
|
2354
|
+
};
|
|
2355
|
+
graphics.points.push({
|
|
2356
|
+
...this.currentPosition,
|
|
2357
|
+
color: this.currentPhase === 1 ? "#FF6B6B" : "#4ECDC4",
|
|
2358
|
+
label: `Phase ${this.currentPhase}`
|
|
2359
|
+
});
|
|
2360
|
+
if (this.phase1Position && this.currentPhase === 2) {
|
|
2361
|
+
graphics.points.push({
|
|
2362
|
+
...this.phase1Position,
|
|
2363
|
+
color: "rgba(255, 107, 107, 0.5)",
|
|
2364
|
+
label: "Phase 1 result"
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
if (this.closestTargetPoint && this.closestTargetPadId) {
|
|
2368
|
+
graphics.points.push({
|
|
2369
|
+
...this.closestTargetPoint,
|
|
2370
|
+
color: "#FFA500",
|
|
2371
|
+
label: `Closest target (${this.closestTargetPadId})`
|
|
2372
|
+
});
|
|
2373
|
+
const closestPad = this.offsetPadPoints.find(
|
|
2374
|
+
(p) => p.id === this.closestTargetPadId
|
|
2375
|
+
);
|
|
2376
|
+
if (closestPad) {
|
|
2377
|
+
const currentPos = this.getBestPosition();
|
|
2378
|
+
const padPos = {
|
|
2379
|
+
x: currentPos.x + closestPad.offsetX,
|
|
2380
|
+
y: currentPos.y + closestPad.offsetY
|
|
2381
|
+
};
|
|
2382
|
+
graphics.lines.push({
|
|
2383
|
+
points: [padPos, this.closestTargetPoint],
|
|
2384
|
+
strokeColor: "#FFA500"
|
|
2385
|
+
});
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
const activeSolver = this.currentPhase === 1 ? this.phase1Solver : this.phase2Solver;
|
|
2389
|
+
if (activeSolver) {
|
|
2390
|
+
const solverViz = activeSolver.visualize();
|
|
2391
|
+
const phaseColor = this.currentPhase === 1 ? "rgba(255, 107, 107, 0.7)" : "rgba(76, 205, 196, 0.7)";
|
|
2392
|
+
if (solverViz.lines) {
|
|
2393
|
+
const modifiedLines = solverViz.lines.map((line) => ({
|
|
2394
|
+
...line,
|
|
2395
|
+
strokeColor: phaseColor
|
|
2396
|
+
}));
|
|
2397
|
+
graphics.lines.push(...modifiedLines);
|
|
2398
|
+
}
|
|
2399
|
+
if (solverViz.points) {
|
|
2400
|
+
graphics.points.push(...solverViz.points);
|
|
2401
|
+
}
|
|
2402
|
+
if (solverViz.rects) {
|
|
2403
|
+
graphics.rects.push(...solverViz.rects);
|
|
2404
|
+
}
|
|
2405
|
+
if (solverViz.circles) {
|
|
2406
|
+
graphics.circles.push(...solverViz.circles);
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
if (this.optimalPosition) {
|
|
2410
|
+
graphics.points.push({
|
|
2411
|
+
...this.optimalPosition,
|
|
2412
|
+
color: "rgba(76, 175, 80, 0.8)",
|
|
2413
|
+
label: "Final optimal position"
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2416
|
+
return graphics;
|
|
2417
|
+
}
|
|
2418
|
+
};
|
|
2419
|
+
|
|
2168
2420
|
// lib/geometry/pointInOutline.ts
|
|
2169
2421
|
var EPS = 1e-9;
|
|
2170
2422
|
function cross2(ax, ay, bx, by) {
|
|
@@ -2309,6 +2561,7 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
|
|
|
2309
2561
|
viableBounds;
|
|
2310
2562
|
optimalPosition;
|
|
2311
2563
|
irlsSolver;
|
|
2564
|
+
twoPhaseIrlsSolver;
|
|
2312
2565
|
constructor(params) {
|
|
2313
2566
|
super();
|
|
2314
2567
|
this.outlineSegment = params.outlineSegment;
|
|
@@ -2427,29 +2680,41 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
|
|
|
2427
2680
|
x: (vp1.x + vp2.x) / 2,
|
|
2428
2681
|
y: (vp1.y + vp2.y) / 2
|
|
2429
2682
|
});
|
|
2430
|
-
this.
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2683
|
+
if (this.packStrategy === "minimum_closest_sum_squared_distance") {
|
|
2684
|
+
this.twoPhaseIrlsSolver = new TwoPhaseIrlsSolver({
|
|
2685
|
+
offsetPadPoints,
|
|
2686
|
+
targetPointMap,
|
|
2687
|
+
initialPosition,
|
|
2688
|
+
constraintFn,
|
|
2689
|
+
epsilon: 1e-6,
|
|
2690
|
+
maxIterations: 50
|
|
2691
|
+
});
|
|
2692
|
+
} else {
|
|
2693
|
+
this.irlsSolver = new MultiOffsetIrlsSolver({
|
|
2694
|
+
offsetPadPoints,
|
|
2695
|
+
targetPointMap,
|
|
2696
|
+
initialPosition,
|
|
2697
|
+
constraintFn,
|
|
2698
|
+
epsilon: 1e-6,
|
|
2699
|
+
maxIterations: 50,
|
|
2700
|
+
useSquaredDistance: this.packStrategy === "minimum_sum_squared_distance_to_network"
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2439
2703
|
}
|
|
2440
2704
|
_step() {
|
|
2441
|
-
|
|
2705
|
+
const activeSolver = this.irlsSolver || this.twoPhaseIrlsSolver;
|
|
2706
|
+
if (!activeSolver) {
|
|
2442
2707
|
this.solved = true;
|
|
2443
2708
|
return;
|
|
2444
2709
|
}
|
|
2445
|
-
|
|
2446
|
-
if (
|
|
2447
|
-
const rawPosition =
|
|
2710
|
+
activeSolver.step();
|
|
2711
|
+
if (activeSolver.solved) {
|
|
2712
|
+
const rawPosition = activeSolver.getBestPosition();
|
|
2448
2713
|
this.optimalPosition = rawPosition;
|
|
2449
2714
|
this.solved = true;
|
|
2450
|
-
} else if (
|
|
2715
|
+
} else if (activeSolver.failed) {
|
|
2451
2716
|
this.failed = true;
|
|
2452
|
-
this.error =
|
|
2717
|
+
this.error = activeSolver.error;
|
|
2453
2718
|
}
|
|
2454
2719
|
}
|
|
2455
2720
|
/**
|
|
@@ -2672,7 +2937,7 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
|
|
|
2672
2937
|
});
|
|
2673
2938
|
}
|
|
2674
2939
|
}
|
|
2675
|
-
const pos = this.optimalPosition ?? this.irlsSolver?.currentPosition ?? {
|
|
2940
|
+
const pos = this.optimalPosition ?? this.irlsSolver?.currentPosition ?? this.twoPhaseIrlsSolver?.currentPosition ?? {
|
|
2676
2941
|
x: 0,
|
|
2677
2942
|
y: 0
|
|
2678
2943
|
};
|
|
@@ -2702,13 +2967,14 @@ var OutlineSegmentCandidatePointSolver = class extends BaseSolver {
|
|
|
2702
2967
|
}
|
|
2703
2968
|
}
|
|
2704
2969
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2970
|
+
const activeSolver = this.irlsSolver || this.twoPhaseIrlsSolver;
|
|
2971
|
+
if (activeSolver) {
|
|
2972
|
+
const currentPos = activeSolver.currentPosition;
|
|
2707
2973
|
graphics.points.push({
|
|
2708
2974
|
...currentPos,
|
|
2709
2975
|
color: "#f44336"
|
|
2710
2976
|
});
|
|
2711
|
-
const solverViz =
|
|
2977
|
+
const solverViz = activeSolver.visualize();
|
|
2712
2978
|
if (solverViz.lines) {
|
|
2713
2979
|
graphics.lines.push(...solverViz.lines);
|
|
2714
2980
|
}
|
|
@@ -2871,7 +3137,7 @@ var SingleComponentPackSolver = class extends BaseSolver {
|
|
|
2871
3137
|
outlineSegment: queuedSegment.segment,
|
|
2872
3138
|
fullOutline: queuedSegment.fullOutline,
|
|
2873
3139
|
componentRotationDegrees: rotation,
|
|
2874
|
-
packStrategy: "minimum_sum_squared_distance_to_network",
|
|
3140
|
+
packStrategy: this.packPlacementStrategy === "minimum_closest_sum_squared_distance" ? "minimum_closest_sum_squared_distance" : "minimum_sum_squared_distance_to_network",
|
|
2875
3141
|
minGap: this.minGap,
|
|
2876
3142
|
packedComponents: this.packedComponents,
|
|
2877
3143
|
componentToPack: this.componentToPack
|
|
@@ -2900,7 +3166,7 @@ var SingleComponentPackSolver = class extends BaseSolver {
|
|
|
2900
3166
|
calculateDistance(position, rotation) {
|
|
2901
3167
|
const tempComponent = this.createPackedComponent(position, rotation);
|
|
2902
3168
|
let totalDistance = 0;
|
|
2903
|
-
const useSquaredDistance = this.packPlacementStrategy === "minimum_sum_squared_distance_to_network";
|
|
3169
|
+
const useSquaredDistance = this.packPlacementStrategy === "minimum_sum_squared_distance_to_network" || this.packPlacementStrategy === "minimum_closest_sum_squared_distance";
|
|
2904
3170
|
for (const pad of tempComponent.pads) {
|
|
2905
3171
|
let minDistanceToNetwork = Infinity;
|
|
2906
3172
|
for (const packedComponent of this.packedComponents) {
|
package/package.json
CHANGED