Ray-casting routines for constructive solid geometry.
This module provides constructors for complex bodies as well as routines to compute intersections of such bodies with ray. In DSMC it is used to calculate points at which particles hit the body surface.
Gas-surface interactions are not handled by this module, see
- data Body
- plane :: Point -> Vec3 -> Body
- sphere :: Vec3 -> Double -> Body
- cylinder :: Point -> Point -> Double -> Body
- cylinderFrustum :: Point -> Point -> Double -> Body
- cone :: Vec3 -> Point -> Double -> Body
- coneFrustum :: (Point, Double) -> (Point, Double) -> Body
- intersect :: Body -> Body -> Body
- unite :: Body -> Body -> Body
- complement :: Body -> Body
- data HitPoint = HitPoint !Double (Maybe Vec3)
- hitPoint :: Time -> Body -> Particle -> Maybe HitPoint
- type HitSegment = Pair HitPoint HitPoint
- type Trace = [HitSegment]
- trace :: Body -> Particle -> Trace
- inside :: Body -> Particle -> Bool
A half-space defined by arbitary point on the boundary plane and outward normal (not necessarily a unit vector).
An infinite circular cylinder defined by two arbitary points on axis and radius.
A finite right circular cylinder defined by two points on its top and bottom and radius.
An infinite right circular cone defined by outward axis vector, apex point and angle between generatrix and axis (in degrees, less than 90).
A conical frustum given by two points on its axis with radii at that points. One of radii may be zero (in which case one of frustum ends will be the apex).
Time when particle hits the surface with normal at the hit point. If hit is in infinity, then normal is Nothing.
Note that this datatype is strict only on first argument: we do not compare normals when classifying traces.
If the particle has hit the body during last time step, calculate
the first corresponding
HitPoint. Note that the time at which the hit
occured will be negative. This is the primary function to calculate
A segment on time line when particle is inside the body.
Using strict tuple performs better: 100 traces for 350K particles perform roughly 7s against 8s with common datatypes.
Trace of a linearly-moving particle on a body is a list of time segments/intervals during which the particle is inside the body.
# - particle \ \ o------------ ---/ * \--- -/ * \- / * \ ( * - trace ) \ * / -\ * /- primitive - ---\ * /--- --------o---- \ \ _\/ \
For example, since a ray intersects a plane only once, a half-space primitive defined by this plane results in a half-interval trace of a particle:
/ / / #------------------------o*****************> | / | particle / goes to infinity / / / / - surface of half-space
Ends of segments or intervals are calculated by intersecting the
trajectory ray of a particle and the surface of the primitive. This
may be done by substituting the equation of trajectory
X(t) = X_o
+ V*t into the equation which defines the surface and solving it
t. If the body is a composition, traces from primitives are
then classified according to operators used to define the body
(union, intersection or complement).
Although only convex primitives are used in current implementation, compositions may result in concave bodies, which is why trace is defined as a list of segments.
In this example, body is an intersection of a sphere and sphere complement:
/|\ | | | ----------- | ----/ \--o- -/ * \- -/ hs2 - * \ -/ * ---/ / o/ / -/| / / | | / | / | | | / | | | | | \ | \ | | | \ | \ \ | \ -\| \ o\ -\ * ---\ -\ hs1 - * / -\ * /- ----\ /--o- ----------- | | | # - particle
If only intersections of concave primitives were allowed, then
trace type might be simplified to be just single