curve_pick Subroutine

private subroutine curve_pick(a, frame, cam, m, hits, n)

A curve's best hit: on the segments drawn (and the trace tail).

Arguments

Type IntentOptional Attributes Name
class(CurveArtist), intent(in), target :: a

the artist

class(ReferenceFrame), intent(in), target :: frame

the frame drawing it (for the hit)

type(PickCamera), intent(in) :: cam

the pick camera

real(kind=wp), intent(in) :: m(4,4)

the frame's transform to the root frame

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

hits are added to hits(1:n)

integer, intent(inout) :: n

number of hits


Calls

proc~~curve_pick~~CallsGraph proc~curve_pick curve_pick chunk_bounds chunk_bounds proc~curve_pick->chunk_bounds is_built is_built proc~curve_pick->is_built num_chunks num_chunks proc~curve_pick->num_chunks positions positions proc~curve_pick->positions proc~add_pick_hit add_pick_hit proc~curve_pick->proc~add_pick_hit proc~art_point art_point proc~curve_pick->proc~art_point proc~better better proc~curve_pick->proc~better proc~is_position_xyz is_position_xyz proc~curve_pick->proc~is_position_xyz proc~point_pick point_pick proc~curve_pick->proc~point_pick proc~segment_pick segment_pick proc~curve_pick->proc~segment_pick proc~sphere_near sphere_near proc~curve_pick->proc~sphere_near proc~transformed transformed proc~curve_pick->proc~transformed proc~point~2 Trajectory%point proc~art_point->proc~point~2 proc~to_shown_at to_shown_at proc~art_point->proc~to_shown_at proc~project project proc~point_pick->proc~project proc~segment_pick->proc~project proc~sphere_near->proc~project proc~to_shown_at->proc~transformed proc~to_shown to_shown proc~to_shown_at->proc~to_shown proc~data_to_shown data_to_shown proc~to_shown->proc~data_to_shown proc~moves moves proc~to_shown->proc~moves proc~rigid_inverse rigid_inverse proc~data_to_shown->proc~rigid_inverse proc~world_matrix_at ReferenceFrame%world_matrix_at proc~data_to_shown->proc~world_matrix_at proc~moves->proc~moves proc~is_following ReferenceFrame%is_following proc~moves->proc~is_following proc~num_parents ReferenceFrame%num_parents proc~moves->proc~num_parents proc~parent ReferenceFrame%parent proc~moves->proc~parent proc~num_trajectories TrajectoryFollower%num_trajectories proc~is_following->proc~num_trajectories proc~world_matrix_at->proc~world_matrix_at proc~local_matrix_at ReferenceFrame%local_matrix_at proc~world_matrix_at->proc~local_matrix_at proc~followed_pose followed_pose proc~local_matrix_at->proc~followed_pose proc~frame_matrix frame_matrix proc~local_matrix_at->proc~frame_matrix proc~followed_pose->proc~rigid_inverse proc~followed_pose->proc~world_matrix_at proc~quat_from_matrix quat_from_matrix proc~followed_pose->proc~quat_from_matrix proc~quat_multiply quat_multiply proc~followed_pose->proc~quat_multiply proc~quat_normalize quat_normalize proc~followed_pose->proc~quat_normalize proc~state_at TrajectoryFollower%state_at proc~followed_pose->proc~state_at proc~quat_to_matrix quat_to_matrix proc~frame_matrix->proc~quat_to_matrix proc~chosen_trajectory chosen_trajectory proc~state_at->proc~chosen_trajectory proc~data_valid TrajectoryFollower%data_valid proc~state_at->proc~data_valid proc~interpolate_attitude interpolate_attitude proc~state_at->proc~interpolate_attitude proc~interpolate_position interpolate_position proc~state_at->proc~interpolate_position proc~time_index Trajectory%time_index proc~state_at->proc~time_index proc~wrapped_time wrapped_time proc~state_at->proc~wrapped_time proc~time_distance Trajectory%time_distance proc~chosen_trajectory->proc~time_distance proc~verify_data Trajectory%verify_data proc~data_valid->proc~verify_data proc~attitude~3 Trajectory%attitude proc~interpolate_attitude->proc~attitude~3 proc~num_attitudes Trajectory%num_attitudes proc~interpolate_attitude->proc~num_attitudes proc~quat_slerp quat_slerp proc~interpolate_attitude->proc~quat_slerp proc~interpolate_position->proc~point~2 proc~num_points Trajectory%num_points proc~interpolate_position->proc~num_points proc~point_between Trajectory%point_between proc~interpolate_position->proc~point_between proc~time_index->proc~time_distance proc~time_range~3 Trajectory%time_range proc~wrapped_time->proc~time_range~3 proc~point_between->proc~point~2 proc~point_between->proc~num_points proc~time_fraction Trajectory%time_fraction proc~point_between->proc~time_fraction

Called by

proc~~curve_pick~~CalledByGraph proc~curve_pick curve_pick proc~drawable_pick DrawableTrajectory%drawable_pick proc~drawable_pick->proc~curve_pick

Source Code

    subroutine curve_pick(a, frame, cam, m, hits, n)
        class(CurveArtist), intent(in), target :: a !! the artist
        class(ReferenceFrame), intent(in), target :: frame  !! the frame drawing it (for the hit)
        type(PickCamera), intent(in) :: cam         !! the pick camera
        real(wp), intent(in) :: m(4,4)              !! the frame's transform to the root frame
        type(PickHit), allocatable, intent(inout) :: hits(:)  !! hits are added to hits(1:n)
        integer, intent(inout) :: n                 !! number of hits
        real(wp), dimension(:,:), pointer :: pos
        real(wp) :: extra, lo(3), hi(3), c(3), p0(3), p1(3), px, s, depth, best_px, best_depth, best_s, t0, t1, frac
        integer :: j, first, count, i1, i2, i, best_i, best_j, nd, d1, d2
        logical :: xyz
        type(PickHit) :: h
        if (.not. associated(a%traj) .or. .not. a%chain%is_built()) return
        nd = a%n_drawn
        if (nd < 1) return
        d1 = a%first_drawn_                                     ! (the points drawn: d1 .. d2)
        d2 = d1 + nd - 1
        extra = 0.5_wp * a%width_ * cam%pixel_ratio
        xyz = is_position_xyz(a%sources_) .and. .not. transformed(a)   ! (transformed: art_point)
        if (xyz) call a%traj%positions(pos)
        best_px = huge(1.0_wp)
        best_depth = huge(1.0_wp)
        best_i = 0
        best_j = 0                                              ! (the hit is between points best_i and best_j)
        best_s = 0.0_wp
        if (nd == 1) then                                       ! (a single point)
            if (point_pick(cam, root_point(d1), px, depth, extra)) then
                best_px = px
                best_depth = depth
                best_i = d1
            end if
        end if
        do j = 1, a%chain%num_chunks()                          ! the segments drawn, chunk by chunk
            call a%chain%chunk_bounds(j, first, count, lo, hi)
            i1 = max(first, d1)
            i2 = min(first + count - 1, d2)
            if (count < 2 .or. i2 <= i1) cycle
            c = matmul(m(1:3, 1:3), 0.5_wp * (lo + hi)) + m(1:3, 4)
            if (.not. sphere_near(cam, c, 0.5_wp * norm2(hi - lo), extra)) cycle       ! (a chunk far off: skipped)
            p0 = root_point(i1)
            do i = i1, i2 - 1
                p1 = root_point(i + 1)
                if (segment_pick(cam, p0, p1, px, s, depth, extra)) then
                    if (better(px, depth, best_px, best_depth)) then
                        best_px = px
                        best_depth = depth
                        best_i = i
                        best_j = i + 1
                        best_s = s
                    end if
                end if
                p0 = p1
            end do
        end do
        ! trace mode: the tail from the latest point passed to the point at the time drawn
        if (a%trace .and. a%tail_shown) then
            t0 = a%traj%time(a%tail_from)
            t1 = a%traj%time(a%tail_to)
            frac = 0.0_wp
            if (t1 /= t0) frac = max(0.0_wp, min(1.0_wp, (a%tail_time - t0) / (t1 - t0)))
            p0 = root_point(a%tail_from)
            p1 = p0 + frac * (root_point(a%tail_to) - p0)
            if (segment_pick(cam, p0, p1, px, s, depth, extra)) then
                if (better(px, depth, best_px, best_depth)) then
                    best_px = px
                    best_depth = depth
                    best_i = a%tail_from
                    best_j = a%tail_to
                    best_s = s * frac
                end if
            end if
        end if
        if (best_i == 0) return
        h%kind = PICK_CURVE
        h%frame => frame
        h%artist => a
        h%trajectory => a%traj
        h%index = best_i
        if (best_j > 0) h%index = min(best_i, best_j)           ! (the point the hit is after, in point order)
        h%local = local_point(best_i)
        h%time = a%traj%time(best_i)
        if (best_j > 0) then
            h%local = h%local + best_s * (local_point(best_j) - h%local)
            h%time = h%time + best_s * (a%traj%time(best_j) - h%time)
        end if
        h%position = matmul(m(1:3, 1:3), h%local) + m(1:3, 4)
        h%distance = best_depth
        h%pixels = best_px
        call add_pick_hit(hits, n, h)

    contains

        !> Point i in the frame's coordinates (straight from the positions if they are the sources).
        function local_point(i) result(v)
            integer, intent(in) :: i                        !! the trajectory point
            real(wp) :: v(3)
            if (xyz) then
                v = pos(:, i)
            else
                v = art_point(a, i, a%sources_)
            end if
        end function local_point

        !> Point i in the root frame.
        function root_point(i) result(v)
            integer, intent(in) :: i                        !! the trajectory point
            real(wp) :: v(3)
            v = matmul(m(1:3, 1:3), local_point(i)) + m(1:3, 4)
        end function root_point

    end subroutine curve_pick