diff --git a/web/app/cad/legacy/brep/revolve.js b/web/app/cad/legacy/brep/revolve.js deleted file mode 100644 index b2fd6d9a..00000000 --- a/web/app/cad/legacy/brep/revolve.js +++ /dev/null @@ -1,35 +0,0 @@ -import {BooleanOperation, combineShells} from './boolean-operation' -import {ReadSketchFromFace} from '../../sketch/sketchReader' -import {revolve} from 'brep/brep-builder' - -export function Revolve(app, params) { - - const face = app.findFace(params.face); - const solid = face.solid; - const surface = face.surface; - - const sketch = ReadSketchFromFace(app, face); - const pivot = evalPivot(params.pivot, sketch, face.csys); - - const shells = []; - const contours = sketch.fetchContours(); - for (let contour of contours) { - const basePath = contour.transferInCoordinateSystem(face.csys); - const shell = revolve(basePath, surface, pivot.p0, pivot.v, params.angle); - shells.push(shell); - } - - const operand = combineShells(shells); - return BooleanOperation(face, solid, operand, 'union'); -} - -export function evalPivot(pivot, sketch, csys) { - const segment = sketch.findById(pivot); - if (segment == null) { - return null; - } - const tr = csys.outTransformation; - const p0 = tr.apply(segment.a); - const v = tr.apply(segment.b).minus(p0)._normalize(); - return {p0, v} -} diff --git a/web/app/cad/legacy/brep/wizards/revolve-wizard.js b/web/app/cad/legacy/brep/wizards/revolve-wizard.js deleted file mode 100644 index b8758a64..00000000 --- a/web/app/cad/legacy/brep/wizards/revolve-wizard.js +++ /dev/null @@ -1,40 +0,0 @@ -import {CURRENT_SELECTION as S} from './wizard' -import {PreviewWizard, SketchBasedNurbsPreviewer } from './preview-wizard' -import {TriangulatePolygons} from '../../../tess/triangulation' -import {revolveToWallNurbs} from 'brep/brep-builder' -import {evalPivot} from '../revolve' -import Vector from 'math/vector'; - -const METADATA = [ - ['angle' , 'number', 5, {min: -360, max: 360, step: 10}], - ['pivot' , 'sketch.segment' , S ], - ['face' , 'face' , S ] -]; - -export class RevolveWizard extends PreviewWizard { - constructor(app, initialState) { - super(app, 'REVOLVE', METADATA, initialState) - } - - createPreviewObject(app, params) { - return REVOLVE_PREVIEWER.createMesh(app, params); - } -} - -export class RevolvePreviewer extends SketchBasedNurbsPreviewer { - - createNurbses(app, params, sketch, face) { - const surface = face.surface(); - const pivot = evalPivot(params.pivot, sketch, surface); - const nurbses = []; - const contours = sketch.fetchContours(); - for (let contour of contours) { - const basePath = contour.approximateOnSurface(surface); - revolveToWallNurbs(basePath, surface, pivot.p0, pivot.v, params.angle).forEach(nurbs => nurbses.push(nurbs)); - } - return nurbses; - } -} - - -const REVOLVE_PREVIEWER = new RevolvePreviewer(); diff --git a/web/app/cad/legacy/brep/wizards/wizard.js b/web/app/cad/legacy/brep/wizards/wizard.js deleted file mode 100644 index 0bf0c00f..00000000 --- a/web/app/cad/legacy/brep/wizards/wizard.js +++ /dev/null @@ -1,177 +0,0 @@ -import * as tk from '../../../../ui/toolkit'; -import {isTCADError} from '../../../../utils/errors'; - -export class Wizard { - - constructor(app, opearation, initialState) { - this.app = app; - this.metadata = metadata; - this.formFields = {}; - this.box = this.createUI(opearation, metadata); - this.overridingHistory = false; - if (initialState !== undefined) { - this.setFormFields(initialState); - } - } - - createRequest() { - return { - type: this.operation, - params: this.readFormFields() - }; - } - - uiLabel(name) { - return camelCaseSplit(name).map(w => w.toLowerCase()).join(' '); - } - - focus() { - this.box.root.find('input, select').first().focus() - } - - createUI(operation, metadata) { - const box = new tk.Box($('#view-3d')); - const folder = new tk.Folder(operation); - tk.add(box, folder); - for (let def of metadata) { - const name = def[0]; - const type = def[1]; - const defaultValue = def[2]; - const params = def[3] || {}; - const label = this.uiLabel(name); - const formItem = this.createFormField(name, label, type, params, defaultValue); - formItem.setter(defaultValue); - tk.add(folder, formItem.ui); - this.formFields[name] = formItem; - } - const buttons = new tk.ButtonRow(["Cancel", "OK"], [() => this.cancelClick(), () => this.okClick()]); - tk.add(folder, buttons); - tk.add(folder, {root: $('
')}); - box.root.keydown((e) => { - switch (e.keyCode) { - case 27 : this.cancelClick(); break; - case 13 : this.okClick(); break; - } - }); - - return box; - } - - cancelClick() { - this.dispose(); - } - - okClick() { - if (this.apply()) { - this.dispose(); - } - } - - apply() { - let errors = this.app.craft.modify(this.createRequest(), this.overridingHistory); - if (errors) { - this.showErrors(errors); - return false; - } else { - return true; - } - } - - showErrors(error) { - this.showErrorText('performing operation with current parameters leads to an invalid object' + - '(manifold / self-intersecting / zero-thickness / complete degeneration or unsupported cases)'); - if (!isTCADError(error)) { - console.error('internal error while performing operation'); - throw error; - } - } - - showErrorText(message) { - this.box.root.find('.errors-message').text(message); - } - - onUIChange() {} - - readFormFields() { - const params = {}; - const keys = Object.keys(this.formFields); - for (let key of keys) { - params[key] = this.formFields[key].getter(); - } - return params; - } - - setFormFields(params) { - const keys = Object.keys(params); - for (let name of keys) { - this.setFormField(name, params[name]); - } - } - - setFormField(name, value) { - const formField = this.formFields[name]; - if (formField) { - formField.setter(value); - } - } - - dispose() { - this.disposed = true; - this.box.close(); - } - - createFormField(name, label, type, params, initValue) { - if (type === 'number') { - const number = tk.config(new tk.Number(label, initValue, params.step, params.round), params); - number.input.on('t-change', () => this.onUIChange(name)); - return Field.fromInput(number, Field.TEXT_TO_NUMBER_COERCION); - } else if (type === 'choice') { - const ops = params.options; - const radio = new tk.InlineRadio(ops, ops, ops.indexOf(initValue)); - radio.root.find('input[type=radio]').on('change', () => { - this.onUIChange(name); - }); - return new Field(radio, () => radio.getValue(), (v) => radio.setValue(v)); - } else if (type === 'face') { - return selectionWidget(name, label, initValue, this.app.context.bus, 'selection_face',(selection) => selection.id); - } else if (type === 'sketch.segment') { - return selectionWidget(name, label, initValue, this.app.context.bus, 'selection_sketchObject', (selection) => selection.__TCAD_SketchObject.id); - } - } -} - -function selectionWidget(name, label, initValue, bus, selectionKey, toId) { - const obj = new tk.Text(label, initValue); - obj.input.on('change', () => this.onUIChange(name)); - return Field.fromInput(obj, undefined, (objId) => { - if (objId === CURRENT_SELECTION) { - let selection = bus.state[selectionKey][0]; - return selection ? toId(selection) : ''; - } else { - return objId; - } - }); - -} - -function FaceSelectionListener() { - this.callbacks = []; -} - -function Field(ui, getter, setter) { - this.ui = ui; - this.getter = getter; - this.setter = setter; -} - -Field.NO_COERCION = (v) => v; -Field.NUMBER_TO_TEXT_COERCION = (v) => v + ""; -Field.TEXT_TO_NUMBER_COERCION = (v) => parseFloat(v); - -Field.fromInput = function (inputEl, getterCoercer, setterCoercer) { - getterCoercer = getterCoercer || Field.NO_COERCION; - setterCoercer = setterCoercer || Field.NO_COERCION; - return new Field(inputEl, () => getterCoercer(inputEl.input.val()), (value) => inputEl.input.val(setterCoercer(value))); -}; - -export const CURRENT_SELECTION = {}; diff --git a/web/app/cad/legacy/mesh.js b/web/app/cad/legacy/mesh.js deleted file mode 100644 index c4da5cab..00000000 --- a/web/app/cad/legacy/mesh.js +++ /dev/null @@ -1,79 +0,0 @@ -import * as cad_utils from '../cad-utils' -import {HashTable} from '../../utils/hashmap' - -export function MeshFace() { - this.polygons = []; -} - -export function MeshPolygon(id, normal, w, points) { - this.id = id; - this.normal = normal; - this.w = w; - this.points = points; - this.neighbors = []; -} - -export function Mesh(edges) { - this.edges = edges; - this.faces = []; - this.getEdgeInfo = function(point1, point2) { - return edges.get(arguments) - } -} - -Mesh.fromPolygons = function(polygons, smoothAngle) { - const edges = HashTable.forEdge(); - - let counter = 0; - const allPolygons = []; - function index(polygon) { - if (polygon.length < 3) { - console.warn('invalid polygon ' + polygon); - return; - } - const normal = cad_utils.normalOfCCWSeq(polygon); - const w = normal.dot(polygon[0]); - - const polygonInfo = new MeshPolygon(counter++, normal, w, polygon); - - allPolygons.push(polygonInfo); - - for (let p = polygon.length - 1, q = 0; q < polygon.length; p = q ++) { - var edgeKey = [polygon[p], polygon[q]]; - let edgeInfo = edges.get(edgeKey); - if (edgeInfo == null) { - edges.put(edgeKey, [polygonInfo]) - } else { - let other = edgeInfo[0]; - other.neighbors.push(polygonInfo); - polygonInfo.neighbors.push(other); - edgeInfo.push(polygonInfo); - } - } - } - - const visited = {}; - function mergePolygons(tr, meshFace) { - if (visited[tr.id]) { - return; - } - visited[tr.id] = true; - meshFace.polygons.push(tr); - for (let nb of tr.neighbors) { - if (Math.acos(nb.normal.dot(tr.normal)) < smoothAngle) { - mergePolygons(nb, meshFace) - } - } - } - polygons.forEach(p => index(p)); - const mesh = new Mesh(edges); - for (let tr of allPolygons) { - const meshFace = new MeshFace(); - mergePolygons(tr, meshFace); - if (meshFace.polygons.length != 0) { - mesh.faces.push(meshFace); - } - } - return mesh; -}; - diff --git a/web/app/cad/legacy/mesh/revolve.js b/web/app/cad/legacy/mesh/revolve.js deleted file mode 100644 index 79553c3b..00000000 --- a/web/app/cad/legacy/mesh/revolve.js +++ /dev/null @@ -1,157 +0,0 @@ -import Vector from 'math/vector'; -import {createShared} from '../../cad-utils' -import {TriangulatePolygons} from '../../tess/triangulation'; -import {Matrix3x4} from "math/matrix"; -import {distanceAB3} from "math/distance"; -import {equal} from "math/equality"; - -function Group(derivedFrom) { - this.polygons = []; - this.derivedFrom = derivedFrom; -} - -export default function revolve(polygons, axisSegment, angle, resolution) { - const groups = {}; - const out = []; - let lids = revolveIterator(polygons, axisSegment, angle, resolution, (pOrig, pRot, p, q, reverse, segmentId) => { - const polygon = [pOrig[p], pOrig[q]]; - - //skip point if they are on the axis of revolving - if (!equal(0, distanceAB3(pOrig[q], pRot[q]))) { - polygon.push(pRot[q]); - } - if (!equal(0, distanceAB3(pOrig[p], pRot[p]))) { - polygon.push(pRot[p]); - } - if (polygon.length < 3) { - return; - } - if (reverse) { - polygon.reverse(); //fixes CCW order - } - - let shared = createShared(); - let sketchConnectionObject = pOrig[p].sketchConnectionObject; - if (sketchConnectionObject) { - if (sketchConnectionObject.TYPE === 'Segment') { - sketchConnectionObject = Object.assign({}, sketchConnectionObject, { - TYPE: 'Arc', - id: sketchConnectionObject.id + ":REVOLVED" // just avoid having object with the same ID but different classes - }); - } - shared.__tcad.csgInfo = {derivedFrom: sketchConnectionObject}; - pRot[p].sketchConnectionObject = sketchConnectionObject; - } - - const face = csgPolygon(polygon, shared); - out.push(face); - }); - if (!equal(_360, angle)) { - if (angle < 0) { - let t = lids; - lids = polygons; - polygons = t; - } - lids.forEach(p => out.push(csgPolygon(p, createShared()))); - polygons.forEach(p => out.push(csgPolygon(p.slice().reverse(), createShared()))); - } - return out; -} - -export function revolveToWireframe(polygons, axisSegment, angle, resolution) { - const out = []; - //add initial polygon - addAsSegments(out, polygons); - revolveIterator(polygons, axisSegment, angle, resolution, (pOrig, pRot, p, q) => { - out.push([pRot[p], pRot[q]]); - addIfNonZero(out, [pOrig[q], pRot[q]]); - addIfNonZero(out, [pOrig[p], pRot[p]]); - }); - return out; -} - -export function revolveToTriangles(polygons, axisSegment, angle, resolution, triangulateBases) { - const out = []; - let lidNormal = null, baseNormal = null; - //add initial polygon - 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 (!equal(0, distanceAB3(pOrig[q], pRot[q]))) { - out.push( [pOrig[p], pOrig[q], pRot[q]] ); - } - if (!equal(0, 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()); - } - return out; -} - -export function revolveIterator(polygons, axisSegment, angle, resolution, callback) { - - if (resolution < 2) resolution = 2; - const reverse = angle < 0; - angle = Math.abs(angle); - if (angle > _360) { - angle = _360; - } - - const angleStep = angle / resolution * (reverse ? -1 : 1); - const axis = new Vector().setV(axisSegment[1])._minus(axisSegment[0]); - const tr = Matrix3x4.rotateMatrix(angleStep, axis, axisSegment[0]); - - for (let resIndex = 0; resIndex < resolution; resIndex++) { - let rotatedPolygons = polygons.map(poly => poly.map(point => tr.apply(point))); - let segmentId = 0; - for (let i = 0; i < polygons.length; i++) { - const pOrig = polygons[i]; - 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 ++, resIndex, resolution); - } - } - polygons = rotatedPolygons; - } - return polygons; -} - - -function addIfNonZero(out, seg) { - if (!equal(0, distanceAB3(seg[0], seg[1]))) { - out.push(seg); - } -} - -function addAsSegments(out, polygons) { - for (let poly of polygons) { - for (let p = poly.length - 1, q = 0; q < poly.length; p = q ++) { - out.push([poly[p], poly[q]]); - } - } -} - -function csgPolygon(points, shared) { - return new CSG.Polygon(points.map(p => new CSG.Vertex(p.csg())), shared); -} - -const _360 = 2 * Math.PI; diff --git a/web/app/cad/legacy/mesh/wizards/box.js b/web/app/cad/legacy/mesh/wizards/box.js deleted file mode 100644 index 566f85fb..00000000 --- a/web/app/cad/legacy/mesh/wizards/box.js +++ /dev/null @@ -1,72 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import {FACE_COLOR} from '../../../cad-utils' -import {Wizard} from './wizard-commons' - -export function BoxWizard(viewer, initParams) { - Wizard.call(this, viewer, initParams); - this.previewGroup = new THREE.Object3D(); - this.viewer.scene.add(this.previewGroup); - this.previewGroup.add(this.box = this.createBox()); - this.synch(); -} - -BoxWizard.prototype = Object.create( Wizard.prototype ); - -BoxWizard.prototype.DEFAULT_PARAMS = [500, 500, 500]; - -BoxWizard.prototype.title = function() { - return "Add a Box"; -}; - -BoxWizard.prototype.createBox = function() { - var geometry = new THREE.BoxGeometry(1, 1, 1); - var material = new THREE.MeshLambertMaterial( { color : FACE_COLOR, transparent: true, opacity:0.5, side: THREE.DoubleSide }); - return new THREE.Mesh(geometry, material); -}; - -BoxWizard.prototype.update = function(w, h, d) { - this.box.scale.x = w; - this.box.scale.y = h; - this.box.scale.z = d; - this.viewer.render(); -}; - -BoxWizard.prototype.createUI = function(w, h, d) { - const ui = this.ui; - const folder = this.ui.folder; - ui.width = tk.config(new tk.Number("Width", w), {min : 0}); - ui.height = tk.config(new tk.Number("Height", h), {min : 0}); - ui.depth = tk.config(new tk.Number("Depth", d), {min : 0}); - tk.add(folder, ui.width); - tk.add(folder, ui.height); - tk.add(folder, ui.depth); - var onChange = tk.methodRef(this, "synch"); - ui.width.input.on('t-change', onChange); - ui.height.input.on('t-change', onChange); - ui.depth.input.on('t-change', onChange); -}; - -BoxWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.viewer.render(); -}; - -BoxWizard.prototype.getParams = function() { - return [Number(this.ui.width.input.val()), Number(this.ui.height.input.val()), Number(this.ui.depth.input.val())]; -}; - -BoxWizard.prototype.createRequest = function(done) { - var params = this.getParams(); - done({ - type: 'BOX', - solids : [], - params : {w : params[0], h : params[1], d : params[2]}, - protoParams : params - }); -}; - -BoxWizard.prototype.dispose = function() { - Wizard.prototype.dispose.call(this); - this.viewer.scene.remove(this.previewGroup); - this.viewer.render(); -}; diff --git a/web/app/cad/legacy/mesh/wizards/extrude.js b/web/app/cad/legacy/mesh/wizards/extrude.js deleted file mode 100644 index eba03508..00000000 --- a/web/app/cad/legacy/mesh/wizards/extrude.js +++ /dev/null @@ -1,105 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import * as workbench from '../workbench' -import * as cad_utils from '../../../cad-utils' -import Vector, {ORIGIN} from 'math/vector'; -import {OpWizard, IMAGINE_MATERIAL, BASE_MATERIAL} from './wizard-commons' -import {Matrix3x4} from 'math/matrix'; - -export function ExtrudeWizard(app, face, invert, initParams) { - this.invert = invert; // title depends on invert flag - OpWizard.call(this, app.viewer, initParams); - this.app = app; - this.face = face; - this.updatePolygons(); - this.synch(); -} - -ExtrudeWizard.prototype = Object.create( OpWizard.prototype ); - -ExtrudeWizard.prototype.DEFAULT_PARAMS = [50, 1, 0, 0]; - -ExtrudeWizard.prototype.title = function() { - return this.invert ? "Cut Options" : "Extrude Options"; -}; - -ExtrudeWizard.prototype.updatePolygons = function() { - this.polygons = workbench.getSketchedPolygons3D(this.app, this.face); -}; - -ExtrudeWizard.prototype.update = function(depth, scale, deflection, angle) { - if (this.invert) depth *= -1; //depth; - - var basis = this.face.basis(); - var normal = new Vector().setV(this.face.csgGroup.plane.normal); - var linesCounter = 0; - var target; - if (deflection != 0) { - target = normal.copy(); - if (depth < 0) target._negate(); - target = Matrix3x4.rotateMatrix(deflection * Math.PI / 180, basis[0], ORIGIN)._apply(target); - if (angle != 0) { - target = Matrix3x4.rotateMatrix(angle * Math.PI / 180, basis[2], ORIGIN)._apply(target); - } - target._multiply(Math.abs(depth)); - } else { - target = normal.multiply(depth) - } - for (var i = 0; i < this.polygons.length; i++) { - var poly = this.polygons[i]; - var lid = cad_utils.calculateExtrudedLid(poly, normal, target, scale); - var p, q, n = poly.length; - for (p = n - 1, q = 0; q < n; p = q++) { - this.setupLine(linesCounter ++, poly[p], poly[q], BASE_MATERIAL); - this.setupLine(linesCounter ++, lid[p], lid[q], IMAGINE_MATERIAL); - } - for (q = 0; q < n; q++) { - this.setupLine(linesCounter ++, poly[q], lid[q], IMAGINE_MATERIAL); - } - } - this.operationParams = { - target : target, - expansionFactor : scale - } -}; - -ExtrudeWizard.prototype.createUI = function (depth, scale, deflection, angle) { - const ui = this.ui; - const folder = this.ui.folder; - tk.add(ui.box, folder); - ui.theValue = tk.config(new tk.Number(this.invert ? "Depth" : "Height", depth), {min: 0}); - ui.scale = tk.config(new tk.Number("Prism", scale, 0.1, 1), {min:0}); - ui.deflection = new tk.Number("Angle", deflection, 1); - ui.angle = new tk.Number("Rotation", angle, 5); - var onChange = tk.methodRef(this, "synch"); - ui.theValue.input.on('t-change', onChange); - ui.scale.input.on('t-change', onChange); - ui.deflection.input.on('t-change', onChange); - ui.angle.input.on('t-change', onChange); - tk.add(folder, ui.theValue); - tk.add(folder, ui.scale); - tk.add(folder, ui.deflection); - tk.add(folder, ui.angle); -}; - -ExtrudeWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.app.viewer.render(); -}; - -ExtrudeWizard.prototype.getParams = function() { - var depthValue = this.ui.theValue.input.val(); - var scaleValue = this.ui.scale.input.val(); - var deflectionValue = this.ui.deflection.input.val(); - var angleValue = this.ui.angle.input.val(); - return [depthValue, scaleValue, deflectionValue, angleValue]; -}; - -ExtrudeWizard.prototype.createRequest = function(done) { - done({ - type : this.invert ? 'CUT' : 'EXTRUDE', - solids : [this.app.findSolidByCadId(this.face.solid.tCadId)], - face : this.app.findFace(this.face.id), - params : this.operationParams, - protoParams : this.getParams() - }); -}; diff --git a/web/app/cad/legacy/mesh/wizards/import.js b/web/app/cad/legacy/mesh/wizards/import.js deleted file mode 100644 index a4c69c56..00000000 --- a/web/app/cad/legacy/mesh/wizards/import.js +++ /dev/null @@ -1,41 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import {Wizard} from './wizard-commons' -import {LoadSTLFromURL} from '../../../stl/io' - -export function ImportWizard(viewer, initParams) { - Wizard.call(this, viewer, initParams); -} - -ImportWizard.prototype = Object.create( Wizard.prototype ); - -ImportWizard.prototype.DEFAULT_PARAMS = ['https://cdn.thingiverse.com/assets/de/88/44/ab/fe/Touring_Bike_not_for_print.stl']; - -ImportWizard.prototype.title = function() { - return "Import URL"; -}; - -ImportWizard.prototype.createUI = function (url) { - this.ui.url = new tk.Text("URL", url); - tk.add(this.ui.folder, this.ui.url); -}; - -ImportWizard.prototype.getParams = function() { - return [this.ui.url.input.val()]; -}; - -ImportWizard.prototype.createRequest = function(done) { - const protoParams = this.getParams(); - const url = protoParams[0]; - LoadSTLFromURL(url, (objects, err) => { - if (objects == null || objects.length == 0) { - done(new Wizard.InvalidRequest("Server returned no data or format isn't supported." + (err ? " Http Status: " + err : "") )) - } else { - done({ - type : 'IMPORT_STL', - solids: [], - params: {objects, url}, - protoParams - }); - } - }); -}; diff --git a/web/app/cad/legacy/mesh/wizards/plane.js b/web/app/cad/legacy/mesh/wizards/plane.js deleted file mode 100644 index e83d827e..00000000 --- a/web/app/cad/legacy/mesh/wizards/plane.js +++ /dev/null @@ -1,124 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import {FACE_COLOR} from '../../../cad-utils' -import {Wizard} from './wizard-commons' -import {IDENTITY_BASIS} from 'math/basis'; -import {AXIS} from "math/vector"; - -export function PlaneWizard(app, initParams) { - Wizard.call(this, app.viewer, initParams); - this.app = app; - this.previewGroup = new THREE.Object3D(); - this.viewer.scene.add(this.previewGroup); - this.previewGroup.add(this.plane = this.createPlane()); - this.operationParams = { - basis : IDENTITY_BASIS, - depth : 0, - relativeToFaceId: '' - }; - this.selectionListener = () => { - const face = this.getFirstSelectedFace(); - if (face) { - this.ui.relativeToFace.input.val(face.id); - this.synch(); - } - }; - app.bus.subscribe('selection', this.selectionListener); - - this.focus = () => this.ui.depth.input.focus(); - this.synch(); -} - -PlaneWizard.prototype = Object.create( Wizard.prototype ); - -PlaneWizard.prototype.DEFAULT_PARAMS = ['XY', 0, '']; - -PlaneWizard.prototype.title = function() { - return "Add a Plane"; -}; - -PlaneWizard.prototype.createPlane = function() { - var geometry = new THREE.PlaneGeometry(750,750,1,1,1); - var material = new THREE.MeshLambertMaterial( { color : FACE_COLOR, transparent: true, opacity:0.5, side: THREE.DoubleSide }); - return new THREE.Mesh(geometry, material); -}; - -PlaneWizard.prototype.update = function(orientation, w, relativeToFaceId) { - if (relativeToFaceId != '') { - const face = this.app.findFace(relativeToFaceId); - const m = new THREE.Matrix4(); - m.makeBasis.apply(m, face.basis()); - const wVec = new THREE.Vector3(0, 0, w + face.depth()); - wVec.applyMatrix4(m); - m.setPosition(wVec); - this.plane.matrix.identity(); - this.plane.applyMatrix(m); - } else if (orientation === 'XY') { - this.plane.rotation.x = 0; - this.plane.rotation.y = 0; - this.plane.rotation.z = 0; - this.plane.position.x = 0; - this.plane.position.y = 0; - this.plane.position.z = w; - this.operationParams.basis = IDENTITY_BASIS; - } else if (orientation === 'XZ') { - this.plane.rotation.x = Math.PI / 2; - this.plane.rotation.y = 0; - this.plane.rotation.z = 0; - this.plane.position.x = 0; - this.plane.position.y = w; - this.plane.position.z = 0; - this.operationParams.basis = [AXIS.X, AXIS.Z, AXIS.Y]; - } else if (orientation === 'ZY') { - this.plane.rotation.x = 0; - this.plane.rotation.y = Math.PI / 2; - this.plane.rotation.z = 0; - this.plane.position.x = w; - this.plane.position.y = 0; - this.plane.position.z = 0; - this.operationParams.basis = [AXIS.Z, AXIS.Y, AXIS.X]; - } else { - throw orientation + " isn't supported yet"; - } - this.operationParams.depth = w; - this.operationParams.relativeToFaceId = relativeToFaceId; - this.viewer.render(); -}; - -PlaneWizard.prototype.createUI = function(orientation, w, relativeToFaceId) { - const folder = this.ui.folder; - const choice = ['XY', 'XZ', 'ZY']; - this.ui.orientation = new tk.InlineRadio(choice, choice, choice.indexOf(orientation)); - this.ui.depth = new tk.Number("Depth", w); - this.ui.relativeToFace = new tk.Text("Relative to Face", relativeToFaceId === undefined ? '' : relativeToFaceId); - tk.add(folder, this.ui.orientation); - tk.add(folder, this.ui.relativeToFace); - tk.add(folder, this.ui.depth); - - var onChange = tk.methodRef(this, "synch"); - this.ui.orientation.root.find('input:radio').change(onChange); - this.ui.depth.input.on('t-change', onChange); -}; - -PlaneWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.viewer.render(); -}; - -PlaneWizard.prototype.getParams = function() { - return [this.ui.orientation.getValue(), parseFloat(this.ui.depth.input.val()), this.ui.relativeToFace.input.val()] -}; - -PlaneWizard.prototype.createRequest = function(done) { - done({ - type: 'PLANE', - solids : [], - params : this.operationParams, - protoParams : this.getParams() - }); -}; - -PlaneWizard.prototype.dispose = function() { - Wizard.prototype.dispose.call(this); - this.viewer.scene.remove(this.previewGroup); - this.viewer.render(); -}; diff --git a/web/app/cad/legacy/mesh/wizards/revolve.js b/web/app/cad/legacy/mesh/wizards/revolve.js deleted file mode 100644 index 1d5a3978..00000000 --- a/web/app/cad/legacy/mesh/wizards/revolve.js +++ /dev/null @@ -1,159 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import * as workbench from '../workbench' -import {revolveToTriangles} from '../revolve' -import {IMAGINARY_SURFACE_MATERIAL, OpWizard,} from './wizard-commons' - -export function RevolveWizard(app, face, initParams) { - if (face.sketch3DGroup == null) app.refreshSketchOnFace(face); - if (!initParams) this.DEFAULT_PARAMS[2] = findDefaultAxis(app, face); - OpWizard.call(this, app.viewer, initParams); - this.app = app; - this.face = face; - this.updatePolygons(); - this.synch(); - this.autoResoltion = true; - this.selectionListener = () => { - const object = this.app.getFirstSelectedFace(); - if (canBePivot(object, this.face)) { - this.ui.pivotSketchObjectId.input.val(object.__TCAD_SketchObject.id); - this.synch(); - } - }; - app.bus.subscribe('selection-sketch-object', this.selectionListener); -} - -function canBePivot(sketchObject, face) { - return sketchObject && isSketchSegment(sketchObject) && sketchObject.parent == face.sketch3DGroup; -} - -function findDefaultAxis(app, face) { - let line; - const preSelected = app.getFirstSelectedFace(); - if (canBePivot(preSelected, face)) { - line = preSelected; - } else { - line = firstSegment(face.sketch3DGroup.children); - if (line) { - app.viewer.sketchSelectionMgr.select(line); - } - } - if (!line) { - alert("Sketch doesn't contain any segments which can be used as a revolve pivot"); - return undefined; - } else { - return line.__TCAD_SketchObject.id; - } -} - -function defaultResolution(angle) { - return Math.max(2, Math.round(Math.abs(angle) / 4.0 )); -} - -RevolveWizard.prototype = Object.create( OpWizard.prototype ); - -RevolveWizard.prototype.DEFAULT_PARAMS = [180, defaultResolution(180)]; - -RevolveWizard.prototype.title = function() { - return "Revolve"; -}; - -RevolveWizard.prototype.updatePolygons = function() { - this.polygons = workbench.getSketchedPolygons3D(this.app, this.face); -}; - -RevolveWizard.prototype.update = function(angle, resolution, pivotSketchObjectId) { - if (this.mesh) { - this.mesh.geometry.dispose(); - this.previewGroup.remove(this.mesh); - } - - const vertices = this.face.getSketchObjectVerticesIn3D(pivotSketchObjectId); - if (!vertices) { - console.log('illegal state'); - return; - } - const axis = [vertices[0], vertices[vertices.length-1]]; - const triangles = revolveToTriangles(this.polygons, axis, angle / 180 * Math.PI, resolution); - const geometry = new THREE.Geometry(); - - for (let tr of triangles) { - const a = geometry.vertices.length; - const b = a + 1; - const c = a + 2; - const face = new THREE.Face3(a, b, c); - tr.forEach(v => geometry.vertices.push(v.three())); - geometry.faces.push(face); - } - geometry.mergeVertices(); - geometry.computeFaceNormals(); - - this.mesh = new THREE.Mesh(geometry, IMAGINARY_SURFACE_MATERIAL); - this.previewGroup.add(this.mesh); -}; - -RevolveWizard.prototype.createUI = function (angle, resolution, axisObjectId) { - const ui = this.ui; - const folder = this.ui.folder; - tk.add(ui.box, folder); - ui.angle = tk.config(new tk.Number("Angle", angle, 5), {min: -360, max: 360, accelerator: 10}); - ui.resolution = tk.config(new tk.Number("Resolution", resolution), {min: 2, accelerator: 2}); - ui.pivotSketchObjectId = new tk.Text("Axis Object", axisObjectId === undefined ? "" : axisObjectId); - - ui.angle.input.on('t-change', () => { - if (this.autoResoltion) { - ui.resolution.input.val(defaultResolution ( parseFloat(ui.angle.input.val()) )); - } - this.synch(); - }); - ui.resolution.input.on('t-change', () => { - this.autoResoltion = false; - this.synch(); - }); - tk.add(folder, ui.angle); - tk.add(folder, ui.resolution); - tk.add(folder, ui.pivotSketchObjectId); -}; - -RevolveWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.app.viewer.render(); -}; - -RevolveWizard.prototype.getParams = function() { - const angleValue = parseFloat(this.ui.angle.input.val()); - const resolutionValue = parseFloat(this.ui.resolution.input.val()); - const pivotSketchObjectId = this.ui.pivotSketchObjectId.input.val(); - return [angleValue, resolutionValue, pivotSketchObjectId]; -}; - -RevolveWizard.prototype.createRequest = function(done) { - const params = this.getParams(); - done({ - type : 'REVOLVE', - solids : [this.app.findSolidByCadId(this.face.solid.tCadId)], - face : this.app.findFace(this.face.id), - params : { - angle: params[0], - resolution: params[1], - pivotSketchObjectId: params[2] - }, - protoParams: params - }); -}; - -RevolveWizard.prototype.dispose = function() { - this.app.bus.unsubscribe('selection-sketch-object', this.selectionListener); - OpWizard.prototype.dispose.call(this); -}; - -function isSketchSegment(line) { - return line.__TCAD_SketchObject && line.__TCAD_SketchObject.TYPE === 'Segment'; -} -function firstSegment(objects) { - for (let line of objects) { - if (isSketchSegment(line)) { - return line; - } - } - return undefined; -} \ No newline at end of file diff --git a/web/app/cad/legacy/mesh/wizards/sphere.js b/web/app/cad/legacy/mesh/wizards/sphere.js deleted file mode 100644 index 528f6a18..00000000 --- a/web/app/cad/legacy/mesh/wizards/sphere.js +++ /dev/null @@ -1,64 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import {FACE_COLOR} from '../../../cad-utils' -import {Wizard} from './wizard-commons' - -export function SphereWizard(viewer, initParams) { - Wizard.call(this, viewer, initParams); - this.previewGroup = new THREE.Object3D(); - this.viewer.scene.add(this.previewGroup); - this.previewGroup.add(this.sphere = this.createSphere()); - this.synch(); -} - -SphereWizard.prototype = Object.create( Wizard.prototype ); - -SphereWizard.prototype.DEFAULT_PARAMS = [500]; - -SphereWizard.prototype.title = function() { - return "Add a Sphere"; -}; - -SphereWizard.prototype.createSphere = function() { - var geometry = new THREE.SphereGeometry(1, 30, 28); - var material = new THREE.MeshLambertMaterial( { color : FACE_COLOR, transparent: true, opacity:0.9 }); - return new THREE.Mesh(geometry, material); -}; - -SphereWizard.prototype.update = function(radius) { - this.sphere.scale.x = radius; - this.sphere.scale.y = radius; - this.sphere.scale.z = radius; - this.viewer.render(); -}; - -SphereWizard.prototype.createUI = function(radius) { - this.ui.radius = tk.config(new tk.Number("Radius", radius), {min : 0}); - tk.add(this.ui.folder, this.ui.radius); - var onChange = tk.methodRef(this, "synch"); - this.ui.radius.input.on('t-change', onChange); -}; - -SphereWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.viewer.render(); -}; - -SphereWizard.prototype.getParams = function() { - return [this.ui.radius.val()]; -}; - -SphereWizard.prototype.createRequest = function(done) { - var params = this.getParams(); - done({ - type: 'SPHERE', - solids : [], - params : {radius : params[0]}, - protoParams : params - }); -}; - -SphereWizard.prototype.dispose = function() { - Wizard.prototype.dispose.call(this); - this.viewer.scene.remove(this.previewGroup); - this.viewer.render(); -}; diff --git a/web/app/cad/legacy/mesh/wizards/transform.js b/web/app/cad/legacy/mesh/wizards/transform.js deleted file mode 100644 index 9d948208..00000000 --- a/web/app/cad/legacy/mesh/wizards/transform.js +++ /dev/null @@ -1,129 +0,0 @@ -import * as tk from '../../../../ui/toolkit.js' -import {FACE_COLOR} from '../../../cad-utils' -import {Wizard} from './wizard-commons' -import {IDENTITY_BASIS} from "math/basis"; -import {AXIS} from "math/vector"; - -export function TransformWizard(viewer, solid, initParams) { - Wizard.call(this, viewer, initParams); - this.previewGroup = new THREE.Object3D(); - this.solid = solid; - this.initialPosition = this.solid.cadGroup.position.clone(); - this.viewer.transformControls.attach(this.solid.cadGroup); - this.transfomControlListener = tk.methodRef(this, "synchToUI"); - this.viewer.transformControls.addEventListener( 'objectChange', this.transfomControlListener ); - this.synch(); -} - -TransformWizard.prototype = Object.create( Wizard.prototype ); - -TransformWizard.prototype.DEFAULT_PARAMS = [0, 0, 0, 0, 0, 0, 1]; - -TransformWizard.prototype.title = function() { - return "Solid Transform"; -}; - -TransformWizard.prototype.discardChanges = function() { - this.solid.cadGroup.position.copy(this.initialPosition); -}; - -TransformWizard.prototype.update = function(x, y, z, rotationX, rotationY, rotationZ, rotationW) { - this.solid.cadGroup.position.setX(x); - this.solid.cadGroup.position.setX(y); - this.solid.cadGroup.position.setX(z); - - this.solid.cadGroup.quaternion.x = rotationX; - this.solid.cadGroup.quaternion.y = rotationY; - this.solid.cadGroup.quaternion.z = rotationZ; - this.solid.cadGroup.quaternion.w = rotationW; - - this.viewer.transformControls.update(); - this.viewer.render(); -}; - -TransformWizard.prototype.createUI = function(x, y, z, rotationX, rotationY, rotationZ, rotationW) { - const ui = this.ui; - const folder = ui.folder; - var position = new tk.Folder("Position"); - var rotation = new tk.Folder("Rotation"); - tk.add(folder, position); - tk.add(folder, rotation); - tk.add(ui.box, folder); - ui.x = new tk.Number("Position X", x, 1, 6); - ui.y = new tk.Number("Position Y", y, 1, 6); - ui.z = new tk.Number("Position Z", z, 1, 6); - ui.rotationX = tk.config(new tk.Number("Rotation X", rotationX, 0.1, 6), {min: -1, max: 1}); - ui.rotationY = tk.config(new tk.Number("Rotation Y", rotationY, 0.1, 6), {min: -1, max: 1}); - ui.rotationZ = tk.config(new tk.Number("Rotation Z", rotationZ, 0.1, 6), {min: -1, max: 1}); - ui.rotationW = tk.config(new tk.Number("Rotation W", rotationW, 0.1, 6), {min: -1, max: 1}); - ui.mode = new tk.InlineRadio(['translate(T)', 'rotate(R)'], ['translate', 'rotate'], 0); - tk.add(position, ui.x); - tk.add(position, ui.y); - tk.add(position, ui.z); - tk.add(rotation, ui.rotationX); - tk.add(rotation, ui.rotationY); - tk.add(rotation, ui.rotationZ); - tk.add(rotation, ui.rotationW); - tk.add(rotation, ui.mode); - this.ui.mode.root.find('input:radio').change(tk.methodRef(this, "modeChanged")); - var onChange = tk.methodRef(this, "synch"); - ui.x.input.on('t-change', onChange); - ui.y.input.on('t-change', onChange); - ui.z.input.on('t-change', onChange); - ui.rotationX.input.on('t-change', onChange); - ui.rotationY.input.on('t-change', onChange); - ui.rotationZ.input.on('t-change', onChange); -}; - -TransformWizard.prototype.modeChanged = function() { - var mode = this.ui.mode.getValue(); - this.viewer.transformControls.setMode(mode); -}; - -TransformWizard.prototype.synchToUI = function() { - function round(val){return val.toFixed(6);} - var ui = this.ui; - ui.x.input.val( round(this.solid.cadGroup.position.x) ); - ui.y.input.val( round(this.solid.cadGroup.position.y) ); - ui.z.input.val( round(this.solid.cadGroup.position.z) ); - ui.rotationX.input.val( round(this.solid.cadGroup.quaternion.x) ); - ui.rotationY.input.val( round(this.solid.cadGroup.quaternion.y) ); - ui.rotationZ.input.val( round(this.solid.cadGroup.quaternion.z) ); - ui.rotationW.input.val( round(this.solid.cadGroup.quaternion.w) ); - this.viewer.render(); -}; - -TransformWizard.prototype.synch = function() { - this.update.apply(this, this.getParams()); - this.viewer.render(); -}; - -TransformWizard.prototype.getParams = function() { - return [this.ui.x.val(), this.ui.y.val(), this.ui.z.val(), - this.ui.rotationX.val(), this.ui.rotationY.val(), this.ui.rotationZ.val(), this.ui.rotationW.val()]; -}; - -TransformWizard.prototype.createRequest = function(done) { - var params = this.getParams(); - done({ - type: 'TRANSFORM', - solids : [], - params : { - position: {x : params[0], y : params[1], z : params[2]}, - rotate: {x : params[3], y : params[4], z : params[5]} - } , - protoParams : params - }); -}; - -TransformWizard.prototype.cancelClick = function() { - Wizard.prototype.cancelClick.call(this); - this.discardChanges(); -}; - -TransformWizard.prototype.dispose = function() { - Wizard.prototype.dispose.call(this); - this.viewer.transformControls.removeEventListener( 'objectChange', this.transfomControlListener ); - this.viewer.transformControls.detach(this.solid.cadGroup); - this.viewer.render(); -}; diff --git a/web/app/cad/legacy/mesh/wizards/wizard-commons.js b/web/app/cad/legacy/mesh/wizards/wizard-commons.js deleted file mode 100644 index 2649917d..00000000 --- a/web/app/cad/legacy/mesh/wizards/wizard-commons.js +++ /dev/null @@ -1,131 +0,0 @@ -import DPR from 'dpr' -import * as tk from '../../../../ui/toolkit' - -const IMAGINE_MATERIAL = new THREE.LineBasicMaterial({ - color: 0xFA8072, - linewidth: 1/DPR, - depthWrite: false, - depthTest: false -}); - -const BASE_MATERIAL = new THREE.LineBasicMaterial({ - color: 0x8B0000, - linewidth: 3/DPR, - depthWrite: false, - depthTest: false -}); - -const IMAGINARY_SURFACE_MATERIAL = new THREE.MeshPhongMaterial({ - vertexColors: THREE.FaceColors, - color: 0xFA8072, - transparent: true, - opacity: 0.5, - shininess: 0, - side : THREE.DoubleSide -}); - -export function Wizard(viewer, initParams) { - if (!initParams) initParams = this.DEFAULT_PARAMS; - this.viewer = viewer; - this.disposed = false; - this.ui = { - box: new tk.Box($('#view-3d')), - folder: new tk.Folder(this.title()) - }; - tk.add(this.ui.box, this.ui.folder); - - this.ui.box.root.keydown((e) => { - switch (e.keyCode) { - case 27 : this.cancelClick(); break; - case 13 : this.okClick(); break; - } - }); - - this.createUI.apply(this, initParams); - this.addButtons(this.ui.folder); -} - -Wizard.prototype.apply = function(done) { - this.createRequest((request) => { - try { - if (!this.disposed) { - this.onRequestReady(request); - } - } finally { - done(); - } - }); -}; - -Wizard.prototype.onRequestReady = function() {}; // For clients - -Wizard.prototype.okClick = function() { - this.ui.buttons.root.find('.tc-block-btn').eq(1) - .removeClass('active-btn') - .html(''); - this.apply(() => this.dispose()); -}; - -Wizard.prototype.cancelClick = function() { - this.dispose(); -}; - -Wizard.prototype.dispose = function() { - this.disposed = true; - this.ui.box.close(); -}; - -Wizard.prototype.focus = function() { - this.ui.box.root.find('input, select').first().focus() -}; - -Wizard.prototype.addButtons = function(folder) { - this.ui.buttons = new tk.ButtonRow(["Cancel", "OK"], [() => this.cancelClick(), () => this.okClick()]); - tk.add(folder, this.ui.buttons); -}; - -Wizard.InvalidRequest = function(message) { - this.invalidAndShouldBeDropped = true; - this.message = message; -}; - -function OpWizard(viewer, initParams) { - Wizard.call(this, viewer, initParams); - this.previewGroup = new THREE.Object3D(); - this.lines = []; - viewer.scene.add(this.previewGroup); -} - -OpWizard.prototype = Object.create( Wizard.prototype ); - -OpWizard.prototype.setupLine = function(lineId, a, b, material) { - var line = this.lines[lineId]; - if (line === undefined) { - var lg = new THREE.Geometry(); - lg.vertices.push(new THREE.Vector3().copy(a)); - lg.vertices.push(new THREE.Vector3().copy(b)); - line = new THREE.Line(lg, material); - line.renderOrder = 1e10; - this.previewGroup.add(line); - this.lines[lineId] = line; - } else { - line.geometry.vertices[0] = new THREE.Vector3().copy(a); - line.geometry.vertices[1] = new THREE.Vector3().copy(b); - line.geometry.verticesNeedUpdate = true; - } -}; - -OpWizard.prototype.disposeLines = function() { - for (let line of this.lines) { - line.geometry.dispose(); - } -}; - -OpWizard.prototype.dispose = function() { - Wizard.prototype.dispose.call(this); - this.viewer.scene.remove(this.previewGroup); - this.disposeLines(); - this.viewer.render(); -}; - -export {OpWizard, IMAGINE_MATERIAL, IMAGINARY_SURFACE_MATERIAL, BASE_MATERIAL} \ No newline at end of file diff --git a/web/app/cad/scene/wrappers/meshSceneObject.js b/web/app/cad/scene/wrappers/meshSceneObject.js index 26793fde..31939b6b 100644 --- a/web/app/cad/scene/wrappers/meshSceneObject.js +++ b/web/app/cad/scene/wrappers/meshSceneObject.js @@ -1,5 +1,5 @@ import {HashTable} from '../../../utils/hashmap' -import {findOutline, reconstructSketchBounds, segmentsToPaths} from '../../legacy/mesh/workbench' +//import {findOutline, reconstructSketchBounds, segmentsToPaths} from '../../legacy/mesh/workbench' import {isCurveClass} from '../../cad-utils' import {SceneFace, SceneSolid} from './sceneObject'