// 给定弧段计算夹角并加入拓扑结构 static void VertexTopo(GeomArc arc, LineSegment seg) { if (!vertPool.ContainsKey(seg.Item1)) { vertPool[seg.Item1] = new SortedDictionary <double, GeomArc>(); } vertPool[seg.Item1][seg.Angle] = arc; }
// 从三角序列创建矢量图层 static GeomLayer FromTriangles(IEnumerable <Triangle> triangles, List <GeomPoint> originalPoints) { // 创建字典用于反查 var pt_mapper = new Dictionary <Vector2, GeomPoint>(); foreach (GeomPoint tmp in originalPoints) { pt_mapper[tmp] = tmp; } // 构造矢量图层 GeomLayer result = new GeomLayer(GeomType.Polygon); var g_points = new Dictionary <Vector2, GeomPoint>(); var g_arcs = new Dictionary <Edge, GeomArc>(); int point_cnt = 0, arc_cnt = 0, poly_cnt = 0; foreach (Triangle tri in triangles) { // 按需创建点 foreach (Vector2 tmp in tri.Points()) { if (!g_points.ContainsKey(tmp)) { var new_point = pt_mapper[tmp].Copy(); // 反查原始数据 new_point.id = ++point_cnt; g_points[tmp] = new_point; } } // 去重获取三边 var arcs = new List <GeomArc>(); foreach (var tmp in tri.Edges()) { GeomArc cur_arc; if (g_arcs.ContainsKey(tmp)) { cur_arc = g_arcs[tmp]; } else { cur_arc = new GeomArc(new GeomPoint[] { g_points[tmp.Item1], g_points[tmp.Item2] }, ++arc_cnt); g_arcs[tmp] = g_arcs[tmp.Reverse()] = cur_arc; } arcs.Add(cur_arc); } // 创建三角形 GeomPoly tri_poly = new GeomPoly(arcs, ++poly_cnt); result.polygons.Add(tri_poly); } // 加入点集、边集 result.points.AddRange(g_points.Values); result.arcs.AddRange(g_arcs.Values); return(result); }
// 2.1 从指定弧段与端点开始搜索相连多边形 static void PolyTopoGroup(GeomPoint pt, GeomArc arc) { inners = new HashSet <GeomPoly>(); stack = new LinkedList <Tuple <GeomPoint, GeomArc> >(); stack.AddFirst(new Tuple <GeomPoint, GeomArc>(pt, arc)); while (stack.Count > 0) { var data = stack.First; stack.RemoveFirst(); PolyTopoUnit(data.Value); } if (inners.Count == 0) { return; } // 获取并删除外包多边形(面积最大) GeomPoly outer = null; if (inners.Count > 1) { outer = null; foreach (var poly in inners) { if (outer == null || outer.OuterArea < poly.OuterArea) { outer = poly; } } inners.Remove(outer); } else { outer = inners.First(); } // 加入待处理孔洞列表 holesGroup.Add(new Tuple <GeomPoly, HashSet <GeomPoly> >(outer, inners)); cPoly.AddRange(inners); }
// 2.1.1 搜索相连多边形:单元操作,返回当前搜索 static void PolyTopoUnit(Tuple <GeomPoint, GeomArc> data) { if (arcUsed.Contains(data)) { return; } var res = new List <Tuple <GeomPoint, GeomArc> >(); // 搜索直到首尾相接 while (true) { // 加入当前弧段 res.Add(data); arcUsed.Add(data); // 获取下一弧段 GeomPoint prevPt = data.Item1; GeomArc prevArc = data.Item2; GeomPoint nextPt = prevArc.First; if (nextPt == prevPt) { nextPt = prevArc.Last; } GeomArc nextArc = vertNext[nextPt][data.Item2]; data = new Tuple <GeomPoint, GeomArc>(nextPt, prevArc); // 同弧段不同顶点 if (!arcUsed.Contains(data)) { stack.AddFirst(data); } data = new Tuple <GeomPoint, GeomArc>(nextPt, nextArc); // 首尾相接时跳出 if (data.Equals(res[0])) { break; } } // 创造多边形 var newPoly = new GeomPoly(from pair in res select pair.Item2); inners.Add(newPoly); }