private void CreateInitialSimplex() { List <int> list = FindInitialPoints(); int[] array = new int[NumOfDimensions + 1]; for (int i = 0; i < NumOfDimensions + 1; i++) { int[] array2 = new int[NumOfDimensions]; int j = 0; int num = 0; for (; j <= NumOfDimensions; j++) { if (i != j) { if (j == list.Count) { int num2 = 0; num2++; } int num3 = list[j]; array2[num++] = num3; } } ConvexFaceInternal convexFaceInternal = FacePool[ObjectManager.GetFace()]; convexFaceInternal.Vertices = array2; Array.Sort(array2); mathHelper.CalculateFacePlane(convexFaceInternal, Center); array[i] = convexFaceInternal.Index; } for (int k = 0; k < NumOfDimensions; k++) { for (int l = k + 1; l < NumOfDimensions + 1; l++) { UpdateAdjacency(FacePool[array[k]], FacePool[array[l]]); } } int[] array3 = array; foreach (int num5 in array3) { ConvexFaceInternal convexFaceInternal2 = FacePool[num5]; FindBeyondVertices(convexFaceInternal2); if (convexFaceInternal2.VerticesBeyond.Count == 0) { ConvexFaces.Add(convexFaceInternal2.Index); } else { UnprocessedFaces.Add(convexFaceInternal2); } } foreach (int item in list) { VertexVisited[item] = false; } }
/// <summary> /// Create the first faces from (dimension + 1) vertices. /// </summary> /// <returns></returns> int[] CreateInitialHull(List <int> initialPoints) { var faces = new int[Dimension + 1]; for (var i = 0; i < Dimension + 1; i++) { var vertices = new int[Dimension]; for (int j = 0, k = 0; j <= Dimension; j++) { if (i != j) { vertices[k++] = initialPoints[j]; } } var newFace = FacePool[ObjectManager.GetFace()]; newFace.Vertices = vertices; Array.Sort(vertices); MathHelper.CalculateFacePlane(newFace, Center); faces[i] = newFace.Index; } // update the adjacency (check all pairs of faces) for (var i = 0; i < Dimension; i++) { for (var j = i + 1; j < Dimension + 1; j++) { UpdateAdjacency(FacePool[faces[i]], FacePool[faces[j]]); } } return(faces); }
/// <summary> /// Init the hull if Vertices.Length == Dimension. /// </summary> void InitSingle() { var vertices = new int[Dimension]; for (int i = 0; i < Vertices.Length; i++) { vertices[i] = i; } var newFace = FacePool[ObjectManager.GetFace()]; newFace.Vertices = vertices; Array.Sort(vertices); MathHelper.CalculateFacePlane(newFace, Center); // Make sure the normal point downwards in case this is used for triangulation if (newFace.Normal[Dimension - 1] >= 0.0) { for (int i = 0; i < Dimension; i++) { newFace.Normal[i] *= -1.0; } newFace.Offset = -newFace.Offset; newFace.IsNormalFlipped = !newFace.IsNormalFlipped; } ConvexFaces.Add(newFace.Index); }
/// <summary> /// Find the (dimension+1) initial points and create the simplexes. /// Creates the initial simplex of n+1 vertices by using points from the bounding box. /// Special care is taken to ensure that the vertices chosen do not result in a degenerate shape /// where vertices are collinear (co-planar, etc). This would technically be resolved when additional /// vertices are checked in the main loop, but: 1) a degenerate simplex would not eliminate any other /// vertices (thus no savings there), 2) the creation of the face normal is prone to error. /// </summary> private void CreateInitialSimplex() { var initialPoints = FindInitialPoints(); #region Create the first faces from (dimension + 1) vertices. var faces = new int[NumOfDimensions + 1]; for (var i = 0; i < NumOfDimensions + 1; i++) { var vertices = new int[NumOfDimensions]; for (int j = 0, k = 0; j <= NumOfDimensions; j++) { if (i != j) { vertices[k++] = initialPoints[j]; } } var newFace = FacePool[ObjectManager.GetFace()]; newFace.Vertices = vertices; Array.Sort(vertices); mathHelper.CalculateFacePlane(newFace, Center); faces[i] = newFace.Index; } // update the adjacency (check all pairs of faces) for (var i = 0; i < NumOfDimensions; i++) { for (var j = i + 1; j < NumOfDimensions + 1; j++) { UpdateAdjacency(FacePool[faces[i]], FacePool[faces[j]]); } } #endregion #region Init the vertex beyond buffers. foreach (var faceIndex in faces) { var face = FacePool[faceIndex]; FindBeyondVertices(face); if (face.VerticesBeyond.Count == 0) { ConvexFaces.Add(face.Index); // The face is on the hull } else { UnprocessedFaces.Add(face); } } #endregion // Set all vertices to false (unvisited). foreach (var vertex in initialPoints) { VertexVisited[vertex] = false; } }
/// <summary> /// Removes the faces "covered" by the current vertex and adds the newly created ones. /// </summary> /// <returns><c>true</c> if possible, <c>false</c> otherwise.</returns> private bool CreateCone() { var currentVertexIndex = CurrentVertex; ConeFaceBuffer.Clear(); for (var fIndex = 0; fIndex < AffectedFaceBuffer.Count; fIndex++) { var oldFaceIndex = AffectedFaceBuffer[fIndex]; var oldFace = FacePool[oldFaceIndex]; // Find the faces that need to be updated var updateCount = 0; for (var i = 0; i < NumOfDimensions; i++) { var af = oldFace.AdjacentFaces[i]; if (!AffectedFaceFlags[af]) // Tag == false when oldFaces does not contain af { UpdateBuffer[updateCount] = af; UpdateIndices[updateCount] = i; ++updateCount; } } for (var i = 0; i < updateCount; i++) { var adjacentFace = FacePool[UpdateBuffer[i]]; var oldFaceAdjacentIndex = 0; var adjFaceAdjacency = adjacentFace.AdjacentFaces; for (var j = 0; j < adjFaceAdjacency.Length; j++) { if (oldFaceIndex == adjFaceAdjacency[j]) { oldFaceAdjacentIndex = j; break; } } var forbidden = UpdateIndices[i]; // Index of the face that corresponds to this adjacent face var newFaceIndex = ObjectManager.GetFace(); var newFace = FacePool[newFaceIndex]; var vertices = newFace.Vertices; for (var j = 0; j < NumOfDimensions; j++) { vertices[j] = oldFace.Vertices[j]; } var oldVertexIndex = vertices[forbidden]; int orderedPivotIndex; // correct the ordering if (currentVertexIndex < oldVertexIndex) { orderedPivotIndex = 0; for (var j = forbidden - 1; j >= 0; j--) { if (vertices[j] > currentVertexIndex) { vertices[j + 1] = vertices[j]; } else { orderedPivotIndex = j + 1; break; } } } else { orderedPivotIndex = NumOfDimensions - 1; for (var j = forbidden + 1; j < NumOfDimensions; j++) { if (vertices[j] < currentVertexIndex) { vertices[j - 1] = vertices[j]; } else { orderedPivotIndex = j - 1; break; } } } vertices[orderedPivotIndex] = CurrentVertex; if (!mathHelper.CalculateFacePlane(newFace, InsidePoint)) { return(false); } ConeFaceBuffer.Add(MakeDeferredFace(newFace, orderedPivotIndex, adjacentFace, oldFaceAdjacentIndex, oldFace)); } } return(true); }
/// <summary> /// Removes the faces "covered" by the current vertex and adds the newly created ones. /// </summary> private bool CreateCone() { var currentVertexIndex = CurrentVertex.Index; ConeFaceBuffer.Clear(); for (int fIndex = 0; fIndex < AffectedFaceBuffer.Count; fIndex++) { var oldFace = AffectedFaceBuffer[fIndex]; // Find the faces that need to be updated int updateCount = 0; for (int i = 0; i < Dimension; i++) { var af = oldFace.AdjacentFaces[i]; if (af.Tag == 0) // Tag == 0 when oldFaces does not contain af { UpdateBuffer[updateCount] = af; UpdateIndices[updateCount] = i; ++updateCount; } } for (int i = 0; i < updateCount; i++) { var adjacentFace = UpdateBuffer[i]; int oldFaceAdjacentIndex = 0; var adjFaceAdjacency = adjacentFace.AdjacentFaces; for (int j = 0; j < Dimension; j++) { if (object.ReferenceEquals(oldFace, adjFaceAdjacency[j])) { oldFaceAdjacentIndex = j; break; } } var forbidden = UpdateIndices[i]; // Index of the face that corresponds to this adjacent face ConvexFaceInternal newFace; int oldVertexIndex; VertexWrap[] vertices; newFace = ObjectManager.GetFace(); vertices = newFace.Vertices; for (int j = 0; j < Dimension; j++) { vertices[j] = oldFace.Vertices[j]; } oldVertexIndex = vertices[forbidden].Index; int orderedPivotIndex; // correct the ordering if (currentVertexIndex < oldVertexIndex) { orderedPivotIndex = 0; for (int j = forbidden - 1; j >= 0; j--) { if (vertices[j].Index > currentVertexIndex) { vertices[j + 1] = vertices[j]; } else { orderedPivotIndex = j + 1; break; } } } else { orderedPivotIndex = Dimension - 1; for (int j = forbidden + 1; j < Dimension; j++) { if (vertices[j].Index < currentVertexIndex) { vertices[j - 1] = vertices[j]; } else { orderedPivotIndex = j - 1; break; } } } vertices[orderedPivotIndex] = CurrentVertex; if (!CalculateFacePlane(newFace)) { return(false); } ConeFaceBuffer.Add(MakeDeferredFace(newFace, orderedPivotIndex, adjacentFace, oldFaceAdjacentIndex, oldFace)); } } return(true); }