RNClassID R3Span:: Clip(const R3Plane& plane) { // Characterize endpoints with respect to plane RNScalar d1 = R3SignedDistance(plane, Start()); RNScalar d2 = R3SignedDistance(plane, End()); // Clip span to plane if (RNIsNegative(d1)) { if (RNIsNegative(d2)) { // Both points are below plane ??? Reset(Start(), Start()); return RN_NULL_CLASS_ID; } else if (RNIsPositive(d2)) { // Start is below, end is above -- move start to plane Reset((Start() * d2 + End() * -d1) / (d2 - d1), End()); return R3_SPAN_CLASS_ID; } else { // Start is below, end is on -- move start to end Reset(End(), End()); return R3_POINT_CLASS_ID; } } else if (RNIsPositive(d1)) { if (RNIsNegative(d2)) { // Start is above, end is below -- move end to plane Reset(Start(), (Start() * -d2 + End() * d1) / (d1 - d2)); return R3_SPAN_CLASS_ID; } else { // Start is above, end is on or above return R3_SPAN_CLASS_ID; } } else { if (RNIsNegative(d2)) { // Start is on, end is below -- move end to start Reset(Start(), Start()); return R3_POINT_CLASS_ID; } else { // Start is on, end is on or above return R3_SPAN_CLASS_ID; } } }
RNLength R2Distance(const R2Point& point, const R2Halfspace& halfspace) { // Return distance from point to halfspace RNScalar d = R2SignedDistance(halfspace.Line(), point); if (RNIsNegative(d)) return -d; else return 0.0; }
RNLength R2Distance(const R2Span& span, const R2Halfspace& halfspace) { // Return distance from span to halfspace RNScalar d = R2SignedDistance(halfspace.Line(), span); if (RNIsNegative(d)) return -d; else return 0.0; }
RNLength R2Distance(const R2Ray& ray, const R2Halfspace& halfspace) { // Return distance from ray to halfspace RNScalar d = R2SignedDistance(halfspace.Line(), ray); if (RNIsNegative(d)) return -d; else return 0.0; }
const RNBoolean R3Matrix:: HasMirror(void) const { // Return whether matrix transformation has mirror operator R2Vector vx(m[0][0], m[1][0]); R2Vector vy(m[0][1], m[1][1]); return RNIsNegative(vx % vy); }
RNLength R2Distance(const R2Line& line, const R2Span& span) { // Return distance from span to line RNScalar d = R2SignedDistance(line, span); if (RNIsPositive(d)) return d; else if (RNIsNegative(d)) return -d; else return 0.0; }
const RNBoolean R4Matrix:: HasMirror(void) const { // Return whether matrix transformation has mirror operator R3Vector vx(m[0][0], m[1][0], m[2][0]); R3Vector vy(m[0][1], m[1][1], m[2][1]); R3Vector vz(m[0][2], m[1][2], m[2][2]); return RNIsNegative(vz.Dot(vx % vy)); }
RNLength R2Distance(const R2Point& point, const R2Ray& ray) { // Check if start point is closest R2Vector v = point - ray.Start(); RNScalar dir = v.Dot(ray.Vector()); if (RNIsNegative(dir)) return v.Length(); // Return distance from point to ray line return R2Distance(point, ray.Line()); }
RNLength R2SignedDistance(const R2Line& line, const R2Box& box) { // Return signed distance from line to box RNQuadrant quadrant = line.Normal().Quadrant(); RNScalar d1 = R2SignedDistance(line, box.Corner(~quadrant & 0x3)); if (RNIsPositiveOrZero(d1)) return d1; RNScalar d2 = R2SignedDistance(line, box.Corner(quadrant)); if (RNIsNegative(d2)) return d2; else return 0.0; }
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Circle& circle) { // Return whether halfspace contains circle RNScalar d = R3SignedDistance(halfspace.Plane(), circle.Center()); if (RNIsNegative(d)) return FALSE; else if (RNIsGreater(d, circle.Radius())) return TRUE; else { RNScalar cos_theta = halfspace.Plane().Normal().Dot(circle.Normal()); if (cos_theta < 0.0) cos_theta = halfspace.Plane().Normal().Dot(-circle.Normal()); return (RNIsGreaterOrEqual(d, cos_theta * circle.Radius())); } }
RNLength R2SignedDistance(const R2Line& line, const R2Span& span) { // Return signed distance from line to span RNLength d1 = R2SignedDistance(line, span.Start()); if (RNIsPositive(d1)) { // Start point is above line RNLength d2 = R2SignedDistance(line, span.End()); if (RNIsPositive(d2)) return ((d1 > d2) ? d2 : d1); else return 0.0; } else if (RNIsNegative(d1)) { // Start point is below line RNLength d2 = R2SignedDistance(line, span.End()); if (RNIsNegative(d2)) return ((d1 > d2) ? d1 : d2); else return 0.0; } else { // Start point is on line return 0.0; } }
RNBoolean R3Contains(const R3Cylinder& cylinder, const R3Point& point) { // Get cylinder axis const R3Span& axis = cylinder.Axis(); // Check if outside top or bottom RNScalar t = axis.T(point); if (RNIsNegative(t) || RNIsGreater(t, axis.Length())) return FALSE; // Check if inside radius RNLength d = R3Distance(point, axis.Point(t)); return (RNIsLessOrEqual(d, cylinder.Radius())); }
RNBoolean R3Contains(const R3Cone& cone, const R3Point& point) { // Get cone axis const R3Span& axis = cone.Axis(); // Check if outside top or bottom RNScalar t = axis.T(point); if (RNIsNegative(t) || RNIsGreater(t, axis.Length())) return FALSE; // Check if inside radius RNLength r = (1.0 - t / axis.Length()) * cone.Radius(); RNLength d = R3Distance(axis.Point(t), point); return RNIsGreaterOrEqual(r, d); }
RNBoolean R3Contains(const R3Triangle& triangle, const R3Point& point) { // Check whether triangle bounding shape contains point if (!R3Contains(triangle.Box(), point)) return FALSE; // Check whether triangle plane contains point if (!R3Contains(triangle.Plane(), point)) return FALSE; // Compute whether point is on correct side of each edge const R3Point& p0 = triangle.Vertex(0)->Position(); const R3Point& p1 = triangle.Vertex(1)->Position(); const R3Point& p2 = triangle.Vertex(2)->Position(); R3Plane h01(p1, triangle.Normal(), p1 - p0); if (RNIsNegative(R3SignedDistance(h01, point))) return FALSE; R3Plane plane01(p1, triangle.Normal(), p1 - p0); if (RNIsNegative(R3SignedDistance(plane01, point))) return FALSE; R3Plane plane12(p2, triangle.Normal(), p2 - p1); if (RNIsNegative(R3SignedDistance(plane12, point))) return FALSE; R3Plane plane20(p0, triangle.Normal(), p0 - p2); if (RNIsNegative(R3SignedDistance(plane20, point))) return FALSE; // Triangle contains point return TRUE; }
RNLength R2Distance(const R2Point& point, const R2Span& span) { // Check span if (RNIsZero(span.Length())) return R2Distance(point, span.Start()); // Check if start point is closest R2Vector v1 = point - span.Start(); RNScalar dir1 = v1.Dot(span.Vector()); if (RNIsNegative(dir1)) return v1.Length(); // Check if end point is closest R2Vector v2 = point - span.End(); RNScalar dir2 = v2.Dot(span.Vector()); if (RNIsPositive(dir2)) return v2.Length(); // Return distance from point to span line return R2Distance(point, span.Line()); }