plot = (model, P, params) => {
const { facets, segments, points } = model;
const { cos, sin } = Math;
const { cos: cosf, culling, revert, hatching } = params;
const facetPts = ({ segments: [s1, s2] }) => {
const [[p1, p2], [pa, pb]] = [s1.pts, s2.pts];
return [p1, p2, pa == p1 || pa == p2 ? pb : pa];
};
const dist = (facet) => {
const [p1, p2, p3] = facetPts(facet);
const [x1, y1, z1] = p1;
const [x2, y2, z2] = p2;
const [x3, y3, z3] = p3;
const point = [(x1 + x2 + x3) / 3, (y1 + y2 + y3) / 3, (z1 + z2 + z3) / 3];
return P.distance(point);
};
const plot = Plot();
const pts2d = new Map(
points.map((pt) => {
const [x, y] = P.project(pt);
return [pt, [x, -y]];
})
);
const polygons = new Polygons();
const drawn = new Set();
const addSegIfNotDrawn = (polygon, segId) => {
if (!drawn.has(segId)) {
const { facets, pts, dot } = segId;
if (
!facets[1] ||
!facets[0].isVisible ||
!facets[1].isVisible ||
dot <= cosf
) {
polygon.addSegments(pts2d.get(pts[0]), pts2d.get(pts[1]));
drawn.add(segId);
}
}
};
let pos = [0, 0];
const vec = ([x1, y1], [x2, y2]) => [x2 - x1, y2 - y1];
facets.forEach(
(facet) =>
(facet.isVisible = P.visible(facet.segments[0].pts[0], facet.normal))
);
facets
.filter(
(facet) => !culling || (revert ? !facet.isVisible : facet.isVisible)
)
.map((facet) => Object.assign(facet, { dist: dist(facet) }))
.sort((f1, f2) => f1.dist - f2.dist)
.forEach((facet, i) => {
const [p1, p2, p3] = facetPts(facet);
if (culling) {
const polygon = polygons.create();
polygon.addPoints(pts2d.get(p1), pts2d.get(p2), pts2d.get(p3));
facet.segments.map((s) => addSegIfNotDrawn(polygon, s));
if (hatching) {
const cos = m4.dot(facet.normal, hatching);
if (cos > 0.75) polygon.addHatching(Math.PI / 4, 0.01);
else if (cos > 0.5) polygon.addHatching(Math.PI / 4, 0.02);
}
polygons.draw(plot, polygon, true);
} else {
plot.move(...vec(pos, (pos = pts2d.get(p1))));
plot.draw(...vec(pos, (pos = pts2d.get(p2))));
plot.draw(...vec(pos, (pos = pts2d.get(p3))));
plot.draw(...vec(pos, (pos = pts2d.get(p1))));
}
});
return plot;
}