mirror of https://gitee.com/cf-fz/WebCAD.git
parent
5704c58c7e
commit
93f404be57
@ -0,0 +1,194 @@
|
||||
import { Vector3 } from 'three';
|
||||
|
||||
import { app } from '../ApplicationServices/Application';
|
||||
import { Arc } from '../DatabaseServices/Arc';
|
||||
import { Curve } from '../DatabaseServices/Curve';
|
||||
import { Line } from '../DatabaseServices/Line';
|
||||
import { Command } from '../Editor/CommandMachine';
|
||||
import { PromptEntityResult, PromptStatus } from '../Editor/PromptResult';
|
||||
import { angle, midPoint } from '../Geometry/GeUtils';
|
||||
import { Intersect } from '../GraphicsSystem/IntersectWith';
|
||||
|
||||
enum FilletState { Invalid = -1, Normal, Parallel, RadiousInvalid }
|
||||
export class CommandFillet implements Command
|
||||
{
|
||||
async exec()
|
||||
{
|
||||
//拾取曲线1.
|
||||
let enRes = await this.SelectCurve([
|
||||
{ msg: "放弃", key: "U" },
|
||||
{ msg: "多段线", key: "P" },
|
||||
{ msg: "半径", key: "R" },
|
||||
{ msg: "修剪", key: "T" },
|
||||
{ msg: "多个", key: "M" }]);
|
||||
if (!enRes) return;
|
||||
let cu1 = enRes.Entity as Curve;
|
||||
|
||||
//拾取曲线2
|
||||
let enRes2 = await this.SelectCurve([{ msg: "放弃", key: "U" }, { msg: "半径", key: "R" }], cu1);
|
||||
if (!enRes2) return;
|
||||
|
||||
let cu2 = enRes2.Entity as Curve;
|
||||
|
||||
//求交点
|
||||
let in_pts = cu1.IntersectWith(cu2, Intersect.ExtendBoth);
|
||||
if (in_pts.length === 0) return;
|
||||
|
||||
//裁剪. 尖角化
|
||||
let new_cu1 = this.SplitCurve(cu1, in_pts, enRes.Point);
|
||||
let new_cu2 = this.SplitCurve(cu2, in_pts, enRes2.Point);
|
||||
|
||||
//偏移
|
||||
let off_cu1 = this.OffsetCurve(new_cu1, new_cu2, 3);
|
||||
let off_cu2 = this.OffsetCurve(new_cu2, new_cu1, 3);
|
||||
|
||||
//圆心
|
||||
let center = off_cu1.IntersectWith(off_cu2, Intersect.ExtendBoth)[0];
|
||||
//圆弧点1
|
||||
let arcP1 = new_cu1.GetClosestPointTo(center, true);
|
||||
if (!new_cu1.PtOnCurve(arcP1))
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("半径过大");
|
||||
return;
|
||||
}
|
||||
//圆弧点2
|
||||
let arcP2 = new_cu2.GetClosestPointTo(center, true);
|
||||
if (!new_cu2.PtOnCurve(arcP2))
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("半径过大");
|
||||
return;
|
||||
}
|
||||
|
||||
//时针校验
|
||||
let v1 = arcP1.clone().sub(center);
|
||||
let v2 = arcP2.clone().sub(center);
|
||||
let [startAngle, endAngle] = [angle(v1), angle(v2)];
|
||||
if (v1.cross(v2).z > 0)
|
||||
[startAngle, endAngle] = [endAngle, startAngle];
|
||||
|
||||
//绘制圆弧
|
||||
let arc = new Arc(center, 3, startAngle, endAngle);
|
||||
app.m_Database.ModelSpace.Append(arc);
|
||||
|
||||
//延伸或者裁剪到圆弧点
|
||||
this.ExtendPt(new_cu1 as Line, in_pts[0], arcP1);
|
||||
this.ExtendPt(new_cu2 as Line, in_pts[0], arcP2);
|
||||
|
||||
cu1.CopyFrom(new_cu1);
|
||||
cu2.CopyFrom(new_cu2);
|
||||
|
||||
app.m_Editor.UpdateScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* 延伸或者裁剪到指定的圆弧的点.
|
||||
*
|
||||
* @param {Line} cu
|
||||
* @param {Vector3} insP
|
||||
* @param {Vector3} newP
|
||||
* @memberof CommandFillet
|
||||
*/
|
||||
ExtendPt(cu: Line, insP: Vector3, newP: Vector3)
|
||||
{
|
||||
if (cu.StartPoint.distanceToSquared(insP) < 1e-5)
|
||||
cu.StartPoint = newP;
|
||||
else
|
||||
cu.EndPoint = newP;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切割或者延伸曲线,尖角化
|
||||
*
|
||||
* @param {Curve} cu 处理的曲线
|
||||
* @param {Array<Vector3>} pts 原先的相交点
|
||||
* @param {Vector3} pickPoint 鼠标点击点
|
||||
* @returns {Curve} 返回新的曲线
|
||||
* @memberof CommandFillet
|
||||
*/
|
||||
SplitCurve(cu: Curve, pts: Array<Vector3>, pickPoint: Vector3): Curve
|
||||
{
|
||||
let cp = cu.GetClosestPointTo(pickPoint, true);
|
||||
|
||||
let cus = cu.GetSplitCurves(pts.map(p => cu.GetParamAtPoint(p)))
|
||||
if (cus.length === 0)
|
||||
cus.push(cu.Clone() as Curve);
|
||||
else
|
||||
{
|
||||
for (let cu of cus)
|
||||
{
|
||||
if (cu.PtOnCurve(cp))
|
||||
return cu;
|
||||
}
|
||||
|
||||
cus.sort((c1: Curve, c2: Curve) =>
|
||||
{
|
||||
return c1.GetClosestPointTo(cp, false).distanceTo(cp)
|
||||
< c2.GetClosestPointTo(cp, false).distanceTo(cp) ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
let newCu = cus[0];
|
||||
newCu.Extend(newCu.GetParamAtPoint(pts[0]));//延伸到需要的长度
|
||||
return cus[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据指定曲线(toCu)偏移.
|
||||
*
|
||||
* @param {Curve} thisCu
|
||||
* @param {Curve} toCu
|
||||
* @param {number} dis 偏移距离
|
||||
* @returns {Curve}
|
||||
* @memberof CommandFillet
|
||||
*/
|
||||
OffsetCurve(thisCu: Curve, toCu: Curve, dis: number): Curve
|
||||
{
|
||||
let minP = midPoint(toCu.StartPoint, toCu.EndPoint);
|
||||
let cp = thisCu.GetClosestPointTo(minP, true);
|
||||
let vec = minP.sub(cp).normalize().multiplyScalar(dis);
|
||||
|
||||
let newCu = thisCu.Clone() as Line;
|
||||
newCu.StartPoint = thisCu.StartPoint.add(vec);
|
||||
newCu.EndPoint = thisCu.EndPoint.add(vec);
|
||||
|
||||
return newCu;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 指定用户选择曲线
|
||||
*
|
||||
* @param {any} keyword 关键字
|
||||
* @param {Curve} [oldCurve] 第一次选择的曲线
|
||||
* @returns {Promise<PromptEntityResult>}
|
||||
* @memberof CommandFillet
|
||||
*/
|
||||
async SelectCurve(keyword, oldCurve?: Curve): Promise<PromptEntityResult>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
let enRes = await app.m_Editor.GetEntity({
|
||||
Msg: oldCurve ? "选择第二个对象:" : "选择第一个对象:",
|
||||
KeyWordList: keyword,
|
||||
});
|
||||
switch (enRes.Status)
|
||||
{
|
||||
case PromptStatus.OK:
|
||||
if (enRes.Entity === oldCurve)
|
||||
{
|
||||
app.m_Editor.m_CommandStore.Prompt("重复的对象!");
|
||||
}
|
||||
else if (enRes.Entity && enRes.Entity instanceof Curve)
|
||||
{
|
||||
return enRes;
|
||||
}
|
||||
break;
|
||||
case PromptStatus.Cancel:
|
||||
return undefined;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue