mirror of https://gitee.com/cf-fz/WebCAD.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
9.0 KiB
283 lines
9.0 KiB
import { Intersection, Object3D, Raycaster, Vector3 } from "three";
|
|
import { begin, end } from "xaop";
|
|
import { app } from "../ApplicationServices/Application";
|
|
import { Sleep } from "../Common/Sleep";
|
|
import { FixedNotZero, GetEntity } from "../Common/Utils";
|
|
import { CommandHistoryRecord } from "../DatabaseServices/CommandHistoryRecord";
|
|
import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension";
|
|
import { Board } from "../DatabaseServices/Entity/Board";
|
|
import { equaln, rotatePoint } from "../Geometry/GeUtils";
|
|
import { RenderType } from "../GraphicsSystem/RenderType";
|
|
import { CommandState } from "./CommandState";
|
|
import { Raycast } from "./PointPick";
|
|
|
|
export class BoardMoveTool
|
|
{
|
|
_DrawDimPoints: [Vector3, Vector3][];
|
|
|
|
_DrawDims: AlignedDimension[] = [];
|
|
|
|
_Board: Board;
|
|
ForceUpdate = false;
|
|
constructor()
|
|
{
|
|
let selectCtrl = app.Editor.SelectCtrl;
|
|
end(selectCtrl, selectCtrl.UpdateSelectEvent, async () =>
|
|
{
|
|
if (!CommandState.CommandIng)
|
|
{
|
|
let set = selectCtrl.SelectSet;
|
|
if (set.SelectObjectCount > 200) return;
|
|
|
|
for (let i = set._SelectSetList.length; i--;)
|
|
{
|
|
let s = set._SelectSetList[i];
|
|
let br: Board;
|
|
for (let o of s._SelectList)
|
|
{
|
|
let e = GetEntity(o);
|
|
if (e instanceof Board)
|
|
br = e;
|
|
}
|
|
if (br)
|
|
{
|
|
this._Board = br;
|
|
this.HitBoard(this._Board);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
begin(app.Viewer.PreViewer, app.Viewer.PreViewer.UpdateScreen, () =>
|
|
{
|
|
this.UpdateDimensionDraw();
|
|
});
|
|
|
|
end(selectCtrl, selectCtrl.CanenEvent, () =>
|
|
{
|
|
this.Clear();
|
|
});
|
|
|
|
//监听模块树的变更,当变更时,刷新视图
|
|
end(app.Database.hm, app.Database.hm.RedoEvent, (cmdName: string, historyRec: CommandHistoryRecord) =>
|
|
{
|
|
this._Board && this.HitBoard(this._Board);
|
|
});
|
|
end(app.Database.hm, app.Database.hm.UndoEvent, (cmdName: string, historyRec: CommandHistoryRecord) =>
|
|
{
|
|
this._Board && this.HitBoard(this._Board);
|
|
});
|
|
app.CommandReactor.OnCommandEnd((cmdName, changeObjects, createObjects) =>
|
|
{
|
|
this._Board && this.HitBoard(this._Board);
|
|
});
|
|
end(app.Database, app.Database.FileRead, () =>
|
|
{
|
|
this.Clear();
|
|
});
|
|
}
|
|
|
|
Clear()
|
|
{
|
|
this._Board = undefined;
|
|
this._DrawDimPoints = undefined;
|
|
this.ForceUpdate = false;
|
|
this.UpdateDimensionDraw();
|
|
app.Viewer.PreViewer.UpdateScreen();
|
|
}
|
|
|
|
private async HitBoard(br: Board)
|
|
{
|
|
await Sleep(1);
|
|
let brOCS = br.OCS;
|
|
let brRot = brOCS.clone().setPosition(0, 0, 0);
|
|
let brOCSInv = br.OCSInv;
|
|
let brNormal = br.Normal;
|
|
let brNormal2 = brNormal.clone().negate();
|
|
|
|
let brsObject: Object3D[] = [];
|
|
let start = performance.now();
|
|
let i = 0;
|
|
for (let obj of app.Viewer.Scene.children)
|
|
{
|
|
if (obj.visible)
|
|
{
|
|
i++;
|
|
if (i > 30)
|
|
{
|
|
let now = performance.now();
|
|
let r = now - start;
|
|
if (now - start > 15)
|
|
{
|
|
await Sleep(1);
|
|
start = now;
|
|
}
|
|
else
|
|
{
|
|
i -= (16 - r) * 3;
|
|
}
|
|
}
|
|
let ent = GetEntity(obj);
|
|
if (ent instanceof Board && ent !== br)
|
|
{
|
|
brsObject.push(ent.GetDrawObjectFromRenderType(RenderType.Physical));
|
|
}
|
|
}
|
|
}
|
|
|
|
let dimPoints: [Vector3, Vector3][] = [];
|
|
|
|
//首先计算四周的板件
|
|
let sideBoards: Board[] = [];
|
|
let pl = br.ContourCurve;
|
|
let d = Math.sign(pl.Area2);
|
|
for (let i = 0.5; i < pl.EndParam; i++)
|
|
{
|
|
let p = pl.GetPointAtParam(i);
|
|
let derv = pl.GetFistDeriv(i).normalize();
|
|
rotatePoint(derv, Math.PI * -0.5 * d);
|
|
derv.applyMatrix4(brRot);
|
|
p.setZ(br.Thickness * 0.5);
|
|
p.applyMatrix4(brOCS);
|
|
await Sleep(1);
|
|
let intersection = this.RayPoint(p, derv, brsObject);
|
|
|
|
if (intersection)
|
|
{
|
|
sideBoards.push(GetEntity(intersection.object) as Board);
|
|
if (intersection.distance > 0.1)
|
|
dimPoints.push([p, intersection.point]);
|
|
}
|
|
}
|
|
|
|
//计算最高和最低
|
|
let maxZ = -Infinity;
|
|
let minZ = Infinity;
|
|
for (let sbr of sideBoards)
|
|
{
|
|
let sbrOCS = sbr.OCS;
|
|
let mtx = sbrOCS.multiplyMatrices(brOCSInv, sbrOCS);
|
|
for (let p of [new Vector3(), new Vector3(sbr.Width), new Vector3(sbr.Width, sbr.Height), new Vector3(0, sbr.Height)])
|
|
{
|
|
p.applyMatrix4(mtx);
|
|
maxZ = Math.max(maxZ, p.z - br.Thickness);
|
|
minZ = Math.min(minZ, p.z);
|
|
}
|
|
}
|
|
|
|
//正面
|
|
{
|
|
let dist: number;
|
|
let centerP: Vector3;
|
|
for (let y of [0.5, 0.71, 0.21])
|
|
{
|
|
let p = new Vector3(br.Width * 0.5, br.Height * y, br.Thickness).applyMatrix4(brOCS);
|
|
centerP = centerP ?? p;
|
|
await Sleep(1);
|
|
let intersection = this.RayPoint(p, brNormal, brsObject);
|
|
if (intersection)
|
|
{
|
|
if (dist !== undefined && equaln(dist, intersection.distance, 0.1))
|
|
continue;
|
|
|
|
dist = dist ?? intersection.distance;
|
|
if (intersection.distance > 0.01)
|
|
{
|
|
dimPoints.push([p, intersection.point]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dist === undefined && maxZ > 0)
|
|
{
|
|
let tp = centerP.clone().add(brNormal.clone().multiplyScalar(maxZ));
|
|
dimPoints.push([centerP, tp]);
|
|
}
|
|
}
|
|
|
|
//反面
|
|
{
|
|
let dist: number;
|
|
let centerP: Vector3;
|
|
for (let y of [0.5, 0.71, 0.21])
|
|
{
|
|
let p = new Vector3(br.Width * 0.5, br.Height * y, 0).applyMatrix4(brOCS);
|
|
centerP = centerP ?? p;
|
|
await Sleep(1);
|
|
let intersection = this.RayPoint(p, brNormal2, brsObject);
|
|
if (intersection)
|
|
{
|
|
if (dist !== undefined && equaln(dist, intersection.distance, 0.1))
|
|
continue;
|
|
|
|
dist = dist ?? intersection.distance;
|
|
if (intersection.distance > 0.01)
|
|
dimPoints.push([p, intersection.point]);
|
|
}
|
|
}
|
|
|
|
if (dist === undefined && minZ < 0)
|
|
{
|
|
let tp = centerP.clone().sub(brNormal2.clone().multiplyScalar(minZ));
|
|
dimPoints.push([centerP, tp]);
|
|
}
|
|
}
|
|
|
|
this._DrawDimPoints = dimPoints;
|
|
|
|
this.UpdateDimensionDraw();
|
|
app.Viewer.PreViewer.UpdateScreen();
|
|
}
|
|
|
|
private RayPoint(p: Vector3, n: Vector3, brs: Object3D[]): Intersection
|
|
{
|
|
let ray = new Raycaster(p, n);
|
|
let intersection = Raycast(ray, brs);
|
|
return intersection;
|
|
}
|
|
|
|
|
|
private UpdateDimensionDraw()
|
|
{
|
|
if ((!this._DrawDimPoints || CommandState.CommandIng) && !this.ForceUpdate)
|
|
{
|
|
for (let dim of this._DrawDims)
|
|
dim.Visible = false;
|
|
|
|
return;
|
|
}
|
|
|
|
for (let i = this._DrawDims.length; i < this._DrawDimPoints.length; i++)
|
|
{
|
|
let dim = new AlignedDimension();
|
|
dim.Text.Height = 20;
|
|
dim.LeadOutVisible = false;
|
|
this._DrawDims.push(dim);
|
|
app.Viewer.PreViewer.Scene.add(dim.DrawObject);
|
|
}
|
|
|
|
for (let i = this._DrawDimPoints.length; i < this._DrawDims.length; i++)
|
|
{
|
|
let dim = this._DrawDims[i];
|
|
dim.Visible = false;
|
|
}
|
|
|
|
for (let i = 0; i < this._DrawDimPoints.length; i++)
|
|
{
|
|
let dim = this._DrawDims[i];
|
|
dim.Visible = true;
|
|
let pts = this._DrawDimPoints[i];
|
|
|
|
let p1 = app.Viewer.PreViewer.WorldToViewPoint(pts[0].clone()).setZ(0);
|
|
let p2 = app.Viewer.PreViewer.WorldToViewPoint(pts[1].clone()).setZ(0);
|
|
dim.FootP1 = p1;
|
|
dim.ArmP1 = p1;
|
|
dim.FootP2 = p2;
|
|
dim.ArmP2 = p2;
|
|
dim.TextRotation = 0;
|
|
dim.TextString = FixedNotZero(pts[0].distanceTo(pts[1]), 2);
|
|
}
|
|
}
|
|
}
|