UNPKG

react-planner

Version:

react-planner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.

411 lines (337 loc) 13 kB
import * as Three from 'three'; import React from 'react'; const HEIGHT = 60; const steel = new Three.MeshLambertMaterial({color:0xffffff}); const grey = new Three.MeshLambertMaterial({color:0xAAAAAA}); const yellow = new Three.MeshLambertMaterial({color: 0xFF9933}); const blue = new Three.MeshLambertMaterial({color:0x0000ff}); function makeObjectMaxLOD(newWidth,newDepth) { let sink = new Three.Mesh(); let rectShape = new Three.Shape(); let x=0; let y=0; let width=newWidth; let height=newDepth; let newHeight= HEIGHT; let radius=newDepth/10; rectShape.moveTo( x, y + radius ); rectShape.lineTo( x, y + height - radius ); rectShape.quadraticCurveTo( x, y + height, x + radius, y + height ); rectShape.lineTo( x + width - radius, y + height) ; rectShape.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); rectShape.lineTo( x + width, y + radius ); rectShape.quadraticCurveTo( x + width, y, x + width - radius, y ); rectShape.lineTo( x + radius, y ); rectShape.quadraticCurveTo( x, y, x, y + radius ); let extrudeSettings = { steps: 2, depth: newHeight/40, bevelEnabled: false, bevelThickness: newHeight, bevelSize: newHeight, bevelSegments: 2 }; let geometry = new Three.ExtrudeGeometry( rectShape, extrudeSettings ); let mesh = new Three.Mesh( geometry, steel ) ; mesh.rotation.x+=Math.PI/2; mesh.position.y=newHeight/4; sink.add(mesh); let rectShape2 = new Three.Shape(); let hole = new Three.Path(); rectShape2.moveTo( x, y + radius ); rectShape2.lineTo( x, y + height - radius ); rectShape2.quadraticCurveTo( x, y + height, x + radius, y + height ); rectShape2.lineTo( x + width - radius, y + height) ; rectShape2.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); rectShape2.lineTo( x + width, y + radius ); rectShape2.quadraticCurveTo( x + width, y, x + width - radius, y ); rectShape2.lineTo( x + radius, y ); rectShape2.quadraticCurveTo( x, y, x, y + radius ); hole.moveTo(newWidth/20, newDepth/20); hole.lineTo(newWidth-newWidth/20, newDepth/20); hole.lineTo(newWidth-newWidth/20, newDepth-newDepth/20); hole.lineTo(newWidth/20, newDepth-newDepth/20); rectShape2.holes.push(hole); let extrudeSettings2 = { steps: 2, depth: newHeight/4, bevelEnabled: false, bevelThickness: newHeight, bevelSize: newHeight, bevelSegments: 2 }; let geometry2 = new Three.ExtrudeGeometry( rectShape2, extrudeSettings2 ); let mesh2 = new Three.Mesh( geometry2, steel ) ; mesh2.rotation.x+=Math.PI/2; mesh2.position.y+=newHeight/2; sink.add(mesh2); //pipe let pipe_p1 = new Three.Mesh(new Three.TorusGeometry( 2.5, 2.5, 16, 16, Math.PI/2 ), yellow); pipe_p1.position.set(newWidth/2,newHeight/5.5,newDepth/2-2.5); pipe_p1.rotation.z=-Math.PI/2; pipe_p1.rotation.y-=Math.PI/2; sink.add(pipe_p1); let cylinderGeometry1 = new Three.CylinderGeometry(2.25,2.25,newDepth/2,80); let pipe_p2 = new Three.Mesh(cylinderGeometry1,yellow); pipe_p2.rotation.z=Math.PI/2; pipe_p2.rotation.y-=Math.PI/2; pipe_p2.position.set(newWidth/2,newHeight/7.5,newDepth/4.5); sink.add(pipe_p2); let cylinderGeometry2 = new Three.CylinderGeometry(2.5,2.5,newDepth/12,80); let pipe_p3 = new Three.Mesh(cylinderGeometry2,yellow); pipe_p3.rotation.y-=Math.PI/2; pipe_p3.position.set(newWidth/2,newHeight/4.85,newDepth/2); sink.add(pipe_p3); //tap let cylinderGeometry66 = new Three.CylinderGeometry(1.25,1.25,8,12); let tap_p1 = new Three.Mesh(cylinderGeometry66,grey); tap_p1.position.set(newWidth/2,newHeight/1.45,3); tap_p1.rotation.z-=Math.PI/2; tap_p1.rotation.y+=Math.PI/2; sink.add(tap_p1); let cylinderGeometry5 = new Three.CylinderGeometry(2.7,3,5,12); let tap_p2 = new Three.Mesh(cylinderGeometry5,grey); tap_p2.position.set(newWidth/2, newHeight/1.45,10); tap_p2.rotation.z-=Math.PI/2; tap_p2.rotation.y+=Math.PI/2; sink.add(tap_p2); let cylinderGeometry6 = new Three.CylinderGeometry(2,2,5.5,80); let tap_p3 = new Three.Mesh(cylinderGeometry6,blue); tap_p3.position.set(newWidth/2, newHeight/1.45,10); tap_p3.rotation.z-=Math.PI/2; tap_p3.rotation.y+=Math.PI/2; sink.add(tap_p3); let curve = new Three.CatmullRomCurve3( [ new Three.Vector3( -12, -10, 0 ), new Three.Vector3( -12, -5, 0 ), new Three.Vector3( 0, 0, 0 ), new Three.Vector3( 6, 5, 0 ), new Three.Vector3( 6, 10, 0 ) ] ); let geometry7 = new Three.TubeGeometry(curve, 32, 1, 16, false); let mesh3 = new Three.Mesh(geometry7, grey); mesh3.position.set(newWidth/2, newHeight/1.7,11); mesh3.rotation.y+=Math.PI/2; mesh3.rotation.z-=Math.PI/8; sink.add(mesh3); //hole let cylinderGeometry7 = new Three.CylinderGeometry(newDepth/20,newDepth/20,newHeight/100,80); let blackMaterial = new Three.MeshLambertMaterial({color: 0x000000}); let hole_p1 = new Three.Mesh(cylinderGeometry7,blackMaterial); hole_p1.position.set(newWidth/2,newHeight/4,newDepth/2); sink.add(hole_p1); let cylinderGeometry8 = new Three.CylinderGeometry(newDepth/10,newDepth/10,newHeight/200,80,80,false,0,Math.PI); let whiteMaterial = new Three.MeshLambertMaterial({color: 0xffffff}); let hole_p2 = new Three.Mesh(cylinderGeometry8,whiteMaterial); hole_p2.scale.set(.25,.5,.5); hole_p2.rotation.z=Math.PI/2; hole_p2.position.set(newWidth/2,newHeight/4,newDepth/2); sink.add(hole_p2); let hole_p3 = new Three.Mesh(cylinderGeometry8,whiteMaterial); hole_p3.rotation.z=Math.PI/2; hole_p3.rotation.y=Math.PI/2; hole_p3.scale.set(.25,.5,.5); hole_p3.position.set(newWidth/2,newHeight/4,newDepth/2); sink.add(hole_p3); let hole_p4 = new Three.Mesh(cylinderGeometry8,whiteMaterial); hole_p4.rotation.z=Math.PI/2; hole_p4.rotation.y=Math.PI/4; hole_p4.position.set(newWidth/2,newHeight/4,newDepth/2); hole_p4.scale.set(.25,.5,.5); sink.add(hole_p4); let hole_p5 = new Three.Mesh(cylinderGeometry8,whiteMaterial); hole_p5.rotation.z=Math.PI/2; hole_p5.rotation.y=-Math.PI/4; hole_p5.position.set(newWidth/2,newHeight/4,newDepth/2); hole_p5.scale.set(.25,.5,.5); sink.add(hole_p5); return sink } function makeObjectMinLOD(newWidth,newDepth) { let sink = new Three.Mesh(); let rectShape = new Three.Shape(); let x=0; let y=0; let width=newWidth; let height=newDepth; let newHeight= HEIGHT; let radius=newDepth/10; rectShape.moveTo( x, y + radius ); rectShape.lineTo( x, y + height - radius ); rectShape.quadraticCurveTo( x, y + height, x + radius, y + height ); rectShape.lineTo( x + width - radius, y + height) ; rectShape.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); rectShape.lineTo( x + width, y + radius ); rectShape.quadraticCurveTo( x + width, y, x + width - radius, y ); rectShape.lineTo( x + radius, y ); rectShape.quadraticCurveTo( x, y, x, y + radius ); let extrudeSettings = { steps: 2, depth: newHeight/40, bevelEnabled: false, bevelThickness: newHeight, bevelSize: newHeight, bevelSegments: 2 }; let geometry = new Three.ExtrudeGeometry( rectShape, extrudeSettings ); let mesh = new Three.Mesh( geometry, steel ) ; mesh.rotation.x+=Math.PI/2; mesh.position.y=newHeight/4; sink.add(mesh); let rectShape2 = new Three.Shape(); let hole = new Three.Path(); rectShape2.moveTo( x, y + radius ); rectShape2.lineTo( x, y + height - radius ); rectShape2.quadraticCurveTo( x, y + height, x + radius, y + height ); rectShape2.lineTo( x + width - radius, y + height) ; rectShape2.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); rectShape2.lineTo( x + width, y + radius ); rectShape2.quadraticCurveTo( x + width, y, x + width - radius, y ); rectShape2.lineTo( x + radius, y ); rectShape2.quadraticCurveTo( x, y, x, y + radius ); hole.moveTo(newWidth/20, newDepth/20); hole.lineTo(newWidth-newWidth/20, newDepth/20); hole.lineTo(newWidth-newWidth/20, newDepth-newDepth/20); hole.lineTo(newWidth/20, newDepth-newDepth/20); rectShape2.holes.push(hole); let extrudeSettings2 = { steps: 2, depth: newHeight/4, bevelEnabled: false, bevelThickness: newHeight, bevelSize: newHeight, bevelSegments: 2 }; let geometry2 = new Three.ExtrudeGeometry( rectShape2, extrudeSettings2 ); let mesh2 = new Three.Mesh( geometry2, steel ) ; mesh2.rotation.x+=Math.PI/2; mesh2.position.y+=newHeight/2; sink.add(mesh2); //tap let cylinderGeometry66 = new Three.CylinderGeometry(1.25,1.25,8,12); let tap_p1 = new Three.Mesh(cylinderGeometry66,grey); tap_p1.position.set(newWidth/2,newHeight/1.45,3); tap_p1.rotation.z-=Math.PI/2; tap_p1.rotation.y+=Math.PI/2; sink.add(tap_p1); let cylinderGeometry5 = new Three.CylinderGeometry(2.7,3,5,12); let tap_p2 = new Three.Mesh(cylinderGeometry5,grey); tap_p2.position.set(newWidth/2, newHeight/1.45,10); tap_p2.rotation.z-=Math.PI/2; tap_p2.rotation.y+=Math.PI/2; sink.add(tap_p2); let cylinderGeometry6 = new Three.CylinderGeometry(2,2,5.5,80); let tap_p3 = new Three.Mesh(cylinderGeometry6,blue); tap_p3.position.set(newWidth/2, newHeight/1.45,10); tap_p3.rotation.z-=Math.PI/2; tap_p3.rotation.y+=Math.PI/2; sink.add(tap_p3); let curve = new Three.CatmullRomCurve3( [ new Three.Vector3( -12, -10, 0 ), new Three.Vector3( -12, -5, 0 ), new Three.Vector3( 0, 0, 0 ), new Three.Vector3( 6, 5, 0 ), new Three.Vector3( 6, 10, 0 ) ] ); let geometry7 = new Three.TubeGeometry(curve, 32, 1, 16, false); let mesh3 = new Three.Mesh(geometry7, grey); mesh3.position.set(newWidth/2, newHeight/1.7,11); mesh3.rotation.y+=Math.PI/2; mesh3.rotation.z-=Math.PI/8; sink.add(mesh3); return sink } export default { name: "sink", prototype: "items", info: { tag: ['furnishings', 'metal'], title: "sink", description: "sink", image: require('./sink.png') }, properties: { width: { label: "width", type: "length-measure", defaultValue: { length: 50, unit: 'cm' } }, depth: { label: "depth", type: "length-measure", defaultValue: { length: 40, unit: 'cm' } }, altitude: { label: "altitude", type: "length-measure", defaultValue: { length: 80, unit: 'cm' } } }, render2D: function (element, layer, scene) { let newWidth = element.properties.get('width').get('length'); let newDepth = element.properties.get('depth').get('length'); let angle = element.rotation + 90; let textRotation = 0; if (Math.sin(angle * Math.PI / 180) < 0) { textRotation = 180; } let rect_style = {stroke : element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#84e1ce"}; return ( <g transform={`translate(${-newWidth / 2},${-newDepth / 2})`}> <rect key="1" x="0" y="0" width={newWidth} height={newDepth} style={rect_style}/> <text key="2" x="0" y="0" transform={`translate(${newWidth / 2}, ${newDepth / 2}) scale(1,-1) rotate(${textRotation})`} style={{textAnchor: "middle", fontSize: "11px"}}> {element.type} </text> </g> ) }, render3D: function (element, layer, scene) { let newWidth = element.properties.get('width').get('length'); let newDepth = element.properties.get('depth').get('length'); let newHeight = HEIGHT; let newAltitude = element.properties.get('altitude').get('length'); /**************** lod max ********************/ let sinkMaxLOD=new Three.Object3D(); sinkMaxLOD.add(makeObjectMaxLOD(newWidth,newDepth).clone()); let value = new Three.Box3().setFromObject(sinkMaxLOD); 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); sinkMaxLOD.scale.set(newWidth / deltaX, newHeight / deltaY, newDepth / deltaZ); sinkMaxLOD.position.y+= -newHeight/5 + newAltitude; sinkMaxLOD.position.z-= newDepth/4; sinkMaxLOD.position.x-= newWidth/2; /**************** lod min ********************/ let sinkMinLOD=new Three.Object3D(); sinkMinLOD.add(makeObjectMinLOD(newWidth,newDepth).clone()); sinkMinLOD.scale.set(newWidth / deltaX, newHeight / deltaY, newDepth / deltaZ); sinkMinLOD.position.y+= -newHeight/5 + newAltitude; sinkMinLOD.position.z-= newDepth/4; sinkMinLOD.position.x-= newWidth/2; /**** all level of detail ***/ let lod = new Three.LOD(); lod.addLevel(sinkMaxLOD, 200); lod.addLevel(sinkMinLOD, 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); } };