@@ -25,22 +25,79 @@ def __call__(self, xyz):
2525
2626
2727class PositiveRegion :
28- def __init__ (self , feature ):
28+ """Helper class for evaluating whether you are in the positive region of a scalar field.
29+ If its outside of the support it will interpolate the average gradient at a point on the 0 isovalue
30+ and calculate the distance from this. Alternatively, a point and vector can be used to save computational time
31+ """
32+
33+ def __init__ (self , feature , vector = None , point = None ):
2934 self .feature = feature
35+ self .vector = vector
36+ self .point = point
3037
3138 def __call__ (self , xyz ):
39+ val = self .feature .evaluate_value (xyz )
40+ # find a point on/near 0 isosurface
41+ if self .point is None :
42+ mask = np .zeros (xyz .shape [0 ], dtype = "bool" )
43+ mask [:] = val < 0
44+ if np .sum (mask ) == 0 :
45+ raise ValueError ("Cannot find point on surface" )
46+ centre = xyz [mask , :][0 , :]
47+ else :
48+ centre = self .point
49+ if self .vector is None :
50+ average_gradient = self .feature .evaluate_gradient (np .array ([centre ]))[0 ]
51+ average_gradient [2 ] = 0
52+ average_gradient /= np .linalg .norm (average_gradient )
53+ else :
54+ average_gradient = self .vector
55+ # distance = ((xyz[:,0] - centre[None,0])*average_gradient[0] +
56+ # (xyz[:,1] - centre[None,1])*average_gradient[1] +
57+ # ( xyz[:,2] - centre[None,2])*average_gradient[2])
58+ distance = np .einsum ("ij,j->i" , centre [None , :] - xyz , average_gradient )
3259 return np .logical_or (
33- self . feature . evaluate_value ( xyz ) > 0 ,
34- np .isnan ( self . feature . evaluate_value ( xyz ) ),
60+ np . logical_and ( ~ np . isnan ( val ), val > 0 ) ,
61+ np .logical_and ( np . isnan ( val ), distance > 0 ),
3562 )
3663
3764
3865class NegativeRegion :
39- def __init__ (self , feature ):
66+ """Helper class for evaluating whether you are in the positive region of a scalar field.
67+ If its outside of the support it will interpolate the average gradient at a point on the 0 isovalue
68+ and calculate the distance from this. Alternatively, a point and vector can be used to save computational time
69+ """
70+
71+ def __init__ (self , feature , vector = None , point = None ):
4072 self .feature = feature
73+ self .vector = vector
74+ self .point = point
4175
4276 def __call__ (self , xyz ):
77+ val = self .feature .evaluate_value (xyz )
78+ # find a point on/near 0 isosurface
79+ if self .point is None :
80+ mask = np .zeros (xyz .shape [0 ], dtype = "bool" )
81+ mask [:] = val < 0
82+ if np .sum (mask ) == 0 :
83+ raise ValueError ("Cannot find point on surface" )
84+ centre = xyz [mask , :][0 , :]
85+ else :
86+ centre = self .point
87+ if self .vector is None :
88+ average_gradient = self .feature .evaluate_gradient (np .array ([centre ]))[0 ]
89+ average_gradient [2 ] = 0
90+ average_gradient /= np .linalg .norm (average_gradient )
91+ else :
92+ average_gradient = self .vector
93+ distance = np .einsum ("ij,j->i" , xyz - centre [None , :], average_gradient )
94+ # distance = ((xyz[:,0] - centre[None,0])*average_gradient[0] +
95+ # (xyz[:,1] - centre[None,1])*average_gradient[1] +
96+ # ( xyz[:,2] - centre[None,2])*average_gradient[2])
97+ # return np.logical_or(np.logical_and(~np.isnan(val),val
98+ # < 0),
99+ # np.logical_and(np.isnan(val),distance>0))
43100 return np .logical_or (
44- self . feature . evaluate_value ( xyz ) < 0 ,
45- np .isnan ( self . feature . evaluate_value ( xyz ) ),
101+ np . logical_and ( ~ np . isnan ( val ), val < 0 ) ,
102+ np .logical_and ( np . isnan ( val ), distance < 0 ),
46103 )
0 commit comments