react-planner
Version:
react-planner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
221 lines (183 loc) • 7.82 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
import { Map, List, Record } from 'immutable';
import * as Geometry from './geometry';
export var SNAP_POINT = 'SNAP_POINT';
export var SNAP_LINE = 'SNAP_LINE';
export var SNAP_SEGMENT = 'SNAP_SEGMENT';
export var SNAP_GRID = 'SNAP_GRID';
export var SNAP_GUIDE = 'SNAP_GUIDE';
export var SNAP_MASK = new Map({
SNAP_POINT: true,
SNAP_LINE: true,
SNAP_SEGMENT: true,
SNAP_GRID: false,
SNAP_GUIDE: true
});
var PointSnap = function (_Record) {
_inherits(PointSnap, _Record);
function PointSnap() {
_classCallCheck(this, PointSnap);
return _possibleConstructorReturn(this, (PointSnap.__proto__ || Object.getPrototypeOf(PointSnap)).apply(this, arguments));
}
_createClass(PointSnap, [{
key: 'nearestPoint',
value: function nearestPoint(x, y) {
return {
x: this.x,
y: this.y,
distance: Geometry.pointsDistance(this.x, this.y, x, y)
};
}
}, {
key: 'isNear',
value: function isNear(x, y, distance) {
return ~(this.x - x) + 1 < distance && ~(this.y - y) + 1 < distance;
}
}]);
return PointSnap;
}(Record({
type: 'point',
x: -1, y: -1,
radius: 1, priority: 1,
related: new List()
}));
var LineSnap = function (_Record2) {
_inherits(LineSnap, _Record2);
function LineSnap() {
_classCallCheck(this, LineSnap);
return _possibleConstructorReturn(this, (LineSnap.__proto__ || Object.getPrototypeOf(LineSnap)).apply(this, arguments));
}
_createClass(LineSnap, [{
key: 'nearestPoint',
value: function nearestPoint(x, y) {
return _extends({}, Geometry.closestPointFromLine(this.a, this.b, this.c, x, y), {
distance: Geometry.distancePointFromLine(this.a, this.b, this.c, x, y)
});
}
}, {
key: 'isNear',
value: function isNear(x, y, distance) {
return true;
}
}]);
return LineSnap;
}(Record({
type: 'line',
a: -1, b: -1, c: -1,
radius: 1, priority: 1,
related: new List()
}));
var LineSegmentSnap = function (_Record3) {
_inherits(LineSegmentSnap, _Record3);
function LineSegmentSnap() {
_classCallCheck(this, LineSegmentSnap);
return _possibleConstructorReturn(this, (LineSegmentSnap.__proto__ || Object.getPrototypeOf(LineSegmentSnap)).apply(this, arguments));
}
_createClass(LineSegmentSnap, [{
key: 'nearestPoint',
value: function nearestPoint(x, y) {
return _extends({}, Geometry.closestPointFromLineSegment(this.x1, this.y1, this.x2, this.y2, x, y), {
distance: Geometry.distancePointFromLineSegment(this.x1, this.y1, this.x2, this.y2, x, y)
});
}
}, {
key: 'isNear',
value: function isNear(x, y, distance) {
return true;
}
}]);
return LineSegmentSnap;
}(Record({
type: 'line-segment',
x1: -1, y1: -1, x2: -1, y2: -1,
radius: 1, priority: 1,
related: new List()
}));
var GridSnap = function (_Record4) {
_inherits(GridSnap, _Record4);
function GridSnap() {
_classCallCheck(this, GridSnap);
return _possibleConstructorReturn(this, (GridSnap.__proto__ || Object.getPrototypeOf(GridSnap)).apply(this, arguments));
}
_createClass(GridSnap, [{
key: 'nearestPoint',
value: function nearestPoint(x, y) {
return {
x: this.x,
y: this.y,
distance: Geometry.pointsDistance(this.x, this.y, x, y)
};
}
}, {
key: 'isNear',
value: function isNear(x, y, distance) {
return ~(this.x - x) + 1 < distance && ~(this.y - y) + 1 < distance;
}
}]);
return GridSnap;
}(Record({
type: 'grid',
x: -1, y: -1,
radius: 1, priority: 1,
related: new List()
}));
export function nearestSnap(snapElements, x, y, snapMask) {
var filter = {
'point': snapMask.get(SNAP_POINT),
'line': snapMask.get(SNAP_LINE),
'line-segment': snapMask.get(SNAP_SEGMENT),
'grid': snapMask.get(SNAP_GRID)
};
return snapElements.valueSeq().filter(function (el) {
return filter[el.type] && el.isNear(x, y, el.radius);
}).map(function (snap) {
return { snap: snap, point: snap.nearestPoint(x, y) };
}).filter(function (_ref) {
var radius = _ref.snap.radius,
distance = _ref.point.distance;
return distance < radius;
}).min(function (_ref2, _ref3) {
var p1 = _ref2.snap.priority,
d1 = _ref2.point.distance;
var p2 = _ref3.snap.priority,
d2 = _ref3.point.distance;
return p1 === p2 ? d1 < d2 ? -1 : 1 : p1 > p2 ? -1 : 1;
});
}
export function addPointSnap(snapElements, x, y, radius, priority, related) {
related = new List([related]);
return snapElements.push(new PointSnap({ x: x, y: y, radius: radius, priority: priority, related: related }));
}
export function addLineSnap(snapElements, a, b, c, radius, priority, related) {
related = new List([related]);
return snapElements.withMutations(function (snapElements) {
var alreadyPresent = snapElements.some(function (lineSnap) {
return lineSnap.type === 'line' && a === lineSnap.a && b === lineSnap.b && c === lineSnap.c;
});
if (alreadyPresent) return snapElements;
var intersections = snapElements.valueSeq().filter(function (snap) {
return snap.type === 'line';
}).map(function (snap) {
return Geometry.twoLinesIntersection(snap.a, snap.b, snap.c, a, b, c);
}).filter(function (intersection) {
return intersection !== undefined;
}).forEach(function (_ref4) {
var x = _ref4.x,
y = _ref4.y;
return addPointSnap(snapElements, x, y, 20, 40);
});
snapElements.push(new LineSnap({ a: a, b: b, c: c, radius: radius, priority: priority, related: related }));
});
}
export function addLineSegmentSnap(snapElements, x1, y1, x2, y2, radius, priority, related) {
related = new List([related]);
return snapElements.push(new LineSegmentSnap({ x1: x1, y1: y1, x2: x2, y2: y2, radius: radius, priority: priority, related: related }));
}
export function addGridSnap(snapElements, x, y, radius, priority, related) {
related = new List([related]);
return snapElements.push(new GridSnap({ x: x, y: y, radius: radius, priority: priority, related: related }));
}