97 type(
field_t),
intent(inout) :: field_data
99 real(kind=
dp),
intent(in) :: max_distance
101 integer :: total_size
104 real(kind=
dp),
dimension(3) :: p
105 real(kind=
dp) :: distance
108 call rzero(field_data%x, field_data%size())
109 total_size = field_data%dof%size()
111 call search_tree%init(
mesh%nelv)
112 call search_tree%build(
mesh%el)
114 if (search_tree%get_size() .ne.
mesh%nelv)
then
115 call neko_error(
"signed_distance_field_tri_mesh: " // &
116 "Error building the search tree.")
120 do id = 1, total_size
121 p(1) = field_data%dof%x(id, 1, 1, 1)
122 p(2) = field_data%dof%y(id, 1, 1, 1)
123 p(3) = field_data%dof%z(id, 1, 1, 1)
127 field_data%x(id, 1, 1, 1) =
real(distance, kind=
rp)
133 & Device version not implemented.")
134 call device_memcpy(field_data%x, field_data%x_d, field_data%size(), &
154 real(kind=
dp),
intent(in) :: p(3)
155 real(kind=
dp),
intent(in) :: max_distance
158 real(kind=
dp) :: distance, weighted_sign
159 real(kind=
dp) :: cd, cs
160 real(kind=
dp) :: tol = 1e-6_dp
162 distance = huge(0.0_dp)
163 weighted_sign = 0.0_dp
169 if (abs(cd - distance) / distance .lt. tol)
then
170 weighted_sign = weighted_sign + cs
171 else if (cd .lt. distance)
then
175 distance = min(cd, distance)
178 distance = sign(min(distance, max_distance), weighted_sign)
198 class(
tri_t),
contiguous,
dimension(:),
intent(in) :: object_list
199 real(kind=
dp),
dimension(3),
intent(in) :: p
200 real(kind=
dp),
intent(in) :: max_distance
202 real(kind=
dp) :: distance
203 real(kind=
dp) :: weighted_sign
205 real(kind=
dp),
parameter :: tol = 1.0e-6_dp
208 integer :: current_index
211 type(
aabb_t) :: current_aabb
212 integer :: current_object_index
213 real(kind=
dp) :: current_distance
214 real(kind=
dp) :: current_sign
220 type(
aabb_t) :: search_box
222 integer :: root_index, left_index, right_index
223 real(kind=
dp) :: random_value
226 call simple_stack%init(
size(object_list) * 2)
227 call search_box%init(p - max_distance, p + max_distance)
231 root_index = tree%get_root_index()
232 root_box = tree%get_aabb(root_index)
234 if (.not. root_box%overlaps(search_box))
then
235 distance = max_distance
236 weighted_sign = 1.0_dp
241 call random_number(random_value)
242 current_object_index = floor(random_value *
size(object_list) + 1)
245 distance = distance + object_list(current_object_index)%diameter()
248 call search_box%init(p - distance, p + distance)
249 call simple_stack%push(root_index)
252 do while (.not. simple_stack%is_empty())
253 current_index = simple_stack%pop()
256 current_node = tree%get_node(current_index)
257 current_aabb = current_node%get_aabb()
259 if (current_node%is_leaf())
then
260 if (distance .lt. current_node%min_distance(p))
then
264 current_object_index = current_node%get_object_index()
266 current_distance, current_sign)
269 if (abs(current_distance - distance) / distance .lt. tol)
then
270 weighted_sign = weighted_sign + current_sign
271 else if (current_distance .lt. distance)
then
272 weighted_sign = current_sign
275 distance = min(distance, current_distance)
278 if (distance .gt. current_aabb%get_diameter())
then
279 call search_box%init(p - distance, p + distance)
283 left_index = tree%get_left_index(current_index)
285 left_node = tree%get_left_node(current_index)
286 if (left_node%aabb%overlaps(search_box))
then
287 call simple_stack%push(left_index)
291 right_index = tree%get_right_index(current_index)
293 right_node = tree%get_right_node(current_index)
294 if (right_node%aabb%overlaps(search_box))
then
295 call simple_stack%push(right_index)
301 if (distance .gt. max_distance)
then
302 distance = max_distance
304 distance = sign(distance, weighted_sign)
350 type(
tri_t),
intent(in) :: triangle
351 real(kind=
dp),
dimension(3),
intent(in) :: p
353 real(kind=
dp),
intent(out) :: distance
354 real(kind=
dp),
intent(out),
optional :: weighted_sign
356 real(kind=
dp),
dimension(3) :: v1, v2, v3
357 real(kind=
dp),
dimension(3) :: normal
358 real(kind=
dp) :: normal_length
359 real(kind=
dp) :: b1, b2, b3
362 real(kind=
dp),
dimension(3) :: edge
363 real(kind=
dp) :: tol = 1e-10_dp
365 real(kind=
dp) :: face_distance
369 v1 = triangle%pts(1)%p%x
370 v2 = triangle%pts(2)%p%x
371 v3 = triangle%pts(3)%p%x
373 normal =
cross(v2 - v1, v3 - v1)
374 normal_length = norm2(normal)
376 if (normal_length .lt. tol)
then
377 distance = huge(1.0_dp)
378 weighted_sign = 0.0_dp
381 normal = normal / normal_length
385 face_distance = dot_product(p - v1, normal)
388 b1 = dot_product(normal,
cross(v2 - v1,
projection - v1)) / normal_length
389 b2 = dot_product(normal,
cross(v3 - v2,
projection - v2)) / normal_length
390 b3 = dot_product(normal,
cross(v1 - v3,
projection - v3)) / normal_length
392 if (b1 .le. tol)
then
394 t = dot_product(p - v1, edge) / norm2(edge)
395 t =
max(0.0_dp, min(1.0_dp, t))
398 else if (b2 .le. tol)
then
400 t = dot_product(p - v2, edge) / norm2(edge)
401 t =
max(0.0_dp, min(1.0_dp, t))
404 else if (b3 .le. tol)
then
406 t = dot_product(p - v3, edge) / norm2(edge)
407 t =
max(0.0_dp, min(1.0_dp, t))
413 if (
present(weighted_sign))
then
414 weighted_sign = face_distance / distance
416 distance = sign(distance, face_distance)