完成下列功能:
1.板件显示 2.板件选中状态 3.标注显示 4.相机控制.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/node_modules
|
||||
/dist
|
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "启动 Chrome 并打开 localhost",
|
||||
"url": "http://localhost:666",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"editor.formatOnSave": true
|
||||
}
|
6939
package-lock.json
generated
Normal file
6939
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
package.json
Normal file
20
package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "cadview",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^10.1.2",
|
||||
"@types/three": "^0.92.0",
|
||||
"typescript": "^2.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"three": "^0.92.0"
|
||||
}
|
||||
}
|
249
src/CameraControls.ts
Normal file
249
src/CameraControls.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
import { KeyBoard, MouseKey } from './KeyEnum';
|
||||
import { Vector3 } from 'three';
|
||||
import { Viewer } from './Viewer';
|
||||
|
||||
//控制类型
|
||||
enum CameraControlsEnabled
|
||||
{
|
||||
Rotate = 1,
|
||||
Zoom = 2,
|
||||
Pan = 4,
|
||||
}
|
||||
|
||||
//相机控制状态
|
||||
export enum CameraControlState
|
||||
{
|
||||
Null = 0, Pan = 1, Rotate = 2, Scale = 3
|
||||
}
|
||||
|
||||
export class CameraControls
|
||||
{
|
||||
m_TouthTypeList = [CameraControlState.Rotate, CameraControlState.Scale, CameraControlState.Pan];
|
||||
m_domElement: HTMLElement;//HTMLDocument
|
||||
//起始点击
|
||||
m_StartClickPoint: THREE.Vector3 = new THREE.Vector3();
|
||||
m_EndClickPoint: THREE.Vector3 = new THREE.Vector3();
|
||||
m_DollyStart: THREE.Vector2 = new THREE.Vector2();
|
||||
m_DollyEnd: THREE.Vector2 = new THREE.Vector2();
|
||||
|
||||
m_KeyDown = new Map<KeyBoard, boolean>();
|
||||
m_MouseDown = new Map<MouseKey, boolean>();
|
||||
|
||||
//状态
|
||||
m_State: CameraControlState = CameraControlState.Null;
|
||||
m_Viewer: Viewer;
|
||||
//左键使用旋转
|
||||
m_LeftUseRotate: boolean = true;
|
||||
|
||||
constructor(viewer: Viewer)
|
||||
{
|
||||
this.m_Viewer = viewer;
|
||||
this.m_domElement = viewer.m_Render.domElement.parentElement;
|
||||
this.RegisterEvent();
|
||||
}
|
||||
|
||||
RegisterEvent()
|
||||
{
|
||||
if (this.m_domElement)
|
||||
{
|
||||
this.m_domElement.addEventListener("mousedown", this.onMouseDown, false)
|
||||
this.m_domElement.addEventListener("mousemove", this.onMouseMove, false)
|
||||
this.m_domElement.addEventListener("mouseup", this.onMouseUp, false)
|
||||
window.addEventListener("keydown", this.onKeyDown, false);
|
||||
window.addEventListener("keyup", this.onKeyUp, false);
|
||||
this.m_domElement.addEventListener('wheel', this.onMouseWheel, false);
|
||||
|
||||
this.m_domElement.addEventListener('touchstart', this.onTouchStart, false);
|
||||
this.m_domElement.addEventListener('touchend', this.onTouchEnd, false);
|
||||
this.m_domElement.addEventListener('touchmove', this.onTouchMove, false);
|
||||
|
||||
window.addEventListener("blur", this.onBlur, false);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 窗体失去焦点时.
|
||||
*
|
||||
* @memberof CameraControls
|
||||
*/
|
||||
onBlur = () =>
|
||||
{
|
||||
this.m_KeyDown.clear();
|
||||
this.m_MouseDown.clear();
|
||||
}
|
||||
|
||||
//触屏开始事件
|
||||
onTouchStart = (event: TouchEvent) =>
|
||||
{
|
||||
this.m_Viewer.UpdateLockTarget();
|
||||
this.m_StartClickPoint.set(event.touches[0].pageX, event.touches[0].pageY, 0);
|
||||
if (event.touches.length < 4)
|
||||
{
|
||||
if (event.touches.length == 2)
|
||||
{
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
this.m_DollyStart.set(0, distance);
|
||||
}
|
||||
this.m_State = this.m_TouthTypeList[event.touches.length - 1];
|
||||
}
|
||||
}
|
||||
onTouchEnd = (event: TouchEvent) =>
|
||||
{
|
||||
this.m_State = CameraControlState.Null;
|
||||
}
|
||||
onTouchMove = (event: TouchEvent) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.m_EndClickPoint.set(event.touches[0].pageX, event.touches[0].pageY, 0);
|
||||
|
||||
let vec = this.m_EndClickPoint.clone().sub(this.m_StartClickPoint);
|
||||
switch (this.m_State)
|
||||
{
|
||||
case CameraControlState.Pan:
|
||||
{
|
||||
this.m_Viewer.Pan(vec);
|
||||
break;
|
||||
}
|
||||
case CameraControlState.Scale:
|
||||
{
|
||||
var dx = event.touches[0].pageX - event.touches[1].pageX;
|
||||
var dy = event.touches[0].pageY - event.touches[1].pageY;
|
||||
|
||||
var distance = Math.sqrt(dx * dx + dy * dy);
|
||||
this.m_DollyEnd.set(0, distance);
|
||||
if (distance > this.m_DollyStart.y)
|
||||
{
|
||||
this.m_Viewer.Zoom(0.95);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_Viewer.Zoom(1.05)
|
||||
}
|
||||
this.m_DollyStart.copy(this.m_DollyEnd);
|
||||
break;
|
||||
}
|
||||
case CameraControlState.Rotate:
|
||||
{
|
||||
this.m_Viewer.Rotate(vec.multiplyScalar(2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.m_StartClickPoint.copy(this.m_EndClickPoint);
|
||||
this.m_Viewer.m_bNeedUpdate = true;
|
||||
}
|
||||
beginRotate()
|
||||
{
|
||||
this.m_State = CameraControlState.Rotate;
|
||||
this.m_Viewer.UpdateLockTarget();
|
||||
}
|
||||
//鼠标
|
||||
onMouseDown = (event: MouseEvent) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
let key: MouseKey = event.button;
|
||||
this.m_MouseDown.set(key, true);
|
||||
this.m_StartClickPoint.set(event.offsetX, event.offsetY, 0);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case MouseKey.Left:
|
||||
{
|
||||
if (this.m_LeftUseRotate)
|
||||
{
|
||||
this.beginRotate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MouseKey.Middle:
|
||||
{
|
||||
if (this.m_KeyDown.get(KeyBoard.Control))
|
||||
{
|
||||
this.beginRotate();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_State = CameraControlState.Pan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MouseKey.Right:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
onMouseUp = (event: MouseEvent) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
this.m_State = CameraControlState.Null;
|
||||
this.m_MouseDown.set(event.button, false);
|
||||
}
|
||||
onMouseMove = (event: MouseEvent) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
this.m_EndClickPoint.set(event.offsetX, event.offsetY, 0);
|
||||
let changeVec = this.m_EndClickPoint.clone().sub(this.m_StartClickPoint);
|
||||
this.m_StartClickPoint.copy(this.m_EndClickPoint);
|
||||
if (
|
||||
(this.m_LeftUseRotate ||
|
||||
(this.m_KeyDown.get(KeyBoard.Control))
|
||||
)
|
||||
&& this.m_State == CameraControlState.Rotate
|
||||
)
|
||||
{
|
||||
this.m_Viewer.Rotate(changeVec);
|
||||
}
|
||||
switch (this.m_State)
|
||||
{
|
||||
case CameraControlState.Pan:
|
||||
{
|
||||
this.m_Viewer.Pan(changeVec);
|
||||
break;
|
||||
}
|
||||
case CameraControlState.Rotate:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CameraControlState.Scale:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 鼠标滚轮事件
|
||||
*
|
||||
* @memberof CameraControls
|
||||
*/
|
||||
onMouseWheel = (event: WheelEvent) =>
|
||||
{
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
let pt = new THREE.Vector3(event.offsetX, event.offsetY, 0);
|
||||
|
||||
this.m_Viewer.ScreenToWorld(pt, new Vector3().setFromMatrixColumn(this.m_Viewer.m_Camera.Camera.matrixWorld, 2));
|
||||
if (event.deltaY < 0)
|
||||
{
|
||||
this.m_Viewer.Zoom(0.6, pt);
|
||||
}
|
||||
else if (event.deltaY > 0)
|
||||
{
|
||||
this.m_Viewer.Zoom(1.4, pt);
|
||||
}
|
||||
}
|
||||
//按键
|
||||
onKeyDown = (event: KeyboardEvent) =>
|
||||
{
|
||||
this.m_KeyDown.set(event.keyCode, true);
|
||||
}
|
||||
onKeyUp = (event: KeyboardEvent) =>
|
||||
{
|
||||
this.m_KeyDown.set(event.keyCode, false);
|
||||
}
|
||||
}
|
220
src/CameraUpdate.ts
Normal file
220
src/CameraUpdate.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import * as THREE from 'three';
|
||||
import { Vector3 } from 'three';
|
||||
import { Orbit } from './Orbit';
|
||||
|
||||
/**
|
||||
*
|
||||
* 相机的控制.
|
||||
* ->切换相机
|
||||
* ->设置视口大小
|
||||
* ->旋转和移动相机.
|
||||
*
|
||||
* @export
|
||||
* @class ViewCameraManage
|
||||
*/
|
||||
export class CameraUpdate
|
||||
{
|
||||
private m_CurCamera: THREE.Camera;
|
||||
private m_CameraArray: Map<any, THREE.Camera> = new Map<any, THREE.Camera>();
|
||||
|
||||
//视口的画布大小
|
||||
private m_Width: number;
|
||||
private m_Height: number;
|
||||
//视口显示的高度
|
||||
private m_ViewHeight: number = 10;
|
||||
|
||||
//观察的位置
|
||||
private m_Target: THREE.Vector3 = new THREE.Vector3();
|
||||
//观察向量
|
||||
private m_Direction: THREE.Vector3 = new THREE.Vector3(0, 0, -1);
|
||||
//观察的轨道.
|
||||
private m_Orbit: Orbit = new Orbit();
|
||||
|
||||
constructor()
|
||||
{
|
||||
this.m_CameraArray.set(THREE.OrthographicCamera, new THREE.OrthographicCamera(-2, 2, 2, -2,
|
||||
-100000, 100000));
|
||||
|
||||
this.m_CameraArray.set(THREE.PerspectiveCamera, new THREE.PerspectiveCamera(50, 1, 0.01, 10000));
|
||||
|
||||
this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera);
|
||||
|
||||
this.m_Orbit.UpdateRoValue(this.m_Direction);
|
||||
|
||||
this.UpdateUp();
|
||||
|
||||
this.Update();
|
||||
}
|
||||
get Aspect(): number
|
||||
{
|
||||
return this.m_Width / this.m_Height;
|
||||
}
|
||||
|
||||
get Camera(): THREE.Camera
|
||||
{
|
||||
return this.m_CurCamera;
|
||||
}
|
||||
get ViewHeight()
|
||||
{
|
||||
return this.m_ViewHeight;
|
||||
}
|
||||
set ViewHeight(height)
|
||||
{
|
||||
this.m_ViewHeight = THREE.Math.clamp(height, 1e-8, 1e8);
|
||||
}
|
||||
|
||||
SetSize(width: number, height: number)
|
||||
{
|
||||
this.m_Width = width;
|
||||
this.m_Height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平移相机.
|
||||
*
|
||||
* @param {THREE.Vector3} mouseMove
|
||||
* @memberof CameraControl
|
||||
*/
|
||||
Pan(mouseMove: THREE.Vector3)
|
||||
{
|
||||
mouseMove.y *= -1;
|
||||
mouseMove.multiplyScalar(-this.m_ViewHeight / this.m_Height);
|
||||
mouseMove.applyQuaternion(this.Camera.quaternion);
|
||||
this.m_Target.add(mouseMove);
|
||||
this.Update();
|
||||
}
|
||||
Rotate(mouseMove: THREE.Vector3, target: THREE.Vector3)
|
||||
{
|
||||
this.m_Orbit.RoX -= mouseMove.y * 0.003;
|
||||
this.m_Orbit.RoZ -= mouseMove.x * 0.003;
|
||||
|
||||
//缓存观察点
|
||||
let oldTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse);
|
||||
|
||||
this.m_Orbit.UpdateDirection(this.m_Direction);
|
||||
this.UpdateUp();
|
||||
this.Update();
|
||||
|
||||
//-----还原观察点
|
||||
//得到新的观察点相对于相机的位置
|
||||
let newTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse);
|
||||
//减去原先的位置. 得到观测点在相机内移动的向量
|
||||
newTargetFormCameraSpace.sub(oldTargetFormCameraSpace);
|
||||
//乘以相机的矩阵. 得到向量在世界坐标系的位置
|
||||
newTargetFormCameraSpace.applyMatrix4(this.Camera.matrix);
|
||||
//因为使用的是点变换,所以减去基点,得到向量
|
||||
newTargetFormCameraSpace.sub(this.Camera.position);
|
||||
//加上移动的向量. 使得观察点时钟在相机的某个位置
|
||||
this.m_Target.add(newTargetFormCameraSpace);
|
||||
|
||||
this.Update();
|
||||
}
|
||||
Zoom(scale: number, scaleCenter?: THREE.Vector3)
|
||||
{
|
||||
if (this.Camera instanceof THREE.OrthographicCamera)
|
||||
{
|
||||
this.ViewHeight *= scale;
|
||||
if (scaleCenter)
|
||||
{
|
||||
this.m_Target.sub(scaleCenter);
|
||||
this.m_Target.multiplyScalar(scale);
|
||||
this.m_Target.add(scaleCenter);
|
||||
}
|
||||
}
|
||||
else if (this.Camera instanceof THREE.PerspectiveCamera)
|
||||
{
|
||||
let add = scale > 1 ? 1 : -1;
|
||||
add *= this.Camera.position.distanceTo(this.m_Target) / 10;
|
||||
this.m_Target.add(this.m_Direction.clone().multiplyScalar(-add));
|
||||
}
|
||||
this.Update();
|
||||
}
|
||||
ZoomExtensBox3(box3: THREE.Box3)
|
||||
{
|
||||
if (!box3) return;
|
||||
this.Camera.updateMatrixWorld(false);
|
||||
//变换到相机坐标系
|
||||
box3.applyMatrix4(this.Camera.matrixWorldInverse);
|
||||
//
|
||||
box3.getCenter(this.m_Target);
|
||||
//世界坐标系
|
||||
this.m_Target.applyMatrix4(this.Camera.matrix);
|
||||
//size
|
||||
let size = box3.getSize(new Vector3());
|
||||
//宽高比
|
||||
let aspectRatio = size.x / size.y;
|
||||
|
||||
let viewAspectRatio = this.Aspect;
|
||||
//
|
||||
if (aspectRatio > viewAspectRatio)
|
||||
{
|
||||
this.m_ViewHeight = size.x / viewAspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_ViewHeight = size.y;
|
||||
}
|
||||
this.Update();
|
||||
}
|
||||
LookAt(dir: THREE.Vector3)
|
||||
{
|
||||
this.m_Orbit.UpdateRoValue(dir);
|
||||
this.m_Direction.copy(dir);
|
||||
this.UpdateUp();
|
||||
this.Update();
|
||||
}
|
||||
|
||||
UpdateUp()
|
||||
{
|
||||
Orbit.ComputUpDirection(this.m_Direction, this.Camera.up);
|
||||
}
|
||||
/**
|
||||
* 根据视口大小,设置相机视口范围.
|
||||
*
|
||||
* @returns
|
||||
* @memberof CameraControl
|
||||
*/
|
||||
Update()
|
||||
{
|
||||
this.Camera.position.copy(this.m_Target);
|
||||
|
||||
if (this.Camera instanceof THREE.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 THREE.PerspectiveCamera)
|
||||
{
|
||||
this.Camera.aspect = this.Aspect;
|
||||
let distens = (this.m_ViewHeight / 2) / (Math.tan(THREE.Math.degToRad(this.Camera.fov) / 2));
|
||||
|
||||
this.Camera.position.sub(this.m_Direction.clone().multiplyScalar(distens));
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.Camera.lookAt(this.m_Target);
|
||||
this.Camera.updateProjectionMatrix();
|
||||
this.Camera.updateMatrixWorld(false);
|
||||
}
|
||||
|
||||
SwitchCamera()
|
||||
{
|
||||
if (this.Camera instanceof THREE.OrthographicCamera)
|
||||
{
|
||||
this.m_CurCamera = this.m_CameraArray.get(THREE.PerspectiveCamera);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera);
|
||||
}
|
||||
this.UpdateUp();
|
||||
this.Update();
|
||||
}
|
||||
}
|
288
src/ColorPalette.ts
Normal file
288
src/ColorPalette.ts
Normal file
@@ -0,0 +1,288 @@
|
||||
import * as THREE from 'three';
|
||||
const ColorPalette = [
|
||||
[255, 0, 0, 255], //----- 0 - lets make it red for an example
|
||||
//[255, 255, 255, 255],//----- 0 - ByBlock - White
|
||||
[255, 0, 0, 255], //----- 1 - Red
|
||||
// [255, 0, 0, 255], //----- 1 - Red
|
||||
[255, 255, 0, 255], //----- 2 - Yellow
|
||||
[0, 255, 0, 255], //----- 3 - Green
|
||||
[0, 255, 255, 255], //----- 4 - Cyan
|
||||
[0, 0, 255, 255], //----- 5 - Blue
|
||||
[255, 0, 255, 255], //----- 6 - Magenta
|
||||
// [255, 0, 0, 255], //----- 7 - More red Red
|
||||
// [255, 0, 0, 255], //----- 8 - More red Red
|
||||
// [255, 0, 0, 255], //----- 9 - More red Red
|
||||
[255, 255, 255, 255],//----- 7 - White
|
||||
[255, 255, 255, 255],//----- 8
|
||||
[255, 255, 255, 255],//----- 9
|
||||
[255, 0, 0, 255], //----- 10
|
||||
[255, 127, 127, 255],//----- 11
|
||||
[165, 0, 0, 255], //----- 12
|
||||
[165, 82, 82, 255], //----- 13
|
||||
[127, 0, 0, 255], //----- 14
|
||||
[127, 63, 63, 255], //----- 15
|
||||
[76, 0, 0, 255], //----- 16
|
||||
[76, 38, 38, 255], //----- 17
|
||||
[38, 0, 0, 255], //----- 18
|
||||
[38, 19, 19, 255], //----- 19
|
||||
[255, 63, 0, 255], //----- 20
|
||||
[255, 159, 127, 255],//----- 21
|
||||
[165, 41, 0, 255], //----- 22
|
||||
[165, 103, 82, 255], //----- 23
|
||||
[127, 31, 0, 255], //----- 24
|
||||
[127, 79, 63, 255], //----- 25
|
||||
[76, 19, 0, 255], //----- 26
|
||||
[76, 47, 38, 255], //----- 27
|
||||
[38, 9, 0, 255], //----- 28
|
||||
[38, 23, 19, 255], //----- 29
|
||||
[255, 127, 0, 255], //----- 30
|
||||
[255, 191, 127, 255],//----- 31
|
||||
[165, 82, 0, 255], //----- 32
|
||||
[165, 124, 82, 255], //----- 33
|
||||
[127, 63, 0, 255], //----- 34
|
||||
[127, 95, 63, 255], //----- 35
|
||||
[76, 38, 0, 255], //----- 36
|
||||
[76, 57, 38, 255], //----- 37
|
||||
[38, 19, 0, 255], //----- 38
|
||||
[38, 28, 19, 255], //----- 39
|
||||
[255, 191, 0, 255], //----- 40
|
||||
[255, 223, 127, 255],//----- 41
|
||||
[165, 124, 0, 255], //----- 42
|
||||
[165, 145, 82, 255], //----- 43
|
||||
[127, 95, 0, 255], //----- 44
|
||||
[127, 111, 63, 255], //----- 45
|
||||
[76, 57, 0, 255], //----- 46
|
||||
[76, 66, 38, 255], //----- 47
|
||||
[38, 28, 0, 255], //----- 48
|
||||
[38, 33, 19, 255], //----- 49
|
||||
[255, 255, 0, 255], //----- 50
|
||||
[255, 255, 127, 255],//----- 51
|
||||
[165, 165, 0, 255], //----- 52
|
||||
[165, 165, 82, 255], //----- 53
|
||||
[127, 127, 0, 255], //----- 54
|
||||
[127, 127, 63, 255], //----- 55
|
||||
[76, 76, 0, 255], //----- 56
|
||||
[76, 76, 38, 255], //----- 57
|
||||
[38, 38, 0, 255], //----- 58
|
||||
[38, 38, 19, 255], //----- 59
|
||||
[191, 255, 0, 255], //----- 60
|
||||
[223, 255, 127, 255],//----- 61
|
||||
[124, 165, 0, 255], //----- 62
|
||||
[145, 165, 82, 255], //----- 63
|
||||
[95, 127, 0, 255], //----- 64
|
||||
[111, 127, 63, 255], //----- 65
|
||||
[57, 76, 0, 255], //----- 66
|
||||
[66, 76, 38, 255], //----- 67
|
||||
[28, 38, 0, 255], //----- 68
|
||||
[33, 38, 19, 255], //----- 69
|
||||
[127, 255, 0, 255], //----- 70
|
||||
[191, 255, 127, 255],//----- 71
|
||||
[82, 165, 0, 255], //----- 72
|
||||
[124, 165, 82, 255], //----- 73
|
||||
[63, 127, 0, 255], //----- 74
|
||||
[95, 127, 63, 255], //----- 75
|
||||
[38, 76, 0, 255], //----- 76
|
||||
[57, 76, 38, 255], //----- 77
|
||||
[19, 38, 0, 255], //----- 78
|
||||
[28, 38, 19, 255], //----- 79
|
||||
[63, 255, 0, 255], //----- 80
|
||||
[159, 255, 127, 255],//----- 81
|
||||
[41, 165, 0, 255], //----- 82
|
||||
[103, 165, 82, 255], //----- 83
|
||||
[31, 127, 0, 255], //----- 84
|
||||
[79, 127, 63, 255], //----- 85
|
||||
[19, 76, 0, 255], //----- 86
|
||||
[47, 76, 38, 255], //----- 87
|
||||
[9, 38, 0, 255], //----- 88
|
||||
[23, 38, 19, 255], //----- 89
|
||||
[0, 255, 0, 255], //----- 90
|
||||
[127, 255, 127, 255],//----- 91
|
||||
[0, 165, 0, 255], //----- 92
|
||||
[82, 165, 82, 255], //----- 93
|
||||
[0, 127, 0, 255], //----- 94
|
||||
[63, 127, 63, 255], //----- 95
|
||||
[0, 76, 0, 255], //----- 96
|
||||
[38, 76, 38, 255], //----- 97
|
||||
[0, 38, 0, 255], //----- 98
|
||||
[19, 38, 19, 255], //----- 99
|
||||
[0, 255, 63, 255], //----- 100
|
||||
[127, 255, 159, 255],//----- 101
|
||||
[0, 165, 41, 255], //----- 102
|
||||
[82, 165, 103, 255], //----- 103
|
||||
[0, 127, 31, 255], //----- 104
|
||||
[63, 127, 79, 255], //----- 105
|
||||
[0, 76, 19, 255], //----- 106
|
||||
[38, 76, 47, 255], //----- 107
|
||||
[0, 38, 9, 255], //----- 108
|
||||
[19, 38, 23, 255], //----- 109
|
||||
[0, 255, 127, 255], //----- 110
|
||||
[127, 255, 191, 255],//----- 111
|
||||
[0, 165, 82, 255], //----- 112
|
||||
[82, 165, 124, 255], //----- 113
|
||||
[0, 127, 63, 255], //----- 114
|
||||
[63, 127, 95, 255], //----- 115
|
||||
[0, 76, 38, 255], //----- 116
|
||||
[38, 76, 57, 255], //----- 117
|
||||
[0, 38, 19, 255], //----- 118
|
||||
[19, 38, 28, 255], //----- 119
|
||||
[0, 255, 191, 255], //----- 120
|
||||
[127, 255, 223, 255],//----- 121
|
||||
[0, 165, 124, 255], //----- 122
|
||||
[82, 165, 145, 255], //----- 123
|
||||
[0, 127, 95, 255], //----- 124
|
||||
[63, 127, 111, 255], //----- 125
|
||||
[0, 76, 57, 255], //----- 126
|
||||
[38, 76, 66, 255], //----- 127
|
||||
[0, 38, 28, 255], //----- 128
|
||||
[19, 38, 33, 255], //----- 129
|
||||
[0, 255, 255, 255], //----- 130
|
||||
[127, 255, 255, 255],//----- 131
|
||||
[0, 165, 165, 255], //----- 132
|
||||
[82, 165, 165, 255], //----- 133
|
||||
[0, 127, 127, 255], //----- 134
|
||||
[63, 127, 127, 255], //----- 135
|
||||
[0, 76, 76, 255], //----- 136
|
||||
[38, 76, 76, 255], //----- 137
|
||||
[0, 38, 38, 255], //----- 138
|
||||
[19, 38, 38, 255], //----- 139
|
||||
[0, 191, 255, 255], //----- 140
|
||||
[127, 223, 255, 255],//----- 141
|
||||
[0, 124, 165, 255], //----- 142
|
||||
[82, 145, 165, 255], //----- 143
|
||||
[0, 95, 127, 255], //----- 144
|
||||
[63, 111, 127, 255], //----- 145
|
||||
[0, 57, 76, 255], //----- 146
|
||||
[38, 66, 76, 255], //----- 147
|
||||
[0, 28, 38, 255], //----- 148
|
||||
[19, 33, 38, 255], //----- 149
|
||||
[0, 127, 255, 255], //----- 150
|
||||
[127, 191, 255, 255],//----- 151
|
||||
[0, 82, 165, 255], //----- 152
|
||||
[82, 124, 165, 255], //----- 153
|
||||
[0, 63, 127, 255], //----- 154
|
||||
[63, 95, 127, 255], //----- 155
|
||||
[0, 38, 76, 255], //----- 156
|
||||
[38, 57, 76, 255], //----- 157
|
||||
[0, 19, 38, 255], //----- 158
|
||||
[19, 28, 38, 255], //----- 159
|
||||
[0, 63, 255, 255], //----- 160
|
||||
[127, 159, 255, 255],//----- 161
|
||||
[0, 41, 165, 255], //----- 162
|
||||
[82, 103, 165, 255], //----- 163
|
||||
[0, 31, 127, 255], //----- 164
|
||||
[63, 79, 127, 255], //----- 165
|
||||
[0, 19, 76, 255], //----- 166
|
||||
[38, 47, 76, 255], //----- 167
|
||||
[0, 9, 38, 255], //----- 168
|
||||
[19, 23, 38, 255], //----- 169
|
||||
[0, 0, 255, 255], //----- 170
|
||||
[127, 127, 255, 255],//----- 171
|
||||
[0, 0, 165, 255], //----- 172
|
||||
[82, 82, 165, 255], //----- 173
|
||||
[0, 0, 127, 255], //----- 174
|
||||
[63, 63, 127, 255], //----- 175
|
||||
[0, 0, 76, 255], //----- 176
|
||||
[38, 38, 76, 255], //----- 177
|
||||
[0, 0, 38, 255], //----- 178
|
||||
[19, 19, 38, 255], //----- 179
|
||||
[63, 0, 255, 255], //----- 180
|
||||
[159, 127, 255, 255],//----- 181
|
||||
[41, 0, 165, 255], //----- 182
|
||||
[103, 82, 165, 255], //----- 183
|
||||
[31, 0, 127, 255], //----- 184
|
||||
[79, 63, 127, 255], //----- 185
|
||||
[19, 0, 76, 255], //----- 186
|
||||
[47, 38, 76, 255], //----- 187
|
||||
[9, 0, 38, 255], //----- 188
|
||||
[23, 19, 38, 255], //----- 189
|
||||
[127, 0, 255, 255], //----- 190
|
||||
[191, 127, 255, 255],//----- 191
|
||||
[82, 0, 165, 255], //----- 192
|
||||
[124, 82, 165, 255], //----- 193
|
||||
[63, 0, 127, 255], //----- 194
|
||||
[95, 63, 127, 255], //----- 195
|
||||
[38, 0, 76, 255], //----- 196
|
||||
[57, 38, 76, 255], //----- 197
|
||||
[19, 0, 38, 255], //----- 198
|
||||
[28, 19, 38, 255], //----- 199
|
||||
[191, 0, 255, 255], //----- 200
|
||||
[223, 127, 255, 255],//----- 201
|
||||
[124, 0, 165, 255], //----- 202
|
||||
[145, 82, 165, 255], //----- 203
|
||||
[95, 0, 127, 255], //----- 204
|
||||
[111, 63, 127, 255], //----- 205
|
||||
[57, 0, 76, 255], //----- 206
|
||||
[66, 38, 76, 255], //----- 207
|
||||
[28, 0, 38, 255], //----- 208
|
||||
[33, 19, 38, 255], //----- 209
|
||||
[255, 0, 255, 255], //----- 210
|
||||
[255, 127, 255, 255],//----- 211
|
||||
[165, 0, 165, 255], //----- 212
|
||||
[165, 82, 165, 255], //----- 213
|
||||
[127, 0, 127, 255], //----- 214
|
||||
[127, 63, 127, 255], //----- 215
|
||||
[76, 0, 76, 255], //----- 216
|
||||
[76, 38, 76, 255], //----- 217
|
||||
[38, 0, 38, 255], //----- 218
|
||||
[38, 19, 38, 255], //----- 219
|
||||
[255, 0, 191, 255], //----- 220
|
||||
[255, 127, 223, 255],//----- 221
|
||||
[165, 0, 124, 255], //----- 222
|
||||
[165, 82, 145, 255], //----- 223
|
||||
[127, 0, 95, 255], //----- 224
|
||||
[127, 63, 111, 255], //----- 225
|
||||
[76, 0, 57, 255], //----- 226
|
||||
[76, 38, 66, 255], //----- 227
|
||||
[38, 0, 28, 255], //----- 228
|
||||
[38, 19, 33, 255], //----- 229
|
||||
[255, 0, 127, 255], //----- 230
|
||||
[255, 127, 191, 255],//----- 231
|
||||
[165, 0, 82, 255], //----- 232
|
||||
[165, 82, 124, 255], //----- 233
|
||||
[127, 0, 63, 255], //----- 234
|
||||
[127, 63, 95, 255], //----- 235
|
||||
[76, 0, 38, 255], //----- 236
|
||||
[76, 38, 57, 255], //----- 237
|
||||
[38, 0, 19, 255], //----- 238
|
||||
[38, 19, 28, 255], //----- 239
|
||||
[255, 0, 63, 255], //----- 240
|
||||
[255, 127, 159, 255],//----- 241
|
||||
[165, 0, 41, 255], //----- 242
|
||||
[165, 82, 103, 255], //----- 243
|
||||
[127, 0, 31, 255], //----- 244
|
||||
[127, 63, 79, 255], //----- 245
|
||||
[76, 0, 19, 255], //----- 246
|
||||
[76, 38, 47, 255], //----- 247
|
||||
[38, 0, 9, 255], //----- 248
|
||||
[38, 19, 23, 255], //----- 249
|
||||
[84, 84, 84, 255], //----- 250
|
||||
[118, 118, 118, 255],//----- 251
|
||||
[152, 152, 152, 255],//----- 252
|
||||
[186, 186, 186, 255],//----- 253
|
||||
[220, 220, 220, 255],//----- 254
|
||||
[255, 255, 255, 255],//----- 255
|
||||
[255, 255, 255, 255] //----- ByLayer - White
|
||||
];
|
||||
|
||||
|
||||
//颜色材质,对于二维图像来说可能有用,应该不对三维对象使用该材质
|
||||
export class ColorMaterial
|
||||
{
|
||||
private constructor() { }
|
||||
private static m_LineMaterialMap = new Map<number, THREE.LineBasicMaterial>();
|
||||
static GetLineMaterial(index): THREE.LineBasicMaterial
|
||||
{
|
||||
if (this.m_LineMaterialMap.has(index))
|
||||
return this.m_LineMaterialMap.get(index);
|
||||
let mat = new THREE.LineBasicMaterial({ color: this.GetColor(index) });
|
||||
this.m_LineMaterialMap.set(index, mat);
|
||||
return mat;
|
||||
}
|
||||
|
||||
static GetColor(index: number)
|
||||
{
|
||||
let rgb = ColorPalette[index];
|
||||
if (rgb)
|
||||
return new THREE.Color(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255);
|
||||
}
|
||||
}
|
58
src/Dimension.ts
Normal file
58
src/Dimension.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Group, Geometry, Vector3, Line, Matrix4 } from "three";
|
||||
import { ColorMaterial } from "./ColorPalette";
|
||||
import { DbText } from "./Text";
|
||||
import { MoveMatrix } from "./GeUtils";
|
||||
|
||||
/**
|
||||
* 标注实体
|
||||
*
|
||||
* @export
|
||||
* @class Dimension
|
||||
* @extends {Group}
|
||||
*/
|
||||
export class Dimension extends Group
|
||||
{
|
||||
|
||||
constructor(length: number, textHeight: number = 25, mirror: boolean = false, mirrorFoot: boolean = false)
|
||||
{
|
||||
super();
|
||||
let footLength = 60;
|
||||
if (mirrorFoot)
|
||||
{
|
||||
footLength = -footLength;
|
||||
}
|
||||
|
||||
//针脚几何体
|
||||
let lineGeo = new Geometry();
|
||||
lineGeo.vertices.push(new Vector3(), new Vector3(0, footLength, 0));
|
||||
|
||||
//托盘几何体
|
||||
let lineGeo2 = new Geometry();
|
||||
lineGeo2.vertices.push(new Vector3(0, footLength), new Vector3(length, footLength, 0));
|
||||
|
||||
let material = ColorMaterial.GetLineMaterial(5)
|
||||
|
||||
let line1 = new Line(lineGeo, material);
|
||||
let line2 = new Line(lineGeo, material);
|
||||
line2.position.x = length;
|
||||
|
||||
let line3 = new Line(lineGeo2, material);
|
||||
|
||||
let text = new DbText(parseFloat(length.toFixed(2)).toString(), textHeight);
|
||||
if (mirror)
|
||||
{
|
||||
let roMat = new Matrix4().makeRotationZ(Math.PI);
|
||||
text.applyMatrix(roMat);
|
||||
text.applyMatrix(MoveMatrix(new Vector3(length * 0.5, footLength - textHeight * 0.1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
text.applyMatrix(MoveMatrix(new Vector3(length * 0.5, footLength * 1.1)));
|
||||
}
|
||||
|
||||
|
||||
this.add(text);
|
||||
|
||||
this.add(line1, line2, line3);
|
||||
}
|
||||
}
|
49
src/DrawDimension.ts
Normal file
49
src/DrawDimension.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Box3, Vector3, Matrix4, Mesh } from "three";
|
||||
import { Dimension, GetBoxArr } from ".";
|
||||
|
||||
|
||||
/**
|
||||
* 绘制标注实体
|
||||
*
|
||||
* @export
|
||||
* @param {Box3} box
|
||||
* @returns 标注实体列表
|
||||
*/
|
||||
export function DrawDimension(brList: Mesh[]): Dimension[]
|
||||
{
|
||||
let box = GetBoxArr(brList);
|
||||
let size = box.getSize(new Vector3());
|
||||
|
||||
let mat4 = new Matrix4();
|
||||
mat4.makeBasis(
|
||||
new Vector3(-1, 0, 0),
|
||||
new Vector3(0, -1, 0),
|
||||
new Vector3(0, 0, 1)
|
||||
)
|
||||
mat4.setPosition(box.min.clone().add(new Vector3(size.x, -30)));
|
||||
|
||||
let textHeight = 45;
|
||||
let dimx = new Dimension(size.x, textHeight, true);
|
||||
dimx.applyMatrix(mat4);
|
||||
|
||||
let dimz = new Dimension(size.z, textHeight);
|
||||
mat4.makeBasis(
|
||||
new Vector3(0, 0, -1),
|
||||
new Vector3(1, 0, 0),
|
||||
new Vector3(0, -1, 0)
|
||||
)
|
||||
mat4.setPosition(box.max.clone().add(new Vector3(30, -size.y)));
|
||||
dimz.applyMatrix(mat4);
|
||||
|
||||
let dimy = new Dimension(size.y, textHeight, true, true);
|
||||
mat4.makeBasis(
|
||||
new Vector3(0, 1, 0),
|
||||
new Vector3(-1, 0, 0),
|
||||
new Vector3(0, 0, 1)
|
||||
)
|
||||
mat4.setPosition(box.max.clone().add(new Vector3(30, -size.y)));
|
||||
dimy.applyMatrix(mat4);
|
||||
|
||||
|
||||
return [dimx, dimy, dimz];
|
||||
}
|
289
src/GeUtils.ts
Normal file
289
src/GeUtils.ts
Normal file
@@ -0,0 +1,289 @@
|
||||
import * as THREE from 'three';
|
||||
import { Geometry, Vector, Vector2, Vector3 } from 'three';
|
||||
import { Matrix2 } from './Matrix2';
|
||||
|
||||
|
||||
export const cZeroVec = new THREE.Vector3();
|
||||
export const cXAxis = new THREE.Vector3(1, 0, 0);
|
||||
export const cYAxis = new THREE.Vector3(0, 1, 0);
|
||||
export const cZAxis = new THREE.Vector3(0, 0, 1);
|
||||
|
||||
/**
|
||||
* 旋转一个点,旋转中心在原点
|
||||
*
|
||||
* @export
|
||||
* @param {Vector3} pt 点
|
||||
* @param {number} ang 角度.
|
||||
* @returns {Vector3} 返回pt不拷贝.
|
||||
*/
|
||||
export function rotatePoint(pt: Vector3, ang: number): Vector3
|
||||
{
|
||||
new Matrix2().setRotate(ang).applyVector(pt);
|
||||
return pt;
|
||||
}
|
||||
|
||||
export function equaln(v1: number, v2: number, fuzz = 1e-3)
|
||||
{
|
||||
return Math.abs(v1 - v2) < fuzz;
|
||||
}
|
||||
export function equal<T extends Vector>(v1: T, v2: T)
|
||||
{
|
||||
return v1.distanceToSquared(v2) < 1e-8;
|
||||
}
|
||||
|
||||
export function fixAngle(an: number, fixAngle: number, fuzz: number = 0.1)
|
||||
{
|
||||
if (an < 0)
|
||||
an += Math.PI * 2;
|
||||
an += fuzz;
|
||||
let rem = an % fixAngle;
|
||||
if (rem < fuzz * 2)
|
||||
{
|
||||
an -= rem;
|
||||
}
|
||||
else
|
||||
{
|
||||
an -= fuzz;
|
||||
}
|
||||
return an;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照极坐标的方式移动一个点
|
||||
*
|
||||
* @export
|
||||
* @template
|
||||
* @param {T} v 向量(2d,3d)
|
||||
* @param {number} an 角度
|
||||
* @param {number} dis 距离
|
||||
* @returns {T}
|
||||
*/
|
||||
export function polar<T extends Vector2 | Vector3>(v: T, an: number, dis: number): T
|
||||
{
|
||||
v.x += Math.cos(an) * dis;
|
||||
v.y += Math.sin(an) * dis;
|
||||
return v;
|
||||
}
|
||||
|
||||
export function angle(v: Vector3 | Vector2)
|
||||
{
|
||||
if (equaln(v.y, 0) && v.x > 0)
|
||||
return 0;
|
||||
let angle = Math.atan2(v.y, v.x);
|
||||
if (angle < 0) angle += Math.PI * 2;
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 求两个向量的夹角,顺时针为负,逆时针为正
|
||||
*
|
||||
* @param {THREE.Vector3} v1
|
||||
* @param {THREE.Vector3} v2
|
||||
* @param {THREE.Vector3} [ref] 参考向量,如果为世界坐标系则为0,0,1
|
||||
* @returns
|
||||
*/
|
||||
export function angleTo(v1: THREE.Vector3, v2: THREE.Vector3, ref: THREE.Vector3 = new THREE.Vector3(0, 0, 1))
|
||||
{
|
||||
if (!ref.equals(new Vector3(0, 0, 1)))
|
||||
{
|
||||
//任意轴坐标系. 使用相机的构造矩阵.
|
||||
ref.multiplyScalar(-1);
|
||||
let up = getLoocAtUpVec(ref);
|
||||
let refOcs = new THREE.Matrix4();
|
||||
refOcs.lookAt(cZeroVec, ref, up);
|
||||
let refOcsInv = new THREE.Matrix4().getInverse(refOcs);
|
||||
v1.applyMatrix4(refOcsInv);
|
||||
v2.applyMatrix4(refOcsInv);
|
||||
v1.z = 0;
|
||||
v2.z = 0;
|
||||
}
|
||||
if (v1.equals(cZeroVec) || v2.equals(cZeroVec))
|
||||
return 0;
|
||||
let cv = new Vector3().crossVectors(v1, v2).normalize();
|
||||
return cv.z === 0 ? v1.angleTo(v2) : v1.angleTo(v2) * cv.z;
|
||||
}
|
||||
|
||||
export function getLoocAtUpVec(dir: THREE.Vector3): THREE.Vector3
|
||||
{
|
||||
if (dir.equals(cZeroVec))
|
||||
{
|
||||
throw ("zero vector")
|
||||
}
|
||||
let norm = dir.clone().normalize();
|
||||
if (norm.equals(cZAxis))
|
||||
{
|
||||
return new THREE.Vector3(0, 1, 0);
|
||||
}
|
||||
else if (norm.equals(cZAxis.clone().negate()))
|
||||
{
|
||||
return new THREE.Vector3(0, -1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
let xv: THREE.Vector3 = new THREE.Vector3();
|
||||
xv.crossVectors(cZAxis, norm);
|
||||
|
||||
let up = new THREE.Vector3();
|
||||
up.crossVectors(norm, xv);
|
||||
return up;
|
||||
}
|
||||
}
|
||||
|
||||
export function createLookAtMat4(dir: THREE.Vector3): THREE.Matrix4
|
||||
{
|
||||
let up = getLoocAtUpVec(dir);
|
||||
let mat = new THREE.Matrix4();
|
||||
mat.lookAt(cZeroVec, dir, up);
|
||||
return mat;
|
||||
}
|
||||
|
||||
export function isParallelTo(v1: THREE.Vector3, v2: THREE.Vector3)
|
||||
{
|
||||
return v1.clone().cross(v2).lengthSq() < 1e-9;
|
||||
}
|
||||
|
||||
export function ptToString(v: THREE.Vector3, fractionDigits: number = 3): string
|
||||
{
|
||||
return v.toArray().map(o =>
|
||||
{
|
||||
return o.toFixed(fractionDigits)
|
||||
}).join(",")
|
||||
}
|
||||
|
||||
export function midPoint(v1: THREE.Vector3, v2: THREE.Vector3): THREE.Vector3
|
||||
{
|
||||
return v1.clone().add(v2).multiplyScalar(0.5);
|
||||
}
|
||||
export function midPoint2(v1: THREE.Vector2, v2: THREE.Vector2): THREE.Vector2
|
||||
{
|
||||
return v1.clone().add(v2).multiplyScalar(0.5);
|
||||
}
|
||||
|
||||
export function midPtCir(v1: THREE.Vector3, v2: THREE.Vector3)
|
||||
{
|
||||
let baseline = new Vector3(1, 0, 0);
|
||||
let outLine = v2.clone().sub(v1);
|
||||
let ang = angleTo(baseline, outLine) / 2;
|
||||
let midLine = rotatePoint(outLine, -ang);
|
||||
return v1.clone().add(midLine);
|
||||
}
|
||||
|
||||
export function GetBox(obj: THREE.Object3D, updateMatrix?: boolean): THREE.Box3
|
||||
{
|
||||
if (updateMatrix) obj.updateMatrixWorld(false);
|
||||
if (obj.hasOwnProperty("geometry"))
|
||||
{
|
||||
let geo = obj["geometry"];
|
||||
if (geo instanceof THREE.Geometry || geo instanceof THREE.BufferGeometry)
|
||||
{
|
||||
if (!geo.boundingBox)
|
||||
geo.computeBoundingBox();
|
||||
return geo.boundingBox.clone().applyMatrix4(obj.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;
|
||||
}
|
||||
|
||||
export function GetBoxArr(arr: Array<THREE.Object3D>): THREE.Box3
|
||||
{
|
||||
if (arr.length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
export function MoveMatrix(v: THREE.Vector3): THREE.Matrix4
|
||||
{
|
||||
let mat = new THREE.Matrix4();
|
||||
mat.makeTranslation(v.x, v.y, v.z);
|
||||
return mat;
|
||||
}
|
||||
|
||||
export function getProjectDist(v1: Vector3, v2: Vector3)
|
||||
{
|
||||
let ang = v1.angleTo(v2);
|
||||
let dist = v1.length();
|
||||
return {
|
||||
h: dist * Math.cos(ang),
|
||||
v: dist * Math.sin(ang)
|
||||
}
|
||||
}
|
||||
//获得输入点在2线组成的4个区间的位置
|
||||
export function getPtPostion(sp: Vector3, ep: Vector3, c: Vector3, inPt: Vector3)
|
||||
{
|
||||
let l1 = sp.clone().sub(c);
|
||||
let l2 = ep.clone().sub(c);
|
||||
let l3 = l1.clone().negate();
|
||||
let l4 = l2.clone().negate();
|
||||
let inputLine = inPt.clone().sub(c);
|
||||
let ang1 = angleTo(l1, l2);
|
||||
let ang2 = Math.PI;
|
||||
let ang3 = ang2 + Math.abs(ang1);
|
||||
let inputAng = angleTo(l1, inputLine);
|
||||
if (ang1 * inputAng < 0)
|
||||
{
|
||||
inputAng = (Math.PI * 2 - Math.abs(inputAng));
|
||||
}
|
||||
ang1 = Math.abs(ang1);
|
||||
inputAng = Math.abs(inputAng);
|
||||
if (inputAng <= ang1)
|
||||
{
|
||||
return { sp, ep };
|
||||
} else if (inputAng > ang1 && inputAng <= ang2)
|
||||
{
|
||||
return { sp: c.clone().add(l3), ep }
|
||||
} else if (inputAng > ang2 && inputAng <= ang3)
|
||||
{
|
||||
return { sp: c.clone().add(l3), ep: c.clone().add(l4) }
|
||||
} else
|
||||
{
|
||||
return { sp, ep: c.clone().add(l4) };
|
||||
}
|
||||
}
|
||||
export function angleAndX(v: Vector3 | Vector2)
|
||||
{
|
||||
return v.x ? Math.atan(v.y / v.x) : Math.PI / 2;
|
||||
}
|
||||
/**
|
||||
* 将角度调整为0-2pi之间
|
||||
*
|
||||
* @export
|
||||
* @param {number} an
|
||||
*/
|
||||
export function angleTo2Pi(an: number)
|
||||
{
|
||||
an = an % (Math.PI * 2);
|
||||
if (an < 0) an += Math.PI * 2
|
||||
return an;
|
||||
}
|
||||
export function updateGeometry(l: THREE.Line | THREE.Mesh, geometry: Geometry)
|
||||
{
|
||||
let geo = l.geometry as THREE.Geometry;
|
||||
geo.dispose();
|
||||
l.geometry = geometry;
|
||||
geometry.verticesNeedUpdate = true;
|
||||
geometry.computeBoundingSphere();
|
||||
}
|
164
src/KeyEnum.ts
Normal file
164
src/KeyEnum.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
//鼠标类型
|
||||
export enum MouseKey
|
||||
{
|
||||
Left = 0,
|
||||
Middle = 1,
|
||||
Right = 2,
|
||||
}
|
||||
|
||||
export enum KeyBoard
|
||||
{
|
||||
// 数字
|
||||
Digit1 = 49,
|
||||
Digit2 = 50,
|
||||
Digit3 = 51,
|
||||
Digit4 = 52,
|
||||
Digit5 = 53,
|
||||
Digit6 = 54,
|
||||
Digit7 = 55,
|
||||
Digit8 = 56,
|
||||
Digit9 = 57,
|
||||
Digit0 = 58,
|
||||
// 字母
|
||||
KeyA = 65,
|
||||
KeyB = 66,
|
||||
KeyC = 67,
|
||||
KeyD = 68,
|
||||
KeyE = 69,
|
||||
KeyF = 70,
|
||||
KeyG = 71,
|
||||
KeyH = 72,
|
||||
KeyI = 73,
|
||||
KeyJ = 74,
|
||||
KeyK = 75,
|
||||
KeyL = 76,
|
||||
KeyM = 77,
|
||||
KeyN = 78,
|
||||
KeyO = 79,
|
||||
KeyP = 80,
|
||||
KeyQ = 81,
|
||||
KeyR = 82,
|
||||
KeyS = 83,
|
||||
KeyT = 84,
|
||||
KeyU = 85,
|
||||
KeyV = 86,
|
||||
KeyW = 87,
|
||||
KeyX = 88,
|
||||
KeyY = 89,
|
||||
KeyZ = 90,
|
||||
|
||||
// 符号
|
||||
/**
|
||||
* 逗号
|
||||
*/
|
||||
Comma = 188,
|
||||
CommaChrome = 229,
|
||||
/**
|
||||
* 句号
|
||||
*/
|
||||
Period = 190,
|
||||
/**
|
||||
* 分号
|
||||
*/
|
||||
Semicolon = 186,
|
||||
/**
|
||||
* 引号
|
||||
*/
|
||||
Quote = 222,
|
||||
/**
|
||||
* 左括号
|
||||
*/
|
||||
BracketLeft = 219,
|
||||
/**
|
||||
* 右括号
|
||||
*/
|
||||
BracketRight = 220,
|
||||
/**
|
||||
* 反引号
|
||||
*/
|
||||
Backquote = 192,
|
||||
/**
|
||||
* 反斜杠
|
||||
*/
|
||||
Backslash = 220,
|
||||
/**
|
||||
* 减号
|
||||
*/
|
||||
Minus = 189,
|
||||
/**
|
||||
* 等号
|
||||
*/
|
||||
Equal = 187,
|
||||
IntlRo = 193,
|
||||
IntlYen = 255,
|
||||
// 功能键
|
||||
Alt = 18,
|
||||
/**
|
||||
* 大写锁定
|
||||
*/
|
||||
CapsLock = 20,
|
||||
Control = 17,
|
||||
/**
|
||||
* win左键
|
||||
*/
|
||||
OSLeft = 91,
|
||||
/**
|
||||
* win右键
|
||||
*/
|
||||
OSRight = 92,
|
||||
Shift = 16,
|
||||
|
||||
ContextMenu = 93,
|
||||
Enter = 13,
|
||||
Space = 32,
|
||||
Backspace = 8,
|
||||
Tab = 9,
|
||||
Delete = 46,
|
||||
End = 35,
|
||||
Home = 36,
|
||||
Insert = 45,
|
||||
PageDown = 34,
|
||||
PageUp = 33,
|
||||
ArrowDown = 40,
|
||||
ArrowLeft = 37,
|
||||
ArrowRight = 39,
|
||||
ArrowUp = 38,
|
||||
Escape = 27,
|
||||
PrintScreen = 44,
|
||||
ScrollLock = 145,
|
||||
Pause = 19,
|
||||
|
||||
// F数字
|
||||
F1 = 112,
|
||||
F2 = 113,
|
||||
F3 = 114,
|
||||
F5 = 116,
|
||||
F6 = 117,
|
||||
F7 = 118,
|
||||
F8 = 119,
|
||||
F9 = 120,
|
||||
F10 = 121,
|
||||
F11 = 122,
|
||||
F12 = 123,
|
||||
|
||||
//数字键盘
|
||||
NumLock = 114,
|
||||
Numpad0 = 96,
|
||||
Numpad1 = 97,
|
||||
Numpad2 = 98,
|
||||
Numpad3 = 99,
|
||||
Numpad4 = 100,
|
||||
Numpad5 = 101,
|
||||
Numpad6 = 102,
|
||||
Numpad7 = 103,
|
||||
Numpad8 = 104,
|
||||
Numpad9 = 105,
|
||||
NumpadAdd = 107,
|
||||
NumpadDivide = 111,
|
||||
NumpadEqual = 12,
|
||||
NumpadMultiply = 106,
|
||||
NumpadSubtract = 109,
|
||||
NumpadDot = 110,
|
||||
NumpadDot1 = 190
|
||||
|
||||
}
|
13
src/Material.ts
Normal file
13
src/Material.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MeshBasicMaterial, Color, LineBasicMaterial } from "three";
|
||||
|
||||
//板件的材质,使用这个材质避免板件将线覆盖.
|
||||
export let boardMaterial = new MeshBasicMaterial({
|
||||
color: new Color(0.8, 0.8, 0.8),
|
||||
polygonOffset: true,
|
||||
polygonOffsetFactor: 1, // positive value pushes polygon further away
|
||||
polygonOffsetUnits: 1
|
||||
});
|
||||
|
||||
//线框的材质
|
||||
export let edgeMaterial = new LineBasicMaterial({ linewidth: 2, color: new Color(0, 0, 0) });
|
||||
|
33
src/Matrix2.ts
Normal file
33
src/Matrix2.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Vector2, Vector3 } from "three";
|
||||
|
||||
export class Matrix2
|
||||
{
|
||||
private el = [1, 0, 0, 1];
|
||||
set(n11: number, n12: number, n21: number, n22: number)
|
||||
{
|
||||
let te = this.el;
|
||||
|
||||
te[0] = n11; te[1] = n21;
|
||||
te[2] = n12; te[3] = n22;
|
||||
return this;
|
||||
}
|
||||
applyVector(vec: Vector2 | Vector3)
|
||||
{
|
||||
let x = vec.x, y = vec.y;
|
||||
let e = this.el;
|
||||
vec.x = e[0] * x + e[2] * y;
|
||||
vec.y = e[1] * x + e[3] * y;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
setRotate(theta: number): Matrix2
|
||||
{
|
||||
let el = this.el;
|
||||
let c = Math.cos(theta), s = Math.sin(theta);
|
||||
|
||||
this.set(c, -s,
|
||||
s, c);
|
||||
return this;
|
||||
}
|
||||
}
|
94
src/Orbit.ts
Normal file
94
src/Orbit.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import * as THREE from "three";
|
||||
|
||||
/**
|
||||
* 轨道控制的数学类,观察向量和角度的互相转换
|
||||
* 当x当抬头或者低头到90度时,触发万向锁.
|
||||
*
|
||||
* @class Orbit
|
||||
*/
|
||||
export class Orbit
|
||||
{
|
||||
//抬头低头 正数抬头 负数低头
|
||||
private m_RoX: number = 0;
|
||||
|
||||
//身体旋转 0为正右边 逆时针旋转
|
||||
RoZ: number = 0;
|
||||
|
||||
get RoX()
|
||||
{
|
||||
return this.m_RoX;
|
||||
}
|
||||
set RoX(v)
|
||||
{
|
||||
this.m_RoX = THREE.Math.clamp(v, Math.PI * -0.5, Math.PI * 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用旋转角度 计算观察向量
|
||||
*
|
||||
* @param {THREE.Vector3} [dir] 引用传入,如果传入,那么就不构造新的向量
|
||||
* @returns {THREE.Vector3} 返回观察向量
|
||||
* @memberof Orbit
|
||||
*/
|
||||
UpdateDirection(dir?: THREE.Vector3): THREE.Vector3
|
||||
{
|
||||
let rtDir = dir ? dir : new THREE.Vector3();
|
||||
|
||||
rtDir.z = Math.sin(this.m_RoX);
|
||||
|
||||
//归一化专用.
|
||||
let d = Math.abs(Math.cos(this.m_RoX));
|
||||
|
||||
rtDir.x = Math.cos(this.RoZ) * d;
|
||||
rtDir.y = Math.sin(this.RoZ) * d;
|
||||
|
||||
return rtDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用观察向量,计算旋转角度
|
||||
*
|
||||
* @param {THREE.Vector3} dir
|
||||
* @memberof Orbit
|
||||
*/
|
||||
UpdateRoValue(dir: THREE.Vector3)
|
||||
{
|
||||
dir.normalize();
|
||||
this.m_RoX = Math.asin(dir.z);
|
||||
if (dir.x < 1e-4 && dir.y < 1e-4)
|
||||
this.RoZ = Math.PI * 0.5;
|
||||
else
|
||||
this.RoZ = Math.atan2(dir.y, dir.x);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 根据观察向量 求头部的向量.
|
||||
*
|
||||
* @static
|
||||
* @param {THREE.Vector3} dir
|
||||
* @param {THREE.Vector3} [up]
|
||||
* @returns {THREE.Vector3}
|
||||
* @memberof Orbit
|
||||
*/
|
||||
static ComputUpDirection(dir: THREE.Vector3, up?: THREE.Vector3): THREE.Vector3
|
||||
{
|
||||
let upRes = up ? up : new THREE.Vector3();
|
||||
if (dir.equals(new THREE.Vector3(0, 0, -1)))
|
||||
{
|
||||
upRes.set(0, 1, 0);
|
||||
}
|
||||
else if (dir.equals(new THREE.Vector3(0, 0, 1)))
|
||||
{
|
||||
upRes.set(0, -1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
let xv = new THREE.Vector3();
|
||||
xv.crossVectors(new THREE.Vector3(0, 0, 1), dir);
|
||||
upRes.crossVectors(dir, xv);
|
||||
upRes.normalize();
|
||||
}
|
||||
return upRes;
|
||||
}
|
||||
}
|
46
src/PlaneExt.ts
Normal file
46
src/PlaneExt.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import * as THREE from 'three';
|
||||
import { Vector3, Line3 } from "three";
|
||||
|
||||
export class PlaneExt extends THREE.Plane
|
||||
{
|
||||
constructor(normal?: THREE.Vector3, constant?: number)
|
||||
{
|
||||
super(normal, constant);
|
||||
}
|
||||
intersectLine(line: Line3, optionalTarget?: Vector3, extendLine?: boolean): Vector3
|
||||
{
|
||||
let v1 = new Vector3();
|
||||
|
||||
let result = optionalTarget || new Vector3();
|
||||
|
||||
let direction = line.delta(v1);
|
||||
|
||||
let denominator = this.normal.dot(direction);
|
||||
|
||||
if (denominator === 0)
|
||||
{
|
||||
// line is coplanar, return origin
|
||||
if (this.distanceToPoint(line.start) === 0)
|
||||
{
|
||||
return result.copy(line.start);
|
||||
}
|
||||
// Unsure if this is the correct method to handle this case.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let t = - (line.start.dot(this.normal) + this.constant) / denominator;
|
||||
//If you not extendLine,check intersect point in Line
|
||||
if (!extendLine && (t < 0 || t > 1))
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return result.copy(direction).multiplyScalar(t).add(line.start);
|
||||
}
|
||||
intersectRay(ray: THREE.Ray, optionalTarget?: Vector3, extendLine?: boolean): Vector3
|
||||
{
|
||||
// 从射线初始位置
|
||||
let line = new THREE.Line3(ray.origin.clone(), ray.origin.clone().add(ray.direction));
|
||||
return this.intersectLine(line, optionalTarget, extendLine);
|
||||
}
|
||||
}
|
58
src/PointPick.ts
Normal file
58
src/PointPick.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Object3D, Raycaster, Face3, Vector3, Vector2, Mesh } from "three";
|
||||
import { Viewer } from ".";
|
||||
|
||||
interface Intersect
|
||||
{
|
||||
distance: number;
|
||||
face: Face3;
|
||||
faceIndex: number;
|
||||
object: Object3D;
|
||||
point: Vector3;
|
||||
uv: Vector2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点选
|
||||
*
|
||||
* @export
|
||||
* @param {Viewer} view
|
||||
* @param {number} ptx
|
||||
* @param {number} pty
|
||||
* @returns {(Mesh | undefined)}
|
||||
*/
|
||||
export function PointPick(view: Viewer, ptx: number, pty: number): Mesh | undefined
|
||||
{
|
||||
let raycaster = new Raycaster();
|
||||
raycaster.setFromCamera({
|
||||
x: (ptx / view._Width) * 2 - 1, //-1 到 1 所以 (x-(w/2))/(w/2) =>
|
||||
y: - (pty / view._Height) * 2 + 1 //y轴相反
|
||||
}, view.m_Camera.Camera);
|
||||
|
||||
//https://github.com/mrdoob/three.js/issues/14128
|
||||
raycaster.ray.origin.set((ptx / view._Width) * 2 - 1, - (pty / view._Height) * 2 + 1, -1).unproject(view.m_Camera.Camera);
|
||||
|
||||
|
||||
let minDis = Infinity;
|
||||
let minObj = undefined;
|
||||
|
||||
view.m_Scene.children.forEach(obj =>
|
||||
{
|
||||
if (obj instanceof Mesh)
|
||||
{
|
||||
let intersects: Intersect[] = [];
|
||||
obj.raycast(raycaster, intersects);
|
||||
|
||||
for (let i of intersects)
|
||||
{
|
||||
if (i.distance < minDis)
|
||||
{
|
||||
minObj = obj;
|
||||
minDis = i.distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return minObj;
|
||||
}
|
25
src/RotateUV.ts
Normal file
25
src/RotateUV.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Matrix2 } from './Matrix2';
|
||||
import * as THREE from 'three';
|
||||
|
||||
|
||||
export function RotateUVs(geo: THREE.Geometry)
|
||||
{
|
||||
let roMat = new Matrix2();
|
||||
roMat.set(0, -1,
|
||||
1, 0);
|
||||
|
||||
let addV = new THREE.Vector2(1, 0);
|
||||
|
||||
for (let uvs of geo.faceVertexUvs)
|
||||
{
|
||||
for (let uv of uvs)
|
||||
{
|
||||
for (let v of uv)
|
||||
{
|
||||
roMat.applyVector(v);
|
||||
v.add(addV);
|
||||
}
|
||||
}
|
||||
}
|
||||
geo.uvsNeedUpdate = true;
|
||||
}
|
45
src/Text.ts
Normal file
45
src/Text.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Font, FontLoader, Mesh, ShapeGeometry, Vector3 } from "three";
|
||||
import { ColorMaterial } from "./ColorPalette";
|
||||
import { MoveMatrix } from "./GeUtils";
|
||||
|
||||
|
||||
class FontLoaderUtil
|
||||
{
|
||||
private static defFont:Font;
|
||||
static Load():Font
|
||||
{
|
||||
if(!this.defFont)
|
||||
{
|
||||
const f = require("../node_modules/three/examples/fonts/helvetiker_regular.typeface.json");
|
||||
let loader = new FontLoader();
|
||||
this.defFont = loader.parse(f);
|
||||
}
|
||||
return this.defFont;
|
||||
}
|
||||
}
|
||||
|
||||
export class DbText extends Mesh
|
||||
{
|
||||
/**
|
||||
*
|
||||
* 构造一个文本对象,8位点(中心点下面)在0点
|
||||
* @param {string} str 数字字符串
|
||||
* @param {number} height 文本高度
|
||||
* @memberof DbText
|
||||
*/
|
||||
constructor(str:string,height:number = 5)
|
||||
{
|
||||
|
||||
let font = FontLoaderUtil.Load();
|
||||
|
||||
let shapes: THREE.Shape[] = font.generateShapes(str, height,0.1);
|
||||
let geometry = new ShapeGeometry(shapes);
|
||||
|
||||
geometry.computeBoundingBox();
|
||||
|
||||
super(geometry,ColorMaterial.GetLineMaterial(5));
|
||||
|
||||
let center = geometry.boundingBox.getCenter(new Vector3());
|
||||
this.applyMatrix(MoveMatrix(new Vector3(-center.x,0,0)));
|
||||
}
|
||||
}
|
27
src/Utils.ts
Normal file
27
src/Utils.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Viewer, createTemplateBoard, createEdge, DrawDimension } from ".";
|
||||
import { Geometry } from "three";
|
||||
|
||||
export function LoadBoard(view: Viewer, data: any[])
|
||||
{
|
||||
view.m_Scene.children.forEach(obj =>
|
||||
{
|
||||
let geo = obj["geometry"] as Geometry;
|
||||
if (geo) geo.dispose();
|
||||
})
|
||||
view.m_Scene.children.length = 0;
|
||||
|
||||
//加板
|
||||
let brList = createTemplateBoard(data);
|
||||
//线框
|
||||
let edgeList = brList.map(br => createEdge(br));
|
||||
//加标注
|
||||
let dims = DrawDimension(brList);
|
||||
|
||||
view.m_Scene.add(...brList);
|
||||
view.m_Scene.add(...edgeList);
|
||||
view.m_Scene.add(...dims);
|
||||
|
||||
view.ViewToSwiso();
|
||||
view.ZoomAll();
|
||||
view.Zoom(1.1);
|
||||
}
|
194
src/Viewer.ts
Normal file
194
src/Viewer.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
import * as THREE from "three";
|
||||
import { CameraUpdate } from "./CameraUpdate";
|
||||
import { GetBox, GetBoxArr, cZeroVec } from "./GeUtils";
|
||||
import { PlaneExt } from "./PlaneExt";
|
||||
import { PointPick, boardMaterial, CameraControls } from ".";
|
||||
import { MeshBasicMaterial, Color, Mesh } from "three";
|
||||
|
||||
export class Viewer
|
||||
{
|
||||
m_LookTarget: any;
|
||||
m_Camera: CameraUpdate = new CameraUpdate();
|
||||
m_bNeedUpdate: boolean = true;
|
||||
m_Render: THREE.WebGLRenderer;//渲染器 //暂时只用这个类型
|
||||
m_DomEl: HTMLElement; //画布容器
|
||||
|
||||
_Height: number;
|
||||
_Width: number;
|
||||
|
||||
m_Scene: THREE.Scene = new THREE.Scene();
|
||||
|
||||
//构造
|
||||
constructor(canvasContainer: HTMLElement)
|
||||
{
|
||||
this.m_DomEl = canvasContainer;
|
||||
this.initRender(canvasContainer);
|
||||
this.OnSize();
|
||||
this.StartRender();
|
||||
new CameraControls(this);
|
||||
window.addEventListener("resize", () =>
|
||||
{
|
||||
this.OnSize();
|
||||
});
|
||||
|
||||
//选中
|
||||
let selectMaterial = new MeshBasicMaterial({ color: new Color(0.1, 0.5, 0.5) });
|
||||
|
||||
let oldMesh: Mesh;
|
||||
this.m_Render.domElement.addEventListener("mousemove", (e: MouseEvent) =>
|
||||
{
|
||||
let mesh = PointPick(this, e.offsetX, e.offsetY);
|
||||
if (oldMesh)
|
||||
oldMesh.material = boardMaterial;
|
||||
if (mesh)
|
||||
{
|
||||
oldMesh = mesh;
|
||||
mesh.material = selectMaterial;
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//初始化render
|
||||
initRender(canvasContainer: HTMLElement)
|
||||
{
|
||||
this.m_Render = new THREE.WebGLRenderer(
|
||||
{
|
||||
antialias: true,//antialias:true/false是否开启反锯齿
|
||||
precision: "highp",//precision:highp/mediump/lowp着色精度选择
|
||||
alpha: true,//alpha:true/false是否可以设置背景色透明
|
||||
// premultipliedAlpha: false,//?
|
||||
// stencil: false,//?
|
||||
// preserveDrawingBuffer: true,//preserveDrawingBuffer:true/false是否保存绘图缓冲
|
||||
// maxLights: 1//maxLights:最大灯光数
|
||||
}
|
||||
);
|
||||
//加到画布
|
||||
canvasContainer.appendChild(this.m_Render.domElement);
|
||||
|
||||
this.m_Render.autoClear = true;
|
||||
|
||||
//如果设置,那么它希望所有的纹理和颜色都是预乘的伽玛。默认值为false。
|
||||
// this.m_Render.gammaInput = true;
|
||||
// this.m_Render.gammaOutput = true;
|
||||
// this.m_Render.shadowMap.enabled = true;
|
||||
// this.m_Render.toneMapping = THREE.ReinhardToneMapping;
|
||||
//设置设备像素比。 这通常用于HiDPI设备,以防止模糊输出画布。
|
||||
this.m_Render.setPixelRatio(window.devicePixelRatio);
|
||||
this.m_Render.physicallyCorrectLights = true;
|
||||
//this.m_Render.toneMappingExposure = Math.pow(1, 5.0); // to allow for very bright scenes.
|
||||
|
||||
//设置它的背景色为黑色
|
||||
this.m_Render.setClearColor(0xffffff, 1);
|
||||
|
||||
|
||||
this.OnSize();
|
||||
}
|
||||
|
||||
OnSize = (width?, height?) =>
|
||||
{
|
||||
this._Width = width ? width : this.m_DomEl.scrollWidth;
|
||||
this._Height = height ? height : this.m_DomEl.scrollHeight;
|
||||
|
||||
//校验.成为2的倍数 避免外轮廓错误.
|
||||
if (this._Width % 2 == 1)
|
||||
this._Width -= 1;
|
||||
if (this._Height % 2 == 1)
|
||||
this._Height -= 1;
|
||||
|
||||
this.m_Render.setSize(this._Width, this._Height);
|
||||
this.m_Camera.SetSize(this._Width, this._Height);
|
||||
}
|
||||
|
||||
StartRender = () =>
|
||||
{
|
||||
requestAnimationFrame(this.StartRender);
|
||||
if (this.m_Scene != null && this.m_bNeedUpdate)
|
||||
{
|
||||
this.Render();
|
||||
this.m_bNeedUpdate = false;
|
||||
}
|
||||
}
|
||||
Render()
|
||||
{
|
||||
this.m_Render.render(this.m_Scene, this.m_Camera.Camera);
|
||||
}
|
||||
|
||||
ScreenToWorld(pt: THREE.Vector3, planVec?: THREE.Vector3)
|
||||
{
|
||||
//变换和求交点
|
||||
let plan = new PlaneExt(planVec || new THREE.Vector3(0, 0, 1));
|
||||
let raycaster = new THREE.Raycaster();
|
||||
// 射线从相机射线向屏幕点位置
|
||||
raycaster.setFromCamera(
|
||||
{
|
||||
x: (pt.x / this._Width) * 2 - 1,
|
||||
y: - (pt.y / this._Height) * 2 + 1
|
||||
}
|
||||
, this.m_Camera.Camera
|
||||
)
|
||||
plan.intersectRay(raycaster.ray, pt, true);
|
||||
}
|
||||
WorldToScreen(pt: THREE.Vector3)
|
||||
{
|
||||
let widthHalf = this._Width * 0.5;
|
||||
let heightHalf = this._Height * 0.5;
|
||||
|
||||
pt.project(this.m_Camera.Camera);
|
||||
|
||||
pt.x = (pt.x * widthHalf) + widthHalf;
|
||||
pt.y = - (pt.y * heightHalf) + heightHalf;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新视角观测目标(物体中心)
|
||||
*
|
||||
* @memberof Viewer
|
||||
*/
|
||||
UpdateLockTarget()
|
||||
{
|
||||
let renderList = this.m_Render.renderLists.get(this.m_Scene, this.m_Camera.Camera);
|
||||
let box = GetBoxArr(renderList.opaque.map(o => o.object));
|
||||
if (box)
|
||||
this.m_LookTarget = box.getCenter(new THREE.Vector3());
|
||||
else
|
||||
this.m_LookTarget = cZeroVec;
|
||||
}
|
||||
Rotate(mouseMove: THREE.Vector3)
|
||||
{
|
||||
this.m_Camera.Rotate(mouseMove, this.m_LookTarget);
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
Pan(mouseMove: THREE.Vector3)
|
||||
{
|
||||
this.m_Camera.Pan(mouseMove);
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
Zoom(scale: number, center?: THREE.Vector3)
|
||||
{
|
||||
this.m_Camera.Zoom(scale, center);
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
ZoomAll()
|
||||
{
|
||||
this.m_Camera.ZoomExtensBox3(GetBox(this.m_Scene, true));
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
|
||||
ViewToTop()
|
||||
{
|
||||
this.m_Camera.LookAt(new THREE.Vector3(0, 0, -1));
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
ViewToFront()
|
||||
{
|
||||
this.m_Camera.LookAt(new THREE.Vector3(0, 1, 0));
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
ViewToSwiso()
|
||||
{
|
||||
this.m_Camera.LookAt(new THREE.Vector3(1, 1, -1));
|
||||
this.m_bNeedUpdate = true;
|
||||
}
|
||||
}
|
142
src/createBoard.ts
Normal file
142
src/createBoard.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import * as THREE from 'three';
|
||||
import { LineSegments, Mesh } from 'three';
|
||||
import { polar } from './GeUtils';
|
||||
import { boardMaterial, edgeMaterial } from './Material';
|
||||
import { RotateUVs } from './RotateUV';
|
||||
//解析二维圆弧类.
|
||||
export class Arc2d
|
||||
{
|
||||
m_StartAn: number;
|
||||
m_EndAn: number;
|
||||
m_StartPoint: THREE.Vector2;
|
||||
m_EndPoint: THREE.Vector2;
|
||||
m_Center: THREE.Vector2;
|
||||
m_Radius: number;
|
||||
constructor(p1: THREE.Vector2, p2: THREE.Vector2, bul: number)
|
||||
{
|
||||
this.m_StartPoint = p1.clone();
|
||||
this.m_EndPoint = p2.clone();
|
||||
|
||||
let vec: THREE.Vector2 = p2.clone().sub(p1);
|
||||
let len = vec.length();
|
||||
let an = vec.angle();
|
||||
this.m_Radius = len / Math.sin(2 * Math.atan(bul)) / 2;
|
||||
let allAngle = Math.atan(bul) * 4;
|
||||
let delDis = bul * len / 2;
|
||||
let toDis = this.m_Radius - delDis;
|
||||
an += Math.PI * 0.5;
|
||||
|
||||
this.m_Center = p1.clone().add(p2);
|
||||
this.m_Center.multiplyScalar(0.5);
|
||||
|
||||
polar(this.m_Center, an, toDis);
|
||||
|
||||
this.m_StartAn = p1.clone().sub(this.m_Center).angle();
|
||||
this.m_EndAn = p2.clone().sub(this.m_Center).angle();
|
||||
if (bul < 0)
|
||||
{
|
||||
//一个神奇的特性 它需要这么做
|
||||
this.m_StartAn -= Math.PI;
|
||||
this.m_EndAn -= Math.PI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//创建轮廓 通过点表和凸度
|
||||
export function createPath(pts: THREE.Vector2[], buls: number[], shapeOut?: THREE.Shape): THREE.Shape
|
||||
{
|
||||
let shape = shapeOut || new THREE.Shape();
|
||||
if (pts.length === 0) return shape;
|
||||
let firstPt = pts[0];
|
||||
|
||||
shape.moveTo(firstPt.x, firstPt.y);
|
||||
for (let i = 0; i < pts.length - 1; i++)
|
||||
{
|
||||
let nextPt = pts[i + 1];
|
||||
if (buls[i] == 0)
|
||||
{
|
||||
shape.lineTo(nextPt.x, nextPt.y)
|
||||
}
|
||||
else
|
||||
{
|
||||
let pt = pts[i];
|
||||
//参考
|
||||
//http://www.dorodnic.com/blog/tag/three-js/ 绘制一个齿轮
|
||||
//https://www.kirupa.com/html5/drawing_circles_canvas.htm //html5
|
||||
let arc2 = new Arc2d(pt, nextPt, buls[i]);
|
||||
let cen = arc2.m_Center;
|
||||
shape.absarc(cen.x, cen.y, arc2.m_Radius, arc2.m_StartAn, arc2.m_EndAn, buls[i] < 0);
|
||||
}
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
export function getVec(data: object): THREE.Vector3
|
||||
{
|
||||
return new THREE.Vector3(data["x"], data["y"], data["z"]);
|
||||
}
|
||||
|
||||
//创建板件 暂时这么写
|
||||
export function createBoard(boardData: object)
|
||||
{
|
||||
let pts: THREE.Vector2[] = new Array();
|
||||
let buls: number[] = new Array();
|
||||
let boardPts = boardData["Pts"];
|
||||
let boardBuls = boardData["Buls"];
|
||||
|
||||
let boardHeight = boardData["H"];
|
||||
|
||||
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"]);
|
||||
|
||||
boardMat.makeBasis(xD, yD, ZD);
|
||||
boardMat.setPosition(pBase);
|
||||
matInv.getInverse(boardMat, true);
|
||||
}
|
||||
|
||||
for (let i = 0; i < boardPts.length; i++)
|
||||
{
|
||||
let pt = getVec(boardPts[i]);
|
||||
pt.applyMatrix4(matInv);
|
||||
pts.push(new THREE.Vector2(pt.x, pt.y));
|
||||
buls.push(boardBuls[i]);
|
||||
}
|
||||
|
||||
let sp = createPath(pts, buls);
|
||||
let extrudeSettings = {
|
||||
steps: 1,
|
||||
bevelEnabled: false,
|
||||
amount: boardHeight
|
||||
};
|
||||
|
||||
let ext = new THREE.ExtrudeGeometry(sp, extrudeSettings);
|
||||
ext.computeBoundingSphere();
|
||||
ext.computeBoundingBox();
|
||||
ext.translate(0, 0, -boardHeight)
|
||||
ext.applyMatrix(boardMat);
|
||||
|
||||
if (boardData["BoardName"] === "地脚线")
|
||||
{
|
||||
RotateUVs(ext);
|
||||
}
|
||||
|
||||
let mesh = new THREE.Mesh(ext, boardMaterial);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
export function createTemplateBoard(brDataList: any[])
|
||||
{
|
||||
return brDataList.map(brData => createBoard(brData));
|
||||
}
|
||||
|
||||
export function createEdge(board: Mesh): LineSegments
|
||||
{
|
||||
let edge = new THREE.EdgesGeometry(board.geometry, 1);
|
||||
return new LineSegments(edge, edgeMaterial);
|
||||
}
|
550
src/data.ts
Normal file
550
src/data.ts
Normal file
@@ -0,0 +1,550 @@
|
||||
export var data =
|
||||
[
|
||||
{
|
||||
"L": 100.0,
|
||||
"W": 800.0,
|
||||
"H": 18.0,
|
||||
"BasePoint": {
|
||||
"x": 2076.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1882.0
|
||||
},
|
||||
"XVec": {
|
||||
"x": 1.0,
|
||||
"y": 4.930380657631324e-32,
|
||||
"z": -2.220446049250313e-16
|
||||
},
|
||||
"YVec": {
|
||||
"x": 2.220446049250313e-16,
|
||||
"y": 2.220446049250313e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 9.860761315262648e-32,
|
||||
"y": -1.0,
|
||||
"z": 2.220446049250313e-16
|
||||
},
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1882.0
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1881.9999999999998
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1981.9999999999998
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1982.0
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1942.2104819571228,
|
||||
"z": 1882.0
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 800.0,
|
||||
"W": 100.00000000000068,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2876.407626150509,
|
||||
"y": 1960.2104819571226,
|
||||
"z": 1900.0000000000005
|
||||
},
|
||||
"XVec": {
|
||||
"x": 4.440892098500626e-16,
|
||||
"y": 1.0,
|
||||
"z": 2.2204460492503124e-16
|
||||
},
|
||||
"YVec": {
|
||||
"x": -1.0,
|
||||
"y": 4.440892098500626e-16,
|
||||
"z": 2.220446049250314e-16
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 2.220446049250313e-16,
|
||||
"y": -2.220446049250313e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"Handle": "293",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1900.0000000000005
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 2060.210481957123,
|
||||
"z": 1900.0000000000005
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.210481957123,
|
||||
"z": 1900.0000000000005
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.210481957123,
|
||||
"z": 1900.0000000000005
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1900.0000000000005
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 1899.9999999999998,
|
||||
"W": 800.0,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": -1.816324868286756e-13
|
||||
},
|
||||
"XVec": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"YVec": {
|
||||
"x": 0.0,
|
||||
"y": 4.440892098500626e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 0.0,
|
||||
"y": -1.0,
|
||||
"z": 4.440892098500626e-16
|
||||
},
|
||||
"Handle": "291",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "背板",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": -1.021405182655144e-13
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": -1.816324868286756e-13
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 2060.210481957123,
|
||||
"z": 1899.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.210481957123,
|
||||
"z": 1899.9999999999998
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": -1.021405182655144e-13
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 800.0,
|
||||
"W": 482.0000000000002,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2876.407626150509,
|
||||
"y": 1578.210481957122,
|
||||
"z": 97.99999999999999
|
||||
},
|
||||
"XVec": {
|
||||
"x": 4.440892098500626e-16,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"YVec": {
|
||||
"x": -1.0,
|
||||
"y": 4.440892098500626e-16,
|
||||
"z": 0.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Handle": "290",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "底板",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1578.210481957122,
|
||||
"z": 97.99999999999999
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": 97.99999999999999
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2060.2104819571225,
|
||||
"z": 97.99999999999999
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1578.2104819571226,
|
||||
"z": 97.99999999999999
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1578.210481957122,
|
||||
"z": 97.99999999999999
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 80.0,
|
||||
"W": 800.0,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2076.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 0.0
|
||||
},
|
||||
"XVec": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"YVec": {
|
||||
"x": 0.0,
|
||||
"y": 4.440892098500626e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 0.0,
|
||||
"y": -1.0,
|
||||
"z": 4.440892098500626e-16
|
||||
},
|
||||
"Handle": "28E",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "地脚线",
|
||||
"Grain": 1,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 0.0
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 0.0
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 80.0
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 80.0
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1578.2104819571223,
|
||||
"z": 0.0
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 800.0,
|
||||
"W": 482.0,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2876.4076261505085,
|
||||
"y": 1478.210481957122,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
"XVec": {
|
||||
"x": 4.440892098500626e-16,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"YVec": {
|
||||
"x": -1.0,
|
||||
"y": 4.440892098500626e-16,
|
||||
"z": 0.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Handle": "28C",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "顶板",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.2104819571223,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1478.2104819571226,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2876.407626150509,
|
||||
"y": 1478.210481957122,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2876.4076261505085,
|
||||
"y": 1960.210481957122,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.2104819571223,
|
||||
"z": 1999.9999999999996
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 1999.9999999999996,
|
||||
"W": 600.0,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2894.4076261505094,
|
||||
"y": 1478.2104819571223,
|
||||
"z": -2.2737367544323197e-13
|
||||
},
|
||||
"XVec": {
|
||||
"x": 4.930380657631324e-32,
|
||||
"y": 1.0,
|
||||
"z": -2.220446049250313e-16
|
||||
},
|
||||
"YVec": {
|
||||
"x": -2.220446049250313e-16,
|
||||
"y": 2.220446049250313e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 2.220446049250313e-16
|
||||
},
|
||||
"Handle": "28B",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "右侧板",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2894.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1899.9999999999989
|
||||
},
|
||||
{
|
||||
"x": 2894.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1999.9999999999994
|
||||
},
|
||||
{
|
||||
"x": 2894.407626150509,
|
||||
"y": 1478.2104819571228,
|
||||
"z": 1999.9999999999994
|
||||
},
|
||||
{
|
||||
"x": 2894.4076261505094,
|
||||
"y": 1478.2104819571223,
|
||||
"z": -1.816324868286755e-13
|
||||
},
|
||||
{
|
||||
"x": 2894.4076261505094,
|
||||
"y": 2078.2104819571225,
|
||||
"z": -6.274980535181384e-13
|
||||
},
|
||||
{
|
||||
"x": 2894.407626150509,
|
||||
"y": 2078.2104819571229,
|
||||
"z": 1899.9999999999973
|
||||
},
|
||||
{
|
||||
"x": 2894.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1899.9999999999989
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
},
|
||||
{
|
||||
"L": 1999.9999999999996,
|
||||
"W": 600.0,
|
||||
"H": 18.0,
|
||||
"MaterialId": "EE",
|
||||
"BasePoint": {
|
||||
"x": 2076.4076261505094,
|
||||
"y": 1478.2104819571223,
|
||||
"z": 1.0097419586828951e-28
|
||||
},
|
||||
"XVec": {
|
||||
"x": 4.930380657631324e-32,
|
||||
"y": 1.0,
|
||||
"z": -2.220446049250313e-16
|
||||
},
|
||||
"YVec": {
|
||||
"x": -2.220446049250313e-16,
|
||||
"y": 2.220446049250313e-16,
|
||||
"z": 1.0
|
||||
},
|
||||
"ZVec": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 2.220446049250313e-16
|
||||
},
|
||||
"Handle": "288",
|
||||
"CabName": "1.标准柜上梁1",
|
||||
"BoardName": "左侧板",
|
||||
"Grain": 0,
|
||||
"Pts": [
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1899.999999999999
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1478.2104819571228,
|
||||
"z": 1999.9999999999996
|
||||
},
|
||||
{
|
||||
"x": 2076.4076261505094,
|
||||
"y": 1478.2104819571223,
|
||||
"z": 1.0097419586828951e-28
|
||||
},
|
||||
{
|
||||
"x": 2076.4076261505094,
|
||||
"y": 2078.2104819571225,
|
||||
"z": -4.4586556668946279e-13
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 2078.2104819571229,
|
||||
"z": 1899.9999999999978
|
||||
},
|
||||
{
|
||||
"x": 2076.407626150509,
|
||||
"y": 1960.2104819571228,
|
||||
"z": 1899.999999999999
|
||||
}
|
||||
],
|
||||
"Buls": [
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"SubBoardLocal": [],
|
||||
"SubBoardAssoc": []
|
||||
}
|
||||
]
|
9
src/index.ts
Normal file
9
src/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from "./Viewer";
|
||||
export * from "./CameraControls";
|
||||
export * from "./GeUtils";
|
||||
export * from "./createBoard";
|
||||
export * from "./Dimension";
|
||||
export * from "./DrawDimension";
|
||||
export * from "./Material";
|
||||
export * from "./PointPick"
|
||||
export * from "./Utils"
|
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"target": "esnext",
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user