<div class="preview">
<p>2D straight skeleton after post processing preview</p>
<canvas id="canvas2d"></canvas>
</div>
import { Vector2 } from "https://esm.sh/three";
// Result of the skeleton and skeletonBox get on previous codepen https://codepen.io/TANK2003/pen/NPKvOqM
const skeleton = {
vertices: [
[259521.140625, 6253168, 0],
[259606.34375, 6253192.5, 0],
[259590.5625, 6253248, 0],
[259505.3125, 6253223.5, 0],
[259570.71875, 6253212.5, 28.852020263671875],
[259540.953125, 6253203.5, 28.85428237915039]
],
polygons: [
[0, 5, 3],
[1, 4, 5, 0],
[2, 4, 1],
[3, 5, 4, 2]
]
};
const skeletonBox = {
maxX: 259606.34375,
maxY: 6253248,
minX: 259505.3125,
minY: 6253168
};
export class StraightSkeletonResult {
vertices: Vector2[];
polygons: {
vertices: Vector2[];
edgeStart: Vector2;
edgeEnd: Vector2;
}[];
constructor(source) {
this.vertices = source.vertices.map((v) => new Vector2(v[0], v[1]));
this.polygons = source.polygons.map((p) => {
const vertices = p.map((v) => this.vertices[v]);
return {
vertices: vertices,
edgeStart: vertices[vertices.length - 1],
edgeEnd: vertices[0]
};
});
}
}
const skeletonResult = new StraightSkeletonResult(skeleton);
const draw2d = (skeletonBox, skeletonResult) => {
// 2D canvas
const canvas2d = document.getElementById("canvas2d");
const ctx = canvas2d.getContext("2d");
canvas2d.width = canvas2d.clientWidth * window.devicePixelRatio;
canvas2d.height = canvas2d.clientHeight * window.devicePixelRatio;
ctx.fillStyle = "#eee";
ctx.fillRect(0, 0, canvas2d.width, canvas2d.height);
const padding = 15 * window.devicePixelRatio;
const scale = Math.min(
(canvas2d.width - padding * 2) / (skeletonBox.maxX - skeletonBox.minX),
(canvas2d.height - padding * 2) / (skeletonBox.maxY - skeletonBox.minY)
);
const offsetX =
(canvas2d.width - (skeletonBox.maxX - skeletonBox.minX) * scale) / 2;
const offsetY =
(canvas2d.height - (skeletonBox.maxY - skeletonBox.minY) * scale) / 2;
ctx.strokeStyle = "#000";
ctx.lineWidth = window.devicePixelRatio;
ctx.fillStyle = "#ffb6e9";
for (const polygon of skeletonResult.polygons) {
ctx.beginPath();
for (let i = 0; i < polygon.vertices.length; i++) {
const vertex = polygon.vertices[i];
const x = (vertex.x - skeletonBox.minX) * scale + offsetX;
const y = (vertex.y - skeletonBox.minY) * scale + offsetY;
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
}
ctx.closePath();
ctx.stroke();
ctx.fill();
}
};
for (let i = 0; i < skeletonResult.polygons.length; i++) {
const polygon = skeletonResult.polygons[i];
// Pour les polygone roses (ceux dont on doit conserver uniquement les sommets de fins et de debut)
// On recherchera les polygones rouges du skeleton adjacents à leurs extrémités
if (polygon.vertices.length === 3) {
// Polygone de notre skeleton adjacent au sommet du debut
const prevPolygon = skeletonResult.polygons.find(
(p) => p.edgeEnd.equals(polygon.edgeStart) && p.vertices.length > 3
);
// Polygone de notre skeleton adjacent au sommet de fin
const nextPolygon = skeletonResult.polygons.find(
(p) => p.edgeStart.equals(polygon.edgeEnd) && p.vertices.length > 3
);
if (prevPolygon && nextPolygon) {
// Projection des polygones rouges adjacents à notre polygone rose
// Le seul sommet de notre polygone rose qui est ni sa fin, ni son debut
const extrudedPoint = polygon.vertices.find((p) => {
return !p.equals(polygon.edgeStart) && !p.equals(polygon.edgeEnd);
});
// Le sommet de nos polygones rouges qui sont à projeter
const prevPolygonExtrudedPoint = prevPolygon.vertices.find((v) =>
v.equals(extrudedPoint)
);
const nextPolygonExtrudedPoint = nextPolygon.vertices.find((v) =>
v.equals(extrudedPoint)
);
// Le sommet situé au milieu du segment[sommet debut, sommet fin] de notre polygone rose
// Qui correspond au sommet souhaité pour notre projection
const middle = new Vector2()
.addVectors(polygon.edgeStart, polygon.edgeEnd)
.multiplyScalar(0.5);
prevPolygonExtrudedPoint.x = nextPolygonExtrudedPoint.x = middle.x;
prevPolygonExtrudedPoint.y = nextPolygonExtrudedPoint.y = middle.y;
// Projection faite, on conserve uniquement les sommets de debut et fin de notre polygone rose
polygon.vertices = [];
}
}
}
draw2d(skeletonBox, skeletonResult);
console.log(JSON.stringify(skeletonResult));
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.