kitchen-simulator
Version:
It is a kitchen simulator (self-contained micro-frontend).
495 lines (481 loc) • 17 kB
JavaScript
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);
}