3
3
from collections .abc import Iterable , Sized
4
4
from itertools import chain , combinations
5
5
from math import factorial
6
- from typing import Any , Iterator , List , Optional , Set , Tuple , Union
6
+ from typing import Any , Iterator , List , Optional , Sequence , Set , Tuple , Union
7
7
8
8
import numpy as np
9
9
import scipy .spatial
10
- from numpy import int32
11
10
11
+ Simplex = Tuple [int , ...] # XXX: check if this is correct
12
12
13
- def fast_norm (v : Union [Tuple [float , float , float ], np .ndarray ]) -> float :
13
+
14
+ def fast_norm (v : Union [Tuple [float , ...], np .ndarray ]) -> float :
14
15
# notice this method can be even more optimised
15
16
if len (v ) == 2 :
16
17
return math .sqrt (v [0 ] * v [0 ] + v [1 ] * v [1 ])
@@ -20,12 +21,8 @@ def fast_norm(v: Union[Tuple[float, float, float], np.ndarray]) -> float:
20
21
21
22
22
23
def fast_2d_point_in_simplex (
23
- point : Union [Tuple [int , int ], Tuple [float , float ], Tuple [float , float ]],
24
- simplex : Union [
25
- List [Union [Tuple [int , int ], Tuple [float , float ]]],
26
- List [Tuple [float , float ]],
27
- np .ndarray ,
28
- ],
24
+ point : Tuple [float , ...],
25
+ simplex : Union [List [Tuple [float , ...]], np .ndarray ],
29
26
eps : float = 1e-8 ,
30
27
) -> Union [bool , np .bool_ ]:
31
28
(p0x , p0y ), (p1x , p1y ), (p2x , p2y ) = simplex
@@ -42,7 +39,7 @@ def fast_2d_point_in_simplex(
42
39
43
40
44
41
def point_in_simplex (
45
- point : Any , simplex : Any , eps : float = 1e-8
42
+ point : Any , simplex : Simplex , eps : float = 1e-8
46
43
) -> Union [bool , np .bool_ ]:
47
44
if len (point ) == 2 :
48
45
return fast_2d_point_in_simplex (point , simplex , eps )
@@ -143,13 +140,7 @@ def fast_det(matrix: np.ndarray) -> float:
143
140
return np .linalg .det (matrix )
144
141
145
142
146
- def circumsphere (
147
- pts : np .ndarray ,
148
- ) -> Union [
149
- Tuple [Tuple [float , float , float , float ], float ],
150
- Tuple [Tuple [float , float ], float ],
151
- Tuple [Tuple [float , float , float ], float ],
152
- ]:
143
+ def circumsphere (pts : np .ndarray ,) -> Tuple [Tuple [float , ...], float ]:
153
144
dim = len (pts ) - 1
154
145
if dim == 2 :
155
146
return fast_2d_circumcircle (pts )
@@ -175,7 +166,7 @@ def circumsphere(
175
166
return tuple (center ), radius
176
167
177
168
178
- def orientation (face : Any , origin : Any ) -> Union [ int , float ] :
169
+ def orientation (face : np . ndarray , origin : np . ndarray ) -> int :
179
170
"""Compute the orientation of the face with respect to a point, origin.
180
171
181
172
Parameters
@@ -205,14 +196,7 @@ def is_iterable_and_sized(obj: Any) -> bool:
205
196
return isinstance (obj , Iterable ) and isinstance (obj , Sized )
206
197
207
198
208
- def simplex_volume_in_embedding (
209
- vertices : Union [
210
- List [Tuple [float , float , float ]],
211
- List [Tuple [float , float , float ]],
212
- List [Tuple [float , float , float , float ]],
213
- List [Tuple [float , float , float , float , float ]],
214
- ]
215
- ) -> float :
199
+ def simplex_volume_in_embedding (vertices : List [Tuple [float , ...]]) -> float :
216
200
"""Calculate the volume of a simplex in a higher dimensional embedding.
217
201
That is: dim > len(vertices) - 1. For example if you would like to know the
218
202
surface area of a triangle in a 3d space.
@@ -293,7 +277,7 @@ class Triangulation:
293
277
or more simplices in the
294
278
"""
295
279
296
- def __init__ (self , coords : Any ) -> None :
280
+ def __init__ (self , coords : np . ndarray ) -> None :
297
281
if not is_iterable_and_sized (coords ):
298
282
raise TypeError ("Please provide a 2-dimensional list of points" )
299
283
coords = list (coords )
@@ -332,27 +316,29 @@ def __init__(self, coords: Any) -> None:
332
316
for simplex in initial_tri .simplices :
333
317
self .add_simplex (simplex )
334
318
335
- def delete_simplex (self , simplex : Any ) -> None :
319
+ def delete_simplex (self , simplex : Simplex ) -> None :
336
320
simplex = tuple (sorted (simplex ))
337
321
self .simplices .remove (simplex )
338
322
for vertex in simplex :
339
323
self .vertex_to_simplices [vertex ].remove (simplex )
340
324
341
- def add_simplex (self , simplex : Any ) -> None :
325
+ def add_simplex (self , simplex : Simplex ) -> None :
342
326
simplex = tuple (sorted (simplex ))
343
327
self .simplices .add (simplex )
344
328
for vertex in simplex :
345
329
self .vertex_to_simplices [vertex ].add (simplex )
346
330
347
- def get_vertices (self , indices : Any ) -> Any :
331
+ def get_vertices (self , indices : Sequence [ int ] ) -> Any :
348
332
return [self .get_vertex (i ) for i in indices ]
349
333
350
- def get_vertex (self , index : Optional [Union [ int32 , int ] ]) -> Any :
334
+ def get_vertex (self , index : Optional [int ]) -> Any :
351
335
if index is None :
352
336
return None
353
337
return self .vertices [index ]
354
338
355
- def get_reduced_simplex (self , point : Any , simplex : Any , eps : float = 1e-8 ) -> list :
339
+ def get_reduced_simplex (
340
+ self , point : Any , simplex : Simplex , eps : float = 1e-8
341
+ ) -> list :
356
342
"""Check whether vertex lies within a simplex.
357
343
358
344
Returns
@@ -378,7 +364,7 @@ def get_reduced_simplex(self, point: Any, simplex: Any, eps: float = 1e-8) -> li
378
364
return [simplex [i ] for i in result ]
379
365
380
366
def point_in_simplex (
381
- self , point : Any , simplex : Any , eps : float = 1e-8
367
+ self , point : Any , simplex : Simplex , eps : float = 1e-8
382
368
) -> Union [bool , np .bool_ ]:
383
369
vertices = self .get_vertices (simplex )
384
370
return point_in_simplex (point , vertices , eps )
@@ -466,12 +452,8 @@ def _extend_hull(self, new_vertex: Any, eps: float = 1e-8) -> Any:
466
452
return new_simplices
467
453
468
454
def circumscribed_circle (
469
- self , simplex : Any , transform : np .ndarray
470
- ) -> Union [
471
- Tuple [Tuple [float , float , float , float ], float ],
472
- Tuple [Tuple [float , float ], float ],
473
- Tuple [Tuple [float , float , float ], float ],
474
- ]:
455
+ self , simplex : Simplex , transform : np .ndarray
456
+ ) -> Tuple [Tuple [float , ...], float ]:
475
457
"""Compute the center and radius of the circumscribed circle of a simplex.
476
458
477
459
Parameters
@@ -488,7 +470,7 @@ def circumscribed_circle(
488
470
return circumsphere (pts )
489
471
490
472
def point_in_cicumcircle (
491
- self , pt_index : int , simplex : Any , transform : np .ndarray
473
+ self , pt_index : int , simplex : Simplex , transform : np .ndarray
492
474
) -> np .bool_ :
493
475
# return self.fast_point_in_circumcircle(pt_index, simplex, transform)
494
476
eps = 1e-8
@@ -567,10 +549,10 @@ def bowyer_watson(
567
549
new_triangles = self .vertex_to_simplices [pt_index ]
568
550
return bad_triangles - new_triangles , new_triangles - bad_triangles
569
551
570
- def _simplex_is_almost_flat (self , simplex : Any ) -> np .bool_ :
552
+ def _simplex_is_almost_flat (self , simplex : Simplex ) -> np .bool_ :
571
553
return self ._relative_volume (simplex ) < 1e-8
572
554
573
- def _relative_volume (self , simplex : Any ) -> float :
555
+ def _relative_volume (self , simplex : Simplex ) -> float :
574
556
"""Compute the volume of a simplex divided by the average (Manhattan)
575
557
distance of its vertices. The advantage of this is that the relative
576
558
volume is only dependent on the shape of the simplex and not on the
@@ -635,7 +617,7 @@ def add_point(
635
617
self .vertices .append (point )
636
618
return self .bowyer_watson (pt_index , actual_simplex , transform )
637
619
638
- def volume (self , simplex : Any ) -> float :
620
+ def volume (self , simplex : Simplex ) -> float :
639
621
prefactor = np .math .factorial (self .dim )
640
622
vertices = np .array (self .get_vertices (simplex ))
641
623
vectors = vertices [1 :] - vertices [0 ]
@@ -658,10 +640,10 @@ def vertex_invariant(self, vertex):
658
640
"""Simplices originating from a vertex don't overlap."""
659
641
raise NotImplementedError
660
642
661
- def get_neighbors_from_vertices (self , simplex : Any ) -> Any :
643
+ def get_neighbors_from_vertices (self , simplex : Simplex ) -> Any :
662
644
return set .union (* [self .vertex_to_simplices [p ] for p in simplex ])
663
645
664
- def get_face_sharing_neighbors (self , neighbors : Any , simplex : Any ) -> Any :
646
+ def get_face_sharing_neighbors (self , neighbors : Any , simplex : Simplex ) -> Any :
665
647
"""Keep only the simplices sharing a whole face with simplex."""
666
648
return {
667
649
simpl for simpl in neighbors if len (set (simpl ) & set (simplex )) == self .dim
@@ -672,15 +654,7 @@ def get_simplices_attached_to_points(self, indices: Any) -> Any:
672
654
neighbors = self .get_neighbors_from_vertices (indices )
673
655
return self .get_face_sharing_neighbors (neighbors , indices )
674
656
675
- def get_opposing_vertices (
676
- self ,
677
- simplex : Union [
678
- Tuple [int32 , int , int ],
679
- Tuple [int32 , int32 , int ],
680
- Tuple [int32 , int32 , int32 ],
681
- Tuple [int , int , int ],
682
- ],
683
- ) -> Any :
657
+ def get_opposing_vertices (self , simplex : Simplex ,) -> Any :
684
658
if simplex not in self .simplices :
685
659
raise ValueError ("Provided simplex is not part of the triangulation" )
686
660
neighbors = self .get_simplices_attached_to_points (simplex )
@@ -698,7 +672,7 @@ def find_opposing_vertex(vertex):
698
672
return result
699
673
700
674
@property
701
- def hull (self ) -> Union [ Set [int32 ], Set [ int ], Set [ Union [ int32 , int ]] ]:
675
+ def hull (self ) -> Set [int ]:
702
676
"""Compute hull from triangulation.
703
677
704
678
Parameters
0 commit comments