动态连接曲线数组

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

@ -143,3 +143,11 @@ Vector3 {
"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 { CurveMap } from "../Geometry/CurveMap";
import { equal } from "../Geometry/GeUtils";
import { Route, Stand } from "../Geometry/RegionParse";
import { Stand } from "../Geometry/RegionParse";
export class LinkSelf
{
private curveUseData: WeakMap<Curve, boolean> = new WeakMap();
private curveIndexData: WeakMap<Curve, number> = new WeakMap();
sealCus: Set<Curve>[] = [];
noSealCus: Curve[][] = [];
private cuMap: CurveMap;
constructor(cus: Curve[])
{
//打断曲线
let breakCus: Curve[] = this.BreakCurve(cus);
//曲线图 用来快速搜索求交
let cuMap = this.GenerateCurveMap(breakCus);
this.cuMap = this.GenerateCurveMap(breakCus);
//自交曲线表
let selfRoutes = this.CalCloseCurve(breakCus, cuMap);
console.log('自交列表: ', selfRoutes);
this.CalCloseCurve(breakCus, this.cuMap);
//非自交曲线连接表
let css = this.CalOrderLink(breakCus, cuMap);
console.log("没有自交的列表:", css);
this.CalOrderLink(breakCus, this.cuMap);
}
@ -109,82 +109,110 @@ export class LinkSelf
{
this.SetCurveUse(c);
}
selfRoutes.push(routeCus);
this.sealCus.push(routeCus);
}
}
}
return selfRoutes;
}
//顺序连接.
private CalOrderLink(breakCus: Curve[], cuMap: CurveMap)
{
//没有自交的线段表 二维数组
let css = [];
let breakCount = breakCus.length;
//剩下没有被自交
for (let i = 0; i < breakCount; i++)
{
let cu = breakCus[i];
if (this.GetCurveUse(cu)) continue;
let cuIndex = this.GetCurveIndex(cu);
// let cuIndex = this.GetCurveIndex(cu);
this.SetCurveUse(cu);
let cs = [cu];
while (true)
//顺序连接
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)
{
let oldCount = cs.length;
let routes = cuMap.GetStand(isInv ? originCu.StartPoint : originCu.EndPoint).routes;
for (let j = routes.length; j--;) //按照索引从小到大搜索
{
let oldCount = cs.length;
let routes = cuMap.GetStand(cu.EndPoint).routes;
for (let j = routes.length; j--;) //按照索引从小到大搜索
let cu2 = routes[j].curve;
let cu2Index = this.GetCurveIndex(cu2);
if (this.GetCurveUse(cu2)) continue;
if (cuIndex === cu2Index)
{
let cu2 = routes[j].curve;
let cu2Index = this.GetCurveIndex(cu2);
if (this.GetCurveUse(cu2)) continue;
if (cuIndex === cu2Index) continue;
if (cu2Index < cuIndex)
{
if (cs.findIndex((c) =>
{
return this.GetCurveIndex(c) === cu2Index;
}) === -1)
{
continue;
}
}
//能够连接
if (equal(cu2.StartPoint, cu.EndPoint))
{
this.SetCurveUse(cu2);
cs.push(cu2);
cu = cu2;
cuIndex = this.GetCurveIndex(cu2);
break;
}
continue;//如果和自身的线连接,则需要判断这条路线是否合理
}
//如果没找到 则退出循环
if (oldCount === cs.length)
//能够连接
let isLink = isInv ? equal(cu2.EndPoint, originCu.StartPoint) : equal(cu2.StartPoint, originCu.EndPoint);
if (isLink)
{
css.push(cs);
this.SetCurveUse(cu2);
isInv ? cs.unshift(cu2) : cs.push(cu2);
originCu = cu2;
cuIndex = this.GetCurveIndex(cu2);
break;
}
}
//如果没找到 则退出循环
if (oldCount === cs.length)
{
this.noSealCus.push(cs);
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
{
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
{

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

Loading…
Cancel
Save