awv3
Version:
⚡ AWV3 embedded CAD
207 lines (172 loc) • 6.43 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _createClass from "@babel/runtime/helpers/createClass";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import * as THREE from 'three';
import cloneDeep from 'lodash/cloneDeep';
import { collectNestedIds } from '../session/helpers';
var SCALE = 6;
var geometry = new THREE.SphereBufferGeometry(1, 6, 6);
var inverseMatrix = new THREE.Matrix4();
var ray = new THREE.Ray();
var sphere = new THREE.Sphere();
/**
* @class Region contains vertices from ClassCAD, which are not visible, but
* can be selected through raycasting and then be created with the given
* information {id, point, meta}.
*/
var Region =
/*#__PURE__*/
function (_THREE$Object3D) {
_inheritsLoose(Region, _THREE$Object3D);
function Region() {
var _this;
_this = _THREE$Object3D.call(this) || this;
_this.type = 'Region';
_this.boundingSphere = new THREE.Sphere();
_this.pointSphere = new THREE.Sphere();
_this.points = [];
_this._visible = false;
_this.viewFound().then(function (view) {
_this.createInteraction().on(THREE.Object3D.Events.Lifecycle.Rendered, function () {
_this.visible && _this.children.forEach(function (point) {
var scaleFactor = view.calculateScaleFactor(_this.localToWorld(point.position.clone()), SCALE);
point.scale.set(scaleFactor, scaleFactor, scaleFactor);
});
});
});
return _this;
}
var _proto = Region.prototype;
_proto.destroyPoints = function destroyPoints() {
if (this.points) {
this.points.forEach(function (point) {
if (point.meta.ref) {
point.meta.ref.destroy();
point.meta.ref = undefined;
}
});
}
};
_proto.createPoint = function createPoint(point, factor) {
if (!point || point.meta.ref) return;
if (factor == undefined) {
factor = point.meta.ref ? point.meta.ref.scale.x : this.view ? this.view.calculateScaleFactor(this.localToWorld(point.meta.position.clone()), SCALE) : 1;
}
var opacity = point.meta.static === true ? 0.1 : 0;
var material = new THREE.MeshBasicMaterial({
color: 0,
transparent: true,
opacity: opacity
});
material.meta = _extends({
id: point.id
}, point.meta, {
material: {
opacity: opacity,
color: new THREE.Color(0)
}
});
var mesh = new THREE.Mesh(geometry, material);
mesh.type = 'RegionPoint';
mesh.position.copy(point.meta.position);
mesh.interactive = false;
mesh.measurable = false;
mesh.renderOrder = 1000;
mesh.scale.set(factor, factor, factor);
point.meta.ref = mesh;
this.add(mesh); // Generate a nested ID to make points assembly safe
material.meta.nestedId = collectNestedIds(mesh).concat([material.meta.id]).join(',');
};
_proto.addPoint = function addPoint(props) {
if (!this.isDuplicatePoint(props.meta.position)) this.points.push(props);
};
_proto.isDuplicatePoint = function isDuplicatePoint(position) {
// TODO: making it more efficient
for (var _iterator = this.points, _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 _point = _ref;
if (_point.meta.position.distanceToSquared(position) < 1e-4 * 1e-4) return true;
}
return false;
};
/**
* This code is mostly copied form THREE.Points.js and adjusted to the fact
* that Region does not have geometry or graphical representation
*/
_proto.raycast = function raycast(raycaster, intersects) {
var _this2 = this;
if (!this.visible) return; // Checking boundingSphere distance to ray
sphere.copy(this.boundingSphere);
sphere.radius += raycaster.params.Points.threshold;
sphere.applyMatrix4(this.matrixWorld);
if (raycaster.ray.intersectsSphere(sphere) === false) return;
inverseMatrix.getInverse(this.matrixWorld);
ray.copy(raycaster.ray).applyMatrix4(inverseMatrix); //test each point
this.points.forEach(function (point, index) {
var child = point.meta.ref;
var scaleFactor = child ? child.scale.x : _this2.view ? _this2.view.calculateScaleFactor(_this2.localToWorld(point.meta.position.clone()), SCALE) : 1;
_this2.pointSphere.center = point.meta.position.clone();
_this2.pointSphere.radius = scaleFactor;
var intersectPoint = ray.intersectSphere(_this2.pointSphere);
if (intersectPoint === null) return;
var rayPointDistanceSq = ray.distanceSqToPoint(_this2.pointSphere.center); // Move back to world space for distance calculation
intersectPoint.applyMatrix4(_this2.matrixWorld);
var distance = raycaster.ray.origin.distanceTo(intersectPoint);
if (distance < raycaster.near || distance > raycaster.far) return;
_this2.createPoint(point, scaleFactor);
intersects.push({
distance: distance,
point: intersectPoint.clone(),
index: index,
face: null,
object: _this2,
ref: point.meta.ref.material
});
});
};
/**
* Computes the bounding sphere of the points (in model coordinates).
*/
_proto.computeBoundingSphere = function computeBoundingSphere() {
if (this.points) {
this.boundingSphere.setFromPoints(this.points.map(function (entry) {
return entry.meta.position;
}));
}
};
_proto.clone = function clone() {
this.destroyPoints();
var clone = _THREE$Object3D.prototype.clone.call(this);
clone.points = cloneDeep(this.points); // TODO: WHY???
clone.visible = this.visible;
clone.computeBoundingSphere();
return clone;
};
_createClass(Region, [{
key: "visible",
get: function get() {
return this._visible;
},
set: function set(value) {
var _this3 = this;
this._visible = value;
if (this.points) {
this.destroyPoints();
if (value === true) this.points.forEach(function (point, index) {
return point.meta.static && _this3.createPoint(point);
});
this.computeBoundingSphere();
}
}
}]);
return Region;
}(THREE.Object3D);
export { Region as default };