awv3
Version:
⚡ AWV3 embedded CAD
470 lines (378 loc) • 14.9 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import * as THREE from 'three';
import Object3 from '../../../three/object3';
import Ccfuturef from '../ccfuturef';
import Ccref from '../ccref';
import { addCommand, restrictionCommands } from '../command/highlevel';
import { Assign, IdToReal, Variable, Return, Sequence } from '../command/lowlevel';
import { incidence } from '../constraint/type';
import { drawPointBy_S, drawLineBy_S_E, drawArcBy_S_E_C, drawArcBy_S_E_M, drawArcBy_S_T_E, drawCircleBy_C_E, getTangent } from '../geomutils';
import { updateGeomObjectContainer } from '../preview';
import BaseHandler from './base';
var Mode = Object.freeze({
point: 'point',
line: 'line',
arccenter: 'arccenter',
arcmiddle: 'arcmiddle',
arctangent: 'arctangent',
circle: 'circle'
});
var DrawHandler =
/*#__PURE__*/
function (_BaseHandler) {
_inheritsLoose(DrawHandler, _BaseHandler);
function DrawHandler(sketcher, name) {
var _this;
_this = _BaseHandler.call(this, sketcher, name) || this;
_this.endPoint = null; // ccref of the last point of the polyline
_this.endTangent = null; // normalized THREE.Vector3() tangent of the last edge
_this.positions = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
_this.preview = new THREE.Group();
_this.sketcher.pool.add(_this.preview);
_this.queue = new PromiseQueue();
_this.startPointRestrictions = {};
_this.restrictions = {};
_this.startPoint = null; // ccref of the first point of the polyline
_this.state = 0; // number of element filled in this.positions
_this.statesCount = 2; // number of states needed to create an edge
return _this;
}
var _proto = DrawHandler.prototype;
_proto.destroy = function destroy() {
this.preview.destroy();
this.sketcher.setCursorCoordinates(undefined);
_BaseHandler.prototype.destroy.call(this);
};
_proto.filterObjectsWithInteraction = function filterObjectsWithInteraction(object) {
return object.id === this.sketch.id && object.graphics !== undefined;
};
_proto[Object3.Events.Interaction.Clicked] = function (object, hitObject) {
var _this2 = this;
var ray = hitObject.ray.clone().applyMatrix4(new THREE.Matrix4().getInverse(this.sketch.matrixWorld));
var position = new THREE.Vector3();
ray.intersectPlane(new THREE.Plane(new THREE.Vector3(0, 0, 1)), position);
return this.queue.run(function () {
return _this2.afterEdgeAdded(_this2.click(position));
});
};
_proto.afterEdgeAdded =
/*#__PURE__*/
function () {
var _afterEdgeAdded = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee(geomParams) {
var object, objectStartPoint, manualConstrCommand, command, p, ccref;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (geomParams) {
_context.next = 2;
break;
}
return _context.abrupt("return");
case 2:
object = new Ccfuturef(Variable(), geomParams);
objectStartPoint = object.isCircle() ? object.center : object.startPoint;
manualConstrCommand = this.endPoint && !this.sketcher.autoconstraintIncremental ? addCommand(this.sketch, {
class: incidence.type,
entities: [this.endPoint, objectStartPoint],
value: {}
}) : null;
command = Sequence.apply(void 0, [Assign(object, addCommand(this.sketch, geomParams))].concat(this.sketcher.autoconstraintCommands(object), restrictionCommands(this.sketch, objectStartPoint, this.startPointRestrictions), restrictionCommands(this.sketch, object, this.restrictions), [manualConstrCommand, Return(IdToReal(object))]));
p = this.sketcher.run(command);
this.sketcher.incrementalSolveConstraints();
if (!(!object.isLine() && !object.isArc())) {
_context.next = 11;
break;
}
this.endPolyline();
return _context.abrupt("return", p);
case 11:
_context.t0 = Ccref;
_context.t1 = this.sketcher;
_context.next = 15;
return p;
case 15:
_context.t2 = _context.sent;
ccref = new _context.t0(_context.t1, _context.t2);
this.startPointRestrictions = {};
this.restrictions = {};
this.startPoint = this.startPoint || ccref.startPoint;
this.endPoint = ccref.endPoint || this.endPoint;
this.endTangent = getTangent(ccref.geomParams, this.endPoint.pos);
this.click(this.endPoint.pos);
case 23:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function afterEdgeAdded(_x) {
return _afterEdgeAdded.apply(this, arguments);
};
}();
_proto.cancel = function cancel() {
if (this.state !== 0) this.endPolyline();else _BaseHandler.prototype.cancel.call(this);
};
_proto.endPolyline = function endPolyline() {
this.endPoint = null;
this.endTangent = null;
this.startPointRestrictions = {};
this.restrictions = {};
this.startPoint = null;
this.state = 0;
this.onMouseMove();
};
_proto.closePolyline =
/*#__PURE__*/
function () {
var _closePolyline = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2() {
var geomParams, object, command;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (!(!this.startPoint || !this.endPoint)) {
_context2.next = 2;
break;
}
return _context2.abrupt("return");
case 2:
geomParams = {
start: this.startPoint.pos,
end: this.endPoint.pos
};
object = new Ccfuturef(Variable(), geomParams);
command = Sequence(Assign(object, addCommand(this.sketch, geomParams)), addCommand(this.sketch, {
class: incidence.type,
entities: [this.endPoint, object.startPoint],
value: {}
}), addCommand(this.sketch, {
class: incidence.type,
entities: [object.endPoint, this.startPoint],
value: {}
}));
_context2.next = 7;
return this.sketcher.run(command);
case 7:
this.endPolyline();
case 8:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
return function closePolyline() {
return _closePolyline.apply(this, arguments);
};
}();
_proto.click = function click(position, doSnapping) {
if (doSnapping === void 0) {
doSnapping = true;
}
var geomParams = this.move(position, true, doSnapping);
if (!this.handleClick(this.positions[this.state])) return;
if (++this.state === this.statesCount) {
this.state = 0;
return geomParams;
} else if (this.state === 1) {
this.startPointRestrictions = this.restrictions;
this.restrictions = {};
}
};
_proto.getPreviewGeomParams = function getPreviewGeomParams() {
if (this.state === 0) return drawPointBy_S(this.positions, this.restrictions);
switch (this.name) {
case Mode.point:
return drawPointBy_S(this.positions, this.restrictions);
case Mode.line:
return drawLineBy_S_E(this.positions, this.restrictions);
case Mode.arccenter:
return drawArcBy_S_E_C(this.positions, this.restrictions);
case Mode.arcmiddle:
return drawArcBy_S_E_M(this.positions, this.restrictions);
case Mode.arctangent:
return drawArcBy_S_T_E([this.positions[0], this.endTangent, this.positions[1]], this.restrictions);
case Mode.circle:
return drawCircleBy_C_E(this.positions, this.restrictions);
}
};
_proto.move = function move(position, force, doSnapping) {
if (doSnapping === void 0) {
doSnapping = true;
}
if (!force && this.queue.isBusy()) return;
if (doSnapping) position.copy(this.doSnapping(position));
this.sketcher.setCursorCoordinates(position);
for (var i = this.state; i < this.positions.length; ++i) {
this.positions[i].copy(position);
}
var previewParams = this.getPreviewGeomParams();
if (this.state === 0) this.positions[0].copy(previewParams.start);
updateGeomObjectContainer(this.preview, _extends({
coordinateSystem: this.sketch.graphics.matrix,
scale: this.sketcher.graphicScale
}, previewParams));
return previewParams;
};
_proto.onMouseMove = function onMouseMove() {
this.move(this.getRecentMousePosition());
this.sketcher.refresh();
};
_proto.switchMode = function switchMode(mode) {
if (this.state > 1) this.state = 1;
this.statesCount = mode === Mode.point ? 1 : mode === Mode.arccenter || mode === Mode.arcmiddle ? 3 : 2; // handler switching logic in handler/index.js expects mode to be stored in this.name
this.name = mode;
};
_proto.consoleComplete = function consoleComplete(cmd) {
cmd = cmd.trim();
var tokens = cmd === '' ? [] : cmd.split(/\s+/);
var completions = _BaseHandler.prototype.consoleComplete.call(this, cmd);
if (completions.indexOf(cmd) !== -1) return completions;
return [cmd].concat(this.name.startsWith('point') ? [cmd + " ax", cmd + " ay"] : this.name.startsWith('line') ? [cmd + " l", cmd + " a", cmd + " x", cmd + " y"] : this.name.startsWith('arc') ? [cmd + " a", cmd + " r", cmd + " cw", cmd + " ccw"] : [], completions);
};
_proto.consoleExecute = function consoleExecute(cmd) {
if (_BaseHandler.prototype.consoleExecute.call(this, cmd)) return; // switch handlers
if (cmd === 'cl' || cmd === 'close') return this.closePolyline();else return this.afterEdgeAdded(this.click(this.getRecentMousePosition(), false));
};
_proto.parseRestrictions = function parseRestrictions(cmd) {
var tokens = cmd.trim().split(/\s+/);
this.restrictions = {};
while (tokens.length !== 0) {
var name = tokens.shift();
var value = Number.NaN;
switch (name) {
case 'x':
name = 'xoffset';
value = Number(tokens.shift());
break;
case 'y':
name = 'yoffset';
value = Number(tokens.shift());
break;
case 'ax':
name = 'xabsolute';
value = Number(tokens.shift());
break;
case 'ay':
name = 'yabsolute';
value = Number(tokens.shift());
break;
case 'l':
name = 'length';
value = Number(tokens.shift());
break;
case 'a':
name = 'angle';
value = Math.PI / 180 * Number(tokens.shift());
break;
case 'r':
name = 'radius';
value = Number(tokens.shift());
break;
case 'cw':
name = 'clockwise';
value = true;
break;
case 'ccw':
name = 'clockwise';
value = false;
break;
}
if (!isFinite(value)) continue;
this.restrictions[name] = value;
} // update priview
this.onMouseMove();
};
_proto.doSnapping = function doSnapping(position) {
if (this.preview.geomType === 'CC_Point') return this.createSnapper().snapPoint(position).position;
if (this.preview.geomType === 'CC_Line') return this.createSnapper().snapPoint(position).position;
if (this.preview.geomType === 'CC_Arc') return this.createSnapper().snapPoint(position).position;
return position;
};
_proto.handleClick = function handleClick(position) {
if (!this.endTangent) {
var variants = []; // for all lines/arcs on the sketch
for (var _iterator = this.sketch.children, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _object = _ref;
if (!_object.isLine() && !_object.isArc()) continue; // for their endpoint matching position
var _arr = ['startPoint', 'endPoint'];
for (var _i2 = 0; _i2 < _arr.length; _i2++) {
var end = _arr[_i2];
if (!_object[end].pos.equals(position)) continue;
var tangent = getTangent(_object.geomParams, position);
if (tangent.lengthSq() === 0) continue;
if (end === 'startPoint') tangent.negate();
variants.push(tangent);
}
} // deny click in arctangent mode if doesn't uniquely determine the tangent
if (this.name === 'arctangent' && variants.length !== 1) return false;
this.endTangent = variants[0] || new THREE.Vector3();
return true;
}
return true;
};
return DrawHandler;
}(BaseHandler);
export { DrawHandler as default };
var PromiseQueue =
/*#__PURE__*/
function () {
function PromiseQueue() {
this.nPending = 0;
this.promise = Promise.resolve();
}
var _proto2 = PromiseQueue.prototype;
_proto2.run = function run(functor) {
var _this3 = this;
this.promise = function () {
var _ref2 = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee3(promise) {
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
++_this3.nPending;
_context3.next = 3;
return promise;
case 3:
_context3.next = 5;
return functor();
case 5:
--_this3.nPending;
case 6:
case "end":
return _context3.stop();
}
}
}, _callee3, this);
}));
return function (_x2) {
return _ref2.apply(this, arguments);
};
}()(this.promise);
return this.promise;
};
_proto2.isBusy = function isBusy() {
return this.nPending > 0;
};
return PromiseQueue;
}();