|
|
@ -1,93 +1,26 @@
|
|
|
|
import { Matrix4, Vector3 } from 'three';
|
|
|
|
|
|
|
|
import { end } from 'xaop';
|
|
|
|
import { end } from 'xaop';
|
|
|
|
import { app } from '../ApplicationServices/Application';
|
|
|
|
import { app } from '../ApplicationServices/Application';
|
|
|
|
import { curveLinkGroup, GetPointAtCurveDir, Vec3DTo2D } from '../Common/CurveUtils';
|
|
|
|
|
|
|
|
import { KeyWord } from '../Common/InputState';
|
|
|
|
import { KeyWord } from '../Common/InputState';
|
|
|
|
import { KeyBoard } from '../Common/KeyEnum';
|
|
|
|
import { KeyBoard } from '../Common/KeyEnum';
|
|
|
|
import { FixedNotZero } from '../Common/Utils';
|
|
|
|
import { FixedNotZero } from '../Common/Utils';
|
|
|
|
import { Arc } from '../DatabaseServices/Arc';
|
|
|
|
|
|
|
|
import { Circle } from '../DatabaseServices/Circle';
|
|
|
|
|
|
|
|
import { Curve } from '../DatabaseServices/Curve';
|
|
|
|
import { Curve } from '../DatabaseServices/Curve';
|
|
|
|
import { Line } from '../DatabaseServices/Line';
|
|
|
|
|
|
|
|
import { Polyline } from '../DatabaseServices/Polyline';
|
|
|
|
import { Polyline } from '../DatabaseServices/Polyline';
|
|
|
|
import { Command } from '../Editor/CommandMachine';
|
|
|
|
import { Command } from '../Editor/CommandMachine';
|
|
|
|
import { JigUtils } from '../Editor/JigUtils';
|
|
|
|
import { JigUtils } from '../Editor/JigUtils';
|
|
|
|
import { PromptEntityResult, PromptStatus } from '../Editor/PromptResult';
|
|
|
|
import { PromptEntityResult, PromptStatus } from '../Editor/PromptResult';
|
|
|
|
import { angle, equalv3, isParallelTo, midPoint } from '../Geometry/GeUtils';
|
|
|
|
import { FilletUtils } from './FilletUtils';
|
|
|
|
import { IntersectOption } from '../GraphicsSystem/IntersectWith';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum ExtendType
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Start = 1,
|
|
|
|
|
|
|
|
End = 2,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cu1: Curve;
|
|
|
|
|
|
|
|
cu2: Curve;
|
|
|
|
|
|
|
|
arc: Arc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type CurveExtend = { Curve: Curve, ExtType: ExtendType };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const RADKEY = 'filletRadius';
|
|
|
|
const RADKEY = 'filletRadius';
|
|
|
|
|
|
|
|
|
|
|
|
function Encode(res: PromptEntityResult, enMap: (PromptEntityResult[])[])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (res.Entity instanceof Line)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
enMap[0].push(res);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (res.Entity instanceof Arc)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
enMap[1].push(res);
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (res.Entity instanceof Polyline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
enMap[2].push(res);
|
|
|
|
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//把圆转换成圆弧,避免圆参与计算.
|
|
|
|
|
|
|
|
function CircleEnResToArc(enRes: PromptEntityResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (enRes.Entity instanceof Circle)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let an = angle(enRes.Point.clone().applyMatrix4(enRes.Entity.OCSInv)) + Math.PI;
|
|
|
|
|
|
|
|
let arc = new Arc(new Vector3(), enRes.Entity.Radius, an, an + 0.1);
|
|
|
|
|
|
|
|
arc.ApplyMatrix(enRes.Entity.OCS);
|
|
|
|
|
|
|
|
arc.Center = enRes.Entity.Center;
|
|
|
|
|
|
|
|
enRes.Entity = arc;
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
|
|
|
enRes.IsCircle = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function GetFilletCurve(enRes: PromptEntityResult): any[]
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (enRes.Entity instanceof Polyline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pl = enRes.Entity;
|
|
|
|
|
|
|
|
let param = pl.GetParamAtPoint(pl.GetClosestPointTo(enRes.Point, false));
|
|
|
|
|
|
|
|
let paramF = Math.floor(param);
|
|
|
|
|
|
|
|
return [pl.GetCurveAtParam(param), paramF];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return [enRes.Entity, NaN];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class CommandFillet implements Command
|
|
|
|
export class CommandFillet implements Command
|
|
|
|
{
|
|
|
|
{
|
|
|
|
m_FilletRadius: number = 0;
|
|
|
|
m_FilletRadius: number = 0;
|
|
|
|
|
|
|
|
private m_FilletUtils = new FilletUtils();
|
|
|
|
constructor()
|
|
|
|
constructor()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let radStr = window.localStorage.getItem(RADKEY);
|
|
|
|
let radStr = window.localStorage.getItem(RADKEY);
|
|
|
|
if (radStr)
|
|
|
|
if (radStr)
|
|
|
|
this.m_FilletRadius = parseFloat(radStr);
|
|
|
|
this.UpdateFilletRadius(parseFloat(radStr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async exec()
|
|
|
|
async exec()
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -105,8 +38,6 @@ export class CommandFillet implements Command
|
|
|
|
app.m_Editor.UCSMatrix = oldUcs;
|
|
|
|
app.m_Editor.UCSMatrix = oldUcs;
|
|
|
|
if (!enRes1) return;
|
|
|
|
if (!enRes1) return;
|
|
|
|
|
|
|
|
|
|
|
|
CircleEnResToArc(enRes1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enRes1.Entity.UpdateJigMaterial();
|
|
|
|
enRes1.Entity.UpdateJigMaterial();
|
|
|
|
|
|
|
|
|
|
|
|
let lastCu: Curve;
|
|
|
|
let lastCu: Curve;
|
|
|
@ -125,10 +56,9 @@ export class CommandFillet implements Command
|
|
|
|
app.m_Editor.UpdateScreen();
|
|
|
|
app.m_Editor.UpdateScreen();
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CircleEnResToArc(res2);
|
|
|
|
|
|
|
|
app.m_Editor.UCSMatrix = res2.Entity.OCS;
|
|
|
|
app.m_Editor.UCSMatrix = res2.Entity.OCS;
|
|
|
|
res2.Entity.UpdateJigMaterial();
|
|
|
|
res2.Entity.UpdateJigMaterial();
|
|
|
|
let fres = this.Fillet(enRes1, res2);
|
|
|
|
let fres = this.m_FilletUtils.Fillet(enRes1, res2);
|
|
|
|
for (let v in fres)
|
|
|
|
for (let v in fres)
|
|
|
|
if (fres[v])
|
|
|
|
if (fres[v])
|
|
|
|
JigUtils.Draw(fres[v])
|
|
|
|
JigUtils.Draw(fres[v])
|
|
|
@ -164,7 +94,7 @@ export class CommandFillet implements Command
|
|
|
|
if (enRes2.Status === PromptStatus.String)
|
|
|
|
if (enRes2.Status === PromptStatus.String)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let rad = parseFloat(enRes2.StringResult);
|
|
|
|
let rad = parseFloat(enRes2.StringResult);
|
|
|
|
if (rad !== 0)
|
|
|
|
if (rad !== 0 && !isNaN(rad))
|
|
|
|
this.UpdateFilletRadius(rad);
|
|
|
|
this.UpdateFilletRadius(rad);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (enRes2.Status !== PromptStatus.None)
|
|
|
|
else if (enRes2.Status !== PromptStatus.None)
|
|
|
@ -180,8 +110,7 @@ export class CommandFillet implements Command
|
|
|
|
|
|
|
|
|
|
|
|
if (enRes2.Status === PromptStatus.OK)
|
|
|
|
if (enRes2.Status === PromptStatus.OK)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
CircleEnResToArc(enRes2);
|
|
|
|
let res = this.m_FilletUtils.Fillet(enRes1, enRes2);
|
|
|
|
let res = this.Fillet(enRes1, enRes2);
|
|
|
|
|
|
|
|
if (!res)
|
|
|
|
if (!res)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
@ -206,743 +135,12 @@ export class CommandFillet implements Command
|
|
|
|
|
|
|
|
|
|
|
|
UpdateFilletRadius(newRadius: number)
|
|
|
|
UpdateFilletRadius(newRadius: number)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (newRadius < 0)
|
|
|
|
if (newRadius < 0 || isNaN(newRadius))
|
|
|
|
app.m_Editor.Prompt("半径不能为负!");
|
|
|
|
app.m_Editor.Prompt("半径不能为负!");
|
|
|
|
this.m_FilletRadius = Math.abs(newRadius);
|
|
|
|
this.m_FilletRadius = Math.abs(newRadius);
|
|
|
|
window.localStorage.setItem(RADKEY, this.m_FilletRadius.toString());
|
|
|
|
window.localStorage.setItem(RADKEY, this.m_FilletRadius.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Fillet(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let { enType, enMap } = this.EnCode(enRes1, enRes2);
|
|
|
|
|
|
|
|
if (enType === 4 && enRes1.Entity === enRes2.Entity)
|
|
|
|
|
|
|
|
return this.FilletPolyLineSelf(enRes1, enRes2);
|
|
|
|
|
|
|
|
else if (enType >= 4)
|
|
|
|
|
|
|
|
return this.FilletPolylineAndCurve(enRes1, enRes2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let interPts = this.GetIntersectAndSort(enRes1, enRes2, enType, enMap);
|
|
|
|
|
|
|
|
if (interPts.length === 0
|
|
|
|
|
|
|
|
|| (interPts.length === 1 && (enType & 2)))//圆弧相切
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (enType === 1)
|
|
|
|
|
|
|
|
return this.FilletParallelLine(enRes1, enRes2);
|
|
|
|
|
|
|
|
else if (enType === 3)
|
|
|
|
|
|
|
|
return this.FilletLineAndArc(enMap, enRes1);
|
|
|
|
|
|
|
|
else if (enType === 2)
|
|
|
|
|
|
|
|
return this.FilletArcAndArc(enRes1, enRes2);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.FilletLineOrArc(enRes1, enRes2, interPts);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FilletLineOrArc(enRes1: PromptEntityResult, enRes2: PromptEntityResult, interPts: Vector3[]): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let iPt = interPts[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//裁剪延伸,使两条线组成一个尖角
|
|
|
|
|
|
|
|
let splitedCu1 = this.SplitCurve(enRes1, iPt, interPts);
|
|
|
|
|
|
|
|
let splitedCu2 = this.SplitCurve(enRes2, iPt, interPts);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let fRadius = this.m_FilletRadius;
|
|
|
|
|
|
|
|
//按下shift键时半径归0
|
|
|
|
|
|
|
|
if (app.m_Editor.m_KeyCtrl.KeyIsDown(KeyBoard.Shift))
|
|
|
|
|
|
|
|
fRadius = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (enRes1.Entity instanceof Arc && enRes2.Entity instanceof Arc)
|
|
|
|
|
|
|
|
return this.FilletArcAndArc(enRes1, enRes2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let res: FilletRes = { cu1: splitedCu1.Curve, cu2: splitedCu2.Curve, arc: undefined };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fRadius > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//角平分线向量.
|
|
|
|
|
|
|
|
let bisectorVec: Vector3 = new Vector3();
|
|
|
|
|
|
|
|
let c1Derv = this.ComputerDerv(splitedCu1, bisectorVec);
|
|
|
|
|
|
|
|
let c2Derv = this.ComputerDerv(splitedCu2, bisectorVec);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//方向相反
|
|
|
|
|
|
|
|
if (equalv3(bisectorVec, new Vector3()))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//相切
|
|
|
|
|
|
|
|
if (equalv3(c2Derv, c1Derv))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
bisectorVec.set(0, 0, 0);
|
|
|
|
|
|
|
|
c1Derv = this.ComputerDerv2(splitedCu1, bisectorVec);
|
|
|
|
|
|
|
|
c2Derv = this.ComputerDerv2(splitedCu2, bisectorVec);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let cu1RoOcsInv = new Matrix4().extractRotation(splitedCu1.Curve.OCSInv);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[c1Derv, c2Derv, bisectorVec].forEach(v => v.applyMatrix4(cu1RoOcsInv));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let offCu1 = splitedCu1.Curve.GetOffsetCurves(
|
|
|
|
|
|
|
|
fRadius * -Math.sign(c1Derv.cross(bisectorVec).z))[0];
|
|
|
|
|
|
|
|
let offCu2 = splitedCu2.Curve.GetOffsetCurves(
|
|
|
|
|
|
|
|
fRadius * -Math.sign(c2Derv.cross(bisectorVec).z))[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!offCu1 || !offCu2)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//测试绘制
|
|
|
|
|
|
|
|
offCu1.ColorIndex = 6;
|
|
|
|
|
|
|
|
offCu2.ColorIndex = 6;
|
|
|
|
|
|
|
|
JigUtils.Draw(offCu1.Clone());
|
|
|
|
|
|
|
|
JigUtils.Draw(offCu2.Clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let center = offCu1.IntersectWith(offCu2, IntersectOption.OnBothOperands)
|
|
|
|
|
|
|
|
.sort((p1, p2) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return p1.distanceToSquared(iPt) - p2.distanceToSquared(iPt);
|
|
|
|
|
|
|
|
})[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!center)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arcP1 = splitedCu1.Curve.GetClosestPointTo(center, true);
|
|
|
|
|
|
|
|
let arcP2 = splitedCu2.Curve.GetClosestPointTo(center, true);
|
|
|
|
|
|
|
|
if (!splitedCu1.Curve.PtOnCurve(arcP1) || !splitedCu2.Curve.PtOnCurve(arcP2))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//时针校验
|
|
|
|
|
|
|
|
let v1 = arcP1.clone().sub(center).applyMatrix4(cu1RoOcsInv);
|
|
|
|
|
|
|
|
let v2 = arcP2.clone().sub(center).applyMatrix4(cu1RoOcsInv);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//绘制圆弧
|
|
|
|
|
|
|
|
let arc = new Arc(new Vector3(), this.m_FilletRadius, angle(v1), angle(v2), v1.cross(v2).z < 0);
|
|
|
|
|
|
|
|
arc.ApplyMatrix(splitedCu1.Curve.OCS);
|
|
|
|
|
|
|
|
arc.Center = center;
|
|
|
|
|
|
|
|
res.arc = arc;
|
|
|
|
|
|
|
|
//延伸或者裁剪到圆弧点
|
|
|
|
|
|
|
|
this.ExtendPt(splitedCu1, arcP1);
|
|
|
|
|
|
|
|
this.ExtendPt(splitedCu2, arcP2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
FilletPolyLineSelf(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pl = enRes1.Entity as Polyline;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let param1 = pl.GetParamAtPoint(pl.GetClosestPointTo(enRes1.Point, false));
|
|
|
|
|
|
|
|
let param2 = pl.GetParamAtPoint(pl.GetClosestPointTo(enRes2.Point, false));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (param1 > param2) [param1, param2] = [param2, param1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let parF1 = Math.floor(param1);
|
|
|
|
|
|
|
|
let parF2 = Math.floor(param2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//共线
|
|
|
|
this.m_FilletUtils.m_FilletRadius = this.m_FilletRadius;
|
|
|
|
if (parF1 === parF2)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let c1 = pl.GetCurveAtParam(param1);
|
|
|
|
|
|
|
|
let c2 = pl.GetCurveAtParam(param2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (equalv3(c1.GetFistDeriv(1).normalize(), c2.GetFistDeriv(0).normalize()))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let rem = parF2 - parF1;
|
|
|
|
|
|
|
|
if (rem === 1 || (rem + 1 === pl.EndParam))//相邻线段倒角
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let es1 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es1.Entity = c1;
|
|
|
|
|
|
|
|
es1.Point = enRes1.Point;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es2 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es2.Entity = c2;
|
|
|
|
|
|
|
|
es2.Point = enRes2.Point;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let res = this.Fillet(es1, es2);
|
|
|
|
|
|
|
|
if (res && res.arc)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pln = pl.Clone();
|
|
|
|
|
|
|
|
//修正凸度
|
|
|
|
|
|
|
|
if (res.cu1 instanceof Arc)
|
|
|
|
|
|
|
|
pln.SetBulgeAt(parF1, res.cu1.Bul);
|
|
|
|
|
|
|
|
if (res.cu2 instanceof Arc)
|
|
|
|
|
|
|
|
pln.SetBulgeAt(parF2, res.cu2.Bul);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sp2d = Vec3DTo2D(res.arc.StartPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
|
|
|
let ep2d = Vec3DTo2D(res.arc.EndPoint.applyMatrix4(pln.OCSInv));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let isNeighbor = rem === 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//#IOX26
|
|
|
|
|
|
|
|
if (isNeighbor && res.cu1 instanceof Arc && res.cu2 instanceof Arc)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let ins = res.cu1.IntersectWith(res.cu2, IntersectOption.OnBothOperands);
|
|
|
|
|
|
|
|
if (ins.length === 1 && !equalv3(pln.StartPoint, ins[0]))
|
|
|
|
|
|
|
|
isNeighbor = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isNeighbor)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pln.SetPointAt(parF2, ep2d);
|
|
|
|
|
|
|
|
pln.AddVertexAt(parF2, sp2d);
|
|
|
|
|
|
|
|
pln.SetBulgeAt(parF2, res.arc.Bul);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else//首尾
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pln.SetPointAt(0, sp2d);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let plPtCount = pln.NumberOfVertices;
|
|
|
|
|
|
|
|
if (pln.EndParam === plPtCount)//CloseMark
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pln.AddVertexAt(plPtCount, ep2d);
|
|
|
|
|
|
|
|
pln.SetBulgeAt(plPtCount, -res.arc.Bul);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pln.SetPointAt(plPtCount - 1, ep2d);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pln.SetBulgeAt(plPtCount - 1, -res.arc.Bul);
|
|
|
|
|
|
|
|
pln.AddVertexAt(plPtCount, sp2d);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: pln,
|
|
|
|
|
|
|
|
cu2: undefined,
|
|
|
|
|
|
|
|
arc: undefined
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else//自交多段线
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let interPts = c1.IntersectWith(c2, IntersectOption.OnBothOperands);
|
|
|
|
|
|
|
|
if (interPts.length === 0)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (interPts.length === 2 && c1.GetParamAtPoint(interPts[0]) > c1.GetParamAtPoint(interPts[1]))
|
|
|
|
|
|
|
|
interPts.reverse();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ipt = interPts[0];
|
|
|
|
|
|
|
|
let splitParam1 = Math.floor(param1) + c1.GetParamAtPoint(ipt);
|
|
|
|
|
|
|
|
let splitParam2 = Math.floor(param2) + c2.GetParamAtPoint(ipt);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cus = pl.GetSplitCurves([splitParam1, splitParam2]);
|
|
|
|
|
|
|
|
if (cus.length >= 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
cus.splice(1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pl1 = cus[0];
|
|
|
|
|
|
|
|
for (let i = 1; i < cus.length; i++)
|
|
|
|
|
|
|
|
pl1.Join(cus[i]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es1 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es1.Entity = pl1;
|
|
|
|
|
|
|
|
es1.Point = c1.GetPointAtParam(0.1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es2 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es2.Entity = pl1;
|
|
|
|
|
|
|
|
es2.Point = c2.GetPointAtParam(0.9);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.FilletPolyLineSelf(es1, es2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FilletPolylineAndCurve(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let arr1 = GetFilletCurve(enRes1);
|
|
|
|
|
|
|
|
let arr2 = GetFilletCurve(enRes2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let [cu1, paramF1] = arr1;
|
|
|
|
|
|
|
|
let [cu2, paramF2] = arr2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es1 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es1.Entity = cu1;
|
|
|
|
|
|
|
|
es1.Point = enRes1.Point;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es2 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es2.Entity = cu2;
|
|
|
|
|
|
|
|
es2.Point = enRes2.Point;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let fres = this.Fillet(es1, es2);
|
|
|
|
|
|
|
|
if (fres)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pln: Polyline;
|
|
|
|
|
|
|
|
let isFirst = false;
|
|
|
|
|
|
|
|
let cus: Curve[] = [];
|
|
|
|
|
|
|
|
if (fres.cu1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (enRes1.Entity instanceof Polyline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
isFirst = true;
|
|
|
|
|
|
|
|
pln = enRes1.Entity.Clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let xcus = enRes1.Entity.Explode();
|
|
|
|
|
|
|
|
xcus[paramF1] = fres.cu1;
|
|
|
|
|
|
|
|
cus.push(...xcus);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
|
|
|
else if (!enRes1.IsCircle)
|
|
|
|
|
|
|
|
cus.push(fres.cu1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fres.arc)
|
|
|
|
|
|
|
|
cus.push(fres.arc);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fres.cu2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (enRes2.Entity instanceof Polyline)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!pln)
|
|
|
|
|
|
|
|
pln = enRes2.Entity.Clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let xcus = enRes2.Entity.Explode();
|
|
|
|
|
|
|
|
xcus[paramF2] = fres.cu2;
|
|
|
|
|
|
|
|
cus.push(...xcus);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
|
|
|
else if (!enRes2.IsCircle)
|
|
|
|
|
|
|
|
cus.push(fres.cu2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let groups = curveLinkGroup(cus);
|
|
|
|
|
|
|
|
for (let g of groups)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (g.includes(fres.cu1) || g.includes(fres.cu2))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pln.LineData = [];
|
|
|
|
|
|
|
|
pln.ApplyMatrix(pln.OCSInv);
|
|
|
|
|
|
|
|
pln.CloseMark = false;
|
|
|
|
|
|
|
|
for (let cu of g)
|
|
|
|
|
|
|
|
pln.Join(cu);
|
|
|
|
|
|
|
|
if (isFirst)
|
|
|
|
|
|
|
|
return { cu1: pln, cu2: undefined, arc: undefined };
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return { cu1: undefined, cu2: pln, arc: undefined };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FilletPolyLineAllAngular(enRes1: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pl = enRes1.Entity as Polyline;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cus = pl.Explode();
|
|
|
|
|
|
|
|
let count = cus.length;
|
|
|
|
|
|
|
|
if (pl.IsClose)
|
|
|
|
|
|
|
|
cus.push(cus[0]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let ncus = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < count; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let c1 = cus[i];
|
|
|
|
|
|
|
|
let c2 = cus[i + 1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncus.push(c1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!c2)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (equalv3(c1.GetFistDeriv(1).normalize(), c2.GetFistDeriv(0).normalize()))
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es1 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es1.Entity = c1;
|
|
|
|
|
|
|
|
es1.Point = c1.EndPoint;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let es2 = new PromptEntityResult();
|
|
|
|
|
|
|
|
es2.Entity = c2;
|
|
|
|
|
|
|
|
es2.Point = c2.StartPoint;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let fres = this.Fillet(es1, es2);
|
|
|
|
|
|
|
|
if (fres)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (fres.cu1)
|
|
|
|
|
|
|
|
c1.CopyFrom(fres.cu1);
|
|
|
|
|
|
|
|
if (fres.cu2)
|
|
|
|
|
|
|
|
c2.CopyFrom(fres.cu2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fres.arc)
|
|
|
|
|
|
|
|
ncus.push(fres.arc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let pln = pl.Clone();
|
|
|
|
|
|
|
|
pln.LineData = [];
|
|
|
|
|
|
|
|
pln.ApplyMatrix(pln.OCSInv);
|
|
|
|
|
|
|
|
pln.CloseMark = false;
|
|
|
|
|
|
|
|
for (let cu of ncus)
|
|
|
|
|
|
|
|
pln.Join(cu);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pln.CloseMark = pl.CloseMark;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: pln,
|
|
|
|
|
|
|
|
cu2: undefined,
|
|
|
|
|
|
|
|
arc: undefined
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 平行线倒角
|
|
|
|
|
|
|
|
* @param enRes1
|
|
|
|
|
|
|
|
* @param enRes2
|
|
|
|
|
|
|
|
* @returns parallel line
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
FilletParallelLine(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let l1 = enRes1.Entity as Line;
|
|
|
|
|
|
|
|
let l2 = enRes2.Entity as Line;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let l1Derv = l1.GetFistDeriv(0);
|
|
|
|
|
|
|
|
if (!isParallelTo(l1Derv, l2.GetFistDeriv(0)))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let par1 = l2.GetClosestAtPoint(l1.StartPoint, true).param;
|
|
|
|
|
|
|
|
let par2 = l2.GetClosestAtPoint(l1.EndPoint, true).param;
|
|
|
|
|
|
|
|
if (!l1.ParamOnCurve(par1) && !l1.ParamOnCurve(par2))
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let lineClone1 = l1.Clone();
|
|
|
|
|
|
|
|
let lineClone2 = l2.Clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let par = l1.GetClosestAtPoint(enRes1.Point, true).param;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let parFix = Math.round(par);
|
|
|
|
|
|
|
|
let ptFix = lineClone1.GetPointAtParam(parFix);
|
|
|
|
|
|
|
|
let ptL2Fix = lineClone2.GetClosestAtPoint(ptFix, true).closestPt;
|
|
|
|
|
|
|
|
if ((par1 > par2) === (parFix === 1))
|
|
|
|
|
|
|
|
lineClone2.StartPoint = ptL2Fix;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
lineClone2.EndPoint = ptL2Fix;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arcCenter = midPoint(ptFix, ptL2Fix);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let sv = ptFix.sub(arcCenter).applyMatrix4(l1.OCSInv);
|
|
|
|
|
|
|
|
let ev = ptL2Fix.sub(arcCenter).applyMatrix4(l2.OCSInv);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (parFix === 0)
|
|
|
|
|
|
|
|
l1Derv.negate();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arc = new Arc(new Vector3(), ptFix.distanceTo(ptL2Fix) / 2, angle(sv), angle(ev), ev.cross(l1Derv.applyMatrix4(l1.OCSInv)).z > 0);
|
|
|
|
|
|
|
|
arc.ApplyMatrix(l1.OCS);
|
|
|
|
|
|
|
|
arc.Center = arcCenter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: lineClone1,
|
|
|
|
|
|
|
|
cu2: lineClone2,
|
|
|
|
|
|
|
|
arc
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 计算圆弧与圆弧没有交点的情况下倒角结果.
|
|
|
|
|
|
|
|
* @param enRes1
|
|
|
|
|
|
|
|
* @param enRes2
|
|
|
|
|
|
|
|
* @returns arc and arc
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
FilletArcAndArc(enRes1: PromptEntityResult, enRes2: PromptEntityResult): FilletRes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let a1 = enRes1.Entity as Arc;
|
|
|
|
|
|
|
|
let a2 = enRes2.Entity as Arc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arcO1 = a1.GetOffsetCurves(this.m_FilletRadius * (a1.IsClockWise ? -1 : 1))[0];
|
|
|
|
|
|
|
|
let arcO2 = a2.GetOffsetCurves(this.m_FilletRadius * (a2.IsClockWise ? -1 : 1))[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
arcO1.ColorIndex = 6;
|
|
|
|
|
|
|
|
arcO2.ColorIndex = 6;
|
|
|
|
|
|
|
|
JigUtils.Draw(arcO1);
|
|
|
|
|
|
|
|
JigUtils.Draw(arcO2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//求交
|
|
|
|
|
|
|
|
let intPts = arcO1.IntersectWith(arcO2, IntersectOption.ExtendBoth);
|
|
|
|
|
|
|
|
if (intPts.length === 0)
|
|
|
|
|
|
|
|
return;//无交点无法倒角
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//两选择点的中点
|
|
|
|
|
|
|
|
let clickMidp = midPoint(enRes1.Point, enRes2.Point);//用来选择合适的交点
|
|
|
|
|
|
|
|
//选择合适的交点
|
|
|
|
|
|
|
|
intPts.sort((p1, p2) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return p1.distanceToSquared(clickMidp) - p2.distanceToSquared(clickMidp);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//圆弧圆心
|
|
|
|
|
|
|
|
let narcCenter = intPts[0];
|
|
|
|
|
|
|
|
let narcP1 = a1.GetClosestPointTo(narcCenter, true);//两圆弧和相切弧的交点
|
|
|
|
|
|
|
|
let narcP2 = a2.GetClosestPointTo(narcCenter, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let tempCircle = new Circle(narcCenter, this.m_FilletRadius);
|
|
|
|
|
|
|
|
let closestPt = a1.GetClosestPointTo(a2.Center, true);//两曲线距离对方圆心最近的点
|
|
|
|
|
|
|
|
let narcMP = tempCircle.GetClosestPointTo(closestPt, false);//相切圆距离closestPt最近的点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//构造圆弧
|
|
|
|
|
|
|
|
let narc = new Arc().ApplyMatrix(a1.OCS).FromThreePoint(narcP1, narcMP, narcP2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let a1Clone = a1.Clone();
|
|
|
|
|
|
|
|
let a2Clone = a2.Clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let a1Param = a1.GetParamAtPoint(narcP1);
|
|
|
|
|
|
|
|
let a2Param = a2.GetParamAtPoint(narcP2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let a1Derv = a1.GetFistDeriv(a1Param).normalize();
|
|
|
|
|
|
|
|
let a2Derv = a2.GetFistDeriv(a2Param).normalize();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let narcDerv0 = narc.GetFistDeriv(0).normalize();
|
|
|
|
|
|
|
|
let narcDerv1 = narc.GetFistDeriv(1).normalize();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//裁剪圆弧
|
|
|
|
|
|
|
|
if (equalv3(a1Derv, narcDerv0))
|
|
|
|
|
|
|
|
a1Clone.EndPoint = narcP1;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
a1Clone.StartPoint = narcP1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (equalv3(a2Derv, narcDerv1))
|
|
|
|
|
|
|
|
a2Clone.StartPoint = narcP2;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
a2Clone.EndPoint = narcP2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: a1Clone,
|
|
|
|
|
|
|
|
cu2: a2Clone,
|
|
|
|
|
|
|
|
arc: narc
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 计算直线与圆弧没有交点的情况下倒角结果.
|
|
|
|
|
|
|
|
* @param enRes1
|
|
|
|
|
|
|
|
* @param enRes2
|
|
|
|
|
|
|
|
* @returns line and cir
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
FilletLineAndArc(enMap: (PromptEntityResult[])[], enRes1: PromptEntityResult): FilletRes | undefined
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let lineRes = enMap[0][0];
|
|
|
|
|
|
|
|
let arcRes = enMap[1][0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let line = lineRes.Entity as Line;
|
|
|
|
|
|
|
|
let arc = arcRes.Entity as Arc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let dir = GetPointAtCurveDir(line, arc.Center) ? 1 : -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let lineO = line.GetOffsetCurves(this.m_FilletRadius * dir)[0];
|
|
|
|
|
|
|
|
let arcO = arc.GetOffsetCurves(this.m_FilletRadius * (arc.IsClockWise ? -1 : 1))[0];// tip:面积逆时针为正, 顺时针为负.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lineO.ColorIndex = 6;
|
|
|
|
|
|
|
|
arcO.ColorIndex = 6;
|
|
|
|
|
|
|
|
JigUtils.Draw(lineO);
|
|
|
|
|
|
|
|
JigUtils.Draw(arcO);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//求交
|
|
|
|
|
|
|
|
let intPts = lineO.IntersectWith(arcO, IntersectOption.ExtendBoth);
|
|
|
|
|
|
|
|
if (intPts.length === 0)
|
|
|
|
|
|
|
|
return;//无交点无法倒角
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//两选择点的中点
|
|
|
|
|
|
|
|
let clickMidp = midPoint(lineRes.Point, arcRes.Point);
|
|
|
|
|
|
|
|
//选择适合的交点。
|
|
|
|
|
|
|
|
intPts.sort((p1, p2) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return p1.distanceToSquared(clickMidp) - p2.distanceToSquared(clickMidp);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
//圆弧圆心
|
|
|
|
|
|
|
|
let arcCenter = intPts[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let arcP1 = line.GetClosestPointTo(arcCenter, true);//直线与相切圆的交点
|
|
|
|
|
|
|
|
let arcP2 = arc.GetClosestPointTo(arcCenter, true);//圆弧与相切圆的交点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let tempCircle = new Circle(arcCenter, this.m_FilletRadius);
|
|
|
|
|
|
|
|
let { closestPt, param } = line.GetClosestAtPoint(arc.Center, true);
|
|
|
|
|
|
|
|
let arcMP = tempCircle.GetClosestPointTo(closestPt, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//构造圆弧
|
|
|
|
|
|
|
|
let narc = new Arc().ApplyMatrix(arc.OCS).FromThreePoint(arcP1, arcMP, arcP2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//裁剪线
|
|
|
|
|
|
|
|
let lineClone = line.Clone();
|
|
|
|
|
|
|
|
let arcClone = arc.Clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let p1Param = line.GetParamAtPoint(arcP1);
|
|
|
|
|
|
|
|
if (p1Param > param)
|
|
|
|
|
|
|
|
lineClone.StartPoint = arcP1;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
lineClone.EndPoint = arcP1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//裁剪圆弧
|
|
|
|
|
|
|
|
let arcParam = arc.GetParamAtPoint(arcP2);
|
|
|
|
|
|
|
|
let arcDerv = arc.GetFistDeriv(arcParam).normalize();
|
|
|
|
|
|
|
|
let narcDerv = narc.GetFistDeriv(1).normalize();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (equalv3(arcDerv, narcDerv))
|
|
|
|
|
|
|
|
arcClone.StartPoint = arcP2;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
arcClone.EndPoint = arcP2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//先选直线为真
|
|
|
|
|
|
|
|
if (enRes1.Entity === line)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: lineClone,
|
|
|
|
|
|
|
|
cu2: arcClone,
|
|
|
|
|
|
|
|
arc: narc
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
cu1: arcClone,
|
|
|
|
|
|
|
|
cu2: lineClone,
|
|
|
|
|
|
|
|
arc: narc
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//获得两曲线的交点,并且排序交点.
|
|
|
|
|
|
|
|
private GetIntersectAndSort(enRes: PromptEntityResult, enRes2: PromptEntityResult, enType: number, enMap: PromptEntityResult[][])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let interPts = enRes.Entity.IntersectWith(enRes2.Entity, IntersectOption.ExtendBoth);
|
|
|
|
|
|
|
|
if (interPts.length > 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let baseP: Vector3;
|
|
|
|
|
|
|
|
if (enType & 1) //如果有直线,那么用直线
|
|
|
|
|
|
|
|
baseP = enMap[0][0].Point;
|
|
|
|
|
|
|
|
else if (enType === 2) //如果都是圆弧,那么取中点
|
|
|
|
|
|
|
|
baseP = midPoint(enMap[1][0].Point, enMap[1][1].Point);
|
|
|
|
|
|
|
|
interPts.sort((p1, p2) => p1.distanceToSquared(baseP) - p2.distanceToSquared(baseP));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return interPts;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 对图元列表进行按位编码,类型映射如下:
|
|
|
|
|
|
|
|
* # 1:line 2:arc 4:polyline
|
|
|
|
|
|
|
|
* @param enRes
|
|
|
|
|
|
|
|
* @param enRes2
|
|
|
|
|
|
|
|
* @returns
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private EnCode(enRes: PromptEntityResult, enRes2: PromptEntityResult)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let enMap: (PromptEntityResult[])[] = [[], [], []];
|
|
|
|
|
|
|
|
let enType = 0;
|
|
|
|
|
|
|
|
enType |= Encode(enRes, enMap);
|
|
|
|
|
|
|
|
enType |= Encode(enRes2, enMap);
|
|
|
|
|
|
|
|
return { enType, enMap };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//计算曲线在相交处的切线,取真实的切线
|
|
|
|
|
|
|
|
private ComputerDerv(cuRes: CurveExtend, dervSum: Vector3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let derv: Vector3;
|
|
|
|
|
|
|
|
let cu = cuRes.Curve;
|
|
|
|
|
|
|
|
if (cuRes.ExtType === ExtendType.Start)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
derv = cu.GetFistDeriv(0).normalize();
|
|
|
|
|
|
|
|
dervSum.add(derv);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
derv = cu.GetFistDeriv(cu.EndParam).normalize();
|
|
|
|
|
|
|
|
dervSum.add(derv.clone().negate());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return derv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算曲线在相交处的切线,取起点到终点的切线.(当曲线相切时调用此方法.)
|
|
|
|
|
|
|
|
private ComputerDerv2(cuRes: CurveExtend, dervSum: Vector3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let cu = cuRes.Curve;
|
|
|
|
|
|
|
|
let derv = cu.EndPoint.sub(cu.StartPoint);
|
|
|
|
|
|
|
|
if (cuRes.ExtType === ExtendType.Start)
|
|
|
|
|
|
|
|
dervSum.add(derv);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
dervSum.add(derv.clone().negate());
|
|
|
|
|
|
|
|
return derv;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 延伸或者裁剪到指定的圆弧的点.
|
|
|
|
|
|
|
|
ExtendPt(cu: CurveExtend, newP: Vector3)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (cu.ExtType === ExtendType.Start)
|
|
|
|
|
|
|
|
cu.Curve.StartPoint = newP;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
cu.Curve.EndPoint = newP;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 切割或者延伸曲线,尖角化
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param cu 处理的曲线
|
|
|
|
|
|
|
|
* @param interPt 原先的相交点
|
|
|
|
|
|
|
|
* @param pickPoint 鼠标点击点
|
|
|
|
|
|
|
|
* @returns 返回新的曲线
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
SplitCurve(enRes: PromptEntityResult, interPt: Vector3, interPts: Vector3[]): CurveExtend
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let cu = enRes.Entity as Curve;
|
|
|
|
|
|
|
|
let pickPoint = enRes.Point;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cp = cu.GetClosestPointTo(pickPoint, false);
|
|
|
|
|
|
|
|
let cus = cu.GetSplitCurvesByPts([interPt]);
|
|
|
|
|
|
|
|
if (cus.length === 0)
|
|
|
|
|
|
|
|
cus.push(cu.Clone() as Curve);
|
|
|
|
|
|
|
|
else if (cus.length === 2)
|
|
|
|
|
|
|
|
cus.sort((c1: Curve, c2: Curve) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return c1.GetClosestPointTo(cp, false).distanceTo(cp)
|
|
|
|
|
|
|
|
< c2.GetClosestPointTo(cp, false).distanceTo(cp) ? -1 : 1;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let exType = undefined;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let newCu = cus[0];
|
|
|
|
|
|
|
|
if (newCu instanceof Line)
|
|
|
|
|
|
|
|
newCu.Extend(newCu.GetParamAtPoint(interPt));//延伸到需要的长度
|
|
|
|
|
|
|
|
else if (newCu instanceof Arc)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let arc = newCu as Arc;
|
|
|
|
|
|
|
|
if (cus.length === 1)
|
|
|
|
|
|
|
|
if (!cu.PtOnCurve(interPt))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (cu.PtOnCurve(interPts[1]))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//交点参数
|
|
|
|
|
|
|
|
let iparam = arc.GetParamAtPoint(interPts[1]);
|
|
|
|
|
|
|
|
let pickParam = arc.GetParamAtAngle(arc.GetAngleAtPoint(pickPoint));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pickParam > iparam)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
arc.EndAngle = arc.GetAngleAtPoint(interPt);
|
|
|
|
|
|
|
|
exType = ExtendType.End;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
arc.StartAngle = arc.GetAngleAtPoint(interPt);
|
|
|
|
|
|
|
|
exType = ExtendType.Start;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//终点,起点
|
|
|
|
|
|
|
|
interPts = interPts.sort((p1, p2) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return arc.ComputeAnlge(arc.GetAngleAtPoint(p1)) - arc.ComputeAnlge(arc.GetAngleAtPoint(p2));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (interPt === interPts[0])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
arc.EndAngle = arc.GetAngleAtPoint(interPt);
|
|
|
|
|
|
|
|
exType = ExtendType.End;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
arc.StartAngle = arc.GetAngleAtPoint(interPt);
|
|
|
|
|
|
|
|
exType = ExtendType.Start;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (exType === undefined)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//使用equalv3时由于精度误差导致的判断错误
|
|
|
|
|
|
|
|
if (interPt.manhattanDistanceTo(newCu.StartPoint) < interPt.manhattanDistanceTo(newCu.EndPoint))
|
|
|
|
|
|
|
|
exType = ExtendType.Start;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
exType = ExtendType.End;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return { Curve: newCu, ExtType: exType };
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async SelectCurve(keyword: KeyWord[]): Promise<PromptEntityResult>
|
|
|
|
async SelectCurve(keyword: KeyWord[]): Promise<PromptEntityResult>
|
|
|
@ -1010,7 +208,7 @@ export class CommandFillet implements Command
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let fres = this.FilletPolyLineAllAngular(e);
|
|
|
|
let fres = this.m_FilletUtils.FilletPolyLineAllAngular(e);
|
|
|
|
if (fres && fres.cu1)
|
|
|
|
if (fres && fres.cu1)
|
|
|
|
JigUtils.Draw(fres.cu1);
|
|
|
|
JigUtils.Draw(fres.cu1);
|
|
|
|
|
|
|
|
|
|
|
@ -1041,7 +239,7 @@ export class CommandFillet implements Command
|
|
|
|
lastPl.RestoreJigMaterial();
|
|
|
|
lastPl.RestoreJigMaterial();
|
|
|
|
if (enRes.Status === PromptStatus.OK)
|
|
|
|
if (enRes.Status === PromptStatus.OK)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let fres = this.FilletPolyLineAllAngular(enRes);
|
|
|
|
let fres = this.m_FilletUtils.FilletPolyLineAllAngular(enRes);
|
|
|
|
if (fres && fres.cu1)
|
|
|
|
if (fres && fres.cu1)
|
|
|
|
enRes.Entity.CopyFrom(fres.cu1);
|
|
|
|
enRes.Entity.CopyFrom(fres.cu1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|