Browse Source

added Surface.remove_unused_vertices()

Fabian Peter Hammerle 5 years ago
parent
commit
c86a00470d
2 changed files with 74 additions and 0 deletions
  1. 11 0
      freesurfer_surface/__init__.py
  2. 63 0
      tests/test_surface.py

+ 11 - 0
freesurfer_surface/__init__.py

@@ -484,3 +484,14 @@ class Surface:
             for vertex_index in triangle.vertex_indices:
                 vertex_indices.discard(vertex_index)
         return vertex_indices
+
+    def remove_unused_vertices(self) -> None:
+        vertex_index_conversion = [0] * len(self.vertices)
+        for vertex_index in sorted(self._unused_vertices(), reverse=True):
+            del self.vertices[vertex_index]
+            vertex_index_conversion[vertex_index] -= 1
+        vertex_index_conversion = numpy.cumsum(vertex_index_conversion)
+        for triangle_index in range(len(self.triangles)):
+            self.triangles[triangle_index] \
+                = Triangle(map(lambda i: i + vertex_index_conversion[i],
+                               self.triangles[triangle_index].vertex_indices))

+ 63 - 0
tests/test_surface.py

@@ -430,3 +430,66 @@ def test__unused_vertices_real():
     surface.triangles = list(filter(lambda t: 42 not in t.vertex_indices,
                                     surface.triangles))
     assert surface._unused_vertices() == {42}
+
+
+def test_remove_unused_vertices_all():
+    surface = Surface()
+    for i in range(5):
+        surface.add_vertex(Vertex(i, i, i))
+    assert len(surface.vertices) == 5
+    surface.remove_unused_vertices()
+    assert not surface.vertices
+    surface.remove_unused_vertices()
+    assert not surface.vertices
+
+
+def test_remove_unused_vertices_almost_all():
+    surface = Surface()
+    for i in range(5):
+        surface.add_vertex(Vertex(i, i, i))
+    assert len(surface.vertices) == 5
+    surface.triangles.append(Triangle((0, 2, 3)))
+    surface.remove_unused_vertices()
+    assert len(surface.vertices) == 3
+    assert surface.vertices[0] == pytest.approx(Vertex(0, 0, 0))
+    assert surface.vertices[1] == pytest.approx(Vertex(2, 2, 2))
+    assert surface.vertices[2] == pytest.approx(Vertex(3, 3, 3))
+    assert len(surface.triangles) == 1
+    assert surface.triangles[0] == Triangle((0, 1, 2))
+    del surface.triangles[0]
+    surface.remove_unused_vertices()
+    assert not surface.vertices
+
+
+def test_remove_unused_vertices_some():
+    surface = Surface()
+    for i in range(9):
+        surface.add_vertex(Vertex(i, i, i))
+    surface.triangles.append(Triangle((0, 2, 3)))
+    surface.triangles.append(Triangle((3, 4, 5)))
+    surface.triangles.append(Triangle((3, 2, 5)))
+    surface.triangles.append(Triangle((3, 2, 8)))
+    surface.remove_unused_vertices()
+    assert len(surface.vertices) == 6
+    assert surface.vertices[0] == pytest.approx(Vertex(0, 0, 0))
+    assert surface.vertices[1] == pytest.approx(Vertex(2, 2, 2))
+    assert surface.vertices[2] == pytest.approx(Vertex(3, 3, 3))
+    assert surface.vertices[3] == pytest.approx(Vertex(4, 4, 4))
+    assert surface.vertices[4] == pytest.approx(Vertex(5, 5, 5))
+    assert surface.vertices[5] == pytest.approx(Vertex(8, 8, 8))
+    assert len(surface.triangles) == 4
+    assert surface.triangles[0] == Triangle((0, 1, 2))
+    assert surface.triangles[1] == Triangle((2, 3, 4))
+    assert surface.triangles[2] == Triangle((2, 1, 4))
+    assert surface.triangles[3] == Triangle((2, 1, 5))
+    surface.remove_unused_vertices()
+    assert len(surface.triangles) == 4
+
+
+def test_remove_unused_vertices_none():
+    surface = Surface.read_triangular(SURFACE_FILE_PATH)
+    assert len(surface.vertices) == 155622
+    assert len(surface.triangles) == 311240
+    surface.remove_unused_vertices()
+    assert len(surface.vertices) == 155622
+    assert len(surface.triangles) == 311240