From 755eb2ee0aead01bb7ac0de3699acbec370c577c Mon Sep 17 00:00:00 2001 From: ChenX Date: Wed, 8 Apr 2020 15:42:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/CurveUtils.ts | 2 +- src/Geometry/CurveMap.ts | 36 +++++++++++++------------- src/Geometry/RegionParse.ts | 45 +++++++++++++++++---------------- src/GraphicsSystem/LinkSelft.ts | 12 ++++----- 4 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/Common/CurveUtils.ts b/src/Common/CurveUtils.ts index 85cd80805..3b5e4b191 100644 --- a/src/Common/CurveUtils.ts +++ b/src/Common/CurveUtils.ts @@ -155,7 +155,7 @@ export function curveLinkGroup(cus: Curve[]): Array> if (cus.length > 0) { - startStand = cuMap.GetStand(cus[0].StartPoint); + startStand = cuMap.GetOnlyVertice(cus[0].StartPoint); while (startStand) startStand = linkCurve(startStand, cus, false); } diff --git a/src/Geometry/CurveMap.ts b/src/Geometry/CurveMap.ts index 7fd697444..daf52225c 100644 --- a/src/Geometry/CurveMap.ts +++ b/src/Geometry/CurveMap.ts @@ -27,7 +27,8 @@ export interface Route } /** - * 曲线地图,使用站点连接. + * 曲线连接图 + * 所有的顶点和边的关系 */ export class CurveMap { @@ -42,24 +43,24 @@ export class CurveMap 每个节点对应下一个路口的路线表. 路口表使用逆时针排序,起始角度使用正x轴. */ - _NodeMap = new Map(); + _VerticeMap = new Map(); + + _Vertices: Vertice[] = []; /** * 得到节点图的所有站点列表 */ get Stands(): Vertice[] { - let stands: Vertice[] = []; - this._NodeMap.forEach(s => stands.push(s)); - return stands; + return this._Vertices; } AddCurveToMap(curve: Curve, isArc: boolean = curve instanceof Arc, removeDuplicate: boolean = false) { let sp = curve.StartPoint; let ep = curve.EndPoint; - let startS = this.GetStand(sp); - let endS = this.GetStand(ep); + let startS = this.GetOnlyVertice(sp); + let endS = this.GetOnlyVertice(ep); //在面域分析中,路线指向同一个顶点已经没有意义了 if (this._RemoveSortLine && startS === endS) @@ -98,15 +99,16 @@ export class CurveMap /** * 获得唯一的顶点 */ - GetStand(p: Vector3): Vertice + GetOnlyVertice(p: Vector3): Vertice { let gp = this.GenerateP(p); - if (this._NodeMap.has(gp)) - return this._NodeMap.get(gp); + if (this._VerticeMap.has(gp)) + return this._VerticeMap.get(gp); - let stand = { position: gp, routes: [] }; - this._NodeMap.set(p, stand); - return stand; + let vertice: Vertice = { position: gp, routes: [] }; + this._VerticeMap.set(p, vertice); + this._Vertices.push(vertice); + return vertice; } _LookupTable: { [key: string]: Vector3; } = {}; @@ -114,10 +116,10 @@ export class CurveMap /** * 生成一个唯一的向量. */ - GenerateP(v: Vector3): Vector3 + GenerateP(p: Vector3): Vector3 { let key = ""; - let els = v.toArray(); + let els = p.toArray(); for (let n of els) { let valueQuantized = Math.round(n * this.multiplier); @@ -145,8 +147,8 @@ export class CurveMap key += hashpart[hashmaskShifted & 1]; hashmaskShifted >>= 1; }); - this._LookupTable[key] = v; + this._LookupTable[key] = p; } - return v; + return p; } } diff --git a/src/Geometry/RegionParse.ts b/src/Geometry/RegionParse.ts index 829b0d8b0..492258415 100644 --- a/src/Geometry/RegionParse.ts +++ b/src/Geometry/RegionParse.ts @@ -1,5 +1,5 @@ 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 { Curve } from "../DatabaseServices/Entity/Curve"; import { Polyline } from "../DatabaseServices/Entity/Polyline"; @@ -10,7 +10,13 @@ import { angle } from "./GeUtils"; //区域的路线表 表示了一个区域 type RegionRouteS = Route[][]; -//区域搜索算法 +/** +面域分析,基于最小循环图重新实现的版本,拓展了实现求最大轮廓。 +当最大轮廓=最小轮廓时,只绘制最大轮廓(独立轮廓无分裂)。 + +算法只实现去重模式,业务场景应该没有非去重模式。 +如果需要非去重模式,那么应该获取到多个CurveMap,然后对多个CurveMap进行面域分析,得出多个重叠的面域。 + */ export class RegionParse { //区域列表 通常是外轮廓 @@ -24,18 +30,20 @@ export class RegionParse private _CurveCount: number; /** - * @param {Curve[]} cuList 请不要传递圆和椭圆. + * @param cuList 请不要传递圆和椭圆. + * @param [numDimensions=3] 精度:小数点后个数 + * @param [removeDuplicate=true] 删除重复(现在必须是true,请不要修改它) */ constructor(cuList: Curve[], public numDimensions = 3, private removeDuplicate = true) { //需要搜索的站 - let vertices = this.GenerateNodeMap(cuList); + let vertices = this.GenerateVerticeMap(cuList); //移除细丝 while (true) { let v = vertices.find(v => v.routes.length < 2); - if (v) vertices = this.RemoveFilamentAt(v, vertices); + if (v) this.RemoveFilamentAt(v, vertices); else break; } let lowerVertice: Vertice; @@ -46,8 +54,8 @@ export class RegionParse let maxWalk = ClosedWalkFrom(lowerVertice, this._CurveCount, WalkType.Max); this.RemoveEdge(minWalk[0]); - vertices = this.RemoveFilamentAt(minWalk[0].from, vertices); - vertices = this.RemoveFilamentAt(minWalk[0].to, vertices); + this.RemoveFilamentAt(minWalk[0].from, vertices); + this.RemoveFilamentAt(minWalk[0].to, vertices); minWalk = ReduceWalk(minWalk); maxWalk = ReduceWalk(maxWalk); @@ -92,7 +100,7 @@ export class RegionParse let current = v; while (current && current.routes.length < 2) { - vertices = arrayRemove(vertices, current); + vertices = arrayRemoveOnce(vertices, current); let r = current.routes[0]; if (r) { @@ -102,7 +110,6 @@ export class RegionParse else current = undefined; } - return vertices; } RemoveEdge(r: Route) @@ -134,7 +141,7 @@ export class RegionParse * 构造路线图. 每个节点对应下一个路口的路线表. 路口表使用逆时针排序,起始角度使用正x轴. * @returns 所有的顶点 */ - private GenerateNodeMap(curveList: Curve[]): Array + private GenerateVerticeMap(curveList: Curve[]): Array { 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; - for (let r of s.routes) - { - if (r.length < minLength) - minLength = r.length; - } - for (let r of s.routes) + for (let r of v.routes) + if (r.length < minLength) minLength = r.length; + for (let r of v.routes) 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; } @@ -222,8 +225,6 @@ export class RegionParse /** * 曲线是否已经被算法使用 - * @param cu - * @returns true if cueve used */ GetCueveUsed(cu: Curve): boolean { diff --git a/src/GraphicsSystem/LinkSelft.ts b/src/GraphicsSystem/LinkSelft.ts index 816ebb176..6cec0cfc8 100644 --- a/src/GraphicsSystem/LinkSelft.ts +++ b/src/GraphicsSystem/LinkSelft.ts @@ -84,7 +84,7 @@ export class LinkSelf let cu = breakCus[i]; if (this.GetCurveUse(cu)) continue; let cuIndex = this.GetCurveIndex(cu); - let stand = cuMap.GetStand(cu.EndPoint); + let stand = cuMap.GetOnlyVertice(cu.EndPoint); let routeCus = new Set(); @@ -92,7 +92,7 @@ export class LinkSelf { //缓存走过的节点 let ways: Vertice[] = []; - ways.push(cuMap.GetStand(cu.StartPoint)); + ways.push(cuMap.GetOnlyVertice(cu.StartPoint)); if (equalv3(route.curve.EndPoint, stand.position)) continue; //如果方向相反,那么退出计算 (不符合) @@ -148,7 +148,7 @@ export class LinkSelf while (true) { let oldCount = cs.length; - let routes = cuMap.GetStand(isInv ? originCu.StartPoint : originCu.EndPoint).routes; + let routes = cuMap.GetOnlyVertice(isInv ? originCu.StartPoint : originCu.EndPoint).routes; //把索引相等的站点最后遍历 for (let i = 0; i < routes.length; i++) @@ -200,7 +200,7 @@ export class LinkSelf { let routes2 = routes.concat();//复制数组保证函数有唯一结果 routes2.push(cu); - curIndex = this.FindMinRoute(this.cuMap.GetStand(cu.EndPoint), nowIndex, cs, routes2); + curIndex = this.FindMinRoute(this.cuMap.GetOnlyVertice(cu.EndPoint), nowIndex, cs, routes2); continue; } @@ -280,9 +280,9 @@ export class LinkSelf let cuMap = new CurveMap(); breakCus.forEach(c => cuMap.AddCurveToMap(c)); //所有的站点 逆序排序. - for (let [, stand] of cuMap._NodeMap) + for (let v of cuMap._Vertices) { - stand.routes.sort((r1, r2) => + v.routes.sort((r1, r2) => { return this.GetCurveIndex(r2.curve) - this.GetCurveIndex(r1.curve); //从大到小 });