Where the ray (origin, unit dir) first meets the ellipsoid centered at
center with semi-axes radii along the columns of axes (unit
vectors): the distance along the ray, the point, and the point in the
ellipsoid's axes (from its center). False if it misses (or the
ellipsoid is behind).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | origin(3) |
the ray (dir: a unit vector) |
||
| real(kind=wp), | intent(in) | :: | dir(3) |
the ray (dir: a unit vector) |
||
| real(kind=wp), | intent(in) | :: | center(3) |
the ellipsoid's center |
||
| real(kind=wp), | intent(in) | :: | axes(3,3) |
its axes (columns: unit vectors) |
||
| real(kind=wp), | intent(in) | :: | radii(3) |
its semi-axes along them |
||
| real(kind=wp), | intent(out) | :: | distance |
along the ray (huge() if missed) |
||
| real(kind=wp), | intent(out) | :: | point(3) |
the point met |
||
| real(kind=wp), | intent(out) | :: | local(3) |
the point in the ellipsoid's axes, from its center |
logical function ray_ellipsoid(origin, dir, center, axes, radii, distance, point, local) result(hit) real(wp), intent(in) :: origin(3), dir(3) !! the ray (dir: a unit vector) real(wp), intent(in) :: center(3) !! the ellipsoid's center real(wp), intent(in) :: axes(3,3) !! its axes (columns: unit vectors) real(wp), intent(in) :: radii(3) !! its semi-axes along them real(wp), intent(out) :: distance !! along the ray (huge() if missed) real(wp), intent(out) :: point(3) !! the point met real(wp), intent(out) :: local(3) !! the point in the ellipsoid's axes, from its center real(wp) :: o(3), d(3), qa, qb, qc, disc, t hit = .false. distance = huge(1.0_wp) point = 0.0_wp local = 0.0_wp if (any(radii <= 0.0_wp)) return o = matmul(transpose(axes), origin - center) / radii ! (the unit sphere) d = matmul(transpose(axes), dir) / radii qa = dot_product(d, d) qb = 2.0_wp * dot_product(o, d) qc = dot_product(o, o) - 1.0_wp disc = qb * qb - 4.0_wp * qa * qc if (disc < 0.0_wp .or. qa <= 0.0_wp) return t = (-qb - sqrt(disc)) / (2.0_wp * qa) if (t < 0.0_wp) t = (-qb + sqrt(disc)) / (2.0_wp * qa) ! (the eye inside it: where the ray leaves) if (t < 0.0_wp) return distance = t point = origin + t * dir local = (o + t * d) * radii hit = .true. end function ray_ellipsoid