@@ -32,61 +32,67 @@ def identifier_simple(mesh):
3232 ----------
3333 identifier: (6,) float, identifying values of the mesh
3434 """
35-
36- # pre-allocate identifier so indexes of values can't move around
37- # like they might if we used hstack or something else
38- identifier = np .zeros (6 , dtype = np .float64 )
39- # avoid thrashing the cache unnecessarily
40- mesh_area = mesh .area
41- # start with properties that are valid regardless of watertightness
42- # note that we're going to try to make all parameters relative
43- # to area so other values don't get blown up at weird scales
44- identifier [0 ] = mesh_area
45- # topological constant and the only thing we can really
46- # trust in this fallen world
47- identifier [1 ] = mesh .euler_number
48- # if we have a watertight mesh include volume and inertia
49- if mesh .is_volume :
50- # side length of a cube ratio
51- # 1.0 for cubes, different values for other things
52- identifier [2 ] = (((mesh_area / 6.0 ) ** (1.0 / 2.0 )) /
53- (mesh .volume ** (1.0 / 3.0 )))
54- # save vertices for radius calculation
55- vertices = mesh .vertices - mesh .center_mass
56- # we are going to special case radially symmetric meshes
57- # to replace their surface area with ratio of their
58- # surface area to a primitive sphere or cylinder surface area
59- # this is because tessellated curved surfaces are really rough
60- # to reliably hash as they are very sensitive to floating point
61- # and tessellation error. By making area proportionate to a fit
62- # primitive area we are able to reliably hash at more sigfigs
63- if mesh .symmetry == 'radial' :
64- # cylinder height
65- h = np .dot (vertices , mesh .symmetry_axis ).ptp ()
66- # section radius
67- R2 = (np .dot (vertices , mesh .symmetry_section .T )** 2 ).sum (axis = 1 ).max ()
68- # area of a cylinder primitive
69- area = (2 * np .pi * (R2 ** .5 ) * h ) + (2 * np .pi * R2 )
70- # replace area in this case with area ratio
71- identifier [0 ] = mesh_area / area
72- elif mesh .symmetry == 'spherical' :
73- # handle a spherically symmetric mesh
35+ # verify the cache once
36+ mesh ._cache .verify ()
37+
38+ # don't check hashes during identifier as we aren't
39+ # changing any data values of the mesh inside block
40+ # if we did change values in cache block things would break
41+ with mesh ._cache :
42+ # pre-allocate identifier so indexes of values can't move around
43+ # like they might if we used hstack or something else
44+ identifier = np .zeros (6 , dtype = np .float64 )
45+ # avoid thrashing the cache unnecessarily
46+ mesh_area = mesh .area
47+ # start with properties that are valid regardless of watertightness
48+ # note that we're going to try to make all parameters relative
49+ # to area so other values don't get blown up at weird scales
50+ identifier [0 ] = mesh_area
51+ # topological constant and the only thing we can really
52+ # trust in this fallen world
53+ identifier [1 ] = mesh .euler_number
54+ # if we have a watertight mesh include volume and inertia
55+ if mesh .is_volume :
56+ # side length of a cube ratio
57+ # 1.0 for cubes, different values for other things
58+ identifier [2 ] = (((mesh_area / 6.0 ) ** (1.0 / 2.0 )) /
59+ (mesh .volume ** (1.0 / 3.0 )))
60+ # save vertices for radius calculation
61+ vertices = mesh .vertices - mesh .center_mass
62+ # we are going to special case radially symmetric meshes
63+ # to replace their surface area with ratio of their
64+ # surface area to a primitive sphere or cylinder surface area
65+ # this is because tessellated curved surfaces are really rough
66+ # to reliably hash as they are very sensitive to floating point
67+ # and tessellation error. By making area proportionate to a fit
68+ # primitive area we are able to reliably hash at more sigfigs
69+ if mesh .symmetry == 'radial' :
70+ # cylinder height
71+ h = np .dot (vertices , mesh .symmetry_axis ).ptp ()
72+ # section radius
73+ R2 = (np .dot (vertices , mesh .symmetry_section .T )** 2 ).sum (axis = 1 ).max ()
74+ # area of a cylinder primitive
75+ area = (2 * np .pi * (R2 ** .5 ) * h ) + (2 * np .pi * R2 )
76+ # replace area in this case with area ratio
77+ identifier [0 ] = mesh_area / area
78+ elif mesh .symmetry == 'spherical' :
79+ # handle a spherically symmetric mesh
80+ R2 = (vertices ** 2 ).sum (axis = 1 ).max ()
81+ area = 4 * np .pi * R2
82+ identifier [0 ] = mesh_area / area
83+ else :
84+ # if we don't have a watertight mesh add information about the
85+ # convex hull, which is slow to compute and unreliable
86+ # just what we're looking for in a hash but hey
87+ identifier [3 ] = mesh_area / mesh .convex_hull .area
88+ # cube side length ratio for the hull
89+ identifier [4 ] = (((mesh .convex_hull .area / 6.0 ) ** (1.0 / 2.0 )) /
90+ (mesh .convex_hull .volume ** (1.0 / 3.0 )))
91+ vertices = mesh .vertices - mesh .centroid
92+
93+ # add in max radius^2 to area ratio
7494 R2 = (vertices ** 2 ).sum (axis = 1 ).max ()
75- area = 4 * np .pi * R2
76- identifier [0 ] = mesh_area / area
77- else :
78- # if we don't have a watertight mesh add information about the
79- # convex hull, which is slow to compute and unreliable
80- # just what we're looking for in a hash but hey
81- identifier [3 ] = mesh_area / mesh .convex_hull .area
82- # cube side length ratio for the hull
83- identifier [4 ] = (((mesh .convex_hull .area / 6.0 ) ** (1.0 / 2.0 )) /
84- (mesh .convex_hull .volume ** (1.0 / 3.0 )))
85- vertices = mesh .vertices - mesh .centroid
86-
87- # add in max radius^2 to area ratio
88- R2 = (vertices ** 2 ).sum (axis = 1 ).max ()
89- identifier [5 ] = R2 / mesh_area
95+ identifier [5 ] = R2 / mesh_area
9096
9197 return identifier
9298
0 commit comments