private static void solve(List <Point> points, Hull hull, List <Triad> triads, bool hullOnly) { int N = points.Count; double[] distSqCentre = new double[N]; int[] sortedInd = new int[N]; for (int i = 0; i < N; i++) { distSqCentre[i] = points[0].distSqTo(points[i]); sortedInd[i] = i; } Array.Sort(distSqCentre, sortedInd); int mid = -1; double rmin2 = double.PositiveInfinity, circumcentreX = 0, circumcentreY = 0; Triad tri = new Triad(sortedInd[0], sortedInd[1], sortedInd[2]); for (int i = 2; i < N; i++) { tri.c = sortedInd[i]; if (tri.findCircumcircle(points) && tri.circumcircleR2 < rmin2) { mid = i; rmin2 = tri.circumcircleR2; circumcentreX = tri.circumcircleX; circumcentreY = tri.circumcircleY; } else if (rmin2 * 4 < distSqCentre[i]) { break; } } if (mid != 2) { int midInd = sortedInd[mid]; double distSqMid = distSqCentre[mid]; Array.Copy(sortedInd, 2, sortedInd, 3, mid - 2); Array.Copy(distSqCentre, 2, distSqCentre, 3, mid - 2); sortedInd[2] = midInd; distSqCentre[2] = distSqMid; } tri.c = sortedInd[2]; tri.makeClockwise(points); tri.findCircumcircle(points); triads.Add(tri); hull.Add(new HullPoint(points, tri.a)); hull.Add(new HullPoint(points, tri.b)); hull.Add(new HullPoint(points, tri.c)); Point centre = new Point(circumcentreX, circumcentreY); for (int i = 3; i < N; i++) { distSqCentre[i] = points[sortedInd[i]].distSqTo(centre); } Array.Sort(distSqCentre, sortedInd, 3, N - 3); int T = 0; for (int i = 3; i < N; i++) { int pInd = sortedInd[i]; HullPoint p = new HullPoint(points, pInd); double dx = p.x - hull[0].x, dy = p.y - hull[0].y; int H = hull.Count, hInd = 0; List <int> pInds = new List <int>(), tInds = new List <int>(); if (hull.edgeVisibleFrom(0, dx, dy)) { hInd = 0; if (hull.edgeVisibleFrom(H - 1, dx, dy)) { pInds.Add(hull[H - 1].pInd); tInds.Add(hull[H - 1].tInd); for (int h = 0; h < H - 1; h++) { pInds.Add(hull[h].pInd); tInds.Add(hull[h].tInd); if (hull.edgeVisibleFrom(h, p)) { hull.RemoveAt(h); h--; H--; } else { hull.Insert(0, p); H++; break; } } for (int h = H - 2; h > 0; h--) { if (hull.edgeVisibleFrom(h, p)) { pInds.Insert(0, hull[h].pInd); tInds.Insert(0, hull[h].tInd); hull.RemoveAt(h + 1); } else { break; } } } else { hInd = 1; pInds.Add(hull[0].pInd); tInds.Add(hull[0].tInd); for (int h = 1; h < H; h++) { pInds.Add(hull[h].pInd); tInds.Add(hull[h].tInd); if (hull.edgeVisibleFrom(h, p)) { hull.RemoveAt(h); h--; H--; } else { hull.Insert(h, p); break; } } } } else { int e1 = -1, e2 = H; for (int h = 1; h < H; h++) { if (hull.edgeVisibleFrom(h, p)) { if (e1 < 0) { e1 = h; } } else { if (e1 > 0) { e2 = h; break; } } } if (e2 < H) { for (int e = e1; e <= e2; e++) { pInds.Add(hull[e].pInd); tInds.Add(hull[e].tInd); } } else { for (int e = e1; e < e2; e++) { pInds.Add(hull[e].pInd); tInds.Add(hull[e].tInd); } pInds.Add(hull[0].pInd); } if (e1 < e2 - 1) { hull.RemoveRange(e1 + 1, e2 - e1 - 1); } hull.Insert(e1 + 1, p); hInd = e1 + 1; } if (hullOnly) { continue; } int a = pInd, T0; int P = pInds.Count(); T = T0 = triads.Count(); for (int j = 0; j < P - 1; j++) { Triad t = new Triad(a, pInds[j], pInds[j + 1]); t.findCircumcircle(points); t.bc = tInds[j]; if (j > 0) { t.ab = T - 1; } t.ac = T + 1; Triad u = triads[tInds[j]]; if ((t.b == u.a && t.c == u.b) || (t.b == u.b && t.c == u.a)) { u.ab = T; } else if ((t.b == u.a && t.c == u.c) || (t.b == u.c && t.c == u.a)) { u.ac = T; } else if ((t.b == u.b && t.c == u.c) || (t.b == u.c && t.c == u.b)) { u.bc = T; } triads.Add(t); T++; } triads[T - 1].ac = -1; hull[hInd].tInd = T - 1; if (hInd > 0) { hull[hInd - 1].tInd = T0; } else { H = hull.Count; hull[hull.Count - 1].tInd = T0; } } }