diff --git a/web/app/cad/craft/revolve/revolveOperation.js b/web/app/cad/craft/revolve/revolveOperation.js index 66634356..763226ed 100644 --- a/web/app/cad/craft/revolve/revolveOperation.js +++ b/web/app/cad/craft/revolve/revolveOperation.js @@ -1,5 +1,7 @@ import RevolveForm from './RevolveForm'; import schema from './schema'; +import {createRevolvePreviewGeomProvider, revolvePreviewGeomProvider} from './revolvePreviewer'; +import {NOOP} from '../../../../../modules/gems/func'; export default { id: 'REVOLVE', @@ -7,8 +9,8 @@ export default { icon: 'img/cad/revolve', info: 'creates a solid based on revolve surfaces', paramsInfo: ({angle}) => angle, - previewGeomProvider: () => new THREE.Geometry(), - run: (request) => console.dir(request), + previewGeomProvider: revolvePreviewGeomProvider, + run: NOOP, form: RevolveForm, schema }; diff --git a/web/app/cad/craft/revolve/revolvePreviewer.js b/web/app/cad/craft/revolve/revolvePreviewer.js new file mode 100644 index 00000000..dc7fbcef --- /dev/null +++ b/web/app/cad/craft/revolve/revolvePreviewer.js @@ -0,0 +1,36 @@ +import {createMeshGeometry} from 'scene/geoms'; +import {DEG_RAD} from '../../../math/math'; +import {revolveToTriangles} from '../../legacy/mesh/revolve'; + +let cache = {}; + +export function revolvePreviewGeomProvider(params, services) { + + const face = services.cadRegistry.findFace(params.face); + const axisModel = services.cadRegistry.findSketchObject(params.axis); + const axis = axisModel.sketchPrimitive; + if (!face || !face.sketch || !axis) return null; + let contours = face.sketch.fetchContours(); + + let polygons = []; + for (let contour of contours) { + const curves = contour.transferInCoordinateSystem(face.csys); + let polygon = []; + for (let curve of curves) { + let points = curve.tessellate(); + for (let i = 0; i < points.length - 1; i++) { + polygon.push(points[i]); + } + } + polygons.push(polygon); + } + + let angle = params.angle * DEG_RAD; + let tr = face.csys.outTransformation.apply; + const triangles = revolveToTriangles(polygons, [tr(axis.a), tr(axis.b)], angle, defaultResolution(params.angle), true); + return createMeshGeometry(triangles); +} + +function defaultResolution(angle) { + return Math.max(2, Math.round(Math.abs(angle) / 4.0)); +} diff --git a/web/app/cad/legacy/mesh/revolve.js b/web/app/cad/legacy/mesh/revolve.js index 240ad1a2..a0069165 100644 --- a/web/app/cad/legacy/mesh/revolve.js +++ b/web/app/cad/legacy/mesh/revolve.js @@ -2,6 +2,7 @@ import {Matrix3} from '../../../math/l3space' import Vector from 'math/vector'; import * as math from '../../../math/math' import {createShared} from '../../cad-utils' +import {TriangulatePolygons} from '../../tess/triangulation'; function Group(derivedFrom) { this.polygons = []; @@ -68,10 +69,11 @@ export function revolveToWireframe(polygons, axisSegment, angle, resolution) { return out; } -export function revolveToTriangles(polygons, axisSegment, angle, resolution) { +export function revolveToTriangles(polygons, axisSegment, angle, resolution, triangulateBases) { const out = []; + let lidNormal = null, baseNormal = null; //add initial polygon - revolveIterator(polygons, axisSegment, angle, resolution, (pOrig, pRot, p, q) => { + let lids = revolveIterator(polygons, axisSegment, angle, resolution, (pOrig, pRot, p, q, r, id, i, length) => { //skip point if they are on the axis of revolving if (!math.equal(0, math.distanceAB3(pOrig[q], pRot[q]))) { out.push( [pOrig[p], pOrig[q], pRot[q]] ); @@ -79,7 +81,24 @@ export function revolveToTriangles(polygons, axisSegment, angle, resolution) { if (!math.equal(0, math.distanceAB3(pOrig[p], pRot[p]))) { out.push( [ pRot[q], pRot[p], pOrig[p]] ); } + let last = i === length - 1 + if (last && !lidNormal) { + lidNormal = pRot[q].minus(pOrig[q])._normalize(); + } + if (i === 0 && !baseNormal) { + baseNormal = pRot[q].minus(pOrig[q])._normalize() + } }); + if (triangulateBases && lidNormal && baseNormal) { + function triangulatePolygons(polygons, normal) { + TriangulatePolygons(polygons, normal, (v) => v.toArray(), (arr) => new Vector().set3(arr)) + .forEach(tr => out.push(tr)); + } + triangulatePolygons(lids, lidNormal); + triangulatePolygons(polygons, baseNormal); + + } + if (angle < 0) { out.forEach(tr => tr.reverse()); } @@ -107,7 +126,7 @@ export function revolveIterator(polygons, axisSegment, angle, resolution, callba const pRot = rotatedPolygons[i]; const n = pOrig.length; for (let p = n - 1, q = 0; q < n; p = q ++) { - callback(pOrig, pRot, p, q, reverse, segmentId ++); + callback(pOrig, pRot, p, q, reverse, segmentId ++, resIndex, resolution); } } polygons = rotatedPolygons; diff --git a/web/app/cad/preview/previewPlugin.js b/web/app/cad/preview/previewPlugin.js index e96d03c5..1c39b57b 100644 --- a/web/app/cad/preview/previewPlugin.js +++ b/web/app/cad/preview/previewPlugin.js @@ -12,17 +12,26 @@ export function activate(ctx) { let previewer = null; materializedWorkingRequest$.attach(({type, params}) => { if (previewer === null) { - if (operation.previewGeomProvider) { - previewer = createPreviewer(operation.previewGeomProvider, services, params); - } else if (operation.previewer) { - previewer = operation.previewer(ctx, params, wizCtx.updateParams); + try { + if (operation.previewGeomProvider) { + previewer = createPreviewer(operation.previewGeomProvider, services, params); + } else if (operation.previewer) { + previewer = operation.previewer(ctx, params, wizCtx.updateParams); + } + } catch (e) { + console.error(e); + return; } wizCtx.addDisposer(() => { previewer.dispose(); ctx.services.viewer.requestRender(); }); } else { - previewer.update(params); + try { + previewer.update(params); + } catch (e) { + console.error(e); + } } ctx.services.viewer.requestRender(); });