mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-07 00:45:08 +01:00
129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
import Vector from 'math/vector';
|
|
import ClipperLib from 'clipper-lib';
|
|
import libtess from 'libtess'
|
|
import tessellateSurface from 'geom/surfaces/surfaceTess';
|
|
|
|
export default function A(face) {
|
|
return tessellateLoopsOnSurface(face.surface, face.loops, loop => loop.halfEdges, seg => seg.edge.curve, seg => seg.inverted)
|
|
}
|
|
|
|
export function tessellateLoopsOnSurface(surface, curveContours, getLoop, getCurve, isInverted) {
|
|
|
|
const loops = [];
|
|
for (const contour of curveContours) {
|
|
const pipLoop = [];
|
|
loops.push(pipLoop);
|
|
for (const segment of getLoop(contour)) {
|
|
const curvePoints = getCurve(segment).tessellate();
|
|
if (isInverted(segment)) {
|
|
curvePoints.reverse();
|
|
}
|
|
curvePoints.pop();
|
|
for (const point of curvePoints) {
|
|
const wp = surface.workingPoint(point);
|
|
pipLoop.push(wp);
|
|
}
|
|
}
|
|
}
|
|
|
|
const tess = tessellateSurface(surface.impl);
|
|
const nurbsTriangles = tess.faces.map(f => f.map(i => surface.createWorkingPoint(tess.uvs[i], Vector.fromData(tess.points[i]))));
|
|
|
|
const paths = clip(nurbsTriangles, loops);
|
|
|
|
const triangles = tessPaths(paths);
|
|
|
|
const out = convertPoints(triangles, p => surface.workingPointTo3D(p) );
|
|
// __DEBUG__.AddPointPolygons(out, 0x00ffff);
|
|
return out;
|
|
}
|
|
|
|
function convertPoints(paths, converter) {
|
|
return paths.map( path => path.map(p => converter(p) ))
|
|
}
|
|
|
|
function clip(triangles, loops) {
|
|
// __DEBUG__.AddPointPolygons(triangles, 0xff00ff);
|
|
// __DEBUG__.AddPointPolygons(loops, 0xffffff);
|
|
|
|
const scale = 1e3 ;// multiplying by BrepSurface.WORKING_POINT_SCALE_FACTOR gives 1e6
|
|
|
|
|
|
const clip_paths = convertPoints(loops, p => ({X:p.x, Y:p.y}) );
|
|
ClipperLib.JS.ScaleUpPaths(clip_paths, scale);
|
|
|
|
let out = [];
|
|
|
|
for (const tr of triangles) {
|
|
const cpr = new ClipperLib.Clipper();
|
|
const subj_paths = convertPoints([tr], p => ({X:p.x, Y:p.y}) );
|
|
|
|
ClipperLib.JS.ScaleUpPaths(subj_paths, scale);
|
|
|
|
|
|
cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true); // true means closed path
|
|
cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true);
|
|
|
|
const solution_paths = new ClipperLib.Paths();
|
|
const succeeded = cpr.Execute(ClipperLib.ClipType.ctIntersection, solution_paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);
|
|
ClipperLib.JS.ScaleUpPaths(solution_paths, 1.0/scale);
|
|
solution_paths.forEach(p => out.push(p));
|
|
}
|
|
|
|
out = convertPoints(out, p => new Vector(p.X, p.Y, 0) );
|
|
return out;
|
|
}
|
|
|
|
|
|
function tessPaths(paths) {
|
|
|
|
function vertexCallback(data, out) {
|
|
out.push(data);
|
|
}
|
|
function combinecallback(coords, data, weight) {
|
|
}
|
|
function edgeCallback(flag) {
|
|
}
|
|
|
|
const tessy = new libtess.GluTesselator();
|
|
// tessy.gluTessProperty(libtess.gluEnum.GLU_TESS_WINDING_RULE, libtess.windingRule.GLU_TESS_WINDING_POSITIVE);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_VERTEX_DATA, vertexCallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_BEGIN, begincallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_ERROR, errorcallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_COMBINE, combinecallback);
|
|
tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_EDGE_FLAG, edgeCallback);
|
|
|
|
tessy.gluTessNormal(0, 0, 1);
|
|
|
|
const vertices = [];
|
|
tessy.gluTessBeginPolygon(vertices);
|
|
|
|
for (const path of paths) {
|
|
tessy.gluTessBeginContour();
|
|
for (const p of path) {
|
|
tessy.gluTessVertex([p.x, p.y, 0], p);
|
|
}
|
|
tessy.gluTessEndContour();
|
|
}
|
|
tessy.gluTessEndPolygon();
|
|
|
|
const triangled = [];
|
|
|
|
for (let i = 0; i < vertices.length; i += 3 ) {
|
|
const a = vertices[i];
|
|
const b = vertices[i + 1];
|
|
const c = vertices[i + 2];
|
|
triangled.push([a, b, c]);
|
|
}
|
|
return triangled;
|
|
}
|
|
|
|
function begincallback(type) {
|
|
if (type !== libtess.primitiveType.GL_TRIANGLES) {
|
|
console.log('expected TRIANGLES but got type: ' + type);
|
|
}
|
|
}
|
|
function errorcallback(errno) {
|
|
console.log('tessellation error');
|
|
console.log('error number: ' + errno);
|
|
}
|