// Точка внутри или на границе. private static bool PointInTriangle(Vector2 pt, Vector2 v1, Vector2 v2, Vector2 v3) { bool b1 = InternalTriangle.Sign(pt, v1, v2) <= 0.0f; bool b2 = InternalTriangle.Sign(pt, v2, v3) <= 0.0f; bool b3 = InternalTriangle.Sign(pt, v3, v1) <= 0.0f; return(b1 == b2 && b2 == b3); }
private void Triangulate() { // Начальный список всех индексов List <int> ind = new List <int>(); for (int i = 0; i < vertices.Length - 2; i++) { ind.Add(i); } int indicesPosition = 0; // int[] resultIndices = new int[(vertices.Length - 4) * 3]; InternalTriangle[] resultTriangles = new InternalTriangle[vertices.Length - 4]; while (ind.Count != 3) { bool found = false; int prevCount = ind.Count; // Нам надо выпуклую найти вершину, для которой две её товарки дают ребро не имеющее пересечений с остальными рёбрами for (int j = 0; j < ind.Count; j++) { int curIndex = ind[j]; int prevIndex = j - 1 < 0 ? ind[ind.Count - 1] : ind[j - 1]; int nextIndex = j + 1 >= ind.Count ? ind[0] : ind[j + 1]; if (!Convex(prevIndex, curIndex, nextIndex)) { //if (!Convex(nextIndex, curIndex, prevIndex)) continue; } // Проверяем что ни одна из точек не попала внутрь этого треугольника for (int i = 0; i < ind.Count; i++) { if (ind[i] == curIndex || ind[i] == prevIndex || ind[i] == nextIndex) { continue; } if (PointInTriangle(vertices[ind[i]], vertices[prevIndex], vertices[curIndex], vertices[nextIndex])) { found = true; break; } } if (found) { found = false; continue; } // Вершины нужно добавлять хитро - чтобы первые две грани были внешними, а последняя - resultTriangles[indicesPosition] = new InternalTriangle( vertices[prevIndex], vertices[curIndex], vertices[nextIndex], !IsExternalEdge(prevIndex, curIndex), !IsExternalEdge(curIndex, nextIndex), !IsExternalEdge(nextIndex, prevIndex) ); indicesPosition++; // её удаляем, а двух её товарок записываем в список вместе с ней ind.RemoveAt(j); break; } if (prevCount == ind.Count) { throw new Exception("Something wrong with contour or algorithm."); } } // И последняя порция // resultIndices[indicesPosition] = ind[0]; // resultIndices[indicesPosition + 1] = ind[1]; // resultIndices[indicesPosition + 2] = ind[2]; // Здесь важно не сделать огромной ошибки, нам нужно, чтобы resultTriangles[indicesPosition] = new InternalTriangle( vertices[ind[0]], vertices[ind[1]], vertices[ind[2]], !IsExternalEdge(ind[0], ind[1]), !IsExternalEdge(ind[1], ind[2]), !IsExternalEdge(ind[2], ind[0])); // indices = resultIndices; triangles = resultTriangles; }