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.
WebCAD/src/Editor/BoardMoveTool.ts

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);
}
}
}