Skip to content
This repository was archived by the owner on Feb 4, 2022. It is now read-only.

Commit 493dfa7

Browse files
committed
Update nesting stuffs.
1 parent a45c8a1 commit 493dfa7

File tree

3 files changed

+115
-39
lines changed

3 files changed

+115
-39
lines changed

src/index.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
import { listen } from "./server";
2-
import { testClipper } from "./nfp";
3-
4-
testClipper();
52

63
listen(5001);

src/nfp.ts

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Point, pointInPolygon, Polygon, polygonBounds } from "geometric";
22
import { GPU } from "gpu.js";
3-
import Shape from "@doodle3d/clipper-js";
3+
import { angleNormalize, Part, partMoveTo, partNestingBounds, partRotate, pointDistanceTo } from "./primitives";
4+
import { origin } from "./nesting";
45

56
const gpu = new GPU({
67
mode: "gpu",
@@ -20,17 +21,13 @@ export function rasterize(bounds: [Point, Point]): Point[] {
2021
return dots;
2122
}
2223

23-
export function noFitRaster(
24-
boardDots: [number, number][],
25-
stationaryDots: [number, number][],
26-
orbitingDots: [number, number][],
27-
): [number, number][] {
24+
export function noFitRaster(boardDots: Point[], stationaryDots: Point[], orbitingDots: Point[]): Point[] {
2825
const kernelFunc = gpu
2926
.createKernel(function (
30-
boardDots: [number, number][],
31-
stationaryDots: [number, number][],
32-
orbitingDots: [number, number][],
33-
orbitingDotsMinimumPoint: [number, number],
27+
boardDots: Point[],
28+
stationaryDots: Point[],
29+
orbitingDots: Point[],
30+
orbitingDotsMinimumPoint: Point,
3431
) {
3532
for (let k = 0; k < this.constants.numOrbitingDots; k++) {
3633
const x1 = orbitingDots[k][0] + boardDots[this.thread.y][0];
@@ -63,9 +60,9 @@ export function noFitRaster(
6360
return boardDots.filter((value, index) => out[index].some((x: number) => x == 1));
6461
}
6562

66-
export function rasterDifference(a: [number, number][], b: [number, number][]): [number, number][] {
63+
export function rasterDifference(a: Point[], b: Point[]): Point[] {
6764
const kernelFunc = gpu
68-
.createKernel(function (a: [number, number][], b: [number, number][]) {
65+
.createKernel(function (a: Point[], b: Point[]) {
6966
for (let k = 0; k < this.constants.numB; k++) {
7067
const x1 = b[k][0];
7168
const x2 = a[this.thread.x][0];
@@ -89,7 +86,7 @@ export function rasterDifference(a: [number, number][], b: [number, number][]):
8986
return a.filter((value, index) => out[index] == 1);
9087
}
9188

92-
export function noFitPolygon(stationaryPolygon: Polygon, orbitingPolygon: Polygon): [number, number][] {
89+
export function noFitPolygon(stationaryPolygon: Polygon, orbitingPolygon: Polygon): Polygon {
9390
const stationaryBounds = polygonBounds(stationaryPolygon);
9491
const orbitingBounds = polygonBounds(orbitingPolygon);
9592

@@ -120,28 +117,61 @@ export function noFitPolygon(stationaryPolygon: Polygon, orbitingPolygon: Polygo
120117
return noFitRaster(boardDots, stationaryDots, orbitingDots);
121118
}
122119

123-
export function testClipper() {
124-
const subjectPaths = [
125-
[
126-
{ X: 30, Y: 30 },
127-
{ X: 10, Y: 30 },
128-
{ X: 10, Y: 10 },
129-
{ X: 30, Y: 10 },
130-
],
131-
];
132-
const clipPaths = [
133-
[
134-
{ X: 20, Y: 20 },
135-
{ X: 0, Y: 20 },
136-
{ X: 0, Y: 0 },
137-
{ X: 20, Y: 0 },
138-
],
139-
];
120+
export function noFitPolygons(
121+
stationaryPartOutsideLoopExtentsPoints: Point[],
122+
orbitingPartOutsideLoopExtentsPoints: Point[],
123+
raster: boolean,
124+
): Polygon[] {
125+
if (!raster) {
126+
throw new Error("not supported");
127+
}
140128

141-
const subject = new Shape(subjectPaths, true);
142-
const clip = new Shape(clipPaths, true);
129+
// TODO
130+
}
143131

144-
const result = subject.intersect(clip);
132+
export function innerFitPolygons(
133+
stationaryPartInsideLoopExtentsPoints: Point[],
134+
orbitingPartOutsideLoopExtentsPoints: Point[],
135+
raseter: boolean,
136+
): Polygon[] {
137+
// TODO
138+
}
139+
140+
export function _noFitPolygonsAndInnerFitPolygons(
141+
stationaryPart: Part,
142+
orbitingPart: Part,
143+
raster: boolean,
144+
): { noFitPolygons: Polygon[]; innerFitPolygons: Polygon[] } {
145+
if (pointDistanceTo(partNestingBounds(stationaryPart)[0], origin) > 0.1) {
146+
throw new Error();
147+
}
148+
149+
if (pointDistanceTo(partNestingBounds(orbitingPart)[0], origin) > 0.1) {
150+
throw new Error();
151+
}
152+
153+
const noFitPolygons: Polygon[] = [];
154+
const innerFitPolygons: Polygon[] = [];
155+
156+
// TODO
157+
158+
// return {
159+
// noFitPolygons: noFitPolygons,
160+
// innerFitPolygons: innerFitPolygons,
161+
// };
162+
}
145163

146-
console.log(JSON.stringify(result));
164+
export function noFitPolygonsAndInnerFitPolygons(
165+
nestedPart: Part,
166+
notNestedPart: Part,
167+
nestingRotationInDegrees: number,
168+
raster: boolean,
169+
): { noFitPolygons: Polygon[]; innerFitPolygons: Polygon[] } {
170+
const rotation = angleNormalize(nestingRotationInDegrees);
171+
172+
return _noFitPolygonsAndInnerFitPolygons(
173+
partMoveTo(nestedPart, origin),
174+
partMoveTo(partRotate(partMoveTo(notNestedPart, origin), rotation), origin),
175+
raster,
176+
);
147177
}

src/primitives.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { Point, pointRotate } from "geometric";
2-
import { partToPartGap } from "./utils";
1+
import { Point, pointRotate, Polygon, polygonArea } from "geometric";
2+
import { clipperScale, partToPartGap, tolerance } from "./utils";
3+
import Shape from "@doodle3d/clipper-js";
4+
5+
export function pointDistanceTo(a: Point, b: Point): number {
6+
return Math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2);
7+
}
38

49
export function vectorAdd(a: [number, number], b: [number, number]): [number, number] {
510
return [a[0] + b[0], a[1] + b[1]];
@@ -14,6 +19,50 @@ export function angleNormalize(angle: number): number {
1419
return normalized < 0.0 ? 360.0 + normalized : normalized;
1520
}
1621

22+
export function polygonsToShape(polygons: Polygon[]): Shape {
23+
return new Shape(
24+
polygons.map((polygon) => polygon.map((p) => ({ X: p[0], Y: p[1] }))),
25+
true,
26+
);
27+
}
28+
29+
export function shapeToPolygons(shape: Shape): Polygon[] {
30+
return shape.paths.map((polygon) => polygon.map((p) => [p.X, p.Y]));
31+
}
32+
33+
export function polygonOffset(points: Polygon, delta: number): Polygon[] {
34+
if (!points) {
35+
return [];
36+
}
37+
38+
return shapeToPolygons(
39+
polygonsToShape([points]).offset(delta, {
40+
jointType: "jtRound",
41+
endType: "etClosedPolygon",
42+
miterLimit: 2.0,
43+
roundPrecision: tolerance * clipperScale,
44+
}),
45+
);
46+
}
47+
48+
export function polygonSimplify(points: Polygon): Polygon {
49+
if (!points) {
50+
return [];
51+
}
52+
53+
const simplifiedPolygons = shapeToPolygons(polygonsToShape([points]).simplify("pftNonZero"));
54+
55+
if (!simplifiedPolygons) {
56+
return [];
57+
}
58+
59+
return simplifiedPolygons.sort((x) => polygonArea(x, false)).reverse()[0];
60+
}
61+
62+
export function polygonClean(points: Polygon, tolerance: number): Polygon {
63+
return shapeToPolygons(polygonsToShape([points]).clean(tolerance * clipperScale))[0];
64+
}
65+
1766
export interface Entity {
1867
layer: string;
1968
nestingId: string;

0 commit comments

Comments
 (0)