Where the ray (origin, unit dir; root frame) meets the constraint taken
at the grab, the frame at transform m to the root: h, in the frame's
coordinates. False if it doesn't.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(DragHandle), | intent(in) | :: | self | |||
| real(kind=wp), | intent(in) | :: | origin(3) |
the cursor's ray: its origin (root frame) |
||
| real(kind=wp), | intent(in) | :: | dir(3) |
its direction (a unit vector) |
||
| real(kind=wp), | intent(in) | :: | m(4,4) |
the frame's transform to the root |
||
| real(kind=wp), | intent(out) | :: | h(3) |
where it meets the constraint (frame coordinates) |
logical function constrained(self, origin, dir, m, h) result(ok) class(DragHandle), intent(in) :: self real(wp), intent(in) :: origin(3) !! the cursor's ray: its origin (root frame) real(wp), intent(in) :: dir(3) !! its direction (a unit vector) real(wp), intent(in) :: m(4,4) !! the frame's transform to the root real(wp), intent(out) :: h(3) !! where it meets the constraint (frame coordinates) real(wp) :: p(3), a(3), c(3), w(3), q(3), t, near, far c = m(1:3, 4) p = matmul(m(1:3, 1:3), self%ref_point) + c a = matmul(m(1:3, 1:3), self%ref_axis) h = self%ref_point select case (self%constraint_) case (HANDLE_FREE, HANDLE_PLANE) ok = ray_plane(origin, dir, p, a, t, w) case (HANDLE_LINE, HANDLE_RADIAL) ok = ray_line(origin, dir, p, a, t, w) case (HANDLE_SPHERE) ok = self%radius > 0.0_wp if (.not. ok) return if (ray_sphere(origin, dir, c, self%radius, near, far)) then t = near if (self%far_side .or. near < 0.0_wp) t = far w = origin + t * dir else ! (missed: the edge nearest the ray) q = origin + max(0.0_wp, dot_product(c - origin, dir)) * dir ok = norm2(q - c) > 0.0_wp if (.not. ok) return w = c + self%radius * (q - c) / norm2(q - c) end if case default ok = .false. end select if (ok) h = matmul(transpose(m(1:3, 1:3)), w - c) end function constrained