!2757 feat: 圆弧板夹点和延伸点拖拽

pull/2703/MERGE
zc 3 months ago committed by ChenX
parent de28219fa1
commit cf7dfe3980

@ -1,3 +1,4 @@
import { Vector3 } from "three";
import { LoadBoardsFromFileData } from "../Utils/LoadEntity.util";
// 测试命令(用于复制)npm run test -- ArcBoardBuild.test.ts
@ -30,3 +31,12 @@ test('创建圆弧板4', () =>
let br = LoadBoardsFromFileData(data)[0];
expect(!br.GetSweepPath()).toBe(false);
});
test('创建圆弧板MeshGeometry', () =>
{
const data = { "file": [1, "Board", 10, 2, 112, 0, 1, 2, 71, [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 19904.78327896535, 4187.958560325209, -11618.264484039242, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 16198.407124815723, 17111.522686662538, -11618.264484039242, 1], 0, 0, 1, 3, 28334.00417465891, 29190.267294923055, 18, false, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 12923.564126337336, 3706.376154149625, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 12923.564126337336, 3706.376154149625, 0, 1], 0, 0, 1, 2, 4, [-12923.564126337336, -3706.376154149625], 0, [6386.434340466485, 993.3625201318764], 0, [16266.703168585718, 12209.356716972983], 0, [5532.995149899774, 24627.628020509284], 0, true, 0, 3, 0, 0, 0, 0, 0, 20, 0, "层板", "", "", "", "", "", 0, 0, "三合一", 2, 0, "1", "1", "1", "1", "", "", "", 4, "三合一", "三合一", "三合一", "三合一", true, true, 0, 0, 0, 0, 0, 0, 0, 0, true, 0, 0, null, 0, 0, "", "", "", "", 0, false, 0, "Polyline", 10, 2, 0, 0, 0, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [2.4868995751603507e-14, -1.0658141036401503e-14], 0, [5602.807360060827, 16026.299899791413], 0, [9473.648588094784, 17992.44147593565], 0, [19929.97581119567, 12595.62742530294], 0, false, 0.7853981633974483, 1, true, 1, -1, 0, 6, 6, 2, 0, 0, 0, 3, 0, 0], "basePt": { "x": 867.6016383403512, "y": 4175.9435246959365, "z": -11618.264484039242 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
const br = LoadBoardsFromFileData(data)[0];
br.MoveGripPoints([2], new Vector3(7509.205851318104, -4891.551400246293, 0));
br.MeshGeometry;
});

@ -0,0 +1,13 @@
import { Polyline } from "../../src/DatabaseServices/Entity/Polyline";
import { LoadCurvesFromFileData } from "../Utils/LoadEntity.util";
import "../Utils/jest.util";
test('多段线圆弧前向延伸错误', () =>
{
let d =
{ "file": [1, "Polyline", 10, 2, 103, 0, 1, 7, 71, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 379.4117647058823, 179.41176470588238, 0, 1], 0, 0, 1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], 0, 0, 1, 2, 4, [0, 0], -0.592698851053085, [511.76470588235316, -30.882352941176464], 0, [1054.4117647058824, -45.58823529411765], -0.8681818857079551, [1107.3529411764707, -508.8235294117648], 0, false], "basePt": { "x": 379.4117647058823, "y": -329.41176470588243, "z": 0 }, "ucs": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] };
let pl = LoadCurvesFromFileData(d)[0] as Polyline;
pl.Extend(-0.2);
expect(pl.Length).toMatchNumberSnapshot();
});

@ -413,8 +413,10 @@ export class ArcBoardBuild
leftPolys.push(poly);
else if (res.type === 4)
{
leftPolys.push(res.back);
rightPolys.push(res.front);
if (res.back)
leftPolys.push(res.back);
if (res.front)
rightPolys.push(res.front);
}
}

@ -1,5 +1,5 @@
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, Vector2, Vector3 } from 'three';
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 { SplitBoardSideModelUtil } from '../../Add-on/BoardCutting/SplitBoardSideModel';
@ -9,7 +9,7 @@ import { DrillType, FaceDirection } from "../../Add-on/DrawDrilling/DrillType";
import { CyHoleInBoard, IBoardRectHoleType, ParseBoardRectHoleType, SetBrHighHoleTypeFromRectHoleType } from '../../Add-on/DrawDrilling/HoleUtils';
import { HostApplicationServices } from '../../ApplicationServices/HostApplicationServices';
import { AddEntityDrawObject } from '../../Common/AddEntityDrawObject';
import { arrayClone, arrayPushArray, arrayRemoveDuplicateBySort, arrayRemoveIf, arraySortByNumber, arraySum } from '../../Common/ArrayExt';
import { arrayLast, arrayPushArray, arrayRemoveDuplicateBySort, arrayRemoveIf, arraySortByNumber, arraySum } from '../../Common/ArrayExt';
import { EBoardKeyList } from '../../Common/BoardKeyList';
import { Geom3Res } from '../../Common/CSGIntersect';
import { ColorMaterial } from '../../Common/ColorPalette';
@ -28,7 +28,7 @@ import { Box3Ext } from '../../Geometry/Box';
import { BufferGeometryUtils } from '../../Geometry/BufferGeometryUtils';
import { AddCSGSubtractTask, CSGTask, TerminateCSGTask } from '../../Geometry/CSGSubtract/CSGSubtractTaskManager';
import { EdgesGeometry } from '../../Geometry/EdgeGeometry';
import { AsVector2, AsVector3, IdentityMtx4, XAxis, XAxisN, YAxis, YAxisN, ZAxis, ZeroVec, equaln, equalv3 } from '../../Geometry/GeUtils';
import { AsVector2, AsVector3, IdentityMtx4, XAxis, XAxisN, YAxis, YAxisN, ZAxis, ZeroVec, equaln, equalv2, equalv3 } from '../../Geometry/GeUtils';
import { PointShapeUtils } from '../../Geometry/PointShapeUtils';
import { GetBoardContour, GetBoardHighSeal, GetBoardSealingCurves, GetHighBoardEdgeRemark, SetBoardEdgeRemarkData, SetBoardTopDownLeftRightSealData } from '../../GraphicsSystem/CalcEdgeSealing';
import { RenderType } from '../../GraphicsSystem/RenderType';
@ -161,19 +161,15 @@ export class Board extends ExtrudeSolid
//二维刀路 id -> polyline
private _KnifePolylineMap: Map<string, Polyline> = new Map();
private _jigSweepPath: Polyline; // 拖拽时见光面的SweepPath
private _jigPath2WCSMtx: Matrix4; // 拖拽时路径转世界坐标系矩阵
constructor()
{
super();
this.InitBoardData();
}
override CheckContourCurve()
{
super.CheckContourCurve();
if (this._SweepPath && !this._FixContourByArcSweepPath_Ing)
this.FixArcSweepPathLength();
}
get BoundingBoxInOCS()
{
if (this._SweepPath)
@ -192,6 +188,56 @@ export class Board extends ExtrudeSolid
this._isDrawArcGroove = v;
}
/**
* path
* @param {{ key: number, arc: Arc; }[]} oldArcs board options key
* @param {Polyline} nPath
* @return {*} {void}
*/
private UpdateArcBoardOptionsByPath(oldArcs: { key: number, arc: Arc; }[], nPath: Polyline): void
{
if (oldArcs.length === 0) return;
const nCurves = nPath.Explode();
const newArcs: { key: number, arc: Arc; }[] = [];
for (let i = 0; i < nCurves.length; i++)
if (nCurves[i] instanceof Arc)
newArcs.push({ key: i, arc: nCurves[i] as Arc });
const newOpts = new Map<number, ArcBoardOptions>();
const oldOpts = this._ArcBoardOptions;
newOpts.set(-1, oldOpts.get(-1));
// 设置新圆弧对应的原始配置
for (let i = 0; i < newArcs.length; i++)
for (const item of oldArcs)
{
const oldArc = item.arc;
const oldKey = item.key;
const newArc = newArcs[i].arc;
const newKey = newArcs[i].key;
if (equalv3(newArc.StartPoint, oldArc.StartPoint, 1e-5) || equalv3(newArc.EndPoint, oldArc.EndPoint, 1e-5)) // 若圆弧的头或尾部位置相同,说明是同一段圆弧
{
newOpts.set(newKey, { ...oldOpts.get(oldKey), arcLength: parseFloat(FixedNotZero(newArc.Length, 5)) });
break;
}
}
// 曲线从头拉到尾部后面,或者从尾拉到头部前面
if (newArcs.length === 1 && newOpts.size === 1)
{
let oldArcIndex = 0;// 第一个圆弧
if (equalv3(newArcs[0].arc.StartPoint, arrayLast(oldArcs).arc.EndPoint, 1e-3)) // 从头拉伸到尾部后面,则新圆弧的起点和旧圆弧的尾点相等。
oldArcIndex = oldArcs.length - 1; // 最后一个圆弧
const oldKey = oldArcs[oldArcIndex].key;
const newKey = newArcs[0].key;
newOpts.set(newKey, { ...oldOpts.get(oldKey), arcLength: parseFloat(FixedNotZero(newArcs[0].arc.Length, 5)) });
}
this._ArcBoardOptions.clear();
this._ArcBoardOptions = newOpts;
}
get ArcBoardOptions()
{
if (this._ArcBoardOptions.size > 0)
@ -2191,6 +2237,7 @@ export class Board extends ExtrudeSolid
|| renderType === RenderType.CustomNumber //自定义编号
|| renderType === RenderType.CustomNumberPrint//自定义编号打印
|| renderType === RenderType.ModelGroove //造型槽
|| this.IsEmbedEntity && !this.ParentEntity.objectId // 复合实体
)
{
obj = new Object3D();
@ -2207,22 +2254,25 @@ export class Board extends ExtrudeSolid
UpdateDrawObject(renderType: RenderType, obj: Object3D)
{
if (this._SweepPath && renderType === RenderType.Jig)
// if (this._SweepPath)
// 圆弧板和复合实体内的圆弧板Jig时实时显示见光面路径
if (this._SweepPath && (renderType === RenderType.Jig || this.IsEmbedEntity && !this.ParentEntity.objectId))
{
DisposeThreeObj(obj);
Object3DRemoveAll(obj);
let pts = this._SweepPath.Shape.getPoints().map(AsVector3);
for (let p of pts)
{
p.z = p.y;
p.y = 0;
if (this._SweepAngle !== 0)
p.applyMatrix4(this.ArcBuild.Rotate2OCSMtx);
}
let geo = new BufferGeometry().setFromPoints(pts);
obj.add(new TLine(geo, ColorMaterial.GetLineMaterial(this.DrawColorIndex)));
if (!this._jigSweepPath)
return;
const path2BoardMtx = new Matrix4();
const invMtx = new Matrix4().getInverse(this._Matrix);
path2BoardMtx.multiplyMatrices(invMtx, this._jigPath2WCSMtx);
const pts = this._jigSweepPath.Shape.getPoints().map(AsVector3);
const geo = new BufferGeometry().setFromPoints(pts);
const line = new TLine(geo, ColorMaterial.GetLineMaterial(this.ColorIndex));
line.matrix = path2BoardMtx;
obj.add(line);
this._jigSweepPath = undefined;
this._jigPath2WCSMtx = undefined;
return;
}
@ -2522,30 +2572,17 @@ export class Board extends ExtrudeSolid
override GetGripPoints(): Vector3[]
{
let pts = super.GetGripPoints();
pts = this.MapToArcPoints(pts, DragPointType.Grip);
return pts;
}
private MapToArcPoints(pts: Vector3[], dragPointType: DragPointType): Vector3[]
{
if (this._SweepPath)
{
if (!this._SweepArcBoardBuild)
this._SweepArcBoardBuild = new ArcBoardBuild(this);
if (false)//暂时放弃这个直接拉伸路径的功能
{
// if (!this._SweepArcBoardBuild)
// {
// this._SweepArcBoardBuild = new ArcBoardBuild(this);
// this._SweepArcBoardBuild.ParseSweepCurves();
// }
let pts = this._SweepPath.GetGripPoints();
for (let p of pts)
{
[p.y, p.z] = [p.z, p.y];//映射点
if (this._SweepAngle !== 0)
p.applyMatrix4(this._SweepArcBoardBuild.Rotate2OCSMtx);
p.applyMatrix4(this.OCSNoClone);
}
return pts;
}
let inv = this.OCSInv;
let mtx = this.OCSNoClone;
if (this._SweepArcBoardBuild._OCS2RotateMtx)
@ -2567,10 +2604,8 @@ export class Board extends ExtrudeSolid
this._SweepArcBoardBuild.PosMap2ArcPos(p);
p.applyMatrix4(mtx);
}
}
if (this.HasSideModel)
this.AddSideModelGripPoints(pts, DragPointType.Grip);
} else if (this.HasSideModel)
this.AddSideModelGripPoints(pts, dragPointType);
return pts;
}
@ -2578,101 +2613,25 @@ export class Board extends ExtrudeSolid
override MoveGripPoints(indexList: number[], vec: Vector3): void
{
if (indexList.length === 0) return;
this.ClearSideModelingCache();
if (this._SweepPath)
{
this.WriteAllObjectRecord();
if (false)//暂时放弃这个直接拉伸路径的功能
{
vec = TransformVector(vec.clone(), this.OCSInv);
if (this._SweepAngle !== 0)
TransformVector(vec, this.ArcBuild.OCS2RotateMtx);
[vec.y, vec.z] = [vec.z, -vec.y];
this._SweepPath.MoveGripPoints(indexList, vec);
let sp = this._SweepPath.StartPoint;
if (!equalv3(sp, ZeroVec))
{
for (let i = 0; i < this._SweepPath.LineData.length; i++)
this._SweepPath.LineData[i].pt.sub(sp as unknown as Vector2);
this._SweepPath.OCSNoClone.identity();
let [y, z] = [sp.y, sp.z];
sp.z = y;
sp.y = -z;
if (this._SweepAngle !== 0)
TransformVector(sp, this.ArcBuild.Rotate2OCSMtx);
TransformVector(sp, this.OCSNoClone);
this.Move(sp);
}
if (this.objectId)
this.FixContourByArcSweepPath();
this.Update();
return;
}
this.MoveArcBoardPoints(indexList, vec, DragPointType.Grip);
this.Update();
}
this.ClearSideModelingCache();
super.MoveGripPoints(indexList, vec);
else
super.MoveGripPoints(indexList, vec);
}
GetStretchPoints()
{
if (this._SweepPath)
{
let spts = this._SweepPath.GetStretchPoints();
let pts: Vector3[] = [];
if (!this._SweepArcBoardBuild)
this._SweepArcBoardBuild = new ArcBoardBuild(this);
for (let p of spts)
{
[p.y, p.z] = [p.z, p.y];//映射点
if (this._SweepAngle !== 0)
p.applyMatrix4(this._SweepArcBoardBuild.Rotate2OCSMtx);
pts.push(p);
}
let brWidth: number;
if (this._SweepAngle === 0)
brWidth = this.height;
else if (equaln(Math.abs(this._SweepAngle), Math.PI / 2))
brWidth = this.width;
else
{
let con = this.ContourCurve.Clone();
let ro = new Matrix4().makeRotationZ(-this._SweepAngle);
con.ApplyMatrix(ro);
let box = con.BoundingBox;
brWidth = box.max.y - box.min.y;
}
let v = new Vector3(0, brWidth, 0);
if (this._SweepAngle !== 0)
TransformVector(v, this._SweepArcBoardBuild.Rotate2OCSMtx);
for (let p of spts)
pts.push(p.clone().add(v));
for (let p of pts)
p.applyMatrix4(this.OCSNoClone);
return pts;
}
let pts = this.GetGripOrStretchPoints(DragPointType.Stretch);
pts = this.MapToArcPoints(pts, DragPointType.Stretch);
for (let m of this._2DModelingList)
{
pts.push(...m.path.GetStretchPoints().map(p => p.add(new Vector3(0, 0, m.dir === FaceDirection.Front ? this.thickness : 0)).applyMatrix4(this.OCSNoClone)));
}
if (this.HasSideModel)
this.AddSideModelGripPoints(pts, DragPointType.Stretch);
return pts;
}
@ -2685,147 +2644,6 @@ export class Board extends ExtrudeSolid
undoData.WriteObjectHistoryPath(this, new HistorycRecord);
return;
}
if (this._SweepPath)
{
if (false)
{
this.WriteAllObjectRecord();
let stretchCount = this._SweepPath.GetDragPointCount(DragPointType.Stretch);
//Move
if (indexList.length === stretchCount * 2)
{
this.Position = this.Position.add(vec);
return;
}
vec = vec.clone();
let inv = this.OCSInv.setPosition(0, 0, 0);
vec.applyMatrix4(inv);
if (this._SweepAngle !== 0)
TransformVector(vec, this.ArcBuild.OCS2RotateMtx);
const IsStretchThickness = (indexs: number[]) =>
{
if (indexs.length === stretchCount)
{
let isF = indexs[0] < stretchCount;
return indexs.every(i => isF === (i < stretchCount));
}
return false;
};
if (IsStretchThickness(indexList))
{
let isFront = indexList[0] < stretchCount;
if (indexList.every(v => v < stretchCount === isFront))
{
function UnEqualProportionScale(cu: Curve, ref: number, dist: number, isFront: boolean)
{
if (cu instanceof Polyline)
{
let lineData = cu.LineData;
let length = lineData.length;
let p = cu.Position.y;
let moveIndexs: number[] = [];
for (let i = 0; i < length; i++)
{
if (isFront ? (lineData[i].pt.y + p < ref) : (lineData[i].pt.y + p > ref))
moveIndexs.push(i);
}
let moveVec = new Vector3();
moveVec.y = dist;
cu.MoveStretchPoints(moveIndexs, moveVec);
return true;
}
return false;
}
//Change thickness
let con = this.ContourCurve.Clone();
if (this._SweepAngle !== 0)
con.ApplyMatrix(this.ArcBuild.OCS2RotateMtx);
(con as Polyline).UpdateOCSTo(new Matrix4);
let box = con.BoundingBox;
let size = box.max.y - box.min.y;
{
// if (this.objectId)
// TestDraw(con.Clone(), 4);
let isSuccess = UnEqualProportionScale(con, size / 2, vec.y, isFront);
// if (this.objectId)
// TestDraw(con.Clone(), 3);
if (this._SweepAngle !== 0)
con.ApplyMatrix(this.ArcBuild.Rotate2OCSMtx);
let box = con.BoundingBox;
// if (this.objectId)
// TestDraw(con.Clone(), 2);
con.Move(box.min.clone().negate());
// if (this.objectId)
// TestDraw(con.Clone(), 1);
this.SetContourCurve(con);
// //移动位置而不改变内部拉槽
let v = box.min;
TransformVector(v, this.OCSNoClone);
this._Matrix.elements[12] += v.x;
this._Matrix.elements[13] += v.y;
this._Matrix.elements[14] += v.z;
}
return;
}
}
indexList = arrayClone(indexList);
//修正点的索引
for (let i = 0; i < indexList.length; i++)
{
let index = indexList[i];
if (index >= stretchCount)
{
index -= stretchCount;
indexList[i] = index;
}
}
indexList = [...new Set(indexList)];
[vec.y, vec.z] = [vec.z, -vec.y];
this._SweepPath.MoveStretchPoints(indexList, vec);
let sp = this._SweepPath.StartPoint;
if (!equalv3(sp, ZeroVec))
{
for (let i = 0; i < this._SweepPath.LineData.length; i++)
this._SweepPath.LineData[i].pt.sub(sp as unknown as Vector2);
this._SweepPath.OCSNoClone.identity();
let [y, z] = [sp.y, sp.z];
sp.z = y;
sp.y = -z;
if (this._SweepAngle !== 0)
TransformVector(sp, this.ArcBuild.Rotate2OCSMtx);
TransformVector(sp, this.OCSNoClone);
this.Move(sp);
}
this.FixContourByArcSweepPath();
this.Update();
}
return;//暂时屏蔽圆弧板的拉伸
}
let exCount = arraySum(this.GetStrectchPointCountList(DragPointType.Stretch));
let originIndexList: number[] = [];
let mIndexList: number[] = [];
@ -2839,7 +2657,10 @@ export class Board extends ExtrudeSolid
let oldOcs = this.OCS;
super.MoveStretchPoints(originIndexList, vec);
if (this._SweepPath)
this.MoveArcBoardPoints(originIndexList, vec, DragPointType.Stretch);
else
super.MoveStretchPoints(originIndexList, vec);
if (!this.Id) return;
@ -2991,6 +2812,257 @@ export class Board extends ExtrudeSolid
return pts;
}
private MoveArcBoardPoints(indexList: Array<number>, vec: Vector3, dragType: DragPointType)
{
this.WriteAllObjectRecord();
const isGrip = dragType === DragPointType.Grip;
const oldPts = isGrip ? this.GetGripPoints() : this.GetStretchPoints();
const MoveBack = () => isGrip ? super.MoveGripPoints(indexList, offsetVec.clone().negate()) : super.MoveStretchPoints(indexList, offsetVec.clone().negate());
let path = this.ArcBuild.SweepPath1.Clone();
// 1、计算沿着SweepPath偏移的向量
const offsetVec = this.GetOffsetVecAlongPath(oldPts[indexList[0]].clone(), vec, path);
const oldPos = this.Position;
const oldCon = this.ContourCurve.Clone();
const ocs2rot = this.ArcBuild.OCS2RotateMtx;
oldCon.ApplyMatrix(ocs2rot);
const oldBox = oldCon.BoundingBox;
// 2、移动平板上的点
isGrip ? super.MoveGripPoints(indexList, offsetVec) : super.MoveStretchPoints(indexList, offsetVec);
const newPos = this.Position;
const conMoveVec = TransformVector(newPos.clone().sub(oldPos), this.OCSInv);//轮廓在OCS中移动的向量
const newCon = this.ContourCurve.Clone();
newCon.Move(conMoveVec);
newCon.ApplyMatrix(ocs2rot);
const newBox = newCon.BoundingBox;
this._jigSweepPath = path.Clone();
// 特殊场景闭合SweepPath其对应的首尾不能发生变化否者会发生path和Contour映射错误。
if (path.CloseMark && !(equaln(newBox.min.x, oldBox.min.x) && equaln(newBox.max.x, oldBox.max.x)))
{
MoveBack();// 若头尾被拖拽过,需要恢复回去
return;
}
// 特殊场景:某些操作,对弧形板进行移动(如当拖拽中间点),未发生路径改变,则重新移动回去
const newSize = newBox.getSize(new Vector3);
const oldSize = oldBox.getSize(new Vector3);
if (equaln(newSize.x, oldSize.x, 1e-3))
{
const newPts = isGrip ? this.GetGripPoints() : this.GetStretchPoints();
if (oldPts.length === newPts.length)
{
const vec = oldPts[0].clone().sub(newPts[0]);
const isMoveArcBoard = oldPts.every((pt, i) => equalv3(pt.clone().sub(newPts[i]), vec));
if (isMoveArcBoard)
{
MoveBack();
return;
}
}
}
// 3、修正SweepPath
path = this.FixSweepPathByContourBondingbox(newBox, oldBox, path);
// 特殊场景path 计算发生错误,需要恢复板的状态
if (!path)
{
MoveBack();
return;
}
// 4、计算弧形板偏移矩阵
if (this.objectId || (this.IsEmbedEntity && this.ParentEntity.objectId))
{
const pts1 = isGrip ? newCon.GetGripPoints() : newCon.GetStretchPoints();
const pts2 = isGrip ? oldCon.GetGripPoints() : oldCon.GetStretchPoints();
const count = Math.min(pts1.length, pts2.length);
this._SweepArcBoardBuild = undefined;
for (let i = 0; i < count; i++)
{
if (equalv2(pts1[i], pts2[i], 1e-3)) // 找到新板和旧板上不变的点,计算出偏移矩阵
{
const pts = isGrip ? this.GetGripPoints() : this.GetStretchPoints();
this.Move(oldPts[i].sub(pts[i]));
break;
}
}
this._SweepArcBoardBuild = undefined;
}
}
private GetOffsetVecAlongPath(oldP: Vector3, vec: Vector3, path: Polyline): Vector3
{
const p = oldP.clone().add(vec);//拉伸后的点 在世界坐标系中
const path2WCSMtx = new Matrix4().makeBasis(XAxis, ZAxis, YAxisN);
if (this._SweepAngle !== 0)
path2WCSMtx.premultiply(this.ArcBuild.Rotate2OCSMtx);
path2WCSMtx.premultiply(this.OCSNoClone);
const wcs2PathMtx = new Matrix4().getInverse(path2WCSMtx);
this._jigPath2WCSMtx = path2WCSMtx.clone();
//变换到路径坐标系
p.applyMatrix4(wcs2PathMtx);
oldP.applyMatrix4(wcs2PathMtx);
// 限制p, 在见光面的曲面中,计算偏移向量
const cp = path.GetClosestPointTo(p, true);
const oldZ = oldP.z;
const newZ = p.z;
const oldPCp = path.GetClosestPointTo(oldP.setZ(0), false);//旧的最近点
const oldDist = path.GetDistAtPoint2(oldPCp);// 移动前的Dist
const movedDist = path.GetDistAtPoint2(cp);// 移动后的Dist
const moveVec = new Vector3(movedDist - oldDist, - newZ + oldZ, 0);
//将moveVec转换到世界坐标系
if (this._SweepAngle !== 0)
TransformVector(moveVec, this.ArcBuild.Rotate2OCSMtx);
TransformVector(moveVec, this.OCSNoClone);
return moveVec;
}
/**
* @private Bondingbox
* @param {Box3Ext} newBox Bondingbox
* @param {Box3Ext} oldBox Bondingbox
* @param {Polyline} path
* @return {*} {Polyline}
*/
private FixSweepPathByContourBondingbox(newBox: Box3Ext, oldBox: Box3Ext, path: Polyline): Polyline
{
// 若头部和尾部重合,则直接不处理
if (equaln(newBox.min.x, newBox.max.x, 0.1))
return;
const GetArcAndKeys = (): { key: number, arc: Arc; }[] =>
{
const curves = path.Explode();
const arcs: { key: number, arc: Arc; }[] = [];
for (let i = 0; i < curves.length; i++)
if (curves[i] instanceof Arc)
arcs.push({ key: i, arc: curves[i].Clone() as Arc });
return arcs;
};
const arcKeys = GetArcAndKeys();
const MovePath = (pathToMove: Polyline, mVec: Vector3) =>
{
// 修正SWeepPath
pathToMove.Move(mVec);
const { pts: pathPts, buls } = pathToMove.MatrixAlignTo2(new Matrix4);
pathToMove.OCSNoClone.identity();
for (let i = 0; i < pathToMove.LineData.length; i++)
{
pathToMove.LineData[i].pt.copy(pathPts[i]);
pathToMove.LineData[i].bul = buls[i];
}
};
let jigSpt: Vector3 = undefined;
const FixHead = () =>
{
if (!equaln(newBox.min.x, 0, 1e-3)) // 头部
{
const c1 = path.GetCurveAtIndex(0);
if (newBox.min.x < 0)
path.Extend(newBox.min.x / c1.Length); // 延伸
else
path = path.GetSplitCurves(path.GetParamAtDist(newBox.min.x))[1]; // 裁剪
jigSpt = path.StartPoint.clone();
MovePath(path, path.StartPoint.clone().negate());// 修正Path
}
};
const FixTail = () =>
{
if (!equaln(newBox.max.x, oldBox.max.x, 1e-3)) // 尾部
{
const dist = newBox.max.x - oldBox.max.x;
const ce = path.GetCurveAtIndex(path.EndParam - 1);
if (dist > 0)
path.Extend(path.EndParam + ((dist) / ce.Length)); // 延伸
else
path = path.GetSplitCurves(path.GetParamAtDist(newBox.max.x - newBox.min.x))[0]; // 裁剪, PS: 从尾部点拉伸到头部点之前newBox.min.x不为零
}
};
/**
*
* ___________
* A | |
* |_______ |
* | |
* old B |___|
* _____
* | | A
* ___|_____|
* | |
* new B |___|
*/
const outofTail = newBox.min.x >= oldBox.max.x
|| equaln(newBox.min.x, oldBox.max.x, 1e-3) // 矩形板:拉伸后,新板头和旧板尾部相同
|| newBox.min.x > oldBox.min.x && newBox.max.x > oldBox.max.x; // 某些异形板:新板头会在旧板中间某处,新板尾超过旧版尾
if (outofTail)
{
// 头部拉伸在超过尾部即新头部大于等于原尾部。则先对尾部延伸再裁剪头部若先裁剪头部则path可能会为空
FixTail();
FixHead();
} else
{
FixHead();
FixTail();
}
// 计算 this._SweepPath
let sweepPath = undefined;
if (this._SweepVisibleFace === FaceDirection.Back)
{
sweepPath = path;
// 做offset偏移查看path是否会被裁剪。若被裁剪会破坏板和路径的映射关系则不能继续其他操作
if (this.objectId || (this.IsEmbedEntity && this.ParentEntity.objectId))
{
const frontPath = ArcBoardBuild.OffsetPolyline(sweepPath, -this.thickness); // 正面path
const backPath = ArcBoardBuild.OffsetPolyline(frontPath, this.thickness); // 背面path
if (!equaln(backPath.Length, sweepPath.Length, 1e-3))
return;
}
}
else
{
sweepPath = ArcBoardBuild.OffsetPolyline(path, this.thickness);
// 做offset偏移查看path是否会被裁剪。若被裁剪会破坏板和路径的映射关系则不能继续其他操作
if (this.objectId || (this.IsEmbedEntity && this.ParentEntity.objectId))
{
const frontPath = ArcBoardBuild.OffsetPolyline(sweepPath, -this.thickness);// 正面path
if (!equaln(frontPath.Length, path.Length, 1e-3))
return;
}
}
this._SweepPath = sweepPath;
this._jigSweepPath = path.Clone();
if (jigSpt)
MovePath(this._jigSweepPath, jigSpt);// 新路径,但是未进行起始点偏移。方便拖拽时,实时显示当前路径
// 更新圆弧配置
if (this.objectId || (this.IsEmbedEntity && this.ParentEntity.objectId))
this.UpdateArcBoardOptionsByPath(arcKeys, this._jigSweepPath);
return path;
}
DeferUpdate()
{
if (this.NeedUpdateFlag & UpdateDraw.Matrix)

@ -114,6 +114,7 @@ export abstract class CompositeEntity extends Entity
for (let e of this.Entitys)
{
e.IsEmbedEntity = true;
e.ParentEntity = this.ParentEntity || this;
// //内嵌实体在某些时候可能被清理,修复它
// if (e.DrawObject.children.length === 0)

@ -27,7 +27,8 @@ import { PhysicalMaterialRecord } from '../PhysicalMaterialRecord';
export class Entity extends CADObject
{
IsEmbedEntity = false;
ParentEntity: Entity; //当这个实体是内嵌实体时,提供了一个访问它父亲的链接
IsEmbedEntity = false;//当这个值为true时,这个实体是复合实体的内嵌实体
/**
* ,

@ -1104,7 +1104,7 @@ export class ExtrudeSolid extends Entity
}
}
if (this.objectId)
if (this.objectId || (this.IsEmbedEntity && this.ParentEntity.objectId))
{
this.CheckContourCurve();
let splitEntitys: this[] = [];

@ -629,6 +629,27 @@ export class Polyline extends Curve
return this.GetDistAtParam(param);
}
/**
* 线线
* @param pt
* @returns
*/
GetDistAtPoint2(pt: Vector3): number
{
let param = this.GetParamAtPoint(pt);
if (param < 0)
{
let c1 = this.GetCurveAtIndex(0);
return c1.Length * param;
}
else if (param > this.EndParam)
{
let ce = this.GetCurveAtIndex(this.EndParam - 1);
return this.Length + ce.Length * (param - this.EndParam);
}
return this.GetDistAtParam(param);
}
/**
* 线.
* 线()线.
@ -850,8 +871,8 @@ export class Polyline extends Curve
//修改凸度
let oldBul = this._LineData[bulIndex].bul;
if (oldBul != 0)
this._LineData[bulIndex].bul = Math.tan(Math.atan(oldBul) * (1 + newParam - ptIndex));
if (oldBul !== 0)
this._LineData[bulIndex].bul = Math.tan(Math.atan(oldBul) * (1 + Math.abs(newParam - ptIndex)));
this.Update();
}

Loading…
Cancel
Save