pick_ellipsoid Function

public function pick_ellipsoid(self, cam, to_root, center, axes, radii, geodetic, hits, n) result(hit)

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.

Arguments

Type IntentOptional 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

Return Value logical


Calls

proc~~pick_ellipsoid~~CallsGraph proc~pick_ellipsoid pick_ellipsoid proc~add_pick_hit add_pick_hit proc~pick_ellipsoid->proc~add_pick_hit proc~ray ray proc~pick_ellipsoid->proc~ray proc~ray_ellipsoid ray_ellipsoid proc~pick_ellipsoid->proc~ray_ellipsoid proc~wants wants proc~pick_ellipsoid->proc~wants

Called by

proc~~pick_ellipsoid~~CalledByGraph proc~pick_ellipsoid pick_ellipsoid proc~model_pick Model%model_pick proc~model_pick->proc~pick_ellipsoid proc~sphere_pick Sphere%sphere_pick proc~sphere_pick->proc~pick_ellipsoid proc~terrain_pick TerrainBody%terrain_pick proc~terrain_pick->proc~pick_ellipsoid

Source Code

    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