Skip to content

Commit 2b3b3c5

Browse files
committed
provide best visual center if area is zero
1 parent 3f7c206 commit 2b3b3c5

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

burnman/utils/plotting.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,47 @@ def __lt__(self, other):
9999
return self.max > other.max
100100

101101

102+
def closest_point_on_segment(p, a, b):
103+
"""
104+
Return the closest point on segment ab to point p.
105+
p, a, b: numpy arrays of shape (2,)
106+
"""
107+
ab = b - a
108+
ap = p - a
109+
110+
ab_len_sq = np.dot(ab, ab)
111+
if ab_len_sq < np.finfo(float).eps:
112+
return a.copy()
113+
else:
114+
t = np.dot(ap, ab) / ab_len_sq
115+
t = np.clip(t, 0, 1) # constrain t to [0, 1]
116+
return a + t * ab
117+
118+
119+
def closest_point_on_polygon(p, polygon):
120+
"""
121+
Find the closest point on a polygon to point p.
122+
123+
:param p: np.array of shape (2,) - the target point
124+
:param polygon: np.array of shape (N, 2) - the polygon vertices
125+
(assumed closed or will be treated as closed)
126+
:return: np.array of shape (2,) - closest point on polygon
127+
"""
128+
min_dist = np.inf
129+
closest_point = None
130+
num_points = polygon.shape[0]
131+
for i in range(num_points):
132+
a = polygon[i]
133+
b = polygon[(i + 1) % num_points] # wrap around
134+
proj = closest_point_on_segment(p, a, b)
135+
dist = np.linalg.norm(p - proj)
136+
if dist < min_dist:
137+
min_dist = dist
138+
closest_point = proj
139+
140+
return closest_point
141+
142+
102143
def _get_centroid_cell(polygon):
103144
"""
104145
Estimate the polygon's centroid as an initial guess.
@@ -121,7 +162,9 @@ def _get_centroid_cell(polygon):
121162
b = a
122163

123164
if area == 0:
124-
return Cell(points[0][0], points[0][1], 0.0, polygon)
165+
midpoint = (np.min(points, axis=0) + np.max(points, axis=0)) / 2
166+
closest = closest_point_on_polygon(midpoint, points)
167+
return Cell(closest[0], closest[1], 0.0, polygon)
125168

126169
return Cell(cx / area, cy / area, 0.0, polygon)
127170

0 commit comments

Comments
 (0)