awv3
Version:
⚡ AWV3 embedded CAD
240 lines (199 loc) • 8.88 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DSU = undefined;
var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _map = require('babel-runtime/core-js/map');
var _map2 = _interopRequireDefault(_map);
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _highlevel = require('../command/highlevel');
var _index = require('./index');
var _index2 = _interopRequireDefault(_index);
var _type = require('./type');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var ConstraintAdder = function () {
function ConstraintAdder(sketch) {
(0, _classCallCheck3.default)(this, ConstraintAdder);
// the sketch we are going to add constraints to
this.sketch = sketch;
// the list of constraint geomParams which really should be added
this.constraints = [];
// dsu structures for incident and inc-tangent point groups
this.incidenceDsu = new DSU();
//this.tangencyDsu = new DSU(); // TODO!
// sets of horizontal and vertical lines
this.horizontalSet = new _set2.default();
this.verticalSet = new _set2.default();
// preprocess all objects and constraints currently on sketch
this.init();
}
(0, _createClass3.default)(ConstraintAdder, [{
key: 'init',
value: function init() {
// take all present constraints into account
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(this.sketch.children), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var object = _step.value;
switch (object.state.class) {
case _type.incidence.type:
this.incidenceDsu.merge(object.entities[0].id, object.entities[1].id);break;
case _type.verticality.type:
this.verticalSet.add(object.entities[0].id);break;
case _type.horizontality.type:
this.horizontalSet.add(object.entities[0].id);break;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
// add a new constraint to the internal buffer (if it is not excessive)
}, {
key: 'add',
value: function add(type, entities) {
var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (type.type !== undefined) type = type.type;
var geomParams = { class: type, entities: entities, value: value };
// if a new constraint is not excessive, then take it into account
switch (type) {
case _type.incidence.type:
// TODO: implement more complicated handling of incidence
// Incidence is an equivalence either on points or on lines / arcs, but not on both together.
// E.g.: if a point is incident to two lines, then these lines may be NOT incident.
if (this.incidenceDsu.getHead(entities[0].id) !== this.incidenceDsu.getHead(entities[1].id)) this.incidenceDsu.merge(entities[0].id, entities[1].id);else return;
break;
case _type.verticality.type:
if (!this.verticalSet.has(entities[0].id)) this.verticalSet.add(entities[0].id);else return;
break;
case _type.horizontality.type:
if (!this.horizontalSet.has(entities[0].id)) this.horizontalSet.add(entities[0].id);else return;
break;
default:
// TODO: optimize this O(N) search
if (this.constraints.some(function (constr) {
return isExcessive(geomParams, constr);
})) return;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = (0, _getIterator3.default)(this.sketch.children), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var object = _step2.value;
if (isExcessive(geomParams, object.geomParams)) return;
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
break;
}
this.constraints.push(geomParams);
}
// return constraint statements in the internal buffer, clear the buffer
}, {
key: 'commit',
value: function commit() {
var _this = this;
var statements = this.constraints.map(function (geomParams) {
return (0, _highlevel.addCommand)(_this.sketch, geomParams);
});
this.constraints = [];
return statements;
}
}]);
return ConstraintAdder;
}();
exports.default = ConstraintAdder;
function isExcessive(constr0, constr1) {
if (constr0.class !== constr1.class) return false;
if (constr0.entities.length !== constr1.entities.length) return false;
if (constr0.value.value || constr1.value.value || constr0.value.expression || constr1.value.expression) return false; // ignore parametric constraints
if (constr0.entities.every(function (obj, idx) {
return obj.id === constr1.entities[idx].id;
})) return true;
var isBinaryCommutative = (0, _index2.default)(constr0.class).isCommutative;
if (isBinaryCommutative && constr0.entities.every(function (obj, idx) {
return obj.id === constr1.entities[1 - idx].id;
})) return true;
return false;
}
// Disjoint Set Union
var DSU = exports.DSU = function () {
function DSU() {
(0, _classCallCheck3.default)(this, DSU);
this.parents = new _map2.default();
}
(0, _createClass3.default)(DSU, [{
key: 'getParent',
value: function getParent(obj) {
return this.parents.has(obj) ? this.parents.get(obj) : obj;
}
}, {
key: 'setParent',
value: function setParent(obj, par) {
this.parents.set(obj, par);
}
}, {
key: 'touch',
value: function touch(obj) {
if (!this.parents.has(obj)) this.parents.set(obj, obj);
}
}, {
key: 'getHead',
value: function getHead(obj) {
var par = this.getParent(obj);
if (par === obj) return obj;
var head = this.getHead(par);
this.setParent(obj, head);
return head;
}
}, {
key: 'merge',
value: function merge(objA, objB) {
this.touch(objA);
this.touch(objB);
objA = this.getHead(objA);
objB = this.getHead(objB);
Math.random() < 0.5 ? this.setParent(objA, objB) : this.setParent(objB, objA);
}
}, {
key: 'getTouched',
value: function getTouched() {
return (0, _from2.default)(this.parents.keys());
}
}]);
return DSU;
}();