mirror of https://gitee.com/cf-fz/WebCAD.git
!1853 新增:模拟走刀增加孔位标注
parent
eab3fc6d82
commit
108dd05ef5
@ -0,0 +1,518 @@
|
||||
import { Intent } from "@blueprintjs/core";
|
||||
import { Box3, Matrix4, Vector3 } from "three";
|
||||
import { app } from "../ApplicationServices/Application";
|
||||
import { arrayRemoveIf } from "../Common/ArrayExt";
|
||||
import { Sleep } from "../Common/Sleep";
|
||||
import { FixedNotZero } from "../Common/Utils";
|
||||
import { DimStyleKeyCode } from "../DatabaseServices/DimStyle/DimstyleKeyCodeEnum";
|
||||
import { AlignedDimension } from "../DatabaseServices/Dimension/AlignedDimension";
|
||||
import { Line } from "../DatabaseServices/Entity/Line";
|
||||
import { angle, equalv3, isParallelTo } from "../Geometry/GeUtils";
|
||||
import { IntersectOption } from "../GraphicsSystem/IntersectWith";
|
||||
import { IDrillingOption, ISpliteOrderData } from "../Production/Product";
|
||||
import { AppToaster } from "../UI/Components/Toaster";
|
||||
|
||||
const AddLeadYNum = 30;
|
||||
|
||||
export async function DrawHoleDim(info: ISpliteOrderData, tMtx: Matrix4, contouLines: Line[], dimStyle: Map<DimStyleKeyCode, any>, box: Box3, originContourBox: Box3)
|
||||
{
|
||||
if (!contouLines.length)
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "未找到合适的标注点位",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const Offset = info.offsetTanslation;
|
||||
const PlCenter = originContourBox.getCenter(new Vector3);
|
||||
const PlBoxSize = originContourBox.getSize(new Vector3);
|
||||
//侧边孔信息
|
||||
const SideHoleOptions = info.holes.sideHoles;
|
||||
//正反面孔信息
|
||||
const FrontBackHoleOptions = [...info.holes.frontBackHoles];
|
||||
//侧边孔在某条边路径上
|
||||
const SideHoleLineMap: Map<Line, IDrillingOption[]> = new Map();
|
||||
//正反面孔 在这条线段的侧孔的endPt上
|
||||
const OnSideEndPtOptions: Map<Line, IDrillingOption[]> = new Map();
|
||||
|
||||
//分析侧孔所在的轮廓线
|
||||
for (let line of contouLines)
|
||||
{
|
||||
let holeOptions = SideHoleOptions.filter((hole) => line.PtOnCurve(new Vector3(hole.position.x, hole.position.y)));
|
||||
if (holeOptions.length)
|
||||
{
|
||||
SideHoleLineMap.set(line, holeOptions);
|
||||
|
||||
//分析正反面孔 在这条线段的侧孔的endPt上
|
||||
let options = [];
|
||||
arrayRemoveIf(FrontBackHoleOptions, (option) =>
|
||||
{
|
||||
let pt = option.position.clone().setZ(0).add(Offset);
|
||||
if (holeOptions.find((op) => equalv3(op.endPt.clone().setZ(0), pt)))
|
||||
{
|
||||
options.push(option);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (options.length)
|
||||
OnSideEndPtOptions.set(line, options);
|
||||
}
|
||||
}
|
||||
|
||||
const NeedDrawCrossLineOptionMap: Map<Line, IDrillingOption[]> = new Map();
|
||||
|
||||
//优先分析长的直线`
|
||||
contouLines.sort((l1, l2) => l2.Length - l1.Length);
|
||||
|
||||
const FrontBackHolePts: Map<Line, Vector3[]> = new Map();
|
||||
|
||||
for (let line of contouLines)
|
||||
{
|
||||
if (SideHoleLineMap.get(line)) continue;
|
||||
|
||||
let pts: Vector3[] = [];
|
||||
let offsetLine = line.Clone().ApplyMatrix(new Matrix4().setPosition(Offset.clone().negate()));
|
||||
|
||||
let { closestPt, param } = line.GetClosestAtPoint(PlCenter, true);
|
||||
let dir = PlCenter.clone().sub(closestPt).normalize();
|
||||
|
||||
let noHasRelevanceLineOption: IDrillingOption[] = [];
|
||||
|
||||
arrayRemoveIf(FrontBackHoleOptions, (opt) =>
|
||||
{
|
||||
let pt = opt.position.clone().setZ(0);
|
||||
let { closestPt, param } = offsetLine.GetClosestAtPoint(pt, true);
|
||||
|
||||
if (pt.distanceTo(closestPt) < 25)
|
||||
{
|
||||
if (!pts.find(pt => equalv3(pt, closestPt)))
|
||||
pts.push(closestPt);
|
||||
noHasRelevanceLineOption.push(opt);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (noHasRelevanceLineOption.length)
|
||||
NeedDrawCrossLineOptionMap.set(line, noHasRelevanceLineOption);
|
||||
|
||||
if (!pts.length) continue;
|
||||
|
||||
pts.push(offsetLine.StartPoint);
|
||||
pts.push(offsetLine.EndPoint);
|
||||
|
||||
if (isParallelTo(dir, new Vector3(0, 1)))
|
||||
pts.sort((pt1, pt2) => pt1.x - pt2.x);
|
||||
else
|
||||
pts.sort((pt1, pt2) => pt1.y - pt2.y);
|
||||
|
||||
//先缓存 不绘制
|
||||
FrontBackHolePts.set(line, pts);
|
||||
|
||||
let dims: AlignedDimension[] = [];
|
||||
let an = angle(dir);
|
||||
|
||||
for (let i = 0; i < pts.length - 1; i++)
|
||||
{
|
||||
let pt1 = pts[i];
|
||||
let pt2 = pts[i + 1];
|
||||
if (equalv3(pt1, pt2)) continue;
|
||||
|
||||
let dim = CreatAlignedDim(pt1, pt2, dir, dimStyle, tMtx);
|
||||
if (an < Math.PI / 2) dim.LeadInLeft = true;
|
||||
await Sleep(0);
|
||||
for (let d of dims) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.Text.BoundingBox))
|
||||
dim.LeadY += AddLeadYNum;
|
||||
}
|
||||
box.union(dim.BoundingBox);
|
||||
dims.push(dim);
|
||||
}
|
||||
}
|
||||
|
||||
//过滤出不同X
|
||||
let onlyXHolesMap: Map<number, IDrillingOption[]> = FrontBackHoleOptions.reduce((someXMap, current) =>
|
||||
{
|
||||
let someX: IDrillingOption[] = someXMap.get(current.position.x) ?? [];
|
||||
if (!someX.find(opt => equalv3(opt.position.clone().setZ(0), current.position.clone().setZ(0))))
|
||||
{
|
||||
someX.push(current);
|
||||
someXMap.set(current.position.x, someX);
|
||||
}
|
||||
|
||||
return someXMap;
|
||||
}, new Map());
|
||||
|
||||
// 按照 key 从小到大排序
|
||||
const SortXHolesMap = Array.from(onlyXHolesMap.entries()).sort((a, b) => a[0] - b[0]);
|
||||
// 创建一个新的 Map 来存储排序后的键值对
|
||||
onlyXHolesMap = new Map(SortXHolesMap);
|
||||
|
||||
|
||||
//过滤出不同Y
|
||||
let onlyYHolesMap: Map<number, IDrillingOption[]> = FrontBackHoleOptions.reduce((someYMap, current) =>
|
||||
{
|
||||
let someY: IDrillingOption[] = someYMap.get(current.position.y) ?? [];
|
||||
if (!someY.find(opt => equalv3(opt.position.clone().setZ(0), current.position.clone().setZ(0))))
|
||||
{
|
||||
someY.push(current);
|
||||
someYMap.set(current.position.y, someY);
|
||||
}
|
||||
|
||||
return someYMap;
|
||||
}, new Map());
|
||||
|
||||
// 按照 key 从小到大排序
|
||||
const SortYHolesMap = Array.from(onlyYHolesMap.entries()).sort((a, b) => a[0] - b[0]);
|
||||
// 创建一个新的 Map 来存储排序后的键值对
|
||||
onlyYHolesMap = new Map(SortYHolesMap);
|
||||
|
||||
//线周围没有孔
|
||||
const NoDimLine = contouLines.filter((line) => !NeedDrawCrossLineOptionMap.get(line) && !SideHoleLineMap.get(line));
|
||||
|
||||
//内部正反面孔编组标注
|
||||
if (onlyYHolesMap.size < onlyXHolesMap.size || PlBoxSize.x <= PlBoxSize.y)
|
||||
{
|
||||
//用于判断避让
|
||||
let parallelToXLineDims: AlignedDimension[] = [];
|
||||
|
||||
for (let [n, opts] of onlyYHolesMap)
|
||||
{
|
||||
let isParallelToXLine: Line;
|
||||
let distToXLine: number = Infinity;
|
||||
let intersectYLinesMap: Map<Line, Vector3> = new Map();
|
||||
|
||||
opts.sort((opt1, opt2) => opt1.position.x - opt2.position.x);
|
||||
|
||||
let centerPt = opts[0].position.clone().setZ(0);
|
||||
let yLine = new Line(new Vector3(0, n), opts[0].position.clone().setZ(0));
|
||||
|
||||
|
||||
for (let cLine of contouLines)
|
||||
{
|
||||
let offsetLine = cLine.Clone().ApplyMatrix(new Matrix4().setPosition(Offset.clone().negate()));
|
||||
let pts = yLine.IntersectWith(offsetLine, IntersectOption.ExtendThis);
|
||||
if (pts.length)
|
||||
intersectYLinesMap.set(cLine, pts[0]);
|
||||
|
||||
if (isParallelTo(offsetLine.GetFirstDeriv(0), new Vector3(1)))
|
||||
{
|
||||
let { closestPt } = offsetLine.GetClosestAtPoint(centerPt, true);
|
||||
let dist = closestPt.distanceTo(centerPt);
|
||||
if (distToXLine > dist)
|
||||
{
|
||||
isParallelToXLine = offsetLine;
|
||||
distToXLine = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dirY: Vector3 = new Vector3(0, -1);
|
||||
|
||||
if (isParallelToXLine)
|
||||
{
|
||||
let { closestPt } = isParallelToXLine.GetClosestAtPoint(centerPt, true);
|
||||
if (isParallelToXLine.PtOnCurve(closestPt))
|
||||
{
|
||||
if (closestPt.y > centerPt.y)
|
||||
dirY = new Vector3(0, 1);
|
||||
|
||||
let fastPt = opts[0].position;
|
||||
let dirX = new Vector3(fastPt.x - PlCenter.x).normalize().multiplyScalar(3);
|
||||
|
||||
let dim = CreatAlignedDim(centerPt, closestPt, dirX, dimStyle, tMtx);
|
||||
await Sleep(0);
|
||||
|
||||
for (let d of parallelToXLineDims) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.BoundingBox))
|
||||
{
|
||||
dim.ArmP1 = dim.ArmP1.sub(dirX.clone().normalize().multiplyScalar(40));
|
||||
dim.ArmP2 = dim.ArmP2.sub(dirX.clone().normalize().multiplyScalar(40));
|
||||
}
|
||||
}
|
||||
parallelToXLineDims.push(dim);
|
||||
box.union(dim.BoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
//正常情况下有两条相交线
|
||||
if (intersectYLinesMap.size === 2)
|
||||
{
|
||||
let pts = Array.from(intersectYLinesMap.values());
|
||||
|
||||
if (opts.length === 1)
|
||||
{
|
||||
let pt1 = pts[0];
|
||||
let pt2 = pts[1];
|
||||
|
||||
let pt = opts[0].position.clone().setZ(0);
|
||||
if (pt1.distanceTo(pt) > pt2.distanceTo(pt))
|
||||
pts[0] = pts[1];
|
||||
pts.length = 1;
|
||||
}
|
||||
|
||||
for (let op of opts)
|
||||
pts.push(op.position.clone().setZ(0));
|
||||
|
||||
pts.sort((pt1, pt2) => pt1.x - pt2.x);
|
||||
|
||||
//用于判断避让
|
||||
let dims: AlignedDimension[] = [];
|
||||
let an = angle(dirY);
|
||||
|
||||
for (let i = 0; i < pts.length - 1; i++)
|
||||
{
|
||||
let pt1 = pts[i];
|
||||
let pt2 = pts[i + 1];
|
||||
let dim = CreatAlignedDim(pt1, pt2, dirY, dimStyle, tMtx);
|
||||
|
||||
if (dim.LeadVisible && an < Math.PI) dim.LeadInLeft = true;
|
||||
for (let d of dims) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.Text.BoundingBox))
|
||||
dim.LeadY += AddLeadYNum;
|
||||
}
|
||||
|
||||
dims.push(dim);
|
||||
box.union(dim.BoundingBox);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//todo
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PlBoxSize.y <= PlBoxSize.x)
|
||||
{
|
||||
//用于判断避让
|
||||
let parallelToYLine: AlignedDimension[] = [];
|
||||
for (let [n, opts] of onlyXHolesMap)
|
||||
{
|
||||
let isParallelToYLine: Line;
|
||||
let distToYLine: number = Infinity;
|
||||
let intersectXLinesMap: Map<Line, Vector3> = new Map();
|
||||
|
||||
opts.sort((opt1, opt2) => opt1.position.y - opt2.position.y);
|
||||
|
||||
let centerPtIndex = Math.max(Math.floor(opts.length / 2) - 1, 0);
|
||||
let centerPt = opts[centerPtIndex].position.clone().setZ(0);
|
||||
let xLine = new Line(new Vector3(n, 0), opts[0].position.clone().setZ(0));
|
||||
|
||||
for (let cLine of contouLines)
|
||||
{
|
||||
let offsetLine = cLine.Clone().ApplyMatrix(new Matrix4().setPosition(Offset.clone().negate()));
|
||||
let pts = xLine.IntersectWith(offsetLine, IntersectOption.ExtendThis);
|
||||
if (pts.length)
|
||||
intersectXLinesMap.set(cLine, pts[0]);
|
||||
|
||||
if (isParallelTo(offsetLine.GetFirstDeriv(0), new Vector3(0, 1)))
|
||||
{
|
||||
let { closestPt } = offsetLine.GetClosestAtPoint(centerPt, true);
|
||||
let dist = closestPt.distanceTo(centerPt);
|
||||
if (distToYLine > dist)
|
||||
{
|
||||
isParallelToYLine = offsetLine;
|
||||
distToYLine = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dirX: Vector3 = new Vector3(-1);
|
||||
|
||||
if (isParallelToYLine)
|
||||
{
|
||||
let { closestPt } = isParallelToYLine.GetClosestAtPoint(centerPt, true);
|
||||
if (isParallelToYLine.PtOnCurve(closestPt))
|
||||
{
|
||||
if (closestPt.x > centerPt.x)
|
||||
dirX = new Vector3(1);
|
||||
|
||||
let firstPt = opts[0].position;
|
||||
let dirY = new Vector3(0, 1);
|
||||
if (firstPt.y - centerPt.y > 35)
|
||||
dirY = new Vector3(0, -1);
|
||||
|
||||
let dim = CreatAlignedDim(centerPt, closestPt, dirY, dimStyle, tMtx);
|
||||
|
||||
await Sleep(0);
|
||||
for (let d of parallelToYLine) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.BoundingBox))
|
||||
{
|
||||
dim.ArmP1 = dim.ArmP1.sub(dirY.clone().multiplyScalar(40));
|
||||
dim.ArmP2 = dim.ArmP2.sub(dirY.clone().multiplyScalar(40));
|
||||
}
|
||||
}
|
||||
parallelToYLine.push(dim);
|
||||
box.union(dim.BoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
//正常情况下有两条相交线
|
||||
if (intersectXLinesMap.size === 2)
|
||||
{
|
||||
let an = angle(dirX);
|
||||
let pts = Array.from(intersectXLinesMap.values());
|
||||
|
||||
for (let op of opts)
|
||||
pts.push(op.position.clone().setZ(0));
|
||||
|
||||
pts.sort((pt1, pt2) => pt1.y - pt2.y);
|
||||
|
||||
//用于判断避让
|
||||
let dims: AlignedDimension[] = [];
|
||||
|
||||
for (let i = 0; i < pts.length - 1; i++)
|
||||
{
|
||||
let pt1 = pts[i];
|
||||
let pt2 = pts[i + 1];
|
||||
let dim = CreatAlignedDim(pt1, pt2, dirX, dimStyle, tMtx);
|
||||
await Sleep(0);
|
||||
|
||||
if (dim.LeadVisible && an < Math.PI) dim.LeadInLeft = true;
|
||||
for (let d of dims) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.Text.BoundingBox))
|
||||
dim.LeadY += AddLeadYNum;
|
||||
}
|
||||
|
||||
dims.push(dim);
|
||||
box.union(dim.BoundingBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//正反面的边孔宽度标注
|
||||
for (let [line, options] of NeedDrawCrossLineOptionMap)
|
||||
{
|
||||
let { closestPt, param } = line.GetClosestAtPoint(PlCenter, true);
|
||||
let dir = PlCenter.clone().sub(closestPt).normalize();
|
||||
//将线段和点转化为X轴方向
|
||||
let an = angle(dir);
|
||||
let ocs = new Matrix4().makeRotationZ(Math.PI / 2 - an);
|
||||
let parallelToXLine = line.Clone().ApplyMatrix(new Matrix4().setPosition(Offset.clone().negate())).ApplyMatrix(ocs);
|
||||
let mat = new Matrix4().setPosition(parallelToXLine.BoundingBox.min.negate());
|
||||
parallelToXLine.ApplyMatrix(mat);
|
||||
ocs = mat.multiply(ocs);
|
||||
const OCSInv = new Matrix4().getInverse(ocs);
|
||||
|
||||
options.sort((opt1, opt2) => opt1.position.clone().applyMatrix4(ocs).x - opt2.position.clone().applyMatrix4(ocs).x);
|
||||
|
||||
let distSet: Set<string> = new Set();
|
||||
for (let opt of options)
|
||||
{
|
||||
let pt = opt.position.clone().applyMatrix4(ocs).setZ(0);
|
||||
let { closestPt, param } = parallelToXLine.GetClosestAtPoint(opt.position.clone().applyMatrix4(ocs).setZ(0), true);
|
||||
|
||||
if (closestPt)
|
||||
{
|
||||
let dist = FixedNotZero(closestPt.distanceTo(pt), 2);
|
||||
if (!distSet.has(dist))
|
||||
{
|
||||
let dir = line.GetFirstDeriv(0).normalize().multiplyScalar(param < 0.5 ? - 40 : 40);
|
||||
let pt1 = pt.applyMatrix4(OCSInv);
|
||||
let pt2 = closestPt.applyMatrix4(OCSInv);
|
||||
if (equalv3(pt1, pt2)) continue;
|
||||
|
||||
let dim = new AlignedDimension(
|
||||
pt1, pt2,
|
||||
pt1.clone().sub(dir),
|
||||
pt2.clone().sub(dir),
|
||||
);
|
||||
|
||||
dim.LeadY = 25;
|
||||
dim.SetDimStyleOverrideValues(dimStyle);
|
||||
if (param < 0.5) dim.LeadInLeft = true;
|
||||
dim.ApplyMatrix(tMtx);
|
||||
app.Database.ModelSpace.Append(dim);
|
||||
box.union(dim.BoundingBox);
|
||||
distSet.add(dist);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//侧孔标注
|
||||
for (let [line, options] of SideHoleLineMap)
|
||||
{
|
||||
let pts: Vector3[] = [line.StartPoint.clone().sub(Offset), line.EndPoint.clone().sub(Offset)];
|
||||
|
||||
for (let op of options)
|
||||
pts.push(op.position.clone().sub(Offset).setZ(0));
|
||||
|
||||
let dir = options[0].endPt.clone().sub(options[0].position).normalize();
|
||||
let an = angle(dir);
|
||||
if (isParallelTo(dir, new Vector3(1)))
|
||||
pts.sort((pt1, pt2) => pt1.y - pt2.y);
|
||||
else
|
||||
pts.sort((pt1, pt2) => pt1.x - pt2.x);
|
||||
|
||||
let dims: AlignedDimension[] = [];
|
||||
|
||||
for (let i = 0; i < pts.length - 1; i++)
|
||||
{
|
||||
let pt1 = pts[i];
|
||||
let pt2 = pts[i + 1];
|
||||
let dim = CreatAlignedDim(pt1, pt2, dir, dimStyle, tMtx);
|
||||
|
||||
if (dim.LeadVisible && an < Math.PI) dim.LeadInLeft = true;
|
||||
await Sleep(0);
|
||||
|
||||
for (let d of dims) //判断身位重叠
|
||||
{
|
||||
if (d.BoundingBox.intersectsBox(dim.Text.BoundingBox))
|
||||
{
|
||||
dim.LeadY += AddLeadYNum;
|
||||
}
|
||||
}
|
||||
box.union(dim.BoundingBox);
|
||||
dims.push(dim);
|
||||
}
|
||||
}
|
||||
|
||||
for (let [line, options] of OnSideEndPtOptions)
|
||||
{
|
||||
let centerPt = options[0].position.clone().setZ(0);
|
||||
let offsetLine = line.Clone().ApplyMatrix(new Matrix4().setPosition(Offset.clone().negate()));
|
||||
|
||||
let { closestPt, param } = offsetLine.GetClosestAtPoint(centerPt, true);
|
||||
let dir = line.GetFirstDeriv(0).normalize().multiplyScalar(param < 0.5 ? - 2 : 2);
|
||||
CreatAlignedDim(centerPt, closestPt, dir, dimStyle, tMtx);
|
||||
}
|
||||
|
||||
//总轮廓标注
|
||||
{
|
||||
let contourBoxMin = box.clone().applyMatrix4(new Matrix4().getInverse(tMtx)).union(originContourBox).min;
|
||||
let dirX = new Vector3(0, contourBoxMin.y / -30 + 1);
|
||||
let dirY = new Vector3(contourBoxMin.x / -30 + 1);
|
||||
|
||||
const dimX = CreatAlignedDim(new Vector3().sub(info.offsetTanslation), new Vector3(originContourBox.max.x).sub(info.offsetTanslation), dirX, dimStyle, tMtx);
|
||||
const dimY = CreatAlignedDim(new Vector3().sub(info.offsetTanslation), new Vector3(0, originContourBox.max.y).sub(info.offsetTanslation), dirY, dimStyle, tMtx);
|
||||
|
||||
|
||||
box.union(dimY.BoundingBox);
|
||||
box.union(dimX.BoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
function CreatAlignedDim(footP1: Vector3, footP2: Vector3, dir: Vector3, dimStyle: Map<DimStyleKeyCode, any>, tMtx: Matrix4)
|
||||
{
|
||||
let dim = new AlignedDimension(
|
||||
footP1, footP2,
|
||||
footP1.clone().sub(dir.clone().multiplyScalar(30)),
|
||||
footP2.clone().sub(dir.clone().multiplyScalar(30))
|
||||
);
|
||||
|
||||
dim.LeadY = 25;
|
||||
dim.SetDimStyleOverrideValues(dimStyle);
|
||||
dim.ApplyMatrix(tMtx);
|
||||
app.Database.ModelSpace.Append(dim);
|
||||
return dim;
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
import { BufferGeometry, Line, Object3D, Vector3 } from "three";
|
||||
import { HostApplicationServices } from "../../ApplicationServices/HostApplicationServices";
|
||||
import { AddEntityDrawObject } from "../../Common/AddEntityDrawObject";
|
||||
import { BufferGeometryUtils } from "../../Geometry/BufferGeometryUtils";
|
||||
import { MoveMatrix } from "../../Geometry/GeUtils";
|
||||
import { RenderType } from "../../GraphicsSystem/RenderType";
|
||||
import { Factory } from "../CADFactory";
|
||||
import { CADFiler } from "../CADFiler";
|
||||
import { Text, TextAligen } from "../Text/Text";
|
||||
import { Dimension } from "./Dimension";
|
||||
import { GetDimLineMaterial } from "./GetDimLineMaterial";
|
||||
|
||||
//箭头引线标签标注 (箭头暂未实现)
|
||||
@Factory
|
||||
export class MLeaderDimension extends Dimension
|
||||
{
|
||||
protected _Text = new Text();
|
||||
|
||||
constructor(
|
||||
protected _TextString: string = "", // 文本
|
||||
protected _StartPoint: Vector3 = new Vector3(), // 引线起点
|
||||
protected _EndPoint: Vector3 = new Vector3(100), // 引线终点
|
||||
)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
get Text()
|
||||
{
|
||||
if (!this._Text.TextString)
|
||||
this.ParseText();
|
||||
|
||||
return this._Text;
|
||||
}
|
||||
|
||||
set StartPoint(p: Vector3)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this._StartPoint.copy(p).applyMatrix4(this.OCSInv);
|
||||
this.Update();
|
||||
}
|
||||
get StartPoint(): Vector3
|
||||
{
|
||||
return this._StartPoint.clone().applyMatrix4(this.OCSNoClone);
|
||||
}
|
||||
|
||||
get EndPoint(): Vector3
|
||||
{
|
||||
return this._EndPoint.clone().applyMatrix4(this.OCSNoClone);
|
||||
}
|
||||
set EndPoint(p: Vector3)
|
||||
{
|
||||
this.WriteAllObjectRecord();
|
||||
this._EndPoint.copy(p).applyMatrix4(this.OCSInv);
|
||||
this.Update();
|
||||
}
|
||||
|
||||
protected GetPrimitiveString(): string
|
||||
{
|
||||
return this._TextString;
|
||||
}
|
||||
|
||||
//#region 拉伸相关
|
||||
GetGripPoints(): Vector3[]
|
||||
{
|
||||
return [this.StartPoint, new Vector3().addVectors(this.EndPoint, this.StartPoint).multiplyScalar(0.5), this.EndPoint];
|
||||
}
|
||||
|
||||
MoveGripPoints(indexList: number[], vec: Vector3)
|
||||
{
|
||||
for (let index of indexList)
|
||||
{
|
||||
if (index === 0)
|
||||
this.StartPoint = this.StartPoint.add(vec);
|
||||
else if (index === 2)
|
||||
this.EndPoint = this.EndPoint.add(vec);
|
||||
else
|
||||
{
|
||||
let m = MoveMatrix(vec);
|
||||
this.ApplyMatrix(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Draw
|
||||
InitDrawObject(renderType: RenderType = RenderType.Wireframe)
|
||||
{
|
||||
let colorMaterial = GetDimLineMaterial(this, renderType);
|
||||
|
||||
let obj = new Object3D();
|
||||
let line = new Line(new BufferGeometry, colorMaterial);
|
||||
obj.add(line);
|
||||
|
||||
this.UpdateDrawObject(renderType, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
UpdateDrawObject(renderType: RenderType, obj: Object3D)
|
||||
{
|
||||
obj.remove(...obj.children.slice(1));
|
||||
|
||||
let line = obj.children[0] as Line;
|
||||
let colorMaterial = GetDimLineMaterial(this, renderType);
|
||||
line.material = colorMaterial;
|
||||
|
||||
this.ParseText();
|
||||
this._Text.DeferUpdate();
|
||||
|
||||
let geo = line.geometry as BufferGeometry;
|
||||
if (!BufferGeometryUtils.UpdatePts(geo, [this._StartPoint, this._EndPoint]))
|
||||
{
|
||||
line.geometry.dispose();
|
||||
line.geometry = BufferGeometryUtils.CreateFromPts([this._StartPoint, this._EndPoint]);
|
||||
}
|
||||
AddEntityDrawObject(obj, this._Text, renderType);
|
||||
}
|
||||
|
||||
ParseText()
|
||||
{
|
||||
this._Text.AutoUpdate = false;
|
||||
this._Text.ColorIndex = this.ColorIndex;
|
||||
this._Text.TextString = this.TextString;
|
||||
this._Text.Height = this.TextSize;
|
||||
this._Text.TextAligen = TextAligen.LeftMid;
|
||||
this._Text.OCS = this.OCS.setPosition(this._EndPoint);
|
||||
this._Text.AutoUpdate = true;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region -------------------------File-------------------------
|
||||
//对象从文件中读取数据,初始化自身
|
||||
protected _ReadFile(file: CADFiler)
|
||||
{
|
||||
let ver = file.Read();
|
||||
super._ReadFile(file);
|
||||
this._TextString = file.Read();
|
||||
this._StartPoint = new Vector3(file.Read(), file.Read(), file.Read());
|
||||
this._EndPoint = new Vector3(file.Read(), file.Read(), file.Read());
|
||||
|
||||
this.ReadDimStyle(file);
|
||||
this._DimStyle = file.ReadHardObjectId() ?? HostApplicationServices.CurrentDimStyle;
|
||||
}
|
||||
//对象将自身数据写入到文件.
|
||||
WriteFile(file: CADFiler)
|
||||
{
|
||||
file.Write(1);
|
||||
super.WriteFile(file);
|
||||
file.Write(this._TextString);
|
||||
file.WriteVec3(this._StartPoint);
|
||||
file.WriteVec3(this._EndPoint);
|
||||
|
||||
this.WriteDimStyle(file);
|
||||
file.WriteHardObjectId(this._DimStyle);
|
||||
}
|
||||
//#endregion
|
||||
}
|
Loading…
Reference in new issue