157 lines
4.7 KiB
JavaScript
157 lines
4.7 KiB
JavaScript
'use strict';
|
|
|
|
var poly3 = require('@jscad/modeling/src/geometries/poly3');
|
|
var booleans = require('@jscad/modeling/src/operations/booleans');
|
|
|
|
/**
|
|
* @param compart true => t2 , false => t1
|
|
* @returns 索引
|
|
*/
|
|
function Max(arr, compart)
|
|
{
|
|
let best = arr[0];
|
|
let bestIndex = 0;
|
|
for (let i = 1; i < arr.length; i++) {
|
|
let t1 = arr[i];
|
|
if (compart(best, t1)) {
|
|
best = t1;
|
|
bestIndex = i;
|
|
}
|
|
}
|
|
return bestIndex;
|
|
}
|
|
|
|
/** Epsilon used during determination of near zero distances.
|
|
* @default
|
|
*/
|
|
const EPS = 5e-2;
|
|
|
|
// //////////////////////////////
|
|
// tolerance: The maximum difference for each parameter allowed to be considered a match
|
|
class FuzzyFactory
|
|
{
|
|
constructor(numdimensions = 3, tolerance = EPS)
|
|
{
|
|
this.lookuptable = {};
|
|
this.multiplier = 1.0 / tolerance;
|
|
}
|
|
// let obj = f.lookupOrCreate([el1, el2, el3], function(elements) {/* create the new object */});
|
|
// Performs a fuzzy lookup of the object with the specified elements.
|
|
// If found, returns the existing object
|
|
// If not found, calls the supplied callback function which should create a new object with
|
|
// the specified properties. This object is inserted in the lookup database.
|
|
lookupOrCreate(els, object)
|
|
{
|
|
let hash = "";
|
|
let multiplier = this.multiplier;
|
|
for (let el of els) {
|
|
let valueQuantized = Math.round(el * multiplier);
|
|
hash += valueQuantized + "/";
|
|
}
|
|
if (hash in this.lookuptable)
|
|
return this.lookuptable[hash];
|
|
else {
|
|
let hashparts = els.map(el =>
|
|
{
|
|
let q0 = Math.floor(el * multiplier);
|
|
let q1 = q0 + 1;
|
|
return ["" + q0 + "/", "" + q1 + "/"];
|
|
});
|
|
let numelements = els.length;
|
|
let numhashes = 1 << numelements;
|
|
for (let hashmask = 0; hashmask < numhashes; ++hashmask) {
|
|
let hashmaskShifted = hashmask;
|
|
hash = "";
|
|
hashparts.forEach(hashpart =>
|
|
{
|
|
hash += hashpart[hashmaskShifted & 1];
|
|
hashmaskShifted >>= 1;
|
|
});
|
|
this.lookuptable[hash] = object;
|
|
}
|
|
return object;
|
|
}
|
|
}
|
|
}
|
|
|
|
//并集path2dCsgs 差集 删除小面积结果
|
|
function CSGSubtract(geom, path2dCsgs)
|
|
{
|
|
let gemUnion = path2dCsgs[0];
|
|
for (let i = 1; i < path2dCsgs.length; i++)
|
|
gemUnion = booleans.union(gemUnion, path2dCsgs[i]);
|
|
let newGeom = booleans.subtract(geom, gemUnion);
|
|
//删除小面积(只留一个)
|
|
{
|
|
let fuzz = new FuzzyFactory;
|
|
let vmap = new Map;
|
|
for (let poly of newGeom.polygons) {
|
|
for (let v of poly.vertices) {
|
|
let key = fuzz.lookupOrCreate(v, v);
|
|
let arr = vmap.get(key);
|
|
if (!arr) {
|
|
arr = [];
|
|
vmap.set(key, arr);
|
|
}
|
|
arr.push(poly);
|
|
v["__key__"] = key;
|
|
}
|
|
}
|
|
let polys = newGeom.polygons.concat();
|
|
let polyGroups = [];
|
|
let calcs = new Set;
|
|
while (polys.length) {
|
|
let poly1 = polys.pop();
|
|
calcs.add(poly1);
|
|
let polyGroup = [poly1];
|
|
polyGroups.push(polyGroup);
|
|
for (let i = 0; i < polyGroup.length; i++) {
|
|
let poly = polyGroup[i];
|
|
for (let v of poly.vertices) {
|
|
let key = v["__key__"];
|
|
let arr = vmap.get(key);
|
|
for (let vpoly of arr) {
|
|
if (calcs.has(vpoly))
|
|
continue;
|
|
calcs.add(vpoly);
|
|
polyGroup.push(vpoly);
|
|
}
|
|
}
|
|
}
|
|
// arrayRemoveIf(polys, poly => !calcs.has(poly)); //加上这个无法提高性能
|
|
}
|
|
let areas = polyGroups.map(polys =>
|
|
{
|
|
let area = 0;
|
|
for (let poly of polys)
|
|
area += poly3.measureArea(poly);
|
|
return area;
|
|
});
|
|
let maxIndex = Max(areas, (t1, t2) => t2 > t1);
|
|
newGeom.polygons = polyGroups[maxIndex];
|
|
}
|
|
return newGeom;
|
|
}
|
|
|
|
addEventListener("message", e =>
|
|
{
|
|
const [path2dCsgs, geom] = e.data;
|
|
try {
|
|
const newGeom = CSGSubtract(geom, path2dCsgs);
|
|
postMessage({
|
|
status: 0,
|
|
geom: newGeom
|
|
});
|
|
}
|
|
catch (error) {
|
|
postMessage({
|
|
status: 1,
|
|
error
|
|
});
|
|
}
|
|
});
|
|
var CSGSubtract_worker = {};
|
|
|
|
module.exports = CSGSubtract_worker;
|
|
//# sourceMappingURL=CSGSubtract.worker.cjs.map
|