Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-12 08:27:03

0001 #pragma once
0002 
0003 /**
0004  * @file csg_intersect_leaf_phi_wedge.h
0005  *
0006  * Shared angular clipping helpers for centred CSG leaf primitives.
0007  *
0008  * Partial-phi spheres and cylinders store their angular interval directly in the
0009  * leaf parameter quad:
0010  *
0011  *     q0.f.x = startPhi
0012  *     q0.f.y = deltaPhi
0013  *
0014  * Angles are in radians and describe a counter-clockwise sweep about the positive
0015  * z axis, starting at `startPhi`. The interval includes both radial boundary
0016  * half-planes and the z axis. A wedge is active only for
0017  * `0 < deltaPhi < 2*pi`; values outside that range preserve the legacy unclipped
0018  * primitive.
0019  *
0020  * These `LEAF_FUNC` helpers are shared by host and device intersection and
0021  * signed-distance implementations. They provide angular classification for
0022  * curved surfaces and caps, a signed field for combining the angular constraint
0023  * with the leaf distance, and intersections with the two radial walls. Wall
0024  * intersections are clipped only to the outward radial half-plane here; callers
0025  * must additionally apply the primitive's radial, axial, and `t_min` constraints.
0026  */
0027 
0028 /**
0029  * Reports whether an angular interval clips a full primitive.
0030  *
0031  * @param deltaPhi Counter-clockwise angular sweep in radians.
0032  * @return `true` only for a positive sweep strictly smaller than a full circle.
0033  *         Non-positive and at-least-full-circle sweeps are treated as unclipped.
0034  */
0035 LEAF_FUNC
0036 bool csg_has_phi_wedge(const float deltaPhi)
0037 {
0038     return deltaPhi > 0.f && deltaPhi < 2.f * CUDART_PI_F;
0039 }
0040 
0041 /**
0042  * Computes the counter-clockwise azimuthal displacement from `startPhi`.
0043  *
0044  * The result is normalized to the half-open interval `[0, 2*pi)`, which also
0045  * makes intervals whose end angle crosses phi zero straightforward to test.
0046  * Callers that need special handling at the z axis should do so before invoking
0047  * this helper because azimuth is undefined there.
0048  *
0049  * @param x Point x coordinate relative to the primitive centre.
0050  * @param y Point y coordinate relative to the primitive centre.
0051  * @param startPhi Angular origin of the wedge in radians.
0052  * @return Normalized counter-clockwise displacement from `startPhi`, in radians.
0053  */
0054 LEAF_FUNC
0055 float csg_phi_delta(const float x, const float y, const float startPhi)
0056 {
0057     const float twoPi = 2.f * CUDART_PI_F;
0058     float       dphi = atan2f(y, x) - startPhi;
0059     while (dphi < 0.f) dphi += twoPi;
0060     while (dphi >= twoPi) dphi -= twoPi;
0061     return dphi;
0062 }
0063 
0064 /**
0065  * Tests whether an xy point lies within an inclusive phi interval.
0066  *
0067  * Inactive wedges accept every point. Points sufficiently close to the z axis
0068  * are also accepted because they belong to both radial boundary half-planes.
0069  * A small angular tolerance includes points lying numerically on the end wall.
0070  *
0071  * @param x Point x coordinate relative to the primitive centre.
0072  * @param y Point y coordinate relative to the primitive centre.
0073  * @param startPhi Start angle of the counter-clockwise interval, in radians.
0074  * @param deltaPhi Angular sweep of the interval, in radians.
0075  * @return `true` when the point is inside or on the wedge, or when no wedge is
0076  *         active.
0077  */
0078 LEAF_FUNC
0079 bool csg_in_phi_wedge(const float x, const float y, const float startPhi, const float deltaPhi)
0080 {
0081     if (!csg_has_phi_wedge(deltaPhi))
0082         return true;
0083 
0084     const float radial2 = x * x + y * y;
0085     if (radial2 < 1.e-12f)
0086         return true;
0087 
0088     return csg_phi_delta(x, y, startPhi) <= deltaPhi + 1.e-6f;
0089 }
0090 
0091 /**
0092  * Evaluates a signed field for the angular wedge constraint.
0093  *
0094  * Negative values classify points inside the wedge, positive values classify
0095  * points outside, and zero identifies either radial wall. For sweeps no larger
0096  * than pi the wedge is the intersection of the two inward half-spaces, so their
0097  * signed plane fields are combined with `max`. For larger "pacman" sweeps the
0098  * wedge is their union and `min` is used instead.
0099  *
0100  * This helper assumes an active wedge (`0 < deltaPhi < 2*pi`). It is intended as
0101  * a classification-compatible field to combine with another leaf distance, not
0102  * as a general Euclidean distance to every feature of the finite primitive.
0103  *
0104  * @param x Point x coordinate relative to the primitive centre.
0105  * @param y Point y coordinate relative to the primitive centre.
0106  * @param startPhi Start angle of the counter-clockwise interval, in radians.
0107  * @param deltaPhi Angular sweep of the interval, in radians.
0108  * @return Signed angular-wedge field: negative inside, positive outside.
0109  */
0110 LEAF_FUNC
0111 float csg_distance_phi_wedge(const float x, const float y, const float startPhi, const float deltaPhi)
0112 {
0113     const float endPhi = startPhi + deltaPhi;
0114     const float sinStart = sinf(startPhi);
0115     const float cosStart = cosf(startPhi);
0116     const float sinEnd = sinf(endPhi);
0117     const float cosEnd = cosf(endPhi);
0118 
0119     const float sdStart = x * sinStart - y * cosStart;
0120     const float sdEnd = -x * sinEnd + y * cosEnd;
0121 
0122     return deltaPhi <= CUDART_PI_F ? fmaxf(sdStart, sdEnd) : fminf(sdStart, sdEnd);
0123 }
0124 
0125 /**
0126  * Intersects a ray with one radial boundary half-plane of a phi wedge.
0127  *
0128  * The boundary is the half of the vertical plane extending from the z axis in
0129  * the direction `boundaryPhi`. Intersections on the opposite radial half-plane
0130  * are rejected. On success, `(nx, ny)` is the outward unit normal for either the
0131  * start or end wall of a counter-clockwise wedge.
0132  *
0133  * This helper does not reject intersections behind the ray origin and does not
0134  * clip against a primitive radius or z extent. The caller must validate `t`
0135  * against `t_min` and its own finite surface bounds. Output values are meaningful
0136  * only when the function returns `true`.
0137  *
0138  * @param[out] t Ray parameter at the wall intersection.
0139  * @param[out] nx Outward wall-normal x component.
0140  * @param[out] ny Outward wall-normal y component.
0141  * @param boundaryPhi Azimuth of the radial boundary half-plane, in radians.
0142  * @param startWall `true` for the interval's start wall, `false` for its end wall.
0143  * @param ox Ray-origin x coordinate relative to the primitive centre.
0144  * @param oy Ray-origin y coordinate relative to the primitive centre.
0145  * @param vx Ray-direction x component.
0146  * @param vy Ray-direction y component.
0147  * @return `true` when the ray is not parallel to the boundary plane and its
0148  *         intersection lies on the outward radial half-plane.
0149  */
0150 LEAF_FUNC
0151 bool csg_intersect_phi_wall(float& t, float& nx, float& ny, const float boundaryPhi, const bool startWall, const float ox, const float oy, const float vx, const float vy)
0152 {
0153     const float sinPhi = sinf(boundaryPhi);
0154     const float cosPhi = cosf(boundaryPhi);
0155     const float denom = vx * sinPhi - vy * cosPhi;
0156 
0157     if (fabsf(denom) <= 1.e-12f)
0158         return false;
0159 
0160     t = -(ox * sinPhi - oy * cosPhi) / denom;
0161 
0162     const float x = ox + t * vx;
0163     const float y = oy + t * vy;
0164 
0165     if (x * cosPhi + y * sinPhi < -1.e-6f)
0166         return false;
0167 
0168     nx = startWall ? sinPhi : -sinPhi;
0169     ny = startWall ? -cosPhi : cosPhi;
0170     return true;
0171 }