code formatting

This commit is contained in:
Stewart Allen 2025-09-22 21:38:02 -04:00
commit d976461ed4
3 changed files with 139 additions and 140 deletions

View file

@ -5,59 +5,59 @@ import { clearPops, env } from "./client.js";
let alert, lastWidget; let alert, lastWidget;
export let helicalOn = false; export let helicalOn = false;
export function selectHelical() { export function selectHelical() {
if (helicalOn) { if (helicalOn) {
return helicalDone(); return helicalDone();
} }
clearPops(); clearPops();
alert = api.show.alert("analyzing surfaces...", 1000); alert = api.show.alert("analyzing surfaces...", 1000);
let cylinders = env.poppedRec.cylinders; let cylinders = env.poppedRec.cylinders;
CAM.surface_prep(false, () => { CAM.surface_prep(false, () => {
api.hide.alert(alert); api.hide.alert(alert);
alert = api.show.alert("[esc] cancels surface selection"); alert = api.show.alert("[esc] cancels surface selection");
for (let [wid, arr] of Object.entries(cylinders)) { for (let [wid, arr] of Object.entries(cylinders)) {
let widget = api.widgets.forid(wid); let widget = api.widgets.forid(wid);
if ( widget && arr?.length ) if (widget && arr?.length)
for (let faceid of arr) { for (let faceid of arr) {
CAM.cylinderToggle(widget, faceid, (faceids) => { CAM.cylinderToggle(widget, faceid, (faceids) => {
// cylinders[widget.id] = faceids; // cylinders[widget.id] = faceids;
}); });
}
}
});
helicalOn = env.hoveredOp;
helicalOn.classList.add("editing");
api.feature.on_mouse_up = (obj, ev) => {
let { face } = obj;
let min = Math.min(face.a, face.b, face.c);
let faceid = min / 3;
let widget = (lastWidget = obj.object.widget);
CAM.cylinderToggle(widget, faceid, ({ faces, error }) => {
if (error) {
api.show.alert(error, 3000);
console.log(error);
return;
}
cylinders[widget.id] = faces;
});
};
};
export function helicalDone() {
if (!(helicalOn && env.poppedRec && env.poppedRec.cylinders)) {
return;
}
let { cylinders } = env.poppedRec;
for (let wid of Object.keys(cylinders)) {
let widget = api.widgets.forid(wid);
if (widget) {
CAM.cylinderClear(widget);
} else {
delete cylinders[wid];
} }
} }
}); api.hide.alert(alert);
helicalOn = env.hoveredOp; api.feature.on_mouse_up = undefined;
helicalOn.classList.add("editing"); helicalOn.classList.remove("editing");
api.feature.on_mouse_up = (obj, ev) => { helicalOn = false;
let { face } = obj;
let min = Math.min(face.a, face.b, face.c);
let faceid = min / 3;
let widget = (lastWidget = obj.object.widget);
CAM.cylinderToggle(widget, faceid, ({ faces, error }) => {
if ( error ) {
api.show.alert(error, 3000);
console.log( error );
return;
}
cylinders[widget.id] = faces;
});
};
};
export function helicalDone(){
if (!( helicalOn && env.poppedRec && env.poppedRec.cylinders )) {
return;
}
let { cylinders } = env.poppedRec;
for (let wid of Object.keys(cylinders)) {
let widget = api.widgets.forid(wid);
if (widget) {
CAM.cylinderClear(widget);
} else {
delete cylinders[wid];
}
}
api.hide.alert(alert);
api.feature.on_mouse_up = undefined;
helicalOn.classList.remove("editing");
helicalOn = false;
}; };

View file

@ -510,8 +510,7 @@ export async function traces(settings, widget) {
widget.traces = polylines; widget.traces = polylines;
return true; return true;
}; }
/** /**
* Returns an array of arrays of perpindicular triangles in the mesh. * Returns an array of arrays of perpindicular triangles in the mesh.
@ -523,110 +522,109 @@ export async function traces(settings, widget) {
* @param {object} opts - options object * @param {object} opts - options object
* @return {array} - array of arrays of triangle data * @return {array} - array of arrays of triangle data
*/ */
export async function cylinders(settings, widget, opts){ export async function cylinders(settings, widget, opts) {
let { } = opts ?? {};
let {} = opts ?? {} let { array: verts } = widget.mesh.geometry.attributes.position;
let perpTriangles = [];
let {array:verts} = widget.mesh.geometry.attributes.position
let perpTriangles = []
//iterate over all triangles //iterate over all triangles
for(let i = 0; i < verts.length; i+=9){ for (let i = 0; i < verts.length; i += 9) {
let a = [verts[i], verts[i+1], verts[i+2]], let a = [verts[i], verts[i + 1], verts[i + 2]],
b = [verts[i+3], verts[i+4], verts[i+5]], b = [verts[i + 3], verts[i + 4], verts[i + 5]],
c = [verts[i+6], verts[i+7], verts[i+8]]; c = [verts[i + 6], verts[i + 7], verts[i + 8]];
//calculate normal //calculate normal
let normal = new THREE.Vector3(a[0]-b[0], a[1]-b[1], a[2]-b[2]) let normal = new THREE.Vector3(a[0] - b[0], a[1] - b[1], a[2] - b[2])
.cross(new THREE.Vector3(b[0]-c[0], b[1]-c[1], b[2]-c[2])) .cross(new THREE.Vector3(b[0] - c[0], b[1] - c[1], b[2] - c[2]))
.normalize() .normalize();
// if perpindicular normal, and at least 2 Zs are the same // if perpindicular normal, and at least 2 Zs are the same
if(normal.z.round(5) == 0 && ! (a[2] != b[2] && b[2] != c[2])){ if (normal.z.round(5) == 0 && !(a[2] != b[2] && b[2] != c[2])) {
let minZ = Math.min(a[2], b[2], c[2]), let minZ = Math.min(a[2], b[2], c[2]),
maxZ = Math.max(a[2], b[2], c[2]); maxZ = Math.max(a[2], b[2], c[2]);
if(minZ == maxZ){ // all Zs are the same indicated malformed geometry if (minZ == maxZ) { // all Zs are the same indicated malformed geometry
continue; continue;
} }
perpTriangles.push({...[a,b,c], normal,minZ,maxZ,i:index}) perpTriangles.push({ ...[a, b, c], normal, minZ, maxZ, i: index });
} }
} }
//map where zmax, zmin -> triangleData //map where zmax, zmin -> triangleData
let cylinderTriangles = new Map() let cylinderTriangles = new Map();
for(let t of perpTriangles){ for (let t of perpTriangles) {
let hash = `${t.minZ.round(5)},${t.maxZ.round(5)}` let hash = `${t.minZ.round(5)},${t.maxZ.round(5)}`;
if(!cylinderTriangles.has(hash)){ if (!cylinderTriangles.has(hash)) {
cylinderTriangles.set(hash,[]) cylinderTriangles.set(hash, []);
} }
cylinderTriangles.get(hash).push(t) cylinderTriangles.get(hash).push(t);
} }
return Array.from(cylinderTriangles.values()) return Array.from(cylinderTriangles.values());
} }
/**
/** * Find all triangles that are part of the same cylinder as the given triangle
* Find all triangles that are part of the same cylinder as the given triangle * @param {Widget} widget - widget object
* @param {Widget} widget - widget object * @param {number} face - index of face in triangle vertex data
* @param {number} face - index of face in triangle vertex data * @return {array} - array of all triangle data that belong to the same cylinder
* @return {array} - array of all triangle data that belong to the same cylinder * @requires surface_prep must be called first
* @requires surface_prep must be called first */
*/
export function cylinder_find (widget, face){ export function cylinder_find (widget, face){
CAM.surface_prep(widget,false); CAM.surface_prep(widget,false);
return widget.tool.findCylinderSurface(face); return widget.tool.findCylinderSurface(face);
} }
export function cylinder_poly_find(widget, face){ export function cylinder_poly_find(widget, face) {
let faces = cylinder_find(widget, face); let faces = cylinder_find(widget, face);
let vert = widget.getGeoVertices({ unroll: true, translate: true }).map(v => v.round(4)); let vert = widget.getGeoVertices({ unroll: true, translate: true }).map(v => v.round(4));
let slicer = new cam_slicer(widget,{}) let slicer = new cam_slicer(widget, {});
let opts = { let firstOffset = faces[0] * 9;
dedup:false, let [x1, y1, z1, x2, y2, z2, x3, y3, z3] = Array.from(vert.subarray(firstOffset, firstOffset + 9));
edges: false, let zs = [z1, z2, z3].map(z => z.round(5));
over:true
}
let firstOffset = faces[0]*9
let [x1,y1,z1,x2,y2,z2,x3,y3,z3]= Array.from(vert.subarray(firstOffset,firstOffset+9))
let zs = [z1,z2,z3].map(z => z.round(5))
let zmin = Math.min(...zs); let zmin = Math.min(...zs);
let zmax = Math.max(...zs); let zmax = Math.max(...zs);
let zmid = (zmin+zmax)/2 let zmid = (zmin + zmax) / 2;
let cylVerts = new Float32Array(faces.length*9) let cylVerts = new Float32Array(faces.length * 9);
let opts = {
dedup: false,
edges: false,
over: true
};
let i = 0 let i = 0
//for each cylinder face index //for each cylinder face index
for(let index of faces){ for (let index of faces) {
let off = index*9 let off = index * 9;
//copy the 9 triangle vertices floats in //copy the 9 triangle vertices floats in
for(let j = 0;j < 9;j++){ for (let j = 0; j < 9; j++) {
cylVerts[i] = vert[off+j] cylVerts[i] = vert[off + j];
i++ i++;
} }
} }
//slice the poly at the midpoint //slice the poly at the midpoint
let poly = slicer.sliceZ(zmid, cylVerts,opts)?.polys?.at(0) let poly = slicer.sliceZ(zmid, cylVerts, opts)?.polys?.at(0);
if(!poly) throw "slicing returned no poly" if (!poly) throw "slicing returned no poly";
let circular = poly.circularity() > 0.98; let circular = poly.circularity() > 0.98;
//throw error if not circular //throw error if not circular
if(!circular) throw "faces must be circular" if (!circular) throw "faces must be circular";
//calculate circle properties //calculate circle properties
let area = poly.area(), let area = poly.area(),
diam = Math.sqrt(area / Math.PI)* 2, diam = Math.sqrt(area / Math.PI) * 2,
center = poly.calcCircleCenter(); center = poly.calcCircleCenter();
//find direction using normal to center point //find direction using normal to center point
let point = newPoint(x1, y1, z1), let point = newPoint(x1, y1, z1),
delta = point.setZ(center.z).sub(center), delta = point.setZ(center.z).sub(center),
normal = new THREE.Vector3(x1-x2, y1-y2, z1-z2) normal = new THREE.Vector3(x1 - x2, y1 - y2, z1 - z2)
.cross(new THREE.Vector3(x2-x3, y2-y3, z2-z3)), .cross(new THREE.Vector3(x2 - x3, y2 - y3, z2 - z3)),
dotProd = normal.dot(delta), dotProd = normal.dot(delta),
interior = dotProd < 0 interior = dotProd < 0
return {faces, zmin, zmax, poly, circular, area, diam, center,interior} return { faces, zmin, zmax, poly, circular, area, diam, center, interior }
} }
/** /**

View file

@ -241,13 +241,12 @@ class MeshTool {
}; };
} }
/** /**
* Retrieves the adjacent faces for a given face index. * Retrieves the adjacent faces for a given face index.
* *
* @param {number} face - The index of the face for which adjacent faces are to be found. * @param {number} face - The index of the face for which adjacent faces are to be found.
* @returns {number[]} An array of face indices that are adjacent to the given face. * @returns {number[]} An array of face indices that are adjacent to the given face.
*/ */
getAdjacentFaces(face) { getAdjacentFaces(face) {
const { faces, sides } = this.getIndex(); const { faces, sides } = this.getIndex();
const foff = face * 6; const foff = face * 6;
@ -319,31 +318,31 @@ class MeshTool {
* 3. Filtering faces with normals perpendicular to Z axis * 3. Filtering faces with normals perpendicular to Z axis
* 4. Recursively adding adjacent faces with the same Z values and normal perpendicular to Z axis * 4. Recursively adding adjacent faces with the same Z values and normal perpendicular to Z axis
*/ */
findCylinderSurface(face){ findCylinderSurface(face) {
face = Number(face) face = Number(face);
const radianTolerance = 8 * (Math.PI / 180);
const radianTolerance = 8 * (Math.PI/180);
const vertexTolerance = 1e-4; const vertexTolerance = 1e-4;
//helper function
const dissimilar = (a,b,c) => Math.abs(a-b) > vertexTolerance && // helper function
Math.abs(b-c) > vertexTolerance && const dissimilar = (a, b, c) => Math.abs(a - b) > vertexTolerance &&
Math.abs(a-c) > vertexTolerance; Math.abs(b - c) > vertexTolerance &&
Math.abs(a - c) > vertexTolerance;
let found = {}, let found = {},
out = [face], out = [face],
{vertices} = this, { vertices } = this,
{faces} = this.getIndex(), { faces } = this.getIndex(),
faceOffset = face*9, faceOffset = face * 9,
zs = [2,5,8].map(i => vertices[faceOffset+i].round(5)), //get zs from face vertices zs = [2, 5, 8].map(i => vertices[faceOffset + i].round(5)), //get zs from face vertices
lowZ = Math.min(zs), lowZ = Math.min(zs),
highZ = Math.max(zs), highZ = Math.max(zs),
checked = {}, checked = {},
check = [face]; check = [face];
//check for errors, and throw if found // check for errors, and throw if found
if(dissimilar(...zs)){ if (dissimilar(...zs)) {
throw `face must have only 2 Z values. found: ${zs.join(", ")}` throw `face must have only 2 Z values. found: ${zs.join(", ")}`
}else if(Math.abs( faces[face * 6 + 2] > 1e-6 )){ } else if (Math.abs(faces[face * 6 + 2] > 1e-6)) {
throw "face's normal must be perpendicular to Z axis" throw "face's normal must be perpendicular to Z axis"
} }
@ -354,9 +353,10 @@ class MeshTool {
const vroot = face * 9 const vroot = face * 9
// filter faces to those perpendicular to +z axis // filter faces to those perpendicular to +z axis
if ( Math.abs( faces[froot + 2] > 1e-6 )) continue; if (Math.abs(faces[froot + 2] > 1e-6)) continue;
//filter faces with verts don't share the z values of the first face
if( // filter faces with verts don't share the z values of the first face
if (
!(vertices[vroot + 2] !== lowZ || vertices[vroot + 2] !== highZ) && !(vertices[vroot + 2] !== lowZ || vertices[vroot + 2] !== highZ) &&
!(vertices[vroot + 5] !== lowZ || vertices[vroot + 5] !== highZ) && !(vertices[vroot + 5] !== lowZ || vertices[vroot + 5] !== highZ) &&
!(vertices[vroot + 8] !== lowZ || vertices[vroot + 8] !== highZ) !(vertices[vroot + 8] !== lowZ || vertices[vroot + 8] !== highZ)
@ -369,7 +369,7 @@ class MeshTool {
} }
const aroot = f * 6; const aroot = f * 6;
let sum = 0; let sum = 0;
for (let i=0; i<3; i++) { for (let i = 0; i < 3; i++) {
sum += Math.pow(faces[froot + i] - faces[aroot + i], 2); sum += Math.pow(faces[froot + i] - faces[aroot + i], 2);
} }
const fn = Math.sqrt(sum); const fn = Math.sqrt(sum);
@ -381,6 +381,7 @@ class MeshTool {
} }
} }
} }
return out; return out;
} }