mirror of https://gitee.com/cf-fz/WebCAD.git
parent
3a36348d60
commit
1a0ec38a21
@ -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,32 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
import { Intersect } from '../../src/Geometry/GeUtils';
|
||||
|
||||
|
||||
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();
|
||||
|
||||
let ins = Intersect(
|
||||
new THREE.Vector3(0, 5),
|
||||
new THREE.Vector3(5, 5),
|
||||
new THREE.Vector3(0.5, 1),
|
||||
new THREE.Vector3(0.5, 8));
|
||||
|
||||
expect(ins).toMatchSnapshot();
|
||||
}
|
||||
)
|
||||
|
@ -1,6 +1,15 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
|
||||
|
||||
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,397 @@
|
||||
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();
|
||||
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
|
||||
//绘制捕捉光标列表
|
||||
for (let snapP of this.m_SnapPtList)
|
||||
{
|
||||
let lines = preView.DrawCross(5, preView.m_BlueDashMaterial);
|
||||
let p = snapP.clone();
|
||||
|
||||
app.m_Viewer.WorldToScreen(p);
|
||||
preView.ScreenPointToViewerPoint(p);
|
||||
|
||||
let move = new THREE.Matrix4();
|
||||
move.setPosition(p);
|
||||
for (let l of lines)
|
||||
{
|
||||
l.applyMatrix(move);
|
||||
|
||||
this.m_SnapAxisBlueLine.push(l);
|
||||
|
||||
preView.Scene.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//如果存在捕捉
|
||||
if (app.m_Viewer.m_PreViewer.m_LastSnapPoint)
|
||||
{
|
||||
let retP = app.m_Viewer.m_PreViewer.ptWcs;
|
||||
app.m_Viewer.ScreenToWorld(retP);
|
||||
return retP;
|
||||
}
|
||||
|
||||
//捕捉轴线列表
|
||||
let snapAxisList: { basePt: THREE.Vector3, snapPt: THREE.Vector3 }[] = [];
|
||||
|
||||
|
||||
for (let i = 0; i < this.m_SnapPtList.length; i++)
|
||||
{
|
||||
let baseP = this.m_SnapPtList[i];
|
||||
let snapPt = this.AxisSnap(baseP, Math.PI * 0.5);
|
||||
if (snapPt)
|
||||
{
|
||||
snapAxisList.push({ basePt: baseP, snapPt: snapPt });
|
||||
}
|
||||
}
|
||||
|
||||
let wcs = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS;
|
||||
if (snapAxisList.length > 0)
|
||||
{
|
||||
|
||||
//轴线交点列表
|
||||
let axisIntersectList: {
|
||||
ins: THREE.Vector3,
|
||||
i1: { basePt: THREE.Vector3, snapPt: THREE.Vector3 },
|
||||
i2: { basePt: THREE.Vector3, snapPt: THREE.Vector3 }
|
||||
}[] = [];
|
||||
|
||||
|
||||
//检测交点
|
||||
for (let i = 0; i < snapAxisList.length; i++)
|
||||
{
|
||||
let d1 = snapAxisList[i];
|
||||
for (let j = i + 1; j < snapAxisList.length; j++)
|
||||
{
|
||||
let d2 = snapAxisList[j];
|
||||
let insP = Intersect(d1.basePt, d1.snapPt, d2.basePt, d2.snapPt);
|
||||
if (insP)
|
||||
{
|
||||
axisIntersectList.push({ ins: insP, i1: d1, i2: d2 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (axisIntersectList.length > 0)
|
||||
{
|
||||
axisIntersectList.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
|
||||
});
|
||||
|
||||
let insD = axisIntersectList[0];
|
||||
if (insD.ins.distanceToSquared(wcs) < 100)
|
||||
{
|
||||
this.DrawLine(insD.i1.basePt, insD.ins, preView.m_BlueDashMaterial);
|
||||
this.DrawLine(insD.i2.basePt, insD.ins, preView.m_BlueDashMaterial);
|
||||
|
||||
return insD.ins.clone();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snapAxisList.sort((d1, d2) =>
|
||||
{
|
||||
return d1.snapPt.distanceTo(wcs) < d2.snapPt.distanceTo(wcs) ? -1 : 1
|
||||
})
|
||||
|
||||
this.DrawLine(snapAxisList[0].basePt, snapAxisList[0].snapPt, preView.m_BlueDashMaterial);
|
||||
return snapAxisList[0].snapPt;
|
||||
}
|
||||
}
|
||||
|
||||
return wcs.clone();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 在preView中绘制 临时的线段
|
||||
*
|
||||
* @param {THREE.Vector3} p1
|
||||
* @param {THREE.Vector3} p2
|
||||
* @param {(THREE.LineBasicMaterial | THREE.LineDashedMaterial)} [material]
|
||||
* @memberof GetPointServices
|
||||
*/
|
||||
DrawLine(p1: THREE.Vector3, p2: THREE.Vector3, material?: THREE.LineBasicMaterial | THREE.LineDashedMaterial)
|
||||
{
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
if (p1.distanceToSquared(this.m_SnapPtList[0]) > 0.001)
|
||||
{
|
||||
let l = preView.DrawLineFromWcs(p1.clone(), p2.clone(), material);
|
||||
this.m_SnapAxisBlueLine.push(l);
|
||||
preView.Scene.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
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, fixAn: number): 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, fixAn);
|
||||
|
||||
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