From 61a2df4ee0b7bf752341ea7796a3a0565dd9cde3 Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Mon, 12 Sep 2016 02:48:01 -0700 Subject: [PATCH] sphere wizard --- web/app/3d/cad-utils.js | 19 ++++++++ web/app/3d/ctrl.js | 11 ++++- web/app/3d/wizards/box.js | 21 ++++----- web/app/3d/wizards/extrude.js | 4 +- web/app/3d/wizards/sphere.js | 70 ++++++++++++++++++++++++++++ web/app/3d/wizards/wizard-commons.js | 1 - web/app/3d/workbench.js | 3 ++ web/app/ui/toolkit.js | 15 +++++- 8 files changed, 127 insertions(+), 17 deletions(-) create mode 100644 web/app/3d/wizards/sphere.js diff --git a/web/app/3d/cad-utils.js b/web/app/3d/cad-utils.js index 55fd8383..4f87648e 100644 --- a/web/app/3d/cad-utils.js +++ b/web/app/3d/cad-utils.js @@ -44,6 +44,24 @@ export function createCSGBox(w, h, d) { return createSolid(csg); } +export function createSphere(radius) { + var csg = CSG.sphere({radius: radius, resolution: 48}); + var shared = createShared(); + shared.__tcad.csgInfo = { + derivedFrom : { + id : 0, + _class : 'TCAD.TWO.Circle' + } + }; + for (var i = 0; i < csg.polygons.length; i++) { + var poly = csg.polygons[i]; + poly.shared = shared; + } + var solid = createSolid(csg); + solid.cadGroup.remove(solid.wireframeGroup); + return solid; +} + export function checkPolygon(poly) { if (poly.length < 3) { throw new Error('Polygon should contain at least 3 point'); @@ -439,6 +457,7 @@ export function calculateExtrudedLid(sourcePolygon, normal, direction, expansion var work; var si; if (!!expansionFactor && expansionFactor != 1) { + if (expansionFactor < 0.001) expansionFactor = 0.0001; var source2d = []; work = []; diff --git a/web/app/3d/ctrl.js b/web/app/3d/ctrl.js index 3b3a726d..025d8506 100644 --- a/web/app/3d/ctrl.js +++ b/web/app/3d/ctrl.js @@ -5,6 +5,7 @@ import * as workbench from './workbench' import {ExtrudeWizard} from './wizards/extrude' import {PlaneWizard} from './wizards/plane' import {BoxWizard} from './wizards/box' +import {SphereWizard} from './wizards/sphere' import {TransformWizard} from './wizards/transform' import {IO} from '../sketcher/io' @@ -18,13 +19,14 @@ function UI(app) { var debugFolder = new tk.Folder("Debug"); var exportFolder = new tk.Folder("Export"); var modificationsFolder = new tk.Folder("Modifications"); - var extrude, cut, edit, addPlane, addBox, save, deselectAll, + var extrude, cut, edit, addPlane, addBox, addSphere, save, deselectAll, refreshSketches, showSketches, printSolids, printFace, printFaceId, finishHistory, stlExport; tk.add(mainBox, propFolder); tk.add(propFolder, extrude = new tk.Button("Extrude")); tk.add(propFolder, cut = new tk.Button("Cut")); tk.add(propFolder, edit = new tk.Button("Edit")); tk.add(propFolder, addPlane = new tk.Button("Add a Plane")); + tk.add(propFolder, addSphere = new tk.Button("Add a Sphere")); tk.add(propFolder, addBox = new tk.Button("Add a Box")); tk.add(propFolder, refreshSketches = new tk.Button("Refresh Sketches")); tk.add(propFolder, save = new tk.Button("Save")); @@ -117,6 +119,9 @@ function UI(app) { addBox.root.click(function() { ui.registerWizard(new BoxWizard(app.viewer), false) }); + addSphere.root.click(function() { + ui.registerWizard(new SphereWizard(app.viewer), false) + }); printSolids.root.click(function () { app.findAllSolids().map(function(o) { console.log("Solid ID: " + o.tCadId); @@ -182,6 +187,8 @@ UI.prototype.getInfoForOp = function(op) { return op.type + " (" + p.w + ", " + p.h + ", " + p.d + ")"; } else if ('PLANE' === op.type) { return op.type + " (" + p.depth + ")"; + } else if ('SPHERE' === op.type) { + return op.type + " (" + p.radius + ")"; } return op.type; }; @@ -202,6 +209,8 @@ UI.prototype.createWizardForOperation = function(op) { wizard = new PlaneWizard(this.app.viewer, initParams); } else if ('BOX' === op.type) { wizard = new BoxWizard(this.app.viewer, initParams); + } else if ('SPHERE' === op.type) { + wizard = new SphereWizard(this.app.viewer, initParams); } this.registerWizard(wizard, true); return wizard; diff --git a/web/app/3d/wizards/box.js b/web/app/3d/wizards/box.js index d79b75ea..ca532263 100644 --- a/web/app/3d/wizards/box.js +++ b/web/app/3d/wizards/box.js @@ -8,7 +8,7 @@ export function BoxWizard(viewer, initParams) { this.viewer = viewer; addOkCancelLogic(this); viewer.scene.add(this.previewGroup); - this.previewGroup.add(this.box = this.createBox()); + this.previewGroup.add(this.box = this.createSphere()); if (!initParams) { initParams = BoxWizard.DEFAULT_PARAMS; } @@ -19,19 +19,16 @@ export function BoxWizard(viewer, initParams) { BoxWizard.DEFAULT_PARAMS = [500, 500, 500]; -BoxWizard.prototype.createBox = function() { - var geometry = new THREE.BoxGeometry(100, 100, 100); +BoxWizard.prototype.createSphere = 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) { - function toScale(v) { - return 1 + (v - 100) / 100; - } - this.box.scale.x = toScale(w); - this.box.scale.y = toScale(h); - this.box.scale.z = toScale(d); + this.box.scale.x = w; + this.box.scale.y = h; + this.box.scale.z = d; this.viewer.render(); }; @@ -40,9 +37,9 @@ BoxWizard.prototype.createUI = function(w, h, d) { ui.box = new tk.Box(); var folder = new tk.Folder("Add a Box"); tk.add(ui.box, folder); - ui.width = new tk.Number("Width", w); - ui.height = new tk.Number("Height", h); - ui.depth = new tk.Number("Depth", d); + 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); diff --git a/web/app/3d/wizards/extrude.js b/web/app/3d/wizards/extrude.js index 2b5b58ef..23d45fa7 100644 --- a/web/app/3d/wizards/extrude.js +++ b/web/app/3d/wizards/extrude.js @@ -69,8 +69,8 @@ ExtrudeWizard.prototype.createUI = function (depth, scale, deflection, angle) { ui.box = new tk.Box(); var folder = new tk.Folder(this.invert ? "Cut Options" : "Extrude Options"); tk.add(ui.box, folder); - ui.theValue = new tk.Number(this.invert ? "Depth" : "Height", depth); - ui.scale = new tk.Number("Expansion", scale, 0.1, 1); + ui.theValue = tk.config(new tk.Number(this.invert ? "Depth" : "Height", depth), {min: 0}); + ui.scale = tk.config(new tk.Number("Expansion", scale, 0.1, 1), {min:0}); ui.deflection = new tk.Number("Deflection", deflection, 1); ui.angle = new tk.Number("Angle", angle, 5); var onChange = tk.methodRef(this, "synch"); diff --git a/web/app/3d/wizards/sphere.js b/web/app/3d/wizards/sphere.js new file mode 100644 index 00000000..f889e46f --- /dev/null +++ b/web/app/3d/wizards/sphere.js @@ -0,0 +1,70 @@ +import {AXIS, IDENTITY_BASIS} from '../../math/l3space' +import * as tk from '../../ui/toolkit.js' +import {FACE_COLOR} from '../cad-utils' +import {addOkCancelLogic} from './wizard-commons' + +export function SphereWizard(viewer, initParams) { + this.previewGroup = new THREE.Object3D(); + this.viewer = viewer; + addOkCancelLogic(this); + viewer.scene.add(this.previewGroup); + this.previewGroup.add(this.sphere = this.createSphere()); + if (!initParams) { + initParams = SphereWizard.DEFAULT_PARAMS; + } + this.ui = {}; + this.createUI.apply(this, initParams); + this.synch(); +} + +SphereWizard.DEFAULT_PARAMS = [500]; + +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) { + var ui = this.ui; + ui.box = new tk.Box(); + var folder = new tk.Folder("Add a Sphere"); + tk.add(ui.box, folder); + ui.radius = tk.config(new tk.Number("Radius", radius), {min : 0}); + tk.add(folder, ui.radius); + var onChange = tk.methodRef(this, "synch"); + ui.radius.input.on('t-change', onChange); + tk.add(folder, new tk.ButtonRow(["Cancel", "OK"], [tk.methodRef(this, "cancelClick"), tk.methodRef(this, "okClick")])); +}; + +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() { + var params = this.getParams(); + return { + type: 'SPHERE', + solids : [], + params : {radius : params[0]}, + protoParams : params + } +}; + +SphereWizard.prototype.dispose = function() { + this.viewer.scene.remove(this.previewGroup); + this.ui.box.close(); + this.viewer.render(); +}; diff --git a/web/app/3d/wizards/wizard-commons.js b/web/app/3d/wizards/wizard-commons.js index a2c34e6f..2af9ef7b 100644 --- a/web/app/3d/wizards/wizard-commons.js +++ b/web/app/3d/wizards/wizard-commons.js @@ -56,5 +56,4 @@ OpWizard.prototype.dispose = function() { this.viewer.render(); }; - export {OpWizard, IMAGINE_MATERIAL, BASE_MATERIAL, addOkCancelLogic} \ No newline at end of file diff --git a/web/app/3d/workbench.js b/web/app/3d/workbench.js index 51bf06aa..8cf758d4 100644 --- a/web/app/3d/workbench.js +++ b/web/app/3d/workbench.js @@ -726,5 +726,8 @@ export const OPERATIONS = { BOX : function(app, request) { var p = request.params; return [cad_utils.createCSGBox(p.w, p.h, p.d)]; + }, + SPHERE : function(app, request) { + return [cad_utils.createSphere(request.params.radius)]; } }; diff --git a/web/app/ui/toolkit.js b/web/app/ui/toolkit.js index 1a446ca8..a650b441 100644 --- a/web/app/ui/toolkit.js +++ b/web/app/ui/toolkit.js @@ -71,7 +71,7 @@ export function propLayout(root, name, valueEl) { .append(valueEl)); } -export function Number(name, initValue, baseStep, round) { +function NumberWidget(name, initValue, baseStep, round) { this.root = $('
', {'class': 'tc-row tc-ctrl tc-ctrl-number'}); this.input = $(""); this.slide = false; @@ -124,6 +124,10 @@ export function Number(name, initValue, baseStep, round) { propLayout(this.root, name, this.input); } +NumberWidget.prototype.val = function() { + return Number(this.input.val()); +}; + export function Combo(id, labelText) { this.root = $('
', {'class': 'tc-row tc-ctrl tc-ctrl-combo'}); var label = $('', {'class': 'tc-prop-name', text: labelText}); @@ -285,3 +289,12 @@ Bus.prototype.defineObservable = function(scope, name, eventName, initValue) { } }); }; + +export function config(obj, props) { + for (var key in props) { + obj[key] = props[key]; + } + return obj; +} + +export {NumberWidget as Number}