/// <summary>
    /// Function returns faces connected to each edge. Result holds indexes to BasicEdges and BasicTriangles, respectively.
    /// </summary>
    public Dictionary <int, List <int> > GetEdgeFacesData()
    {
        Dictionary <int, List <int> > edgeFaces = new Dictionary <int, List <int> >();

        var basicTriangles = BasicTriangles;
        var basicEdges     = BasicEdges;

        for (int t = 0; t < basicTriangles.Count; t++)
        {
            BasicTriangle basicTriangle = basicTriangles[t];
            for (int e = 0; e < basicEdges.Count; e++)
            {
                BasicEdge basicEdge = basicEdges[e];
                if (basicTriangle.ContainsEdge(basicEdge))
                {
                    if (!edgeFaces.ContainsKey(e))
                    {
                        edgeFaces.Add(e, new List <int>());
                    }
                    edgeFaces[e].Add(t);
                }
            }
        }

        return(edgeFaces);
    }
    /// <summary>
    /// Function returns list, which provides us with same edge index for both combinations of edge indexes passed into.
    /// Search index form should be: v0 * Vertices.Count + v1.
    /// </summary>
    public List <int> GetUniversalEdgesList()
    {
        int verticesCount   = Vertices.Count;
        int emptyEdge       = int.MaxValue;
        int basicEdgesCount = 0;    // Should increment in a way that BasicEdges are created, so it will actually point to correct BasicEdge.

        List <int> result = new List <int>().Populate(emptyEdge, verticesCount * verticesCount);

        for (int t = 0; t < BasicTriangles.Count; t++)
        {
            BasicTriangle basicTriangle = BasicTriangles[t];
            for (int a = 2, b = 0; b < 3; a = b++)
            {
                int v = basicTriangle.v[a];
                int u = basicTriangle.v[b];

                if (result[v * verticesCount + u] == emptyEdge)
                {
                    result[v * verticesCount + u] = basicEdgesCount;
                    result[u * verticesCount + v] = basicEdgesCount;

                    basicEdgesCount++;
                }
            }
        }

        return(result);
    }
    public void AlgorithmRandomIncremental()
    {
        ClearIfNecessary();

        if (mDataCloud.Count < 4)
        {
            Debugger.Get.Log("Insufficient points to generate a tetrahedron.", DebugOption.CH3);
            return;
        }

        int index = 0;
        // Pick first point.
        KeyValuePair <int, Vector3> P1 = new KeyValuePair <int, Vector3>(index, mDataCloud[index]);

        KeyValuePair <int, Vector3> P2 = new KeyValuePair <int, Vector3>(-1, Vector3.zero);

        while (P2.Key == -1 && ++index < mDataCloud.Count)
        {
            // Two points form a line if they are not equal.
            Vector3 P = mDataCloud[index];
            if (!ExtMathf.Equal(P2.Value, P))
            {
                P2 = new KeyValuePair <int, Vector3>(index, P);
            }
        }
        if (P2.Key == -1)
        {
            Debugger.Get.Log("Couldn't find two not equal points.", DebugOption.CH3);
            return;
        }

        // Points on line and on the same plane, still should be considered later on. Happens.
        List <int> skippedPoints = new List <int>();

        Edge line = new Edge(P1.Value, P2.Value);
        KeyValuePair <int, Vector3> P3 = new KeyValuePair <int, Vector3>(-1, Vector3.zero);

        while (P3.Key == -1 && ++index < mDataCloud.Count)
        {
            // Three points form a triangle if they are not on the same line.
            Vector3 P = mDataCloud[index];
            if (!line.CalculateIfIsOnLine(P))
            {
                P3 = new KeyValuePair <int, Vector3>(index, P);
            }
            else
            {
                skippedPoints.Add(index);
            }
        }
        if (P3.Key == -1)
        {
            Debugger.Get.Log("Couldn't find three not linear points.", DebugOption.CH3);
            return;
        }

        Triangle planeTriangle         = new Triangle(P1.Value, P2.Value, P3.Value);
        KeyValuePair <int, Vector3> P4 = new KeyValuePair <int, Vector3>(-1, Vector3.zero);

        while (P4.Key == -1 && ++index < mDataCloud.Count)
        {
            // Four points form a tetrahedron if they are not on the same plane.
            Vector3 P = mDataCloud[index];
            if (planeTriangle.CalculateRelativePosition(P) != 0)
            {
                P4 = new KeyValuePair <int, Vector3>(index, P);
            }
            else
            {
                skippedPoints.Add(index);
            }
        }
        if (P4.Key == -1)
        {
            Debugger.Get.Log("Couldn't find four not planar points.", DebugOption.CH3);
            return;
        }

        // Calculate reference centroid of ConvexHull.
        Vector3 centroid = ExtMathf.Centroid(P1.Value, P2.Value, P3.Value, P4.Value);

        List <BasicTriangle> tetrahedronTriangles = new List <BasicTriangle>();

        tetrahedronTriangles.Add(new BasicTriangle(P3.Key, P2.Key, P1.Key));
        tetrahedronTriangles.Add(new BasicTriangle(P1.Key, P2.Key, P4.Key));
        tetrahedronTriangles.Add(new BasicTriangle(P2.Key, P3.Key, P4.Key));
        tetrahedronTriangles.Add(new BasicTriangle(P3.Key, P1.Key, P4.Key));

        foreach (BasicTriangle basicTriangle in tetrahedronTriangles)
        {
            Triangle triangle = new Triangle(
                mDataCloud[basicTriangle.v[0]],
                mDataCloud[basicTriangle.v[1]],
                mDataCloud[basicTriangle.v[2]]
                );

            if (triangle.CalculateRelativePosition(centroid) != -1)
            {   // Centroid of ConvexHull should always be inside.
                basicTriangle.Reverse();
            }
            mBasicTriangles.Add(basicTriangle);
        }

        Dictionary <int, HashSet <BasicTriangle> > pointFacets = new Dictionary <int, HashSet <BasicTriangle> >();
        Dictionary <BasicTriangle, HashSet <int> > facetPoints = new Dictionary <BasicTriangle, HashSet <int> >();

        foreach (BasicTriangle basicTriangle in mBasicTriangles)
        {
            Triangle triangle = new Triangle(
                mDataCloud[basicTriangle.v[0]],
                mDataCloud[basicTriangle.v[1]],
                mDataCloud[basicTriangle.v[2]]
                );

            for (int p = index; p < mDataCloud.Count; p++)
            {
                if (triangle.CalculateRelativePosition(mDataCloud[p]) == 1)
                {
                    if (!pointFacets.ContainsKey(p))
                    {
                        pointFacets.Add(p, new HashSet <BasicTriangle>());
                    }
                    pointFacets[p].Add(basicTriangle);

                    if (!facetPoints.ContainsKey(basicTriangle))
                    {
                        facetPoints.Add(basicTriangle, new HashSet <int>());
                    }
                    facetPoints[basicTriangle].Add(p);
                }
            }

            foreach (int p in skippedPoints)
            {
                if (triangle.CalculateRelativePosition(mDataCloud[p]) == 1)
                {
                    if (!pointFacets.ContainsKey(p))
                    {
                        pointFacets.Add(p, new HashSet <BasicTriangle>());
                    }
                    pointFacets[p].Add(basicTriangle);
                    facetPoints[basicTriangle].Add(p);
                }
            }
        }

        while (pointFacets.Count > 0)
        {
            var firstPointFacet = pointFacets.First();
            if (firstPointFacet.Value.Count > 0)
            {
                Dictionary <BasicEdge, BasicEdge> horizon = new Dictionary <BasicEdge, BasicEdge>();

                foreach (BasicTriangle basicTriangle in firstPointFacet.Value)
                {
                    for (int a = 2, b = 0; b < 3; a = b++)
                    {
                        BasicEdge edge          = new BasicEdge(basicTriangle.v[a], basicTriangle.v[b]);
                        BasicEdge edgeUnordered = edge.Unordered();

                        if (horizon.ContainsKey(edgeUnordered))
                        {
                            horizon.Remove(edgeUnordered);
                        }
                        else
                        {
                            horizon.Add(edgeUnordered, edge);
                        }
                    }
                }

                int pointKey = firstPointFacet.Key;
                foreach (BasicTriangle facet in firstPointFacet.Value)
                {
                    foreach (int facetPointKey in facetPoints[facet])
                    {
                        if (facetPointKey != pointKey)
                        {
                            pointFacets[facetPointKey].Remove(facet);
                        }
                    }

                    facetPoints.Remove(facet);
                    mBasicTriangles.Remove(facet);
                }
                pointFacets.Remove(pointKey);

                foreach (KeyValuePair <BasicEdge, BasicEdge> edges in horizon)
                {
                    BasicTriangle newBasicTriangle = new BasicTriangle(edges.Value.v[0], edges.Value.v[1], pointKey);

                    mBasicTriangles.Add(newBasicTriangle);

                    if (pointFacets.Count > 0)
                    {
                        Triangle newTriangle = new Triangle(
                            mDataCloud[newBasicTriangle.v[0]],
                            mDataCloud[newBasicTriangle.v[1]],
                            mDataCloud[newBasicTriangle.v[2]]
                            );

                        foreach (var pointFacetsKey in pointFacets.Keys)
                        {
                            if (newTriangle.CalculateRelativePosition(mDataCloud[pointFacetsKey]) == 1)
                            {
                                pointFacets[pointFacetsKey].Add(newBasicTriangle);

                                if (!facetPoints.ContainsKey(newBasicTriangle))
                                {
                                    facetPoints.Add(newBasicTriangle, new HashSet <int>());
                                }
                                facetPoints[newBasicTriangle].Add(pointFacetsKey);
                            }
                        }
                    }
                }
            }
            else
            {
                pointFacets.Remove(firstPointFacet.Key);
            }
        }
    }
예제 #4
0
 public static Triangle FromBasicTriangle(BasicTriangle basicTriangle, List <Vector3> dataCloud)
 {
     return(new Triangle(dataCloud[basicTriangle.v[0]], dataCloud[basicTriangle.v[1]], dataCloud[basicTriangle.v[2]]));
 }