mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-08 09:24:18 +01:00
rotate datum operation
This commit is contained in:
parent
df742b81d6
commit
49dffd435b
13 changed files with 152 additions and 24 deletions
|
|
@ -3,7 +3,6 @@ import {Geometry, Line, LineBasicMaterial, MeshBasicMaterial, Object3D, Vector3}
|
|||
|
||||
import CSysObject3D from './csysObject';
|
||||
import {NOOP} from 'gems/func';
|
||||
import {findAncestor} from '../../../../../modules/scene/sceneGraph';
|
||||
|
||||
export default class DatumObject3D extends Object3D {
|
||||
|
||||
|
|
@ -32,6 +31,7 @@ export default class DatumObject3D extends Object3D {
|
|||
this.add(this.csysObj);
|
||||
this.exitEditMode = NOOP;
|
||||
this.beingDraggedAxis = null;
|
||||
this.freezeDragging = false;
|
||||
}
|
||||
|
||||
setMoveMode(axis) {
|
||||
|
|
@ -136,6 +136,9 @@ export default class DatumObject3D extends Object3D {
|
|||
function addOnHoverBehaviour(handle, viewer) {
|
||||
handle.onMouseDown = function(e, hits, startDrag) {
|
||||
let datum = this.parent.parent.parent;
|
||||
if (datum.freezeDraggin) {
|
||||
return;
|
||||
}
|
||||
startDrag(datum);
|
||||
datum.dragStart(e, this.parent);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
export default {
|
||||
datum: {
|
||||
type: 'datum'
|
||||
type: 'datum',
|
||||
defaultValue: {type: 'selection'}
|
||||
},
|
||||
x: {
|
||||
type: 'number',
|
||||
|
|
|
|||
|
|
@ -51,12 +51,8 @@ function previewer(ctx, initialParams, updateParams) {
|
|||
function dispose() {
|
||||
datum3D.csys.copy(mDatum.csys);
|
||||
datum3D.finishOperation();
|
||||
datum3D.operationStarted = false;
|
||||
datum3D.exitEditMode();
|
||||
datum3D.applyMove = NOOP;
|
||||
}
|
||||
|
||||
|
||||
update(initialParams);
|
||||
|
||||
return {
|
||||
|
|
|
|||
15
web/app/cad/craft/datum/rotate/RotateDatumWizard.jsx
Normal file
15
web/app/cad/craft/datum/rotate/RotateDatumWizard.jsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
import {Group} from '../../wizard/components/form/Form';
|
||||
import {NumberField, RadioButtonsField} from '../../wizard/components/form/Fields';
|
||||
import {RadioButton} from 'ui/components/controls/RadioButtons';
|
||||
|
||||
export default function RotateDatumWizard() {
|
||||
return <Group>
|
||||
<RadioButtonsField name='axis'>
|
||||
<RadioButton value='X' />
|
||||
<RadioButton value='Y' />
|
||||
<RadioButton value='Z' />
|
||||
</RadioButtonsField>
|
||||
<NumberField name='angle' />
|
||||
</Group>;
|
||||
}
|
||||
15
web/app/cad/craft/datum/rotate/rotateDatumOpSchema.js
Normal file
15
web/app/cad/craft/datum/rotate/rotateDatumOpSchema.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export default {
|
||||
datum: {
|
||||
type: 'datum',
|
||||
defaultValue: {type: 'selection'}
|
||||
},
|
||||
axis: {
|
||||
type: 'enum',
|
||||
values: ['X', 'Y', 'Z'],
|
||||
defaultValue: 'X'
|
||||
},
|
||||
angle: {
|
||||
type: 'number',
|
||||
defaultValue: 0
|
||||
}
|
||||
}
|
||||
79
web/app/cad/craft/datum/rotate/rotateDatumOperation.js
Normal file
79
web/app/cad/craft/datum/rotate/rotateDatumOperation.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import schema from './rotateDatumOpSchema';
|
||||
import {MDatum} from '../../../model/mdatum';
|
||||
import RotateDatumWizard from './RotateDatumWizard';
|
||||
import {Matrix3, ORIGIN} from '../../../../math/l3space';
|
||||
import {DEG_RAD} from '../../../../math/math';
|
||||
|
||||
|
||||
function rotate(params, {cadRegistry}) {
|
||||
|
||||
let mDatum = cadRegistry.findDatum(params.datum);
|
||||
|
||||
let axis = mDatum.csys[params.axis.toLowerCase()];
|
||||
|
||||
let csys = mDatum.csys.clone();
|
||||
|
||||
applyRotation(mDatum.csys, csys, params.angle, axis);
|
||||
|
||||
return {
|
||||
outdated: [mDatum],
|
||||
created: [new MDatum(csys)]
|
||||
}
|
||||
}
|
||||
|
||||
let auxMatrix = new Matrix3();
|
||||
|
||||
function previewer(ctx, initialParams) {
|
||||
|
||||
let mDatum = ctx.services.cadRegistry.findDatum(initialParams.datum);
|
||||
|
||||
if (!mDatum) {
|
||||
return null;
|
||||
}
|
||||
let view = mDatum.ext.view;
|
||||
if (!view) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let datum3D = view.rootGroup;
|
||||
datum3D.beginOperation(true);
|
||||
|
||||
function update(params) {
|
||||
let axis = mDatum.csys[params.axis.toLowerCase()];
|
||||
applyRotation(mDatum.csys, datum3D.csys, params.angle, axis);
|
||||
}
|
||||
|
||||
function dispose() {
|
||||
datum3D.csys.copy(mDatum.csys);
|
||||
datum3D.finishOperation();
|
||||
}
|
||||
|
||||
|
||||
update(initialParams);
|
||||
|
||||
return {
|
||||
update, dispose
|
||||
}
|
||||
}
|
||||
|
||||
function applyRotation(origCsys, csys, angle, axis) {
|
||||
auxMatrix.rotate(angle * DEG_RAD, axis, ORIGIN);
|
||||
auxMatrix.__apply(origCsys.x, csys.x);
|
||||
auxMatrix.__apply(origCsys.y, csys.y);
|
||||
auxMatrix.__apply(origCsys.z, csys.z);
|
||||
}
|
||||
|
||||
export default {
|
||||
id: 'DATUM_ROTATE',
|
||||
label: 'Rotate Datum',
|
||||
icon: 'img/cad/plane',
|
||||
info: 'rotates a datum',
|
||||
paramsInfo: ({axis, angle}) => `${axis} - ${angle}`,
|
||||
previewer,
|
||||
run: rotate,
|
||||
form: RotateDatumWizard,
|
||||
schema
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ export default [
|
|||
label: 'datum',
|
||||
cssIcons: ['magic'],
|
||||
info: 'operations on datum',
|
||||
actions: ['DATUM_MOVE']
|
||||
actions: ['DATUM_ROTATE', 'DATUM_MOVE']
|
||||
// actions: ['DATUM_MOVE', 'DATUM_ROTATE', 'DATUM_REBASE', '-', 'PLANE_FROM_DATUM', 'BOX', 'SPHERE', 'TORUS',
|
||||
// 'CONE', 'CYLINDER']
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import filletOperation from '../craft/fillet/filletOperation';
|
|||
import revolveOperation from '../craft/revolve/revolveOperation';
|
||||
import createDatumOperation from '../craft/datum/create/createDatumOperation';
|
||||
import moveDatumOperation from '../craft/datum/move/moveDatumOperation';
|
||||
import rotateDatumOperation from '../craft/datum/rotate/rotateDatumOperation';
|
||||
|
||||
export function activate({services}) {
|
||||
services.operation.registerOperations([
|
||||
|
|
@ -16,6 +17,7 @@ export function activate({services}) {
|
|||
revolveOperation,
|
||||
filletOperation,
|
||||
createDatumOperation,
|
||||
moveDatumOperation
|
||||
moveDatumOperation,
|
||||
rotateDatumOperation
|
||||
])
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import * as mask from 'gems/mask'
|
||||
import {getAttribute, setAttribute} from 'scene/objectData';
|
||||
import {FACE, EDGE, SKETCH_OBJECT} from '../entites';
|
||||
import {FACE, EDGE, SKETCH_OBJECT, DATUM} from '../entites';
|
||||
import {state} from 'lstream';
|
||||
|
||||
export const PICK_KIND = {
|
||||
|
|
@ -9,7 +9,7 @@ export const PICK_KIND = {
|
|||
EDGE: mask.type(3)
|
||||
};
|
||||
|
||||
const SELECTABLE_ENTITIES = [FACE, EDGE, SKETCH_OBJECT];
|
||||
const SELECTABLE_ENTITIES = [FACE, EDGE, SKETCH_OBJECT, DATUM];
|
||||
|
||||
export function activate(context) {
|
||||
const {services, streams} = context;
|
||||
|
|
@ -130,10 +130,8 @@ export function defineStreams({streams}) {
|
|||
streams.selection = {
|
||||
};
|
||||
SELECTABLE_ENTITIES.forEach(entity => {
|
||||
let selectionState = state([]);
|
||||
streams.selection[entity] = state([]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function initStateAndServices({streams, services}) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export function activate(context) {
|
|||
streams.sketcher.update.attach(mFace => mFace.ext.view.updateSketch());
|
||||
}
|
||||
|
||||
function sceneSynchronizer({services: {cadScene, cadRegistry, viewer, wizard, action}}) {
|
||||
function sceneSynchronizer({services: {cadScene, cadRegistry, viewer, wizard, action, selection}}) {
|
||||
return function() {
|
||||
let wgChildren = cadScene.workGroup.children;
|
||||
let existent = new Set();
|
||||
|
|
@ -42,7 +42,10 @@ function sceneSynchronizer({services: {cadScene, cadRegistry, viewer, wizard, ac
|
|||
} else if (model instanceof MShell) {
|
||||
modelView = new ShellView(model);
|
||||
} else if (model instanceof MDatum) {
|
||||
modelView = new DatumView(model, viewer, wizard.open, (e) => action.run('menu.datum', e));
|
||||
modelView = new DatumView(model, viewer,
|
||||
wizard.open,
|
||||
datumId => selection.datum.select([datumId]),
|
||||
e => action.run('menu.datum', e));
|
||||
} else {
|
||||
console.warn('unsupported model ' + model);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ import {DATUM} from '../entites';
|
|||
import {setAttribute} from 'scene/objectData';
|
||||
import {Mesh, MeshBasicMaterial, PolyhedronGeometry, SphereGeometry} from 'three';
|
||||
import {CSYS_SIZE_MODEL} from '../../craft/datum/csysObject';
|
||||
import {NOOP} from '../../../../../modules/gems/func';
|
||||
|
||||
export default class DatumView extends View {
|
||||
|
||||
constructor(datum, viewer, beginOperation, showDatumMenu) {
|
||||
constructor(datum, viewer, beginOperation, selectDatum, showDatumMenu) {
|
||||
super(datum);
|
||||
|
||||
class MenuButton extends Mesh {
|
||||
|
|
@ -54,6 +55,7 @@ export default class DatumView extends View {
|
|||
}
|
||||
|
||||
onMouseClick(e) {
|
||||
selectDatum(datum.id);
|
||||
showDatumMenu({
|
||||
x: e.offsetX,
|
||||
y: e.offsetY
|
||||
|
|
@ -101,23 +103,24 @@ export default class DatumView extends View {
|
|||
|
||||
dragStart(e, axis) {
|
||||
if (!this.operationStarted) {
|
||||
beginOperation('DATUM_MOVE', {
|
||||
datum: datum.id
|
||||
});
|
||||
selectDatum(datum.id);
|
||||
beginOperation('DATUM_MOVE');
|
||||
this.beginOperation();
|
||||
}
|
||||
super.dragStart(e, axis);
|
||||
}
|
||||
|
||||
beginOperation() {
|
||||
beginOperation(freezeDragging = false) {
|
||||
this.freezeDragging = freezeDragging;
|
||||
this.operationStarted = true;
|
||||
this.menuButton.updateVisibility();
|
||||
}
|
||||
|
||||
finishOperation() {
|
||||
this.freezeDragging = false;
|
||||
this.operationStarted = false;
|
||||
this.exitEditMode();
|
||||
this.menuButton.updateVisibility();
|
||||
this.exitEditMode();
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@ Matrix3.prototype.setBasis = function(basis) {
|
|||
return this;
|
||||
};
|
||||
|
||||
Matrix3.prototype.setBasisAxises = function(x, y, z) {
|
||||
this.mxx = x.x; this.mxy = y.x; this.mxz = z.x; this.tx = 0;
|
||||
this.myx = x.y; this.myy = y.y; this.myz = z.y; this.ty = 0;
|
||||
this.mzx = x.z; this.mzy = y.z; this.mzz = z.z; this.tz = 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
Matrix3.prototype.scale = function(dx, dy, dz) {
|
||||
this.mxx *= dx;
|
||||
this.myy *= dy;
|
||||
|
|
@ -143,7 +150,7 @@ Matrix3.prototype.__invert = function(out) {
|
|||
return out;
|
||||
};
|
||||
|
||||
Matrix3.prototype.combine = function(transform) {
|
||||
Matrix3.prototype.combine = function(transform, out) {
|
||||
var txx = transform.mxx;
|
||||
var txy = transform.mxy;
|
||||
var txz = transform.mxz;
|
||||
|
|
@ -157,7 +164,7 @@ Matrix3.prototype.combine = function(transform) {
|
|||
var tzz = transform.mzz;
|
||||
var ttz = transform.tz;
|
||||
|
||||
var m = new Matrix3();
|
||||
var m = out || new Matrix3();
|
||||
m.mxx = (this.mxx * txx + this.mxy * tyx + this.mxz * tzx);
|
||||
m.mxy = (this.mxx * txy + this.mxy * tyy + this.mxz * tzy);
|
||||
m.mxz = (this.mxx * txz + this.mxy * tyz + this.mxz * tzz);
|
||||
|
|
@ -207,11 +214,15 @@ Matrix3.prototype.__apply3 = function([x, y, z], out) {
|
|||
return out;
|
||||
};
|
||||
|
||||
Matrix3.rotateMatrix = function(angle, axis, pivot) {
|
||||
Matrix3.prototype.rotate = function(angle, axis, pivot) {
|
||||
return Matrix3.rotateMatrix(angle, axis, pivot, this);
|
||||
};
|
||||
|
||||
Matrix3.rotateMatrix = function(angle, axis, pivot, matrix) {
|
||||
var sin = Math.sin(angle);
|
||||
var cos = Math.cos(angle);
|
||||
var axisX, axisY, axisZ;
|
||||
var m = new Matrix3();
|
||||
var m = matrix || new Matrix3();
|
||||
|
||||
if (axis === AXIS.X || axis === AXIS.Y || axis === AXIS.Z) {
|
||||
axisX = axis.x;
|
||||
|
|
|
|||
|
|
@ -245,4 +245,6 @@ export function perpendicularVector(v) {
|
|||
.sort((a, b) => vec.lengthSq(b) - vec.lengthSq(a))[0];
|
||||
}
|
||||
|
||||
export const DEG_RAD = Math.PI / 180.0;
|
||||
|
||||
export const sq = (a) => a * a;
|
||||
|
|
|
|||
Loading…
Reference in a new issue