Pick a body of frame self: the ellipsoid centered at center with
semi-axes radii along the columns of axes (unit vectors; all in the
frame's coordinates), hit by the ray through the cursor. Adds a
PICK_BODY hit (with the geodetic latitude and longitude of the point
on the ellipsoid if geodetic); true if hit.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(ReferenceFrame), | intent(in), | target | :: | self | ||
| type(PickCamera), | intent(in) | :: | cam |
the cursor's ray and the pick's settings |
||
| real(kind=wp), | intent(in) | :: | to_root(4,4) |
center, axes: frame coordinates |
||
| real(kind=wp), | intent(in) | :: | center(3) |
center, axes: frame coordinates |
||
| real(kind=wp), | intent(in) | :: | axes(3,3) |
center, axes: frame coordinates |
||
| real(kind=wp), | intent(in) | :: | radii(3) |
center, axes: frame coordinates |
||
| logical, | intent(in) | :: | geodetic |
(true: also the hit's geodetic latitude and longitude) |
||
| type(PickHit), | intent(inout), | allocatable | :: | hits(:) |
hits so far (grown as needed) |
|
| integer, | intent(inout) | :: | n |
number of hits in hits |
logical function pick_ellipsoid(self, cam, to_root, center, axes, radii, geodetic, hits, n) result(hit) class(ReferenceFrame), intent(in), target :: self type(PickCamera), intent(in) :: cam !! the cursor's ray and the pick's settings real(wp), intent(in) :: to_root(4,4), center(3), axes(3,3), radii(3) !! center, axes: frame coordinates logical, intent(in) :: geodetic !! (true: also the hit's geodetic latitude and longitude) type(PickHit), allocatable, intent(inout) :: hits(:) !! hits so far (grown as needed) integer, intent(inout) :: n !! number of hits in hits type(PickHit) :: h real(wp) :: origin(3), dir(3), along, local(3), normal(3) hit = .false. if (.not. wants(cam, PICK_BODY)) return call ray(cam, origin, dir) hit = ray_ellipsoid(origin, dir, matmul(to_root(1:3, 1:3), center) + to_root(1:3, 4), & matmul(to_root(1:3, 1:3), axes), radii, along, h%position, local) if (hit) hit = dot_product(h%position - cam%eye, cam%forward) <= cam%max_depth if (.not. hit) return h%kind = PICK_BODY h%frame => self h%local = matmul(transpose(to_root(1:3, 1:3)), h%position - to_root(1:3, 4)) h%distance = dot_product(h%position - cam%eye, cam%forward) h%pixels = 0.0_wp if (geodetic) then normal = local / radii**2 ! (the surface normal there) h%latitude = asin(max(-1.0_wp, min(1.0_wp, normal(3) / norm2(normal)))) h%longitude = atan2(normal(2), normal(1)) end if call add_pick_hit(hits, n, h) end function pick_ellipsoid