UNPKG

kitchen-simulator

Version:

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

495 lines (481 loc) 17 kB
import React from 'react'; import Ruler3D from "./ruler3D"; import { convert } from "../../../utils/convert-units-lite"; import { GeometryUtils } from "../../../utils/export"; import { returnReplaceableDeepSearchType } from "../../../components/viewer2d/utils"; import { DECIMAL_PLACES_2, DELTA, DISTANCE_EPSILON } from "../../../constants"; import { formatNumber, isNonZeroText } from "../../../utils/math"; export default function Layer3D(_ref) { var layer = _ref.layer, frontRect = _ref.frontRect, lineLength = _ref.lineLength, ceilHeight = _ref.ceilHeight, catalog = _ref.catalog, scene = _ref.scene, scale = _ref.scale, mode = _ref.mode, line = _ref.line, viewScale = _ref.viewScale, downloadFlag = _ref.downloadFlag; var width = frontRect.width, height = frontRect.height; var v0 = layer.vertices.get(line.vertices.get(0)); var v1 = layer.vertices.get(line.vertices.get(1)); var l0 = { x: v0.x, y: v0.y }; var l1 = { x: v1.x, y: v1.y }; var rulerSpace = 50 * viewScale; var lineSpace = 25 * viewScale; var rulerLines = [], rulerData = [], baseItems = [], wallItems = [], basePosArray = [{ x: width / 2, y: height / 2 }, { x: -width / 2, y: height / 2 }], wallPosArray = [{ x: -width / 2, y: -height / 2 }, { x: width / 2, y: -height / 2 }], left_count = 0, right_count = 0, leftBaseItems = [], rightBaseItems = [], leftWallItems = [], rightWallItems = [], toler_unit = 'mm'; // get length between 2 points var getLength = function getLength(vertex0, vertex1) { return Math.sqrt(Math.pow(vertex0.x - vertex1.x, 2) + Math.pow(vertex0.y - vertex1.y, 2)); }; // determin if this line(vertex0, vertex1) is snapped into wall var isSnapped = function isSnapped(vertex0, vertex1) { var itemSnapped = false; var delta = GeometryUtils.distancePointFromLineSegment(l0, l1, (vertex0.x + vertex1.x) / 2, (vertex0.y + vertex1.y) / 2); if (delta < DISTANCE_EPSILON) { itemSnapped = true; } return itemSnapped; }; // get array of wallItem and baseITem in layer layer.items.forEach(function (item) { var val = { pos: { x: item.x, y: item.y }, rotRad: item.rotation / 180 * Math.PI }; var catid = item.type; var cat = catalog.elements[catid]; if (!cat) cat = catalog.elements[returnReplaceableDeepSearchType(catid)]; var width = convert(item.properties.getIn(['width', '_length'])).from(item.properties.getIn(['width', '_unit'])).to(scene.unit); var height = convert(item.properties.getIn(['height', '_length'])).from(item.properties.getIn(['height', '_unit'])).to(scene.unit); var depth = convert(item.properties.getIn(['depth', '_length'])).from(item.properties.getIn(['depth', '_unit'])).to(scene.unit); var altitude = convert(item.properties.getIn(['altitude', '_length'])).from(item.properties.getIn(['altitude', '_unit'])).to(scene.unit); val.size = { width: width, height: height, depth: depth, altitude: altitude }; val.layoutpos = cat && cat.info.layoutpos; val.is_corner = cat && cat.info.is_corner; val.item = item.toJS(); var calcrect = GeometryUtils.getCalcRectFromItem3D(val); if (isSnapped(calcrect.rect[3], calcrect.rect[2]) || isSnapped(calcrect.rect[2], calcrect.rect[1]) || isSnapped(calcrect.rect[0], calcrect.rect[3])) { if (calcrect.itemInfo.properties.altitude.length) { wallItems.push(calcrect); } else { baseItems.push(calcrect); } } }); // sort function var sortFunc = function sortFunc(a, b) { return a.pos.x - b.pos.x; }; var negSortFunc = function negSortFunc(a, b) { return -sortFunc(a, b); }; // get item's pos array about baseItem, then sort - baseItems' order is right: (width/2) -> left: (-width/2) if (baseItems.length) { baseItems.forEach(function (item) { var vertex0, vertex1; if (isSnapped(item.rect[3], item.rect[2])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[3], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[2], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; } else if (isSnapped(item.rect[2], item.rect[1])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[2], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[1], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; } else if (isSnapped(item.rect[0], item.rect[3])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[0], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[3], v0)).from('cm').to(layer.unit) * scale, y: height / 2 }; } basePosArray.push(vertex0); basePosArray.push(vertex1); // determin which side(left or right) item is closer to. If item is closer to left side, it will be included in leftBaseITems var distLeft = getLength(item.pos, v0); var distRight = getLength(item.pos, v1); if (distLeft < distRight) { leftBaseItems.push(item); } else { rightBaseItems.push(item); } }); } basePosArray.sort(function (a, b) { return b.x - a.x; }); // get item's pos array about wallItem, then sort - wallItems' order is left: (-width/2) -> right: (width/2) if (wallItems.length) { wallItems.forEach(function (item) { var vertex0, vertex1; if (isSnapped(item.rect[3], item.rect[2])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[3], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[2], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; } else if (isSnapped(item.rect[2], item.rect[1])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[2], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[1], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; } else if (isSnapped(item.rect[0], item.rect[3])) { vertex0 = { x: -frontRect.width / 2 + convert(getLength(item.rect[0], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; vertex1 = { x: -frontRect.width / 2 + convert(getLength(item.rect[3], v0)).from('cm').to(layer.unit) * scale, y: -height / 2 }; } wallPosArray.push(vertex0); wallPosArray.push(vertex1); // determin which side(left or right) item is closer to. If item is closer to left side, it will be included in leftBaseITems var distLeft = getLength(item.pos, v0); var distRight = getLength(item.pos, v1); if (distLeft < distRight) { rightWallItems.push(item); } else { leftWallItems.push(item); } }); } wallPosArray.sort(function (a, b) { return a.x - b.x; }); // leftItems = leftBaseItems + inverted leftWallItems : Here, it's different between BaseItem's order and WallItem's order leftBaseItems.sort(sortFunc); leftWallItems.sort(negSortFunc); rightBaseItems.sort(negSortFunc); rightWallItems.sort(sortFunc); var leftItems = leftBaseItems.concat(leftWallItems); var rightItems = rightBaseItems.concat(rightWallItems); // To display side dimensions, set rulerLines about leftItems leftItems.forEach(function (item, idx) { var forwardItems = []; var distLine = 0; var itemHeight = convert(item.size.height).from(scene.unit).to(layer.unit); for (var i = 0; i < idx; i++) { forwardItems.push(leftItems[i]); } if (!forwardItems.filter(function (it) { return it.itemInfo.properties.altitude._length === item.itemInfo.properties.altitude._length && it.itemInfo.properties.height._length === item.itemInfo.properties.height._length; }).length) { if (item.itemInfo.properties.altitude._length) { if (isSnapped(item.rect[3], item.rect[2])) { distLine = convert(getLength(item.rect[2], v1)).from(scene.unit).to(layer.unit); } else if (isSnapped(item.rect[2], item.rect[1])) { distLine = convert(getLength(item.rect[1], v1)).from(scene.unit).to(layer.unit); } var itemAltitude = convert(item.size.altitude).from(scene.unit).to(layer.unit); if (ceilHeight - (itemAltitude + itemHeight) > convert(DELTA).from(toler_unit).to(layer.unit)) { rulerLines.push({ v0: { x: width / 2, y: -height / 2 }, v1: { x: width / 2, y: height / 2 - (itemHeight + itemAltitude) * scale }, text: formatNumber(ceilHeight - (itemAltitude + itemHeight), DECIMAL_PLACES_2), space: rulerSpace + right_count * lineSpace }); } rulerLines.push({ v0: { x: width / 2 - distLine * scale, y: height / 2 - (itemHeight + itemAltitude) * scale }, v1: { x: width / 2 - distLine * scale, y: height / 2 - itemAltitude * scale }, text: formatNumber(itemHeight, DECIMAL_PLACES_2), space: rulerSpace + distLine * scale + right_count * lineSpace }); rulerLines.push({ v0: { x: width / 2, y: height / 2 - itemAltitude * scale }, v1: { x: width / 2, y: height / 2 }, text: formatNumber(itemAltitude, DECIMAL_PLACES_2), space: rulerSpace + right_count * lineSpace }); right_count++; } else { if (isSnapped(item.rect[3], item.rect[2])) { distLine = convert(getLength(item.rect[3], v0)).from(scene.unit).to(layer.unit); } else if (isSnapped(item.rect[2], item.rect[1])) { distLine = convert(getLength(item.rect[2], v0)).from(scene.unit).to(layer.unit); } rulerLines.push({ v0: { x: -width / 2 + distLine * scale, y: height / 2 }, v1: { x: -width / 2 + distLine * scale, y: height / 2 - itemHeight * scale }, text: formatNumber(itemHeight, DECIMAL_PLACES_2), space: rulerSpace + distLine * scale + left_count * lineSpace }); rulerLines.push({ v0: { x: -width / 2, y: height / 2 - itemHeight * scale }, v1: { x: -width / 2, y: -height / 2 }, text: formatNumber(ceilHeight - itemHeight, DECIMAL_PLACES_2), space: rulerSpace + left_count * lineSpace }); left_count++; } } }); // To display side dimensions, set rulerLines about rightItems rightItems.forEach(function (item, idx) { var forwardItems = []; var distLine = 0; var itemHeight = convert(item.size.height).from(scene.unit).to(layer.unit); for (var i = 0; i < idx; i++) { forwardItems.push(rightItems[i]); } if (!forwardItems.filter(function (it) { return it.itemInfo.properties.altitude._length === item.itemInfo.properties.altitude._length && it.itemInfo.properties.height._length === item.itemInfo.properties.height._length; }).length) { if (item.itemInfo.properties.altitude._length) { if (isSnapped(item.rect[3], item.rect[2])) { distLine = convert(getLength(item.rect[3], v0)).from(scene.unit).to(layer.unit); } else if (isSnapped(item.rect[2], item.rect[1])) { distLine = convert(getLength(item.rect[2], v0)).from(scene.unit).to(layer.unit); } var _itemHeight = convert(item.size.height).from(scene.unit).to(layer.unit); var itemAltitude = convert(item.size.altitude).from(scene.unit).to(layer.unit); rulerLines.push({ v0: { x: -width / 2, y: height / 2 }, v1: { x: -width / 2, y: height / 2 - itemAltitude * scale }, text: formatNumber(itemAltitude, DECIMAL_PLACES_2), space: rulerSpace + left_count * lineSpace }); rulerLines.push({ v0: { x: -width / 2 + distLine * scale, y: height / 2 - itemAltitude * scale }, v1: { x: -width / 2 + distLine * scale, y: height / 2 - (itemAltitude + _itemHeight) * scale }, text: formatNumber(_itemHeight, DECIMAL_PLACES_2), space: rulerSpace + +distLine * scale + left_count * lineSpace }); if (ceilHeight - (itemAltitude + _itemHeight) > convert(DELTA).from(toler_unit).to(layer.unit)) { rulerLines.push({ v0: { x: -width / 2, y: height / 2 - (itemAltitude + _itemHeight) * scale }, v1: { x: -width / 2, y: -height / 2 }, text: formatNumber(ceilHeight - (itemAltitude + _itemHeight), DECIMAL_PLACES_2), space: rulerSpace + left_count * lineSpace }); } left_count++; } else { if (isSnapped(item.rect[3], item.rect[2])) { distLine = convert(getLength(item.rect[2], v1)).from(scene.unit).to(layer.unit); } else if (isSnapped(item.rect[2], item.rect[1])) { distLine = convert(getLength(item.rect[1], v1)).from(scene.unit).to(layer.unit); } rulerLines.push({ v0: { x: width / 2, y: -height / 2 }, v1: { x: width / 2, y: height / 2 - itemHeight * scale }, text: formatNumber(ceilHeight - itemHeight, DECIMAL_PLACES_2), space: rulerSpace + right_count * lineSpace }); rulerLines.push({ v0: { x: width / 2 - distLine * scale, y: height / 2 - itemHeight * scale }, v1: { x: width / 2 - distLine * scale, y: height / 2 }, text: formatNumber(itemHeight, DECIMAL_PLACES_2), space: rulerSpace + distLine * scale + right_count * lineSpace }); right_count++; } } }); // To display wall line dimensions, set rulerLines rulerLines.push({ v0: { x: width / 2, y: -height / 2 }, v1: { x: width / 2, y: height / 2 }, text: ceilHeight, space: rulerSpace + lineSpace * right_count }); rulerLines.push({ v0: { x: -width / 2, y: height / 2 }, v1: { x: -width / 2, y: -height / 2 }, text: ceilHeight, space: rulerSpace + lineSpace * left_count }); rulerLines.push({ v0: { x: width / 2, y: height / 2 }, v1: { x: -width / 2, y: height / 2 }, text: formatNumber(lineLength, DECIMAL_PLACES_2), space: rulerSpace + (baseItems.length ? lineSpace : 0) }); rulerLines.push({ v0: { x: -width / 2, y: -height / 2 }, v1: { x: width / 2, y: -height / 2 }, text: formatNumber(lineLength, DECIMAL_PLACES_2), space: rulerSpace + (wallItems.length ? lineSpace : 0) }); // To display wallItems dimensions, set rulerLines with wallPosArray if (wallItems.length) { for (var i = 0; i < wallPosArray.length - 1; i++) { var dist = getLength(wallPosArray[i], wallPosArray[i + 1]) / scale; rulerLines.push({ v0: wallPosArray[i], v1: wallPosArray[i + 1], space: rulerSpace, text: formatNumber(dist, DECIMAL_PLACES_2) }); } } // To display baseItems dimensions, set rulerLines with basePosArray if (baseItems.length) { for (var j = 0; j < basePosArray.length - 1; j++) { var _dist = getLength(basePosArray[j], basePosArray[j + 1]) / scale; rulerLines.push({ v0: basePosArray[j], v1: basePosArray[j + 1], space: rulerSpace, text: formatNumber(_dist, DECIMAL_PLACES_2) }); } } rulerLines.forEach(function (line) { if (isNonZeroText(line.text)) rulerData.push(/*#__PURE__*/React.createElement(Ruler3D, { line: line, layer: layer, viewScale: viewScale, downloadFlag: downloadFlag })); }); return /*#__PURE__*/React.createElement("g", { opacity: layer.opacity }, rulerData); }