private static int MergeDuplicatePositions(IList <Vector3F> positions, float positionTolerance, int[] positionRemap) { Debug.Assert(positions != null); Debug.Assert(positions.Count > 0); Debug.Assert(positionTolerance > 0); Debug.Assert(positionRemap == null || positionRemap.Length == positions.Count); // Create working data. int numberOfVertices = positions.Count; var data = new WeldVertex[numberOfVertices]; for (int i = 0; i < numberOfVertices; i++) { Vector3F position = positions[i]; data[i].Position = position; data[i].OriginalIndex = i; data[i].SortValue = Math.Abs(position.X) + Math.Abs(position.Y) + Math.Abs(position.Z); data[i].MergedIndex = -1; } // Sort positions by absolute component sum of position |X|+|Y|+|Z|. Array.Sort(data, WeldVertex.CompareSortValue); int numberOfMergedVertices = 0; // Loop over positions. Try to merge each vertex with the next positions in the array. for (int i = 0; i < numberOfVertices; i++) { // For positions that have already been merged, the index was set to > -1. if (data[i].MergedIndex >= 0) { // Vertex is a duplicate. - Nothing to do. continue; } // Now, we compare vertex i against the next positions in the array. for (int j = i + 1; j < numberOfVertices; j++) { // We can stop comparing if the SortValue differs by more than 3 * epsilon. if (data[j].SortValue - data[i].SortValue > 3 * positionTolerance) { break; } //if (Vector3F.AreNumericallyEqual(data[i].Position, data[j].Position, positionTolerance)) // Optimized version: (Probably does not work for infinite float values!) float delta = Math.Abs(data[i].Position.X - data[j].Position.X); if (delta <= positionTolerance) { delta = Math.Abs(data[i].Position.Y - data[j].Position.Y); if (delta <= positionTolerance) { delta = Math.Abs(data[i].Position.Z - data[j].Position.Z); if (delta <= positionTolerance) { // Vertex positions are near each other and should be merged. numberOfMergedVertices++; data[j].MergedIndex = data[i].OriginalIndex; } } } } } if (numberOfMergedVertices == 0) { return(0); } // Sort by original index. Array.Sort(data, WeldVertex.CompareOriginalIndex); // Rebuild positions (omitting the merged positions). positions.Clear(); if (positionRemap == null) { for (int i = 0; i < numberOfVertices; i++) { if (data[i].MergedIndex < 0) { positions.Add(data[i].Position); } } } else { // Rebuild positions and at the same time we fill the position remap table. for (int i = 0; i < numberOfVertices; i++) { if (data[i].MergedIndex < 0) { positionRemap[i] = positions.Count; positions.Add(data[i].Position); } else { positionRemap[i] = -1; } } // Now, fill in the other entries in the index redirection table. for (int i = 0; i < numberOfVertices; i++) { if (data[i].MergedIndex >= 0) { positionRemap[i] = positionRemap[data[i].MergedIndex]; } Debug.Assert(positionRemap[i] != -1); } } return(numberOfMergedVertices); }
public static int CompareOriginalIndex(WeldVertex v0, WeldVertex v1) { return(v0.OriginalIndex.CompareTo(v1.OriginalIndex)); }
public int MergedIndex; // >= 0 if this vertex was merged. public static int CompareSortValue(WeldVertex v0, WeldVertex v1) { return(v0.SortValue.CompareTo(v1.SortValue)); }
public static int CompareSortValue(WeldVertex v0, WeldVertex v1) { return v0.SortValue.CompareTo(v1.SortValue); }
public float SortValue; // Absolute component sum of position: |X|+|Y|+|Z| #endregion Fields #region Methods public static int CompareOriginalIndex(WeldVertex v0, WeldVertex v1) { return v0.OriginalIndex.CompareTo(v1.OriginalIndex); }
private static int MergeDuplicatePositions(IList<Vector3F> positions, float positionTolerance, int[] positionRemap) { Debug.Assert(positions != null); Debug.Assert(positions.Count > 0); Debug.Assert(positionTolerance > 0); Debug.Assert(positionRemap == null || positionRemap.Length == positions.Count); // Create working data. int numberOfVertices = positions.Count; var data = new WeldVertex[numberOfVertices]; for (int i = 0; i < numberOfVertices; i++) { Vector3F position = positions[i]; data[i].Position = position; data[i].OriginalIndex = i; data[i].SortValue = Math.Abs(position.X) + Math.Abs(position.Y) + Math.Abs(position.Z); data[i].MergedIndex = -1; } // Sort positions by absolute component sum of position |X|+|Y|+|Z|. Array.Sort(data, WeldVertex.CompareSortValue); int numberOfMergedVertices = 0; // Loop over positions. Try to merge each vertex with the next positions in the array. for (int i = 0; i < numberOfVertices; i++) { // For positions that have already been merged, the index was set to > -1. if (data[i].MergedIndex >= 0) { // Vertex is a duplicate. - Nothing to do. continue; } // Now, we compare vertex i against the next positions in the array. for (int j = i + 1; j < numberOfVertices; j++) { // We can stop comparing if the SortValue differs by more than 3 * epsilon. if (data[j].SortValue - data[i].SortValue > 3 * positionTolerance) break; //if (Vector3F.AreNumericallyEqual(data[i].Position, data[j].Position, positionTolerance)) // Optimized version: (Probably does not work for infinite float values!) float delta = Math.Abs(data[i].Position.X - data[j].Position.X); if (delta <= positionTolerance) { delta = Math.Abs(data[i].Position.Y - data[j].Position.Y); if (delta <= positionTolerance) { delta = Math.Abs(data[i].Position.Z - data[j].Position.Z); if (delta <= positionTolerance) { // Vertex positions are near each other and should be merged. numberOfMergedVertices++; data[j].MergedIndex = data[i].OriginalIndex; } } } } } if (numberOfMergedVertices == 0) return 0; // Sort by original index. Array.Sort(data, WeldVertex.CompareOriginalIndex); // Rebuild positions (omitting the merged positions). positions.Clear(); if (positionRemap == null) { for (int i = 0; i < numberOfVertices; i++) if (data[i].MergedIndex < 0) positions.Add(data[i].Position); } else { // Rebuild positions and at the same time we fill the position remap table. for (int i = 0; i < numberOfVertices; i++) { if (data[i].MergedIndex < 0) { positionRemap[i] = positions.Count; positions.Add(data[i].Position); } else { positionRemap[i] = -1; } } // Now, fill in the other entries in the index redirection table. for (int i = 0; i < numberOfVertices; i++) { if (data[i].MergedIndex >= 0) positionRemap[i] = positionRemap[data[i].MergedIndex]; Debug.Assert(positionRemap[i] != -1); } } return numberOfMergedVertices; }