@@ -578,7 +578,14 @@ contains
578578
579579 end function f_model_is_inside
580580
581- impure function f_model_is_inside_flat (ntrs , trs_v , trs_n , pid , point , spacing , spc ) result(fraction)
581+ !> This procedure, given a cell center will determine if a point exists instide a surface
582+ !! @param ntrs Number of triangles in the model
583+ !! @param trs_v Model vertices of each triangle
584+ !! @param trs_n Model normal vectors of each triangle
585+ !! @param pid Patch ID od this model
586+ !! @param point Point to test.
587+ !! @return fraction The perfentage of candidate rays cast indicate that we are inside the model
588+ impure function f_model_is_inside_flat (ntrs , trs_v , trs_n , pid , point ) result(fraction)
582589
583590 $:GPU_ROUTINE(parallelism= ' [seq]' )
584591
@@ -587,47 +594,49 @@ contains
587594 real (wp), dimension (:, :, :), intent (in ) :: trs_n
588595 integer , intent (in ) :: pid
589596 real (wp), dimension (1 :3 ), intent (in ) :: point
590- real (wp), dimension (1 :3 ), intent (in ) :: spacing
591- integer , intent (in ) :: spc
592597
593598 real (wp) :: fraction
594- real (wp) :: origin(1 :3 ), dir(1 :3 ), dir_mag
595599 type(t_ray) :: ray
596600 type(t_triangle) :: tri
597- integer :: i, j, k, nInOrOut, nHits
598- integer :: rand_seed
601+ integer :: i, j, k, q, nInOrOut, nHits
599602
600- rand_seed = int (point(1 )* 73856093._wp ) + &
601- int (point(2 )* 19349663._wp ) + &
602- int (point(3 )* 83492791._wp )
603- if (rand_seed == 0 ) rand_seed = 1
604-
605- ! generate our random collection of rays
603+ ! cast 26 rays from the point and count the number at leave the boundary
606604 nInOrOut = 0
607- do i = 1 , spc
608- ! Generate one ray at a time — no arrays needed
609- do k = 1 , 3
610- origin(k) = point(k) + (f_model_random_number(rand_seed) - 0.5_wp )* spacing (k)
611- dir(k) = point(k) + f_model_random_number(rand_seed) - 0.5_wp
612- end do
613- dir_mag = sqrt (dir(1 )* dir(1 ) + dir(2 )* dir(2 ) + dir(3 )* dir(3 ))
614- dir(:) = dir(:)/ dir_mag
615-
616- ray%o = origin
617- ray%d = dir
618-
619- nHits = 0
620- do j = 1 , ntrs
621- tri%v(:, :) = trs_v(:, :, j, pid)
622- tri%n(:) = trs_n(:, j, pid)
623- if (f_intersects_triangle(ray, tri)) then
624- nHits = nHits + 1
625- end if
605+ do i = - 1 , 1
606+ do j = - 1 , 1
607+ do k = - 1 , 1
608+ if (i /= 0 .or. j /= 0 .or. k /= 0 ) then
609+ ! We cannot get inersections if the ray is exactly in line with triangle plane
610+ if (p == 0 .and. k == 0 ) cycle
611+
612+ ! generate the ray
613+ ray%o = point
614+ ray%d(:) = [real (i, wp), real (j, wp), real (k, wp)]
615+ ray%d = ray%d/ sqrt (real (abs (i) + abs (j) + abs (k), wp))
616+
617+ ! count the number of intersections
618+ nHits = 0
619+ do q = 1 , ntrs
620+ tri%v(:, :) = trs_v(:, :, q, pid)
621+ tri%n(:) = trs_n(:, q, pid)
622+ if (f_intersects_triangle(ray, tri)) then
623+ nHits = nHits + 1
624+ end if
625+ end do
626+ ! if the ray intersected an odd number of times, we must be inside
627+ nInOrOut = nInOrOut + mod (nHits, 2 )
628+ end if
629+ end do
626630 end do
627- nInOrOut = nInOrOut + mod (nHits, 2 )
628631 end do
629632
630- fraction = real (nInOrOut)/ real (spc)
633+ if (p == 0 ) then
634+ ! in 2D , we skipped 8 rays
635+ fraction = real (nInOrOut)/ 18._wp
636+ else
637+ fraction = real (nInOrOut)/ 26._wp
638+ end if
639+
631640 end function f_model_is_inside_flat
632641
633642 ! From https:// www.scratchapixel.com/ lessons/ 3e - basic- rendering/ ray- tracing- rendering- a- triangle/ ray- triangle- intersection- geometric- solution.html
@@ -846,7 +855,7 @@ contains
846855 real (wp) :: dist_min, dist_proj, dist_v, dist_e, t
847856 real (wp) :: v1(1 :3 ), v2(1 :3 ), v3(1 :3 )
848857 real (wp) :: e0(1 :3 ), e1(1 :3 ), pv(1 :3 )
849- real (wp) :: n(1 :3 ), proj(1 :3 ), normals( 1 : 3 ), norm_vec(1 :3 )
858+ real (wp) :: n(1 :3 ), proj(1 :3 ), norm_vec(1 :3 )
850859 real (wp) :: d, ndot, denom, norm_mag
851860 real (wp) :: u, v_bary, w
852861 real (wp) :: l00, l01, l11, l20, l21
@@ -884,6 +893,7 @@ contains
884893
885894 denom = l00* l11 - l01* l01
886895
896+ ! compute the barycentric coordinates of the projection in the triangle
887897 if (abs (denom) > 0._wp ) then
888898 v_bary = (l11* l20 - l01* l21)/ denom
889899 w = (l00* l21 - l01* l20)/ denom
@@ -897,8 +907,8 @@ contains
897907 ! If projection is inside triangle
898908 if (u >= 0._wp .and. v_bary >= 0._wp .and. w >= 0._wp ) then
899909 dist_proj = sqrt ((point(1 ) - proj(1 ))** 2 + &
900- (point(2 ) - proj(2 ))** 2 + &
901- (point(3 ) - proj(3 ))** 2 )
910+ (point(2 ) - proj(2 ))** 2 + &
911+ (point(3 ) - proj(3 ))** 2 )
902912
903913 if (dist_proj < dist_min) then
904914 dist_min = dist_proj
@@ -927,7 +937,7 @@ contains
927937 dist_min = dist_e
928938 norm_vec(:) = point(:) - verts(:, j)
929939 norm_mag = sqrt (dot_product (norm_vec, norm_vec))
930- if (norm_mag > 0._wp ) norm_vec = norm_vec / norm_mag
940+ if (norm_mag > 0._wp ) norm_vec = norm_vec/ norm_mag
931941 normals(:) = norm_vec(:)
932942 end if
933943 else if (t < 0._wp ) then
@@ -939,7 +949,7 @@ contains
939949 dist_min = dist_v
940950 norm_vec(:) = point(:) - verts(:, j)
941951 norm_mag = sqrt (dot_product (norm_vec, norm_vec))
942- if (norm_mag > 0._wp ) norm_vec = norm_vec / norm_mag
952+ if (norm_mag > 0._wp ) norm_vec = norm_vec/ norm_mag
943953 normals(:) = norm_vec(:)
944954 end if
945955 else
@@ -951,7 +961,7 @@ contains
951961 dist_min = dist_v
952962 norm_vec(:) = point(:) - verts(:, mod (j, 3 ) + 1 )
953963 norm_mag = sqrt (dot_product (norm_vec, norm_vec))
954- if (norm_mag > 0._wp ) norm_vec = norm_vec / norm_mag
964+ if (norm_mag > 0._wp ) norm_vec = norm_vec/ norm_mag
955965 normals(:) = norm_vec(:)
956966 end if
957967 end if
@@ -1021,13 +1031,13 @@ contains
10211031 norm(1 ) = point(1 ) - v1(1 )
10221032 norm(2 ) = point(2 ) - v1(2 )
10231033 norm_mag = sqrt (dot_product (norm, norm))
1024- norm = norm / norm_mag
1034+ norm = norm/ norm_mag
10251035 else ! t > 1 means that v2 is the closest point on the line edge
10261036 dist = sqrt ((point(1 ) - v2(1 ))** 2 + (point(2 ) - v2(2 ))** 2 )
10271037 norm(1 ) = point(1 ) - v2(1 )
10281038 norm(2 ) = point(2 ) - v2(2 )
10291039 norm_mag = sqrt (dot_product (norm, norm))
1030- norm = norm / norm_mag
1040+ norm = norm/ norm_mag
10311041 end if
10321042
10331043 if (dist < dist_min) then
0 commit comments