mirror of https://gitee.com/cf-fz/WebCAD.git
parent
2fb22f9792
commit
f04751a658
@ -0,0 +1,11 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`相交测试 1`] = `
|
||||||
|
Vector3 {
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`相交测试 2`] = `undefined`;
|
@ -0,0 +1,22 @@
|
|||||||
|
import * as assert from 'assert';
|
||||||
|
import { Intersect } from '../../src/Geometry/GeUtils';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
|
||||||
|
test('相交测试', () =>
|
||||||
|
{
|
||||||
|
let p1 = new THREE.Vector3(0, 0, 0);
|
||||||
|
let p2 = new THREE.Vector3(1, 0, 0);
|
||||||
|
let p3 = new THREE.Vector3(0.5, 0.5, 0);
|
||||||
|
let p4 = new THREE.Vector3(0.5, 1, 0);
|
||||||
|
|
||||||
|
let p5 = new THREE.Vector3(3, 0, 0);
|
||||||
|
let p6 = new THREE.Vector3(6, 0, 0);
|
||||||
|
|
||||||
|
let res = Intersect(p1, p2, p3, p4);/*?*/
|
||||||
|
|
||||||
|
expect(res).toMatchSnapshot();
|
||||||
|
|
||||||
|
res = Intersect(p1, p2, p5, p6);/*?*/
|
||||||
|
expect(res).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
@ -1,6 +1,15 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
test('should behave...', () =>
|
test('should behave...', () =>
|
||||||
{
|
{
|
||||||
|
let p1 = new THREE.Vector3(0, 0, 0);
|
||||||
|
let p2 = new THREE.Vector3(1, 0, 0);
|
||||||
|
let p3 = new THREE.Vector3(0.5, 0.5, 0);
|
||||||
|
let p4 = new THREE.Vector3(0.5, 1, 0);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,350 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import * as xaop from 'xaop';
|
||||||
|
|
||||||
|
import { app } from '../ApplicationServices/Application';
|
||||||
|
import { GetPointPrompt, InputState } from '../Common/InputState';
|
||||||
|
import { MouseKey } from '../Common/KeyEnum';
|
||||||
|
import { Line } from '../DatabaseServices/Entity';
|
||||||
|
import { angle, equaln, fixAngle, Intersect } from '../Geometry/GeUtils';
|
||||||
|
import { PromptPointResult, PromptStatus } from './PromptResult';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为拾取点提供服务,提供一个类以供Editor引用.
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @class GetPointServices
|
||||||
|
*/
|
||||||
|
export class GetPointServices
|
||||||
|
{
|
||||||
|
Doit(prompt?: GetPointPrompt): Promise<PromptPointResult>
|
||||||
|
{
|
||||||
|
app.m_Editor.m_InputState = InputState.GetPoint;
|
||||||
|
|
||||||
|
prompt = prompt ? prompt : {};
|
||||||
|
app.m_Viewer.m_PreViewer.ToGetpoint();
|
||||||
|
let retValue = new PromptPointResult();
|
||||||
|
|
||||||
|
let removeCalls = []; //删除回调列表
|
||||||
|
|
||||||
|
removeCalls.push(this.Snap());
|
||||||
|
removeCalls.push(() => { this.DestroySnapLine() });
|
||||||
|
|
||||||
|
return new Promise<PromptPointResult>((resolve, reject) =>
|
||||||
|
{
|
||||||
|
//如果有基点,那么绘制直线
|
||||||
|
if (prompt.BasePoint && prompt.AllowDrawRubberBand)
|
||||||
|
{
|
||||||
|
this.m_SnapPtList = [prompt.BasePoint];
|
||||||
|
if (prompt.AllowDrawRubberBand)
|
||||||
|
{
|
||||||
|
let preView = app.m_Viewer.m_PreViewer;
|
||||||
|
|
||||||
|
let startP = prompt.BasePoint.clone();
|
||||||
|
app.m_Viewer.WorldToScreen(startP);
|
||||||
|
preView.ScreenPointToViewerPoint(startP);
|
||||||
|
|
||||||
|
let line = preView.DrawLine(startP, startP, preView.m_DashMaterial);
|
||||||
|
let geo = line.geometry as THREE.Geometry;
|
||||||
|
geo.computeLineDistances();
|
||||||
|
|
||||||
|
preView.Scene.add(line);
|
||||||
|
removeCalls.push(
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
preView.Scene.remove(line);
|
||||||
|
},
|
||||||
|
xaop.end(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.onMouseMove, () =>
|
||||||
|
{
|
||||||
|
let endP = this.GetNowPoint();
|
||||||
|
app.m_Viewer.WorldToScreen(endP);
|
||||||
|
preView.ScreenPointToViewerPoint(endP);
|
||||||
|
|
||||||
|
geo.vertices[1] = endP;
|
||||||
|
geo.computeLineDistances();
|
||||||
|
geo.lineDistancesNeedUpdate = true;
|
||||||
|
geo.verticesNeedUpdate = true;
|
||||||
|
|
||||||
|
preView.render();
|
||||||
|
app.m_Editor.UpdateScreen();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//调用回调
|
||||||
|
if (prompt.Callback)
|
||||||
|
{
|
||||||
|
removeCalls.push(
|
||||||
|
xaop.end(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.onMouseMove, () =>
|
||||||
|
{
|
||||||
|
let p = this.GetNowPoint();
|
||||||
|
prompt.Callback(p);
|
||||||
|
app.m_Editor.UpdateScreen();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//鼠标按下
|
||||||
|
removeCalls.push(
|
||||||
|
xaop.end(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.onMouseDown, (e: MouseEvent) =>
|
||||||
|
{
|
||||||
|
if (e.button == MouseKey.Left)
|
||||||
|
{
|
||||||
|
retValue.Status = PromptStatus.OK;
|
||||||
|
retValue.Value = this.GetNowPoint();
|
||||||
|
_return();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
//键盘按下
|
||||||
|
removeCalls.push(
|
||||||
|
xaop.begin(app.m_Editor.m_KeyCtrl, app.m_Editor.m_KeyCtrl.OnKeyDown, (e: KeyboardEvent) =>
|
||||||
|
{
|
||||||
|
if (e.keyCode == 27)
|
||||||
|
{
|
||||||
|
retValue.Status = PromptStatus.Cancel;
|
||||||
|
_return();
|
||||||
|
}
|
||||||
|
else if (e.keyCode == 32)
|
||||||
|
{
|
||||||
|
retValue.Status = PromptStatus.None;
|
||||||
|
_return();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
//返回
|
||||||
|
let _return = () =>
|
||||||
|
{
|
||||||
|
app.m_Editor.m_InputState = InputState.None;
|
||||||
|
this.noSnapList.clear();
|
||||||
|
|
||||||
|
//清理所有的注入函数.
|
||||||
|
for (let destroyFunc of removeCalls)
|
||||||
|
{
|
||||||
|
destroyFunc();
|
||||||
|
}
|
||||||
|
app.m_Viewer.m_PreViewer.ToSelect();
|
||||||
|
|
||||||
|
resolve(retValue);
|
||||||
|
app.m_Editor.UpdateScreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//极轴捕捉的线列表
|
||||||
|
m_SnapAxisBlueLine: THREE.Line[] = [];
|
||||||
|
|
||||||
|
private DestroySnapLine()
|
||||||
|
{
|
||||||
|
for (let l of this.m_SnapAxisBlueLine)
|
||||||
|
{
|
||||||
|
app.m_Viewer.m_PreViewer.Scene.remove(l);
|
||||||
|
l.geometry.dispose();
|
||||||
|
}
|
||||||
|
this.m_SnapAxisBlueLine = [];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 获得当前光标所在的点, 先判断捕捉,在判断极轴捕捉
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {THREE.Vector3}
|
||||||
|
* @memberof Editor
|
||||||
|
*/
|
||||||
|
private GetNowPoint(): THREE.Vector3
|
||||||
|
{
|
||||||
|
this.DestroySnapLine();
|
||||||
|
if (app.m_Viewer.m_PreViewer.m_LastSnapPoint)
|
||||||
|
{
|
||||||
|
let retP = app.m_Viewer.m_PreViewer.ptWcs;
|
||||||
|
app.m_Viewer.ScreenToWorld(retP);
|
||||||
|
return retP;
|
||||||
|
}
|
||||||
|
|
||||||
|
let snapPts: { pbase: THREE.Vector3, pSnap: THREE.Vector3 }[] = [];
|
||||||
|
for (let baseP of this.m_SnapPtList)
|
||||||
|
{
|
||||||
|
let newP = this.AxisSnap(baseP);
|
||||||
|
if (newP)
|
||||||
|
{
|
||||||
|
snapPts.push({ pbase: baseP, pSnap: newP });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let wcs = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS;
|
||||||
|
if (snapPts.length > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
let insPList: {
|
||||||
|
ins: THREE.Vector3,
|
||||||
|
i1: { pbase: THREE.Vector3, pSnap: THREE.Vector3 },
|
||||||
|
i2: { pbase: THREE.Vector3, pSnap: THREE.Vector3 }
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
|
||||||
|
for (let i = 0; i < snapPts.length; i++)
|
||||||
|
{
|
||||||
|
let d1 = snapPts[i];
|
||||||
|
for (let j = i + 1; j < snapPts.length; j++)
|
||||||
|
{
|
||||||
|
let d2 = snapPts[j];
|
||||||
|
let insP = Intersect(d1.pbase, d1.pSnap, d2.pbase, d2.pSnap);
|
||||||
|
if (insP)
|
||||||
|
{
|
||||||
|
insPList.push({ ins: insP, i1: d1, i2: d2 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insPList.length > 0)
|
||||||
|
{
|
||||||
|
insPList.sort((d1, d2) =>
|
||||||
|
{
|
||||||
|
let dis1 = d1.ins.distanceTo(wcs);
|
||||||
|
let dis2 = d2.ins.distanceTo(wcs);
|
||||||
|
if (dis1 == dis2)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return dis1 < dis2 ? -1 : 1
|
||||||
|
});
|
||||||
|
if (insPList[0].ins.distanceToSquared(wcs) < 100)
|
||||||
|
{
|
||||||
|
let insD = insPList[0];
|
||||||
|
|
||||||
|
let l1 = app.m_Viewer.m_PreViewer.DrawLineFromWcs(insD.i1.pbase.clone(), insD.ins.clone(), app.m_Viewer.m_PreViewer.m_BlueDashMaterial)
|
||||||
|
let l2 = app.m_Viewer.m_PreViewer.DrawLineFromWcs(insD.i2.pbase.clone(), insD.ins.clone(), app.m_Viewer.m_PreViewer.m_BlueDashMaterial)
|
||||||
|
|
||||||
|
app.m_Viewer.m_PreViewer.Scene.add(l1)
|
||||||
|
app.m_Viewer.m_PreViewer.Scene.add(l2)
|
||||||
|
|
||||||
|
|
||||||
|
this.m_SnapAxisBlueLine.push(l1, l2)
|
||||||
|
|
||||||
|
return insPList[0].ins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snapPts.sort((d1, d2) =>
|
||||||
|
{
|
||||||
|
return d1.pSnap.distanceTo(wcs) < d2.pSnap.distanceTo(wcs) ? -1 : 1
|
||||||
|
})
|
||||||
|
return snapPts[0].pSnap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wcs.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
noSnapList = new Set<THREE.Object3D>();
|
||||||
|
m_SnapPtList: THREE.Vector3[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点捕捉服务. 如果有捕捉 将设置光标的捕捉设置
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* @memberof Editor
|
||||||
|
*/
|
||||||
|
Snap()
|
||||||
|
{
|
||||||
|
this.m_SnapPtList.length = 0;
|
||||||
|
let testSnap = () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
for (let obj of app.m_Viewer.m_Scene.children)
|
||||||
|
{
|
||||||
|
if (this.noSnapList.has(obj))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let geo = obj["geometry"];
|
||||||
|
|
||||||
|
let g: THREE.Geometry
|
||||||
|
if (geo instanceof THREE.Geometry)
|
||||||
|
{
|
||||||
|
g = geo;
|
||||||
|
}
|
||||||
|
else if (geo instanceof THREE.BufferGeometry)
|
||||||
|
{
|
||||||
|
g = new THREE.Geometry().fromBufferGeometry(geo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < g.vertices.length; i++)
|
||||||
|
{
|
||||||
|
let ptC = g.vertices[i].clone();
|
||||||
|
ptC.applyMatrix4(obj.matrix);
|
||||||
|
let ptWcs = ptC.clone();
|
||||||
|
app.m_Viewer.WorldToScreen(ptC);
|
||||||
|
|
||||||
|
if (ptC.distanceToSquared(app.m_Editor.m_MouseCtrl.m_CurMousePointVCS) < 100)
|
||||||
|
{
|
||||||
|
app.m_Viewer.m_PreViewer.m_LastSnapPoint = ptC;
|
||||||
|
|
||||||
|
app.m_Viewer.m_PreViewer.m_LastEntity = obj;
|
||||||
|
app.m_Viewer.m_PreViewer.m_LastIndex = i;
|
||||||
|
|
||||||
|
app.m_Viewer.m_PreViewer.SerCursorPostion(ptC);
|
||||||
|
|
||||||
|
app.m_Viewer.m_PreViewer.render();
|
||||||
|
|
||||||
|
for (let p of this.m_SnapPtList)
|
||||||
|
{
|
||||||
|
if (p.distanceToSquared(ptWcs) < 0.01)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.m_SnapPtList.push(ptWcs);
|
||||||
|
if (this.m_SnapPtList.length > 7)
|
||||||
|
{
|
||||||
|
this.m_SnapPtList.shift();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testSnap();
|
||||||
|
return xaop.end(app.m_Editor.m_MouseCtrl, app.m_Editor.m_MouseCtrl.onMouseMove, testSnap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 轴捕捉
|
||||||
|
* @param {any} basePoint
|
||||||
|
* @returns {THREE.Vector3} 返回捕捉的点 如果捕捉不到 那么返回空
|
||||||
|
* @memberof Editor
|
||||||
|
*/
|
||||||
|
AxisSnap(basePoint): THREE.Vector3
|
||||||
|
{
|
||||||
|
let wcs = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone();
|
||||||
|
|
||||||
|
//相差向量
|
||||||
|
let subVec = wcs.clone().sub(basePoint);
|
||||||
|
let an = Math.atan2(subVec.y, subVec.x);
|
||||||
|
|
||||||
|
if (an < 0) an += Math.PI * 2;
|
||||||
|
let newan = fixAngle(an, Math.PI * 0.25);
|
||||||
|
|
||||||
|
if (!equaln(newan, an, 0.001))
|
||||||
|
{
|
||||||
|
//dis.
|
||||||
|
let v0 = new THREE.Vector3(0, 0, 0);
|
||||||
|
angle(v0, newan, 1);
|
||||||
|
|
||||||
|
let dis = v0.dot(wcs.sub(basePoint));
|
||||||
|
|
||||||
|
let retP = basePoint.clone();
|
||||||
|
angle(retP, newan, dis);
|
||||||
|
|
||||||
|
return retP;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue