From d79d759091dbab9e4d2249154ff62c17814b012a Mon Sep 17 00:00:00 2001 From: ChenX Date: Mon, 29 Oct 2018 14:49:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=88=86=E7=82=B8=E5=9B=BE?= =?UTF-8?q?=E4=BE=8B=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/umd/cad.js | 2 ++ config/umd/cad.js.map | 1 + src/GeUtils.ts | 60 ++++++++++++++++++++----------------------- src/ViewSrc/index.ts | 58 +++++++++++++++++++++++++++++++++++++++-- src/createBoard.ts | 18 ++++++------- 5 files changed, 96 insertions(+), 43 deletions(-) create mode 100644 config/umd/cad.js create mode 100644 config/umd/cad.js.map diff --git a/config/umd/cad.js b/config/umd/cad.js new file mode 100644 index 0000000..caac570 --- /dev/null +++ b/config/umd/cad.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("THREE")):"function"==typeof define&&define.amd?define(["THREE"],t):"object"==typeof exports?exports.cad=t(require("THREE")):e.cad=t(e.THREE)}(window,function(e){return function(e){var t={};function l(i){if(t[i])return t[i].exports;var q=t[i]={i:i,l:!1,exports:{}};return e[i].call(q.exports,q,q.exports,l),q.l=!0,q.exports}return l.m=e,l.c=t,l.d=function(e,t,i){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(l.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var q in e)l.d(i,q,function(t){return e[t]}.bind(null,q));return i},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="",l(l.s=2)}([function(t,l){t.exports=e},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=l(0),a=l(4);function n(e,t){return(new a.Matrix2).setRotate(t).applyVector(e),e}function o(e,t,l){return void 0===l&&(l=.001),Math.abs(e-t)0)return 0;var t=Math.atan2(e.y,e.x);return t<0&&(t+=2*Math.PI),t},t.angleTo=r,t.getLoocAtUpVec=m,t.createLookAtMat4=function(e){var l=m(e),q=new i.Matrix4;return q.lookAt(t.cZeroVec,e,l),q},t.isParallelTo=function(e,t){return e.clone().cross(t).lengthSq()<1e-9},t.ptToString=function(e,t){return void 0===t&&(t=3),e.toArray().map(function(e){return e.toFixed(t)}).join(",")},t.midPoint=function(e,t){return e.clone().add(t).multiplyScalar(.5)},t.midPoint2=function(e,t){return e.clone().add(t).multiplyScalar(.5)},t.midPtCir=function(e,t){var l=new q.Vector3(1,0,0),i=t.clone().sub(e),a=n(i,-r(l,i)/2);return e.clone().add(a)},t.GetBox=s,t.GetBoxArr=function(e){for(var t=new q.Box3,l=0,i=e;ls&&x<=h?{sp:l.clone().add(n),ep:t}:x>h&&x<=c?{sp:l.clone().add(n),ep:l.clone().add(o)}:{sp:e,ep:l.clone().add(o)}},t.angleAndX=function(e){return e.x?Math.atan(e.y/e.x):Math.PI/2},t.angleTo2Pi=function(e){return(e%=2*Math.PI)<0&&(e+=2*Math.PI),e},t.updateGeometry=function(e,t){e.geometry.dispose(),e.geometry=t,t.verticesNeedUpdate=!0,t.computeBoundingSphere()}},function(e,t,l){"use strict";function i(e){for(var l in e)t.hasOwnProperty(l)||(t[l]=e[l])}Object.defineProperty(t,"__esModule",{value:!0}),i(l(6)),i(l(10)),i(l(1)),i(l(12)),i(l(15)),i(l(18)),i(l(5)),i(l(19)),i(l(20))},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=[[255,0,0,255],[255,0,0,255],[255,255,0,255],[0,255,0,255],[0,255,255,255],[0,0,255,255],[255,0,255,255]],a=function(){function e(){}return e.GetLineMaterial=function(e){if(this.m_LineMaterialMap.has(e))return this.m_LineMaterialMap.get(e);var t=new i.LineBasicMaterial({color:this.GetColor(e)});return this.m_LineMaterialMap.set(e,t),t},e.GetBasicMaterial=function(e){if(this.m_BasicMaterialMap.has(e))return this.m_BasicMaterialMap.get(e);var t=new i.MeshBasicMaterial({color:this.GetColor(e)});return this.m_BasicMaterialMap.set(e,t),t},e.GetColor=function(e){var t=q[e];if(t)return new i.Color(t[0]/255,t[1]/255,t[2]/255)},e.m_LineMaterialMap=new Map,e.m_BasicMaterialMap=new Map,e}();t.ColorMaterial=a},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.el=[1,0,0,1]}return e.prototype.set=function(e,t,l,i){var q=this.el;return q[0]=e,q[1]=l,q[2]=t,q[3]=i,this},e.prototype.applyVector=function(e){var t=e.x,l=e.y,i=this.el;return e.x=i[0]*t+i[2]*l,e.y=i[1]*t+i[3]*l,this},e.prototype.setRotate=function(e){this.el;var t=Math.cos(e),l=Math.sin(e);return this.set(t,-l,l,t),this},e}();t.Matrix2=i},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0);t.boardMaterial=new i.MeshBasicMaterial({color:new i.Color(.8,.8,.8),polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),t.selectMaterial=new i.MeshBasicMaterial({color:new i.Color(.1,.5,.5),polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}),t.edgeMaterial=new i.LineBasicMaterial({linewidth:2,color:new i.Color(0,0,0)})},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=l(2),a=l(7),n=l(3),o=l(1),r=l(9),m=function(){function e(e){var t,l=this;this.m_Camera=new a.CameraUpdate,this.m_bNeedUpdate=!0,this.m_Scene=new i.Scene,this.OnSize=function(e,t){l._Width=e||l.m_DomEl.clientWidth,l._Height=t||l.m_DomEl.clientHeight,l._Width%2==1&&(l._Width-=1),l._Height%2==1&&(l._Height-=1),l.m_Render.setSize(l._Width,l._Height),l.m_Camera.SetSize(l._Width,l._Height)},this.StartRender=function(){requestAnimationFrame(l.StartRender),null!=l.m_Scene&&l.m_bNeedUpdate&&(l.Render(),l.m_bNeedUpdate=!1)},this.m_DomEl=e,this.initRender(e),this.OnSize(),this.StartRender(),this.m_CameraCtrl=new q.CameraControls(this),window.addEventListener("resize",function(){l.OnSize()}),this.m_Render.domElement.addEventListener("mousemove",function(e){var i=q.PointPick(l,e.offsetX,e.offsetY);t&&(t.material=q.boardMaterial),i&&i.material!==n.ColorMaterial.GetBasicMaterial(1)&&(t=i,i.material=q.selectMaterial),l.m_bNeedUpdate=!0})}return e.prototype.initRender=function(e){var t={antialias:!0,precision:"highp",alpha:!0};e instanceof HTMLCanvasElement?(t.canvas=e,this.m_Render=new i.WebGLRenderer(t)):(this.m_Render=new i.WebGLRenderer(t),e.appendChild(this.m_Render.domElement)),this.m_Render.autoClear=!0,this.m_Render.setPixelRatio(window.devicePixelRatio),this.m_Render.physicallyCorrectLights=!0,this.m_Render.setClearColor(16777215,1),this.OnSize()},e.prototype.Render=function(){this.m_Render.render(this.m_Scene,this.m_Camera.Camera)},e.prototype.ScreenToWorld=function(e,t){var l=new r.PlaneExt(t||new i.Vector3(0,0,1)),q=new i.Raycaster;q.setFromCamera({x:e.x/this._Width*2-1,y:-e.y/this._Height*2+1},this.m_Camera.Camera),l.intersectRay(q.ray,e,!0)},e.prototype.WorldToScreen=function(e){var t=.5*this._Width,l=.5*this._Height;e.project(this.m_Camera.Camera),e.x=e.x*t+t,e.y=-e.y*l+l},e.prototype.UpdateLockTarget=function(){var e=this.m_Render.renderLists.get(this.m_Scene,this.m_Camera.Camera),t=o.GetBoxArr(e.opaque.map(function(e){return e.object}));this.m_LookTarget=t?t.getCenter(new i.Vector3):o.cZeroVec},e.prototype.Rotate=function(e){this.m_Camera.Rotate(e,this.m_LookTarget),this.m_bNeedUpdate=!0},e.prototype.Pan=function(e){this.m_Camera.Pan(e),this.m_bNeedUpdate=!0},e.prototype.Zoom=function(e,t){this.m_Camera.Zoom(e,t),this.m_bNeedUpdate=!0},e.prototype.ZoomAll=function(){this.m_Camera.ZoomExtensBox3(o.GetBox(this.m_Scene,!0)),this.m_bNeedUpdate=!0},e.prototype.ViewToTop=function(){this.m_Camera.LookAt(new i.Vector3(0,0,-1)),this.m_bNeedUpdate=!0},e.prototype.ViewToFront=function(){this.m_Camera.LookAt(new i.Vector3(0,1,0)),this.m_bNeedUpdate=!0},e.prototype.ViewToSwiso=function(){this.m_Camera.LookAt(new i.Vector3(1,1,-1)),this.m_bNeedUpdate=!0},e}();t.Viewer=m},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=l(0),a=l(8),n=function(){function e(){this.m_CameraArray=new Map,this.m_ViewHeight=10,this.m_Target=new i.Vector3,this.m_Direction=new i.Vector3(0,0,-1),this.m_Orbit=new a.Orbit,this.m_MinViewHeight=10,this.m_MaxViewHeight=3e4,this.m_CameraArray.set(i.OrthographicCamera,new i.OrthographicCamera(-2,2,2,-2,-1e6,1e6)),this.m_CameraArray.set(i.PerspectiveCamera,new i.PerspectiveCamera(50,1,.01,1e4)),this.m_CurCamera=this.m_CameraArray.get(i.OrthographicCamera),this.m_Orbit.UpdateRoValue(this.m_Direction),this.UpdateUp(),this.Update()}return Object.defineProperty(e.prototype,"Aspect",{get:function(){return this.m_Width/this.m_Height},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"Camera",{get:function(){return this.m_CurCamera},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ViewHeight",{get:function(){return this.m_ViewHeight},set:function(e){this.m_ViewHeight=i.Math.clamp(e,this.m_MinViewHeight,this.m_MaxViewHeight)},enumerable:!0,configurable:!0}),e.prototype.SetSize=function(e,t){this.m_Width=e,this.m_Height=t},e.prototype.Pan=function(e){e.y*=-1,e.multiplyScalar(-this.m_ViewHeight/this.m_Height),e.applyQuaternion(this.Camera.quaternion),this.m_Target.add(e),this.Update()},e.prototype.Rotate=function(e,t){this.m_Orbit.RoX-=.003*e.y,this.m_Orbit.RoZ-=.003*e.x;var l=t.clone().applyMatrix4(this.Camera.matrixWorldInverse);this.m_Orbit.UpdateDirection(this.m_Direction),this.UpdateUp(),this.Update();var i=t.clone().applyMatrix4(this.Camera.matrixWorldInverse);i.sub(l),i.applyMatrix4(this.Camera.matrix),i.sub(this.Camera.position),this.m_Target.add(i),this.Update()},e.prototype.Zoom=function(e,t){if(this.Camera instanceof i.OrthographicCamera)this.ViewHeight*=e,t&&this.m_ViewHeight1?1:-1;l*=this.Camera.position.distanceTo(this.m_Target)/10,this.m_Target.add(this.m_Direction.clone().multiplyScalar(-l))}this.Update()},e.prototype.ZoomExtensBox3=function(e){if(e&&!e.isEmpty()){this.Camera.updateMatrixWorld(!1),e.applyMatrix4(this.Camera.matrixWorldInverse),e.getCenter(this.m_Target),this.m_Target.applyMatrix4(this.Camera.matrix);var t=e.getSize(new q.Vector3),l=t.x/t.y,i=this.Aspect;this.m_ViewHeight=l>i?t.x/i:t.y,this.Update()}},e.prototype.LookAt=function(e){this.m_Orbit.UpdateRoValue(e),this.m_Direction.copy(e),this.UpdateUp(),this.Update()},e.prototype.UpdateUp=function(){a.Orbit.ComputUpDirection(this.m_Direction,this.Camera.up)},e.prototype.Update=function(){if(this.Camera.position.copy(this.m_Target),this.Camera instanceof i.OrthographicCamera)this.Camera.left=this.Aspect*this.m_ViewHeight/-2,this.Camera.right=this.Aspect*this.m_ViewHeight/2,this.Camera.bottom=this.m_ViewHeight/-2,this.Camera.top=this.m_ViewHeight/2,this.Camera.position.sub(this.m_Direction);else{if(!(this.Camera instanceof i.PerspectiveCamera))return;this.Camera.aspect=this.Aspect;var e=this.m_ViewHeight/2/Math.tan(i.Math.degToRad(this.Camera.fov)/2);this.Camera.position.sub(this.m_Direction.clone().multiplyScalar(e))}this.Camera.lookAt(this.m_Target),this.Camera.updateProjectionMatrix(),this.Camera.updateMatrixWorld(!1)},e.prototype.SwitchCamera=function(){this.Camera instanceof i.OrthographicCamera?this.m_CurCamera=this.m_CameraArray.get(i.PerspectiveCamera):this.m_CurCamera=this.m_CameraArray.get(i.OrthographicCamera),this.UpdateUp(),this.Update()},e}();t.CameraUpdate=n},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=function(){function e(){this.m_RoX=0,this.RoZ=0}return Object.defineProperty(e.prototype,"RoX",{get:function(){return this.m_RoX},set:function(e){this.m_RoX=i.Math.clamp(e,-.5*Math.PI,.5*Math.PI)},enumerable:!0,configurable:!0}),e.prototype.UpdateDirection=function(e){var t=e||new i.Vector3;t.z=Math.sin(this.m_RoX);var l=Math.abs(Math.cos(this.m_RoX));return t.x=Math.cos(this.RoZ)*l,t.y=Math.sin(this.RoZ)*l,t},e.prototype.UpdateRoValue=function(e){e.normalize(),this.m_RoX=Math.asin(e.z),e.x<1e-4&&e.y<1e-4?this.RoZ=.5*Math.PI:this.RoZ=Math.atan2(e.y,e.x)},e.ComputUpDirection=function(e,t){var l=t||new i.Vector3;if(e.equals(new i.Vector3(0,0,-1)))l.set(0,1,0);else if(e.equals(new i.Vector3(0,0,1)))l.set(0,-1,0);else{var q=new i.Vector3;q.crossVectors(new i.Vector3(0,0,1),e),l.crossVectors(e,q),l.normalize()}return l},e}();t.Orbit=q},function(e,t,l){"use strict";var i=this&&this.__extends||function(){var e=function(t,l){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var l in t)t.hasOwnProperty(l)&&(e[l]=t[l])})(t,l)};return function(t,l){function i(){this.constructor=t}e(t,l),t.prototype=null===l?Object.create(l):(i.prototype=l.prototype,new i)}}();Object.defineProperty(t,"__esModule",{value:!0});var q=l(0),a=l(0),n=function(e){function t(t,l){return e.call(this,t,l)||this}return i(t,e),t.prototype.intersectLine=function(e,t,l){var i=new a.Vector3,q=t||new a.Vector3,n=e.delta(i),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(e.start)?q.copy(e.start):void 0;var r=-(e.start.dot(this.normal)+this.constant)/o;return l||!(r<0||r>1)?q.copy(n).multiplyScalar(r).add(e.start):void 0},t.prototype.intersectRay=function(e,t,l){var i=new q.Line3(e.origin.clone(),e.origin.clone().add(e.direction));return this.intersectLine(i,t,l)},t}(q.Plane);t.PlaneExt=n},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i,q=l(0),a=l(11),n=l(0);!function(e){e[e.Null=0]="Null",e[e.Pan=1]="Pan",e[e.Rotate=2]="Rotate",e[e.Scale=3]="Scale"}(i=t.CameraControlState||(t.CameraControlState={}));var o=function(){function e(e){var t=this;this.m_TouthTypeList=[i.Rotate,i.Scale,i.Pan],this.m_StartClickPoint=new q.Vector3,this.m_EndClickPoint=new q.Vector3,this.m_DollyStart=new q.Vector2,this.m_DollyEnd=new q.Vector2,this.m_KeyDown=new Map,this.m_MouseDown=new Map,this.m_State=i.Null,this.m_LeftUseRotate=!0,this.onBlur=function(){t.m_KeyDown.clear(),t.m_MouseDown.clear()},this.onTouchStart=function(e){if(t.m_Viewer.UpdateLockTarget(),t.m_StartClickPoint.set(e.touches[0].pageX,e.touches[0].pageY,0),e.touches.length<4){if(2==e.touches.length){var l=e.touches[0].pageX-e.touches[1].pageX,i=e.touches[0].pageY-e.touches[1].pageY,q=Math.sqrt(l*l+i*i);t.m_DollyStart.set(0,q)}t.m_State=t.m_TouthTypeList[e.touches.length-1]}},this.onTouchEnd=function(e){t.m_State=i.Null},this.onTouchMove=function(e){e.preventDefault(),e.stopPropagation(),t.m_EndClickPoint.set(e.touches[0].pageX,e.touches[0].pageY,0);var l=t.m_EndClickPoint.clone().sub(t.m_StartClickPoint);switch(t.m_State){case i.Pan:t.m_Viewer.Pan(l);break;case i.Scale:var q=e.touches[0].pageX-e.touches[1].pageX,a=e.touches[0].pageY-e.touches[1].pageY,n=Math.sqrt(q*q+a*a);t.m_DollyEnd.set(0,n),n>t.m_DollyStart.y?t.m_Viewer.Zoom(.95):t.m_Viewer.Zoom(1.05),t.m_DollyStart.copy(t.m_DollyEnd);break;case i.Rotate:t.m_Viewer.Rotate(l.multiplyScalar(2))}t.m_StartClickPoint.copy(t.m_EndClickPoint),t.m_Viewer.m_bNeedUpdate=!0},this.lastMiddleClickTime=0,this.onMouseDown=function(e){e.preventDefault();var l=e.button;switch(t.m_MouseDown.set(l,!0),t.m_StartClickPoint.set(e.offsetX,e.offsetY,0),l){case a.MouseKey.Left:t.m_LeftUseRotate&&t.beginRotate();break;case a.MouseKey.Middle:var q=Date.now(),n=q-t.lastMiddleClickTime;if(t.lastMiddleClickTime=q,n<350)return void t.m_Viewer.ZoomAll();t.m_KeyDown.get(a.KeyBoard.Control)?t.beginRotate():t.m_State=i.Pan;break;case a.MouseKey.Right:}},this.onMouseUp=function(e){e.preventDefault(),t.m_State=i.Null,t.m_MouseDown.set(e.button,!1)},this.onMouseMove=function(e){e.preventDefault(),t.m_EndClickPoint.set(e.offsetX,e.offsetY,0);var l=t.m_EndClickPoint.clone().sub(t.m_StartClickPoint);switch(t.m_StartClickPoint.copy(t.m_EndClickPoint),(t.m_LeftUseRotate||t.m_KeyDown.get(a.KeyBoard.Control))&&t.m_State==i.Rotate&&t.m_Viewer.Rotate(l),t.m_State){case i.Pan:t.m_Viewer.Pan(l);break;case i.Rotate:case i.Scale:}},this.onMouseWheel=function(e){e.preventDefault(),e.stopPropagation();var l=new q.Vector3(e.offsetX,e.offsetY,0);t.m_Viewer.ScreenToWorld(l,(new n.Vector3).setFromMatrixColumn(t.m_Viewer.m_Camera.Camera.matrixWorld,2)),e.deltaY<0?t.m_Viewer.Zoom(.6,l):e.deltaY>0&&t.m_Viewer.Zoom(1.4,l)},this.onKeyDown=function(e){t.m_KeyDown.set(e.keyCode,!0)},this.onKeyUp=function(e){t.m_KeyDown.set(e.keyCode,!1)},this.m_Viewer=e,this.m_domElement=e.m_Render.domElement.parentElement,this.RegisterEvent()}return e.prototype.RegisterEvent=function(){this.m_domElement&&(this.m_domElement.addEventListener("mousedown",this.onMouseDown,!1),this.m_domElement.addEventListener("mousemove",this.onMouseMove,!1),this.m_domElement.addEventListener("mouseup",this.onMouseUp,!1),window.addEventListener("keydown",this.onKeyDown,!1),window.addEventListener("keyup",this.onKeyUp,!1),this.m_domElement.addEventListener("wheel",this.onMouseWheel,!1),this.m_domElement.addEventListener("touchstart",this.onTouchStart,!1),this.m_domElement.addEventListener("touchend",this.onTouchEnd,!1),this.m_domElement.addEventListener("touchmove",this.onTouchMove,!1),window.addEventListener("blur",this.onBlur,!1))},e.prototype.beginRotate=function(){this.m_State=i.Rotate,this.m_Viewer.UpdateLockTarget()},e}();t.CameraControls=o},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e[e.Left=0]="Left",e[e.Middle=1]="Middle",e[e.Right=2]="Right"}(t.MouseKey||(t.MouseKey={})),function(e){e[e.Digit1=49]="Digit1",e[e.Digit2=50]="Digit2",e[e.Digit3=51]="Digit3",e[e.Digit4=52]="Digit4",e[e.Digit5=53]="Digit5",e[e.Digit6=54]="Digit6",e[e.Digit7=55]="Digit7",e[e.Digit8=56]="Digit8",e[e.Digit9=57]="Digit9",e[e.Digit0=58]="Digit0",e[e.KeyA=65]="KeyA",e[e.KeyB=66]="KeyB",e[e.KeyC=67]="KeyC",e[e.KeyD=68]="KeyD",e[e.KeyE=69]="KeyE",e[e.KeyF=70]="KeyF",e[e.KeyG=71]="KeyG",e[e.KeyH=72]="KeyH",e[e.KeyI=73]="KeyI",e[e.KeyJ=74]="KeyJ",e[e.KeyK=75]="KeyK",e[e.KeyL=76]="KeyL",e[e.KeyM=77]="KeyM",e[e.KeyN=78]="KeyN",e[e.KeyO=79]="KeyO",e[e.KeyP=80]="KeyP",e[e.KeyQ=81]="KeyQ",e[e.KeyR=82]="KeyR",e[e.KeyS=83]="KeyS",e[e.KeyT=84]="KeyT",e[e.KeyU=85]="KeyU",e[e.KeyV=86]="KeyV",e[e.KeyW=87]="KeyW",e[e.KeyX=88]="KeyX",e[e.KeyY=89]="KeyY",e[e.KeyZ=90]="KeyZ",e[e.Comma=188]="Comma",e[e.CommaChrome=229]="CommaChrome",e[e.Period=190]="Period",e[e.Semicolon=186]="Semicolon",e[e.Quote=222]="Quote",e[e.BracketLeft=219]="BracketLeft",e[e.BracketRight=220]="BracketRight",e[e.Backquote=192]="Backquote",e[e.Backslash=220]="Backslash",e[e.Minus=189]="Minus",e[e.Equal=187]="Equal",e[e.IntlRo=193]="IntlRo",e[e.IntlYen=255]="IntlYen",e[e.Alt=18]="Alt",e[e.CapsLock=20]="CapsLock",e[e.Control=17]="Control",e[e.OSLeft=91]="OSLeft",e[e.OSRight=92]="OSRight",e[e.Shift=16]="Shift",e[e.ContextMenu=93]="ContextMenu",e[e.Enter=13]="Enter",e[e.Space=32]="Space",e[e.Backspace=8]="Backspace",e[e.Tab=9]="Tab",e[e.Delete=46]="Delete",e[e.End=35]="End",e[e.Home=36]="Home",e[e.Insert=45]="Insert",e[e.PageDown=34]="PageDown",e[e.PageUp=33]="PageUp",e[e.ArrowDown=40]="ArrowDown",e[e.ArrowLeft=37]="ArrowLeft",e[e.ArrowRight=39]="ArrowRight",e[e.ArrowUp=38]="ArrowUp",e[e.Escape=27]="Escape",e[e.PrintScreen=44]="PrintScreen",e[e.ScrollLock=145]="ScrollLock",e[e.Pause=19]="Pause",e[e.F1=112]="F1",e[e.F2=113]="F2",e[e.F3=114]="F3",e[e.F5=116]="F5",e[e.F6=117]="F6",e[e.F7=118]="F7",e[e.F8=119]="F8",e[e.F9=120]="F9",e[e.F10=121]="F10",e[e.F11=122]="F11",e[e.F12=123]="F12",e[e.NumLock=114]="NumLock",e[e.Numpad0=96]="Numpad0",e[e.Numpad1=97]="Numpad1",e[e.Numpad2=98]="Numpad2",e[e.Numpad3=99]="Numpad3",e[e.Numpad4=100]="Numpad4",e[e.Numpad5=101]="Numpad5",e[e.Numpad6=102]="Numpad6",e[e.Numpad7=103]="Numpad7",e[e.Numpad8=104]="Numpad8",e[e.Numpad9=105]="Numpad9",e[e.NumpadAdd=107]="NumpadAdd",e[e.NumpadDivide=111]="NumpadDivide",e[e.NumpadEqual=12]="NumpadEqual",e[e.NumpadMultiply=106]="NumpadMultiply",e[e.NumpadSubtract=109]="NumpadSubtract",e[e.NumpadDot=110]="NumpadDot",e[e.NumpadDot1=190]="NumpadDot1"}(t.KeyBoard||(t.KeyBoard={}))},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=l(0),a=l(3),n=l(1),o=l(5),r=l(13),m=l(14),s=function(){return function(e,t,l){this.m_StartPoint=e.clone(),this.m_EndPoint=t.clone();var i=t.clone().sub(e),q=i.length(),a=i.angle();this.m_Radius=q/Math.sin(2*Math.atan(l))/2,Math.atan(l);var o=l*q/2,r=this.m_Radius-o;a+=.5*Math.PI,this.m_Center=e.clone().add(t),this.m_Center.multiplyScalar(.5),n.polar(this.m_Center,a,r),this.m_StartAn=e.clone().sub(this.m_Center).angle(),this.m_EndAn=t.clone().sub(this.m_Center).angle(),l<0&&(this.m_StartAn-=Math.PI,this.m_EndAn-=Math.PI)}}();function h(e,t,l){var i=l||new q.Shape;if(0===e.length)return i;var a=e[0];i.moveTo(a.x,a.y);for(var n=0;n0}function _(e){var t=new i.EdgesGeometry(e,1);return new q.LineSegments(t,o.edgeMaterial)}t.Arc2d=s,t.createPath=h,t.getVec=c,t.createBoard=x,t.createTemplateBoard=function(e){for(var t=[],l=[],i=0,q=e;i0?this.calculateProperties():this.normal=this.w=void 0}return e.prototype.calculateProperties=function(){var e=this.vertices[0],t=this.vertices[1],l=this.vertices[2];return this.normal=t.clone().subtract(e).cross(l.clone().subtract(e)).normalize(),this.w=this.normal.clone().dot(e),this},e.prototype.clone=function(){var t,l,i=new e;for(t=0,l=this.vertices.length;t=0;e--)t.push(this.vertices[e]);return this.vertices=t,this},e.prototype.classifyVertex=function(e){var t=this.normal.dot(e)-this.w;return t<-1e-5?2:t>1e-5?1:0},e.prototype.classifySide=function(e){var t,l,i,q=0,a=0,n=e.vertices.length;for(t=0;t0&&0===a?1:0===q&&a>0?2:0===q&&0===a?0:3},e.prototype.splitPolygon=function(t,l,i,q,a){var n=this.classifySide(t);if(0===n)(this.normal.dot(t.normal)>0?l:i).push(t);else if(1===n)q.push(t);else if(2===n)a.push(t);else{var o,r=void 0,m=void 0,s=void 0,h=void 0,c=void 0,x=void 0,u=void 0,_=void 0,p=[],d=[];for(r=0,o=t.vertices.length;r=3&&q.push(new e(p).calculateProperties()),d.length>=3&&a.push(new e(d).calculateProperties())}},e}();t.Polygon=a;var n=function(){function e(e,t,l,q,a){this.x=e,this.y=t,this.z=l,this.normal=q||new i.Vector3,this.uv=a||new i.Vector2}return e.prototype.clone=function(){return new e(this.x,this.y,this.z,this.normal.clone(),this.uv.clone())},e.prototype.add=function(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this},e.prototype.subtract=function(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this},e.prototype.multiplyScalar=function(e){return this.x*=e,this.y*=e,this.z*=e,this},e.prototype.cross=function(e){var t=this.x,l=this.y,i=this.z;return this.x=l*e.z-i*e.y,this.y=i*e.x-t*e.z,this.z=t*e.y-l*e.x,this},e.prototype.normalize=function(){var e=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);return this.x/=e,this.y/=e,this.z/=e,this},e.prototype.dot=function(e){return this.x*e.x+this.y*e.y+this.z*e.z},e.prototype.lerp=function(e,t){return this.add(e.clone().subtract(this).multiplyScalar(t)),this.normal.add(e.normal.clone().sub(this.normal).multiplyScalar(t)),this.uv.add(e.uv.clone().sub(this.uv).multiplyScalar(t)),this},e.prototype.interpolate=function(e,t){return this.clone().lerp(e,t)},e.prototype.applyMatrix4=function(e){var t=this.x,l=this.y,i=this.z,q=e.elements;return this.x=q[0]*t+q[4]*l+q[8]*i+q[12],this.y=q[1]*t+q[5]*l+q[9]*i+q[13],this.z=q[2]*t+q[6]*l+q[10]*i+q[14],this},e}();t.Vertex=n;var o=function(){function e(t){var l,i,q=[],a=[];if(this.polygons=[],this.front=this.back=void 0,t instanceof Array&&0!==t.length){for(this.divider=t[0].clone(),l=0,i=t.length;l0&&(this.front=new e(q)),a.length>0&&(this.back=new e(a))}}return e.prototype.isConvex=function(e){var t,l;for(t=0;t0&&(this.front||(this.front=new e),this.front.build(q)),a.length>0&&(this.back||(this.back=new e),this.back.build(a))},e.prototype.allPolygons=function(){var e=this.polygons.slice();return this.front&&(e=e.concat(this.front.allPolygons())),this.back&&(e=e.concat(this.back.allPolygons())),e},e.prototype.clone=function(){var t=new e;return t.divider=this.divider.clone(),t.polygons=this.polygons.map(function(e){return e.clone()}),t.front=this.front&&this.front.clone(),t.back=this.back&&this.back.clone(),t},e.prototype.invert=function(){var e,t,l;for(e=0,t=this.polygons.length;e":{x_min:18.0625,x_max:774,ha:792,o:"m 774 376 l 18 40 l 18 149 l 631 421 l 18 692 l 18 799 l 774 465 l 774 376 "},v:{x_min:0,x_max:675.15625,ha:761,o:"m 675 738 l 404 0 l 272 0 l 0 738 l 133 737 l 340 147 l 541 737 l 675 738 "},"τ":{x_min:.28125,x_max:644.5,ha:703,o:"m 644 628 l 382 628 l 382 179 q 388 120 382 137 q 436 91 401 91 q 474 94 447 91 q 504 97 501 97 l 504 0 q 454 -9 482 -5 q 401 -14 426 -14 q 278 67 308 -14 q 260 233 260 118 l 260 628 l 0 628 l 0 739 l 644 739 l 644 628 "},"ξ":{x_min:0,x_max:624.9375,ha:699,o:"m 624 -37 q 608 -153 624 -96 q 563 -278 593 -211 l 454 -278 q 491 -183 486 -200 q 511 -83 511 -126 q 484 -23 511 -44 q 370 1 452 1 q 323 0 354 1 q 283 -1 293 -1 q 84 76 169 -1 q 0 266 0 154 q 56 431 0 358 q 197 538 108 498 q 94 613 134 562 q 54 730 54 665 q 77 823 54 780 q 143 901 101 867 l 27 901 l 27 1012 l 576 1012 l 576 901 l 380 901 q 244 863 303 901 q 178 745 178 820 q 312 600 178 636 q 532 582 380 582 l 532 479 q 276 455 361 479 q 118 281 118 410 q 165 173 118 217 q 274 120 208 133 q 494 101 384 110 q 624 -37 624 76 "},"&":{x_min:-3,x_max:894.25,ha:992,o:"m 894 0 l 725 0 l 624 123 q 471 0 553 40 q 306 -41 390 -41 q 168 -7 231 -41 q 62 92 105 26 q 14 187 31 139 q -3 276 -3 235 q 55 433 -3 358 q 248 581 114 508 q 170 689 196 640 q 137 817 137 751 q 214 985 137 922 q 384 1041 284 1041 q 548 988 483 1041 q 622 824 622 928 q 563 666 622 739 q 431 556 516 608 l 621 326 q 649 407 639 361 q 663 493 653 426 l 781 493 q 703 229 781 352 l 894 0 m 504 818 q 468 908 504 877 q 384 940 433 940 q 293 907 331 940 q 255 818 255 875 q 289 714 255 767 q 363 628 313 678 q 477 729 446 682 q 504 818 504 771 m 556 209 l 314 499 q 179 395 223 449 q 135 283 135 341 q 146 222 135 253 q 183 158 158 192 q 333 80 241 80 q 556 209 448 80 "},"Λ":{x_min:0,x_max:862.5,ha:942,o:"m 862 0 l 719 0 l 426 847 l 143 0 l 0 0 l 356 1013 l 501 1013 l 862 0 "},I:{x_min:41,x_max:180,ha:293,o:"m 180 0 l 41 0 l 41 1013 l 180 1013 l 180 0 "},G:{x_min:0,x_max:921,ha:1011,o:"m 921 0 l 832 0 l 801 136 q 655 15 741 58 q 470 -28 568 -28 q 126 133 259 -28 q 0 499 0 284 q 125 881 0 731 q 486 1043 259 1043 q 763 957 647 1043 q 905 709 890 864 l 772 709 q 668 866 747 807 q 486 926 589 926 q 228 795 322 926 q 142 507 142 677 q 228 224 142 342 q 483 94 323 94 q 712 195 625 94 q 796 435 796 291 l 477 435 l 477 549 l 921 549 l 921 0 "},"ΰ":{x_min:0,x_max:617,ha:725,o:"m 524 800 l 414 800 l 414 925 l 524 925 l 524 800 m 183 800 l 73 800 l 73 925 l 183 925 l 183 800 m 617 352 q 540 93 617 199 q 308 -24 455 -24 q 76 93 161 -24 q 0 352 0 199 l 0 738 l 126 738 l 126 354 q 169 185 126 257 q 312 98 220 98 q 451 185 402 98 q 492 354 492 257 l 492 738 l 617 738 l 617 352 m 489 1040 l 300 819 l 216 819 l 351 1040 l 489 1040 "},"`":{x_min:0,x_max:138.890625,ha:236,o:"m 138 699 l 0 699 l 0 861 q 36 974 0 929 q 138 1041 72 1020 l 138 977 q 82 931 95 969 q 69 839 69 893 l 138 839 l 138 699 "},"·":{x_min:0,x_max:142,ha:239,o:"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 "},"Υ":{x_min:.328125,x_max:819.515625,ha:889,o:"m 819 1013 l 482 416 l 482 0 l 342 0 l 342 416 l 0 1013 l 140 1013 l 411 533 l 679 1013 l 819 1013 "},r:{x_min:0,x_max:355.5625,ha:432,o:"m 355 621 l 343 621 q 179 569 236 621 q 122 411 122 518 l 122 0 l 0 0 l 0 737 l 117 737 l 117 604 q 204 719 146 686 q 355 753 262 753 l 355 621 "},x:{x_min:0,x_max:675,ha:764,o:"m 675 0 l 525 0 l 331 286 l 144 0 l 0 0 l 256 379 l 12 738 l 157 737 l 336 473 l 516 738 l 661 738 l 412 380 l 675 0 "},"μ":{x_min:0,x_max:696.609375,ha:747,o:"m 696 -4 q 628 -14 657 -14 q 498 97 513 -14 q 422 8 470 41 q 313 -24 374 -24 q 207 3 258 -24 q 120 80 157 31 l 120 -278 l 0 -278 l 0 738 l 124 738 l 124 343 q 165 172 124 246 q 308 82 216 82 q 451 177 402 82 q 492 358 492 254 l 492 738 l 616 738 l 616 214 q 623 136 616 160 q 673 92 636 92 q 696 95 684 92 l 696 -4 "},h:{x_min:0,x_max:615,ha:724,o:"m 615 472 l 615 0 l 490 0 l 490 454 q 456 590 490 535 q 338 654 416 654 q 186 588 251 654 q 122 436 122 522 l 122 0 l 0 0 l 0 1013 l 122 1013 l 122 633 q 218 727 149 694 q 362 760 287 760 q 552 676 484 760 q 615 472 615 600 "},".":{x_min:0,x_max:142,ha:239,o:"m 142 0 l 0 0 l 0 151 l 142 151 l 142 0 "},"φ":{x_min:-2,x_max:878,ha:974,o:"m 496 -279 l 378 -279 l 378 -17 q 101 88 204 -17 q -2 367 -2 194 q 68 626 -2 510 q 283 758 151 758 l 283 646 q 167 537 209 626 q 133 373 133 462 q 192 177 133 254 q 378 93 259 93 l 378 758 q 445 764 426 763 q 476 765 464 765 q 765 659 653 765 q 878 377 878 553 q 771 96 878 209 q 496 -17 665 -17 l 496 -279 m 496 93 l 514 93 q 687 183 623 93 q 746 380 746 265 q 691 569 746 491 q 522 658 629 658 l 496 656 l 496 93 "},";":{x_min:0,x_max:142,ha:239,o:"m 142 585 l 0 585 l 0 738 l 142 738 l 142 585 m 142 -12 q 105 -132 142 -82 q 0 -206 68 -182 l 0 -138 q 58 -82 43 -123 q 68 0 68 -56 l 0 0 l 0 151 l 142 151 l 142 -12 "},f:{x_min:0,x_max:378,ha:472,o:"m 378 638 l 246 638 l 246 0 l 121 0 l 121 638 l 0 638 l 0 738 l 121 738 q 137 935 121 887 q 290 1028 171 1028 q 320 1027 305 1028 q 378 1021 334 1026 l 378 908 q 323 918 346 918 q 257 870 273 918 q 246 780 246 840 l 246 738 l 378 738 l 378 638 "},"“":{x_min:1,x_max:348.21875,ha:454,o:"m 140 670 l 1 670 l 1 830 q 37 943 1 897 q 140 1011 74 990 l 140 947 q 82 900 97 940 q 68 810 68 861 l 140 810 l 140 670 m 348 670 l 209 670 l 209 830 q 245 943 209 897 q 348 1011 282 990 l 348 947 q 290 900 305 940 q 276 810 276 861 l 348 810 l 348 670 "},A:{x_min:.03125,x_max:906.953125,ha:1008,o:"m 906 0 l 756 0 l 648 303 l 251 303 l 142 0 l 0 0 l 376 1013 l 529 1013 l 906 0 m 610 421 l 452 867 l 293 421 l 610 421 "},"‘":{x_min:1,x_max:139.890625,ha:236,o:"m 139 670 l 1 670 l 1 830 q 37 943 1 897 q 139 1011 74 990 l 139 947 q 82 900 97 940 q 68 810 68 861 l 139 810 l 139 670 "},"ϊ":{x_min:-70,x_max:283,ha:361,o:"m 283 800 l 173 800 l 173 925 l 283 925 l 283 800 m 40 800 l -70 800 l -70 925 l 40 925 l 40 800 m 283 3 q 232 -10 257 -5 q 181 -15 206 -15 q 84 26 118 -15 q 41 200 41 79 l 41 737 l 166 737 l 167 215 q 171 141 167 157 q 225 101 182 101 q 247 103 238 101 q 283 112 256 104 l 283 3 "},"π":{x_min:-.21875,x_max:773.21875,ha:857,o:"m 773 -7 l 707 -11 q 575 40 607 -11 q 552 174 552 77 l 552 226 l 552 626 l 222 626 l 222 0 l 97 0 l 97 626 l 0 626 l 0 737 l 773 737 l 773 626 l 676 626 l 676 171 q 695 103 676 117 q 773 90 714 90 l 773 -7 "},"ά":{x_min:0,x_max:765.5625,ha:809,o:"m 765 -4 q 698 -14 726 -14 q 564 97 586 -14 q 466 7 525 40 q 337 -26 407 -26 q 88 98 186 -26 q 0 369 0 212 q 88 637 0 525 q 337 760 184 760 q 465 727 407 760 q 563 637 524 695 l 563 738 l 685 738 l 685 222 q 693 141 685 168 q 748 94 708 94 q 765 95 760 94 l 765 -4 m 584 371 q 531 562 584 485 q 360 653 470 653 q 192 566 254 653 q 135 379 135 489 q 186 181 135 261 q 358 84 247 84 q 528 176 465 84 q 584 371 584 260 m 604 1040 l 415 819 l 332 819 l 466 1040 l 604 1040 "},O:{x_min:0,x_max:958,ha:1057,o:"m 485 1041 q 834 882 702 1041 q 958 512 958 734 q 834 136 958 287 q 481 -26 702 -26 q 126 130 261 -26 q 0 504 0 279 q 127 880 0 728 q 485 1041 263 1041 m 480 98 q 731 225 638 98 q 815 504 815 340 q 733 783 815 669 q 480 912 640 912 q 226 784 321 912 q 142 504 142 670 q 226 224 142 339 q 480 98 319 98 "},n:{x_min:0,x_max:615,ha:724,o:"m 615 463 l 615 0 l 490 0 l 490 454 q 453 592 490 537 q 331 656 410 656 q 178 585 240 656 q 117 421 117 514 l 117 0 l 0 0 l 0 738 l 117 738 l 117 630 q 218 728 150 693 q 359 764 286 764 q 552 675 484 764 q 615 463 615 593 "},l:{x_min:41,x_max:166,ha:279,o:"m 166 0 l 41 0 l 41 1013 l 166 1013 l 166 0 "},"¤":{x_min:40.09375,x_max:728.796875,ha:825,o:"m 728 304 l 649 224 l 512 363 q 383 331 458 331 q 256 363 310 331 l 119 224 l 40 304 l 177 441 q 150 553 150 493 q 184 673 150 621 l 40 818 l 119 898 l 267 749 q 321 766 291 759 q 384 773 351 773 q 447 766 417 773 q 501 749 477 759 l 649 898 l 728 818 l 585 675 q 612 618 604 648 q 621 553 621 587 q 591 441 621 491 l 728 304 m 384 682 q 280 643 318 682 q 243 551 243 604 q 279 461 243 499 q 383 423 316 423 q 487 461 449 423 q 525 553 525 500 q 490 641 525 605 q 384 682 451 682 "},"κ":{x_min:0,x_max:632.328125,ha:679,o:"m 632 0 l 482 0 l 225 384 l 124 288 l 124 0 l 0 0 l 0 738 l 124 738 l 124 446 l 433 738 l 596 738 l 312 466 l 632 0 "},p:{x_min:0,x_max:685,ha:786,o:"m 685 364 q 598 96 685 205 q 350 -23 504 -23 q 121 89 205 -23 l 121 -278 l 0 -278 l 0 738 l 121 738 l 121 633 q 220 726 159 691 q 351 761 280 761 q 598 636 504 761 q 685 364 685 522 m 557 371 q 501 560 557 481 q 330 651 437 651 q 162 559 223 651 q 108 366 108 479 q 162 177 108 254 q 333 87 224 87 q 502 178 441 87 q 557 371 557 258 "},"‡":{x_min:0,x_max:777,ha:835,o:"m 458 238 l 458 0 l 319 0 l 319 238 l 0 238 l 0 360 l 319 360 l 319 681 l 0 683 l 0 804 l 319 804 l 319 1015 l 458 1013 l 458 804 l 777 804 l 777 683 l 458 683 l 458 360 l 777 360 l 777 238 l 458 238 "},"ψ":{x_min:0,x_max:808,ha:907,o:"m 465 -278 l 341 -278 l 341 -15 q 87 102 180 -15 q 0 378 0 210 l 0 739 l 133 739 l 133 379 q 182 195 133 275 q 341 98 242 98 l 341 922 l 465 922 l 465 98 q 623 195 563 98 q 675 382 675 278 l 675 742 l 808 742 l 808 381 q 720 104 808 213 q 466 -13 627 -13 l 465 -278 "},"η":{x_min:.78125,x_max:697,ha:810,o:"m 697 -278 l 572 -278 l 572 454 q 540 587 572 536 q 425 650 501 650 q 271 579 337 650 q 206 420 206 509 l 206 0 l 81 0 l 81 489 q 73 588 81 562 q 0 644 56 644 l 0 741 q 68 755 38 755 q 158 720 124 755 q 200 630 193 686 q 297 726 234 692 q 434 761 359 761 q 620 692 544 761 q 697 516 697 624 l 697 -278 "}},cssFontWeight:"normal",ascender:1189,underlinePosition:-100,cssFontStyle:"normal",boundingBox:{yMin:-334,xMin:-111,yMax:1189,xMax:1672},resolution:1e3,original_font_information:{postscript_name:"Helvetiker-Regular",version_string:"Version 1.00 2004 initial release",vendor_url:"http://www.magenta.gr/",full_font_name:"Helvetiker",font_family_name:"Helvetiker",copyright:"Copyright (c) Μagenta ltd, 2004",description:"",trademark:"",designer:"",designer_url:"",unique_font_identifier:"Μagenta ltd:Helvetiker:22-10-104",license_url:"http://www.ellak.gr/fonts/MgOpen/license.html",license_description:'Copyright (c) 2004 by MAGENTA Ltd. All Rights Reserved.\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: \r\n\r\nThe above copyright and this permission notice shall be included in all copies of one or more of the Font Software typefaces.\r\n\r\nThe Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word "MgOpen", or if the modifications are accepted for inclusion in the Font Software itself by the each appointed Administrator.\r\n\r\nThis License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "MgOpen" name.\r\n\r\nThe Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. \r\n\r\nTHE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL MAGENTA OR PERSONS OR BODIES IN CHARGE OF ADMINISTRATION AND MAINTENANCE OF THE FONT SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.',manufacturer_name:"Μagenta ltd",font_sub_family_name:"Regular"},descender:-334,familyName:"Helvetiker",lineHeight:1522,underlineThickness:50}},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0),q=l(2);t.DrawDimension=function(e){var t=q.GetBoxArr(e),l=t.getSize(new i.Vector3),a=new i.Matrix4;a.makeBasis(new i.Vector3(-1,0,0),new i.Vector3(0,-1,0),new i.Vector3(0,0,1)),a.setPosition(t.min.clone().add(new i.Vector3(l.x,-30)));var n=new q.Dimension(l.x,45,!0);n.applyMatrix(a);var o=new q.Dimension(l.z,45);a.makeBasis(new i.Vector3(0,0,-1),new i.Vector3(1,0,0),new i.Vector3(0,-1,0)),a.setPosition(t.max.clone().add(new i.Vector3(30,-l.y))),o.applyMatrix(a);var r=new q.Dimension(l.y,45,!0,!0);return a.makeBasis(new i.Vector3(0,1,0),new i.Vector3(-1,0,0),new i.Vector3(0,0,1)),a.setPosition(t.max.clone().add(new i.Vector3(30,-l.y))),r.applyMatrix(a),[n,r,o]}},function(e,t,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=l(0);t.PointPick=function(e,t,l){var q=new i.Raycaster;q.setFromCamera({x:t/e._Width*2-1,y:-l/e._Height*2+1},e.m_Camera.Camera),q.ray.origin.set(t/e._Width*2-1,-l/e._Height*2+1,-1).unproject(e.m_Camera.Camera);var a=1/0,n=void 0;return e.m_Scene.children.forEach(function(e){if(e instanceof i.Mesh){var t=[];e.raycast(q,t);for(var l=0,o=t;l(v1: T, v2: T)\r\n{\r\n return v1.distanceToSquared(v2) < 1e-8;\r\n}\r\n\r\nexport function fixAngle(an: number, fixAngle: number, fuzz: number = 0.1)\r\n{\r\n if (an < 0)\r\n an += Math.PI * 2;\r\n an += fuzz;\r\n let rem = an % fixAngle;\r\n if (rem < fuzz * 2)\r\n {\r\n an -= rem;\r\n }\r\n else\r\n {\r\n an -= fuzz;\r\n }\r\n return an;\r\n}\r\n\r\n/**\r\n * 按照极坐标的方式移动一个点\r\n * \r\n * @export\r\n * @template \r\n * @param {T} v 向量(2d,3d)\r\n * @param {number} an 角度\r\n * @param {number} dis 距离\r\n * @returns {T} \r\n */\r\nexport function polar(v: T, an: number, dis: number): T\r\n{\r\n v.x += Math.cos(an) * dis;\r\n v.y += Math.sin(an) * dis;\r\n return v;\r\n}\r\n\r\nexport function angle(v: Vector3 | Vector2)\r\n{\r\n if (equaln(v.y, 0) && v.x > 0)\r\n return 0;\r\n let angle = Math.atan2(v.y, v.x);\r\n if (angle < 0) angle += Math.PI * 2;\r\n return angle;\r\n}\r\n\r\n/**\r\n * 求两个向量的夹角,顺时针为负,逆时针为正\r\n * \r\n * @param {THREE.Vector3} v1 \r\n * @param {THREE.Vector3} v2 \r\n * @param {THREE.Vector3} [ref] 参考向量,如果为世界坐标系则为0,0,1\r\n * @returns \r\n */\r\nexport function angleTo(v1: THREE.Vector3, v2: THREE.Vector3, ref: THREE.Vector3 = new THREE.Vector3(0, 0, 1))\r\n{\r\n if (!ref.equals(new Vector3(0, 0, 1)))\r\n {\r\n //任意轴坐标系. 使用相机的构造矩阵.\r\n ref.multiplyScalar(-1);\r\n let up = getLoocAtUpVec(ref);\r\n let refOcs = new THREE.Matrix4();\r\n refOcs.lookAt(cZeroVec, ref, up);\r\n let refOcsInv = new THREE.Matrix4().getInverse(refOcs);\r\n v1.applyMatrix4(refOcsInv);\r\n v2.applyMatrix4(refOcsInv);\r\n v1.z = 0;\r\n v2.z = 0;\r\n }\r\n if (v1.equals(cZeroVec) || v2.equals(cZeroVec))\r\n return 0;\r\n let cv = new Vector3().crossVectors(v1, v2).normalize();\r\n return cv.z === 0 ? v1.angleTo(v2) : v1.angleTo(v2) * cv.z;\r\n}\r\n\r\nexport function getLoocAtUpVec(dir: THREE.Vector3): THREE.Vector3\r\n{\r\n if (dir.equals(cZeroVec))\r\n {\r\n throw (\"zero vector\")\r\n }\r\n let norm = dir.clone().normalize();\r\n if (norm.equals(cZAxis))\r\n {\r\n return new THREE.Vector3(0, 1, 0);\r\n }\r\n else if (norm.equals(cZAxis.clone().negate()))\r\n {\r\n return new THREE.Vector3(0, -1, 0);\r\n }\r\n else\r\n {\r\n let xv: THREE.Vector3 = new THREE.Vector3();\r\n xv.crossVectors(cZAxis, norm);\r\n\r\n let up = new THREE.Vector3();\r\n up.crossVectors(norm, xv);\r\n return up;\r\n }\r\n}\r\n\r\nexport function createLookAtMat4(dir: THREE.Vector3): THREE.Matrix4\r\n{\r\n let up = getLoocAtUpVec(dir);\r\n let mat = new THREE.Matrix4();\r\n mat.lookAt(cZeroVec, dir, up);\r\n return mat;\r\n}\r\n\r\nexport function isParallelTo(v1: THREE.Vector3, v2: THREE.Vector3)\r\n{\r\n return v1.clone().cross(v2).lengthSq() < 1e-9;\r\n}\r\n\r\nexport function ptToString(v: THREE.Vector3, fractionDigits: number = 3): string\r\n{\r\n return v.toArray().map(o =>\r\n {\r\n return o.toFixed(fractionDigits)\r\n }).join(\",\")\r\n}\r\n\r\nexport function midPoint(v1: THREE.Vector3, v2: THREE.Vector3): THREE.Vector3\r\n{\r\n return v1.clone().add(v2).multiplyScalar(0.5);\r\n}\r\nexport function midPoint2(v1: THREE.Vector2, v2: THREE.Vector2): THREE.Vector2\r\n{\r\n return v1.clone().add(v2).multiplyScalar(0.5);\r\n}\r\n\r\nexport function midPtCir(v1: THREE.Vector3, v2: THREE.Vector3)\r\n{\r\n let baseline = new Vector3(1, 0, 0);\r\n let outLine = v2.clone().sub(v1);\r\n let ang = angleTo(baseline, outLine) / 2;\r\n let midLine = rotatePoint(outLine, -ang);\r\n return v1.clone().add(midLine);\r\n}\r\n\r\n/**\r\n * 获得Three对象的包围盒.\r\n * @param obj \r\n * @param [updateMatrix] 是否应该更新对象矩阵\r\n * @returns box \r\n */\r\nexport function GetBox(obj: THREE.Object3D, updateMatrix?: boolean): THREE.Box3\r\n{\r\n let box = new Box3();\r\n if (updateMatrix) obj.updateMatrixWorld(false);\r\n if (!obj.visible) return box;\r\n\r\n obj.traverse(o =>\r\n {\r\n //因为实体Erase时,实体仍然保存在Scene中.\r\n if (o.visible === false)\r\n return;\r\n\r\n //@ts-ignore\r\n let geo = o.geometry as BufferGeometry;\r\n if (geo)\r\n {\r\n if (!geo.boundingBox)\r\n geo.computeBoundingBox();\r\n box.union(geo.boundingBox.clone().applyMatrix4(o.matrixWorld));\r\n }\r\n });\r\n\r\n return box;\r\n}\r\n\r\nexport function GetBoxArr(arr: Array): THREE.Box3\r\n{\r\n let box = new Box3();\r\n for (let o of arr)\r\n {\r\n let b = GetBox(o);\r\n if (!b.isEmpty())\r\n box.union(b);\r\n }\r\n return box;\r\n}\r\n\r\nexport function MoveMatrix(v: THREE.Vector3): THREE.Matrix4\r\n{\r\n let mat = new THREE.Matrix4();\r\n mat.makeTranslation(v.x, v.y, v.z);\r\n return mat;\r\n}\r\n\r\nexport function getProjectDist(v1: Vector3, v2: Vector3)\r\n{\r\n let ang = v1.angleTo(v2);\r\n let dist = v1.length();\r\n return {\r\n h: dist * Math.cos(ang),\r\n v: dist * Math.sin(ang)\r\n }\r\n}\r\n//获得输入点在2线组成的4个区间的位置\r\nexport function getPtPostion(sp: Vector3, ep: Vector3, c: Vector3, inPt: Vector3)\r\n{\r\n let l1 = sp.clone().sub(c);\r\n let l2 = ep.clone().sub(c);\r\n let l3 = l1.clone().negate();\r\n let l4 = l2.clone().negate();\r\n let inputLine = inPt.clone().sub(c);\r\n let ang1 = angleTo(l1, l2);\r\n let ang2 = Math.PI;\r\n let ang3 = ang2 + Math.abs(ang1);\r\n let inputAng = angleTo(l1, inputLine);\r\n if (ang1 * inputAng < 0)\r\n {\r\n inputAng = (Math.PI * 2 - Math.abs(inputAng));\r\n }\r\n ang1 = Math.abs(ang1);\r\n inputAng = Math.abs(inputAng);\r\n if (inputAng <= ang1)\r\n {\r\n return { sp, ep };\r\n } else if (inputAng > ang1 && inputAng <= ang2)\r\n {\r\n return { sp: c.clone().add(l3), ep }\r\n } else if (inputAng > ang2 && inputAng <= ang3)\r\n {\r\n return { sp: c.clone().add(l3), ep: c.clone().add(l4) }\r\n } else\r\n {\r\n return { sp, ep: c.clone().add(l4) };\r\n }\r\n}\r\nexport function angleAndX(v: Vector3 | Vector2)\r\n{\r\n return v.x ? Math.atan(v.y / v.x) : Math.PI / 2;\r\n}\r\n/**\r\n * 将角度调整为0-2pi之间\r\n * \r\n * @export\r\n * @param {number} an \r\n */\r\nexport function angleTo2Pi(an: number)\r\n{\r\n an = an % (Math.PI * 2);\r\n if (an < 0) an += Math.PI * 2\r\n return an;\r\n}\r\nexport function updateGeometry(l: THREE.Line | THREE.Mesh, geometry: Geometry)\r\n{\r\n let geo = l.geometry as THREE.Geometry;\r\n geo.dispose();\r\n l.geometry = geometry;\r\n geometry.verticesNeedUpdate = true;\r\n geometry.computeBoundingSphere();\r\n}\r\n","export * from \"./Viewer\";\r\nexport * from \"./CameraControls\";\r\nexport * from \"./GeUtils\";\r\nexport * from \"./createBoard\";\r\nexport * from \"./Dimension\";\r\nexport * from \"./DrawDimension\";\r\nexport * from \"./Material\";\r\nexport * from \"./PointPick\"\r\nexport * from \"./Utils\"\r\n","import * as THREE from 'three';\r\nimport { LineBasicMaterial, MeshBasicMaterial, Color } from 'three';\r\nconst ColorPalette = [\r\n [255, 0, 0, 255], //----- 0 - lets make it red for an example\r\n //[255, 255, 255, 255],//----- 0 - ByBlock - White\r\n [255, 0, 0, 255], //----- 1 - Red\r\n // [255, 0, 0, 255], //----- 1 - Red\r\n [255, 255, 0, 255], //----- 2 - Yellow\r\n [0, 255, 0, 255], //----- 3 - Green\r\n [0, 255, 255, 255], //----- 4 - Cyan\r\n [0, 0, 255, 255], //----- 5 - Blue\r\n [255, 0, 255, 255], //----- 6 - Magenta\r\n // [255, 0, 0, 255], //----- 7 - More red Red\r\n // [255, 0, 0, 255], //----- 8 - More red Red\r\n // [255, 0, 0, 255], //----- 9 - More red Red\r\n // [255, 255, 255, 255],//----- 7 - White\r\n // [255, 255, 255, 255],//----- 8\r\n // [255, 255, 255, 255],//----- 9\r\n // [255, 0, 0, 255], //----- 10\r\n // [255, 127, 127, 255],//----- 11\r\n // [165, 0, 0, 255], //----- 12\r\n // [165, 82, 82, 255], //----- 13\r\n // [127, 0, 0, 255], //----- 14\r\n // [127, 63, 63, 255], //----- 15\r\n // [76, 0, 0, 255], //----- 16\r\n // [76, 38, 38, 255], //----- 17\r\n // [38, 0, 0, 255], //----- 18\r\n // [38, 19, 19, 255], //----- 19\r\n // [255, 63, 0, 255], //----- 20\r\n // [255, 159, 127, 255],//----- 21\r\n // [165, 41, 0, 255], //----- 22\r\n // [165, 103, 82, 255], //----- 23\r\n // [127, 31, 0, 255], //----- 24\r\n // [127, 79, 63, 255], //----- 25\r\n // [76, 19, 0, 255], //----- 26\r\n // [76, 47, 38, 255], //----- 27\r\n // [38, 9, 0, 255], //----- 28\r\n // [38, 23, 19, 255], //----- 29\r\n // [255, 127, 0, 255], //----- 30\r\n // [255, 191, 127, 255],//----- 31\r\n // [165, 82, 0, 255], //----- 32\r\n // [165, 124, 82, 255], //----- 33\r\n // [127, 63, 0, 255], //----- 34\r\n // [127, 95, 63, 255], //----- 35\r\n // [76, 38, 0, 255], //----- 36\r\n // [76, 57, 38, 255], //----- 37\r\n // [38, 19, 0, 255], //----- 38\r\n // [38, 28, 19, 255], //----- 39\r\n // [255, 191, 0, 255], //----- 40\r\n // [255, 223, 127, 255],//----- 41\r\n // [165, 124, 0, 255], //----- 42\r\n // [165, 145, 82, 255], //----- 43\r\n // [127, 95, 0, 255], //----- 44\r\n // [127, 111, 63, 255], //----- 45\r\n // [76, 57, 0, 255], //----- 46\r\n // [76, 66, 38, 255], //----- 47\r\n // [38, 28, 0, 255], //----- 48\r\n // [38, 33, 19, 255], //----- 49\r\n // [255, 255, 0, 255], //----- 50\r\n // [255, 255, 127, 255],//----- 51\r\n // [165, 165, 0, 255], //----- 52\r\n // [165, 165, 82, 255], //----- 53\r\n // [127, 127, 0, 255], //----- 54\r\n // [127, 127, 63, 255], //----- 55\r\n // [76, 76, 0, 255], //----- 56\r\n // [76, 76, 38, 255], //----- 57\r\n // [38, 38, 0, 255], //----- 58\r\n // [38, 38, 19, 255], //----- 59\r\n // [191, 255, 0, 255], //----- 60\r\n // [223, 255, 127, 255],//----- 61\r\n // [124, 165, 0, 255], //----- 62\r\n // [145, 165, 82, 255], //----- 63\r\n // [95, 127, 0, 255], //----- 64\r\n // [111, 127, 63, 255], //----- 65\r\n // [57, 76, 0, 255], //----- 66\r\n // [66, 76, 38, 255], //----- 67\r\n // [28, 38, 0, 255], //----- 68\r\n // [33, 38, 19, 255], //----- 69\r\n // [127, 255, 0, 255], //----- 70\r\n // [191, 255, 127, 255],//----- 71\r\n // [82, 165, 0, 255], //----- 72\r\n // [124, 165, 82, 255], //----- 73\r\n // [63, 127, 0, 255], //----- 74\r\n // [95, 127, 63, 255], //----- 75\r\n // [38, 76, 0, 255], //----- 76\r\n // [57, 76, 38, 255], //----- 77\r\n // [19, 38, 0, 255], //----- 78\r\n // [28, 38, 19, 255], //----- 79\r\n // [63, 255, 0, 255], //----- 80\r\n // [159, 255, 127, 255],//----- 81\r\n // [41, 165, 0, 255], //----- 82\r\n // [103, 165, 82, 255], //----- 83\r\n // [31, 127, 0, 255], //----- 84\r\n // [79, 127, 63, 255], //----- 85\r\n // [19, 76, 0, 255], //----- 86\r\n // [47, 76, 38, 255], //----- 87\r\n // [9, 38, 0, 255], //----- 88\r\n // [23, 38, 19, 255], //----- 89\r\n // [0, 255, 0, 255], //----- 90\r\n // [127, 255, 127, 255],//----- 91\r\n // [0, 165, 0, 255], //----- 92\r\n // [82, 165, 82, 255], //----- 93\r\n // [0, 127, 0, 255], //----- 94\r\n // [63, 127, 63, 255], //----- 95\r\n // [0, 76, 0, 255], //----- 96\r\n // [38, 76, 38, 255], //----- 97\r\n // [0, 38, 0, 255], //----- 98\r\n // [19, 38, 19, 255], //----- 99\r\n // [0, 255, 63, 255], //----- 100\r\n // [127, 255, 159, 255],//----- 101\r\n // [0, 165, 41, 255], //----- 102\r\n // [82, 165, 103, 255], //----- 103\r\n // [0, 127, 31, 255], //----- 104\r\n // [63, 127, 79, 255], //----- 105\r\n // [0, 76, 19, 255], //----- 106\r\n // [38, 76, 47, 255], //----- 107\r\n // [0, 38, 9, 255], //----- 108\r\n // [19, 38, 23, 255], //----- 109\r\n // [0, 255, 127, 255], //----- 110\r\n // [127, 255, 191, 255],//----- 111\r\n // [0, 165, 82, 255], //----- 112\r\n // [82, 165, 124, 255], //----- 113\r\n // [0, 127, 63, 255], //----- 114\r\n // [63, 127, 95, 255], //----- 115\r\n // [0, 76, 38, 255], //----- 116\r\n // [38, 76, 57, 255], //----- 117\r\n // [0, 38, 19, 255], //----- 118\r\n // [19, 38, 28, 255], //----- 119\r\n // [0, 255, 191, 255], //----- 120\r\n // [127, 255, 223, 255],//----- 121\r\n // [0, 165, 124, 255], //----- 122\r\n // [82, 165, 145, 255], //----- 123\r\n // [0, 127, 95, 255], //----- 124\r\n // [63, 127, 111, 255], //----- 125\r\n // [0, 76, 57, 255], //----- 126\r\n // [38, 76, 66, 255], //----- 127\r\n // [0, 38, 28, 255], //----- 128\r\n // [19, 38, 33, 255], //----- 129\r\n // [0, 255, 255, 255], //----- 130\r\n // [127, 255, 255, 255],//----- 131\r\n // [0, 165, 165, 255], //----- 132\r\n // [82, 165, 165, 255], //----- 133\r\n // [0, 127, 127, 255], //----- 134\r\n // [63, 127, 127, 255], //----- 135\r\n // [0, 76, 76, 255], //----- 136\r\n // [38, 76, 76, 255], //----- 137\r\n // [0, 38, 38, 255], //----- 138\r\n // [19, 38, 38, 255], //----- 139\r\n // [0, 191, 255, 255], //----- 140\r\n // [127, 223, 255, 255],//----- 141\r\n // [0, 124, 165, 255], //----- 142\r\n // [82, 145, 165, 255], //----- 143\r\n // [0, 95, 127, 255], //----- 144\r\n // [63, 111, 127, 255], //----- 145\r\n // [0, 57, 76, 255], //----- 146\r\n // [38, 66, 76, 255], //----- 147\r\n // [0, 28, 38, 255], //----- 148\r\n // [19, 33, 38, 255], //----- 149\r\n // [0, 127, 255, 255], //----- 150\r\n // [127, 191, 255, 255],//----- 151\r\n // [0, 82, 165, 255], //----- 152\r\n // [82, 124, 165, 255], //----- 153\r\n // [0, 63, 127, 255], //----- 154\r\n // [63, 95, 127, 255], //----- 155\r\n // [0, 38, 76, 255], //----- 156\r\n // [38, 57, 76, 255], //----- 157\r\n // [0, 19, 38, 255], //----- 158\r\n // [19, 28, 38, 255], //----- 159\r\n // [0, 63, 255, 255], //----- 160\r\n // [127, 159, 255, 255],//----- 161\r\n // [0, 41, 165, 255], //----- 162\r\n // [82, 103, 165, 255], //----- 163\r\n // [0, 31, 127, 255], //----- 164\r\n // [63, 79, 127, 255], //----- 165\r\n // [0, 19, 76, 255], //----- 166\r\n // [38, 47, 76, 255], //----- 167\r\n // [0, 9, 38, 255], //----- 168\r\n // [19, 23, 38, 255], //----- 169\r\n // [0, 0, 255, 255], //----- 170\r\n // [127, 127, 255, 255],//----- 171\r\n // [0, 0, 165, 255], //----- 172\r\n // [82, 82, 165, 255], //----- 173\r\n // [0, 0, 127, 255], //----- 174\r\n // [63, 63, 127, 255], //----- 175\r\n // [0, 0, 76, 255], //----- 176\r\n // [38, 38, 76, 255], //----- 177\r\n // [0, 0, 38, 255], //----- 178\r\n // [19, 19, 38, 255], //----- 179\r\n // [63, 0, 255, 255], //----- 180\r\n // [159, 127, 255, 255],//----- 181\r\n // [41, 0, 165, 255], //----- 182\r\n // [103, 82, 165, 255], //----- 183\r\n // [31, 0, 127, 255], //----- 184\r\n // [79, 63, 127, 255], //----- 185\r\n // [19, 0, 76, 255], //----- 186\r\n // [47, 38, 76, 255], //----- 187\r\n // [9, 0, 38, 255], //----- 188\r\n // [23, 19, 38, 255], //----- 189\r\n // [127, 0, 255, 255], //----- 190\r\n // [191, 127, 255, 255],//----- 191\r\n // [82, 0, 165, 255], //----- 192\r\n // [124, 82, 165, 255], //----- 193\r\n // [63, 0, 127, 255], //----- 194\r\n // [95, 63, 127, 255], //----- 195\r\n // [38, 0, 76, 255], //----- 196\r\n // [57, 38, 76, 255], //----- 197\r\n // [19, 0, 38, 255], //----- 198\r\n // [28, 19, 38, 255], //----- 199\r\n // [191, 0, 255, 255], //----- 200\r\n // [223, 127, 255, 255],//----- 201\r\n // [124, 0, 165, 255], //----- 202\r\n // [145, 82, 165, 255], //----- 203\r\n // [95, 0, 127, 255], //----- 204\r\n // [111, 63, 127, 255], //----- 205\r\n // [57, 0, 76, 255], //----- 206\r\n // [66, 38, 76, 255], //----- 207\r\n // [28, 0, 38, 255], //----- 208\r\n // [33, 19, 38, 255], //----- 209\r\n // [255, 0, 255, 255], //----- 210\r\n // [255, 127, 255, 255],//----- 211\r\n // [165, 0, 165, 255], //----- 212\r\n // [165, 82, 165, 255], //----- 213\r\n // [127, 0, 127, 255], //----- 214\r\n // [127, 63, 127, 255], //----- 215\r\n // [76, 0, 76, 255], //----- 216\r\n // [76, 38, 76, 255], //----- 217\r\n // [38, 0, 38, 255], //----- 218\r\n // [38, 19, 38, 255], //----- 219\r\n // [255, 0, 191, 255], //----- 220\r\n // [255, 127, 223, 255],//----- 221\r\n // [165, 0, 124, 255], //----- 222\r\n // [165, 82, 145, 255], //----- 223\r\n // [127, 0, 95, 255], //----- 224\r\n // [127, 63, 111, 255], //----- 225\r\n // [76, 0, 57, 255], //----- 226\r\n // [76, 38, 66, 255], //----- 227\r\n // [38, 0, 28, 255], //----- 228\r\n // [38, 19, 33, 255], //----- 229\r\n // [255, 0, 127, 255], //----- 230\r\n // [255, 127, 191, 255],//----- 231\r\n // [165, 0, 82, 255], //----- 232\r\n // [165, 82, 124, 255], //----- 233\r\n // [127, 0, 63, 255], //----- 234\r\n // [127, 63, 95, 255], //----- 235\r\n // [76, 0, 38, 255], //----- 236\r\n // [76, 38, 57, 255], //----- 237\r\n // [38, 0, 19, 255], //----- 238\r\n // [38, 19, 28, 255], //----- 239\r\n // [255, 0, 63, 255], //----- 240\r\n // [255, 127, 159, 255],//----- 241\r\n // [165, 0, 41, 255], //----- 242\r\n // [165, 82, 103, 255], //----- 243\r\n // [127, 0, 31, 255], //----- 244\r\n // [127, 63, 79, 255], //----- 245\r\n // [76, 0, 19, 255], //----- 246\r\n // [76, 38, 47, 255], //----- 247\r\n // [38, 0, 9, 255], //----- 248\r\n // [38, 19, 23, 255], //----- 249\r\n // [84, 84, 84, 255], //----- 250\r\n // [118, 118, 118, 255],//----- 251\r\n // [152, 152, 152, 255],//----- 252\r\n // [186, 186, 186, 255],//----- 253\r\n // [220, 220, 220, 255],//----- 254\r\n // [255, 255, 255, 255],//----- 255\r\n // [255, 255, 255, 255] //----- ByLayer - White\r\n];\r\n\r\n\r\n//颜色材质,对于二维图像来说可能有用,应该不对三维对象使用该材质\r\nexport class ColorMaterial\r\n{\r\n private constructor() { }\r\n private static m_LineMaterialMap = new Map();\r\n static GetLineMaterial(index): LineBasicMaterial\r\n {\r\n if (this.m_LineMaterialMap.has(index))\r\n return this.m_LineMaterialMap.get(index);\r\n let mat = new LineBasicMaterial({ color: this.GetColor(index) });\r\n this.m_LineMaterialMap.set(index, mat);\r\n return mat;\r\n }\r\n private static m_BasicMaterialMap = new Map();\r\n static GetBasicMaterial(index: number): MeshBasicMaterial\r\n {\r\n if (this.m_BasicMaterialMap.has(index))\r\n return this.m_BasicMaterialMap.get(index);\r\n let mat = new MeshBasicMaterial({ color: this.GetColor(index) });\r\n this.m_BasicMaterialMap.set(index, mat);\r\n return mat;\r\n }\r\n\r\n static GetColor(index: number)\r\n {\r\n let rgb = ColorPalette[index];\r\n if (rgb)\r\n return new Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255);\r\n }\r\n}\r\n","import { Vector2, Vector3 } from \"three\";\r\n\r\nexport class Matrix2\r\n{\r\n private el = [1, 0, 0, 1];\r\n set(n11: number, n12: number, n21: number, n22: number)\r\n {\r\n let te = this.el;\r\n\r\n te[0] = n11; te[1] = n21;\r\n te[2] = n12; te[3] = n22;\r\n return this;\r\n }\r\n applyVector(vec: Vector2 | Vector3)\r\n {\r\n let x = vec.x, y = vec.y;\r\n let e = this.el;\r\n vec.x = e[0] * x + e[2] * y;\r\n vec.y = e[1] * x + e[3] * y;\r\n\r\n return this;\r\n }\r\n\r\n setRotate(theta: number): Matrix2\r\n {\r\n let el = this.el;\r\n let c = Math.cos(theta), s = Math.sin(theta);\r\n\r\n this.set(c, -s,\r\n s, c);\r\n return this;\r\n }\r\n}\r\n","import { MeshBasicMaterial, Color, LineBasicMaterial } from \"three\";\r\n\r\n//板件的材质,使用这个材质避免板件将线覆盖.\r\nexport let boardMaterial = new MeshBasicMaterial({\r\n color: new Color(0.8, 0.8, 0.8),\r\n polygonOffset: true,\r\n polygonOffsetFactor: 1, // positive value pushes polygon further away\r\n polygonOffsetUnits: 1\r\n});\r\n\r\nexport let selectMaterial = new MeshBasicMaterial({\r\n color: new Color(0.1, 0.5, 0.5),\r\n polygonOffset: true,\r\n polygonOffsetFactor: 1, // positive value pushes polygon further away\r\n polygonOffsetUnits: 1\r\n});\r\n\r\n//线框的材质\r\nexport let edgeMaterial = new LineBasicMaterial({ linewidth: 2, color: new Color(0, 0, 0) });\r\n\r\n","\r\nimport { Mesh, Raycaster, Scene, Vector3, WebGLRenderer, WebGLRendererParameters } from \"three\";\r\nimport { boardMaterial, CameraControls, PointPick, selectMaterial } from \".\";\r\nimport { CameraUpdate } from \"./CameraUpdate\";\r\nimport { ColorMaterial } from \"./ColorPalette\";\r\nimport { cZeroVec, GetBox, GetBoxArr } from \"./GeUtils\";\r\nimport { PlaneExt } from \"./PlaneExt\";\r\n\r\nexport class Viewer\r\n{\r\n m_LookTarget: any;\r\n m_Camera: CameraUpdate = new CameraUpdate();\r\n m_CameraCtrl: CameraControls;\r\n m_bNeedUpdate: boolean = true;\r\n m_Render: WebGLRenderer;//渲染器 //暂时只用这个类型\r\n m_DomEl: HTMLElement; //画布容器\r\n\r\n _Height: number;\r\n _Width: number;\r\n\r\n m_Scene: Scene = new Scene();\r\n\r\n /**\r\n * \r\n * @param {HTMLElement} canvasContainer 可以传入一个div或者一个画布\r\n * @memberof Viewer\r\n */\r\n constructor(canvasContainer: HTMLElement)\r\n {\r\n this.m_DomEl = canvasContainer;\r\n this.initRender(canvasContainer);\r\n this.OnSize();\r\n this.StartRender();\r\n this.m_CameraCtrl = new CameraControls(this);\r\n window.addEventListener(\"resize\", () =>\r\n {\r\n this.OnSize();\r\n });\r\n\r\n let oldMesh: Mesh;\r\n this.m_Render.domElement.addEventListener(\"mousemove\", (e: MouseEvent) =>\r\n {\r\n let mesh = PointPick(this, e.offsetX, e.offsetY);\r\n if (oldMesh)\r\n oldMesh.material = boardMaterial;\r\n if (mesh && mesh.material !== ColorMaterial.GetBasicMaterial(1))\r\n {\r\n oldMesh = mesh;\r\n mesh.material = selectMaterial;\r\n }\r\n this.m_bNeedUpdate = true;\r\n })\r\n }\r\n\r\n //初始化render\r\n initRender(canvasContainer: HTMLElement)\r\n {\r\n let params: WebGLRendererParameters = {\r\n antialias: true,//antialias:true/false是否开启反锯齿\r\n precision: \"highp\",//precision:highp/mediump/lowp着色精度选择\r\n alpha: true//alpha:true/false是否可以设置背景色透明\r\n };\r\n if (canvasContainer instanceof HTMLCanvasElement)\r\n {\r\n params.canvas = canvasContainer;\r\n this.m_Render = new WebGLRenderer(params);\r\n }\r\n else\r\n {\r\n this.m_Render = new WebGLRenderer(params);\r\n //加到画布\r\n canvasContainer.appendChild(this.m_Render.domElement);\r\n }\r\n\r\n this.m_Render.autoClear = true;\r\n\r\n //如果设置,那么它希望所有的纹理和颜色都是预乘的伽玛。默认值为false。\r\n // this.m_Render.gammaInput = true;\r\n // this.m_Render.gammaOutput = true;\r\n // this.m_Render.shadowMap.enabled = true;\r\n // this.m_Render.toneMapping = ReinhardToneMapping;\r\n //设置设备像素比。 这通常用于HiDPI设备,以防止模糊输出画布。\r\n this.m_Render.setPixelRatio(window.devicePixelRatio);\r\n this.m_Render.physicallyCorrectLights = true;\r\n //this.m_Render.toneMappingExposure = Math.pow(1, 5.0); // to allow for very bright scenes.\r\n\r\n //设置它的背景色为黑色\r\n this.m_Render.setClearColor(0xffffff, 1);\r\n\r\n\r\n this.OnSize();\r\n }\r\n\r\n OnSize = (width?, height?) =>\r\n {\r\n this._Width = width ? width : this.m_DomEl.clientWidth;\r\n this._Height = height ? height : this.m_DomEl.clientHeight;\r\n\r\n //校验.成为2的倍数 避免外轮廓错误.\r\n if (this._Width % 2 == 1)\r\n this._Width -= 1;\r\n if (this._Height % 2 == 1)\r\n this._Height -= 1;\r\n\r\n this.m_Render.setSize(this._Width, this._Height);\r\n this.m_Camera.SetSize(this._Width, this._Height);\r\n }\r\n\r\n StartRender = () =>\r\n {\r\n requestAnimationFrame(this.StartRender);\r\n if (this.m_Scene != null && this.m_bNeedUpdate)\r\n {\r\n this.Render();\r\n this.m_bNeedUpdate = false;\r\n }\r\n }\r\n Render()\r\n {\r\n this.m_Render.render(this.m_Scene, this.m_Camera.Camera);\r\n }\r\n\r\n ScreenToWorld(pt: Vector3, planVec?: Vector3)\r\n {\r\n //变换和求交点\r\n let plan = new PlaneExt(planVec || new Vector3(0, 0, 1));\r\n let raycaster = new Raycaster();\r\n // 射线从相机射线向屏幕点位置\r\n raycaster.setFromCamera(\r\n {\r\n x: (pt.x / this._Width) * 2 - 1,\r\n y: - (pt.y / this._Height) * 2 + 1\r\n }\r\n , this.m_Camera.Camera\r\n )\r\n plan.intersectRay(raycaster.ray, pt, true);\r\n }\r\n WorldToScreen(pt: Vector3)\r\n {\r\n let widthHalf = this._Width * 0.5;\r\n let heightHalf = this._Height * 0.5;\r\n\r\n pt.project(this.m_Camera.Camera);\r\n\r\n pt.x = (pt.x * widthHalf) + widthHalf;\r\n pt.y = - (pt.y * heightHalf) + heightHalf;\r\n }\r\n\r\n /**\r\n * 更新视角观测目标(物体中心)\r\n * \r\n * @memberof Viewer\r\n */\r\n UpdateLockTarget()\r\n {\r\n let renderList = this.m_Render.renderLists.get(this.m_Scene, this.m_Camera.Camera);\r\n let box = GetBoxArr(renderList.opaque.map(o => o.object));\r\n if (box)\r\n this.m_LookTarget = box.getCenter(new Vector3());\r\n else\r\n this.m_LookTarget = cZeroVec;\r\n }\r\n Rotate(mouseMove: Vector3)\r\n {\r\n this.m_Camera.Rotate(mouseMove, this.m_LookTarget);\r\n this.m_bNeedUpdate = true;\r\n }\r\n Pan(mouseMove: Vector3)\r\n {\r\n this.m_Camera.Pan(mouseMove);\r\n this.m_bNeedUpdate = true;\r\n }\r\n Zoom(scale: number, center?: Vector3)\r\n {\r\n this.m_Camera.Zoom(scale, center);\r\n this.m_bNeedUpdate = true;\r\n }\r\n ZoomAll()\r\n {\r\n this.m_Camera.ZoomExtensBox3(GetBox(this.m_Scene, true));\r\n this.m_bNeedUpdate = true;\r\n }\r\n\r\n ViewToTop()\r\n {\r\n this.m_Camera.LookAt(new Vector3(0, 0, -1));\r\n this.m_bNeedUpdate = true;\r\n }\r\n ViewToFront()\r\n {\r\n this.m_Camera.LookAt(new Vector3(0, 1, 0));\r\n this.m_bNeedUpdate = true;\r\n }\r\n ViewToSwiso()\r\n {\r\n this.m_Camera.LookAt(new Vector3(1, 1, -1));\r\n this.m_bNeedUpdate = true;\r\n }\r\n}\r\n","import * as THREE from 'three';\r\nimport { Vector3 } from 'three';\r\nimport { Orbit } from './Orbit';\r\n\r\n/**\r\n * \r\n * 相机的控制.\r\n * ->切换相机\r\n * ->设置视口大小\r\n * ->旋转和移动相机.\r\n * \r\n * @export\r\n * @class ViewCameraManage\r\n */\r\nexport class CameraUpdate\r\n{\r\n private m_CurCamera: THREE.Camera;\r\n private m_CameraArray: Map = new Map();\r\n\r\n //视口的画布大小\r\n private m_Width: number;\r\n private m_Height: number;\r\n //视口显示的高度\r\n private m_ViewHeight: number = 10;\r\n\r\n //观察的位置\r\n private m_Target: THREE.Vector3 = new THREE.Vector3();\r\n //观察向量\r\n private m_Direction: THREE.Vector3 = new THREE.Vector3(0, 0, -1);\r\n //观察的轨道.\r\n private m_Orbit: Orbit = new Orbit();\r\n\r\n m_MinViewHeight = 10;\r\n m_MaxViewHeight = 3e4;\r\n\r\n constructor()\r\n {\r\n this.m_CameraArray.set(THREE.OrthographicCamera, new THREE.OrthographicCamera(-2, 2, 2, -2,\r\n -1e6, 1e6));\r\n\r\n this.m_CameraArray.set(THREE.PerspectiveCamera, new THREE.PerspectiveCamera(50, 1, 0.01, 10000));\r\n\r\n this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera);\r\n\r\n this.m_Orbit.UpdateRoValue(this.m_Direction);\r\n\r\n this.UpdateUp();\r\n\r\n this.Update();\r\n }\r\n get Aspect(): number\r\n {\r\n return this.m_Width / this.m_Height;\r\n }\r\n\r\n get Camera(): THREE.Camera\r\n {\r\n return this.m_CurCamera;\r\n }\r\n get ViewHeight()\r\n {\r\n return this.m_ViewHeight;\r\n }\r\n set ViewHeight(height)\r\n {\r\n this.m_ViewHeight = THREE.Math.clamp(height, this.m_MinViewHeight, this.m_MaxViewHeight);\r\n }\r\n\r\n SetSize(width: number, height: number)\r\n {\r\n this.m_Width = width;\r\n this.m_Height = height;\r\n }\r\n\r\n /**\r\n * 平移相机.\r\n * \r\n * @param {THREE.Vector3} mouseMove\r\n * @memberof CameraControl\r\n */\r\n Pan(mouseMove: THREE.Vector3)\r\n {\r\n mouseMove.y *= -1;\r\n mouseMove.multiplyScalar(-this.m_ViewHeight / this.m_Height);\r\n mouseMove.applyQuaternion(this.Camera.quaternion);\r\n this.m_Target.add(mouseMove);\r\n this.Update();\r\n }\r\n Rotate(mouseMove: THREE.Vector3, target: THREE.Vector3)\r\n {\r\n this.m_Orbit.RoX -= mouseMove.y * 0.003;\r\n this.m_Orbit.RoZ -= mouseMove.x * 0.003;\r\n\r\n //缓存观察点\r\n let oldTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse);\r\n\r\n this.m_Orbit.UpdateDirection(this.m_Direction);\r\n this.UpdateUp();\r\n this.Update();\r\n\r\n //-----还原观察点\r\n //得到新的观察点相对于相机的位置\r\n let newTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse);\r\n //减去原先的位置. 得到观测点在相机内移动的向量\r\n newTargetFormCameraSpace.sub(oldTargetFormCameraSpace);\r\n //乘以相机的矩阵. 得到向量在世界坐标系的位置\r\n newTargetFormCameraSpace.applyMatrix4(this.Camera.matrix);\r\n //因为使用的是点变换,所以减去基点,得到向量\r\n newTargetFormCameraSpace.sub(this.Camera.position);\r\n //加上移动的向量. 使得观察点时钟在相机的某个位置\r\n this.m_Target.add(newTargetFormCameraSpace);\r\n\r\n this.Update();\r\n }\r\n Zoom(scale: number, scaleCenter?: THREE.Vector3)\r\n {\r\n if (this.Camera instanceof THREE.OrthographicCamera)\r\n {\r\n this.ViewHeight *= scale;\r\n if (scaleCenter && this.m_ViewHeight < this.m_MaxViewHeight)\r\n {\r\n this.m_Target.sub(scaleCenter);\r\n this.m_Target.multiplyScalar(scale);\r\n this.m_Target.add(scaleCenter);\r\n }\r\n }\r\n else if (this.Camera instanceof THREE.PerspectiveCamera)\r\n {\r\n let add = scale > 1 ? 1 : -1;\r\n add *= this.Camera.position.distanceTo(this.m_Target) / 10;\r\n this.m_Target.add(this.m_Direction.clone().multiplyScalar(-add));\r\n }\r\n this.Update();\r\n }\r\n ZoomExtensBox3(box3: THREE.Box3)\r\n {\r\n if (!box3 || box3.isEmpty()) return;\r\n this.Camera.updateMatrixWorld(false);\r\n //变换到相机坐标系\r\n box3.applyMatrix4(this.Camera.matrixWorldInverse);\r\n //\r\n box3.getCenter(this.m_Target);\r\n //世界坐标系\r\n this.m_Target.applyMatrix4(this.Camera.matrix);\r\n //size\r\n let size = box3.getSize(new Vector3());\r\n //宽高比\r\n let aspectRatio = size.x / size.y;\r\n\r\n let viewAspectRatio = this.Aspect;\r\n //\r\n if (aspectRatio > viewAspectRatio)\r\n {\r\n this.m_ViewHeight = size.x / viewAspectRatio;\r\n }\r\n else\r\n {\r\n this.m_ViewHeight = size.y;\r\n }\r\n this.Update();\r\n }\r\n LookAt(dir: THREE.Vector3)\r\n {\r\n this.m_Orbit.UpdateRoValue(dir);\r\n this.m_Direction.copy(dir);\r\n this.UpdateUp();\r\n this.Update();\r\n }\r\n\r\n UpdateUp()\r\n {\r\n Orbit.ComputUpDirection(this.m_Direction, this.Camera.up);\r\n }\r\n /**\r\n * 根据视口大小,设置相机视口范围.\r\n * \r\n * @returns \r\n * @memberof CameraControl\r\n */\r\n Update()\r\n {\r\n this.Camera.position.copy(this.m_Target);\r\n\r\n if (this.Camera instanceof THREE.OrthographicCamera)\r\n {\r\n this.Camera.left = this.Aspect * this.m_ViewHeight / -2;\r\n this.Camera.right = this.Aspect * this.m_ViewHeight / 2;\r\n this.Camera.bottom = this.m_ViewHeight / -2;\r\n this.Camera.top = this.m_ViewHeight / 2;\r\n\r\n this.Camera.position.sub(this.m_Direction);\r\n }\r\n else if (this.Camera instanceof THREE.PerspectiveCamera)\r\n {\r\n this.Camera.aspect = this.Aspect;\r\n let distens = (this.m_ViewHeight / 2) / (Math.tan(THREE.Math.degToRad(this.Camera.fov) / 2));\r\n\r\n this.Camera.position.sub(this.m_Direction.clone().multiplyScalar(distens));\r\n }\r\n else\r\n {\r\n return;\r\n }\r\n\r\n this.Camera.lookAt(this.m_Target);\r\n this.Camera.updateProjectionMatrix();\r\n this.Camera.updateMatrixWorld(false);\r\n }\r\n\r\n SwitchCamera()\r\n {\r\n if (this.Camera instanceof THREE.OrthographicCamera)\r\n {\r\n this.m_CurCamera = this.m_CameraArray.get(THREE.PerspectiveCamera);\r\n }\r\n else\r\n {\r\n this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera);\r\n }\r\n this.UpdateUp();\r\n this.Update();\r\n }\r\n}\r\n","import * as THREE from \"three\";\r\n\r\n/**\r\n * 轨道控制的数学类,观察向量和角度的互相转换\r\n * 当x当抬头或者低头到90度时,触发万向锁.\r\n * \r\n * @class Orbit\r\n */\r\nexport class Orbit\r\n{\r\n //抬头低头 正数抬头 负数低头\r\n private m_RoX: number = 0;\r\n\r\n //身体旋转 0为正右边 逆时针旋转\r\n RoZ: number = 0;\r\n\r\n get RoX()\r\n {\r\n return this.m_RoX;\r\n }\r\n set RoX(v)\r\n {\r\n this.m_RoX = THREE.Math.clamp(v, Math.PI * -0.5, Math.PI * 0.5);\r\n }\r\n\r\n /**\r\n * 使用旋转角度 计算观察向量\r\n * \r\n * @param {THREE.Vector3} [dir] 引用传入,如果传入,那么就不构造新的向量\r\n * @returns {THREE.Vector3} 返回观察向量\r\n * @memberof Orbit\r\n */\r\n UpdateDirection(dir?: THREE.Vector3): THREE.Vector3\r\n {\r\n let rtDir = dir ? dir : new THREE.Vector3();\r\n\r\n rtDir.z = Math.sin(this.m_RoX);\r\n\r\n //归一化专用.\r\n let d = Math.abs(Math.cos(this.m_RoX));\r\n\r\n rtDir.x = Math.cos(this.RoZ) * d;\r\n rtDir.y = Math.sin(this.RoZ) * d;\r\n\r\n return rtDir;\r\n }\r\n\r\n /**\r\n * 使用观察向量,计算旋转角度\r\n * \r\n * @param {THREE.Vector3} dir \r\n * @memberof Orbit\r\n */\r\n UpdateRoValue(dir: THREE.Vector3)\r\n {\r\n dir.normalize();\r\n this.m_RoX = Math.asin(dir.z);\r\n if (dir.x < 1e-4 && dir.y < 1e-4)\r\n this.RoZ = Math.PI * 0.5;\r\n else\r\n this.RoZ = Math.atan2(dir.y, dir.x);\r\n }\r\n\r\n /**\r\n * \r\n * 根据观察向量 求头部的向量.\r\n * \r\n * @static\r\n * @param {THREE.Vector3} dir \r\n * @param {THREE.Vector3} [up] \r\n * @returns {THREE.Vector3} \r\n * @memberof Orbit\r\n */\r\n static ComputUpDirection(dir: THREE.Vector3, up?: THREE.Vector3): THREE.Vector3\r\n {\r\n let upRes = up ? up : new THREE.Vector3();\r\n if (dir.equals(new THREE.Vector3(0, 0, -1)))\r\n {\r\n upRes.set(0, 1, 0);\r\n }\r\n else if (dir.equals(new THREE.Vector3(0, 0, 1)))\r\n {\r\n upRes.set(0, -1, 0);\r\n }\r\n else\r\n {\r\n let xv = new THREE.Vector3();\r\n xv.crossVectors(new THREE.Vector3(0, 0, 1), dir);\r\n upRes.crossVectors(dir, xv);\r\n upRes.normalize();\r\n }\r\n return upRes;\r\n }\r\n}\r\n","import * as THREE from 'three';\r\nimport { Vector3, Line3 } from \"three\";\r\n\r\nexport class PlaneExt extends THREE.Plane\r\n{\r\n constructor(normal?: THREE.Vector3, constant?: number)\r\n {\r\n super(normal, constant);\r\n }\r\n intersectLine(line: Line3, optionalTarget?: Vector3, extendLine?: boolean): Vector3\r\n {\r\n let v1 = new Vector3();\r\n\r\n let result = optionalTarget || new Vector3();\r\n\r\n let direction = line.delta(v1);\r\n\r\n let denominator = this.normal.dot(direction);\r\n\r\n if (denominator === 0)\r\n {\r\n // line is coplanar, return origin\r\n if (this.distanceToPoint(line.start) === 0)\r\n {\r\n return result.copy(line.start);\r\n }\r\n // Unsure if this is the correct method to handle this case.\r\n return undefined;\r\n }\r\n\r\n let t = - (line.start.dot(this.normal) + this.constant) / denominator;\r\n //If you not extendLine,check intersect point in Line\r\n if (!extendLine && (t < 0 || t > 1))\r\n {\r\n return undefined;\r\n }\r\n\r\n return result.copy(direction).multiplyScalar(t).add(line.start);\r\n }\r\n intersectRay(ray: THREE.Ray, optionalTarget?: Vector3, extendLine?: boolean): Vector3\r\n {\r\n // 从射线初始位置\r\n let line = new THREE.Line3(ray.origin.clone(), ray.origin.clone().add(ray.direction));\r\n return this.intersectLine(line, optionalTarget, extendLine);\r\n }\r\n}\r\n","import * as THREE from 'three';\r\n\r\nimport { KeyBoard, MouseKey } from './KeyEnum';\r\nimport { Vector3 } from 'three';\r\nimport { Viewer } from './Viewer';\r\n\r\n//相机控制状态\r\nexport enum CameraControlState\r\n{\r\n Null = 0, Pan = 1, Rotate = 2, Scale = 3\r\n}\r\n\r\nexport class CameraControls\r\n{\r\n m_TouthTypeList = [CameraControlState.Rotate, CameraControlState.Scale, CameraControlState.Pan];\r\n m_domElement: HTMLElement;//HTMLDocument\r\n //起始点击\r\n m_StartClickPoint: THREE.Vector3 = new THREE.Vector3();\r\n m_EndClickPoint: THREE.Vector3 = new THREE.Vector3();\r\n m_DollyStart: THREE.Vector2 = new THREE.Vector2();\r\n m_DollyEnd: THREE.Vector2 = new THREE.Vector2();\r\n\r\n m_KeyDown = new Map();\r\n m_MouseDown = new Map();\r\n\r\n //状态\r\n m_State: CameraControlState = CameraControlState.Null;\r\n m_Viewer: Viewer;\r\n //左键使用旋转\r\n m_LeftUseRotate: boolean = true;\r\n\r\n constructor(viewer: Viewer)\r\n {\r\n this.m_Viewer = viewer;\r\n this.m_domElement = viewer.m_Render.domElement.parentElement;\r\n this.RegisterEvent();\r\n }\r\n\r\n RegisterEvent()\r\n {\r\n if (this.m_domElement)\r\n {\r\n this.m_domElement.addEventListener(\"mousedown\", this.onMouseDown, false)\r\n this.m_domElement.addEventListener(\"mousemove\", this.onMouseMove, false)\r\n this.m_domElement.addEventListener(\"mouseup\", this.onMouseUp, false)\r\n window.addEventListener(\"keydown\", this.onKeyDown, false);\r\n window.addEventListener(\"keyup\", this.onKeyUp, false);\r\n this.m_domElement.addEventListener('wheel', this.onMouseWheel, false);\r\n\r\n this.m_domElement.addEventListener('touchstart', this.onTouchStart, false);\r\n this.m_domElement.addEventListener('touchend', this.onTouchEnd, false);\r\n this.m_domElement.addEventListener('touchmove', this.onTouchMove, false);\r\n\r\n window.addEventListener(\"blur\", this.onBlur, false);\r\n }\r\n }\r\n /**\r\n * 窗体失去焦点时.\r\n * \r\n * @memberof CameraControls\r\n */\r\n onBlur = () =>\r\n {\r\n this.m_KeyDown.clear();\r\n this.m_MouseDown.clear();\r\n }\r\n\r\n //触屏开始事件\r\n onTouchStart = (event: TouchEvent) =>\r\n {\r\n this.m_Viewer.UpdateLockTarget();\r\n this.m_StartClickPoint.set(event.touches[0].pageX, event.touches[0].pageY, 0);\r\n if (event.touches.length < 4)\r\n {\r\n if (event.touches.length == 2)\r\n {\r\n var dx = event.touches[0].pageX - event.touches[1].pageX;\r\n var dy = event.touches[0].pageY - event.touches[1].pageY;\r\n var distance = Math.sqrt(dx * dx + dy * dy);\r\n this.m_DollyStart.set(0, distance);\r\n }\r\n this.m_State = this.m_TouthTypeList[event.touches.length - 1];\r\n }\r\n }\r\n onTouchEnd = (event: TouchEvent) =>\r\n {\r\n this.m_State = CameraControlState.Null;\r\n }\r\n onTouchMove = (event: TouchEvent) =>\r\n {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n this.m_EndClickPoint.set(event.touches[0].pageX, event.touches[0].pageY, 0);\r\n\r\n let vec = this.m_EndClickPoint.clone().sub(this.m_StartClickPoint);\r\n switch (this.m_State)\r\n {\r\n case CameraControlState.Pan:\r\n {\r\n this.m_Viewer.Pan(vec);\r\n break;\r\n }\r\n case CameraControlState.Scale:\r\n {\r\n var dx = event.touches[0].pageX - event.touches[1].pageX;\r\n var dy = event.touches[0].pageY - event.touches[1].pageY;\r\n\r\n var distance = Math.sqrt(dx * dx + dy * dy);\r\n this.m_DollyEnd.set(0, distance);\r\n if (distance > this.m_DollyStart.y)\r\n {\r\n this.m_Viewer.Zoom(0.95);\r\n }\r\n else\r\n {\r\n this.m_Viewer.Zoom(1.05)\r\n }\r\n this.m_DollyStart.copy(this.m_DollyEnd);\r\n break;\r\n }\r\n case CameraControlState.Rotate:\r\n {\r\n this.m_Viewer.Rotate(vec.multiplyScalar(2));\r\n break;\r\n }\r\n }\r\n this.m_StartClickPoint.copy(this.m_EndClickPoint);\r\n this.m_Viewer.m_bNeedUpdate = true;\r\n }\r\n beginRotate()\r\n {\r\n this.m_State = CameraControlState.Rotate;\r\n this.m_Viewer.UpdateLockTarget();\r\n }\r\n\r\n //最后一次按中键的时间\r\n lastMiddleClickTime = 0;\r\n //鼠标 \r\n onMouseDown = (event: MouseEvent) =>\r\n {\r\n event.preventDefault();\r\n let key: MouseKey = event.button;\r\n this.m_MouseDown.set(key, true);\r\n this.m_StartClickPoint.set(event.offsetX, event.offsetY, 0);\r\n\r\n switch (key)\r\n {\r\n case MouseKey.Left:\r\n {\r\n if (this.m_LeftUseRotate)\r\n {\r\n this.beginRotate();\r\n }\r\n break;\r\n }\r\n case MouseKey.Middle:\r\n {\r\n let curTime = Date.now();\r\n let t = curTime - this.lastMiddleClickTime;\r\n this.lastMiddleClickTime = curTime;\r\n if (t < 350)\r\n {\r\n this.m_Viewer.ZoomAll();\r\n return;\r\n }\r\n if (this.m_KeyDown.get(KeyBoard.Control))\r\n {\r\n this.beginRotate();\r\n }\r\n else\r\n {\r\n this.m_State = CameraControlState.Pan;\r\n }\r\n break;\r\n }\r\n case MouseKey.Right:\r\n {\r\n break;\r\n }\r\n }\r\n }\r\n onMouseUp = (event: MouseEvent) =>\r\n {\r\n event.preventDefault();\r\n this.m_State = CameraControlState.Null;\r\n this.m_MouseDown.set(event.button, false);\r\n }\r\n onMouseMove = (event: MouseEvent) =>\r\n {\r\n event.preventDefault();\r\n this.m_EndClickPoint.set(event.offsetX, event.offsetY, 0);\r\n let changeVec = this.m_EndClickPoint.clone().sub(this.m_StartClickPoint);\r\n this.m_StartClickPoint.copy(this.m_EndClickPoint);\r\n if (\r\n (this.m_LeftUseRotate ||\r\n (this.m_KeyDown.get(KeyBoard.Control))\r\n )\r\n && this.m_State == CameraControlState.Rotate\r\n )\r\n {\r\n this.m_Viewer.Rotate(changeVec);\r\n }\r\n switch (this.m_State)\r\n {\r\n case CameraControlState.Pan:\r\n {\r\n this.m_Viewer.Pan(changeVec);\r\n break;\r\n }\r\n case CameraControlState.Rotate:\r\n {\r\n break;\r\n }\r\n case CameraControlState.Scale:\r\n {\r\n break;\r\n }\r\n }\r\n }\r\n /**\r\n * 鼠标滚轮事件\r\n * \r\n * @memberof CameraControls\r\n */\r\n onMouseWheel = (event: WheelEvent) =>\r\n {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n let pt = new THREE.Vector3(event.offsetX, event.offsetY, 0);\r\n\r\n this.m_Viewer.ScreenToWorld(pt, new Vector3().setFromMatrixColumn(this.m_Viewer.m_Camera.Camera.matrixWorld, 2));\r\n if (event.deltaY < 0)\r\n {\r\n this.m_Viewer.Zoom(0.6, pt);\r\n }\r\n else if (event.deltaY > 0)\r\n {\r\n this.m_Viewer.Zoom(1.4, pt);\r\n }\r\n }\r\n //按键\r\n onKeyDown = (event: KeyboardEvent) =>\r\n {\r\n this.m_KeyDown.set(event.keyCode, true);\r\n }\r\n onKeyUp = (event: KeyboardEvent) =>\r\n {\r\n this.m_KeyDown.set(event.keyCode, false);\r\n }\r\n}\r\n","//鼠标类型\r\nexport enum MouseKey\r\n{\r\n Left = 0,\r\n Middle = 1,\r\n Right = 2,\r\n}\r\n\r\nexport enum KeyBoard\r\n{\r\n // 数字\r\n Digit1 = 49,\r\n Digit2 = 50,\r\n Digit3 = 51,\r\n Digit4 = 52,\r\n Digit5 = 53,\r\n Digit6 = 54,\r\n Digit7 = 55,\r\n Digit8 = 56,\r\n Digit9 = 57,\r\n Digit0 = 58,\r\n // 字母\r\n KeyA = 65,\r\n KeyB = 66,\r\n KeyC = 67,\r\n KeyD = 68,\r\n KeyE = 69,\r\n KeyF = 70,\r\n KeyG = 71,\r\n KeyH = 72,\r\n KeyI = 73,\r\n KeyJ = 74,\r\n KeyK = 75,\r\n KeyL = 76,\r\n KeyM = 77,\r\n KeyN = 78,\r\n KeyO = 79,\r\n KeyP = 80,\r\n KeyQ = 81,\r\n KeyR = 82,\r\n KeyS = 83,\r\n KeyT = 84,\r\n KeyU = 85,\r\n KeyV = 86,\r\n KeyW = 87,\r\n KeyX = 88,\r\n KeyY = 89,\r\n KeyZ = 90,\r\n\r\n // 符号\r\n /**\r\n * 逗号\r\n */\r\n Comma = 188,\r\n CommaChrome = 229,\r\n /**\r\n * 句号\r\n */\r\n Period = 190,\r\n /**\r\n * 分号\r\n */\r\n Semicolon = 186,\r\n /**\r\n * 引号\r\n */\r\n Quote = 222,\r\n /**\r\n * 左括号\r\n */\r\n BracketLeft = 219,\r\n /**\r\n * 右括号\r\n */\r\n BracketRight = 220,\r\n /**\r\n * 反引号\r\n */\r\n Backquote = 192,\r\n /**\r\n * 反斜杠\r\n */\r\n Backslash = 220,\r\n /**\r\n * 减号\r\n */\r\n Minus = 189,\r\n /**\r\n * 等号\r\n */\r\n Equal = 187,\r\n IntlRo = 193,\r\n IntlYen = 255,\r\n // 功能键\r\n Alt = 18,\r\n /**\r\n * 大写锁定\r\n */\r\n CapsLock = 20,\r\n Control = 17,\r\n /**\r\n * win左键\r\n */\r\n OSLeft = 91,\r\n /**\r\n * win右键\r\n */\r\n OSRight = 92,\r\n Shift = 16,\r\n\r\n ContextMenu = 93,\r\n Enter = 13,\r\n Space = 32,\r\n Backspace = 8,\r\n Tab = 9,\r\n Delete = 46,\r\n End = 35,\r\n Home = 36,\r\n Insert = 45,\r\n PageDown = 34,\r\n PageUp = 33,\r\n ArrowDown = 40,\r\n ArrowLeft = 37,\r\n ArrowRight = 39,\r\n ArrowUp = 38,\r\n Escape = 27,\r\n PrintScreen = 44,\r\n ScrollLock = 145,\r\n Pause = 19,\r\n\r\n // F数字\r\n F1 = 112,\r\n F2 = 113,\r\n F3 = 114,\r\n F5 = 116,\r\n F6 = 117,\r\n F7 = 118,\r\n F8 = 119,\r\n F9 = 120,\r\n F10 = 121,\r\n F11 = 122,\r\n F12 = 123,\r\n\r\n //数字键盘\r\n NumLock = 114,\r\n Numpad0 = 96,\r\n Numpad1 = 97,\r\n Numpad2 = 98,\r\n Numpad3 = 99,\r\n Numpad4 = 100,\r\n Numpad5 = 101,\r\n Numpad6 = 102,\r\n Numpad7 = 103,\r\n Numpad8 = 104,\r\n Numpad9 = 105,\r\n NumpadAdd = 107,\r\n NumpadDivide = 111,\r\n NumpadEqual = 12,\r\n NumpadMultiply = 106,\r\n NumpadSubtract = 109,\r\n NumpadDot = 110,\r\n NumpadDot1 = 190\r\n\r\n}\r\n","import * as THREE from 'three';\r\nimport { CylinderGeometry, Geometry, LineSegments, Mesh, Shape, Vector2 } from 'three';\r\nimport { ColorMaterial } from './ColorPalette';\r\nimport { polar } from './GeUtils';\r\nimport { boardMaterial, edgeMaterial } from './Material';\r\nimport { RotateUVs } from './RotateUV';\r\nimport { ThreeBSP } from './ThreeCSG';\r\n//解析二维圆弧类.\r\nexport class Arc2d\r\n{\r\n m_StartAn: number;\r\n m_EndAn: number;\r\n m_StartPoint: THREE.Vector2;\r\n m_EndPoint: THREE.Vector2;\r\n m_Center: THREE.Vector2;\r\n m_Radius: number;\r\n constructor(p1: THREE.Vector2, p2: THREE.Vector2, bul: number)\r\n {\r\n this.m_StartPoint = p1.clone();\r\n this.m_EndPoint = p2.clone();\r\n\r\n let vec: THREE.Vector2 = p2.clone().sub(p1);\r\n let len = vec.length();\r\n let an = vec.angle();\r\n this.m_Radius = len / Math.sin(2 * Math.atan(bul)) / 2;\r\n let allAngle = Math.atan(bul) * 4;\r\n let delDis = bul * len / 2;\r\n let toDis = this.m_Radius - delDis;\r\n an += Math.PI * 0.5;\r\n\r\n this.m_Center = p1.clone().add(p2);\r\n this.m_Center.multiplyScalar(0.5);\r\n\r\n polar(this.m_Center, an, toDis);\r\n\r\n this.m_StartAn = p1.clone().sub(this.m_Center).angle();\r\n this.m_EndAn = p2.clone().sub(this.m_Center).angle();\r\n if (bul < 0)\r\n {\r\n //一个神奇的特性 它需要这么做\r\n this.m_StartAn -= Math.PI;\r\n this.m_EndAn -= Math.PI;\r\n }\r\n }\r\n}\r\n\r\n//创建轮廓 通过点表和凸度 \r\nexport function createPath(pts: Vector2[], buls: number[], shapeOut?: Shape): Shape\r\n{\r\n let shape = shapeOut || new Shape();\r\n if (pts.length === 0) return shape;\r\n let firstPt = pts[0];\r\n\r\n shape.moveTo(firstPt.x, firstPt.y);\r\n for (let i = 0; i < pts.length - 1; i++)\r\n {\r\n let nextPt = pts[i + 1];\r\n if (buls[i] == 0)\r\n {\r\n shape.lineTo(nextPt.x, nextPt.y)\r\n }\r\n else\r\n {\r\n let pt = pts[i];\r\n //参考\r\n //http://www.dorodnic.com/blog/tag/three-js/ 绘制一个齿轮\r\n //https://www.kirupa.com/html5/drawing_circles_canvas.htm //html5\r\n let arc2 = new Arc2d(pt, nextPt, buls[i]);\r\n let cen = arc2.m_Center;\r\n shape.absarc(cen.x, cen.y, arc2.m_Radius, arc2.m_StartAn, arc2.m_EndAn, buls[i] < 0);\r\n }\r\n }\r\n return shape;\r\n}\r\nexport function getVec(data: object): THREE.Vector3\r\n{\r\n return new THREE.Vector3(data[\"x\"], data[\"y\"], data[\"z\"]);\r\n}\r\n\r\n//创建板件 暂时这么写\r\nexport function createBoard(boardData: object)\r\n{\r\n let pts: THREE.Vector2[] = [];\r\n let buls: number[] = [];\r\n let boardPts = boardData[\"Pts\"];\r\n let boardBuls = boardData[\"Buls\"];\r\n\r\n let boardHeight = boardData[\"H\"];\r\n\r\n let boardMat = new THREE.Matrix4();\r\n let matInv: THREE.Matrix4 = new THREE.Matrix4();\r\n //InitBoardMat\r\n let xD = getVec(boardData[\"XVec\"]);\r\n let yD = getVec(boardData[\"YVec\"]);\r\n let ZD = getVec(boardData[\"ZVec\"]);\r\n let pBase = getVec(boardData[\"BasePoint\"]);\r\n\r\n boardMat.makeBasis(xD, yD, ZD);\r\n boardMat.setPosition(pBase);\r\n matInv.getInverse(boardMat, true);\r\n\r\n if (boardPts && boardPts.length !== 0)\r\n for (let i = 0; i < boardPts.length; i++)\r\n {\r\n let pt = getVec(boardPts[i]);\r\n if (boardPts[i].z !== undefined)\r\n pt.applyMatrix4(matInv);\r\n pts.push(new THREE.Vector2(pt.x, pt.y));\r\n buls.push(boardBuls[i]);\r\n }\r\n else\r\n {\r\n let length = boardData[\"L\"];\r\n let width = boardData[\"W\"];\r\n let height = boardData[\"H\"];\r\n pts.push(new Vector2(0, 0),\r\n new Vector2(width, 0),\r\n new Vector2(width, length),\r\n new Vector2(0, length),\r\n new Vector2(0, 0)\r\n );\r\n buls.push(0, 0, 0, 0, 0);\r\n }\r\n\r\n let sp = createPath(pts, buls);\r\n let extrudeSettings = {\r\n steps: 1,\r\n bevelEnabled: false,\r\n amount: boardHeight\r\n };\r\n\r\n let ext = new THREE.ExtrudeGeometry(sp, extrudeSettings) as Geometry;\r\n ext.computeBoundingSphere();\r\n ext.computeBoundingBox();\r\n ext.translate(0, 0, -boardHeight)\r\n ext.applyMatrix(boardMat);\r\n\r\n //外边.\r\n let edges: (LineSegments | Mesh)[] = [createEdge(ext)];\r\n\r\n //差集\r\n if (checkObjectArray(boardData, \"SubBoardLocal\")\r\n || checkObjectArray(boardData, \"Drillings\"))\r\n {\r\n let thisCsg = new ThreeBSP(ext);\r\n\r\n if (boardData[\"SubBoardLocal\"])\r\n {\r\n let subBoardList = boardData[\"SubBoardLocal\"].map(d => createBoard(d));\r\n for (let br of subBoardList)\r\n {\r\n edges.push(...br.edges);\r\n let subCsg = new ThreeBSP(br.mesh);\r\n thisCsg = thisCsg.subtract(subCsg);\r\n }\r\n }\r\n if (boardData[\"Drillings\"])\r\n {\r\n let dris = boardData[\"Drillings\"];\r\n for (let dri of dris)\r\n {\r\n let geo = new CylinderGeometry(dri.r, dri.r, dri.h, 8);\r\n geo.rotateX(Math.PI * 0.5);\r\n\r\n if (dri.f === 0) //0正\r\n geo.translate(dri.x, dri.y, -dri.h * 0.5);\r\n else //1反\r\n geo.translate(dri.x, dri.y, dri.h * 0.5 - boardData[\"H\"]);\r\n\r\n geo.applyMatrix(boardMat);\r\n\r\n let mesh = new Mesh(geo, ColorMaterial.GetBasicMaterial(1));\r\n edges.push(mesh);\r\n // let edge = createEdge(geo);\r\n // edge.material = new LineBasicMaterial({ color: new Color(1, 0, 0) });\r\n // edges.push(edge);\r\n\r\n // let subCsg = new ThreeBSP(geo);\r\n // thisCsg = thisCsg.subtract(subCsg);\r\n }\r\n }\r\n ext = thisCsg.toGeometry();\r\n }\r\n\r\n if (boardData[\"BoardName\"] === \"地脚线\")\r\n RotateUVs(ext);\r\n\r\n let mesh = new THREE.Mesh(ext, boardMaterial);\r\n mesh.userData = ZD;\r\n edges.forEach(e => e.userData = ZD);\r\n return { mesh, edges };\r\n}\r\n\r\nfunction checkObjectArray(obj: any, key: string)\r\n{\r\n return obj[key] && obj[key].length > 0;\r\n}\r\n\r\nexport function createTemplateBoard(brDataList: any[])\r\n{\r\n let meshs = [];\r\n let edgesa = [];\r\n for (let d of brDataList)\r\n {\r\n let { mesh, edges } = createBoard(d);\r\n meshs.push(mesh);\r\n edgesa.push(...edges);\r\n }\r\n return { meshs, edgesa };\r\n}\r\n\r\nexport function createEdge(geo: Geometry): LineSegments\r\n{\r\n let edge = new THREE.EdgesGeometry(geo, 1);\r\n return new LineSegments(edge, edgeMaterial);\r\n}\r\n","import { Matrix2 } from './Matrix2';\r\nimport { Geometry, Vector2 } from 'three';\r\n\r\n\r\nexport function RotateUVs(geo: Geometry)\r\n{\r\n let roMat = new Matrix2();\r\n roMat.set(0, -1,\r\n 1, 0);\r\n\r\n let addV = new Vector2(1, 0);\r\n\r\n for (let uvs of geo.faceVertexUvs)\r\n {\r\n for (let uv of uvs)\r\n {\r\n for (let v of uv)\r\n {\r\n roMat.applyVector(v);\r\n v.add(addV);\r\n }\r\n }\r\n }\r\n geo.uvsNeedUpdate = true;\r\n}\r\n","import * as THREE from \"three\";\r\n\r\n/*jshint esversion: 6 */\r\n\r\nconst EPSILON = 1e-5,\r\n COPLANAR = 0, //共面\r\n FRONT = 1, //前\r\n BACK = 2,\r\n SPANNING = 3;\r\n\r\nexport class ThreeBSP\r\n{\r\n tree: Node;\r\n matrix: THREE.Matrix4;\r\n Node: typeof Node;\r\n Vertex: typeof Vertex;\r\n Polygon: typeof Polygon;\r\n constructor(geometry)\r\n {\r\n // Convert THREE.Geometry to ThreeBSP\r\n let i, _length_i,\r\n face, vertex, faceVertexUvs, uvs,\r\n polygon,\r\n polygons = [],\r\n tree;\r\n\r\n this.Polygon = Polygon;\r\n this.Vertex = Vertex;\r\n this.Node = Node;\r\n if (geometry instanceof THREE.Geometry)\r\n {\r\n this.matrix = new THREE.Matrix4();\r\n } else if (geometry instanceof THREE.Mesh)\r\n {\r\n // #todo: add hierarchy support\r\n geometry.updateMatrix();\r\n this.matrix = geometry.matrix.clone();\r\n geometry = geometry.geometry;\r\n } else if (geometry instanceof Node)\r\n {\r\n this.tree = geometry;\r\n this.matrix = new THREE.Matrix4();\r\n return this;\r\n } else\r\n {\r\n throw 'ThreeBSP: Given geometry is unsupported';\r\n }\r\n\r\n for (i = 0, _length_i = geometry.faces.length; i < _length_i; i++)\r\n {\r\n face = geometry.faces[i];\r\n faceVertexUvs = geometry.faceVertexUvs[0][i];\r\n polygon = new Polygon();\r\n\r\n if (face instanceof THREE.Face3)\r\n {\r\n vertex = geometry.vertices[face.a];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[0].x, faceVertexUvs[0].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n\r\n vertex = geometry.vertices[face.b];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[1].x, faceVertexUvs[1].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n\r\n vertex = geometry.vertices[face.c];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[2].x, faceVertexUvs[2].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n } else if (typeof THREE.Face4)\r\n {\r\n vertex = geometry.vertices[face.a];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[0].x, faceVertexUvs[0].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n\r\n vertex = geometry.vertices[face.b];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[1].x, faceVertexUvs[1].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n\r\n vertex = geometry.vertices[face.c];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[2].x, faceVertexUvs[2].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n\r\n vertex = geometry.vertices[face.d];\r\n uvs = faceVertexUvs ? new THREE.Vector2(faceVertexUvs[3].x, faceVertexUvs[3].y) : null;\r\n vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[3], uvs);\r\n vertex.applyMatrix4(this.matrix);\r\n polygon.vertices.push(vertex);\r\n } else\r\n {\r\n throw 'Invalid face type at index ' + i;\r\n }\r\n\r\n polygon.calculateProperties();\r\n polygons.push(polygon);\r\n }\r\n\r\n this.tree = new Node(polygons);\r\n }\r\n\r\n //减\r\n subtract(other_tree)\r\n {\r\n let a = this.tree.clone(),\r\n b = other_tree.tree.clone();\r\n\r\n a.invert();\r\n a.clipTo(b);\r\n b.clipTo(a);\r\n b.invert();\r\n b.clipTo(a);\r\n b.invert();\r\n a.build(b.allPolygons());\r\n a.invert();\r\n let bsp = new ThreeBSP(a);\r\n bsp.matrix = this.matrix;\r\n return bsp;\r\n }\r\n\r\n //结合\r\n union(other_tree)\r\n {\r\n let a = this.tree.clone(),\r\n b = other_tree.tree.clone();\r\n\r\n a.clipTo(b);\r\n b.clipTo(a);\r\n b.invert();\r\n b.clipTo(a);\r\n b.invert();\r\n a.build(b.allPolygons());\r\n let bsp = new ThreeBSP(a);\r\n bsp.matrix = this.matrix;\r\n return bsp;\r\n }\r\n\r\n //相交\r\n intersect(other_tree)\r\n {\r\n let a = this.tree.clone(),\r\n b = other_tree.tree.clone();\r\n\r\n a.invert();\r\n b.clipTo(a);\r\n b.invert();\r\n a.clipTo(b);\r\n b.clipTo(a);\r\n a.build(b.allPolygons());\r\n a.invert();\r\n let bsp = new ThreeBSP(a);\r\n bsp.matrix = this.matrix;\r\n return bsp;\r\n }\r\n\r\n toGeometry()\r\n {\r\n let i, j,\r\n matrix = new THREE.Matrix4().getInverse(this.matrix),\r\n geometry = new THREE.Geometry(),\r\n polygons = this.tree.allPolygons(),\r\n polygon_count = polygons.length,\r\n polygon, polygon_vertice_count,\r\n vertice_dict = {},\r\n vertex_idx_a, vertex_idx_b, vertex_idx_c,\r\n vertex, face,\r\n verticeUvs;\r\n\r\n for (i = 0; i < polygon_count; i++)\r\n {\r\n polygon = polygons[i];\r\n polygon_vertice_count = polygon.vertices.length;\r\n\r\n for (j = 2; j < polygon_vertice_count; j++)\r\n {\r\n verticeUvs = [];\r\n\r\n vertex = polygon.vertices[0];\r\n verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));\r\n vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);\r\n vertex.applyMatrix4(matrix);\r\n\r\n if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined')\r\n {\r\n vertex_idx_a = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];\r\n } else\r\n {\r\n geometry.vertices.push(vertex);\r\n vertex_idx_a = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;\r\n }\r\n\r\n vertex = polygon.vertices[j - 1];\r\n verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));\r\n vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);\r\n vertex.applyMatrix4(matrix);\r\n if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined')\r\n {\r\n vertex_idx_b = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];\r\n } else\r\n {\r\n geometry.vertices.push(vertex);\r\n vertex_idx_b = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;\r\n }\r\n\r\n vertex = polygon.vertices[j];\r\n verticeUvs.push(new THREE.Vector2(vertex.uv.x, vertex.uv.y));\r\n vertex = new THREE.Vector3(vertex.x, vertex.y, vertex.z);\r\n vertex.applyMatrix4(matrix);\r\n if (typeof vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] !== 'undefined')\r\n {\r\n vertex_idx_c = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z];\r\n } else\r\n {\r\n geometry.vertices.push(vertex);\r\n vertex_idx_c = vertice_dict[vertex.x + ',' + vertex.y + ',' + vertex.z] = geometry.vertices.length - 1;\r\n }\r\n\r\n face = new THREE.Face3(\r\n vertex_idx_a,\r\n vertex_idx_b,\r\n vertex_idx_c,\r\n new THREE.Vector3(polygon.normal.x, polygon.normal.y, polygon.normal.z)\r\n );\r\n\r\n geometry.faces.push(face);\r\n geometry.faceVertexUvs[0].push(verticeUvs);\r\n }\r\n\r\n }\r\n return geometry;\r\n }\r\n\r\n toMesh(material)\r\n {\r\n let geometry = this.toGeometry(),\r\n mesh = new THREE.Mesh(geometry, material);\r\n\r\n mesh.position.setFromMatrixPosition(this.matrix);\r\n mesh.rotation.setFromRotationMatrix(this.matrix);\r\n\r\n return mesh;\r\n }\r\n}\r\n\r\n//多边形\r\nexport class Polygon\r\n{\r\n w: any;\r\n normal: any;\r\n vertices: any;\r\n constructor(vertices?, normal?, w?)\r\n {\r\n if (!(vertices instanceof Array))\r\n {\r\n vertices = [];\r\n }\r\n\r\n this.vertices = vertices;\r\n if (vertices.length > 0)\r\n {\r\n this.calculateProperties();\r\n } else\r\n {\r\n this.normal = this.w = undefined;\r\n }\r\n }\r\n\r\n calculateProperties()\r\n {\r\n let a = this.vertices[0],\r\n b = this.vertices[1],\r\n c = this.vertices[2];\r\n\r\n this.normal = b.clone().subtract(a).cross(\r\n c.clone().subtract(a)\r\n ).normalize();\r\n\r\n this.w = this.normal.clone().dot(a);\r\n\r\n return this;\r\n }\r\n\r\n clone()\r\n {\r\n let i, vertice_count,\r\n polygon = new Polygon();\r\n\r\n for (i = 0, vertice_count = this.vertices.length; i < vertice_count; i++)\r\n {\r\n polygon.vertices.push(this.vertices[i].clone());\r\n }\r\n polygon.calculateProperties();\r\n\r\n return polygon;\r\n }\r\n\r\n flip()\r\n {\r\n let i, vertices = [];\r\n\r\n this.normal.multiplyScalar(-1);\r\n this.w *= -1;\r\n\r\n for (i = this.vertices.length - 1; i >= 0; i--)\r\n {\r\n vertices.push(this.vertices[i]);\r\n }\r\n this.vertices = vertices;\r\n\r\n return this;\r\n }\r\n\r\n //划分?\r\n classifyVertex(vertex)\r\n {\r\n let side_value = this.normal.dot(vertex) - this.w;\r\n\r\n if (side_value < -EPSILON)\r\n {\r\n return BACK;\r\n } else if (side_value > EPSILON)\r\n {\r\n return FRONT;\r\n } else\r\n {\r\n return COPLANAR;\r\n }\r\n }\r\n\r\n //划分边?\r\n classifySide(polygon)\r\n {\r\n let i, vertex, classification,\r\n num_positive = 0,\r\n num_negative = 0,\r\n vertice_count = polygon.vertices.length;\r\n\r\n for (i = 0; i < vertice_count; i++)\r\n {\r\n vertex = polygon.vertices[i];\r\n classification = this.classifyVertex(vertex);\r\n if (classification === FRONT)\r\n {\r\n num_positive++;\r\n } else if (classification === BACK)\r\n {\r\n num_negative++;\r\n }\r\n }\r\n\r\n if (num_positive > 0 && num_negative === 0)\r\n {\r\n return FRONT;\r\n } else if (num_positive === 0 && num_negative > 0)\r\n {\r\n return BACK;\r\n } else if (num_positive === 0 && num_negative === 0)\r\n {\r\n return COPLANAR;\r\n } else\r\n {\r\n return SPANNING;\r\n }\r\n }\r\n\r\n //分解 分离 区域?\r\n splitPolygon(polygon, coplanar_front, coplanar_back, front, back)\r\n {\r\n let classification = this.classifySide(polygon);\r\n\r\n if (classification === COPLANAR)\r\n {\r\n\r\n (this.normal.dot(polygon.normal) > 0 ? coplanar_front : coplanar_back).push(polygon);\r\n\r\n } else if (classification === FRONT)\r\n {\r\n\r\n front.push(polygon);\r\n\r\n } else if (classification === BACK)\r\n {\r\n\r\n back.push(polygon);\r\n\r\n } else\r\n {\r\n\r\n let vertice_count,\r\n i, j, ti, tj, vi, vj,\r\n t, v,\r\n f = [],\r\n b = [];\r\n\r\n for (i = 0, vertice_count = polygon.vertices.length; i < vertice_count; i++)\r\n {\r\n\r\n j = (i + 1) % vertice_count;\r\n vi = polygon.vertices[i];\r\n vj = polygon.vertices[j];\r\n ti = this.classifyVertex(vi);\r\n tj = this.classifyVertex(vj);\r\n\r\n if (ti != BACK) f.push(vi);\r\n if (ti != FRONT) b.push(vi);\r\n if ((ti | tj) === SPANNING)\r\n {\r\n t = (this.w - this.normal.dot(vi)) / this.normal.dot(vj.clone().subtract(vi));\r\n v = vi.interpolate(vj, t);\r\n f.push(v);\r\n b.push(v);\r\n }\r\n }\r\n\r\n\r\n if (f.length >= 3) front.push(new Polygon(f).calculateProperties());\r\n if (b.length >= 3) back.push(new Polygon(b).calculateProperties());\r\n }\r\n }\r\n}\r\n\r\nexport class Vertex\r\n{\r\n uv: any;\r\n normal: any;\r\n z: any;\r\n y: any;\r\n x: any;\r\n constructor(x: number, y: number, z: number, normal: THREE.Vector3, uv: THREE.Vector2)\r\n {\r\n this.x = x;\r\n this.y = y;\r\n this.z = z;\r\n this.normal = normal || new THREE.Vector3();\r\n this.uv = uv || new THREE.Vector2();\r\n }\r\n\r\n clone()\r\n {\r\n return new Vertex(this.x, this.y, this.z, this.normal.clone(), this.uv.clone());\r\n }\r\n\r\n add(vertex)\r\n {\r\n this.x += vertex.x;\r\n this.y += vertex.y;\r\n this.z += vertex.z;\r\n return this;\r\n }\r\n\r\n subtract(vertex)\r\n {\r\n this.x -= vertex.x;\r\n this.y -= vertex.y;\r\n this.z -= vertex.z;\r\n return this;\r\n }\r\n\r\n multiplyScalar(scalar)\r\n {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n this.z *= scalar;\r\n return this;\r\n }\r\n\r\n //×乘\r\n cross(vertex)\r\n {\r\n let x = this.x,\r\n y = this.y,\r\n z = this.z;\r\n\r\n this.x = y * vertex.z - z * vertex.y;\r\n this.y = z * vertex.x - x * vertex.z;\r\n this.z = x * vertex.y - y * vertex.x;\r\n\r\n return this;\r\n }\r\n\r\n normalize()\r\n {\r\n let length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\r\n\r\n this.x /= length;\r\n this.y /= length;\r\n this.z /= length;\r\n\r\n return this;\r\n }\r\n\r\n //点乘\r\n dot(vertex)\r\n {\r\n return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z;\r\n }\r\n\r\n //线性插值\r\n lerp(a, t)\r\n {\r\n this.add(\r\n a.clone().subtract(this).multiplyScalar(t)\r\n );\r\n\r\n this.normal.add(\r\n a.normal.clone().sub(this.normal).multiplyScalar(t)\r\n );\r\n\r\n this.uv.add(\r\n a.uv.clone().sub(this.uv).multiplyScalar(t)\r\n );\r\n\r\n return this;\r\n }\r\n\r\n //插值\r\n interpolate(other, t)\r\n {\r\n return this.clone().lerp(other, t);\r\n }\r\n\r\n applyMatrix4(m)\r\n {\r\n\r\n // input: THREE.Matrix4 affine matrix\r\n\r\n let x = this.x, y = this.y, z = this.z;\r\n\r\n let e = m.elements;\r\n\r\n this.x = e[0] * x + e[4] * y + e[8] * z + e[12];\r\n this.y = e[1] * x + e[5] * y + e[9] * z + e[13];\r\n this.z = e[2] * x + e[6] * y + e[10] * z + e[14];\r\n\r\n return this;\r\n\r\n }\r\n}\r\nexport class Node\r\n{\r\n divider: any;\r\n back: any;\r\n front: any;\r\n polygons: any[];\r\n constructor(polygons?)\r\n {\r\n let i, polygon_count,\r\n front = [],\r\n back = [];\r\n\r\n this.polygons = [];\r\n this.front = this.back = undefined;\r\n\r\n if (!(polygons instanceof Array) || polygons.length === 0) return;\r\n\r\n this.divider = polygons[0].clone();\r\n\r\n for (i = 0, polygon_count = polygons.length; i < polygon_count; i++)\r\n {\r\n this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);\r\n }\r\n\r\n if (front.length > 0)\r\n {\r\n this.front = new Node(front);\r\n }\r\n\r\n if (back.length > 0)\r\n {\r\n this.back = new Node(back);\r\n }\r\n }\r\n\r\n //是凸的? 凸包?\r\n isConvex(polygons)\r\n {\r\n let i, j;\r\n for (i = 0; i < polygons.length; i++)\r\n {\r\n for (j = 0; j < polygons.length; j++)\r\n {\r\n if (i !== j && polygons[i].classifySide(polygons[j]) !== BACK)\r\n {\r\n return false;\r\n }\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n build(polygons)\r\n {\r\n let i, polygon_count,\r\n front = [],\r\n back = [];\r\n\r\n if (!this.divider)\r\n {\r\n this.divider = polygons[0].clone();\r\n }\r\n\r\n for (i = 0, polygon_count = polygons.length; i < polygon_count; i++)\r\n {\r\n this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);\r\n }\r\n\r\n if (front.length > 0)\r\n {\r\n if (!this.front) this.front = new Node();\r\n this.front.build(front);\r\n }\r\n\r\n if (back.length > 0)\r\n {\r\n if (!this.back) this.back = new Node();\r\n this.back.build(back);\r\n }\r\n }\r\n\r\n allPolygons()\r\n {\r\n let polygons = this.polygons.slice();\r\n if (this.front) polygons = polygons.concat(this.front.allPolygons());\r\n if (this.back) polygons = polygons.concat(this.back.allPolygons());\r\n return polygons;\r\n }\r\n\r\n clone()\r\n {\r\n let node = new Node();\r\n\r\n node.divider = this.divider.clone();\r\n node.polygons = this.polygons.map(function (polygon)\r\n {\r\n return polygon.clone();\r\n });\r\n node.front = this.front && this.front.clone();\r\n node.back = this.back && this.back.clone();\r\n\r\n return node;\r\n }\r\n\r\n //反转\r\n invert()\r\n {\r\n let i, polygon_count, temp;\r\n\r\n for (i = 0, polygon_count = this.polygons.length; i < polygon_count; i++)\r\n {\r\n this.polygons[i].flip();\r\n }\r\n\r\n this.divider.flip();\r\n if (this.front) this.front.invert();\r\n if (this.back) this.back.invert();\r\n\r\n temp = this.front;\r\n this.front = this.back;\r\n this.back = temp;\r\n\r\n return this;\r\n }\r\n\r\n //\r\n clipPolygons(polygons)\r\n {\r\n let i, polygon_count,\r\n front, back;\r\n\r\n if (!this.divider) return polygons.slice();\r\n\r\n front = [];\r\n back = [];\r\n\r\n for (i = 0, polygon_count = polygons.length; i < polygon_count; i++)\r\n {\r\n this.divider.splitPolygon(polygons[i], front, back, front, back);\r\n }\r\n\r\n if (this.front) front = this.front.clipPolygons(front);\r\n if (this.back) back = this.back.clipPolygons(back);\r\n else back = [];\r\n\r\n return front.concat(back);\r\n }\r\n\r\n clipTo(node)\r\n {\r\n this.polygons = node.clipPolygons(this.polygons);\r\n if (this.front) this.front.clipTo(node);\r\n if (this.back) this.back.clipTo(node);\r\n }\r\n}\r\n","import { Group, Geometry, Vector3, Line, Matrix4 } from \"three\";\r\nimport { ColorMaterial } from \"./ColorPalette\";\r\nimport { DbText } from \"./Text\";\r\nimport { MoveMatrix } from \"./GeUtils\";\r\n\r\n/**\r\n * 标注实体\r\n * \r\n * @export\r\n * @class Dimension\r\n * @extends {Group}\r\n */\r\nexport class Dimension extends Group\r\n{\r\n\r\n constructor(length: number, textHeight: number = 25, mirror: boolean = false, mirrorFoot: boolean = false)\r\n {\r\n super();\r\n let footLength = 60;\r\n if (mirrorFoot)\r\n {\r\n footLength = -footLength;\r\n }\r\n\r\n //针脚几何体\r\n let lineGeo = new Geometry();\r\n lineGeo.vertices.push(new Vector3(), new Vector3(0, footLength, 0));\r\n\r\n //托盘几何体\r\n let lineGeo2 = new Geometry();\r\n lineGeo2.vertices.push(new Vector3(0, footLength), new Vector3(length, footLength, 0));\r\n\r\n let material = ColorMaterial.GetLineMaterial(5)\r\n\r\n let line1 = new Line(lineGeo, material);\r\n let line2 = new Line(lineGeo, material);\r\n line2.position.x = length;\r\n\r\n let line3 = new Line(lineGeo2, material);\r\n\r\n let text = new DbText(parseFloat(length.toFixed(2)).toString(), textHeight);\r\n if (mirror)\r\n {\r\n let roMat = new Matrix4().makeRotationZ(Math.PI);\r\n text.applyMatrix(roMat);\r\n text.applyMatrix(MoveMatrix(new Vector3(length * 0.5, footLength - textHeight * 0.1)));\r\n }\r\n else\r\n {\r\n text.applyMatrix(MoveMatrix(new Vector3(length * 0.5, footLength * 1.1)));\r\n }\r\n\r\n\r\n this.add(text);\r\n\r\n this.add(line1, line2, line3);\r\n }\r\n}\r\n","import { Font, FontLoader, Mesh, ShapeGeometry, Vector3 } from \"three\";\r\nimport { ColorMaterial } from \"./ColorPalette\";\r\nimport { MoveMatrix } from \"./GeUtils\";\r\n\r\nclass FontLoaderUtil\r\n{\r\n private static defFont: Font;\r\n static Load(): Font\r\n {\r\n if (!this.defFont)\r\n {\r\n const f = require(\"../resources/fonts/helvetiker_regular.typeface.json\");\r\n let loader = new FontLoader();\r\n this.defFont = loader.parse(f);\r\n }\r\n return this.defFont;\r\n }\r\n}\r\n\r\nexport class DbText extends Mesh\r\n{\r\n /**\r\n *\r\n * 构造一个文本对象,8位点(中心点下面)在0点\r\n * @param {string} str 数字字符串\r\n * @param {number} height 文本高度\r\n * @memberof DbText\r\n */\r\n constructor(str: string, height: number = 5)\r\n {\r\n let font = FontLoaderUtil.Load();\r\n\r\n let shapes: THREE.Shape[] = font.generateShapes(str, height, 0.1);\r\n let geometry = new ShapeGeometry(shapes);\r\n\r\n geometry.computeBoundingBox();\r\n\r\n super(geometry, ColorMaterial.GetBasicMaterial(5));\r\n\r\n let center = geometry.boundingBox.getCenter(new Vector3());\r\n this.applyMatrix(MoveMatrix(new Vector3(-center.x, 0, 0)));\r\n }\r\n}\r\n","import { Box3, Vector3, Matrix4, Mesh } from \"three\";\r\nimport { Dimension, GetBoxArr } from \".\";\r\n\r\n\r\n/**\r\n * 绘制标注实体\r\n * \r\n * @export\r\n * @param {Box3} box \r\n * @returns 标注实体列表\r\n */\r\nexport function DrawDimension(brList: Mesh[]): Dimension[]\r\n{\r\n let box = GetBoxArr(brList);\r\n let size = box.getSize(new Vector3());\r\n\r\n let mat4 = new Matrix4();\r\n mat4.makeBasis(\r\n new Vector3(-1, 0, 0),\r\n new Vector3(0, -1, 0),\r\n new Vector3(0, 0, 1)\r\n )\r\n mat4.setPosition(box.min.clone().add(new Vector3(size.x, -30)));\r\n\r\n let textHeight = 45;\r\n let dimx = new Dimension(size.x, textHeight, true);\r\n dimx.applyMatrix(mat4);\r\n\r\n let dimz = new Dimension(size.z, textHeight);\r\n mat4.makeBasis(\r\n new Vector3(0, 0, -1),\r\n new Vector3(1, 0, 0),\r\n new Vector3(0, -1, 0)\r\n )\r\n mat4.setPosition(box.max.clone().add(new Vector3(30, -size.y)));\r\n dimz.applyMatrix(mat4);\r\n\r\n let dimy = new Dimension(size.y, textHeight, true, true);\r\n mat4.makeBasis(\r\n new Vector3(0, 1, 0),\r\n new Vector3(-1, 0, 0),\r\n new Vector3(0, 0, 1)\r\n )\r\n mat4.setPosition(box.max.clone().add(new Vector3(30, -size.y)));\r\n dimy.applyMatrix(mat4);\r\n\r\n\r\n return [dimx, dimy, dimz];\r\n}\r\n","import { Object3D, Raycaster, Face3, Vector3, Vector2, Mesh } from \"three\";\r\nimport { Viewer } from \".\";\r\n\r\ninterface Intersect\r\n{\r\n distance: number;\r\n face: Face3;\r\n faceIndex: number;\r\n object: Object3D;\r\n point: Vector3;\r\n uv: Vector2;\r\n}\r\n\r\n\r\n/**\r\n * 点选\r\n * \r\n * @export\r\n * @param {Viewer} view \r\n * @param {number} ptx \r\n * @param {number} pty \r\n * @returns {(Mesh | undefined)} \r\n */\r\nexport function PointPick(view: Viewer, ptx: number, pty: number): Mesh | undefined\r\n{\r\n let raycaster = new Raycaster();\r\n raycaster.setFromCamera({\r\n x: (ptx / view._Width) * 2 - 1, //-1 到 1 所以 (x-(w/2))/(w/2) =>\r\n y: - (pty / view._Height) * 2 + 1 //y轴相反\r\n }, view.m_Camera.Camera);\r\n\r\n //https://github.com/mrdoob/three.js/issues/14128\r\n raycaster.ray.origin.set((ptx / view._Width) * 2 - 1, - (pty / view._Height) * 2 + 1, -1).unproject(view.m_Camera.Camera);\r\n\r\n\r\n let minDis = Infinity;\r\n let minObj = undefined;\r\n\r\n view.m_Scene.children.forEach(obj =>\r\n {\r\n if (obj instanceof Mesh)\r\n {\r\n let intersects: Intersect[] = [];\r\n obj.raycast(raycaster, intersects);\r\n\r\n for (let i of intersects)\r\n {\r\n if (i.distance < minDis)\r\n {\r\n minObj = obj;\r\n minDis = i.distance;\r\n }\r\n }\r\n }\r\n });\r\n\r\n return minObj;\r\n}\r\n","import { Object3D } from \"three\";\r\nimport { createTemplateBoard, DrawDimension, Viewer } from \".\";\r\n\r\nfunction dispose(m: Object3D)\r\n{\r\n //@ts-ignore\r\n if (m.geometry)\r\n //@ts-ignore\r\n m.geometry.dispose();\r\n\r\n m.children.forEach(o => dispose(o));\r\n}\r\n\r\nexport function LoadBoard(view: Viewer, data: any[], clear: boolean = true)\r\n{\r\n if (clear)\r\n {\r\n dispose(view.m_Scene);\r\n view.m_Scene.children.length = 0;\r\n }\r\n\r\n if (data.length === 0) return;\r\n //加板\r\n let { meshs, edgesa } = createTemplateBoard(data);\r\n //加标注\r\n let dims = DrawDimension(meshs);\r\n\r\n view.m_Scene.add(...meshs);\r\n view.m_Scene.add(...edgesa);\r\n view.m_Scene.add(...dims);\r\n\r\n view.ViewToSwiso();\r\n view.ZoomAll();\r\n view.Zoom(1.1);\r\n}\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/src/GeUtils.ts b/src/GeUtils.ts index 00ee8c1..64073d5 100644 --- a/src/GeUtils.ts +++ b/src/GeUtils.ts @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import { Geometry, Vector, Vector2, Vector3 } from 'three'; +import { Geometry, Vector, Vector2, Vector3, Box3 } from 'three'; import { Matrix2 } from './Matrix2'; @@ -168,51 +168,47 @@ export function midPtCir(v1: THREE.Vector3, v2: THREE.Vector3) return v1.clone().add(midLine); } +/** + * 获得Three对象的包围盒. + * @param obj + * @param [updateMatrix] 是否应该更新对象矩阵 + * @returns box + */ export function GetBox(obj: THREE.Object3D, updateMatrix?: boolean): THREE.Box3 { + let box = new Box3(); if (updateMatrix) obj.updateMatrixWorld(false); - if (obj.hasOwnProperty("geometry")) + if (!obj.visible) return box; + + obj.traverse(o => { - let geo = obj["geometry"]; - if (geo instanceof THREE.Geometry || geo instanceof THREE.BufferGeometry) + //因为实体Erase时,实体仍然保存在Scene中. + if (o.visible === false) + return; + + //@ts-ignore + let geo = o.geometry as BufferGeometry; + if (geo) { if (!geo.boundingBox) geo.computeBoundingBox(); - return geo.boundingBox.clone().applyMatrix4(obj.matrixWorld); + box.union(geo.boundingBox.clone().applyMatrix4(o.matrixWorld)); } - } - else if (obj.children.length > 0) - { - let box = obj.children.reduce((sumBox, itemObj) => - { - let itemBox = GetBox(itemObj); - if (itemBox) - sumBox.union(itemBox); - return sumBox; - }, new THREE.Box3()) - // if (box) box.applyMatrix4(obj.matrixWorld); - return box; - } - else - return null; + }); + + return box; } export function GetBoxArr(arr: Array): THREE.Box3 { - if (arr.length == 0) + let box = new Box3(); + for (let o of arr) { - return null; + let b = GetBox(o); + if (!b.isEmpty()) + box.union(b); } - return arr.map(o => - { - return GetBox(o); - }).filter(o => - { - return o; - }).reduce((sumBox: THREE.Box3, objBox: THREE.Box3) => - { - return sumBox.union(objBox) - }, new THREE.Box3()); + return box; } export function MoveMatrix(v: THREE.Vector3): THREE.Matrix4 diff --git a/src/ViewSrc/index.ts b/src/ViewSrc/index.ts index cd2df13..9dc79fe 100644 --- a/src/ViewSrc/index.ts +++ b/src/ViewSrc/index.ts @@ -1,9 +1,11 @@ // import { Color, Face3, MeshBasicMaterial, Object3D, Vector2, Vector3 } from "three"; // import "./style.css"; -import { data } from "../data"; -import { Viewer } from "../Viewer"; +import { Vector3 } from "three"; import { CameraControlState } from "../CameraControls"; +import { data } from "../data"; +import { GetBox } from "../GeUtils"; import { LoadBoard } from "../Utils"; +import { Viewer } from "../Viewer"; let btn = document.createElement("button"); btn.innerHTML = "载入" @@ -13,6 +15,10 @@ let btn2 = document.createElement("button"); btn2.innerHTML = "清理" document.body.appendChild(btn2); +let btn3 = document.createElement("button"); +btn3.innerHTML = "爆炸图" +document.body.appendChild(btn3); + let el = document.createElement("canvas"); el.style.width = "80%"; @@ -39,3 +45,51 @@ btn2.onclick = () => { // LoadBoard(view, []); } + +btn3.onclick = () => +{ + let box = GetBox(view.m_Scene); + + let cen = box.getCenter(new Vector3()); + let m = []; + for (let obj of view.m_Scene.children) + { + if (obj.userData && obj.userData instanceof Vector3) + { + let objCen = GetBox(obj).getCenter(new Vector3()); + + let v = objCen.clone().sub(cen); + + let zv = obj.userData as Vector3; + if (zv instanceof Vector3) + { + let d = zv.dot(v); + // m.set(obj, zv.clone().multiplyScalar(d)); + m.push([obj, zv.clone().multiplyScalar(d)]); + } + } + } + + + let count = 0; + + let t = setInterval(() => + { + for (let [o, v] of m) + { + o.position.add( + v.clone().multiplyScalar(1.5 / 120) + ); + o.updateMatrix(); + } + + view.ZoomAll(); + + view.m_bNeedUpdate = true; + + count++; + + if (count === 60) + clearInterval(t); + }, 16) +} diff --git a/src/createBoard.ts b/src/createBoard.ts index 696b094..047706b 100644 --- a/src/createBoard.ts +++ b/src/createBoard.ts @@ -90,16 +90,14 @@ export function createBoard(boardData: object) let boardMat = new THREE.Matrix4(); let matInv: THREE.Matrix4 = new THREE.Matrix4(); //InitBoardMat - { - let xD = getVec(boardData["XVec"]); - let yD = getVec(boardData["YVec"]); - let ZD = getVec(boardData["ZVec"]); - let pBase = getVec(boardData["BasePoint"]); + let xD = getVec(boardData["XVec"]); + let yD = getVec(boardData["YVec"]); + let ZD = getVec(boardData["ZVec"]); + let pBase = getVec(boardData["BasePoint"]); - boardMat.makeBasis(xD, yD, ZD); - boardMat.setPosition(pBase); - matInv.getInverse(boardMat, true); - } + boardMat.makeBasis(xD, yD, ZD); + boardMat.setPosition(pBase); + matInv.getInverse(boardMat, true); if (boardPts && boardPts.length !== 0) for (let i = 0; i < boardPts.length; i++) @@ -188,6 +186,8 @@ export function createBoard(boardData: object) RotateUVs(ext); let mesh = new THREE.Mesh(ext, boardMaterial); + mesh.userData = ZD; + edges.forEach(e => e.userData = ZD); return { mesh, edges }; }