window_pick Subroutine

private subroutine window_pick(self, x, y, hits, tolerance, kinds, nearest)

What is under point (x, y) of the window (-1 to 1 across it, y up: as the event handler's positions), nearest first (see the module documentation): none before the first frame. tolerance: how close lines, markers and frames' origins must be, in window units (logical pixels; default 4), beyond half a line's width or a marker's size. kinds: only hits of these kinds (PICK_*; the others aren't tested). nearest: only the nearest hit (cheaper: what is deeper than a hit found is skipped, e.g. to pick on every mouse move). Frames and artists can be left out (set_pickable(.false.)).

What was clicked, from a WindowEventHandler extension's button_press (registered with window%set_event_handler(handler)):

subroutine on_click(self, window, x, y, button)
    class(ClickPicker), intent(inout) :: self
    class(WindowProxy), intent(inout) :: window
    real(wp), intent(in) :: x, y
    integer, intent(in) :: button
    type(PickHit), allocatable :: hits(:)
    call window%pick(x, y, hits)
    if (size(hits) == 0) return
    select case (hits(1)%kind)
    case (PICK_CURVE)
        write(*, '(a,f0.1,a)') 'picked the orbit at t = ', hits(1)%time, ' s'
    case (PICK_BODY)
        write(*, '(a,2f8.2)') 'picked '//hits(1)%frame%name()//' at lat, lon (deg) ', &
            hits(1)%latitude * 180.0_wp / pi, hits(1)%longitude * 180.0_wp / pi
    end select
end subroutine on_click

Type Bound

WindowProxy

Arguments

Type IntentOptional Attributes Name
class(WindowProxy), intent(in), target :: self
real(kind=wp), intent(in) :: x

-1 to 1 across the window, y up

real(kind=wp), intent(in) :: y

-1 to 1 across the window, y up

type(PickHit), intent(out), allocatable :: hits(:)

what is there, nearest first

real(kind=wp), intent(in), optional :: tolerance

window units (default 4)

integer, intent(in), optional :: kinds(:)

PICK_* (default: all)

logical, intent(in), optional :: nearest

default false


Calls

proc~~window_pick~~CallsGraph proc~window_pick WindowProxy%window_pick proc~child ReferenceFrame%child proc~window_pick->proc~child proc~fm_frame FrameManager%fm_frame proc~window_pick->proc~fm_frame proc~identity_matrix identity_matrix proc~window_pick->proc~identity_matrix proc~local_matrix ReferenceFrame%local_matrix proc~window_pick->proc~local_matrix proc~num_children ReferenceFrame%num_children proc~window_pick->proc~num_children proc~pick ReferenceFrame%pick proc~window_pick->proc~pick proc~pickable ReferenceFrame%pickable proc~window_pick->proc~pickable proc~view_camera view_camera proc~window_pick->proc~view_camera proc~frame_matrix frame_matrix proc~local_matrix->proc~frame_matrix proc~add_pick_hit add_pick_hit proc~pick->proc~add_pick_hit proc~point_pick point_pick proc~pick->proc~point_pick proc~wants wants proc~pick->proc~wants interface~vkf_viewer_pixel_ratio vkf_viewer_pixel_ratio proc~view_camera->interface~vkf_viewer_pixel_ratio interface~vkf_viewer_size vkf_viewer_size proc~view_camera->interface~vkf_viewer_size proc~aspect_ratio aspect_ratio proc~view_camera->proc~aspect_ratio proc~field_of_view View%field_of_view proc~view_camera->proc~field_of_view proc~get_camera WindowProxy%get_camera proc~view_camera->proc~get_camera proc~is_open WindowProxy%is_open proc~view_camera->proc~is_open proc~orthographic_bounds View%orthographic_bounds proc~view_camera->proc~orthographic_bounds proc~pick_camera pick_camera proc~view_camera->proc~pick_camera proc~projection_type View%projection_type proc~view_camera->proc~projection_type proc~aspect_ratio->interface~vkf_viewer_size proc~quat_to_matrix quat_to_matrix proc~frame_matrix->proc~quat_to_matrix proc~get_camera->proc~is_open interface~vkf_viewer_get_look_at vkf_viewer_get_look_at proc~get_camera->interface~vkf_viewer_get_look_at proc~rigid_inverse rigid_inverse proc~get_camera->proc~rigid_inverse proc~transform_camera transform_camera proc~get_camera->proc~transform_camera proc~world_to_view View%world_to_view proc~get_camera->proc~world_to_view proc~cross cross proc~pick_camera->proc~cross proc~project project proc~point_pick->proc~project proc~world_to_view->proc~identity_matrix proc~world_to_view->proc~quat_to_matrix proc~world_to_view->proc~rigid_inverse proc~frame_to_root frame_to_root proc~world_to_view->proc~frame_to_root proc~quat_from_vectors quat_from_vectors proc~world_to_view->proc~quat_from_vectors proc~rotated rotated proc~world_to_view->proc~rotated proc~translation_matrix translation_matrix proc~world_to_view->proc~translation_matrix proc~frame_to_root->proc~rigid_inverse proc~world_matrix ReferenceFrame%world_matrix proc~frame_to_root->proc~world_matrix proc~quat_from_vectors->proc~cross proc~quat_normalize quat_normalize proc~quat_from_vectors->proc~quat_normalize proc~translation_matrix->proc~identity_matrix proc~world_matrix->proc~local_matrix proc~world_matrix->proc~world_matrix

Called by

proc~~window_pick~~CalledByGraph proc~window_pick WindowProxy%window_pick proc~hover_handle hover_handle proc~hover_handle->proc~window_pick proc~dispatch_event dispatch_event proc~dispatch_event->proc~hover_handle proc~release_handle release_handle proc~dispatch_event->proc~release_handle proc~release_handle->proc~hover_handle proc~dispatch_events dispatch_events proc~dispatch_events->proc~dispatch_event proc~frame WindowProxy%frame proc~frame->proc~dispatch_events proc~resize WindowProxy%resize proc~resize->proc~frame proc~run WindowProxy%run proc~run->proc~frame

Source Code

    subroutine window_pick(self, x, y, hits, tolerance, kinds, nearest)
        class(WindowProxy), intent(in), target :: self
        real(wp), intent(in) :: x, y                        !! -1 to 1 across the window, y up
        type(PickHit), allocatable, intent(out) :: hits(:)  !! what is there, nearest first
        real(wp), intent(in), optional :: tolerance         !! window units (default 4)
        integer, intent(in), optional :: kinds(:)           !! PICK_* (default: all)
        logical, intent(in), optional :: nearest            !! default false
        class(ReferenceFrame), pointer :: root
        type(PickCamera) :: cam
        type(PickHit) :: h
        integer :: n, i, j
        logical :: only_nearest
        n = 0
        only_nearest = .false.
        if (present(nearest)) only_nearest = nearest
        allocate(hits(8))
        root => null()
        if (associated(self%scene)) root => self%scene%frame()
        if (.not. associated(root) .or. .not. view_camera(self, x, y, cam)) then
            hits = hits(1:0)
            return
        end if
        cam%tolerance = 4.0_wp * cam%pixel_ratio
        if (present(tolerance)) cam%tolerance = tolerance * cam%pixel_ratio
        if (present(kinds)) then
            cam%kinds = 0
            do i = 1, size(kinds)
                if (kinds(i) >= 0 .and. kinds(i) < bit_size(cam%kinds)) cam%kinds = ibset(cam%kinds, kinds(i))
            end do
        end if
        call pick_frame(root, identity_matrix())                  ! (the root frame's coordinates: the camera's)
        do i = 2, n                                               ! nearest first
            h = hits(i)
            j = i - 1
            do while (j >= 1)
                if (hits(j)%distance <= h%distance) exit
                hits(j + 1) = hits(j)
                j = j - 1
            end do
            hits(j + 1) = h
        end do
        hits = hits(1:n)

    contains

        !> Frame f (at transform m to the root) and its children, under each of
        !> their parents.
        recursive subroutine pick_frame(f, m)
            class(ReferenceFrame), intent(in), target :: f  !! the frame (with its children)
            real(wp), intent(in) :: m(4,4)                  !! f's transform to the root frame
            class(ReferenceFrame), pointer :: c
            integer :: k, best
            if (f%pickable()) call f%pick(cam, m, hits, n)
            if (only_nearest .and. n > 1) then                    ! (keep the nearest; skip what is deeper)
                best = minloc(hits(1:n)%distance, dim=1)
                hits(1) = hits(best)
                n = 1
            end if
            if (only_nearest .and. n == 1) cam%max_depth = hits(1)%distance
            do k = 1, f%num_children()
                c => f%child(k)
                call pick_frame(c, matmul(m, c%local_matrix()))
            end do
        end subroutine pick_frame

    end subroutine window_pick