Skip to content

Commit 7ea9beb

Browse files
author
Lachlan Grose
committed
fix: 🐛 fixed bug with fault clipping, uses normal direction to infer hanging wall side away from interpolated surfaces
1 parent 45c44d3 commit 7ea9beb

File tree

1 file changed

+63
-6
lines changed

1 file changed

+63
-6
lines changed

LoopStructural/utils/regions.py

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,79 @@ def __call__(self, xyz):
2525

2626

2727
class 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

3865
class 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

Comments
 (0)