mirror of https://gitee.com/cf-fz/WebCAD.git
parent
0c019f4450
commit
26989e59e1
@ -0,0 +1,263 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
import { app } from '../ApplicationServices/Application';
|
||||
import { ColorMaterial } from '../Common/ColorPalette';
|
||||
import { GetPointPrompt } from '../Common/InputState';
|
||||
import { Entity } from '../DatabaseServices/Entity';
|
||||
import { equaln, fixAngle, Intersect, polar } from '../Geometry/GeUtils';
|
||||
import { PreViewer } from '../GraphicsSystem/PreViewer';
|
||||
|
||||
|
||||
//捕捉轴
|
||||
interface SnapAxis
|
||||
{
|
||||
BasePoint: THREE.Vector3;//基点
|
||||
SnapPoint: THREE.Vector3;//捕捉到的点
|
||||
}
|
||||
|
||||
//轴线相交数据
|
||||
interface SnapIntersect
|
||||
{
|
||||
IntersectPoint: THREE.Vector3;
|
||||
Axis1: SnapAxis;
|
||||
Axis2: SnapAxis;
|
||||
}
|
||||
|
||||
|
||||
//提供点捕捉的服务.
|
||||
export class SnapServices
|
||||
{
|
||||
private preLines: THREE.Line[] = []; //前视图绘制的线表
|
||||
notSnapEntity = new Set<THREE.Object3D>();//不参与捕捉的实体列表,这个属性由开发人员维护.
|
||||
private snapPoints: THREE.Vector3[] = [];//捕捉的点列表
|
||||
//开始捕捉
|
||||
Start(prompt: GetPointPrompt)
|
||||
{
|
||||
if (prompt.BasePoint) this.snapPoints.push(prompt.BasePoint);
|
||||
}
|
||||
//结束捕捉服务
|
||||
Stop()
|
||||
{
|
||||
this.DestroySnapLine();
|
||||
this.snapPoints.length = 0;
|
||||
}
|
||||
|
||||
GetSnapPoint(wcsP: THREE.Vector3)
|
||||
{
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
this.DestroySnapLine();
|
||||
this.DrawSnapCross(preView);
|
||||
|
||||
return this.GetEntitySnapPoint() || this.GetAxisSnapPoint(wcsP);
|
||||
}
|
||||
|
||||
//-------------------计算函数//-------------------
|
||||
|
||||
//根据角度进行轴线捕捉,如果存在捕捉,那么返回捕捉点
|
||||
private AxisSnap(basePoint: THREE.Vector3, 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);
|
||||
polar(v0, newan, 1);
|
||||
|
||||
let dis = v0.dot(wcs.sub(basePoint));
|
||||
|
||||
let retP = basePoint.clone();
|
||||
polar(retP, newan, dis);
|
||||
|
||||
return retP;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//返回合适的轴线交点,如果不存在交点,那么返回轴线上的点
|
||||
private GetAxisSnapPoint(wcsP: THREE.Vector3)
|
||||
{
|
||||
//轴线列表
|
||||
let snapAxisList: SnapAxis[] = this.snapPoints.map((p) =>
|
||||
{
|
||||
let snapPoint = this.AxisSnap(p, Math.PI * 0.5);
|
||||
return { BasePoint: p, SnapPoint: snapPoint };
|
||||
}).filter(a => a.SnapPoint);
|
||||
|
||||
if (snapAxisList.length === 0)
|
||||
return;
|
||||
|
||||
//检测交点
|
||||
let axisIntersectList: SnapIntersect[] = [];
|
||||
for (let i = 0; i < snapAxisList.length; i++)
|
||||
{
|
||||
let axis1 = snapAxisList[i];
|
||||
for (let j = i + 1; j < snapAxisList.length; j++)
|
||||
{
|
||||
let axis2 = snapAxisList[j];
|
||||
let insP = Intersect(axis1.BasePoint, axis1.SnapPoint, axis2.BasePoint, axis2.SnapPoint);
|
||||
if (insP)
|
||||
axisIntersectList.push({
|
||||
IntersectPoint: insP,
|
||||
Axis1: axis1,
|
||||
Axis2: axis2
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//如果存在交点 那么找到最近的交点
|
||||
if (axisIntersectList.length > 0)
|
||||
{
|
||||
axisIntersectList.sort((d1, d2) =>
|
||||
{
|
||||
return d1.IntersectPoint.distanceTo(wcsP) < d2.IntersectPoint.distanceTo(wcsP) ? -1 : 1;
|
||||
});
|
||||
let insData = axisIntersectList[0];
|
||||
if (insData.IntersectPoint.distanceToSquared(wcsP) < 100)
|
||||
{
|
||||
this.DrawLine(insData.Axis1.BasePoint, insData.IntersectPoint, app.m_Viewer.m_PreViewer.m_BlueDashMaterial);
|
||||
this.DrawLine(insData.Axis2.BasePoint, insData.IntersectPoint, app.m_Viewer.m_PreViewer.m_BlueDashMaterial);
|
||||
|
||||
this.DrawBaisCross(insData.IntersectPoint);
|
||||
return insData.IntersectPoint.clone();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snapAxisList.sort((d1, d2) =>
|
||||
{
|
||||
return d1.SnapPoint.distanceTo(wcsP) < d2.SnapPoint.distanceTo(wcsP) ? -1 : 1;
|
||||
});
|
||||
|
||||
let snapAxis = snapAxisList[0];
|
||||
this.DrawLine(snapAxis.BasePoint, snapAxis.SnapPoint, app.m_Viewer.m_PreViewer.m_BlueDashMaterial);
|
||||
return snapAxis.SnapPoint;
|
||||
}
|
||||
}
|
||||
|
||||
//计算图形的捕捉点 如果有 则返回.
|
||||
private GetEntitySnapPoint()
|
||||
{
|
||||
let vcsP = app.m_Editor.m_MouseCtrl.m_CurMousePointVCS;
|
||||
for (let obj of app.m_Viewer.m_Scene.children)
|
||||
{
|
||||
if (!this.notSnapEntity.has(obj) && obj.userData && obj.userData instanceof Entity)
|
||||
{
|
||||
for (let p of obj.userData.GetSnapPoints())
|
||||
{
|
||||
let pv = p.clone();
|
||||
app.m_Viewer.WorldToScreen(pv);
|
||||
if (pv.distanceToSquared(vcsP) < 100)
|
||||
{
|
||||
if (!this.snapPoints.some(sp => { return sp.distanceToSquared(p) < 1e-5 }))
|
||||
{
|
||||
this.snapPoints.push(p);
|
||||
if (this.snapPoints.length > 7) this.snapPoints.shift();
|
||||
}
|
||||
this.DrawSquare(p, 10);
|
||||
return p.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------绘制函数-------------------
|
||||
|
||||
//绘制十字光标列表
|
||||
private DrawSnapCross(preView: PreViewer)
|
||||
{
|
||||
for (let snapP of this.snapPoints)
|
||||
{
|
||||
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.preLines.push(l);
|
||||
preView.Scene.add(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//绘制 x光标 轴线捕捉
|
||||
private DrawBaisCross(ptWcs: THREE.Vector3)
|
||||
{
|
||||
let lines = app.m_Viewer.m_PreViewer.DrawBiasCross(10, ColorMaterial.GetLineMaterial(3));
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
let pv = this.WorldToViewPoint(ptWcs);
|
||||
|
||||
let move = new THREE.Matrix4().makeTranslation(pv.x, pv.y, pv.z);
|
||||
lines.forEach(l => { l.applyMatrix(move) });
|
||||
this.preLines.push(...lines);
|
||||
preView.Scene.add(...lines);
|
||||
}
|
||||
|
||||
//绘制正方形
|
||||
private DrawSquare(ptWcs: THREE.Vector3, size: number)
|
||||
{
|
||||
let pv = this.WorldToViewPoint(ptWcs);
|
||||
|
||||
let addV = new THREE.Vector3(size * 0.5, size * 0.5, 0);
|
||||
let p1 = pv.clone().sub(addV);
|
||||
let p3 = pv.clone().add(addV)
|
||||
addV.x *= -1;
|
||||
let p2 = pv.clone().add(addV);
|
||||
let p4 = pv.clone().sub(addV);
|
||||
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
let material = app.m_Viewer.m_PreViewer.m_SnapMaterial;
|
||||
|
||||
let lines = [
|
||||
preView.DrawLine(p1, p2, material),
|
||||
preView.DrawLine(p2, p3, material),
|
||||
preView.DrawLine(p3, p4, material),
|
||||
preView.DrawLine(p1, p4, material)
|
||||
]
|
||||
|
||||
this.preLines.push(...lines);
|
||||
preView.Scene.add(...lines);
|
||||
}
|
||||
|
||||
private WorldToViewPoint(pWcs: THREE.Vector3)
|
||||
{
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
let pv = pWcs.clone();
|
||||
app.m_Viewer.WorldToScreen(pv);
|
||||
preView.ScreenPointToViewerPoint(pv);
|
||||
return pv;
|
||||
}
|
||||
|
||||
//在preView中绘制 临时的线段 wcs
|
||||
private DrawLine(p1: THREE.Vector3, p2: THREE.Vector3, material?: THREE.LineBasicMaterial | THREE.LineDashedMaterial)
|
||||
{
|
||||
if (p1.distanceToSquared(p2) > 0.001)
|
||||
{
|
||||
let preView = app.m_Viewer.m_PreViewer;
|
||||
let l = preView.DrawLineFromWcs(p1.clone(), p2.clone(), material);
|
||||
this.preLines.push(l);
|
||||
preView.Scene.add(l);
|
||||
}
|
||||
}
|
||||
//销毁绘制的函数
|
||||
private DestroySnapLine()
|
||||
{
|
||||
this.preLines.forEach(l =>
|
||||
{
|
||||
l.parent.remove(l);
|
||||
l.geometry.dispose();
|
||||
})
|
||||
this.preLines.length = 0;
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import { ApplicationService } from '../ApplicationServices/Application';
|
||||
|
||||
|
||||
/**
|
||||
* 提供捕捉的服务.
|
||||
*
|
||||
* @class SnapServices
|
||||
*/
|
||||
export class SnapServices
|
||||
{
|
||||
|
||||
constructor(app: ApplicationService)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in new issue