MCPcopy
hub / github.com/tum-pbs/PhiFlow / _closest_surface

Method _closest_surface

phi/geom/_spline_solid.py:228–267  ·  view source on GitHub ↗
(self, location: Tensor)

Source from the content-addressed store, hash-verified

226
227 @staticmethod
228 def _closest_surface(self, location: Tensor):
229 on_skeleton, uv, unbounded_uv, tangents = closest_param(self.order, self.points, location, uv_gradient=False)
230 delta = location - on_skeleton
231 normal_c = vec_normalize(cross(*tangents.tangents.dual))
232 thickness = self.thickness_at(uv)
233 radius = .5 * thickness
234 # --- Compute effective fillet (1 inside valid uv range) ---
235 is_edge = stack({'-': unbounded_uv < uv, '+': unbounded_uv > uv}, '~side')
236 fillets = stack({dim: stack({'-': self.fillet[dim+'-'], '+': self.fillet[dim+'+']}, '~side') for dim in spatial(self.points).names}, 'spline:c')
237 fillet = where(is_edge, fillets, 1)
238 h = normal_c.vector @ delta
239 is_corner = math.sum(is_edge, 'spline,~side') >= 2
240 # --- Corner: Constrain sphere center to plane orthogonal to large fillet ---
241 large_fillet = math.max(fillets * is_edge, '~side,spline')
242 small_fillet = math.min(fillet, '~side,spline')
243 large_fillet_tangent = math.min(tangents, '~tangents', key=dsum(fillet * is_edge).spline.as_dual('tangents'))
244 ortho_dir = vec_normalize(cross(normal_c, large_fillet_tangent))
245 w = ortho_dir.vector @ (location - on_skeleton)
246 safe_h = radius * (1 - large_fillet)
247 # ToDo need safe_w after all
248 h_over = maximum(0, abs(h) - safe_h) * sign(h)
249 over = clip_length(vec('dir', w=w, h=h_over), max_len=radius * (large_fillet - small_fillet), vec_dim='dir')
250 wh = vec('dir', w=0, h=clip(h, -safe_h, safe_h)) + over
251 dirs = stack({'w': ortho_dir, 'h': normal_c}, '~dir')
252 c_sphere_offset = dirs @ wh
253 c_sphere_rad = radius * small_fillet
254 # --- Edge/segment: Constrain sphere center to line orthogonal to spline skeleton ---
255 sphere_rad = radius * dmin(fillet.spline.as_dual('tangents'))
256 sphere_h_lim = radius - sphere_rad
257 sphere_h = clip(h, -sphere_h_lim, sphere_h_lim)
258 sphere_offset = normal_c * sphere_h
259 # --- Construct sphere ---
260 sphere_offset = where(is_corner, c_sphere_offset, sphere_offset)
261 sphere_rad = where(is_corner, c_sphere_rad, sphere_rad)
262 sphere = Sphere(center=on_skeleton + sphere_offset, radius=sphere_rad)
263 face_index = vec('index', **to_int32(clip(unbounded_uv+1, 0, self.resolution)).spline, **{'~side': to_int32(h <= 0)})
264 def sphere_sdf(sphere: Sphere, location: Tensor):
265 return sphere.approximate_closest_surface(location)
266 sdf, delta, normal, offset, _ = map_types(sphere_sdf, instance(location), batch)(sphere, location)
267 return sdf, delta, normal, offset, face_index, on_skeleton, uv, unbounded_uv, tangents, normal_c, thickness, is_edge, is_corner
268
269 def thickness_at(self, uv: Tensor):
270 if not spatial(self.thickness):

Callers 1

transform_with_splineFunction · 0.80

Calls 8

thickness_atMethod · 0.95
stackFunction · 0.90
whereFunction · 0.90
maximumFunction · 0.90
vec_normalizeFunction · 0.85
crossFunction · 0.85
clip_lengthFunction · 0.85
SphereClass · 0.85

Tested by

no test coverage detected