react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
339 lines (257 loc) • 9.46 kB
JSX
import * as Three from 'three';
import React from 'react';
const WIDTH=90;
const DEPTH=40;
const HEIGHT=30;
const grey = new Three.MeshLambertMaterial( {color: 0xd9d7d7} );
grey.side = Three.DoubleSide;
const darkGrey = new Three.MeshLambertMaterial( {color: 0x808287} );
darkGrey.side = Three.DoubleSide;
const black = new Three.MeshLambertMaterial({color:0x000000});
black.side = Three.DoubleSide;
const objectMaxLOD = makeObjectMaxLOD();
const objectMinLOD = makeObjectMinLOD();
function makeObjectMaxLOD() {
let air_conditioner = new Three.Mesh();
let roundedRectShape = new Three.Shape();
let x=0;
let y=0;
let width=.15;
let height=.6;
let radius=0.15;
roundedRectShape.moveTo( x, y );
roundedRectShape.lineTo( x + width, y);
roundedRectShape.lineTo( x + width + radius, y + radius);
roundedRectShape.quadraticCurveTo( x + width + radius, y + height, x + width/2, y + height );
roundedRectShape.lineTo( x + width/2, y+height );
roundedRectShape.lineTo( x, y + height) ;
let extrudeSettings = {
steps: 2,
depth: 1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let bodyGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings );
let body = new Three.Mesh( bodyGeometry, grey );
body.position.set(-.11,1.2,0);
body.rotation.z+=Math.PI;
air_conditioner.add(body);
let j=1.18;
for (let i = -.30; i > -.36; i-=.005) {
let gridHorizontalGeometry = new Three.BoxGeometry(.001, .025, .705);
let gridHorizontal = new Three.Mesh(gridHorizontalGeometry, darkGrey);
gridHorizontal.position.set(i,j,.5);
gridHorizontal.rotation.z+=Math.PI/4;
air_conditioner.add(gridHorizontal);
j-=.005
}
for (let k = .15; k < .87; k+=.05) {
let gridVerticalGeometry = new Three.BoxGeometry(.079, .025, .005);
let gridVertical = new Three.Mesh(gridVerticalGeometry, darkGrey);
gridVertical.position.set(-.324,1.148,k);
gridVertical.rotation.z+=Math.PI/4;
air_conditioner.add(gridVertical);
}
let roundedRectShape2 = new Three.Shape();
let x2=0;
let y2=0;
let width2=.2;
let height2=.4;
let radius2=0.15;
roundedRectShape2.moveTo( x2, y2 );
roundedRectShape2.lineTo( x2 + width2, y2);
roundedRectShape2.quadraticCurveTo( x2 + width2 + radius2, y2 + height2, x2 + width2/2, y2 + height2 );
roundedRectShape2.lineTo( x2 + width2/2, y2+height2 );
roundedRectShape2.quadraticCurveTo( x2 + width2 + radius2, y2 + height2/4, x2 , y2 );
let extrudeSettings2 = {
steps: 2,
depth: 1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let frontCoverGeometry = new Three.ExtrudeGeometry( roundedRectShape2, extrudeSettings2 );
let frontCover = new Three.Mesh( frontCoverGeometry, grey) ;
frontCover.position.set(-.2,1.1,0);
frontCover.rotation.z+=Math.PI;
air_conditioner.add(frontCover);
let roundedRectShape3 = new Three.Shape();
let x3=0;
let y3=0;
let width3=.1;
let height3=.1;
let radius3=0.15;
roundedRectShape3.moveTo( x3, y3 );
roundedRectShape3.quadraticCurveTo( x3 - width3/2 + radius3/2, y3 - height3, x3 + width3, y3);
roundedRectShape3.lineTo( x3 + width3, y3);
roundedRectShape3.quadraticCurveTo( x3 + width3/2 + radius3/2, y3 + 2 * height3, x3 + width3/2, y3 + height3 );
roundedRectShape3.lineTo( x3 + width3/2, y3 + height3 );
roundedRectShape3.quadraticCurveTo( x3 + width3/4, y3 + height3/6, x3 , y3 );
let extrudeSettings3 = {
steps: 2,
depth: .1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let flapSupportGeometry = new Three.ExtrudeGeometry( roundedRectShape3, extrudeSettings3 );
let flapLeft = new Three.Mesh( flapSupportGeometry, darkGrey ) ;
flapLeft.position.set(-.27,.62,0.1);
flapLeft.rotation.y+=Math.PI;
flapLeft.rotation.z-=Math.PI/9;
air_conditioner.add(flapLeft);
let flapRight = new Three.Mesh( flapSupportGeometry, darkGrey ) ;
flapRight.position.set(-.27,.62,1);
flapRight.rotation.y+=Math.PI;
flapRight.rotation.z-=Math.PI/9;
air_conditioner.add(flapRight);
let points2 = [];
points2.push( new Three.Vector3(.5, 0));
points2.push( new Three.Vector3(.5, 0));
points2.push( new Three.Vector3(.5, .8));
points2.push( new Three.Vector3(.5, .8));
let flapGeometry = new Three.LatheGeometry( points2, 200, Math.PI/2, Math.PI/16 );
let flap1 = new Three.Mesh( flapGeometry, darkGrey );
flap1.position.set(-.4,.18,.9);
flap1.rotation.z+=Math.PI/2;
flap1.rotation.y+=-Math.PI/2;
air_conditioner.add(flap1);
let flap2 = new Three.Mesh( flapGeometry, darkGrey );
flap2.position.set(-.4,.15,.9);
flap2.rotation.z+=Math.PI/2;
flap2.rotation.y+=-Math.PI/2;
air_conditioner.add(flap2);
return air_conditioner
}
function makeObjectMinLOD() {
let air_conditioner = new Three.Mesh();
let roundedRectShape = new Three.Shape();
let x=0;
let y=0;
let width=.15;
let height=.6;
let radius=0.15;
roundedRectShape.moveTo( x, y );
roundedRectShape.lineTo( x + width, y);
roundedRectShape.lineTo( x + width + radius, y + radius);
roundedRectShape.quadraticCurveTo( x + width + radius, y + height, x + width/2, y + height );
roundedRectShape.lineTo( x + width/2, y+height );
roundedRectShape.lineTo( x, y + height) ;
let extrudeSettings = {
steps: 2,
depth: 1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let bodyGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings );
let body = new Three.Mesh( bodyGeometry, grey );
body.position.set(-.11,1.2,0);
body.rotation.z+=Math.PI;
air_conditioner.add(body);
let roundedRectShape2 = new Three.Shape();
let x2=0;
let y2=0;
let width2=.2;
let height2=.4;
let radius2=0.15;
roundedRectShape2.moveTo( x2, y2 );
roundedRectShape2.lineTo( x2 + width2, y2);
roundedRectShape2.quadraticCurveTo( x2 + width2 + radius2, y2 + height2, x2 + width2/2, y2 + height2 );
roundedRectShape2.lineTo( x2 + width2/2, y2+height2 );
roundedRectShape2.quadraticCurveTo( x2 + width2 + radius2, y2 + height2/4, x2 , y2 );
let extrudeSettings2 = {
steps: 2,
depth: 1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
let frontCoverGeometry = new Three.ExtrudeGeometry( roundedRectShape2, extrudeSettings2 );
let frontCover = new Three.Mesh( frontCoverGeometry, grey) ;
frontCover.position.set(-.2,1.1,0);
frontCover.rotation.z+=Math.PI;
air_conditioner.add(frontCover);
return air_conditioner
}
export default {
name: 'conditioner',
prototype: 'items',
info: {
tag: ['furnishings', 'metal'],
title: 'air conditioner',
description: 'air conditioner',
image: require('./air_conditioner.png')
},
properties: {
altitude: {
label: 'quota',
type: 'length-measure',
defaultValue: {
length: 220,
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;
}
return (
<g transform={`translate(${-WIDTH / 2},${-DEPTH / 2})`}>
<rect key='1' x='0' y='0' width={WIDTH} height={DEPTH}
style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: '2px', fill: '#84e1ce'}}/>
<text key='2' x='0' y='0'
transform={`translate(${WIDTH / 2}, ${DEPTH / 2}) 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 air_conditionerMaxLOD = new Three.Object3D();
air_conditionerMaxLOD.add(objectMaxLOD.clone());
let value = new Three.Box3().setFromObject(air_conditionerMaxLOD);
let deltaX = Math.abs(value.max.x - value.min.x);
let deltaY = Math.abs(value.max.y - value.min.y);
let deltaZ = Math.abs(value.max.z - value.min.z);
air_conditionerMaxLOD.position.x+= WIDTH/2.2;
air_conditionerMaxLOD.position.z+= DEPTH/1.2;
air_conditionerMaxLOD.position.y+= newAltitude;
air_conditionerMaxLOD.rotation.y+= -Math.PI/2;
air_conditionerMaxLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX/1.4);
/*************** lod min *******************/
let air_conditionerMinLOD = new Three.Object3D();
air_conditionerMinLOD.add(objectMinLOD.clone());
air_conditionerMinLOD.position.x+= WIDTH/2.2;
air_conditionerMinLOD.position.z+= DEPTH/1.2;
air_conditionerMinLOD.position.y+= newAltitude;
air_conditionerMinLOD.rotation.y+= -Math.PI/2;
air_conditionerMinLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX/1.4);
/**** all level of detail ***/
let lod = new Three.LOD();
lod.addLevel(air_conditionerMaxLOD, 200);
lod.addLevel(air_conditionerMinLOD, 900);
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);
}
};