@@ -231,6 +231,14 @@ def is_iterable_and_sized(obj):
231231 return isinstance (obj , Iterable ) and isinstance (obj , Sized )
232232
233233
234+ def _flat_simplices (coords ):
235+ """Yield the intervals of a 1D triangulation in sorted coordinate order."""
236+ sorted_indices = sorted (range (len (coords )), key = coords .__getitem__ )
237+ for left , right in zip (sorted_indices , sorted_indices [1 :]):
238+ if coords [left ] != coords [right ]:
239+ yield left , right
240+
241+
234242def simplex_volume_in_embedding (vertices ) -> float :
235243 """Calculate the volume of a simplex in a higher dimensional embedding.
236244 That is: dim > len(vertices) - 1. For example if you would like to know the
@@ -257,12 +265,13 @@ def simplex_volume_in_embedding(vertices) -> float:
257265 # Modified from https://codereview.stackexchange.com/questions/77593/calculating-the-volume-of-a-tetrahedron
258266
259267 vertices = asarray (vertices , dtype = float )
260- if len (vertices ) == 2 :
261- # 1-simplex (line segment): volume is the Euclidean distance
268+ num_vertices = len (vertices )
269+ if num_vertices == 2 :
270+ # A 1-simplex is just a line segment.
262271 return float (norm (vertices [1 ] - vertices [0 ]))
263272
264- dim = len (vertices [0 ])
265- if dim == 2 :
273+ embedding_dim = len (vertices [0 ])
274+ if embedding_dim == 2 :
266275 # Heron's formula
267276 a , b , c = scipy .spatial .distance .pdist (vertices , metric = "euclidean" )
268277 s = 0.5 * (a + b + c )
@@ -272,13 +281,12 @@ def simplex_volume_in_embedding(vertices) -> float:
272281 sq_dists = scipy .spatial .distance .pdist (vertices , metric = "sqeuclidean" )
273282
274283 # Add border while compressed
275- num_verts = scipy .spatial .distance .num_obs_y (sq_dists )
276- bordered = concatenate ((ones (num_verts ), sq_dists ))
284+ bordered = concatenate ((ones (num_vertices ), sq_dists ))
277285
278286 # Make matrix and find volume
279287 sq_dists_mat = scipy .spatial .distance .squareform (bordered )
280288
281- coeff = - ((- 2 ) ** (num_verts - 1 )) * factorial (num_verts - 1 ) ** 2
289+ coeff = - ((- 2 ) ** (num_vertices - 1 )) * factorial (num_vertices - 1 ) ** 2
282290 vol_square = fast_det (sq_dists_mat ) / coeff
283291
284292 if vol_square < 0 :
@@ -346,19 +354,14 @@ def __init__(self, coords):
346354 self .vertex_to_simplices = [set () for _ in coords ]
347355
348356 if dim == 1 :
349- # For 1D, sort points and create intervals as simplices,
350- # skipping adjacent duplicates to avoid degenerate zero-volume simplices
351- sorted_indices = sorted (range (len (coords )), key = lambda i : coords [i ])
352- for i in range (len (sorted_indices ) - 1 ):
353- if coords [sorted_indices [i ]] == coords [sorted_indices [i + 1 ]]:
354- continue
355- self .add_simplex ((sorted_indices [i ], sorted_indices [i + 1 ]))
357+ simplices = _flat_simplices (coords )
356358 else :
357- # find a Delaunay triangulation to start with, then we will throw it
358- # away and continue with our own algorithm
359- initial_tri = scipy .spatial .Delaunay (coords )
360- for simplex in initial_tri .simplices :
361- self .add_simplex (simplex )
359+ # Find a Delaunay triangulation to start with, then we will throw it
360+ # away and continue with our own algorithm.
361+ simplices = scipy .spatial .Delaunay (coords ).simplices
362+
363+ for simplex in simplices :
364+ self .add_simplex (simplex )
362365
363366 def delete_simplex (self , simplex ):
364367 simplex = tuple (sorted (simplex ))
0 commit comments