예제 #1
0
        // Точка внутри или на границе.
        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);
        }
예제 #2
0
        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;
        }