react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
338 lines (262 loc) • 10.8 kB
JSX
import * as Three from 'three';
import React from 'react';
const RADIUS = 15;
const HEIGHT = 60;
//colors
const black = new Three.MeshLambertMaterial({color: 0x000000});
const red = new Three.MeshLambertMaterial({color: 0xff0000});
const grey = new Three.MeshLambertMaterial({color: 0xCCCCCC});
const yellow = new Three.MeshLambertMaterial({color: 0xffff00});
const objectMaxLOD = makeObjectMaxLOD();
const objectMiddleLOD = makeObjectMiddleLOD();
const objectMinLOD = makeObjectMinLOD();
function makeObjectMaxLOD() {
const bodyGeometry = new Three.CylinderGeometry(0.1, 0.1, 0.5, 32);
const body = new Three.Mesh(bodyGeometry, red);
body.position.set(0, 1, 0);
const bodyGeometry2 = new Three.CylinderGeometry(0.11, 0.11, 0.03, 32);
const lock = new Three.Mesh(bodyGeometry2, black);
lock.position.set(0, -0.2, 0);
body.add(lock);
const geometrySphereUp = new Three.SphereGeometry(0.1, 32, 32);
const sphereUp = new Three.Mesh(geometrySphereUp, red);
sphereUp.position.set(0, 0.25, 0);
body.add(sphereUp);
const cylinderGeometry = new Three.CylinderGeometry(0.015, 0.025, 0.05, 32);
const vent_p1 = new Three.Mesh(cylinderGeometry, black);
vent_p1.position.z = -0.13;
vent_p1.position.y = -0.23;
body.add(vent_p1);
const cylinderGeometry1 = new Three.CylinderGeometry(0.01, 0.01, 0.02, 32);
const vent_p2 = new Three.Mesh(cylinderGeometry1, grey);
vent_p2.position.z = -0.13;
vent_p2.position.y = -0.2;
body.add(vent_p2);
const cylinderGeometry2 = new Three.CylinderGeometry(0.015, 0.02, 0.04, 32);
const cylinder2 = new Three.Mesh(cylinderGeometry2, black);
cylinder2.position.set(0, 0.35, 0);
body.add(cylinder2);
const cylinderGeometry3 = new Three.CylinderGeometry(0.01, 0.01, 0.02, 32);
const cylinder3 = new Three.Mesh(cylinderGeometry3, grey);
cylinder3.position.set(0, 0.38, 0);
body.add(cylinder3);
const cylinderGeometry4 = new Three.CylinderGeometry(0.005, 0.005, 0.02, 32);
const cylinder4 = new Three.Mesh(cylinderGeometry4, grey);
cylinder4.position.set(-0.01, 0.38, 0);
cylinder4.rotation.z += Math.PI / 2;
body.add(cylinder4);
const cylinderGeometry5 = new Three.CylinderGeometry(0.02, 0.02, 0.01, 32);
const cylinder5 = new Three.Mesh(cylinderGeometry5, grey);
cylinder5.position.set(-0.02, 0.38, 0);
cylinder5.rotation.z += Math.PI / 2;
body.add(cylinder5);
const textureLoader = new Three.TextureLoader();
const gageImage = textureLoader.load(require('./gage-image.png'));
const geometry2 = new Three.PlaneGeometry(0.04, 0.04);
const material2 = new Three.MeshLambertMaterial({map: gageImage, transparent: true});
const gage = new Three.Mesh(geometry2, material2);
gage.position.set(-0.0255, 0.38, 0);
gage.rotation.y = -Math.PI / 2;
body.add(gage);
const cylinderGeometry6 = new Three.CylinderGeometry(0.005, 0.005, 0.03, 32);
const cylinder6 = new Three.Mesh(cylinderGeometry6, grey);
cylinder6.position.set(0, 0.38, -0.01);
cylinder6.rotation.z += Math.PI / 2;
cylinder6.rotation.y += Math.PI / 2;
body.add(cylinder6);
const cylinderGeometry7 = new Three.CylinderGeometry(0.01, 0.01, 0.02, 32);
const cylinder7 = new Three.Mesh(cylinderGeometry7, grey);
cylinder7.position.set(0, 0.38, -0.03);
cylinder7.rotation.z += Math.PI / 2;
cylinder7.rotation.y += Math.PI / 2;
body.add(cylinder7);
const labelImage = textureLoader.load(require('./label-image.png'));
labelImage.wrapS = Three.RepeatWrapping;
labelImage.wrapT = Three.RepeatWrapping;
labelImage.repeat.set(1, 1);
labelImage.offset.x = 0; // 0.0 - 1.0
labelImage.offset.y = 0; // 0.0 - 1.0
const points = [
new Three.Vector2(.1, .666),
new Three.Vector2(.1, 1)
];
const geometry = new Three.LatheGeometry(points, 200, 0, Math.PI);
const material = new Three.MeshLambertMaterial({map: labelImage});
const label = new Three.Mesh(geometry, material);
label.rotation.y = 60;
label.position.y -= .75;
body.add(label);
const shape2 = new Three.Shape();
shape2.moveTo(0.02, 0.06);
shape2.lineTo(0.06, 0.07);
shape2.lineTo(0.08, 0.1);
shape2.lineTo(0.16, 0.1);
shape2.lineTo(0.18, 0.09);
shape2.lineTo(0.09, 0.08);
shape2.lineTo(0.07, 0.05);
shape2.lineTo(0.02, 0.04);
const extrudeSettings = {
steps: 2,
depth: 0.02,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
const geometry4 = new Three.ExtrudeGeometry(shape2, extrudeSettings);
const material4 = new Three.MeshLambertMaterial({color: 0xff0000});
const valve_p1 = new Three.Mesh(geometry4, material4);
valve_p1.rotation.y = -Math.PI / 2;
valve_p1.position.set(0.01, 0.35, -0.035);
body.add(valve_p1);
const shape3 = new Three.Shape();
shape3.moveTo(0.02, 0.06);
shape3.lineTo(0.04, 0.06);
shape3.lineTo(0.16, 0.05);
shape3.lineTo(0.18, 0.03);
shape3.lineTo(0.16, 0.04);
shape3.lineTo(0.02, 0.04);
const extrudeSettings2 = {
steps: 2,
depth: 0.016,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
const geometry5 = new Three.ExtrudeGeometry(shape3, extrudeSettings2);
const valve_p2 = new Three.Mesh(geometry5, red);
valve_p2.rotation.y = -Math.PI / 2;
valve_p2.position.set(0.01, 0.34, -0.035);
body.add(valve_p2);
const geometry6 = new Three.TorusGeometry(0.0075, 0.00125, 16, 32, 1200);
const safetyValve_p1 = new Three.Mesh(geometry6, yellow);
safetyValve_p1.rotation.x = -Math.PI / 2;
safetyValve_p1.position.set(-0.023, 0.41, 0.02);
body.add(safetyValve_p1);
const cylinderGeometry8 = new Three.CylinderGeometry(0.001, 0.001, 0.03, 32);
const safetyValve_p2 = new Three.Mesh(cylinderGeometry8, yellow);
safetyValve_p2.position.set(0, 0.41, 0.02);
safetyValve_p2.rotation.z += Math.PI / 2;
body.add(safetyValve_p2);
const cylinderGeometry9 = new Three.CylinderGeometry(0.0025, 0.0025, 0.026, 32);
const cylinder9 = new Three.Mesh(cylinderGeometry9, grey);
cylinder9.position.set(0, 0.40, 0.0);
cylinder9.rotation.z += Math.PI / 2;
body.add(cylinder9);
const curve = new Three.CatmullRomCurve3([
new Three.Vector3(.5, 0, 0),
new Three.Vector3(.5, 0, 0),
new Three.Vector3(0, 0, 0),
new Three.Vector3(-0.03, .1050, 0),
new Three.Vector3(-0.03, .1050, 0)
]);
const geometry7 = new Three.TubeGeometry(curve, 32, 0.008, 16, false);
const mesh = new Three.Mesh(geometry7, black);
mesh.position.set(0, 0.35, -0.13);
mesh.rotation.y -= Math.PI / 2;
mesh.rotation.z = (Math.PI / 2) + (4 * Math.PI);
mesh.rotation.x += Math.PI;
body.add(mesh);
return body
}
function makeObjectMiddleLOD() {
let bodyGeometry21 = new Three.CylinderGeometry(0.1, 0.1, 0.5, 8);
let body1 = new Three.Mesh(bodyGeometry21, red);
body1.position.set(0, 1, 0);
let bodyGeometry22 = new Three.CylinderGeometry(0.11, 0.11, 0.03, 8);
let lock2 = new Three.Mesh(bodyGeometry22, black);
lock2.position.set(0, -0.2, 0);
body1.add(lock2);
let geometrySphereUp1 = new Three.SphereGeometry(0.095, 32, 8);
let sphereUp1 = new Three.Mesh(geometrySphereUp1, red);
sphereUp1.position.set(0, 0.25, 0);
body1.add(sphereUp1);
return body1
}
function makeObjectMinLOD() {
let bodyGeometry0 = new Three.CylinderGeometry(0.1, 0.1, 0.475, 6);
let body0 = new Three.Mesh(bodyGeometry0, red);
body0.position.set(0, .95, 0);
return body0
}
export default {
name: "fire-extinguisher",
prototype: "items",
info: {
tag: ['security'],
title: "Fire extinguisher",
description: "Fire extinguisher",
image: require('./fire-extinguisher.png')
},
properties: {
altitude: {
label: "altitude",
type: "length-measure",
defaultValue: {
length: 100,
unit: 'cm'
}
}
},
render2D: function (element, layer, scene) {
let angle = element.rotation + 90;
let textRotation = 0;
if (Math.sin(angle * Math.PI / 180) < 0) {
textRotation = 180;
}
let arrow_style = {stroke: element.selected ? '#0096fd' : null, strokeWidth: "2px", fill: "#84e1ce"};
return (
<g transform={`translate(${-RADIUS / (RADIUS / 2)},${-(RADIUS + 5) / (RADIUS / 2) })`}>
<ellipse key="1" cx="0" cy="0" rx={RADIUS + 5} ry={RADIUS}
style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#ff0000"}}/>
<line key="2" x1={0} x2={0} y1={RADIUS} y2={2 * RADIUS} style={arrow_style}/>
<line key="3" x1={-RADIUS / 2 + .15 * RADIUS} x2={-RADIUS / 2 + RADIUS / 2} y1={1.2 * RADIUS} y2={2 * RADIUS}
style={arrow_style}/>
<line key="4" x1={0} x2={-RADIUS / 2 + .85 * RADIUS} y1={2 * RADIUS} y2={1.2 * RADIUS} style={arrow_style}/>
<text key="5" cx={RADIUS} cy={RADIUS}
transform={ `translate(${RADIUS / 8}, ${0}) scale(1,-1) rotate(${textRotation})`}
style={{textAnchor: "middle", fontSize: "11px"}}>
{element.type}
</text>
</g>
)
},
render3D: function (element, layer, scene) {
let newAltitude = element.properties.get('altitude').get('length');
/**************** LOD max ***********************/
let fireExtinguisher2 = new Three.Object3D();
fireExtinguisher2.add(objectMaxLOD.clone());
let value = new Three.Box3().setFromObject(fireExtinguisher2);
let deltaX = Math.abs(value.max.x - value.min.x);
let deltaY = Math.abs(value.max.y - value.min.y);
fireExtinguisher2.rotation.y += -Math.PI / 2;
fireExtinguisher2.position.y += -HEIGHT / 1.25 + newAltitude;
fireExtinguisher2.scale.set(RADIUS / deltaX, RADIUS / deltaX, HEIGHT / deltaY);
/**************** LOD middle ***********************/
let fireExtinguisher1 = new Three.Object3D();
fireExtinguisher1.add(objectMiddleLOD.clone());
fireExtinguisher1.position.y += -HEIGHT / 1.25 + newAltitude;
fireExtinguisher1.scale.set(RADIUS / deltaX, RADIUS / deltaX, HEIGHT / deltaY);
/**************** LOD min ***********************/
let fireExtinguisher0 = new Three.Object3D();
fireExtinguisher0.add(objectMinLOD.clone());
fireExtinguisher0.position.y += -HEIGHT / 1.35 + newAltitude;
fireExtinguisher0.scale.set(RADIUS / deltaX, RADIUS / deltaX, HEIGHT / deltaY);
/*** add all Level of Detail ***/
let lod = new Three.LOD();
lod.addLevel(fireExtinguisher2, 200);
lod.addLevel(fireExtinguisher1, 900);
lod.addLevel(fireExtinguisher0, 1200);
lod.updateMatrix();
lod.matrixAutoUpdate = false;
if (element.selected) {
let bbox = new Three.BoxHelper(lod, 0x99c3fb);
bbox.material.linewidth = 5;
bbox.renderOrder = 1000;
bbox.material.depthTest = false;
lod.add(bbox);
}
return Promise.resolve(lod);
}
};