|
|
@ -1,5 +1,5 @@
|
|
|
|
import { Vector3 } from "three";
|
|
|
|
import { Vector3 } from "three";
|
|
|
|
import { arrayLast, arrayRemove, arrayRemoveIf } from "../Common/ArrayExt";
|
|
|
|
import { arrayLast, arrayRemoveIf, arrayRemoveOnce } from "../Common/ArrayExt";
|
|
|
|
import { Arc } from "../DatabaseServices/Entity/Arc";
|
|
|
|
import { Arc } from "../DatabaseServices/Entity/Arc";
|
|
|
|
import { Curve } from "../DatabaseServices/Entity/Curve";
|
|
|
|
import { Curve } from "../DatabaseServices/Entity/Curve";
|
|
|
|
import { Polyline } from "../DatabaseServices/Entity/Polyline";
|
|
|
|
import { Polyline } from "../DatabaseServices/Entity/Polyline";
|
|
|
@ -10,7 +10,13 @@ import { angle } from "./GeUtils";
|
|
|
|
//区域的路线表 表示了一个区域
|
|
|
|
//区域的路线表 表示了一个区域
|
|
|
|
type RegionRouteS = Route[][];
|
|
|
|
type RegionRouteS = Route[][];
|
|
|
|
|
|
|
|
|
|
|
|
//区域搜索算法
|
|
|
|
/**
|
|
|
|
|
|
|
|
面域分析,基于最小循环图重新实现的版本,拓展了实现求最大轮廓。
|
|
|
|
|
|
|
|
当最大轮廓=最小轮廓时,只绘制最大轮廓(独立轮廓无分裂)。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
算法只实现去重模式,业务场景应该没有非去重模式。
|
|
|
|
|
|
|
|
如果需要非去重模式,那么应该获取到多个CurveMap,然后对多个CurveMap进行面域分析,得出多个重叠的面域。
|
|
|
|
|
|
|
|
*/
|
|
|
|
export class RegionParse
|
|
|
|
export class RegionParse
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//区域列表 通常是外轮廓
|
|
|
|
//区域列表 通常是外轮廓
|
|
|
@ -24,18 +30,20 @@ export class RegionParse
|
|
|
|
private _CurveCount: number;
|
|
|
|
private _CurveCount: number;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @param {Curve[]} cuList 请不要传递圆和椭圆.
|
|
|
|
* @param cuList 请不要传递圆和椭圆.
|
|
|
|
|
|
|
|
* @param [numDimensions=3] 精度:小数点后个数
|
|
|
|
|
|
|
|
* @param [removeDuplicate=true] 删除重复(现在必须是true,请不要修改它)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
constructor(cuList: Curve[], public numDimensions = 3, private removeDuplicate = true)
|
|
|
|
constructor(cuList: Curve[], public numDimensions = 3, private removeDuplicate = true)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//需要搜索的站
|
|
|
|
//需要搜索的站
|
|
|
|
let vertices = this.GenerateNodeMap(cuList);
|
|
|
|
let vertices = this.GenerateVerticeMap(cuList);
|
|
|
|
|
|
|
|
|
|
|
|
//移除细丝
|
|
|
|
//移除细丝
|
|
|
|
while (true)
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let v = vertices.find(v => v.routes.length < 2);
|
|
|
|
let v = vertices.find(v => v.routes.length < 2);
|
|
|
|
if (v) vertices = this.RemoveFilamentAt(v, vertices);
|
|
|
|
if (v) this.RemoveFilamentAt(v, vertices);
|
|
|
|
else break;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let lowerVertice: Vertice;
|
|
|
|
let lowerVertice: Vertice;
|
|
|
@ -46,8 +54,8 @@ export class RegionParse
|
|
|
|
let maxWalk = ClosedWalkFrom(lowerVertice, this._CurveCount, WalkType.Max);
|
|
|
|
let maxWalk = ClosedWalkFrom(lowerVertice, this._CurveCount, WalkType.Max);
|
|
|
|
|
|
|
|
|
|
|
|
this.RemoveEdge(minWalk[0]);
|
|
|
|
this.RemoveEdge(minWalk[0]);
|
|
|
|
vertices = this.RemoveFilamentAt(minWalk[0].from, vertices);
|
|
|
|
this.RemoveFilamentAt(minWalk[0].from, vertices);
|
|
|
|
vertices = this.RemoveFilamentAt(minWalk[0].to, vertices);
|
|
|
|
this.RemoveFilamentAt(minWalk[0].to, vertices);
|
|
|
|
|
|
|
|
|
|
|
|
minWalk = ReduceWalk(minWalk);
|
|
|
|
minWalk = ReduceWalk(minWalk);
|
|
|
|
maxWalk = ReduceWalk(maxWalk);
|
|
|
|
maxWalk = ReduceWalk(maxWalk);
|
|
|
@ -92,7 +100,7 @@ export class RegionParse
|
|
|
|
let current = v;
|
|
|
|
let current = v;
|
|
|
|
while (current && current.routes.length < 2)
|
|
|
|
while (current && current.routes.length < 2)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
vertices = arrayRemove(vertices, current);
|
|
|
|
vertices = arrayRemoveOnce(vertices, current);
|
|
|
|
let r = current.routes[0];
|
|
|
|
let r = current.routes[0];
|
|
|
|
if (r)
|
|
|
|
if (r)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -102,7 +110,6 @@ export class RegionParse
|
|
|
|
else
|
|
|
|
else
|
|
|
|
current = undefined;
|
|
|
|
current = undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vertices;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RemoveEdge(r: Route)
|
|
|
|
RemoveEdge(r: Route)
|
|
|
@ -134,7 +141,7 @@ export class RegionParse
|
|
|
|
* 构造路线图. 每个节点对应下一个路口的路线表. 路口表使用逆时针排序,起始角度使用正x轴.
|
|
|
|
* 构造路线图. 每个节点对应下一个路口的路线表. 路口表使用逆时针排序,起始角度使用正x轴.
|
|
|
|
* @returns 所有的顶点
|
|
|
|
* @returns 所有的顶点
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
private GenerateNodeMap(curveList: Curve[]): Array<Vertice>
|
|
|
|
private GenerateVerticeMap(curveList: Curve[]): Array<Vertice>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let curveMap = new CurveMap(this.numDimensions, true);
|
|
|
|
let curveMap = new CurveMap(this.numDimensions, true);
|
|
|
|
|
|
|
|
|
|
|
@ -194,19 +201,15 @@ export class RegionParse
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//排序,根据角度逆时针排序.
|
|
|
|
//排序,根据角度逆时针排序.
|
|
|
|
curveMap._NodeMap.forEach(s =>
|
|
|
|
for (let v of curveMap._Vertices)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let minLength = Infinity;
|
|
|
|
let minLength = Infinity;
|
|
|
|
for (let r of s.routes)
|
|
|
|
for (let r of v.routes)
|
|
|
|
{
|
|
|
|
if (r.length < minLength) minLength = r.length;
|
|
|
|
if (r.length < minLength)
|
|
|
|
for (let r of v.routes)
|
|
|
|
minLength = r.length;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let r of s.routes)
|
|
|
|
|
|
|
|
CalcRouteAngle(r, minLength * 0.2);
|
|
|
|
CalcRouteAngle(r, minLength * 0.2);
|
|
|
|
s.routes.sort((r1, r2) => r1.an - r2.an);
|
|
|
|
v.routes.sort((r1, r2) => r1.an - r2.an);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return curveMap.Stands;
|
|
|
|
return curveMap.Stands;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -222,8 +225,6 @@ export class RegionParse
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* 曲线是否已经被算法使用
|
|
|
|
* 曲线是否已经被算法使用
|
|
|
|
* @param cu
|
|
|
|
|
|
|
|
* @returns true if cueve used
|
|
|
|
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
GetCueveUsed(cu: Curve): boolean
|
|
|
|
GetCueveUsed(cu: Curve): boolean
|
|
|
|
{
|
|
|
|
{
|
|
|
|