!167 完善轴线捕捉(极轴捕捉,正交捕捉)

Merge pull request !167 from ChenX/SnapOrtho
pull/167/MERGE
ChenX 6 years ago
parent 6052844c2c
commit d57a4a9a7b

@ -46,8 +46,8 @@ export abstract class DrawBoardTool implements Command
private async SelectAndBuildBoard() private async SelectAndBuildBoard()
{ {
//原来禁用捕捉开启状态 //原来禁用捕捉开启状态
let oldSnapState = app.m_Editor.m_GetpointServices.snapServices.m_Disabled; let oldSnapState = app.m_Editor.m_GetpointServices.snapServices.Disabled;
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = true; app.m_Editor.m_GetpointServices.snapServices.Disabled = true;
while (true) while (true)
{ {
@ -99,7 +99,7 @@ export abstract class DrawBoardTool implements Command
app.m_Editor.UpdateScreen(); app.m_Editor.UpdateScreen();
} }
//恢复原先状态 //恢复原先状态
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = oldSnapState; app.m_Editor.m_GetpointServices.snapServices.Disabled = oldSnapState;
} }
//构建板件 //构建板件

@ -3,6 +3,7 @@ import { AlignedDimension } from '../../DatabaseServices/Dimension/AlignedDimens
import { LinearDimension } from '../../DatabaseServices/Dimension/LinearDimension'; import { LinearDimension } from '../../DatabaseServices/Dimension/LinearDimension';
import { Command } from '../../Editor/CommandMachine'; import { Command } from '../../Editor/CommandMachine';
import { PromptStatus } from '../../Editor/PromptResult'; import { PromptStatus } from '../../Editor/PromptResult';
import { Jig } from '../../Editor/Jig';
export enum DimensionType export enum DimensionType
{ {
@ -46,8 +47,7 @@ export class DrawAlignedDimension implements Command
alDim = new LinearDimension(startPt, endPt, linePt, startPt.distanceTo(endPt) + ''); alDim = new LinearDimension(startPt, endPt, linePt, startPt.distanceTo(endPt) + '');
} }
app.m_Editor.AddNoSnapEntity(alDim); Jig.Draw(alDim);
app.m_Database.ModelSpace.Append(alDim);
app.m_Editor.Prompt("指定尺寸线位置:"); app.m_Editor.Prompt("指定尺寸线位置:");
ptRes = await app.m_Editor.GetPoint({ ptRes = await app.m_Editor.GetPoint({
@ -62,6 +62,7 @@ export class DrawAlignedDimension implements Command
if (ptRes.Status == PromptStatus.OK) if (ptRes.Status == PromptStatus.OK)
{ {
alDim.LinePoint = ptRes.Value; alDim.LinePoint = ptRes.Value;
app.m_Database.ModelSpace.Append(alDim);
} }
else if (ptRes.Status == PromptStatus.Keyword) else if (ptRes.Status == PromptStatus.Keyword)
{ {

@ -25,7 +25,7 @@ export class Entsel implements Command
dyn.SetPostion(vcs); dyn.SetPostion(vcs);
if (res.Entity instanceof Polyline) if (res.Entity instanceof Polyline)
dyn.updatePrompt(res.Entity.constructor.name + ",area:" + res.Entity.Area2); dyn.UpdatePrompt(res.Entity.constructor.name + ",area:" + res.Entity.Area2);
} }
else else
dyn.Visible = false; dyn.Visible = false;

@ -80,8 +80,8 @@ export class Command_Offset implements Command
{ {
let oldDir = 0; let oldDir = 0;
let oldSnap = app.m_Editor.m_GetpointServices.snapServices.m_Disabled; let oldSnap = app.m_Editor.m_GetpointServices.snapServices.Disabled;
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = true; app.m_Editor.m_GetpointServices.snapServices.Disabled = true;
let ptRes = await app.m_Editor.GetPoint({ let ptRes = await app.m_Editor.GetPoint({
Msg: "指定要偏移的那一侧的点", Msg: "指定要偏移的那一侧的点",
Callback: (p: Vector3) => Callback: (p: Vector3) =>
@ -96,7 +96,7 @@ export class Command_Offset implements Command
} }
} }
}); });
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = oldSnap; app.m_Editor.m_GetpointServices.snapServices.Disabled = oldSnap;
let status = { Status: ptRes.Status, offsetDist: 0 }; let status = { Status: ptRes.Status, offsetDist: 0 };
if (ptRes.Status === PromptStatus.OK) if (ptRes.Status === PromptStatus.OK)
{ {

@ -11,6 +11,7 @@ import { Command } from '../Editor/CommandMachine';
import { PromptStatus } from '../Editor/PromptResult'; import { PromptStatus } from '../Editor/PromptResult';
import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock'; import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock';
import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage'; import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage';
import { Jig } from '../Editor/Jig';
export class Command_ClosePt implements Command export class Command_ClosePt implements Command
@ -26,20 +27,16 @@ export class Command_ClosePt implements Command
{ {
let cu = cuRes.Entity as Curve; let cu = cuRes.Entity as Curve;
let line = new Line(); let line = new Line();
let closeCir = new Circle(new Vector3(), 0.5); let closeCir = new Circle(new Vector3(), 5);
let derLine = new Line(); let derLine = new Line();
app.m_Database.ModelSpace.Append(closeCir);
app.m_Database.ModelSpace.Append(line);
app.m_Database.ModelSpace.Append(derLine);
app.m_Editor.AddNoSnapEntity(closeCir); Jig.Draw(line);
app.m_Editor.AddNoSnapEntity(line); Jig.Draw(closeCir);
app.m_Editor.AddNoSnapEntity(derLine); Jig.Draw(derLine);
let extend = false; let extend = false;
while (true) while (true)
{ {
app.m_Editor.AddNoSnapEntity(line);
let p = await app.m_Editor.GetPoint({ let p = await app.m_Editor.GetPoint({
KeyWordList: [{ key: "C", msg: (extend ? "不" : "") + "延伸" }], KeyWordList: [{ key: "C", msg: (extend ? "不" : "") + "延伸" }],
Callback: p => Callback: p =>
@ -63,7 +60,7 @@ export class Command_ClosePt implements Command
vcs.add(new Vector3(0, -20, 0)); vcs.add(new Vector3(0, -20, 0));
dyn.SetPostion(vcs); dyn.SetPostion(vcs);
dyn.updatePrompt("点在线内外?:" + IsPointInPolyLine(cu, p)); dyn.UpdatePrompt("点在线内外?:" + IsPointInPolyLine(cu, p));
closeCir.Center = p; closeCir.Center = p;
closeCir.ColorIndex = GetPointAtCurveDir(cu, p) ? 1 : 2; closeCir.ColorIndex = GetPointAtCurveDir(cu, p) ? 1 : 2;
} }

@ -3,17 +3,18 @@ import * as xaop from 'xaop';
import { KeyBoard } from '../Common/KeyEnum'; import { KeyBoard } from '../Common/KeyEnum';
import { CADFile } from '../DatabaseServices/CADFile'; import { CADFile } from '../DatabaseServices/CADFile';
import { Database } from '../DatabaseServices/Database'; import { Database } from '../DatabaseServices/Database';
import { FontLoader } from '../DatabaseServices/Text/FontLoader';
import { CameraControls } from '../Editor/CameraControls'; import { CameraControls } from '../Editor/CameraControls';
import { commandMachine } from '../Editor/CommandMachine'; import { commandMachine } from '../Editor/CommandMachine';
import { DatGUI } from '../Editor/DebugDatUi'; import { DatGUI } from '../Editor/DebugDatUi';
import { Editor } from '../Editor/Editor'; import { Editor } from '../Editor/Editor';
import { Gesture } from '../Editor/Gesture';
import { RegisterGesture } from '../Editor/RegisterGesture';
import { SelectSetBase } from '../Editor/SelectBase'; import { SelectSetBase } from '../Editor/SelectBase';
import { Viewer } from '../GraphicsSystem/Viewer'; import { Viewer } from '../GraphicsSystem/Viewer';
import { appUi } from '../UI/Layout/ApplicationLayout'; import { appUi } from '../UI/Layout/ApplicationLayout';
import { layoutOnsizeEvent } from '../UI/Layout/LayoutOnSizeEventManage'; import { layoutOnsizeEvent } from '../UI/Layout/LayoutOnSizeEventManage';
import { Gesture } from '../Editor/Gesture'; import { DownPanelStore } from '../UI/Store/DownPanelStore';
import { RegisterGesture } from '../Editor/RegisterGesture';
import { FontLoader } from '../DatabaseServices/Text/FontLoader';
export var app: ApplicationService export var app: ApplicationService
@ -120,6 +121,11 @@ export class ApplicationService
} }
app.m_Editor.UpdateScreen(); app.m_Editor.UpdateScreen();
} }
else if (e.keyCode === KeyBoard.F8)
{
let s = DownPanelStore.Store();
s.useOrtho = !s.useOrtho;
}
}); });
//加载字体. //加载字体.

@ -75,7 +75,6 @@ export class CommandMachine
app.m_Database.hm.Undo(); app.m_Database.hm.Undo();
this.m_CommandIng = false; this.m_CommandIng = false;
app.m_Viewer.m_GripScene.UpdateAll(); app.m_Viewer.m_GripScene.UpdateAll();
app.m_Editor.ClearSnapEntity();
Jig.End(); Jig.End();
app.m_Editor.UpdateScreen(); app.m_Editor.UpdateScreen();
} }

@ -131,20 +131,6 @@ export class Editor
{ {
return this.m_SsgetServices.Start(prompt); return this.m_SsgetServices.Start(prompt);
} }
AddNoSnapEntity(e: Entity)
{
this.m_GetpointServices.snapServices.notSnapEntity.add(e);
}
RemoveNoSnapEntity(e)
{
this.m_GetpointServices.snapServices.notSnapEntity.delete(e);
}
ClearSnapEntity()
{
this.m_GetpointServices.snapServices.notSnapEntity.clear();
}
PointToScreen(pt: THREE.Vector3): THREE.Vector2 PointToScreen(pt: THREE.Vector3): THREE.Vector2
{ {
return null; return null;

@ -97,7 +97,7 @@ export class GetDistanceServices
if (prompt.Default !== undefined) if (prompt.Default !== undefined)
prompt.Msg += `<${prompt.Default}>`; prompt.Msg += `<${prompt.Default}>`;
dynInput.updatePrompt(prompt.Msg); dynInput.UpdatePrompt(prompt.Msg);
this.removeCalls.push(() => this.removeCalls.push(() =>
{ {
dynInput.Destroy(); dynInput.Destroy();

@ -144,7 +144,7 @@ export class GetEntityServices implements EditorService
private InitDynPrompt(prompt: GetEntityPrompt, mouseCtrl: MouseControls) private InitDynPrompt(prompt: GetEntityPrompt, mouseCtrl: MouseControls)
{ {
let dyn = new PromptBlock(DynamicInputManage.GetManage()); let dyn = new PromptBlock(DynamicInputManage.GetManage());
dyn.updatePrompt(prompt.Msg || "请选择对象:"); dyn.UpdatePrompt(prompt.Msg || "请选择对象:");
this.removeCalls.push(() => { dyn.Destroy(); }); this.removeCalls.push(() => { dyn.Destroy(); });
this.removeCalls.push(end(mouseCtrl, mouseCtrl.onMouseMove, () => this.removeCalls.push(end(mouseCtrl, mouseCtrl.onMouseMove, () =>
{ {

@ -266,13 +266,37 @@ export class GetPointServices implements EditorService
} }
else else
dynPrompt = new GetPointPromptBlock(DynamicInputManage.GetManage()); dynPrompt = new GetPointPromptBlock(DynamicInputManage.GetManage());
dynPrompt.updatePrompt(prompt.Msg); dynPrompt.UpdatePrompt(prompt.Msg);
this.removeCalls.push(() => this.removeCalls.push(() =>
{ {
dynPrompt.Destroy(); dynPrompt.Destroy();
}); });
this.removeCalls.push(xaop.end(this, this.UpdateCurPointEvent, () => this.removeCalls.push(xaop.end(this, this.UpdateCurPointEvent, () =>
{ {
//当存在轴线捕捉的时,并且不存在基点时,切换成轴线输入模式.
if (!prompt.BasePoint)
{
if (this.snapServices.m_AxisPts.length === 2)
{
if (dynPrompt instanceof GetPointPromptBlock)
{
dynPrompt.Destroy();
dynPrompt = new GetPoint2PromptBlock(DynamicInputManage.GetManage());
dynPrompt.BasePoint = this.snapServices.m_AxisPts[0];
dynPrompt.UpdatePrompt("轴线:");
}
}
else
{
if (dynPrompt instanceof GetPoint2PromptBlock)
{
dynPrompt.Destroy();
dynPrompt = new GetPointPromptBlock(DynamicInputManage.GetManage());
dynPrompt.UpdatePrompt(prompt.Msg);
}
}
}
dynPrompt.SetPostion(app.m_Editor.m_MouseCtrl.m_CurMousePointVCS); dynPrompt.SetPostion(app.m_Editor.m_MouseCtrl.m_CurMousePointVCS);
dynPrompt.Value = this.curPoint; dynPrompt.Value = this.curPoint;
})); }));

@ -1,131 +1,255 @@
import * as THREE from 'three'; import { BufferGeometry, Line, Matrix4, Object3D, Vector3, PerspectiveCamera } from 'three';
import { Matrix4, Vector3 } from 'three';
import { app } from '../ApplicationServices/Application'; import { app } from '../ApplicationServices/Application';
import { ColorMaterial } from '../Common/ColorPalette'; import { ColorMaterial } from '../Common/ColorPalette';
import { DisposeThreeObj } from '../Common/Dispose';
import { GetPointPrompt } from '../Common/InputState'; import { GetPointPrompt } from '../Common/InputState';
import { Entity } from '../DatabaseServices/Entity'; import { Entity } from '../DatabaseServices/Entity';
import { equaln, fixAngle, polar, SnapPoint } from '../Geometry/GeUtils'; import { Line as DbLine } from "../DatabaseServices/Line";
import { BufferGeometryUtils } from '../Geometry/BufferGeometryUtils';
import { cXAxis, cYAxis, cZAxis, isParallelTo, SnapPoint, midPoint } from '../Geometry/GeUtils';
import { IntersectLAndLFor3D } from '../GraphicsSystem/IntersectWith'; import { IntersectLAndLFor3D } from '../GraphicsSystem/IntersectWith';
import { DrawMode } from '../GraphicsSystem/PreViewer'; import { DrawMode } from '../GraphicsSystem/PreViewer';
import { PromptBlock } from '../UI/DynamicPrompt/PromptBlock';
import { DynamicInputManage } from '../UI/DynamicPrompt/DynamicInputManage';
/**
* 线
*/
export enum AxisSnapMode
{
Polar = 1,//极轴
Ortho = 2,//正交
}
//捕捉轴 //捕捉轴
interface SnapAxis interface SnapAxis
{ {
BasePoint: THREE.Vector3;//基点 BasePoint: Vector3;//基点
SnapPoint: THREE.Vector3;//捕捉到的点 SnapPoint: Vector3;//捕捉到的点
} }
//轴线相交数据 //轴线相交数据
interface SnapIntersect interface SnapIntersect
{ {
IntersectPoint: THREE.Vector3; IntersectPoint: Vector3;
Axis1: SnapAxis; Axis1: SnapAxis;
Axis2: SnapAxis; Axis2: SnapAxis;
} }
//正交捕捉轴
const OrthoAxis = [cXAxis, cYAxis, cZAxis];
const PolarAxis = [cXAxis, new Vector3(1, 1).normalize(), cYAxis, new Vector3(-1, 1).normalize(), cZAxis];
//提供点捕捉的服务. //提供点捕捉的服务.
export class SnapServices export class SnapServices
{ {
m_Disabled: boolean = false;//禁用捕捉 Disabled: boolean = false;//禁用捕捉
private preLines: THREE.Line[] = []; //前视图绘制的线表
notSnapEntity = new Set<Entity>();//不参与捕捉的实体列表,这个属性由开发人员维护.
SnapSize = 15;//捕捉框大小 SnapSize = 15;//捕捉框大小
private snapPoints: THREE.Vector3[] = [];//捕捉的点列表 AxisSnapMode = AxisSnapMode.Polar;//极轴捕捉模式
private m_SupportSnapPoints: Vector3[] = [];//辅助捕捉点WCS
private m_UCSInv: Matrix4;
private m_UCS: Matrix4;
m_AxisPts: Vector3[] = [];
SnapPoint: Vector3;
private m_DynPrompt: PromptBlock;
//开始捕捉 //开始捕捉
Start(prompt: GetPointPrompt) Start(prompt: GetPointPrompt)
{ {
if (prompt.BasePoint) this.snapPoints.push(prompt.BasePoint); this.m_UCSInv = app.m_Editor.UCSMatrixInv;
this.m_UCS = app.m_Editor.UCSMatrix;
this.InitDynPrompt();
this.InitCrossCursor();
this.InitAxisCursor();
this.InitSquareCursor();
this.InitBiasCrossCursor();
this.InitBiasOutline();
if (prompt.BasePoint)
{
this.m_SupportSnapPoints.push(prompt.BasePoint.clone());
this.UpdateCrossCursor();
}
} }
//结束捕捉服务 //结束捕捉服务
Stop() Stop()
{ {
this.DestroySnapLine(); this.m_SupportSnapPoints.length = 0;
this.snapPoints.length = 0; this.m_AxisPts.length = 0;
this.SnapPoint = undefined;
this.m_DynPrompt.Visible = false;
this.UpdateCursort();
} }
GetSnapPoint() private UpdateCursort()
{ {
this.DestroySnapLine(); this.UpdateAxisCursor();
this.DrawSnapCross(); this.UpdateSquareCursor();
this.UpdateCrossCursor();
this.UpdateBiasCrossCursor();
this.UpdateBiasOutline();
this.UpdateDynPrompt();
return this.GetEntitySnapPoint() || this.GetAxisSnapPoint(); app.m_Viewer.m_PreViewer.UpdateScreen();
} }
//-------------------计算函数//------------------- /**
* ,.
//根据角度进行轴线捕捉,如果存在捕捉,那么返回捕捉点,(极轴捕捉,正交捕捉) * @returns
private AxisSnap(basePoint: THREE.Vector3, fixAn: number): THREE.Vector3 */
GetSnapPoint(): Vector3 | undefined
{ {
let ucsInv = app.m_Editor.UCSMatrixInv; this.m_AxisPts.length = 0;
this.SnapPoint = this.GetEntitySnapPoint() || this.GetAxisSnapPoint();
let bpUCS = basePoint.clone().applyMatrix4(ucsInv); this.UpdateCursort();
let nowUCS = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone().applyMatrix4(ucsInv);
//相差向量 return this.SnapPoint;
let subVec = nowUCS.sub(bpUCS); }
let an = Math.atan2(subVec.y, subVec.x);
let newan = fixAngle(an, fixAn);
if (!isNaN(newan)) //延迟添加辅助的捕捉点
{ private m_DelaySupportSnapId;
//dis.
let v0 = new THREE.Vector3(0, 0, 0);
polar(v0, newan, 1);
let dis = v0.clone().dot(subVec); /**
* ,,,
* @returns
*/
private GetEntitySnapPoint()
{
if (this.Disabled) return;
if (this.m_DelaySupportSnapId)
{
clearTimeout(this.m_DelaySupportSnapId);
this.m_DelaySupportSnapId = undefined;
}
let ucsRo = new Matrix4().extractRotation(app.m_Editor.UCSMatrix); let vcsP = app.m_Editor.m_MouseCtrl.m_CurMousePointVCS;
v0.multiplyScalar(dis); for (let obj of app.m_Viewer.Scene.children)
v0.applyMatrix4(ucsRo); {
if (obj.userData && obj.userData instanceof Entity)
{
let ent = obj.userData;
if (ent.IsErase || ent.Id === undefined)
continue;
for (let p of ent.GetSnapPoints())
{
let pv = p.clone();
app.m_Viewer.WorldToScreen(pv);
if (SnapPoint(vcsP, pv, this.SnapSize))
{
if (!this.m_SupportSnapPoints.some(sp => sp.distanceToSquared(p) < 1e-5))
{
this.m_DelaySupportSnapId = setTimeout(() =>
{
this.m_SupportSnapPoints.push(p.clone());
if (this.m_SupportSnapPoints.length > 7)
this.m_SupportSnapPoints.shift();
return basePoint.clone().add(v0); this.UpdateCrossCursor();
}, 37);
}
return p.clone();
}
}
}
}
} }
//#region Z轴捕捉 /**
let zv = new Vector3(0, 0, 1); * 线,,,(,)
zv.applyMatrix4( * @param supportSnapPtUCS .
new Matrix4().getInverse( * @param nowPtUCS
new Matrix4().extractRotation(app.m_Viewer.Camera.matrix)) * @param snapAn
); * @param [isFirst]
if (equaln(zv.x, 0, 1e-8) && !(equaln(zv.y, 0, 1e-8) || equaln(zv.y, 1, 1e-8))) * @returns snapUCS
*/
private AxisSnap(supportSnapPtUCS: Vector3, nowPtUCS: Vector3, isFirst = false): Vector3
{ {
let bpVCS = app.m_Viewer.WorldToScreen(basePoint.clone()); let allowNegateSnap = true;//允许捕捉轴的反方向.
let nowVCS = app.m_Editor.m_MouseCtrl.m_CurMousePointVCS.clone(); let allowMouseDistSq = 100;//允许鼠标距离Sq
let axisVecs = PolarAxis;
if (this.AxisSnapMode === AxisSnapMode.Ortho)
{
axisVecs = OrthoAxis;
if (isFirst)
allowMouseDistSq = Infinity;
}
let nowVCS = app.m_Viewer.WorldToScreen(nowPtUCS.clone().applyMatrix4(this.m_UCS));
let v = nowVCS.clone().sub(bpVCS); let pts: Vector3[] = [supportSnapPtUCS.clone()];
an = Math.atan2(v.y, v.x); pts.push(...axisVecs.map(v => supportSnapPtUCS.clone().add(v)));
if (Math.abs(v.x) < 8) for (let p of pts)
{ {
let dir = app.m_Viewer.m_CameraCtrl.Direction; p.applyMatrix4(this.m_UCS);
app.m_Viewer.WorldToScreen(p);
}
let planVec: Vector3; let minIndex = 0, minP: Vector3, minDist = Infinity;
if (Math.abs(dir.x) > Math.abs(dir.y))
planVec = new Vector3(0, 1, 0); let l = new DbLine();
else l.StartPoint = pts[0];
planVec = new Vector3(1, 0, 0); for (let i = 1; i <= axisVecs.length; i++)
{
l.EndPoint = pts[i];
let { closestPt, param } = l.GetClosestAtPoint(nowVCS, true);
let dist = closestPt.distanceToSquared(nowVCS);
let np = app.m_Viewer.ScreenToWorld(nowVCS, planVec, basePoint); if (dist < minDist && (allowNegateSnap || param > 0))
return basePoint.clone().setZ(np.z); {
minIndex = i;
minDist = dist;
minP = closestPt;
} }
} }
//#endregion
//超过最大间隙
if (minDist > allowMouseDistSq)
return undefined; return undefined;
let snapAxis = axisVecs[minIndex - 1];
//Z轴
if (isParallelTo(snapAxis, cZAxis))
{
let dir = app.m_Viewer.m_CameraCtrl.Direction;
let supWcs = supportSnapPtUCS.clone().applyMatrix4(this.m_UCS);
if (app.m_Viewer.Camera instanceof PerspectiveCamera)
dir = app.m_Viewer.Camera.position.clone().sub(supWcs);
let zVecWcs = snapAxis.clone().applyMatrix4(new Matrix4().extractRotation(this.m_UCS));
dir.cross(zVecWcs).cross(zVecWcs);
let zp = app.m_Viewer.ScreenToWorld(minP, dir, supWcs).applyMatrix4(this.m_UCSInv);
return supportSnapPtUCS.clone().setZ(zp.z);
}
else
{
//相差向量
let subVec = nowPtUCS.clone().sub(supportSnapPtUCS);
let dis = snapAxis.dot(subVec);
return supportSnapPtUCS.clone().add(snapAxis.clone().multiplyScalar(dis));
}
} }
//返回合适的轴线交点,如果不存在交点,那么返回轴线上的点 //返回合适的轴线交点,如果不存在交点,那么返回轴线上的点
private GetAxisSnapPoint() private GetAxisSnapPoint()
{ {
//轴线列表 //轴线列表
let snapAxisList: SnapAxis[] = this.snapPoints.map((p) => let snapAxisList: SnapAxis[] = [];
let curPUCS = app.m_Editor.m_MouseCtrl.m_CurMousePointWCS.clone().applyMatrix4(this.m_UCSInv);
for (let i = 0, l = this.m_SupportSnapPoints.length; i < l; i++)
{ {
let snapPoint = this.AxisSnap(p, Math.PI * 0.5); let supWcs = this.m_SupportSnapPoints[i];
return { BasePoint: p, SnapPoint: snapPoint }; let supUCS = supWcs.clone().applyMatrix4(this.m_UCSInv);
}).filter(a => a.SnapPoint); let snapUCS = this.AxisSnap(supUCS, curPUCS, i === 0);
if (snapUCS)
snapAxisList.push({ BasePoint: supWcs, SnapPoint: snapUCS.applyMatrix4(this.m_UCS) });
}
if (snapAxisList.length === 0) if (snapAxisList.length === 0)
return; return;
@ -160,29 +284,30 @@ export class SnapServices
}); });
let insData = axisIntersectList[0]; let insData = axisIntersectList[0];
if (this.AxisSnapMode === AxisSnapMode.Ortho)
{
let p = this.AxisSnap(
this.m_SupportSnapPoints[0].clone().applyMatrix4(this.m_UCSInv),
insData.IntersectPoint.clone().applyMatrix4(this.m_UCSInv), true)
.applyMatrix4(this.m_UCS);
this.m_AxisPts = [insData.Axis1.BasePoint, p, insData.Axis2.BasePoint];
return p;
}
if (SnapPoint(app.m_Viewer.WorldToScreen(insData.IntersectPoint.clone()), mouseVcs, this.SnapSize)) if (SnapPoint(app.m_Viewer.WorldToScreen(insData.IntersectPoint.clone()), mouseVcs, this.SnapSize))
{ {
this.preLines.push( this.m_AxisPts = [insData.Axis1.BasePoint, insData.IntersectPoint, insData.Axis2.BasePoint];
//交叉轴线
app.m_Viewer.m_PreViewer.DrawLine(
[insData.Axis1.BasePoint, insData.IntersectPoint, insData.Axis2.BasePoint],
ColorMaterial.SnapAxisMaterial
),
//X光标
app.m_Viewer.m_PreViewer.Draw(
DrawMode.BaisCross,
this.SnapSize,
insData.IntersectPoint.clone(),
ColorMaterial.GetLineMaterial(3),
true
)
);
app.m_Viewer.m_PreViewer.UpdateScreen();
return insData.IntersectPoint.clone(); return insData.IntersectPoint.clone();
} }
} }
else//如果没有交叉点,那么使用轴线上的点 else//如果没有交叉点,那么使用轴线上的点
{ {
if (this.AxisSnapMode === AxisSnapMode.Ortho)
{
this.m_AxisPts = [snapAxisList[0].BasePoint, snapAxisList[0].SnapPoint];
return snapAxisList[0].SnapPoint;
}
snapAxisList.sort((d1, d2) => snapAxisList.sort((d1, d2) =>
{ {
return app.m_Viewer.WorldToScreen(d1.SnapPoint.clone()).distanceToSquared(mouseVcs) return app.m_Viewer.WorldToScreen(d1.SnapPoint.clone()).distanceToSquared(mouseVcs)
@ -190,81 +315,188 @@ export class SnapServices
}); });
let snapAxis = snapAxisList[0]; let snapAxis = snapAxisList[0];
this.m_AxisPts = [snapAxis.BasePoint, snapAxis.SnapPoint];
return snapAxis.SnapPoint;
}
}
//#region 绘制
this.preLines.push( /**
app.m_Viewer.m_PreViewer.DrawLine( *
[snapAxis.BasePoint, snapAxis.SnapPoint], */
ColorMaterial.SnapAxisMaterial private m_CrossCursor: Object3D[] = [];
/**
* ()
*/
private InitCrossCursor()
{
if (this.m_CrossCursor.length === 0)
{
let preView = app.m_Viewer.m_PreViewer;
for (let i = 0; i < 7; i++)
{
this.m_CrossCursor.push(
preView.Draw(
DrawMode.Cross,
this.SnapSize,
new Vector3(),
ColorMaterial.GetLineMaterial(3))
) )
); }
app.m_Viewer.m_PreViewer.UpdateScreen();
return snapAxis.SnapPoint;
} }
} }
//计算图形的捕捉点 如果有 则返回. /**
private GetEntitySnapPoint() *
*/
private UpdateCrossCursor()
{ {
if (this.m_Disabled) return; let preView = app.m_Viewer.m_PreViewer;
let vcsP = app.m_Editor.m_MouseCtrl.m_CurMousePointVCS; for (let i = 0; i < 7; i++)
for (let obj of app.m_Viewer.Scene.children)
{ {
if (obj.userData && obj.userData instanceof Entity) let l = this.m_CrossCursor[i];
if (this.m_SupportSnapPoints[i])
{
l.position.copy(preView.WorldToViewPoint(this.m_SupportSnapPoints[i].clone()));
l.visible = true;
}
else
l.visible = false;
}
preView.UpdateScreen();
}
private m_AxisCursor: Line;
/**
* 线
*/
private InitAxisCursor()
{ {
if (this.notSnapEntity.has(obj.userData)) continue; if (!this.m_AxisCursor)
if (obj.userData.IsErase) continue; this.m_AxisCursor = app.m_Viewer.m_PreViewer.DrawLine(
if (!obj.userData.Id) continue; [new Vector3(), new Vector3(), new Vector3()],
for (let p of obj.userData.GetSnapPoints()) ColorMaterial.SnapAxisMaterial,
);
}
private UpdateAxisCursor()
{ {
let pv = p.clone(); if (this.m_AxisPts.length > 0)
app.m_Viewer.WorldToScreen(pv);
if (SnapPoint(vcsP, pv, this.SnapSize))
{ {
if (!this.snapPoints.some(sp => { return sp.distanceToSquared(p) < 1e-5 })) this.m_AxisCursor.visible = true;
let geo = this.m_AxisCursor.geometry as BufferGeometry;
BufferGeometryUtils.UpdatePts(geo, this.m_AxisPts.map(p =>
{ {
this.snapPoints.push(p); return app.m_Viewer.m_PreViewer.WorldToViewPoint(p.clone());
if (this.snapPoints.length > 7) }));
this.snapPoints.shift(); geo.drawRange.count = this.m_AxisPts.length;
this.m_AxisCursor.computeLineDistances();
} }
this.preLines.push( else
app.m_Viewer.m_PreViewer.Draw( this.m_AxisCursor.visible = false;
DrawMode.Square, }
this.SnapSize,
p.clone(), //方向光标,用于捕捉实体夹点
private m_SquareCursor: Line;
private InitSquareCursor()
{
if (!this.m_SquareCursor)
this.m_SquareCursor = app.m_Viewer.m_PreViewer.Draw(
DrawMode.Square, this.SnapSize, new Vector3(),
ColorMaterial.GetLineMaterial(3) ColorMaterial.GetLineMaterial(3)
)
); );
return p.clone();
} }
private UpdateSquareCursor()
{
this.UpdateObjectPosition(
this.m_SquareCursor,
this.SnapPoint && this.m_AxisPts.length === 0
);
} }
private m_BiasCrossCursor: Line;
//×光标,用于捕捉轴线
private InitBiasCrossCursor()
{
if (!this.m_BiasCrossCursor)
{
this.m_BiasCrossCursor = app.m_Viewer.m_PreViewer.Draw(
DrawMode.BaisCross,
8,
new Vector3(),
ColorMaterial.GetLineMaterial(3)
);
} }
} }
private UpdateBiasCrossCursor()
{
this.UpdateObjectPosition(
this.m_BiasCrossCursor,
this.m_AxisPts.length > 0
);
} }
//-------------------绘制函数------------------- private m_BiasOutline: Line;
//初始化X光标外包围框(虚线),用户显示光标交叉
//绘制所有的十字光标 private InitBiasOutline()
private DrawSnapCross()
{ {
let preView = app.m_Viewer.m_PreViewer; if (!this.m_BiasOutline)
for (let snapP of this.snapPoints) this.m_BiasOutline = app.m_Viewer.m_PreViewer.Draw(
this.preLines.push( DrawMode.Square,
preView.Draw(
DrawMode.Cross,
this.SnapSize, this.SnapSize,
snapP.clone(), new Vector3(),
ColorMaterial.GetLineMaterial(3)) ColorMaterial.SnapAxisMaterial,
)
}
private UpdateBiasOutline()
{
this.UpdateObjectPosition(
this.m_BiasOutline,
this.m_AxisPts.length > 2
); );
} }
//销毁绘制的函数 private UpdateObjectPosition(obj: Object3D, update: boolean)
private DestroySnapLine() {
if (update)
{
obj.visible = true;
obj.position.copy(
app.m_Viewer.m_PreViewer.WorldToViewPoint(this.SnapPoint.clone())
);
}
else
obj.visible = false;
}
InitDynPrompt()
{
if (!this.m_DynPrompt)
{ {
this.preLines.forEach(l => this.m_DynPrompt = new PromptBlock(DynamicInputManage.GetManage());
this.m_DynPrompt.Visible = false;
}
}
UpdateDynPrompt()
{
if (this.m_AxisPts.length === 2
&& isParallelTo(cZAxis,
this.m_AxisPts[1].clone().sub(this.m_AxisPts[0])
.applyMatrix4(new Matrix4().extractRotation(this.m_UCSInv))
)
)
{ {
l.parent.remove(l); this.m_DynPrompt.Visible = true;
DisposeThreeObj(l); this.m_DynPrompt.UpdatePrompt("Z轴");
}) let vps = this.m_AxisPts.map(p => app.m_Viewer.WorldToScreen(p.clone()));
this.preLines.length = 0; this.m_DynPrompt.SetPostion(midPoint(vps[0], vps[1]));
} }
else
this.m_DynPrompt.Visible = false;
}
//#endregion
} }

@ -3,13 +3,12 @@ import { end } from 'xaop';
import { app } from '../../ApplicationServices/Application'; import { app } from '../../ApplicationServices/Application';
import { InputState } from '../../Common/InputState'; import { InputState } from '../../Common/InputState';
import { MouseKey } from '../../Common/KeyEnum'; import { MouseKey } from '../../Common/KeyEnum';
import { CADFile } from '../../DatabaseServices/CADFile';
import { Entity } from '../../DatabaseServices/Entity'; import { Entity } from '../../DatabaseServices/Entity';
import { MoveMatrix } from '../../Geometry/GeUtils'; import { MoveMatrix } from '../../Geometry/GeUtils';
import { RenderType } from '../../GraphicsSystem/Enum';
import { PreViewer } from '../../GraphicsSystem/PreViewer'; import { PreViewer } from '../../GraphicsSystem/PreViewer';
import { commandMachine } from '../CommandMachine'; import { commandMachine } from '../CommandMachine';
import { Editor, EditorService } from '../Editor'; import { Editor, EditorService } from '../Editor';
import { Jig } from '../Jig';
import { PointPick } from '../PointPick'; import { PointPick } from '../PointPick';
import { PromptStatus } from '../PromptResult'; import { PromptStatus } from '../PromptResult';
import { MatrixToPreViewMat } from '../UCSServices'; import { MatrixToPreViewMat } from '../UCSServices';
@ -87,13 +86,7 @@ export class TransformServicess implements EditorService
app.m_Database.hm.StartCmd("_move"); app.m_Database.hm.StartCmd("_move");
app.m_Viewer.m_GripScene.visible = false; app.m_Viewer.m_GripScene.visible = false;
let newEns: { old: Entity, new: Entity }[] = this.m_Ents.map(e => let jigEns = this.m_Ents.map(e => Jig.Draw(e));
{
let newE = e.Clone() as Entity;
app.m_Viewer.Scene.add(newE.Draw(RenderType.Wireframe));
app.m_Editor.AddNoSnapEntity(newE);
return { old: e, new: newE };
});
let base = new THREE.Vector3().setFromMatrixColumn(this.m_Matrix, 3); let base = new THREE.Vector3().setFromMatrixColumn(this.m_Matrix, 3);
let ptRes = await this.m_Editor.GetPoint({ let ptRes = await this.m_Editor.GetPoint({
@ -102,28 +95,18 @@ export class TransformServicess implements EditorService
AllowDrawRubberBand: true, AllowDrawRubberBand: true,
Callback: (newP) => Callback: (newP) =>
{ {
for (let piar of newEns) Jig.Restore();
{ let m = MoveMatrix(newP.clone().sub(base));
let f = new CADFile(); for (let e of jigEns)
piar.old.WriteFile(f); e.ApplyMatrix(m);
piar.new.ReadFile(f);
piar.new.ApplyMatrix(MoveMatrix(newP.clone().sub(base)));
}
app.m_Editor.UpdateScreen(); app.m_Editor.UpdateScreen();
} }
}); });
newEns.forEach(p =>
{
p.new.GoodBye();
});
if (ptRes.Status === PromptStatus.OK) if (ptRes.Status === PromptStatus.OK)
{ {
let m = MoveMatrix(ptRes.Value.sub(base)); let m = MoveMatrix(ptRes.Value.sub(base));
newEns.forEach(p => for (let e of this.m_Ents)
{ e.ApplyMatrix(m);
p.old.ApplyMatrix(m);
})
} }
app.m_Viewer.m_GripScene.visible = true; app.m_Viewer.m_GripScene.visible = true;

@ -2,10 +2,10 @@ import * as THREE from 'three';
import { Box3, BufferGeometry, Geometry, Matrix4, Vector, Vector2, Vector3, BufferAttribute } from 'three'; import { Box3, BufferGeometry, Geometry, Matrix4, Vector, Vector2, Vector3, BufferAttribute } from 'three';
import { Matrix2 } from './Matrix2'; import { Matrix2 } from './Matrix2';
export const cZeroVec = new THREE.Vector3(); export const cZeroVec = new Vector3();
export const cXAxis = new THREE.Vector3(1, 0, 0); export const cXAxis = new Vector3(1, 0, 0);
export const cYAxis = new THREE.Vector3(0, 1, 0); export const cYAxis = new Vector3(0, 1, 0);
export const cZAxis = new THREE.Vector3(0, 0, 1); export const cZAxis = new Vector3(0, 0, 1);
/** /**
* , * ,
@ -43,23 +43,6 @@ export function greater(v1, v2, fuzz = 0)
return v1 - v2 > fuzz; return v1 - v2 > fuzz;
} }
/**
*
* @param an
* @param fixAngle
* @param [fuzz]
* @returns
*/
export function fixAngle(an: number, fixAngle: number, fuzz: number = 0.05)
{
let s = an / fixAngle;
let sf = Math.round(s);
if (equaln(s, sf, fuzz))
return sf * fixAngle;
else return NaN;
}
/** /**
* *
* *
@ -220,9 +203,9 @@ export function GetBoxArr(arr: Array<THREE.Object3D>): THREE.Box3
return box; return box;
} }
export function MoveMatrix(v: THREE.Vector3): THREE.Matrix4 export function MoveMatrix(v: Vector3): Matrix4
{ {
return new THREE.Matrix4().setPosition(v); return new Matrix4().setPosition(v);
} }
export function getProjectDist(v1: Vector3, v2: Vector3) export function getProjectDist(v1: Vector3, v2: Vector3)
@ -247,24 +230,17 @@ export function getPtPostion(sp: Vector3, ep: Vector3, c: Vector3, inPt: Vector3
let ang3 = ang2 + Math.abs(ang1); let ang3 = ang2 + Math.abs(ang1);
let inputAng = angleTo(l1, inputLine); let inputAng = angleTo(l1, inputLine);
if (ang1 * inputAng < 0) if (ang1 * inputAng < 0)
{
inputAng = (Math.PI * 2 - Math.abs(inputAng)); inputAng = (Math.PI * 2 - Math.abs(inputAng));
}
ang1 = Math.abs(ang1); ang1 = Math.abs(ang1);
inputAng = Math.abs(inputAng); inputAng = Math.abs(inputAng);
if (inputAng <= ang1) if (inputAng <= ang1)
{
return { sp, ep }; return { sp, ep };
} else if (inputAng > ang1 && inputAng <= ang2) else if (inputAng > ang1 && inputAng <= ang2)
{
return { sp: c.clone().add(l3), ep } return { sp: c.clone().add(l3), ep }
} else if (inputAng > ang2 && inputAng <= ang3) else if (inputAng > ang2 && inputAng <= ang3)
{
return { sp: c.clone().add(l3), ep: c.clone().add(l4) } return { sp: c.clone().add(l3), ep: c.clone().add(l4) }
} else else
{
return { sp, ep: c.clone().add(l4) }; return { sp, ep: c.clone().add(l4) };
}
} }
export function angleAndX(v: Vector3 | Vector2) export function angleAndX(v: Vector3 | Vector2)
{ {

@ -186,6 +186,16 @@ export class DownPanel extends React.Component<{ store?: DownPanelStore }, {}>
style={switchStyle} style={switchStyle}
alignIndicator={Alignment.RIGHT} alignIndicator={Alignment.RIGHT}
/> />
<Switch
checked={this.props.store.useOrtho}
label="正交"
onChange={e =>
{
this.props.store.useOrtho = e.currentTarget.checked;
}}
style={switchStyle}
alignIndicator={Alignment.RIGHT}
/>
<div style={switchStyle}> <div style={switchStyle}>
<label></label> <label></label>
<HTMLSelect <HTMLSelect

@ -107,6 +107,8 @@ export class DynamicInput
default: default:
break; break;
} }
if (e.keyCode !== KeyBoard.F8)
e.stopPropagation(); e.stopPropagation();
} }

@ -13,7 +13,7 @@ export class GetDistancePromptBlock extends PromptBlock
super(dynamicInputManage); super(dynamicInputManage);
this.valueDynIpt = new RealDynamicInput(this.promptContainer); this.valueDynIpt = new RealDynamicInput(this.promptContainer);
dynamicInputManage.AddDynamicInput(this.valueDynIpt); dynamicInputManage.AddDynamicInput(this.valueDynIpt);
this.updatePrompt("请点击或者输入距离:"); this.UpdatePrompt("请点击或者输入距离:");
} }
//设置输入距离的位置 //设置输入距离的位置

@ -55,7 +55,7 @@ export class GetPointPromptBlock extends PromptBlock
{ {
this.AddDynamicInput(o); this.AddDynamicInput(o);
}) })
this.updatePrompt("请输入一个点:"); this.UpdatePrompt("请输入一个点:");
dynamicInputManage.FocusIndex = 0; dynamicInputManage.FocusIndex = 0;
} }
@ -113,7 +113,7 @@ export class GetPoint2PromptBlock extends PromptBlock
this.angleDynIpt = new AngleDynamicInput(this.promptContainer); this.angleDynIpt = new AngleDynamicInput(this.promptContainer);
dynamicInputManage.AddDynamicInput(this.angleDynIpt); dynamicInputManage.AddDynamicInput(this.angleDynIpt);
this.angleDynIpt.Fixed = true; this.angleDynIpt.Fixed = true;
this.updatePrompt("请点击或者输入距离:"); this.UpdatePrompt("请点击或者输入距离:");
dynamicInputManage.FocusIndex = 0; dynamicInputManage.FocusIndex = 0;
} }
set BasePoint(v: Vector3) set BasePoint(v: Vector3)
@ -150,8 +150,11 @@ export class GetPoint2PromptBlock extends PromptBlock
); );
app.m_Viewer.WorldToScreen(angPos); app.m_Viewer.WorldToScreen(angPos);
angPos.clamp(new Vector3(), new Vector3(app.m_Viewer.Width - 38, app.m_Viewer.Height - 24)); let angRect = this.angleDynIpt.inputEl.getBoundingClientRect();
angPos.y += 70; let angSize = new Vector3(angRect.width, angRect.height);
angPos.clamp(new Vector3(), new Vector3(app.m_Viewer.Width, app.m_Viewer.Height).sub(angSize));
angPos.y += app.m_Viewer.m_DomEl.getBoundingClientRect().top;
this.angleDynIpt.SetPosition(angPos.x, angPos.y); this.angleDynIpt.SetPosition(angPos.x, angPos.y);
} }
get Value(): Vector3 get Value(): Vector3

@ -61,7 +61,7 @@ export class PromptBlock
this.dynamicInputManage.Focus(); this.dynamicInputManage.Focus();
} }
public updatePrompt(prompt: string) public UpdatePrompt(prompt: string)
{ {
if (prompt) this.promptEl.innerText = prompt; if (prompt) this.promptEl.innerText = prompt;
} }

@ -2,6 +2,7 @@ import { autorun, observable } from 'mobx';
import { Vector3 } from 'three'; import { Vector3 } from 'three';
import * as xaop from 'xaop'; import * as xaop from 'xaop';
import { app } from '../../ApplicationServices/Application'; import { app } from '../../ApplicationServices/Application';
import { AxisSnapMode } from '../../Editor/SnapServices';
//点转换为字符串. //点转换为字符串.
function PointToString(pt: Vector3): string function PointToString(pt: Vector3): string
@ -22,6 +23,7 @@ export class DownPanelStore
@observable showToolBar: boolean = true; @observable showToolBar: boolean = true;
@observable useDynSnap: boolean = true; @observable useDynSnap: boolean = true;
@observable usePass: boolean = true; @observable usePass: boolean = true;
@observable useOrtho: boolean = false;
@observable fontName: string = "songti"; @observable fontName: string = "songti";
private constructor() private constructor()
{ {
@ -31,8 +33,10 @@ export class DownPanelStore
}); });
autorun(() => autorun(() =>
{ {
app.m_Editor.m_GetpointServices.snapServices.m_Disabled = !this.useDynSnap; app.m_Editor.m_GetpointServices.snapServices.Disabled = !this.useDynSnap;
app.m_Editor.m_GetpointServices.snapServices.AxisSnapMode = this.useOrtho ? AxisSnapMode.Ortho : AxisSnapMode.Polar;
app.m_Viewer.m_bUsePass = this.usePass; app.m_Viewer.m_bUsePass = this.usePass;
}); });
} }

Loading…
Cancel
Save