/// <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); } } }
public static Triangle FromBasicTriangle(BasicTriangle basicTriangle, List <Vector3> dataCloud) { return(new Triangle(dataCloud[basicTriangle.v[0]], dataCloud[basicTriangle.v[1]], dataCloud[basicTriangle.v[2]])); }