UNPKG

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
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); } };