动态连接曲线数组

pull/68/head
Zoe 6 years ago
parent d840c35af4
commit d120d83062

@ -143,3 +143,11 @@ Vector3 {
"z": 0, "z": 0,
} }
`; `;
exports[`最近点2 1`] = `
Vector3 {
"x": 10,
"y": 0,
"z": 0,
}
`;

@ -3,29 +3,29 @@ import { Curve } from "../DatabaseServices/Curve";
import { CurveIntersection } from "../Geometry/CurveIntersection"; import { CurveIntersection } from "../Geometry/CurveIntersection";
import { CurveMap } from "../Geometry/CurveMap"; import { CurveMap } from "../Geometry/CurveMap";
import { equal } from "../Geometry/GeUtils"; import { equal } from "../Geometry/GeUtils";
import { Route, Stand } from "../Geometry/RegionParse"; import { Stand } from "../Geometry/RegionParse";
export class LinkSelf export class LinkSelf
{ {
private curveUseData: WeakMap<Curve, boolean> = new WeakMap(); private curveUseData: WeakMap<Curve, boolean> = new WeakMap();
private curveIndexData: WeakMap<Curve, number> = new WeakMap(); private curveIndexData: WeakMap<Curve, number> = new WeakMap();
sealCus: Set<Curve>[] = [];
noSealCus: Curve[][] = [];
private cuMap: CurveMap;
constructor(cus: Curve[]) constructor(cus: Curve[])
{ {
//打断曲线 //打断曲线
let breakCus: Curve[] = this.BreakCurve(cus); let breakCus: Curve[] = this.BreakCurve(cus);
//曲线图 用来快速搜索求交 //曲线图 用来快速搜索求交
let cuMap = this.GenerateCurveMap(breakCus); this.cuMap = this.GenerateCurveMap(breakCus);
//自交曲线表 //自交曲线表
let selfRoutes = this.CalCloseCurve(breakCus, cuMap); this.CalCloseCurve(breakCus, this.cuMap);
console.log('自交列表: ', selfRoutes);
//非自交曲线连接表 //非自交曲线连接表
let css = this.CalOrderLink(breakCus, cuMap); this.CalOrderLink(breakCus, this.cuMap);
console.log("没有自交的列表:", css);
} }
@ -109,58 +109,56 @@ export class LinkSelf
{ {
this.SetCurveUse(c); this.SetCurveUse(c);
} }
selfRoutes.push(routeCus); this.sealCus.push(routeCus);
} }
} }
} }
return selfRoutes;
} }
//顺序连接. //顺序连接.
private CalOrderLink(breakCus: Curve[], cuMap: CurveMap) private CalOrderLink(breakCus: Curve[], cuMap: CurveMap)
{ {
//没有自交的线段表 二维数组
let css = [];
let breakCount = breakCus.length; let breakCount = breakCus.length;
//剩下没有被自交 //剩下没有被自交
for (let i = 0; i < breakCount; i++) for (let i = 0; i < breakCount; i++)
{ {
let cu = breakCus[i]; let cu = breakCus[i];
if (this.GetCurveUse(cu)) continue; if (this.GetCurveUse(cu)) continue;
let cuIndex = this.GetCurveIndex(cu); // let cuIndex = this.GetCurveIndex(cu);
this.SetCurveUse(cu); this.SetCurveUse(cu);
let cs = [cu]; let cs = [cu];
//顺序连接
this.linkCurve(cu, cuMap, cs);
//拿出第一条进行倒序连接
cu = cs[0];
this.linkCurve(cu, cuMap, cs, true);
}
}
linkCurve(originCu: Curve, cuMap: CurveMap, cs: Curve[], isInv: boolean = false)
{
let cuIndex = this.GetCurveIndex(originCu);
while (true) while (true)
{ {
let oldCount = cs.length; let oldCount = cs.length;
let routes = cuMap.GetStand(cu.EndPoint).routes; let routes = cuMap.GetStand(isInv ? originCu.StartPoint : originCu.EndPoint).routes;
for (let j = routes.length; j--;) //按照索引从小到大搜索 for (let j = routes.length; j--;) //按照索引从小到大搜索
{ {
let cu2 = routes[j].curve; let cu2 = routes[j].curve;
let cu2Index = this.GetCurveIndex(cu2); let cu2Index = this.GetCurveIndex(cu2);
if (this.GetCurveUse(cu2)) continue; if (this.GetCurveUse(cu2)) continue;
if (cuIndex === cu2Index) continue; if (cuIndex === cu2Index)
if (cu2Index < cuIndex)
{
if (cs.findIndex((c) =>
{ {
return this.GetCurveIndex(c) === cu2Index; continue;//如果和自身的线连接,则需要判断这条路线是否合理
}) === -1)
{
continue;
}
} }
//能够连接 //能够连接
if (equal(cu2.StartPoint, cu.EndPoint)) let isLink = isInv ? equal(cu2.EndPoint, originCu.StartPoint) : equal(cu2.StartPoint, originCu.EndPoint);
if (isLink)
{ {
this.SetCurveUse(cu2); this.SetCurveUse(cu2);
cs.push(cu2); isInv ? cs.unshift(cu2) : cs.push(cu2);
cu = cu2; originCu = cu2;
cuIndex = this.GetCurveIndex(cu2); cuIndex = this.GetCurveIndex(cu2);
break; break;
} }
@ -169,22 +167,52 @@ export class LinkSelf
//如果没找到 则退出循环 //如果没找到 则退出循环
if (oldCount === cs.length) if (oldCount === cs.length)
{ {
css.push(cs); this.noSealCus.push(cs);
break; break;
} }
} }
} }
//寻找最小索引的路线
private FindMinRoute(nowStand: Stand, nowIndex: number, cs: Curve[], routes: Curve[]): { minIndex: number, routes: Curve[] }
{
//和当前索引一样的 搜索结果
let curIndex: { minIndex: number, routes: Curve[] } = undefined;
for (let j = nowStand.routes.length; j--;) //按照索引从小到大搜索
{
let cu = nowStand.routes[j].curve;
let cuIndex = this.GetCurveIndex(cu);
if (this.GetCurveUse(cu)) continue;
if (!equal(cu.StartPoint, nowStand.position)) continue;
if (nowIndex === cuIndex)
{
let routes2 = routes.concat();//复制数组保证函数有唯一结果
routes2.push(cu);
curIndex = this.FindMinRoute(this.cuMap.GetStand(cu.EndPoint), nowIndex, cs, routes2);
continue;
}
if (cuIndex < nowIndex) //小于 回归自身
if (cs.findIndex((c) => this.GetCurveIndex(c) === cuIndex) === -1)
continue;
if (curIndex && curIndex.minIndex < cuIndex)
return curIndex;
//这里不复制数组,因为数组不会再被改变
routes.push(cu);
return { minIndex: cuIndex, routes };
}
return css; return { minIndex: Infinity, routes };
} }
GetCurveUse(curve: Curve): boolean GetCurveUse(curve: Curve): boolean
{ {
return this.curveUseData.get(curve); return this.curveUseData.get(curve);
} }
SetCurveUse(curve: Curve) SetCurveUse(curve: Curve, use: boolean = true)
{ {
this.curveUseData.set(curve, true); this.curveUseData.set(curve, use);
} }
GetCurveIndex(curve: Curve): number GetCurveIndex(curve: Curve): number
{ {

@ -1,6 +1,6 @@
import { Vector3 } from "three"; import { Vector3 } from "three";
import { arrayLast } from "../Common/ArrayExt"; import { arrayLast } from "../Common/ArrayExt";
import { Vec3DTo2D, curveLinkGroup, getCirAngleByChordAndTangent, Vec2DTo3D } from "../Common/CurveUtils"; import { Vec2DTo3D, Vec3DTo2D, curveLinkGroup, getCirAngleByChordAndTangent } from "../Common/CurveUtils";
import { FixIndex } from "../Common/Utils"; import { FixIndex } from "../Common/Utils";
import { Arc } from "../DatabaseServices/Arc"; import { Arc } from "../DatabaseServices/Arc";
import { Circle } from "../DatabaseServices/Circle"; import { Circle } from "../DatabaseServices/Circle";
@ -8,10 +8,10 @@ import { Contour } from "../DatabaseServices/Contour";
import { Curve } from "../DatabaseServices/Curve"; import { Curve } from "../DatabaseServices/Curve";
import { Line } from "../DatabaseServices/Line"; import { Line } from "../DatabaseServices/Line";
import { Polyline } from '../DatabaseServices/Polyline'; import { Polyline } from '../DatabaseServices/Polyline';
import { equal, equaln, midPoint } from "../Geometry/GeUtils"; import { equal, equaln } from "../Geometry/GeUtils";
import { isTargetCurInSourceCur, isTargetCurOutOrOnSourceCur } from "./BoolOperateUtils"; import { isTargetCurInSourceCur, isTargetCurOutOrOnSourceCur } from "./BoolOperateUtils";
import { IntersectOption } from "./IntersectWith"; import { IntersectOption } from "./IntersectWith";
import { app } from "../ApplicationServices/Application"; import { LinkSelf } from "./LinkSelft";
interface offestRes interface offestRes
{ {
index: number, index: number,
@ -22,13 +22,13 @@ export class PolyOffestUtil
{ {
private m_Polyline: Polyline; private m_Polyline: Polyline;
private m_OffestDist: number; private m_OffestDist: number;
private m_OffDir: number; // private m_OffDir: number;
private IsKeepAllCurves = false; //为true时 保留全部,不优化裁剪 private IsKeepAllCurves = false; //为true时 保留全部,不优化裁剪
constructor(pl: Polyline, offest: number) constructor(pl: Polyline, offest: number)
{ {
this.m_Polyline = pl; this.m_Polyline = pl;
this.m_OffestDist = offest; this.m_OffestDist = offest;
this.m_OffDir = Math.sign(this.m_OffestDist) * Math.sign(this.m_Polyline.Area2); // this.m_OffDir = Math.sign(this.m_OffestDist) * Math.sign(this.m_Polyline.Area2);
} }
//偏移 //偏移
GetOffsetCurves(): Curve[] GetOffsetCurves(): Curve[]
@ -61,42 +61,86 @@ export class PolyOffestUtil
let newPls = this.trimAndJointOffestPolyline(offres1, this.m_Polyline); let newPls = this.trimAndJointOffestPolyline(offres1, this.m_Polyline);
let cus = this.trimByContours(newPls, contours); let cus = this.trimByContours(newPls, contours);
let rets = this.linkSelfingCurves(cus); let rets = this.linkSelfingCurves2(cus);
if (!this.IsKeepAllCurves) if (!this.IsKeepAllCurves)
{ {
// 先尝试把线段相连成封闭区域 // rets = this.optimizeCus(rets);
rets = rets.map(cu => this.closePolyline(cu)).filter((l, i) => }
return rets;
}
/**
* 线
* 线,线
* @param {Polyline[]} rets
* @returns
* @memberof PolyOffestUtil
*/
optimizeCus(rets: Polyline[])
{ {
if (i === 0) return true; if (rets.length <= 1) return rets;
else
if (this.m_Polyline.IsClose)
{ {
return l.IsClose || l.IntersectWith(rets[0], IntersectOption.OnBothOperands).length === 0; return rets.filter(l => l.IsClose)
} }
});
if (this.m_Polyline.IsClose)
rets = rets.filter(l => l.IsClose);
else else
rets = rets.sort((l1, l2) => l2.Length - l1.Length)
.filter((l, i) =>
{ {
if (i == 0) return true; let baseline = rets[0];
else
if (!baseline.IsClose)
{
let longestCu = baseline;
for (let i = 1; i < rets.length; i++)
{ {
if (l.IsClose) if (rets[i].Length > longestCu.Length)
{ {
let pts = l.PtsBuls.pts; longestCu = rets[i];
}
}
if (baseline !== longestCu)
{
let isVail = this.compareCus(longestCu, baseline);
if (!isVail)
{
rets.shift();
baseline = rets[0];
}
}
}
rets = rets.filter((l, i) =>
{
if (i === 0) return true;
else return (l.IsClose || l.IntersectWith(baseline, IntersectOption.OnBothOperands).length === 0) && this.compareCus(baseline, l);
})
for (let i = 1; i < rets.length - 1; i++)
{
let isvail1 = this.compareCus(rets[i], rets[i + 1]);
let isvail2 = this.compareCus(rets[i + 1], rets[i]);
if (!isvail1)
{
rets.splice(i + 1, 1);
i--;
}
else if (!isvail2 && !rets[i].IsClose)
{
rets.splice(i, 1);
i--;
}
}
}
return rets;
}
compareCus(srcLine: Polyline, tarLine: Polyline)
{
let pts = tarLine.PtsBuls.pts;
return pts.some(p => return pts.some(p =>
{ {
let p1 = Vec2DTo3D(p); let p1 = Vec2DTo3D(p);
let closePt = rets[0].GetClosestPointTo(p1, false); let closePt = srcLine.GetClosestPointTo(p1, false);
let dist = closePt.distanceToSquared(p1); let dist = closePt.distanceToSquared(p1);
return dist > Math.pow(this.m_OffestDist, 2); return dist > Math.pow(this.m_OffestDist, 2);
}) })
} else return false;
}
});
}
return rets;
} }
//偏移曲线 //偏移曲线
private offestCurve(pls: Curve[], dis: number): offestRes[] private offestCurve(pls: Curve[], dis: number): offestRes[]
@ -417,6 +461,7 @@ export class PolyOffestUtil
*/ */
private isSelfingCus(cus: Curve[]): boolean private isSelfingCus(cus: Curve[]): boolean
{ {
if (cus.length <= 1) return false;
for (let i = 0; i < cus.length; i++) for (let i = 0; i < cus.length; i++)
{ {
let frontLine = cus[i]; let frontLine = cus[i];
@ -493,6 +538,7 @@ export class PolyOffestUtil
}); });
if (pts.length) if (pts.length)
{ {
//TODO:判断0~j之间的曲线是否自交,不自觉直接按顺序连接起来
let parForFront = frontLine.GetParamAtPoint(pts[0]); let parForFront = frontLine.GetParamAtPoint(pts[0]);
let parForLater = laterLine.GetParamAtPoint(pts[0]); let parForLater = laterLine.GetParamAtPoint(pts[0]);
@ -544,6 +590,41 @@ export class PolyOffestUtil
retPls.push(...this.linkCurves(cus)); retPls.push(...this.linkCurves(cus));
return retPls; return retPls;
} }
//
linkSelfingCurves2(cus: Curve[]): Polyline[]
{
let retPls: Polyline[] = [];
let retsCus = new LinkSelf(cus);
retsCus.noSealCus.forEach(cs =>
{
let pl = new Polyline();
cs.forEach(c =>
{
pl.Join(c)
})
retPls.push(pl);
})
// let seals: Polyline[] = [];
retsCus.sealCus.forEach(s =>
{
let pl = new Polyline();
s.forEach(c =>
{
pl.Join(c)
})
retPls.push(pl);
})
// retPls = retPls.filter((l, i) =>
// {
// if (i === 0) return true;
// return seals.every(l1 => l1.IntersectWith(l, IntersectOption.OnBothOperands).length === 0)
// })
// retPls.push(...seals);
return retPls;
}
closePolyline(pl: Polyline) closePolyline(pl: Polyline)
{ {
//闭合或者只有一条线段或者2条线段都是直线的,直接返回 //闭合或者只有一条线段或者2条线段都是直线的,直接返回

Loading…
Cancel
Save