コード例 #1
0
        public void Execute()
        {
            outputEdges.Clear();

            int triCount = inputTriangles.Length, A, B, C;
            NativeHashMap <int, bool> m_hash = new NativeHashMap <int, bool>(triCount, Allocator.Temp);

            bool     bAB = false, bBC = false, bCA = false, r;
            int      hAB, hBC, hCA;
            UIntPair AB, BC, CA;
            Triad    triad;

            for (int i = 0; i < triCount; i++)
            {
                triad = inputTriangles[i];

                A  = triad.A; B = triad.B; C = triad.C;
                AB = new UIntPair(A, B);
                BC = new UIntPair(B, C);
                CA = new UIntPair(C, A);

                hAB = AB.GetHashCode();
                hBC = BC.GetHashCode();
                hCA = CA.GetHashCode();

                #region Loop

                //Fast but consistency drop over ~200k edges.
                bAB = m_hash.TryGetValue(hAB, out r);
                bBC = m_hash.TryGetValue(hBC, out r);
                bCA = m_hash.TryGetValue(hCA, out r);

                /*
                 * eCount = outputEdges.Length;
                 * for (int ie = 0; ie < eCount; ie++)
                 * {
                 *  EE = outputEdges[ie];
                 *
                 *  iA = EE.A; iB = EE.B;
                 *
                 *  if (!bAB && ((iA == A && iB == B) || (iA == B && iB == A))) { bAB = true; }
                 *  else if (!bBC && ((iA == B && iB == C) || (iA == C && iB == B))) { bBC = true; }
                 *  else if (!bCA && ((iA == C && iB == A) || (iA == A && iB == C))) { bCA = true; }
                 *
                 * }
                 */
                if (!bAB)
                {
                    outputEdges.Add(AB); m_hash.TryAdd(hAB, true);
                }
                if (!bBC)
                {
                    outputEdges.Add(BC); m_hash.TryAdd(hBC, true);
                }
                if (!bCA)
                {
                    outputEdges.Add(CA); m_hash.TryAdd(hCA, true);
                }

                #endregion
            }
        }
コード例 #2
0
        public void Execute(int index)
        {
            RaycastData   raycast = m_inputRaycasts[index];
            RaycastResult result  = new RaycastResult()
            {
                hitAgent        = -1,
                hitObstacle     = -1,
                dynamicObstacle = false
            };

            RaycastFilter filter = raycast.filter;

            if (filter == 0)
            {
                m_results[index] = result;
                return;
            }

            float2
                r_position = raycast.position,
                r_dir      = raycast.direction,
                hitLocation;

            float
                a_bottom  = raycast.baseline,
                a_top     = a_bottom,
                a_sqRange = lengthsq(raycast.distance);

            Segment2D raySegment = new Segment2D(raycast.position, raycast.position + raycast.direction * raycast.distance),
                      segment;

            UIntPair           pair = new UIntPair(0, 0);
            ObstacleVertexData otherVertex;
            bool
                twoSidedCast   = raycast.twoSided,
                alreadyCovered = false,
                hit;

            #region static obstacles

            if ((filter & RaycastFilter.OBSTACLE_STATIC) != 0)
            {
                NativeList <int> staticObstacleNeighbors = new NativeList <int>(10, Allocator.Temp);

                if (m_staticObstacleTree.Length > 0)
                {
                    QueryObstacleTreeRecursive(ref raycast, ref a_sqRange, 0, ref staticObstacleNeighbors,
                                               ref m_staticObstacles, ref m_staticRefObstacles, ref m_staticObstacleInfos, ref m_staticObstacleTree);
                }

                NativeHashMap <UIntPair, bool> coveredStaticEdges = new NativeHashMap <UIntPair, bool>(m_staticObstacleTree.Length * 2, Allocator.Temp);

                for (int i = 0; i < staticObstacleNeighbors.Length; ++i)
                {
                    ObstacleVertexData vertex = m_staticObstacles[staticObstacleNeighbors[i]];
                    ObstacleInfos      infos  = m_staticObstacleInfos[vertex.infos];

                    pair           = new UIntPair(vertex.index, vertex.next);
                    alreadyCovered = coveredStaticEdges.TryGetValue(pair, out hit);

                    if (!alreadyCovered)
                    {
                        otherVertex    = m_staticRefObstacles[vertex.next];
                        segment        = new Segment2D(vertex.pos, otherVertex.pos);
                        alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f);

                        if (!alreadyCovered)
                        {
                            if (raySegment.IsIntersecting(segment, out hitLocation))
                            {
                                //Rays intersecting !
                                if (result.hitObstacle == -1 ||
                                    distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D))
                                {
                                    result.hitObstacleLocation2D = hitLocation;
                                    result.hitObstacle           = infos.index;
                                }
                            }
                        }

                        coveredStaticEdges.TryAdd(pair, true);
                    }

                    pair           = new UIntPair(vertex.index, vertex.prev);
                    alreadyCovered = coveredStaticEdges.ContainsKey(pair);

                    if (!alreadyCovered)
                    {
                        otherVertex    = m_staticRefObstacles[vertex.prev];
                        segment        = new Segment2D(vertex.pos, otherVertex.pos);
                        alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f);

                        if (!alreadyCovered)
                        {
                            if (raySegment.IsIntersecting(segment, out hitLocation))
                            {
                                //Rays intersecting !
                                if (result.hitObstacle == -1 ||
                                    distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D))
                                {
                                    result.hitObstacleLocation2D = hitLocation;
                                    result.hitObstacle           = infos.index;
                                }
                            }
                        }

                        coveredStaticEdges.TryAdd(pair, true);
                    }
                }

                staticObstacleNeighbors.Dispose();
                coveredStaticEdges.Dispose();
            }

            #endregion

            #region dynamic obstacles

            if ((filter & RaycastFilter.OBSTACLE_DYNAMIC) != 0)
            {
                NativeList <int> dynObstacleNeighbors = new NativeList <int>(10, Allocator.Temp);

                if (m_dynObstacleTree.Length > 0)
                {
                    QueryObstacleTreeRecursive(ref raycast, ref a_sqRange, 0, ref dynObstacleNeighbors,
                                               ref m_dynObstacles, ref m_dynRefObstacles, ref m_dynObstacleInfos, ref m_dynObstacleTree);
                }

                NativeHashMap <UIntPair, bool> coveredDynEdges = new NativeHashMap <UIntPair, bool>(m_dynObstacleTree.Length * 2, Allocator.Temp);

                for (int i = 0; i < dynObstacleNeighbors.Length; ++i)
                {
                    ObstacleVertexData vertex = m_dynObstacles[dynObstacleNeighbors[i]];
                    ObstacleInfos      infos  = m_dynObstacleInfos[vertex.infos];

                    pair           = new UIntPair(vertex.index, vertex.next);
                    alreadyCovered = coveredDynEdges.TryGetValue(pair, out hit);

                    if (!alreadyCovered)
                    {
                        otherVertex    = m_dynRefObstacles[vertex.next];
                        segment        = new Segment2D(vertex.pos, otherVertex.pos);
                        alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f);

                        if (!alreadyCovered)
                        {
                            if (raySegment.IsIntersecting(segment, out hitLocation))
                            {
                                //Rays intersecting !
                                if (result.hitObstacle == -1 ||
                                    distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D))
                                {
                                    result.hitObstacleLocation2D = hitLocation;
                                    result.hitObstacle           = infos.index;
                                    result.dynamicObstacle       = true;
                                }
                            }
                        }

                        coveredDynEdges.TryAdd(pair, true);
                    }

                    pair           = new UIntPair(vertex.index, vertex.prev);
                    alreadyCovered = coveredDynEdges.ContainsKey(pair);

                    if (!alreadyCovered)
                    {
                        otherVertex    = m_dynRefObstacles[vertex.prev];
                        segment        = new Segment2D(vertex.pos, otherVertex.pos);
                        alreadyCovered = (!twoSidedCast && dot(r_dir, segment.normal) < 0f);

                        if (!alreadyCovered)
                        {
                            if (raySegment.IsIntersecting(segment, out hitLocation))
                            {
                                //Rays intersecting !
                                if (result.hitObstacle == -1 ||
                                    distancesq(r_position, hitLocation) < distancesq(r_position, result.hitObstacleLocation2D))
                                {
                                    result.hitObstacleLocation2D = hitLocation;
                                    result.hitObstacle           = infos.index;
                                    result.dynamicObstacle       = true;
                                }
                            }
                        }

                        coveredDynEdges.TryAdd(pair, true);
                    }
                }

                dynObstacleNeighbors.Dispose();
                coveredDynEdges.Dispose();
            }

            #endregion

            #region Agents

            if ((filter & RaycastFilter.AGENTS) != 0)
            {
                NativeList <int> agentNeighbors = new NativeList <int>(10, Allocator.Temp);

                float radSq = a_sqRange + lengthsq(m_maxAgentRadius);

                if (m_inputAgents.Length > 0)
                {
                    QueryAgentTreeRecursive(ref raycast, ref radSq, 0, ref agentNeighbors);
                }

                AgentData agent;
                int       iResult, agentIndex;
                float2    center, i1, i2, rayEnd = r_position + normalize(r_dir) * raycast.distance;
                float
                    a_radius, a_sqRadius, cx, cy,
                    Ax   = r_position.x,
                    Ay   = r_position.y,
                    Bx   = rayEnd.x,
                    By   = rayEnd.y,
                    dx   = Bx - Ax,
                    dy   = By - Ay,
                    magA = dx * dx + dy * dy,
                    distSq;

                int TryGetIntersection(out float2 intersection1, out float2 intersection2)
                {
                    float
                        magB = 2f * (dx * (Ax - cx) + dy * (Ay - cy)),
                        magC = (Ax - cx) * (Ax - cx) + (Ay - cy) * (Ay - cy) - a_sqRadius,
                        det = magB * magB - 4f * magA * magC,
                        sqDet, t;

                    if ((magA <= float.Epsilon) || (det < 0f))
                    {
                        // No real solutions.
                        intersection1 = float2(float.NaN, float.NaN);
                        intersection2 = float2(float.NaN, float.NaN);

                        return(0);
                    }

                    if (det == 0)
                    {
                        // One solution.
                        t = -magB / (2f * magA);

                        intersection1 = float2(Ax + t * dx, Ay + t * dy);
                        intersection2 = float2(float.NaN, float.NaN);

                        return(1);
                    }
                    else
                    {
                        // Two solutions.
                        sqDet = sqrt(det);

                        t             = ((-magB + sqDet) / (2f * magA));
                        intersection1 = float2(Ax + t * dx, Ay + t * dy);

                        t             = ((-magB - sqDet) / (2f * magA));
                        intersection2 = float2(Ax + t * dx, Ay + t * dy);

                        return(2);
                    }
                }

                for (int i = 0; i < agentNeighbors.Length; ++i)
                {
                    agentIndex = agentNeighbors[i];
                    agent      = m_inputAgents[agentIndex];

                    center = agent.position;
                    cx     = center.x;
                    cy     = center.y;

                    a_radius   = agent.radius;
                    a_sqRadius = a_radius * a_radius;

                    if (dot(center - r_position, r_dir) < 0f)
                    {
                        continue;
                    }

                    iResult = TryGetIntersection(out i1, out i2);

                    if (iResult == 0)
                    {
                        continue;
                    }

                    distSq = distancesq(r_position, i1);

                    if (distSq < a_sqRange &&
                        (result.hitAgent == -1 || distSq < distancesq(r_position, result.hitAgentLocation2D)) &&
                        IsBetween(r_position, center, i1))
                    {
                        result.hitAgentLocation2D = i1;
                        result.hitAgent           = agentIndex;
                    }

                    if (iResult == 2)
                    {
                        distSq = distancesq(r_position, i2);

                        if (distSq < a_sqRange &&
                            (result.hitAgent == -1 || distSq < distancesq(r_position, result.hitAgentLocation2D)) &&
                            IsBetween(r_position, center, i2))
                        {
                            result.hitAgentLocation2D = i2;
                            result.hitAgent           = agentIndex;
                        }
                    }
                }

                agentNeighbors.Dispose();
            }

            #endregion

            if (m_plane == AxisPair.XY)
            {
                float baseline = raycast.worldPosition.z;

                if (result.hitAgent != -1)
                {
                    result.hitAgentLocation = float3(result.hitAgentLocation2D, baseline);
                }

                if (result.hitObstacle != -1)
                {
                    result.hitObstacleLocation = float3(result.hitObstacleLocation2D, baseline);
                }
            }
            else
            {
                float baseline = raycast.worldPosition.y;

                if (result.hitAgent != -1)
                {
                    result.hitAgentLocation = float3(result.hitAgentLocation2D.x, baseline, result.hitAgentLocation2D.y);
                }

                if (result.hitObstacle != -1)
                {
                    result.hitObstacleLocation = float3(result.hitObstacleLocation2D.x, baseline, result.hitObstacleLocation2D.y);
                }
            }

            m_results[index] = result;
        }
コード例 #3
0
        public void Execute()
        {
            int      A, B, C, siteCount = inputTriangles.Length, edgeIndex = -1, Ti;
            float3   centroid, circumcenter;
            UIntPair edge;
            Triad    triad;
            NativeHashMap <UIntPair, int>      uniqueEdges        = new NativeHashMap <UIntPair, int>(siteCount * 3, Allocator.Temp);
            NativeMultiHashMap <UIntPair, int> connectedTriangles = new NativeMultiHashMap <UIntPair, int>(siteCount * 3, Allocator.Temp);
            NativeList <int> neighbors = new NativeList <int>(0, Allocator.Temp);
            float            weight    = clamp(centroidWeight, 0f, 1f);

            if (weight == 0f)
            {
                for (int i = 0; i < siteCount; i++)
                {
                    triad = inputTriangles[i];
                    A     = triad.A; B = triad.B; C = triad.C;
                    outputVertices.Add(Circumcenter(ref triad, ref inputVertices));

                    connectedTriangles.Add(new UIntPair(A, B), i);
                    connectedTriangles.Add(new UIntPair(B, C), i);
                    connectedTriangles.Add(new UIntPair(C, A), i);
                }
            }
            else if (weight == 1f)
            {
                for (int i = 0; i < siteCount; i++)
                {
                    triad = inputTriangles[i];
                    A     = triad.A; B = triad.B; C = triad.C;
                    outputVertices.Add((inputVertices[A] + inputVertices[B] + inputVertices[C]) / 3f);

                    connectedTriangles.Add(new UIntPair(A, B), i);
                    connectedTriangles.Add(new UIntPair(B, C), i);
                    connectedTriangles.Add(new UIntPair(C, A), i);
                }
            }
            else
            {
                for (int i = 0; i < siteCount; i++)
                {
                    triad = inputTriangles[i];
                    A     = triad.A; B = triad.B; C = triad.C;

                    centroid     = (inputVertices[A] + inputVertices[B] + inputVertices[C]) / 3f;
                    circumcenter = Circumcenter(ref triad, ref inputVertices);

                    outputVertices.Add(lerp(circumcenter, centroid, weight));

                    connectedTriangles.Add(new UIntPair(A, B), i);
                    connectedTriangles.Add(new UIntPair(B, C), i);
                    connectedTriangles.Add(new UIntPair(C, A), i);
                }
            }

            for (int i = 0; i < siteCount; i++)
            {
                triad = inputTriangles[i];
                A     = triad.A; B = triad.B; C = triad.C;

                outputSites.Add(A, i);
                outputSites.Add(B, i);
                outputSites.Add(C, i);

                neighbors.Clear();

                edge = new UIntPair(A, B);
                connectedTriangles.PushValues(ref edge, ref neighbors);
                edge = new UIntPair(B, C);
                connectedTriangles.PushValues(ref edge, ref neighbors);
                edge = new UIntPair(C, A);
                connectedTriangles.PushValues(ref edge, ref neighbors);

                for (int t = 0; t < neighbors.Length; t++)
                {
                    Ti = neighbors[t];
                    if (Ti == i)
                    {
                        continue;
                    }

                    edge = new UIntPair(Ti, i);

                    if (!uniqueEdges.TryGetValue(edge, out edgeIndex))
                    {
                        uniqueEdges.TryAdd(edge, outputEdges.Length);
                        outputEdges.Add(edge);
                    }
                }
            }
        }
コード例 #4
0
        public void Execute()
        {
            outputTriangles.Clear();
            NativeList <UIntPair> hole = new NativeList <UIntPair>(20, Allocator.Temp);

            float  m = 100f;
            float3 V, vA, vB, vC, bA, bB, bC, centroid;
            int    vCount = inputVertices.Length, A = vCount, B = vCount + 1, C = vCount + 2, D = vCount + 3, iA, iB, extraVCount = 3;
            Triad  triad;
            NativeArray <float3> vertices = new NativeArray <float3>(vCount + extraVCount, Allocator.Temp);

            #region Create enclosing quad

            float maxX = float.MinValue, maxY = float.MinValue, minX = float.MaxValue, minY = float.MaxValue;

            //Find the min-max positions
            for (int index = 0; index < vCount; index++)
            {
                V = inputVertices[index];
                vertices[index] = V;
                if (V.x > maxX)
                {
                    maxX = V.x;
                }
                else if (V.x < minX)
                {
                    minX = V.x;
                }
                if (V.y > maxY)
                {
                    maxY = V.y;
                }
                else if (V.y < minY)
                {
                    minY = V.y;
                }
            }

            //Offset min/max to ensure proper enclosure
            minX *= m; minY *= m; maxX *= m; maxY *= m;

            /*
             * bA = new float3(minX, maxY); bB = new float3(maxX, maxY);
             * bC = new float3(maxX, minY); bD = new float3(minX, minY);
             *
             * vertices[A] = bA; vertices[B] = bB;
             * vertices[C] = bC; vertices[D] = bD;
             *
             * Triad(out triad, A, B, C, ref vertices);
             * outputTriangles.Add(triad);
             *
             * Triad(out triad, A, C, D, ref vertices);
             * outputTriangles.Add(triad);
             */

            #region single enclosing triangle

            float width = maxX - minX, height = maxY - minY;
            centroid = new float3(minX + width * 0.5f, minY + 0.5f, 0f);

            bA = new float3(centroid.x - (width * 2f), minY - 0.5f, 0f); bB = new float3(centroid.x + (width * 2f), minY - 0.5f, 0f);
            bC = new float3(centroid.x, centroid.y - height * 0.5f + height * 2f, 0f);

            vertices[A] = bA; vertices[B] = bB;
            vertices[C] = bC;

            Triad(out triad, A, B, C, ref vertices);
            outputTriangles.Add(triad);

            #endregion

            #endregion

            int      triCount, eCount = 0, t = 0;
            bool     bAB = false, bBC = false, bCA = false, inc = false;
            UIntPair edge, AB, BC, CA, EE;

            for (int index = 0; index < vCount; index++)
            {
                V = vertices[index];

                #region bad triangles

                //Find & remove bad triangles in current triangulation, given the current vertex
                triCount = outputTriangles.Length;
                t        = 0;

                hole.Clear();

                for (int i = 0; i < triCount; i++)
                {
                    triad = outputTriangles[i];

                    //CircumcircleContainsXY
                    if (((V.x - triad.circumcenter.x) * (V.x - triad.circumcenter.x) + (V.y - triad.circumcenter.y) * (V.y - triad.circumcenter.y)) < triad.sqRadius)
                    {
                        //This is a bad triangle.
                        //Add edges forming the triangle to the list of hole boundaries
                        A  = triad.A; B = triad.B; C = triad.C;
                        AB = new UIntPair(A, B);
                        BC = new UIntPair(B, C);
                        CA = new UIntPair(C, A);

                        #region Loop

                        bAB    = false; bBC = false; bCA = false; inc = false;
                        eCount = hole.Length;
                        for (int ie = 0; ie < eCount; ie++)
                        {
                            EE = hole[ie];

                            //if (EE.d != 0) { continue; }

                            inc = false;
                            iA  = EE.x; iB = EE.y;

                            if (!bAB && ((iA == A && iB == B) || (iA == B && iB == A)))
                            {
                                inc = bAB = true;
                            }
                            else if (!bBC && ((iA == B && iB == C) || (iA == C && iB == B)))
                            {
                                inc = bBC = true;
                            }
                            else if (!bCA && ((iA == C && iB == A) || (iA == A && iB == C)))
                            {
                                inc = bCA = true;
                            }

                            if (inc)
                            {
                                EE.d++;
                                hole[ie] = EE;
                            }
                        }

                        if (!bAB)
                        {
                            hole.Add(AB);
                        }
                        if (!bBC)
                        {
                            hole.Add(BC);
                        }
                        if (!bCA)
                        {
                            hole.Add(CA);
                        }

                        #endregion

                        //If constructing Voronoi, remove triangle from each point 'linked' triangles
                        //(do this here, as triad gets removed.)
                    }
                    else
                    {
                        //Move good triangle to the next good index
                        outputTriangles[t] = triad;
                        t++;
                    }
                }

                //Truncate triangulation
                outputTriangles.ResizeUninitialized(t);
                triCount = t;

                #endregion

                #region new triangles

                eCount = hole.Length;

                for (int e = 0; e < eCount; e++)
                {
                    edge = hole[e];
                    if (edge.d != 0)
                    {
                        continue;
                    }
                    A  = edge.x; B = edge.y;
                    vA = vertices[A]; vB = vertices[B];

                    Triad(out triad, index, A, B, ref vertices);

                    outputTriangles.Add(triad);
                }

                #endregion

                hole.Clear();
            }

            #region wrap up

            //Remove all triangles with a vertex superior to initial vertice count
            //as they are linked to initial 4 boundaries vertices
            triCount = outputTriangles.Length;
            t        = 0;
            int      extraIndex = -1;
            UIntPair hullEdge;

            if (computeTriadCentroid)
            {
                for (int i = 0; i < triCount; i++)
                {
                    triad      = outputTriangles[i];
                    A          = triad.A; B = triad.B; C = triad.C;
                    extraIndex = -1;

                    if (A >= vCount)
                    {
                        extraIndex = A;
                    }
                    else if (B >= vCount)
                    {
                        extraIndex = B;
                    }
                    else if (C >= vCount)
                    {
                        extraIndex = C;
                    }

                    if (extraIndex != -1)
                    {
                        //Add opposite edge to unordered hull
                        hullEdge = triad.OppositeEdge(extraIndex).ascending;
                        outputUnorderedHullEdges.TryAdd(hullEdge.x, hullEdge);
                        outputHullVertices.Add(hullEdge.x);
                        continue;
                    }

                    vA             = vertices[triad.A];
                    vB             = vertices[triad.B];
                    vC             = vertices[triad.C];
                    triad.centroid = (vA + vB + vC) / 3f;

                    outputTriangles[t] = triad;
                    t++;
                }
            }
            else
            {
                for (int i = 0; i < triCount; i++)
                {
                    triad      = outputTriangles[i];
                    A          = triad.A; B = triad.B; C = triad.C;
                    extraIndex = -1;

                    if (A >= vCount)
                    {
                        extraIndex = A;
                    }
                    else if (B >= vCount)
                    {
                        extraIndex = B;
                    }
                    else if (C >= vCount)
                    {
                        extraIndex = C;
                    }

                    if (extraIndex != -1)
                    {
                        //Add opposite edge to unordered hull
                        hullEdge = triad.OppositeEdge(extraIndex).ascending;
                        outputUnorderedHullEdges.TryAdd(hullEdge.x, hullEdge);
                        outputHullVertices.Add(hullEdge.x);
                        continue;
                    }

                    outputTriangles[t] = triad;
                    t++;
                }
            }

            outputTriangles.ResizeUninitialized(t);

            #endregion

            hole.Dispose();
        }
コード例 #5
0
        /// <summary>
        /// Bowyer-Watson triangulation algorithm with respect to Delaunay condition
        /// </summary>
        /// <param name="inputVertices"></param>
        /// <returns></returns>
        public static void Process(
            List <Vertex> inputVertices,
            List <Triad> outputTriangles,
            List <UIntPair> outputEdges = null)
        {
            vertices = inputVertices;

            float3 V, vA, vB, centroid;
            int    vCount = vertices.Count, A = vCount, B = vCount + 1, C = vCount + 2, D = vCount + 3, iA, iB;
            Triad  triad;

            outputTriangles.Clear();
            outputTriangles.Capacity = vCount * 3;

            #region Create enclosing quad

            float maxX = float.MinValue, maxY = float.MinValue, minX = float.MaxValue, minY = float.MaxValue;

            //Find the min-max positions
            for (int index = 0; index < vCount; index++)
            {
                V = vertices[index].pos;
                if (V.x > maxX)
                {
                    maxX = V.x;
                }
                else if (V.x < minX)
                {
                    minX = V.x;
                }
                if (V.y > maxY)
                {
                    maxY = V.y;
                }
                else if (V.y < minY)
                {
                    minY = V.y;
                }
            }

            //Offset min/max to ensure proper enclosure
            minX *= m; minY *= m; maxX *= m; maxY *= m;

            /*
             *
             * bA.v = new float3(minX, maxY); bB.v = new float3(maxX, maxY);
             * bC.v = new float3(maxX, minY); bD.v = new float3(minX, minY);
             *
             * vertices[A] = bA; vertices[B] = bB;
             * vertices[C] = bC; vertices[D] = bD;
             *
             * Triad(out triad, A, B, C);
             * outputTriangles.Add(triad);
             *
             * Triad(out triad, A, C, D);
             * outputTriangles.Add(triad);
             *
             */

            #region single enclosing triangle

            float width = maxX - minX, height = maxY - minY;
            centroid = new float3(minX + width * 0.5f, minY + 0.5f, 0f);

            bA.pos = new float3(centroid.x - (width * 2f), minY - 0.5f, 0f); bB.pos = new float3(centroid.x + (width * 2f), minY - 0.5f, 0f);
            bC.pos = new float3(centroid.x, centroid.y - height * 0.5f + height * 2f, 0f);

            vertices.Add(bA); vertices.Add(bB);
            vertices.Add(bC);

            Triad(out triad, A, B, C);
            outputTriangles.Add(triad);

            #endregion


            #endregion

            int      triCount, eCount = 0, t = 0;
            bool     bAB = false, bBC = false, bCA = false, inc = false;
            UIntPair edge, AB, BC, CA, EE;

            for (int index = 0; index < vCount; index++)
            {
                V = vertices[index].pos;

                #region bad triangles

                //Find & remove bad triangles in current triangulation, given the current vertex
                triCount = outputTriangles.Count;
                t        = 0;

                hole.Clear();

                for (int i = 0; i < triCount; i++)
                {
                    triad = outputTriangles[i];

                    //CircumcircleContainsXY
                    if (((V.x - triad.circumcenter.x) * (V.x - triad.circumcenter.x) + (V.y - triad.circumcenter.y) * (V.y - triad.circumcenter.y)) < triad.sqRadius)
                    {
                        //This is a bad triangle.
                        //Add edges forming the triangle to the list of hole boundaries
                        A  = triad.A; B = triad.B; C = triad.C;
                        AB = new UIntPair(A, B);
                        BC = new UIntPair(B, C);
                        CA = new UIntPair(C, A);

                        #region Loop

                        bAB    = false; bBC = false; bCA = false; inc = false;
                        eCount = hole.Count;
                        for (int ie = 0; ie < eCount; ie++)
                        {
                            EE = hole[ie];

                            inc = false;
                            iA  = EE.x; iB = EE.y;

                            if (!bAB && ((iA == A && iB == B) || (iA == B && iB == A)))
                            {
                                inc = bAB = true;
                            }
                            else if (!bBC && ((iA == B && iB == C) || (iA == C && iB == B)))
                            {
                                inc = bBC = true;
                            }
                            else if (!bCA && ((iA == C && iB == A) || (iA == A && iB == C)))
                            {
                                inc = bCA = true;
                            }

                            if (inc)
                            {
                                EE.d++;//= EE.d + 1;
                                hole[ie] = EE;
                            }
                        }

                        if (!bAB)
                        {
                            hole.Add(AB);
                        }
                        if (!bBC)
                        {
                            hole.Add(BC);
                        }
                        if (!bCA)
                        {
                            hole.Add(CA);
                        }

                        #endregion

                        //If constructing Voronoi, remove triangle from each point 'linked' triangles
                        //(do this here, as triad gets removed.)
                    }
                    else
                    {
                        //Move good triangle to the next good index
                        outputTriangles[t] = triad;
                        t++;
                    }
                }

                //Truncate triangulation
                outputTriangles.RemoveRange(t, triCount - t);

                #endregion

                #region new triangles

                eCount = hole.Count;
                for (int e = 0; e < eCount; e++)
                {
                    edge = hole[e];

                    if (edge.d != 0)
                    {
                        continue;
                    }

                    A  = edge.x; B = edge.y;
                    vA = vertices[A]; vB = vertices[B];

                    Triad(out triad, index, A, B);

                    outputTriangles.Add(triad);
                }

                #endregion

                hole.Clear();
            }

            #region wrap up

            //Remove the extra vertices introduced earlier
            vertices.RemoveRange(vCount, extraVCount);

            //Remove all triangles with a vertex superior to initial vertice count
            //as they are linked to initial boundaries vertices
            triCount = outputTriangles.Count;
            t        = 0;
            for (int i = 0; i < triCount; i++)
            {
                triad = outputTriangles[i];
                A     = triad.A; B = triad.B; C = triad.C;

                if (A >= vCount || B >= vCount || C >= vCount)
                {
                    continue;
                }

                outputTriangles[t] = triad;
                t++;
            }

            outputTriangles.RemoveRange(t, triCount - t);

            vertices = null;

            #endregion

            #region edge output

            //If requested, compute edges based on cleaned up triangulation
            if (outputEdges != null)
            {
                outputEdges.Clear();

                triCount = outputTriangles.Count;
                for (int i = 0; i < triCount; i++)
                {
                    triad = outputTriangles[i];

                    //This is a bad triangle.
                    //Add edges forming the triangle to the list of hole boundaries
                    A  = triad.A; B = triad.B; C = triad.C;
                    AB = new UIntPair(A, B);
                    BC = new UIntPair(B, C);
                    CA = new UIntPair(C, A);

                    #region Loop

                    bAB    = false; bBC = false; bCA = false;
                    eCount = outputEdges.Count;
                    for (int ie = 0; ie < eCount; ie++)
                    {
                        EE = outputEdges[ie];

                        inc = false;
                        iA  = EE.x; iB = EE.y;

                        if (!bAB && ((iA == A && iB == B) || (iA == B && iB == A)))
                        {
                            bAB = true;
                        }
                        else if (!bBC && ((iA == B && iB == C) || (iA == C && iB == B)))
                        {
                            bBC = true;
                        }
                        else if (!bCA && ((iA == C && iB == A) || (iA == A && iB == C)))
                        {
                            bCA = true;
                        }
                    }

                    if (!bAB)
                    {
                        outputEdges.Add(AB);
                    }
                    if (!bBC)
                    {
                        outputEdges.Add(BC);
                    }
                    if (!bCA)
                    {
                        outputEdges.Add(CA);
                    }

                    #endregion
                }
            }

            #endregion
        }
コード例 #6
0
        public void Execute()
        {
            int      A, B, C, vCount = inputVertices.Length, triCount = inputTriangles.Length;
            float3   vA, vB, vC;
            float    AB, BC, CA;
            UIntPair edge;
            Triad    triad;
            bool     tooLong;
            NativeHashMap <UIntPair, bool> longuestEdges = new NativeHashMap <UIntPair, bool>(triCount * 3, Allocator.Temp);
            NativeHashMap <UIntPair, bool> uniqueEdges   = new NativeHashMap <UIntPair, bool>(triCount * 3, Allocator.Temp);

            for (int i = 0; i < triCount; i++)
            {
                triad = inputTriangles[i];
                A     = triad.A; B = triad.B; C = triad.C;
                vA    = inputVertices[A]; vB = inputVertices[B]; vC = inputVertices[C];
                AB    = distancesq(vA, vB);
                BC    = distancesq(vB, vC);
                CA    = distancesq(vC, vA);

                if (AB > BC && AB > CA)
                {
                    edge = new UIntPair(A, B);
                }
                else if (BC > AB && BC > CA)
                {
                    edge = new UIntPair(B, C);
                }
                else// if (CA > AB && CA > BC)
                {
                    edge = new UIntPair(C, A);
                }

                longuestEdges.TryAdd(edge, true);
            }

            for (int i = 0; i < triCount; i++)
            {
                triad = inputTriangles[i];
                A     = triad.A; B = triad.B; C = triad.C;

                edge = new UIntPair(A, B);
                if (!longuestEdges.TryGetValue(edge, out tooLong) &&
                    !uniqueEdges.TryGetValue(edge, out tooLong))
                {
                    outputConnections.Add(edge.y, edge.x);
                    outputConnections.Add(edge.x, edge.y);
                    outputEdges.Add(edge);
                }

                edge = new UIntPair(B, C);
                if (!longuestEdges.TryGetValue(edge, out tooLong) &&
                    !uniqueEdges.TryGetValue(edge, out tooLong))
                {
                    outputConnections.Add(edge.y, edge.x);
                    outputConnections.Add(edge.x, edge.y);
                    outputEdges.Add(edge);
                }

                edge = new UIntPair(C, A);
                if (!longuestEdges.TryGetValue(edge, out tooLong) &&
                    !uniqueEdges.TryGetValue(edge, out tooLong))
                {
                    outputConnections.Add(edge.y, edge.x);
                    outputConnections.Add(edge.x, edge.y);
                    outputEdges.Add(edge);
                }
            }
        }