Skip to content

Commit

Permalink
adding radial distance resampling technique
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjacobson committed Sep 5, 2024
1 parent 5c52977 commit 36fc37a
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 8 deletions.
10 changes: 5 additions & 5 deletions examples/basicExample.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
[this.polyline, this.stitchLength, this.ropeWidth] = [polyline, stitchLength, ropeWidth];
}
getStitches(pixelsPerUnit) {
let resampled = this.polyline.getResampled(pixelsPerUnit * this.stitchLength).vertices;
let resampled = this.polyline.getRadialDistanceResampled(pixelsPerUnit * this.stitchLength).vertices;
if (this.polyline.isClosed) resampled.push(resampled[0]);
let [middleRope, leftRope, rightRope] = [[], [], [], []];
for (let i = 0, stitchCount = 0; i < resampled.length; i++) {
Expand Down Expand Up @@ -168,7 +168,7 @@
/* useful for computationally intensive patterns */
window.addEventListener("resize", Stitch.Browser.Utils.debounce(() => {
svg.remove();
let svg = Stitch.Graphics.getSvg(pattern, window.innerWidth, window.innerHeight);
svg = Stitch.Graphics.getSvg(pattern, window.innerWidth, window.innerHeight);
svg.setAttribute('style', 'margin: auto; position: absolute; inset: 0;');
document.body.append(svg);
}, 10));
Expand Down Expand Up @@ -203,11 +203,11 @@
if (e.code === "KeyD") {
modal.open();
} else if (e.code === "Digit1") {
Stitch.IO.write(pattern, Stitch.Units.inToMm(1.75), Stitch.Units.inToMm(1), `basicExampleSmall.dst`);
Stitch.IO.write(pattern, Stitch.Math.Utils.inToMm(1.75), Stitch.Math.Utils.inToMm(1), `basicExampleSmall.dst`);
} else if (e.code === "Digit2") {
Stitch.IO.write(pattern, Stitch.Units.inToMm(3.5), Stitch.Units.inToMm(2), `basicExampleMedium.dst`);
Stitch.IO.write(pattern, Stitch.Math.Utils.inToMm(3.5), Stitch.Math.Utils.inToMm(2), `basicExampleMedium.dst`);
} else if (e.code === "Digit3") {
Stitch.IO.write(pattern, Stitch.Units.inToMm(7), Stitch.Units.inToMm(4), `basicExampleLarge.dst`);
Stitch.IO.write(pattern, Stitch.Math.Utils.inToMm(7), Stitch.Math.Utils.inToMm(4), `basicExampleLarge.dst`);
} else {
console.log(`Unmapped key pressed: Code ${e.code}.`);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@stitchables/stitchjs",
"license": "MIT",
"version": "0.0.5",
"version": "0.0.6",
"main": "dist/stitch.js",
"module": "dist/stitch.mjs",
"types": "dist/stitch.d.ts",
Expand Down
48 changes: 48 additions & 0 deletions src/Math/Polyline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,54 @@ export class Polyline {
}
}
}
// https://www.codeproject.com/Articles/114797/Polyline-Simplification#headingRD
getRadialDistanceResampled(radius: number): Polyline {
const result = new Polyline(this.isClosed);
let key = this.vertices[0];
result.addVertex(key.x, key.y);

function getNext(nextKey: Vector, prev: Vector): Vector | undefined {
if (key.distance(nextKey) > radius) {
const intersections = Utils.lineSegmentCircleIntersection(
prev,
nextKey,
key,
radius,
);
if (intersections.length === 1) {
const start = intersections[0];
const distance = start.distance(nextKey);
if (distance > radius) {
result.addVertex(start.x, start.y);
const countSamples = Math.floor(distance / radius) - 1;
for (let j = 0; j < countSamples; j++) {
const w = Utils.map(j + 1, 0, countSamples, 0, 1);
const p = start.lerp(nextKey, w);
result.addVertex(p.x, p.y);
}
}
}
return nextKey;
}
return undefined;
}

for (
let i = 1;
i < (this.isClosed ? this.vertices.length + 1 : this.vertices.length);
i++
) {
const nextKey = getNext(
this.vertices[i % this.vertices.length],
this.vertices[i - 1],
);
if (nextKey && i < this.vertices.length) {
key = nextKey;
result.addVertex(key.x, key.y);
}
}
return result;
}
translate(x: number, y: number): Polyline {
const translatePolyline = new Polyline(this.isClosed);
for (const vertex of this.vertices)
Expand Down
43 changes: 43 additions & 0 deletions src/Math/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,49 @@ export const Utils = {
Math.abs(v.y - m * v.x - b) / Math.sqrt(m * m + 1),
);
},
lineSegmentCircleIntersection(
start: Vector,
end: Vector,
center: Vector,
radius: number,
) {
// Translate the problem so the circle is centered at the origin
const dx = end.x - start.x;
const dy = end.y - start.y;
const fx = start.x - center.x;
const fy = start.y - center.y;

// Coefficients for the quadratic equation (t^2 * A + t * B + C = 0)
const A = dx * dx + dy * dy;
const B = 2 * (fx * dx + fy * dy);
const C = fx * fx + fy * fy - radius * radius;

// Discriminant
const discriminant = B * B - 4 * A * C;

if (discriminant < 0) {
// No intersection
return [];
}

// Calculate the two possible solutions for t
const t1 = (-B + Math.sqrt(discriminant)) / (2 * A);
const t2 = (-B - Math.sqrt(discriminant)) / (2 * A);

const points: Vector[] = [];

// Check if t1 is within the bounds of the line segment
if (t1 >= 0 && t1 <= 1) {
points.push(new Vector(start.x + t1 * dx, start.y + t1 * dy));
}

// Check if t2 is within the bounds of the line segment
if (t2 >= 0 && t2 <= 1) {
points.push(new Vector(start.x + t2 * dx, start.y + t2 * dy));
}

return points;
},
closestPointsOnSegments: function (
p1: Vector,
p2: Vector,
Expand Down
4 changes: 3 additions & 1 deletion src/Runs/Run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export class Run implements IRun {
this.density = density;
}
getStitches(pixelsPerMm: number): Vector[] {
const resampled = this.polyline.getResampled(pixelsPerMm * this.density).vertices;
const resampled = this.polyline.getRadialDistanceResampled(
pixelsPerMm * this.density,
).vertices;
if (this.polyline.isClosed) return [...resampled, resampled[0]];
return resampled;
}
Expand Down
4 changes: 3 additions & 1 deletion src/Runs/Satin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export class Satin {
[this.polyline, this.widthPx, this.densityMm] = [polyline, widthPx, densityMm];
}
getStitches(pixelsPerMm: number) {
const resampled = this.polyline.getResampled(pixelsPerMm * this.densityMm).vertices;
const resampled = this.polyline.getRadialDistanceResampled(
pixelsPerMm * this.densityMm,
).vertices;
if (this.polyline.isClosed) resampled.push(resampled[0]);
const stitches = [] as Vector[];
for (let i = 0; i < resampled.length; i++) {
Expand Down

0 comments on commit 36fc37a

Please sign in to comment.