removed old unused functionality.

This commit is contained in:
Mike Molinari 2022-07-25 02:49:55 +00:00 committed by Val Erastov
parent 78df458e9d
commit 69bf713fea
14 changed files with 1 additions and 1314 deletions

View file

@ -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}
}

View file

@ -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();

View file

@ -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: $('<div class="errors-message" />')});
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 = {};

View file

@ -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;
};

View file

@ -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;

View file

@ -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();
};

View file

@ -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()
});
};

View file

@ -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
});
}
});
};

View file

@ -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();
};

View file

@ -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;
}

View file

@ -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();
};

View file

@ -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();
};

View file

@ -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('<i class="fa fa-cog fa-spin"></i>');
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}

View file

@ -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'