public static void triangulate <T>(Project <T> project, FList <T> poly, FList <TriIdx> result) { var N = poly.Count; result.Clear(); if (N < 3) { return; } result.Capacity = poly.Count - 2; if (N == 3) { result.Add(new TriIdx(0, 1, 2)); return; } var vinfo = new vertex_info[N]; vinfo[0] = new vertex_info(project(poly[0]), 0); for (int i = 1; i < N - 1; ++i) { vinfo[i] = new vertex_info(project(poly[i]), i); vinfo[i].prev = vinfo[i - 1]; vinfo[i - 1].next = vinfo[i]; } vinfo[N - 1] = new vertex_info(project(poly[N - 1]), N - 1); vinfo[N - 1].prev = vinfo[N - 2]; vinfo[N - 1].next = vinfo[0]; vinfo[0].prev = vinfo[N - 1]; vinfo[N - 2].next = vinfo[N - 1]; for (int i = 0; i < N; ++i) { vinfo[i].recompute(); } var begin = vinfo[0]; removeDegeneracies(ref begin, result); doTriangulate(begin, result); }
/// <summary> /// 全要素を取り除く /// </summary> public void Clear() { _List.Clear(); }
static bool findDiagonal(vertex_info begin, out vertex_info v1, out vertex_info v2) { vertex_info t; var heap = new FList <vertex_info>(); v1 = begin; do { heap.Clear(); for (v2 = v1.next.next; v2 != v1.prev; v2 = v2.next) { if (!internalToAngle(v1.next, v1, v1.prev, v2.p) || !internalToAngle(v2.next, v2, v2.prev, v1.p)) { continue; } PriorityQueue <vertex_info> .PushHeap(heap, v2, new vertex_info_l2norm_inc_ordering(v1)); } while (heap.Count != 0) { v2 = PriorityQueue <vertex_info> .PopHeap(heap, new vertex_info_l2norm_inc_ordering(v1)); // test whether v1-v2 is a valid diagonal. var v_min_x = Math.Min(v1.p.X, v2.p.X); var v_max_x = Math.Max(v1.p.X, v2.p.X); bool intersected = false; for (t = v1.next; !intersected && t != v1.prev; t = t.next) { vertex_info u = t.next; if (t == v2 || u == v2) { continue; } var l1 = orient2d(v1.p, v2.p, t.p); var l2 = orient2d(v1.p, v2.p, u.p); if ((l1 > 0.0 && l2 > 0.0) || (l1 < 0.0 && l2 < 0.0)) { // both on the same side; no intersection continue; } var dx13 = v1.p.X - t.p.X; var dy13 = v1.p.Y - t.p.Y; var dx43 = u.p.X - t.p.X; var dy43 = u.p.Y - t.p.Y; var dx21 = v2.p.X - v1.p.X; var dy21 = v2.p.Y - v1.p.Y; var ua_n = dx43 * dy13 - dy43 * dx13; var ub_n = dx21 * dy13 - dy21 * dx13; var u_d = dy43 * dx21 - dx43 * dy21; if (Math.Abs(u_d) < element.Epsilon) { // parallel if (Math.Abs(ua_n) < element.Epsilon) { // colinear if (Math.Max(t.p.X, u.p.X) >= v_min_x && Math.Min(t.p.X, u.p.X) <= v_max_x) { // colinear and intersecting intersected = true; } } } else { // not parallel var ua = ua_n / u_d; var ub = ub_n / u_d; if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { intersected = true; } } } if (!intersected) { // test whether midpoint winding == 1 var mid = (v1.p + v2.p) / 2; if (windingNumber(begin, mid) == 1) { // this diagonal is ok return(true); } } } // couldn't find a diagonal from v1 that was ok. v1 = v1.next; } while (v1 != begin); return(false); }