kitchen-simulator
Version:
It is a kitchen simulator (self-contained micro-frontend).
663 lines (653 loc) • 26.7 kB
JavaScript
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import { List } from 'immutable';
import { Project, Area, Line, Hole, Item, Vertex } from "./export";
import { GraphInnerCycles, GeometryUtils, IDBroker } from "../utils/export";
import { Layer as LayerModel } from "../models";
import { isEmpty } from "../utils/helper";
var sameSet = function sameSet(set1, set2) {
return set1.size === set2.size && set1.isSuperset(set2) && set1.isSubset(set2);
};
var sameDirection = function sameDirection(list1, list2) {
if (!sameSet(list1, list2)) return false;
if (list1.size < 3) return true;
var l0 = list1.get(0);
var l1 = list1.get(1);
var i0 = list2.indexOf(l0);
var i1 = list2.indexOf(l1);
return (i1 - i0 - 1) % list1.size == 0;
};
var Layer = /*#__PURE__*/function () {
function Layer() {
_classCallCheck(this, Layer);
}
return _createClass(Layer, null, [{
key: "create",
value: function create(state, name, altitude) {
var layerID = IDBroker.acquireID();
name = name || "layer ".concat(layerID);
altitude = altitude || 0;
var layer = new LayerModel({
id: layerID,
name: name,
altitude: altitude
});
state = state.setIn(['scene', 'selectedLayer'], layerID);
state = state.setIn(['scene', 'layers', layerID], layer);
return {
updatedState: state
};
}
}, {
key: "select",
value: function select(state, layerID) {
if (!state.get('alterate')) state = Project.unselectAll(state).updatedState;
state = state.setIn(['scene', 'selectedLayer'], layerID);
return {
updatedState: state
};
}
}, {
key: "selectAll",
value: function selectAll(state, layerID) {
if (!state.get('alterate')) state = Project.unselectAll(state).updatedState;
state = state.setIn(['scene', 'selectedLayer'], layerID);
var layer = state.scene.layers.get(layerID);
layer.items.forEach(function (data) {
state = Layer.selectElement(state, layerID, 'items', data.id).updatedState;
});
layer.lines.forEach(function (data) {
state = Layer.selectElement(state, layerID, 'lines', data.id).updatedState;
});
layer.holes.forEach(function (data) {
state = Layer.selectElement(state, layerID, 'holes', data.id).updatedState;
});
layer.areas.forEach(function (data) {
state = Layer.selectElement(state, layerID, 'areas', data.id).updatedState;
});
layer.vertices.forEach(function (data) {
state = Layer.selectElement(state, layerID, 'vertices', data.id).updatedState;
});
return {
updatedState: state
};
}
}, {
key: "selectElement",
value: function selectElement(state, layerID, elementPrototype, elementID) {
state = state.setIn(['scene', 'layers', layerID, elementPrototype, elementID, 'selected'], true);
state = state.updateIn(['scene', 'layers', layerID, 'selected', elementPrototype], function (elems) {
return elems.push(elementID);
});
return {
updatedState: state
};
}
}, {
key: "unselect",
value: function unselect(state, layerID, elementPrototype, elementID) {
state = state.setIn(['scene', 'layers', layerID, elementPrototype, elementID, 'selected'], false);
state = state.updateIn(['scene', 'layers', layerID, 'selected', elementPrototype], function (elems) {
return elems.filter(function (el) {
return el.id === elementID;
});
});
return {
updatedState: state
};
}
}, {
key: "updateMovingState",
value: function updateMovingState(state, showflag) {
var _state = state,
scene = _state.scene;
state = state.merge({
scene: scene.mergeIn(['showfg'], showflag)
});
return {
updatedState: state
};
}
}, {
key: "unselectAll",
value: function unselectAll(state, layerID) {
var _state$getIn = state.getIn(['scene', 'layers', layerID]),
lines = _state$getIn.lines,
holes = _state$getIn.holes,
items = _state$getIn.items,
areas = _state$getIn.areas;
if (lines) lines.forEach(function (line) {
state = Line.unselect(state, layerID, line.id).updatedState;
});
if (holes) holes.forEach(function (hole) {
state = Hole.unselect(state, layerID, hole.id).updatedState;
});
if (items) items.forEach(function (item) {
state = Item.unselect(state, layerID, item.id).updatedState;
});
if (areas) areas.forEach(function (area) {
state = Area.unselect(state, layerID, area.id).updatedState;
});
return {
updatedState: state
};
}
}, {
key: "setInitialDoorStyle",
value: function setInitialDoorStyle(state, doorStyle, oStyle) {
state = state.merge({
doorStyle: doorStyle
});
var _state2 = state,
scene = _state2.scene;
var layerID = scene.get('selectedLayer');
var selectedLayer = scene.layers.get(layerID);
selectedLayer = selectedLayer.setIn(['doorStyle'], doorStyle);
state = state.merge({
scene: scene.setIn(['layers', layerID], selectedLayer)
});
return {
updatedState: state
};
}
}, {
key: "setProperties",
value: function setProperties(state, layerID, properties) {
state = state.mergeIn(['scene', 'layers', layerID], properties);
state = state.updateIn(['scene', 'layers'], function (layers) {
return layers.sort(function (a, b) {
return a.altitude !== b.altitude ? a.altitude - b.altitude : a.order - b.order;
});
});
return {
updatedState: state
};
}
}, {
key: "remove",
value: function remove(state, layerID) {
state = state.removeIn(['scene', 'layers', layerID]);
state = state.setIn(['scene', 'selectedLayer'], state.scene.selectedLayer !== layerID ? state.scene.selectedLayer : state.scene.layers.first().id);
return {
updatedState: state
};
}
}, {
key: "removeElement",
value: function removeElement(state, layerID, elementPrototype, elementID) {
state = state.deleteIn(['scene', 'layers', layerID, elementPrototype, elementID]);
return {
updatedState: state
};
}
}, {
key: "lineInterior",
value: function lineInterior(relatedLine, line, changeLines, vertices, allLines, checkLines) {
var _this = this;
if (line.vertices[1] === relatedLine.vertices[1] || line.vertices[0] === relatedLine.vertices[0]) {
var tmp = line.vertices[0];
line.vertices[0] = line.vertices[1];
line.vertices[1] = tmp;
changeLines.push(line);
}
checkLines.push(relatedLine);
checkLines.push(line);
var relatedLines = [];
GeometryUtils.getRelatedLines(relatedLines, line, vertices, allLines);
var delflag = false;
if (isEmpty(allLines[line.id])) {
delflag = true;
}
if (relatedLines.length > 1) {
var _loop = function _loop(i) {
if (!changeLines.some(function (line) {
return line.id === relatedLines[i].id;
}) && !checkLines.some(function (cline) {
return cline.id === relatedLines[i].id;
})) {
var tline = delflag ? relatedLine : line;
_this.lineInterior(tline, relatedLines[i], changeLines, vertices, allLines, checkLines);
}
};
for (var i = 0; i < relatedLines.length; i++) {
_loop(i);
}
} else return;
}
}, {
key: "interiorsurfacedetect",
value: function interiorsurfacedetect(state, drawingLine, vertices, allLineArray, layerID) {
var relatedLines = [];
var allLines = allLineArray.toJS();
GeometryUtils.getRelatedLines(relatedLines, drawingLine, vertices, allLines);
if (isEmpty(relatedLines)) {
return {
updatedState: state
};
}
var changeLines = [];
var checkLines = [];
this.lineInterior(relatedLines[0], drawingLine, changeLines, vertices, allLines, checkLines);
for (var i = 0; i < changeLines.length; i++) {
// if (changeLines[i].vertices.length === 2)
if (!isEmpty(allLines[changeLines[i].id])) {
state = state.mergeIn(['scene', 'layers', layerID, 'lines', changeLines[i].id, 'vertices'], changeLines[i].vertices);
}
}
// determine the interior surface
var alltriangles = [];
var interiorLines = state.getIn(['scene', 'layers', layerID, 'lines']);
var tallLines = interiorLines.toJS();
var tallLinesArray = interiorLines.toArray();
var reverseLines = [];
tallLinesArray.forEach(function (tline) {
var line = tline.toJS();
var relatedLines = [];
GeometryUtils.getRelatedLines(relatedLines, line, vertices, tallLines);
relatedLines.forEach(function (relLine) {
if (relLine.vertices[0] === line.vertices[1]) {
if (!reverseLines.some(function (reverseLine) {
return reverseLine.id === relLine.id;
})) {
reverseLines.push(relLine);
}
if (!reverseLines.some(function (reverseLine) {
return reverseLine.id === line.id;
})) {
reverseLines.push(line);
}
// get the three points of triangle
var x1 = vertices[line.vertices[0]].x;
var y1 = vertices[line.vertices[0]].y;
var x2 = vertices[line.vertices[1]].x;
var y2 = vertices[line.vertices[1]].y;
var x3 = vertices[relLine.vertices[1]].x;
var y3 = vertices[relLine.vertices[1]].y;
// calculate the area of triangle
var triArea = Math.abs((y1 + y3) * (x3 - x1) - (y1 + y2) * (x2 - x1) - (y3 + y2) * (x3 - x2)) / 2;
var triangle = {
points: [{
x: x1,
y: y1
}, {
x: x2,
y: y2
}, {
x: x3,
y: y3
}],
area: triArea
};
// determine the + or - symbol of triangle
var area = 0;
for (var _i = 0; _i < 3; _i++) {
var j = (_i + 1) % 3;
area += triangle.points[_i].x * triangle.points[j].y;
area -= triangle.points[j].x * triangle.points[_i].y;
}
if (area > 0) {
triangle.area = -triangle.area;
}
alltriangles.push(triangle);
}
});
});
var reverse = false;
var allSum = 0;
alltriangles.forEach(function (triangle) {
allSum += triangle.area;
});
// if all sum of triangle's area is smaller than zero, all walls have to be inverted.
if (allSum >= 0) {
reverse = false;
} else reverse = true;
if (reverse) {
reverseLines.forEach(function (line) {
var tmp = line.vertices[0];
line.vertices[0] = line.vertices[1];
line.vertices[1] = tmp;
state = state.mergeIn(['scene', 'layers', layerID, 'lines', line.id, 'vertices'], line.vertices);
});
}
return {
updatedState: state
};
}
}, {
key: "detectAndUpdateAreas",
value: function detectAndUpdateAreas(state, layerID, drawingInfor) {
var verticesArray = []; //array with vertices coords
var linesArray;
var virtualArray = []; //array with edges
var vertexID_to_verticesArrayIndex = {};
var verticesArrayIndex_to_vertexID = {};
state.getIn(['scene', 'layers', layerID, 'vertices']).forEach(function (vertex) {
var verticesCount = verticesArray.push([vertex.x, vertex.y]);
var latestVertexIndex = verticesCount - 1;
vertexID_to_verticesArrayIndex[vertex.id] = latestVertexIndex;
verticesArrayIndex_to_vertexID[latestVertexIndex] = vertex.id;
});
var vertexCount = verticesArray.length;
var vitual = {};
linesArray = state.getIn(['scene', 'layers', layerID, 'lines']).map(function (line) {
return line.vertices.map(function (vertexID) {
return vertexID_to_verticesArrayIndex[vertexID];
}).toArray();
});
//open line
// if (vertexCount > 1 && !linesArray.some(line => (line[0]==0 && line[1]==vertexCount-1) || (line[1]==0 && line[0]==vertexCount-1))) {
// linesArray = linesArray.set(IDBroker.acquireID(), [0, vertexCount-1]);
// }
var innerCyclesByVerticesArrayIndex = GraphInnerCycles.calculateInnerCycles(verticesArray, linesArray);
var innerCyclesByVerticesID = new List(innerCyclesByVerticesArrayIndex).map(function (cycle) {
return new List(cycle.map(function (vertexIndex) {
return verticesArrayIndex_to_vertexID[vertexIndex];
}));
});
// All area vertices should be ordered in counterclockwise order
innerCyclesByVerticesID = innerCyclesByVerticesID.map(function (area) {
return GraphInnerCycles.isClockWiseOrder(area.map(function (vertexID) {
return state.getIn(['scene', 'layers', layerID, 'vertices', vertexID]);
})) ? area.reverse() : area;
});
var areaIDs = [];
//remove areas
state.getIn(['scene', 'layers', layerID, 'areas']).forEach(function (area) {
var areaInUse = innerCyclesByVerticesID.some(function (vertices) {
return sameDirection(vertices, area.vertices);
});
if (!areaInUse) {
state = Area.remove(state, layerID, area.id).updatedState;
}
});
//add new areas
innerCyclesByVerticesID.forEach(function (cycle, ind) {
var areaInUse = state.getIn(['scene', 'layers', layerID, 'areas']).find(function (area) {
return sameDirection(area.vertices, cycle);
});
if (areaInUse) {
areaIDs[ind] = areaInUse.id;
state = state.setIn(['scene', 'layers', layerID, 'areas', areaIDs[ind], 'holes'], new List());
} else {
var areaVerticesCoords = cycle.map(function (vertexID) {
return state.getIn(['scene', 'layers', layerID, 'vertices', vertexID]);
});
var resultAdd = Area.add(state, layerID, 'area', areaVerticesCoords, state.catalog);
areaIDs[ind] = resultAdd.area.id;
state = resultAdd.updatedState;
}
});
// Build a relationship between areas and their coordinates
var verticesCoordsForArea = areaIDs.map(function (id) {
var vertices = state.getIn(['scene', 'layers', layerID, 'areas', id]).vertices.map(function (vertexID) {
var _state$getIn2 = state.getIn(['scene', 'layers', layerID, 'vertices', vertexID]),
x = _state$getIn2.x,
y = _state$getIn2.y;
return new List([x, y]);
});
return {
id: id,
vertices: vertices
};
});
// Find all holes for an area
var i, j;
for (i = 0; i < verticesCoordsForArea.length; i++) {
var holesList = new List(); // The holes for this area
var areaVerticesList = verticesCoordsForArea[i].vertices.flatten().toArray();
for (j = 0; j < verticesCoordsForArea.length; j++) {
if (i !== j) {
var isHole = GeometryUtils.ContainsPoint(areaVerticesList, verticesCoordsForArea[j].vertices.get(0).get(0), verticesCoordsForArea[j].vertices.get(0).get(1));
if (isHole) {
holesList = holesList.push(verticesCoordsForArea[j].id);
}
}
}
state = state.setIn(['scene', 'layers', layerID, 'areas', verticesCoordsForArea[i].id, 'holes'], holesList);
}
// Remove holes which are already holes for other areas
areaIDs.forEach(function (areaID) {
var doubleHoles = new Set();
var areaHoles = state.getIn(['scene', 'layers', layerID, 'areas', areaID, 'holes']);
areaHoles.forEach(function (areaHoleID) {
var holesOfholes = state.getIn(['scene', 'layers', layerID, 'areas', areaHoleID, 'holes']);
holesOfholes.forEach(function (holeID) {
if (areaHoles.indexOf(holeID) !== -1) doubleHoles.add(holeID);
});
});
doubleHoles.forEach(function (doubleHoleID) {
areaHoles = areaHoles.remove(areaHoles.indexOf(doubleHoleID));
});
state = state.setIn(['scene', 'layers', layerID, 'areas', areaID, 'holes'], areaHoles);
});
// update direction of lines surrounding area
var layer = state.getIn(['scene', 'layers', layerID]);
var allAreaLines = GeometryUtils.getAllAreaLines(layer);
// check whether the room is colsed. in this case, the allAreaLines have some values and if doesn't close, this value has nothing.
layer.lines.forEach(function (line) {
allAreaLines.some(function (l) {
if (line.vertices.get(0) == l[0] && line.vertices.get(1) == l[1]) {
state = state.setIn(['scene', 'layers', layerID, 'lines', line.id, 'vertices', 0], l[1]);
state = state.setIn(['scene', 'layers', layerID, 'lines', line.id, 'vertices', 1], l[0]);
return true;
} else if (line.vertices.get(1) == l[0] && line.vertices.get(0) == l[1]) {
return true;
} else {
return false;
}
});
});
//
var separatedLine = [];
var allLinesArray = state.getIn(['scene', 'layers', layerID, 'lines']);
allLinesArray.forEach(function (line) {
var isAreaLine = false;
isAreaLine = allAreaLines.some(function (areaLine) {
if (areaLine[0] == line.vertices.get(0) && areaLine[1] == line.vertices.get(1) || areaLine[0] == line.vertices.get(1) && areaLine[1] == line.vertices.get(0)) return true;
});
// console.log(
// 'Layer_Vertices',
// layer.vertices.get(line.vertices.get(0)).toJS()
// );
if (!isAreaLine) {
if (!(GeometryUtils.isPointInArea(GeometryUtils.getAllArea(layer), layer.vertices.get(line.vertices.get(0))) && GeometryUtils.isPointInArea(GeometryUtils.getAllArea(layer), layer.vertices.get(line.vertices.get(1))))) {
separatedLine.push(line);
}
}
});
var separatedLineCnt = separatedLine.length;
if (separatedLineCnt == 1) {
separatedLine.forEach(function (line) {
var ptArray = [],
pt3 = [],
pt4 = [];
ptArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(0)]]);
ptArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(1)]]);
pt3.push(ptArray[1][1] - ptArray[0][1] + ptArray[1][0]);
pt3.push(ptArray[0][0] - ptArray[1][0] + ptArray[1][1]);
ptArray.push(pt3);
pt4.push(ptArray[0][0] + ptArray[2][0] - ptArray[1][0]);
pt4.push(ptArray[0][1] + ptArray[2][1] - ptArray[1][1]);
ptArray.push(pt4);
var pointArray = [];
ptArray.forEach(function (pt) {
var point = {
x: pt[0],
y: pt[1]
};
pointArray.push(point);
});
pointArray.reverse();
var resultAdd = Area.add(state, layerID, 'area', pointArray, state.catalog);
state = resultAdd.updatedState;
});
} else if (separatedLineCnt > 1) {
var ptXArray = [],
ptYArray = [],
ptXMin,
ptXMax,
ptYMin,
ptYMAX;
separatedLine.forEach(function (line) {
ptXArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(0)]][0]);
ptXArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(1)]][0]);
ptYArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(0)]][1]);
ptYArray.push(verticesArray[vertexID_to_verticesArrayIndex[line.vertices.get(1)]][1]);
});
ptXMin = Math.min.apply(null, ptXArray);
ptXMax = Math.max.apply(null, ptXArray);
ptYMin = Math.min.apply(null, ptYArray);
ptYMAX = Math.max.apply(null, ptYArray);
var pointArray = [];
pointArray.push({
x: ptXMin,
y: ptYMin
});
pointArray.push({
x: ptXMax,
y: ptYMin
});
pointArray.push({
x: ptXMax,
y: ptYMAX
});
pointArray.push({
x: ptXMin,
y: ptYMAX
});
var resultAdd = Area.add(state, layerID, 'area', pointArray, state.catalog);
state = resultAdd.updatedState;
if (!isEmpty(drawingInfor)) {
var allVertices = state.getIn(['scene', 'layers', layerID, 'vertices']);
var resultInterior = this.interiorsurfacedetect(state, drawingInfor.drawingLine.toJS(), allVertices.toJS(), allLinesArray, layerID);
if (!isEmpty(resultInterior)) {
state = resultInterior.updatedState;
}
}
}
return {
updatedState: state
};
}
}, {
key: "removeZeroLengthLines",
value: function removeZeroLengthLines(state, layerID) {
var updatedState = state.getIn(['scene', 'layers', layerID, 'lines']).reduce(function (newState, line) {
var v_id0 = line.getIn(['vertices', 0]);
var v_id1 = line.getIn(['vertices', 1]);
var v0 = newState.getIn(['scene', 'layers', layerID, 'vertices', v_id0]);
var v1 = newState.getIn(['scene', 'layers', layerID, 'vertices', v_id1]);
if (GeometryUtils.verticesDistance(v0, v1) === 0) {
newState = Line.remove(newState, layerID, line.id).updatedState;
}
return newState;
}, state);
return {
updatedState: updatedState
};
}
}, {
key: "mergeEqualsVertices",
value: function mergeEqualsVertices(state, layerID, vertexID) {
//1. find vertices to remove
var vertex = state.getIn(['scene', 'layers', layerID, 'vertices', vertexID]);
if (vertex === undefined || vertex === null) return {
updatedState: state
};
var doubleVertices = state.getIn(['scene', 'layers', layerID, 'vertices']).filter(function (v) {
return v.id !== vertexID && GeometryUtils.samePoints(vertex, v) // &&
//!v.lines.contains( vertexID ) &&
//!v.areas.contains( vertexID )
;
});
if (doubleVertices.isEmpty()) return {
updatedState: state
};
doubleVertices.forEach(function (doubleVertex) {
var reduced = doubleVertex.lines.reduce(function (reducedState, lineID) {
reducedState = reducedState.updateIn(['scene', 'layers', layerID, 'lines', lineID, 'vertices'], function (vertices) {
if (vertices) {
return vertices.map(function (v) {
return v === doubleVertex.id ? vertexID : v;
});
}
});
reducedState = Vertex.addElement(reducedState, layerID, vertexID, 'lines', lineID).updatedState;
return reducedState;
}, state);
var biReduced = doubleVertex.areas.reduce(function (reducedState, areaID) {
reducedState = reducedState.updateIn(['scene', 'layers', layerID, 'areas', areaID, 'vertices'], function (vertices) {
if (vertices) return vertices.map(function (v) {
return v === doubleVertex.id ? vertexID : v;
});
});
reducedState = Vertex.addElement(reducedState, layerID, vertexID, 'areas', areaID).updatedState;
return reducedState;
}, reduced);
state = Vertex.remove(biReduced, layerID, doubleVertex.id, null, null, true).updatedState;
});
return {
updatedState: state
};
}
}, {
key: "setPropertiesOnSelected",
value: function setPropertiesOnSelected(state, layerID, properties) {
var selected = state.getIn(['scene', 'layers', layerID, 'selected']);
selected.lines.forEach(function (lineID) {
return state = Line.setProperties(state, layerID, lineID, properties).updatedState;
});
selected.holes.forEach(function (holeID) {
return state = Hole.setProperties(state, layerID, holeID, properties).updatedState;
});
selected.areas.forEach(function (areaID) {
return state = Area.setProperties(state, layerID, areaID, properties).updatedState;
});
selected.items.forEach(function (itemID) {
return state = Item.setProperties(state, layerID, itemID, properties).updatedState;
});
return {
updatedState: state
};
}
}, {
key: "updatePropertiesOnSelected",
value: function updatePropertiesOnSelected(state, layerID, properties) {
var selected = state.getIn(['scene', 'layers', layerID, 'selected']);
selected.lines.forEach(function (lineID) {
return state = Line.updateProperties(state, layerID, lineID, properties).updatedState;
});
selected.holes.forEach(function (holeID) {
return state = Hole.updateProperties(state, layerID, holeID, properties).updatedState;
});
selected.areas.forEach(function (areaID) {
return state = Area.updateProperties(state, layerID, areaID, properties).updatedState;
});
selected.items.forEach(function (itemID) {
return state = Item.updateProperties(state, layerID, itemID, properties).updatedState;
});
return {
updatedState: state
};
}
}, {
key: "setAttributesOnSelected",
value: function setAttributesOnSelected(state, layerID, attributes) {
var selected = state.getIn(['scene', 'layers', layerID, 'selected']);
selected.lines.forEach(function (lineID) {
return state = Line.setAttributes(state, layerID, lineID, attributes).updatedState;
});
selected.holes.forEach(function (holeID) {
return state = Hole.setAttributes(state, layerID, holeID, attributes).updatedState;
});
selected.items.forEach(function (itemID) {
return state = Item.setAttributes(state, layerID, itemID, attributes).updatedState;
});
//selected.areas.forEach(areaID => state = Area.setAttributes( state, layerID, areaID, attributes ).updatedState);
return {
updatedState: state
};
}
}]);
}();
export { Layer as default };