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 } }
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; }
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); } } } }
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(); }
/// <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 }
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); } } }