diff --git a/src/Add-on/BoardCutting/LinearCuttingForSweep.ts b/src/Add-on/BoardCutting/LinearCuttingForSweep.ts index 129286d2b..9b36cc8d5 100644 --- a/src/Add-on/BoardCutting/LinearCuttingForSweep.ts +++ b/src/Add-on/BoardCutting/LinearCuttingForSweep.ts @@ -831,7 +831,7 @@ export class LinearCuttingForSweep const [pA, paramA, distA] = FlatToCurved(box.min); const [pB, paramB, distB] = FlatToCurved(LimitMaxInVector3(box.max, { x: sweepPath.Length })); const sweepPathCopy = sweepPath.Clone(); - const partPath = CurveManager.Get_Pl_InParamAtoParamB(sweepPathCopy, pA, pB); + const partPath = CurveManager.Get_Pl_InPtAtoPtB(sweepPathCopy, pA, pB); // 修正轮廓 let baseLen = pA.x - box.min.x - firstPt.x; const biasX = Math.cos(sweepAngle) * baseLen; @@ -918,7 +918,7 @@ export class ViewManager } /** 线段管理器 */ -class CurveManager +export class CurveManager { /** X轴的平行线 */ static CreateXLine = (p: Vector3) => new Line(new Vector3(p.x - 1000, p.y, p.z), new Vector3(p.x + 1000, p.y, p.z)); @@ -998,14 +998,20 @@ class CurveManager return pl; }; /** 获取pA-pB之间的曲线 */ - static Get_Pl_InParamAtoParamB(pl: Polyline, pA: Vector3, pB: Vector3) + static Get_Pl_InPtAtoPtB(pl: Polyline, pA: Vector3, pB: Vector3) { + // 确保pA在pB前面 + if (pl.GetParamAtPoint(pA) > pl.GetParamAtPoint(pB)) + { + const temp = pA; + pA = pB; + pB = temp; + } const paramA = pl.GetParamAtPoint(pA); const pls = pl.GetSplitCurves(paramA); pl = pls[1] || pls[0]; const paramB = pl.GetParamAtPoint(pB); - const pls2 = pl.GetSplitCurves(paramB); - return pls2[0]; + return pl.GetSplitCurves(paramB)[0]; }; } diff --git a/src/DatabaseServices/Entity/Board.ts b/src/DatabaseServices/Entity/Board.ts index 6ad270a54..b22c53b2e 100644 --- a/src/DatabaseServices/Entity/Board.ts +++ b/src/DatabaseServices/Entity/Board.ts @@ -2,6 +2,7 @@ import Geom3 from '@jscad/modeling/src/geometries/geom3/type'; import { BufferAttribute, BufferGeometry, Euler, FrontSide, Frustum, Geometry, LineSegments, Matrix3, Matrix4, Mesh, Object3D, ShapeGeometry, Line as TLine, UVGenerator, Vector3 } from 'three'; import { ArcBoardBuild } from '../../Add-on/ArcBoard/ArcBoardBuild'; import { ArcBoardOptions, ParseBoardArcFeed, defultArcBoardOption } from '../../Add-on/ArcBoard/ArcBoardFeeding'; +import { CurveManager } from '../../Add-on/BoardCutting/LinearCuttingForSweep'; import { SplitBoardSideModelUtil } from '../../Add-on/BoardCutting/SplitBoardSideModel'; import { Board2Regions } from '../../Add-on/BoardEditor/Board2Regions'; import { DeserializationBoard2DModeingData, DeserializationBoard3DModeingData, DeserializationBoardSideModeingData, SerializeBoard2DModeingData, SerializeBoard3DModeingData, SerializeBoardSideModeingData, deserializationBoardData, serializeBoardData } from '../../Add-on/BoardEditor/SerializeBoardData'; @@ -490,6 +491,51 @@ export class Board extends ExtrudeSolid this.Update(); } + override AdjustPath(br: Board, outline: Polyline | Circle) + { + if (this.IsArcBoard) + { + const path = this.GetSweepPath(); + // 1.将放样路径展开 + const pathWCS = this.GetSweepPathInWCS(); + pathWCS.ApplyMatrix(pathWCS.OCSInv); + const expandPath = CurveManager.CreateExpandPl(pathWCS); + // 2.将轮廓进行旋转 + outline.ApplyMatrix(new Matrix4().makeRotationZ(-this.SweepAngle)); + // 3.根据轮廓的左右两侧,截取取对应的放样路径 + const leftParam = expandPath.GetParamAtDist(outline.BoundingBox.min.x); + const rightParam = expandPath.GetParamAtDist(outline.BoundingBox.max.x); + const leftPt = path.GetPointAtParam(leftParam); + const rightPt = path.GetPointAtParam(rightParam); + const newPath = CurveManager.Get_Pl_InPtAtoPtB(path, leftPt, rightPt); + // 4.路径起点为原点 + newPath.Move(newPath.StartPoint.negate()); + br.SetSweepPath(newPath, this.SweepAngle); + } + } + + override AdjustPosition(br: Board, basePoint: Vector3) + { + if (this.IsArcBoard) + { + // 映射shape上的基点 + basePoint.applyMatrix4(this.ArcBuild.OCS2RotateMtx); + this.ArcBuild.ParseAllX_Map([basePoint.x]); + this.ArcBuild.PosMap2ArcPos(basePoint); + basePoint.applyMatrix4(this.ArcBuild.Rotate2OCSMtx); + basePoint.applyMatrix4(this.OCSNoClone); + // 映射board上的基点 + const basePointInBoard = br.ContourCurve.StartPoint; + basePointInBoard.applyMatrix4(br.ArcBuild.OCS2RotateMtx); + br.ArcBuild.ParseAllX_Map([basePointInBoard.x]); + br.ArcBuild.PosMap2ArcPos(basePointInBoard); + basePointInBoard.applyMatrix4(br.ArcBuild.Rotate2OCSMtx); + basePointInBoard.applyMatrix4(br.OCSNoClone); + // 移动(boardBasePoint -> basePoint) + br.Move(basePoint.sub(basePointInBoard)); + } + } + /** * 创建一个代理数组,数组改变时被监听 */ diff --git a/src/DatabaseServices/Entity/Extrude.ts b/src/DatabaseServices/Entity/Extrude.ts index bddd1f1ed..20843a9c0 100644 --- a/src/DatabaseServices/Entity/Extrude.ts +++ b/src/DatabaseServices/Entity/Extrude.ts @@ -1603,6 +1603,12 @@ export class ExtrudeSolid extends Entity return grooves; } } + + /** (步骤4.2.1) 针对圆弧板-修正路径 */ + AdjustPath(ext: ExtrudeSolid, outline: Polyline | Circle) { } + /** (步骤4.2.2) 针对圆弧板-修正位置 */ + AdjustPosition(ext: ExtrudeSolid, basePoint: Vector3) { } + /** * (步骤4.2) * 计算本实体被全身的凹槽差集后正确的实体轮廓,和有可能的分裂实体 @@ -1689,8 +1695,14 @@ export class ExtrudeSolid extends Entity ext.grooves.push(groove); } + const shapeOutline = shape.Outline.Curve.Clone(); + // 针对圆弧板-修正路径 + this.AdjustPath(ext, shapeOutline); + const shapeBasePoint = shape.Outline.Curve.StartPoint; ext.ContourCurve = shape.Outline.Curve; ext.GrooveCheckAll(splitEntitys); + // 针对圆弧板-修正位置 + this.AdjustPosition(ext, shapeBasePoint); ext.Update(); splitEntitys.push(ext); } diff --git a/src/DatabaseServices/ShapeManager.ts b/src/DatabaseServices/ShapeManager.ts index d454effe1..1284ef534 100644 --- a/src/DatabaseServices/ShapeManager.ts +++ b/src/DatabaseServices/ShapeManager.ts @@ -12,7 +12,7 @@ export class ShapeManager } - get ShapeList() + get ShapeList(): Shape[] { return this._ShapeList.slice(); }