mirror of https://gitee.com/cf-fz/WebCAD.git
parent
e342a4058f
commit
b111b71cac
@ -0,0 +1,277 @@
|
||||
import { Vector3 } from "three";
|
||||
import { EBoardKeyList } from "../Common/BoardKeyList";
|
||||
import { CylinderHole, GangDrillType } from "../DatabaseServices/3DSolid/CylinderHole";
|
||||
import { ExtrudeHole } from "../DatabaseServices/3DSolid/ExtrudeHole";
|
||||
import { Board } from "../DatabaseServices/Entity/Board";
|
||||
import { Circle } from "../DatabaseServices/Entity/Circle";
|
||||
import { ExtureContourCurve } from "../DatabaseServices/Entity/Extrude";
|
||||
import { Line } from "../DatabaseServices/Entity/Line";
|
||||
import { angleTo, equaln, equalv3, isParallelTo, XAxis } from "../Geometry/GeUtils";
|
||||
import { FaceDirection } from "../UI/Store/BoardInterface";
|
||||
import { DrillingFace, IBoardHoleInfo, IDrillingOption } from "./Product";
|
||||
|
||||
/**
|
||||
* 解析排钻数据的性能优化类,这个类并没有启用
|
||||
*/
|
||||
export class ParseBoardHoleData
|
||||
{
|
||||
frontBackHoles: IDrillingOption[] = [];
|
||||
sideHoles: IDrillingOption[] = [];
|
||||
|
||||
constructor(
|
||||
private _Board: Board,
|
||||
private _offsetTanslation: Vector3,
|
||||
private _SealedContour: ExtureContourCurve,//已经计算封边的轮廓
|
||||
private _Normal = _Board.Normal,
|
||||
private _OCSInv = _Board.OCSInv,
|
||||
private _OCSInvRo = _OCSInv.clone().setPosition(0, 0, 0),
|
||||
private _ContourBox = _SealedContour.BoundingBox,
|
||||
)
|
||||
{
|
||||
for (let [, driss] of _Board.DrillList)
|
||||
{
|
||||
for (let dris of driss)
|
||||
{
|
||||
for (let dId of dris)
|
||||
{
|
||||
if (!dId || dId.IsErase)
|
||||
continue;
|
||||
let d = dId.Object as CylinderHole;
|
||||
if (d instanceof ExtrudeHole)
|
||||
this.ParseExtrudeHoles(d, _offsetTanslation);
|
||||
else
|
||||
this.ParseCylHoles(d, _offsetTanslation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetData(): IBoardHoleInfo
|
||||
{
|
||||
return { frontBackHoles: this.frontBackHoles, sideHoles: this.sideHoles };
|
||||
}
|
||||
|
||||
/**分析常规排钻 */
|
||||
ParseCylHoles(d: CylinderHole, offsetTanslation: Vector3): void
|
||||
{
|
||||
let processData = this._Board.BoardProcessOption;
|
||||
let brNormal = this._Normal;
|
||||
let roMat = this._OCSInvRo;
|
||||
let position = d.Position.applyMatrix4(this._OCSInv);
|
||||
let holes = this.frontBackHoles;
|
||||
let face: number;
|
||||
let isPush = false;
|
||||
let endPt: Vector3;
|
||||
let depth = d.Height;
|
||||
let diffMat = d.OCS.premultiply(this._OCSInv);
|
||||
let x = new Vector3().setFromMatrixColumn(diffMat, 0);
|
||||
let angle = angleTo(XAxis, x);
|
||||
if (d.Type === GangDrillType.Pxl || d.Type === GangDrillType.WoodPXL)
|
||||
{
|
||||
if (isParallelTo(d.Normal, brNormal))
|
||||
{
|
||||
if (position.x <= 0 || position.x >= this._Board.Width || position.y <= 0 || position.y >= this._Board.Height || !this.PointInBoard(position.clone().setZ(0))) return;
|
||||
|
||||
position.sub(offsetTanslation);
|
||||
face = processData[EBoardKeyList.BigHole];
|
||||
isPush = true;
|
||||
}
|
||||
}
|
||||
else if (d.Type === GangDrillType.Ljg || d.Type === GangDrillType.Wood)
|
||||
{
|
||||
if (!isParallelTo(d.Normal, brNormal))
|
||||
{
|
||||
let z = position.z;
|
||||
let line = new Line(position.clone().setZ(0), position.clone().setZ(0).add(d.Normal.multiplyScalar(d.Height).applyMatrix4(roMat)));
|
||||
let pt = this._SealedContour.IntersectWith(line, 0)[0];
|
||||
if (!pt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
position = pt.clone().setZ(z);
|
||||
for (let p of [line.StartPoint, line.EndPoint])
|
||||
{
|
||||
if (this._SealedContour.PtInCurve(p))
|
||||
{
|
||||
endPt = p.setZ(z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!endPt)
|
||||
{
|
||||
console.warn("排钻位置有问题");
|
||||
return;
|
||||
}
|
||||
holes = this.sideHoles;
|
||||
face = Math.floor(this._SealedContour.GetParamAtPoint(pt));
|
||||
isPush = true;
|
||||
depth = position.distanceTo(endPt);
|
||||
angle = undefined;
|
||||
|
||||
this.InvertPosition(position, this._Board.Thickness);
|
||||
this.InvertPosition(endPt, this._Board.Thickness);
|
||||
}
|
||||
else if (d.Type === GangDrillType.Wood)
|
||||
{
|
||||
if (!this._SealedContour.PtInCurve(position.clone().setZ(0))) return;
|
||||
face = position.z > 0 ? FaceDirection.Front : FaceDirection.Back;
|
||||
holes = this.frontBackHoles;
|
||||
if (position.z > 0)
|
||||
{
|
||||
let z1 = position.z - d.Height;
|
||||
if (z1 > 0 && z1 < this._Board.Thickness)
|
||||
{
|
||||
depth = this._Board.Thickness - z1;
|
||||
isPush = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let z1 = position.z + d.Height;
|
||||
if (z1 > 0 && z1 < this._Board.Thickness)
|
||||
{
|
||||
depth = z1;
|
||||
isPush = true;
|
||||
}
|
||||
}
|
||||
position.sub(offsetTanslation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isParallelTo(d.Normal, this._Normal))
|
||||
{
|
||||
if (position.x <= 0 || position.x >= this._Board.Width || position.y <= 0 || position.y >= this._Board.Height) return;
|
||||
position.sub(offsetTanslation);
|
||||
holes = this.frontBackHoles;
|
||||
face = !equalv3(d.Normal, brNormal, 1e-3) ? 0 : 1;
|
||||
isPush = true;
|
||||
}
|
||||
}
|
||||
isPush && holes.push({
|
||||
type: d.Type,
|
||||
position,
|
||||
radius: d.Radius,
|
||||
depth,
|
||||
face,
|
||||
endPt,
|
||||
angle
|
||||
});
|
||||
}
|
||||
|
||||
/**分析自定义圆柱排钻 */
|
||||
ParseExtrudeHoles(d: ExtrudeHole, offsetTanslation: Vector3): void
|
||||
{
|
||||
if (!d.isHole)
|
||||
return;
|
||||
|
||||
let outline = this._SealedContour;
|
||||
|
||||
let brNormal = this._Normal;
|
||||
let cir = d.ContourCurve;
|
||||
if (cir instanceof Circle)
|
||||
{
|
||||
let diffMtx = d.OCS.premultiply(this._OCSInv);
|
||||
let nor = d.Normal;
|
||||
let sp = cir.Center.applyMatrix4(diffMtx);
|
||||
let ep = cir.Center.add(new Vector3(0, 0, d.Height)).applyMatrix4(diffMtx);
|
||||
let x = new Vector3().setFromMatrixColumn(diffMtx, 0);
|
||||
if (isParallelTo(nor, brNormal))
|
||||
{
|
||||
let z0 = Math.min(sp.z, ep.z);
|
||||
let z1 = Math.max(sp.z, ep.z);
|
||||
let p = sp.clone().setZ(0).sub(offsetTanslation);
|
||||
|
||||
if (Math.max(z0, 0) < Math.min(z1, this._Board.Thickness) - 1e-6 && outline.PtInCurve(p))
|
||||
{
|
||||
this.frontBackHoles.push({
|
||||
type: GangDrillType.Pxl,
|
||||
position: z0 < 1e-6 ? p : p.setZ(this._Board.Thickness),
|
||||
radius: cir.Radius,
|
||||
depth: z0 < 1e-6 ? z1 : this._Board.Thickness - z0,
|
||||
face: z0 < 1e-6 ? DrillingFace.Back : DrillingFace.Front,
|
||||
angle: angleTo(XAxis, x),
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let oldZ = sp.z;
|
||||
let [minX, maxX] = sp.x < ep.x ? [sp.x, ep.x] : [ep.x, sp.x];
|
||||
let [minY, maxY] = sp.y < ep.y ? [sp.y, ep.y] : [ep.y, sp.y];
|
||||
|
||||
|
||||
if (sp.z > cir.Radius
|
||||
&& sp.z < this._Board.Thickness - cir.Radius
|
||||
&& Math.max(minX, 0) < Math.min(this._Board.Width, maxX) + 1e-6
|
||||
&& Math.max(minY, 0) < Math.min(this._Board.Height, maxY) + 1e-6
|
||||
)
|
||||
{
|
||||
sp.setZ(0);
|
||||
ep.setZ(0);
|
||||
let line = new Line(sp, ep);
|
||||
let pt = outline.IntersectWith(line, 0)[0];
|
||||
if (!pt)
|
||||
{
|
||||
console.error("排钻嵌在板件内部");
|
||||
return;
|
||||
}
|
||||
let position = pt.clone().setZ(oldZ);
|
||||
let endPt: Vector3;
|
||||
let face = Math.floor(outline.GetParamAtPoint(pt));
|
||||
for (let p of [line.StartPoint, line.EndPoint])
|
||||
{
|
||||
if (outline.PtInCurve(p))
|
||||
{
|
||||
endPt = p.setZ(oldZ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!endPt)
|
||||
return;
|
||||
let depth = position.distanceTo(endPt);
|
||||
|
||||
if (equaln(depth, 0))
|
||||
return;
|
||||
|
||||
this.InvertPosition(position, this._Board.Thickness);
|
||||
this.InvertPosition(endPt, this._Board.Thickness);
|
||||
|
||||
this.sideHoles.push({
|
||||
type: GangDrillType.Ljg,
|
||||
endPt,
|
||||
position,
|
||||
radius: cir.Radius,
|
||||
depth,
|
||||
face,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**拆单那边需要把侧孔 z 坐标转换为从上到下 */
|
||||
private InvertPosition(pos: Vector3, thickness: number)
|
||||
{
|
||||
pos.z = thickness - pos.z;
|
||||
}
|
||||
|
||||
|
||||
//由于我们现在的数据结构有了个多余的圆柱,所以我们为了优化这个的计算性能,进行了缓存
|
||||
PointCheckCache: Map<string, boolean> = new Map();
|
||||
private PointInBoard(p: Vector3): boolean
|
||||
{
|
||||
if (!this._ContourBox.containsPoint(p)) return false;
|
||||
|
||||
let key = `${Math.floor(p.x)},${Math.floor(p.y)}`;
|
||||
|
||||
if (this.PointCheckCache.has(key)) return this.PointCheckCache.get(key);
|
||||
|
||||
let inBr = this._SealedContour.PtInCurve(p);
|
||||
|
||||
this.PointCheckCache.set(key, inBr);
|
||||
|
||||
return inBr;
|
||||
}
|
||||
}
|
Loading…
Reference in new issue