UNPKG

kitchen-simulator

Version:

It is a kitchen simulator (self-contained micro-frontend).

1,122 lines (1,106 loc) 121 kB
'use strict'; import _readOnlyError from "@babel/runtime/helpers/esm/readOnlyError"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf"; import _inherits from "@babel/runtime/helpers/esm/inherits"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } import React from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import * as Three from 'three'; import { checkCabinetOverlap, createBacksplash, deleteSpecifiedMeshObjects, fVLine, getDistances, parseData, updateScene, visibleTransformBox } from "./scene-creator"; import { disposeObject, disposeScene } from "./three-memory-cleaner"; import diff from 'immutablediff'; import * as SharedStyle from "../../shared-style"; import { BASE_CABINET_LAYOUTPOS, MODE_3D_VIEW, MODE_DRAGGING_ITEM_3D, MODE_DRAWING_HOLE_3D, MODE_DRAWING_ITEM_3D, MODE_ELEVATION_VIEW, MODE_IDLE_3D, MODE_ROTATING_ITEM_3D, SECONDARY_PURPLE_COLOR, TALL_CABINET_LAYOUTPOS, UNIT_CENTIMETER, WALL_CABINET_LAYOUTPOS } from "../../constants"; import { isUndefined } from 'util'; import { verticesDistance } from "../../utils/geometry"; import { convert } from "../../utils/convert-units-lite"; import { GeometryUtils } from "../../utils/export"; import { handleCamRect, isElevationView, isEmpty } from "../../utils/helper"; import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'; import CameraControls from 'camera-controls'; import { returnReplaceableDeepSearchType } from "../viewer2d/utils"; import { getAllMeshes, vectorIntersectWithMesh } from "../../utils/objects-utils"; CameraControls.install({ THREE: Three }); var Scene3DViewer = /*#__PURE__*/function (_React$Component) { function Scene3DViewer(props) { var _this; _classCallCheck(this, Scene3DViewer); _this = _callSuper(this, Scene3DViewer, [props]); _this.state = { isLoading: false, showflag: true, isLoadingCabinet: props.state.scene.isLoadingCabinet, toolObj: null, angleObj: null, waitForRender: 0, lineLength: null // when view wall's elevation, that wall's length }; _this.lastMousePosition = {}; _this.width = props.width; _this.height = props.height; _this.renderingID = 0; var mode = props.state.mode; if (!window.__elevationRendererDownload) { window.__elevationRendererDownload = {}; } switch (mode) { case MODE_IDLE_3D: _this.renderer = window.__threeRenderer || new Three.WebGLRenderer({ preserveDrawingBuffer: true, alpha: true, antialias: true }); break; case MODE_3D_VIEW: _this.renderer = window.__threeRendererDownload || new Three.WebGLRenderer({ preserveDrawingBuffer: true, alpha: true, antialias: true }); break; default: if (_this.props.downloadFlag) { _this.renderer = window.__elevationRendererDownload[mode] || new Three.WebGLRenderer({ preserveDrawingBuffer: true, alpha: true, antialias: true }); } else { _this.renderer = window.__elevationRenderer || new Three.WebGLRenderer({ preserveDrawingBuffer: true, alpha: true, antialias: true }); } break; } _this.renderer.shadowMap.enabled = true; _this.renderer.shadowMapSoft = true; if (mode == 'MODE_IDLE_3D') { window.__threeRenderer = _this.renderer; } else if (mode == 'MODE_3D_VIEW') { window.__threeRendererDownload = _this.renderer; } else { if (_this.props.downloadFlag) window.__elevationRendererDownload[mode] = _this.renderer;else window.__elevationRenderer = _this.renderer; } _this.renderer.domElement.style.display = 'none'; return _this; } _inherits(Scene3DViewer, _React$Component); return _createClass(Scene3DViewer, [{ key: "componentDidMount", value: function componentDidMount(nextProps) { var _this2 = this; var scene3D, camera, pivot, cameraControls, clock; var spotLight1, spotLightTarget; var actions = { areaActions: this.context.areaActions, holesActions: this.context.holesActions, itemsActions: this.context.itemsActions, sceneActions: this.context.sceneActions, linesActions: this.context.linesActions, projectActions: this.context.projectActions, catalog: this.context.catalog }; var self = this; var state = this.props.state; var mode = state.mode, scene = state.scene; function setupLight(scene, inbBox) { if (isElevationView(mode)) { var ambilight = new Three.AmbientLight('0xffffff', 3); scene.add(ambilight); } else { var addDirLight = function addDirLight(inColor, inIntensity, inPosition) { var dirLight = new Three.DirectionalLight(inColor, inIntensity); dirLight.castShadow = true; dirLight.shadow.mapSize.x = shadowMapSize; dirLight.shadow.mapSize.y = shadowMapSize; dirLight.shadow.camera.near = 0; dirLight.shadow.camera.far = shadowCameraFar; dirLight.shadow.camera.top = shadowCameraSize * 1.5; dirLight.shadow.camera.bottom = -shadowCameraSize * 1.5; dirLight.shadow.camera.left = -shadowCameraSize * 1.5; dirLight.shadow.camera.right = shadowCameraSize * 1.5; dirLight.position.copy(inPosition); var targetObject = new Three.Object3D(); targetObject.position.copy(bboxCenter); scene.add(targetObject); dirLight.target = targetObject; dirLight.target.updateMatrixWorld(); scene.add(dirLight); }; var addSpotLight = function addSpotLight(inColor, inIntensity, inPosition, inTarget, inDistance) { var spotLight = new Three.SpotLight(); spotLight.intensity = inIntensity; spotLight.color.setHex(inColor); spotLight.position.copy(inPosition); spotLight.angle = 1.3; spotLight.distance = inDistance; spotLight.penumbra = 1.8; spotLight.decay = 0.01; spotLight.castShadow = true; spotLight.shadow.intensity = 2; spotLight.shadow.mapSize.width = 4096; spotLight.shadow.mapSize.height = 4096; var targetObject = new Three.Object3D(); targetObject.position.copy(new Three.Vector3(inTarget.x, 0, inTarget.z)); scene.add(targetObject); spotLight.target = targetObject; spotLight.target.updateMatrixWorld(); scene.add(spotLight); }; var shadowMapSize = 2048; var shadowCameraSize = Math.max(Math.abs(inbBox.min.x - inbBox.max.x), Math.abs(inbBox.min.y - inbBox.max.y), Math.abs(inbBox.min.z - inbBox.max.z)) / 2; var shadowCameraFar = shadowCameraSize * 10; var bboxCenter = new Three.Vector3((inbBox.min.x + inbBox.max.x) / 2, inbBox.min.y, (inbBox.min.z + inbBox.max.z) / 2); var dirLightPos = new Three.Vector3(inbBox.max.x, inbBox.max.y + 1.8 * Math.abs(inbBox.max.y - inbBox.min.y), inbBox.min.z - 0.5 * Math.abs(inbBox.max.z - inbBox.min.z)); addDirLight('white', 1.5, dirLightPos); var ceiling = scene3D.getObjectByName('ceil'); if (ceiling) { var ceilBBox = new Three.Box3().setFromObject(ceiling); var spot1 = new Three.Vector3(ceilBBox.min.x + Math.abs(ceilBBox.min.x - ceilBBox.max.x) / 4, ceilBBox.max.y - 0.5, ceilBBox.min.z + Math.abs(ceilBBox.min.z - inbBox.max.z) / 4); var spot2 = new Three.Vector3(ceilBBox.min.x + Math.abs(ceilBBox.min.x - ceilBBox.max.x) / 4, ceilBBox.max.y - 0.5, ceilBBox.max.z - Math.abs(ceilBBox.min.z - ceilBBox.max.z) / 4); var spot3 = new Three.Vector3(ceilBBox.max.x - Math.abs(ceilBBox.min.x - ceilBBox.max.x) / 4, ceilBBox.max.y - 0.5, ceilBBox.min.z + Math.abs(ceilBBox.min.z - ceilBBox.max.z) / 4); var spot4 = new Three.Vector3(ceilBBox.max.x - Math.abs(ceilBBox.min.x - ceilBBox.max.x) / 4, ceilBBox.max.y - 0.5, ceilBBox.max.z - Math.abs(ceilBBox.min.z - ceilBBox.max.z) / 4); var spotlightDis = 1.5 * Math.abs(inbBox.min.y - inbBox.max.y); // check if spotlight is inside the room vectorIntersectWithMesh(spot1, scene3D.getObjectByName('floor')) && addSpotLight('0xffffff', 0.8, spot1, spot1, spotlightDis); vectorIntersectWithMesh(spot2, scene3D.getObjectByName('floor')) && addSpotLight('0xffffff', 0.8, spot2, spot2, spotlightDis); vectorIntersectWithMesh(spot3, scene3D.getObjectByName('floor')) && addSpotLight('0xffffff', 0.8, spot3, spot3, spotlightDis); vectorIntersectWithMesh(spot4, scene3D.getObjectByName('floor')) && addSpotLight('0xffffff', 0.8, spot4, spot4, spotlightDis); } } } // Load data this.setState({ isLoading: true }); if (self.props.downloadFlag) { this.setState({ waitForRender: 0 }); // set loading bar switch (self.props.state.mode) { case MODE_ELEVATION_VIEW: self.props.setIsLoadingElevation('front', true); break; case MODE_3D_VIEW: self.props.setIsLoading3D(true); break; } } var _parseData = parseData(scene, actions, this.context.catalog, camera, this.renderer, state.mode), promise = _parseData.promise, planData = _parseData.planData; promise.then(function () { var objToRemove = []; planData.plan.traverse(function (obj) { if (obj.geometry === null) { objToRemove.push(obj); } }); objToRemove.forEach(function (obj) { obj.removeFromParent(); }); var bbox = new Three.Box3().setFromObject(planData.plan); if (!isElevationView(state.mode)) { cameraControls.fitToBox(bbox); } setupLight(scene3D, planData.boundingBox); self.setState({ waitForRender: 1 }); setTimeout(function () { self.setState({ isLoading: false }); self.renderer.domElement.style.display = 'block'; }, 1500); }); var area = scene.getIn(['layers', scene.selectedLayer, 'areas']); var layer = scene.getIn(['layers', scene.selectedLayer]); var areas = [], lights = []; var snapBox = null; // Check for data var msg = ''; scene.layers.forEach(function (layer) { if (layer.id === scene.selectedLayer || layer.visible) { layer.items.forEach(function (item) { if (item.doorStyle === null) { if (!msg.includes(item.name + "'s doorStyle is null.")) msg += item.name + "'s doorStyle is null.\n"; } }); } }); if (msg !== '') { confirm(msg); } init(); render(); // area lightning(wall lightning)///// area.forEach(function (data) { areas.push(data); }); var _loop = function _loop() { var aVertices = []; var lines = []; var height = 100; areas[i].vertices.forEach(function (data) { aVertices.push(data); }); layer.lines.forEach(function (data) { lines.push(data); }); var _loop3 = function _loop3() { var data = lines[_i15]; var realVec = []; data.vertices.forEach(function (vec) { realVec.push(vec); }); if (aVertices.includes(realVec[0]) && aVertices.includes(realVec[1])) { height = convert(layer.ceilHeight).from(layer.unit).to(UNIT_CENTIMETER); // height = data.properties.getIn(['height', 'length']); return 1; // break } }; for (var _i15 = 0; _i15 < lines.length; _i15++) { if (_loop3()) break; } var vertices = []; areas[i].vertices.forEach(function (datas) { var vertex = scene.getIn(['layers', scene.selectedLayer, 'vertices', datas]); vertices.push(vertex); }); vertices.push(vertices[0]); var fLen = vertices.length - 1; for (var _i16 = 0; _i16 < fLen; _i16++) { var sX = vertices[_i16].x; var sY = vertices[_i16].y; var eX = vertices[_i16 + 1].x; var eY = vertices[_i16 + 1].y; var len = Math.sqrt((eX - sX) * (eX - sX) + (eY - sY) * (eY - sY)); for (var cLen = 200; cLen < len; cLen += 200) { var cX = sX + (eX - sX) * cLen / len; var cY = sY + (eY - sY) * cLen / len; var endLen = Math.sqrt((eX - cX) * (eX - cX) + (eY - cY) * (eY - cY)); if (endLen <= 100) continue; var vec2 = new Three.Vector2(cX - sX, cY - sY); var angle = vec2.angle() + Math.PI / 2; cX = Math.cos(angle) * 30 + cX; cY = Math.sin(angle) * 30 + cY; var spotLight = new Three.SpotLight(0xeeeeee, 1.7); spotLight.angle = 0.76; spotLight.castShadow = true; spotLight.penumbra = 1; spotLight.decay = 1.7; spotLight.distance = height - 20; var target = new Three.Object3D(); spotLight.target = target; lights.push({ light: spotLight, target: target, x: cX, y: cY, height: height }); } } }; for (var i = 0; i < areas.length; i++) { _loop(); } // ////////////////////////// // OBJECT PICKING var toIntersect = [planData.plan]; var mouse = new Three.Vector2(); var gridPlane = planData.grid; var raycaster = new Three.Raycaster(); var selectedObject = {}; var selectedFlag = false; var currentObject = null; var isSelected = false; var bRotate = false; var bMove = false; var bMoveUP = false; /** Transformation matrix of grid */ var gridMatrix = new Three.Matrix4(); var rayDirection = new Three.Vector3(); /** World position of grid plane */ var gridPlanOrigin = new Three.Vector3(); var Point = new Three.Vector2(); var sPoint = new Three.Vector2(); // SNAP FUNCTION VARIABLE var snapFlag = false; var snapAnimI = 0; var snapDelta = 6; var t_i = 0; var targetPoint = new Three.Vector3(); var targetRot = 0; var targetUVec = new Three.Vector3(); var targetCRotation = 0; var targetObj = null; var targetNumber = 0; var wallSlide = false; var pinFlag = false; var sFlag = false; //for all object move var endPoint = {}; var allItemRect; var allItemSnap; var allLines; var allLineRects; var allLineSnap; var allRect; var allArea; // FLAG FOR initial phase of drawing an item var isInitialPhase = true; // end snap function variable/////////////////////// var backsplashVisible = false; var holeItems = GeometryUtils.getHoleItems(layer); var removeSnapBox = function removeSnapBox() { if (snapBox != null) { planData.plan.remove(snapBox); disposeObject(snapBox); snapBox = null; targetObj = null; snapFlag = false; } }; var camToGrid = new Three.Vector3(); var camPos = camera.position; var mapCursorPosition = function mapCursorPosition(e, altitude) { camToGrid.subVectors(gridPlanOrigin, camPos); var camD = camToGrid.y + (altitude ? altitude : 0); var rayD = rayDirection.y; var intersectPt = rayDirection.multiplyScalar(camD / rayD).add(camPos); intersectPt.y = gridPlanOrigin.y; intersectPt.applyMatrix4(gridMatrix); return { x: intersectPt.x, y: -intersectPt.z }; }; /* for Snap Functions*/ var pointLineDistance = function pointLineDistance(point, line) { // return distance from point to line and directional point of line var pX = point.x; var pY = point.y; var l1x = line[0].x; var l1y = line[0].y; var l2x = line[1].x; var l2y = line[1].y; var pLine = new Three.Vector2(l1x - pX, l1y - pY); var Line = new Three.Vector2(l1x - l2x, l1y - l2y); var pAngle = pLine.angle(); var lAngle = Line.angle(); var pDistance = pLine.length(); var oDistance = Line.length(); var directDistance = Math.sin(pAngle - lAngle) * pDistance; var lineDistance = Math.cos(pAngle - lAngle) * pDistance; var dX = l1x + (l2x - l1x) * lineDistance / oDistance; var dY = l1y + (l2y - l1y) * lineDistance / oDistance; var dPoint = { x: dX, y: dY }; return { distance: directDistance, point: dPoint }; }; var getInterSect = function getInterSect(shape1, shape2) { // return result of intersect of two shape var count = 0; for (var _i = 0; _i < shape1.length - 1; _i++) { var sl1 = { x: shape1[_i].x, y: shape1[_i].y }; var sl2 = { x: shape1[_i + 1].x, y: shape1[_i + 1].y }; for (var j = 0; j < shape2.length - 1; j++) { var el1 = { x: shape2[j].x, y: shape2[j].y }; var el2 = { x: shape2[j + 1].x, y: shape2[j + 1].y }; var flag = GeometryUtils.getLineInterSect(sl1.x, sl1.y, sl2.x, sl2.y, el1.x, el1.y, el2.x, el2.y); if (flag) { count++; if (count > 1) return true; } } } return false; }; this.getRectPoints = function (width, height, pos, rot) { // return 4 points from it's position, width, height, and rotation info var rX = width / 2; var rY = height / 2; var vertices = []; var cRot = rot; var pX = pos.x + Math.cos(cRot) * rX + Math.cos(cRot + Math.PI / 2) * rY; var pY = pos.y + Math.sin(cRot) * rX + Math.sin(cRot + Math.PI / 2) * rY; vertices.push({ x: Math.floor(pX + 0.5), y: Math.floor(pY + 0.5) }); rX = -rX; pX = pos.x + Math.cos(cRot) * rX + Math.cos(cRot + Math.PI / 2) * rY; pY = pos.y + Math.sin(cRot) * rX + Math.sin(cRot + Math.PI / 2) * rY; vertices.push({ x: Math.floor(pX + 0.5), y: Math.floor(pY + 0.5) }); rY = -rY; pX = pos.x + Math.cos(cRot) * rX + Math.cos(cRot + Math.PI / 2) * rY; pY = pos.y + Math.sin(cRot) * rX + Math.sin(cRot + Math.PI / 2) * rY; vertices.push({ x: Math.floor(pX + 0.5), y: Math.floor(pY + 0.5) }); rX = -rX; pX = pos.x + Math.cos(cRot) * rX + Math.cos(cRot + Math.PI / 2) * rY; pY = pos.y + Math.sin(cRot) * rX + Math.sin(cRot + Math.PI / 2) * rY; vertices.push({ x: Math.floor(pX + 0.5), y: Math.floor(pY + 0.5) }); vertices.push(vertices[0]); vertices.push(vertices[2]); return vertices; }; var prepareSnap = function prepareSnap(layer) { allLines = GeometryUtils.getAllLines(layer); allLineRects = GeometryUtils.buildRectFromLines(layer, allLines); allItemRect = GeometryUtils.getAllItems(_this2.props.state.scene, actions.catalog, allLineRects); allItemSnap = GeometryUtils.getAllItemSnap(allItemRect); allLineSnap = GeometryUtils.getAllLineSnap(allLineRects, allItemRect.cur); allRect = allItemRect.others.concat(allLineRects); allItemSnap = GeometryUtils.validateSnaps(allItemSnap, allRect); allLineSnap = GeometryUtils.validateSnaps(allLineSnap, allRect); allArea = GeometryUtils.getAllArea(layer); }; var prepareSnapSpec = function prepareSnapSpec(layer) { allLines = GeometryUtils.getAllLines(layer); allLineRects = GeometryUtils.buildRectFromLines(layer, allLines); allItemRect = GeometryUtils.getAllItemSpecified(_this2.props.state.scene, actions.catalog, WALL_CABINET_LAYOUTPOS); // allItemSnap = GeometryUtils.getAllItemSnap(allItemRect); }; // prepareSnapSpec(layer); var lineRect = function lineRect(layer) { var areainfo = []; layer.areas.forEach(function (area) { var sz = area.vertices.size; for (var i = 0; i < sz; i++) { areainfo.push(area.vertices.get(i)); } }); var rect = []; areainfo.forEach(function (area) { var vert = layer.vertices.get(area); rect.push(vert.x, vert.y); }); return rect; }; this.collisionCheck = function (obj, pos, rot, tObj) { var _this3 = this; var item = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var catalog = arguments.length > 5 ? arguments[5] : undefined; //collision check from one object to every other object excpet target object var layer = this.props.state.scene.getIn(['layers', obj.userData.layerId]); var layoutpos = 'utype'; if (item !== null) { var catid = item.type; var cat = catalog.elements[catid]; layoutpos = cat.info.layoutpos; } var oPos = new Three.Vector2(pos.clone().x, pos.clone().y); var sBounding = obj.children[0].userData; var width = sBounding.max.x - sBounding.min.x; var depth = sBounding.max.z - sBounding.min.z; var oVertices = this.getRectPoints(width, depth, oPos.clone(), rot % 360 / 180 * Math.PI); var datas = []; layer.items.forEach(function (data) { datas.push(data); }); for (var _i2 = 0; _i2 < datas.length; _i2++) { var data = datas[_i2]; if (data.id == obj.userData.itemId || data.id == tObj.userData.itemId) continue; var target = planData.sceneGraph.layers[obj.userData.layerId].items[data.id]; if (target === undefined) { console.log(data.id + ' does not exist in viewer3d/viewer3d.js collisionCheck function'); return false; } var _item = layer.items.getIn([data.id]); var ocatid = _item.type; var ocat = catalog.elements[ocatid]; var olayoutpos = ocat.info.layoutpos; if (!(layoutpos === BASE_CABINET_LAYOUTPOS && olayoutpos === WALL_CABINET_LAYOUTPOS || layoutpos === WALL_CABINET_LAYOUTPOS && olayoutpos === BASE_CABINET_LAYOUTPOS)) { var tRot = _item.rotation; var tPos = new Three.Vector2(_item.x, _item.y); var tBounding = target.children[0].userData; var twidth = tBounding.max.x - tBounding.min.x; var tdepth = tBounding.max.z - tBounding.min.z; var tVertices = this.getRectPoints(twidth, tdepth, tPos.clone(), tRot % 360 / 180 * Math.PI); if (getInterSect(oVertices, tVertices)) { return false; } } } datas = []; layer.lines.forEach(function (data) { datas.push(data); }); var _loop2 = function _loop2() { var data = datas[_i3]; if (data.id == obj.userData.itemId || data.id == tObj.userData.itemId) return 0; // continue var item = layer.lines.getIn([data.id]); // let llayoutpos = catalog.elements[item.type].info.layoutpos; var vertices = []; item.vertices.forEach(function (data) { var vertex = layer.vertices.get(data); vertices.push({ x: vertex.x, y: vertex.y }); }); var vec = new Three.Vector2(vertices[1].x - vertices[0].x, vertices[1].y - vertices[0].y); var tRot = vec.angle(); var tPos = new Three.Vector2((vertices[0].x + vertices[1].x) / 2, (vertices[0].y + vertices[1].y) / 2); var tdepth = item.properties.getIn(['thickness', 'length']); var twidth = Math.sqrt(vec.x * vec.x + vec.y * vec.y); var tVertices = _this3.getRectPoints(twidth, tdepth, tPos.clone(), tRot); if (getInterSect(oVertices, tVertices)) { return { v: false }; } }, _ret; for (var _i3 = 0; _i3 < datas.length; _i3++) { _ret = _loop2(); if (_ret === 0) continue; if (_ret) return _ret.v; } return true; }; this.collisionHoleCheck = function (obj, pos, rot, tObj) { var item = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var catalog = arguments.length > 5 ? arguments[5] : undefined; var layer = this.props.state.scene.getIn(['layers', obj.userData.layerId]); var currentItem; if (item !== null) { var catid = item.type; var cat = catalog.elements[catid]; currentItem = { selectedItem: item, cat: cat }; } var oPos = new Three.Vector2(pos.clone().x, pos.clone().y); var sBounding = obj.children[0].userData; var width = sBounding.max.x - sBounding.min.x; var depth = sBounding.max.z - sBounding.min.z; var oVertices = this.getRectPoints(width, depth, oPos.clone(), rot % 360 / 180 * Math.PI); var datas = []; layer.items.forEach(function (data) { datas.push(data); }); for (var _i4 = 0; _i4 < datas.length; _i4++) { var data = datas[_i4]; if (data.id == obj.userData.itemId || data.id == tObj.userData.itemId) continue; var target = planData.sceneGraph.layers[obj.userData.layerId].items[data.id]; if (target === undefined) { console.log(data.id + ' does not exist in viewer3d/viewer3d.js collisionCheck function'); return false; } var _item2 = layer.items.getIn([data.id]); var ocatid = _item2.type; var ocat = catalog.elements[ocatid]; if (!ocat) ocat = catalog.elements[returnReplaceableDeepSearchType(ocatid)]; var otherItem = { item: _item2, cat: ocat }; if (GeometryUtils.needSnap(currentItem, otherItem) && otherItem.cat.type != 'cabinet') { var tRot = _item2.rotation; var tPos = new Three.Vector2(_item2.x, _item2.y); var tBounding = target.children[0].userData; var twidth = tBounding.max.x - tBounding.min.x; var tdepth = tBounding.max.z - tBounding.min.z; var tVertices = this.getRectPoints(twidth, tdepth, tPos.clone(), tRot % 360 / 180 * Math.PI); if (getInterSect(oVertices, tVertices)) { return false; } } } var holes = []; layer.lines.forEach(function (line) { line.holes.forEach(function (holeID) { var hole = layer.holes.get(holeID); holes.push(hole); }); }); var i = 0; for (; i < holes.length; i++) { var _tPos = new Three.Vector2(holes[i].x, holes[i].y); var _twidth = holes[i].properties.getIn(['width', 'length']); var theight = holes[i].properties.getIn(['thickness', 'length']); var trot = holes[i].rotation; var _tVertices = this.getRectPoints(_twidth, theight, _tPos.clone(), trot); if (getInterSect(oVertices, _tVertices)) { return false; } } return true; }; this.collisionSlide = function (item3D, originPos, layer, sVertices, tPos, item) { var items = []; var cur_category = ''; var catalog = actions.catalog; if (layer.selected.items.size > 0) { var selectedItem = layer.getIn(['items', layer.selected.items.get(0)]); var catid = selectedItem.type; var cat = catalog.elements[catid]; if (cat === undefined || cat === null) cat = catalog.getIn(['elements', catid]); cur_category = cat.obj.category; } layer.items.forEach(function (data) { if (data.id == selectedObject.itemID) { return; } items.push(data.toJS()); }); var oPos = new Three.Vector2(originPos.x, -originPos.z); // sort from distance for (var _i5 = 0; _i5 < items.length - 1; _i5++) { for (var j = _i5 + 1; j < items.length; j++) { if (verticesDistance(oPos, new Three.Vector2(items[_i5].x, items[_i5].y)) > verticesDistance(oPos, new Three.Vector2(items[j].x, items[j].y))) { var exchange = items[j]; items[j] = items[_i5]; items[_i5] = exchange; } } } var i = 0; for (; i < items.length; i++) { if (!items[i]) return; var _target = planData.sceneGraph.layers[selectedObject.layerID].items[items[i].id]; if (_target === undefined) { return false; } var _targetData = layer.items.getIn([items[i].id]); var _tRot = _targetData.rotation; var _tPos2 = new Three.Vector2(_targetData.x, _targetData.y); var _tBounding = _target.children[0].userData; var _twidth2 = _tBounding.max.x - _tBounding.min.x; var _tdepth = _tBounding.max.z - _tBounding.min.z; var _tVertices2 = this.getRectPoints(_twidth2, _tdepth, _tPos2.clone(), _tRot % 360 / 180 * Math.PI); if (getInterSect(sVertices, _tVertices2)) { break; } } if (items.length == 0 || !items[i]) return; var target = planData.sceneGraph.layers[selectedObject.layerID].items[items[i].id]; var targetData = layer.items.getIn([items[i].id]); var targetPos = new Three.Vector2(targetData.x, targetData.y); var tRot = targetData.rotation; var tBounding = target.children[0].userData; var twidth = tBounding.max.x - tBounding.min.x; var tdepth = tBounding.max.z - tBounding.min.z; var tVertices = this.getRectPoints(twidth, tdepth, targetPos.clone(), tRot % 360 / 180 * Math.PI); // //////////////////////// var vArray = []; var dteArray = []; var lineArray = []; var vdistanceArray = []; var cVecArray = []; var inFlag = false; for (var _i6 = 0; _i6 < 4; _i6++) { var v1 = tVertices[_i6]; var v2 = tVertices[_i6 + 1]; var data = pointLineDistance({ x: tPos.x, y: tPos.y }, [{ x: v1.x, y: v1.y }, { x: v2.x, y: v2.y }]); dteArray.push(data.distance); vArray.push(data.point); lineArray.push([v1, v2]); } // if tPos in target object var tPosDistance = Math.abs(pointLineDistance(tPos, lineArray[0]).distance) + Math.abs(pointLineDistance(tPos, lineArray[2]).distance); var realDistance = new Three.Vector2(lineArray[1][0].x - lineArray[1][1].x, lineArray[1][0].y - lineArray[1][1].y).length(); var tPosDistance1 = Math.abs(pointLineDistance(tPos, lineArray[1]).distance) + Math.abs(pointLineDistance(tPos, lineArray[3]).distance); var realDistance1 = new Three.Vector2(lineArray[0][0].x - lineArray[0][1].x, lineArray[0][0].y - lineArray[0][1].y).length(); if (Math.abs(Math.abs(tPosDistance) - Math.abs(realDistance)) < 0.01 && Math.abs(Math.abs(tPosDistance1) - Math.abs(realDistance1)) < 0.01) inFlag = true; // //////////////////// var key = 0; // sort distance from origin point for (var _j = 0; _j < dteArray.length - 1; _j++) { for (var k = _j + 1; k < dteArray.length; k++) { if (Math.abs(dteArray[_j]) > Math.abs(dteArray[k])) { var temp = dteArray[k]; dteArray[_j] = dteArray[k]; dteArray[k] = temp; var temp1 = vArray[k]; vArray[_j] = vArray[k]; vArray[k] = temp1; var temp2 = lineArray[k]; lineArray[_j] = lineArray[k]; lineArray[k] = temp2; } } } // ////////////////////////////// for (var _i7 = 0; _i7 < 4; _i7++) { var _data = pointLineDistance(sVertices[_i7], lineArray[key]); vdistanceArray.push(_data.distance); cVecArray.push({ x: _data.point.x - sVertices[_i7].x, y: _data.point.y - sVertices[_i7].y }); } for (var _j2 = 0; _j2 < vdistanceArray.length; _j2++) { var tX = tPos.x + cVecArray[_j2].x; var tY = tPos.y + cVecArray[_j2].y; if (this.collisionCheck(item3D, new Three.Vector2(tX, tY), item.rotation, { userData: { itemId: null } }, item, this.context.catalog)) { item3D.position.set(tX, originPos.y, -tY); sPoint.set(tX, tY); break; } } }; this.snap = function (obj, layer) { // snap operation var target = obj.userData.target; for (; target.parent != null;) { if (target.name == 'pivot') break; target = target.parent; } var source = obj.parent.parent.parent; if (target.userData.type == 'item') { var sRot = layer.getIn(['items', source.userData.itemId]).rotation; var tRot = layer.getIn(['items', target.userData.itemId]) ? layer.getIn(['items', target.userData.itemId]).rotation : 0; var item = layer.getIn(['items', source.userData.itemId]); var layoutType = item.layoutpos; var altitudeLength = convert(item.properties.getIn(['altitude', '_length'])).from('in').to('cm'); var sBounding = source.children[0].userData; var tBounding = target.children[0].userData; var tPos = target.position.clone(); var width = sBounding.max.x - sBounding.min.x; var height = sBounding.max.y - sBounding.min.y; var depth = sBounding.max.z - sBounding.min.z; var snapBoxGeom = new Three.BoxGeometry(width, height, depth); var snapBoxObj = new Three.Mesh(snapBoxGeom, new Three.MeshBasicMaterial({ // color: 0x2cde6b, // opacity: 0.7, transparent: true, blending: Three.MultiplyBlending })); var removeSnapBoxObj = function removeSnapBoxObj() { if (snapBoxObj) { planData.plan.remove(snapBoxObj); disposeObject(snapBoxObj); } snapFlag = false; }; var box = new Three.BoxHelper(snapBoxObj, 0xffffff); box.material.linewidth = 2; box.material.depthTest = false; box.renderOrder = 200; snapBoxObj.add(box); snapBoxObj.position.set(source.position.x, layoutType === WALL_CABINET_LAYOUTPOS ? altitudeLength + source.position.y + height / 2 : source.position.y + height / 2, source.position.z); snapBoxObj.rotation.set(source.rotation.x, source.rotation.y, source.rotation.z); snapBoxObj.name = 'TransformBox'; planData.plan.add(snapBoxObj); var deltaX = (tBounding.max.x - tBounding.min.x) / 2 + (sBounding.max.x - sBounding.min.x) / 2; var deltaZ = (tBounding.max.z - tBounding.min.z) / 2 - (sBounding.max.z - sBounding.min.z) / 2; var sPos = snapBoxObj.position.clone(); // avaliable snap place/////////////// var tPoses = []; var pX = tPos.x + deltaX * Math.cos(tRot / 180 * Math.PI) + deltaZ * Math.sin(tRot / 180 * Math.PI); var pZ = tPos.z - deltaX * Math.sin(tRot / 180 * Math.PI) + deltaZ * Math.cos(tRot / 180 * Math.PI); tPoses.push(new Three.Vector3(pX, 0, pZ)); deltaX = -deltaX; pX = tPos.x + deltaX * Math.cos(tRot / 180 * Math.PI) + deltaZ * Math.sin(tRot / 180 * Math.PI); pZ = tPos.z - deltaX * Math.sin(tRot / 180 * Math.PI) + deltaZ * Math.cos(tRot / 180 * Math.PI); tPoses.push(new Three.Vector3(pX, 0, pZ)); deltaX = (tBounding.max.x - tBounding.min.x) / 2 - (sBounding.max.x - sBounding.min.x) / 2; deltaZ = -(tBounding.max.z - tBounding.min.z) / 2 - (sBounding.max.z - sBounding.min.z) / 2; pX = tPos.x + deltaX * Math.cos(tRot / 180 * Math.PI) + deltaZ * Math.sin(tRot / 180 * Math.PI); pZ = tPos.z - deltaX * Math.sin(tRot / 180 * Math.PI) + deltaZ * Math.cos(tRot / 180 * Math.PI); tPoses.push(new Three.Vector3(pX, 0, pZ)); deltaX = -deltaX; pX = tPos.x + deltaX * Math.cos(tRot / 180 * Math.PI) + deltaZ * Math.sin(tRot / 180 * Math.PI); pZ = tPos.z - deltaX * Math.sin(tRot / 180 * Math.PI) + deltaZ * Math.cos(tRot / 180 * Math.PI); tPoses.push(new Three.Vector3(pX, 0, pZ)); var distance = Math.sqrt((sPos.x - tPoses[0].x) * (sPos.x - tPoses[0].x) + (sPos.z - tPoses[0].z) * (sPos.z - tPoses[0].z)); var tNum = 1; tPos = tPoses[0].clone(); for (var _i8 = 1; _i8 < tPoses.length; _i8++) { var curDis = Math.sqrt((sPos.x - tPoses[_i8].x) * (sPos.x - tPoses[_i8].x) + (sPos.z - tPoses[_i8].z) * (sPos.z - tPoses[_i8].z)); if (curDis < distance) { distance = curDis; tNum = _i8 + 1; tPos = tPoses[_i8].clone(); } } // ////////////////////////////////// if (targetObj != null && targetObj.userData.itemId == target.userData.itemId && tNum == targetNumber) { removeSnapBoxObj(); return; } else { removeSnapBox(); } // ////////////////////////////////// if (tNum >= 3) tRot += 180; snapAnimI = 0; t_i = 0; targetObj = target; targetNumber = tNum; targetRot = tRot; targetPoint = tPos; snapBox = snapBoxObj; var cx = sPos.x - tPos.x; var cz = sPos.z - tPos.z; targetUVec = new Three.Vector3(cx, 0, cz); targetCRotation = (tRot - sRot) % 360 / 180 * Math.PI; } else { var _item3 = layer.getIn(['items', source.userData.itemId]); if (holeItems.length && selectedObj) { var _i9; for (_i9 = 0; _i9 < holeItems.length; _i9++) { var hole = holeItems[_i9]; if (Math.abs(Math.sin(selectedObj.rotRad)) === 1) { if (_item3.y + selectedObj.size.width / 2 >= hole.y - hole.width / 2 && _item3.y - selectedObj.size.width / 2 <= hole.y + hole.width / 2 && (selectedObj.rotRad == 0 || selectedObj.rotRad == -Math.PI / 2 ? _item3.x <= hole.x && _item3.x + selectedObj.size.height >= hole.x : _item3.x >= hole.x && _item3.x - selectedObj.size.height <= hole.x)) break; } else { if (_item3.x + selectedObj.size.width / 2 >= hole.x - hole.width / 2 && _item3.x - selectedObj.size.width / 2 <= hole.x + hole.width / 2 && (selectedObj.rotRad == 0 || selectedObj.rotRad == -Math.PI / 2 ? _item3.y <= hole.y && _item3.y + selectedObj.size.height >= hole.y : _item3.y >= hole.y && _item3.y - selectedObj.size.height <= hole.y)) break; } } if (_i9 != holeItems.length) return; } if (target.userData.type == 'hole') { snapFlag = false; return; } else { var _layoutType = _item3.layoutpos; var _altitudeLength = convert(_item3.properties.getIn(['altitude', '_length'])).from('in').to('cm'); var _sBounding = source.children[0].userData; var _width = _sBounding.max.x - _sBounding.min.x; var _height = _sBounding.max.y - _sBounding.min.y; var _depth = _sBounding.max.z - _sBounding.min.z; var _snapBoxGeom = new Three.BoxGeometry(_width, _height, _depth); var _snapBoxObj = new Three.Mesh(_snapBoxGeom, new Three.MeshBasicMaterial({ // color: 0x2cde6b, // opacity: 0.7, transparent: true, blending: Three.MultiplyBlending })); var _removeSnapBoxObj = function _removeSnapBoxObj() { if (_snapBoxObj) { planData.plan.remove(_snapBoxObj); disposeObject(_snapBoxObj); } snapFlag = false; }; var _box = new Three.BoxHelper(_snapBoxObj, 0xffffff); _box.material.linewidth = 2; _box.material.depthTest = false; _box.renderOrder = 100; _snapBoxObj.add(_box); _snapBoxObj.position.set(source.position.x, _layoutType === WALL_CABINET_LAYOUTPOS ? _altitudeLength + source.position.y + _height / 2 : source.position.y + _height / 2, source.position.z); _snapBoxObj.rotation.set(source.rotation.x, source.rotation.y, source.rotation.z); _snapBoxObj.name = 'TransformBox'; planData.plan.add(_snapBoxObj); var snapLine = layer.getIn(['lines', target.userData.lineId]); // let snapLineThickness = snapLine.properties.getIn([ // 'thickness', // 'length' // ]); var snapLineThickness = 10.64; var vertices = []; if (snapLine === undefined) return; snapLine.vertices.forEach(function (data) { var vec = layer.getIn(['vertices', data]); vertices.push(vec); }); var iX = source.position.clone().x; var iY = -source.position.clone().z; var lineVec = new Three.Vector2(vertices[1].x - vertices[0].x, vertices[1].y - vertices[0].y); var oLength = Math.sqrt(lineVec.x * lineVec.x + lineVec.y * lineVec.y); lineVec.normalize(); var vec2 = new Three.Vector2(iX - vertices[0].x, iY - vertices[0].y); var vec2Legnth = Math.sqrt(vec2.x * vec2.x + vec2.y * vec2.y); var angle = Math.abs(lineVec.angle() - vec2.angle()); angle = angle > Math.PI ? 2 * Math.PI - angle : angle; var lineLength = Math.cos(angle) * vec2Legnth; var transLength = 0; if (lineLength < 100) { transLength = -lineLength + (snapLineThickness + _width) / 2; } if (lineLength > oLength - 100) { transLength = -lineLength - (snapLineThickness + _width) / 2 + oLength; } var directPoint = new Three.Vector2(lineVec.x * lineLength + vertices[0].x, lineVec.y * lineLength + vertices[0].y); var directLine = new Three.Vector2(directPoint.x - iX, directPoint.y - iY); var dLength = Math.sqrt((iX - directPoint.x) * (iX - directPoint.x) + (iY - directPoint.y) * (iY - directPoint.y)); var reduceLen = (snapLineThickness + _depth) / 2; var scale = (dLength - reduceLen) / dLength; var _tPos3 = new Three.Vector2(iX + (directPoint.x - iX) * scale + lineVec.x * transLength, iY + (directPoint.y - iY) * scale + lineVec.y * transLength); var realAngle = directLine.angle() - Math.PI / 2; var _tRot2 = realAngle * 180 / Math.PI; var _sPos = new Three.Vector2(iX, iY); var _sRot = _item3.rotation; var _tNum = 0; // ////////////////////////////////////// // check part//// var result = this.collisionCheck(source, _tPos3, _tRot2, target, _item3, this.context.catalog); // console.log('result', result); if (result == false) { _removeSnapBoxObj(); removeSnapBox(); return; } // //////////////// if (targetObj === target && snapBox !== null) { _removeSnapBoxObj(); snapAnimI = 20; targetPoint = new Three.Vector3(_tPos3.x, 0, -_tPos3.y); var _sourcePos = snapBox.position.clone(); var _cx = _sourcePos.x - targetPoint.x; var _cz = _sourcePos.z - targetPoint.z; targetUVec = new Three.Vector3(_cx, 0, _cz); targetRot = _tRot2; targetCRotation = (_tRot2 - _sRot) % 360 / 180 * Math.PI; snapFlag = false; return; } else { removeSnapBox(); } // ////////////////////////////////////// snapAnimI = 0; t_i = 0; targetObj = target; targetNumber = _tNum; targetRot = _tRot2; targetPoint = new Three.Vector3(_tPos3.x, 0, -_tPos3.y); snapBox = _snapBoxObj; var sourcePos = snapBox.position.clone(); var _cx2 = sourcePos.x - targetPoint.x; var _cz2 = sourcePos.z - targetPoint.z; targetUVec = new Three.Vector3(_cx2, 0, _cz2); targetRot = _tRot2; targetCRotation = (_tRot2 - _sRot) % 360 / 180 * Math.PI; } } }; /*end of snap functions*/ var selectedObj = null; var firstMove = false; var prevX, prevY; var selObj = null; var createToolObject = function createToolObject() { var canvas = document.createElement('canvas'); canvas.width = 100; canvas.height = 200; canvas.style.width = 50 + 'px'; canvas.style.height = 100 + 'px'; var ctx = canvas.getContext('2d'); ctx.fillStyle = '#FFFFFF'; ctx.strokeStyle = '#000000'; ctx.beginPath(); ctx.arc(50, 50, 40, 0, 4 * Math.PI); ctx.fill(); ctx.stroke(); var img1 = new Image(); img1.crossOrigin = 'anonymous'; img1.src = '/assets/img/svg/3d_item_rotation.svg'; img1.onload = function () { ctx.drawImage(img1, 16, 16, 68, 68); }; ctx.beginPath(); ctx.arc(50, 150, 40, 0, 4 * Math.PI); ctx.fill(); ctx.stroke(); var img2 = new Image(); img2.crossOrigin = 'anonymous'; img2.src = '/assets/img/svg/3d_item_move.svg'; img2.onload = function () { ctx.drawImage(img2, 16, 116, 68, 68); }; return canvas; }; var clockWise = true; var lastAngle = 0; var createAngleObject = function createAngleObject(rotate) { var canvas = document.createElement('canvas'); canvas.width = 100; canvas.height = 100; canvas.style.width = 100 + 'px'; canvas.style.height = 100 + 'px'; var ctx = canvas.getContext('2d'); ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 10; ctx.beginPath(); ctx.arc(50, 50, 45, 0, 2 * Math.PI); ctx.stroke(); ctx.strokeStyle = SECONDARY_PURPLE_COLOR; ctx.lineWidth = 6; ctx.beginPath(); if (lastAngle < 15 && lastAngle > -15) { if (rotate >= 0) { clockWise = false; } else { clockWise = true; } if (lastAngle === 0) { if (rotate > -180) { clockWise = true; } else { clockWise = false; } } } ctx.arc(50, 50, 45, 0, rotate / 180.0 * Math.PI, clockWise); ctx.stroke(); lastAngle = rotate; return canvas; }; var toolTexture = new Three.Texture(createToolObject()); toolTexture.needsUpdate = true; var toolObj = new Three.Sprite(new Three.SpriteMaterial({ map: toolTexture, sizeAttenuation: true })); toolObj.material.transparent = true; toolObj.material.depthTest = false; toolObj.scale.set(20, 40, 20); toolObj.renderOrder = 3; tool