Last active
October 22, 2020 19:34
-
-
Save villares/af485db805881af5964063587dfe8a0f to your computer and use it in GitHub Desktop.
FreyaHolmer's Mathfs ported to Processing Java!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // https://twitter.com/FreyaHolmer/status/1319278214087258112?s=20 | |
| // FROM: https://github.com/FreyaHolmer/Mathfs/ | |
| /* | |
| TODO: YEAH INTERSECT IT IS HARD... IF ANYONE WANTS TO HELP...! | |
| - CircleFromThreePoints() depends on LineSegment2D and Intersect... | |
| - I have some lazy line segment intersection I could use | |
| but Freya's has cool Rays and infinite lines... | |
| - ... | |
| - Then I'll port everything to Processing Python mode... | |
| */ | |
| class Circle { | |
| PVector center; | |
| float radius; | |
| Circle( PVector center, float radius ) { | |
| this.center = center; | |
| this.radius = radius; | |
| } | |
| Circle(float x, float y, float radius) { | |
| this.center = new PVector(x, y); | |
| this.radius = radius; | |
| } | |
| void draw() { | |
| circle(center.x, center.y, radius * 2); | |
| } | |
| float Area() { | |
| return RadiusToArea(radius); | |
| } | |
| float Circumference() { | |
| return RadiusToCircumference( radius ); | |
| } | |
| float RadiusToArea( float r ) { | |
| return r * r * ( 0.5f * TAU ); | |
| } | |
| float AreaToRadius( float area ) { | |
| return sqrt( 2 * area / TAU ); | |
| } | |
| float AreaToCircumference( float area ) { | |
| return sqrt( 2 * area / TAU ) * TAU; | |
| } | |
| float CircumferenceToArea( float c ) { | |
| return c * c / ( 2 * TAU ); | |
| } | |
| float RadiusToCircumference( float r ) { | |
| return r * TAU; | |
| } | |
| float CircumferenceToRadius( float c ) { | |
| return c / TAU; | |
| } | |
| } | |
| //Circle CircleFromThreePoints( PVector a, PVector b, PVector c) { | |
| // Line2D lineA = LineSegment2D.GetBisectorFast( a, b ); | |
| // Line2D lineB = LineSegment2D.GetBisectorFast( b, c ); | |
| // PVector center = Intersect.Lines( lineA, lineB); | |
| // if (center != null) { | |
| // return new Circle(center, PVector.dist(center, a ); | |
| // ); | |
| // } | |
| // return null; | |
| //} | |
| Circle CircleFromTwoPoints( PVector a, PVector b ) { | |
| return new Circle(PVector.add(a, b).div(2.0), PVector.dist( a, b ) / 2.0); | |
| } | |
| Circle CircleFromTwoPoints(float xa, float ya, float xb, float yb ) { | |
| return CircleFromTwoPoints( new PVector(xa, ya), new PVector(xb, yb)); | |
| } | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 2D line math | |
| class Line2D { | |
| PVector origin; | |
| PVector dir; | |
| Line2D( PVector origin, PVector dir ) { | |
| this.origin = origin; | |
| this.dir = dir; | |
| } | |
| PVector GetPoint( float t ) { | |
| return origin.add(dir.mult(t)); | |
| } | |
| /// Projects a point onto an infinite line | |
| /// "lineOrigin">Line origin | |
| /// "lineDir">Line direction (does not have to be normalized) | |
| /// "point">The point to project onto the line | |
| PVector ProjectPointToLine( PVector lineOrigin, PVector lineDir, PVector point ) { | |
| PVector coord = point.sub(lineOrigin); | |
| float t = PVector.dot( lineDir, coord ) / PVector.dot( lineDir, lineDir ); | |
| return lineOrigin.add(lineDir.mult(t)); | |
| } | |
| /// Projects a point onto an infinite line | |
| /// "line">Line to project onto | |
| /// "point">The point to project onto the line | |
| PVector ProjectPointToLine( Line2D line, PVector point ) { | |
| return ProjectPointToLine( line.origin, line.dir, point ); | |
| } | |
| /// Returns the signed distance to a 2D plane | |
| /// "planeOrigin">Plane origin | |
| /// "planeNormal">Plane normal (has to be normalized for a true distance) | |
| /// "point">The point to use when checking distance to the plane | |
| float PointToPlaneSignedDistance( PVector planeOrigin, PVector planeNormal, PVector point ) { | |
| return PVector.dot( point.sub(planeOrigin), planeNormal ); | |
| } | |
| /// Returns the distance to a 2D plane | |
| /// "planeOrigin">Plane origin | |
| /// "planeNormal">Plane normal (has to be normalized for a true distance) | |
| /// "point">The point to use when checking distance to the plane | |
| float PointToPlaneDistance( PVector planeOrigin, PVector planeNormal, PVector point ) { | |
| return abs( PointToPlaneSignedDistance( planeOrigin, planeNormal, point ) ); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| void setup(){ | |
| size(400, 400); | |
| Circle c0 = new Circle(100, 100, 100); | |
| c0.draw(); | |
| // Circle c1 = CircleFromTwoPoints(new PVector(100, 100), new PVector(200, 200)); | |
| Circle c1 = CircleFromTwoPoints(100, 100, 200, 200); | |
| c1.draw(); | |
| } |
Author
villares
commented
Oct 22, 2020

Work in progres... In Java I don't have "out" parameters (reminds me of VAR in Pascal!).
Vector2 -> PVector
I'm going with null (non-intersecting) or PVector (intersection), I guess.
// static class Intersect {
// These are used to see if an intersection t-value is valid for rays and line segments
// If you want make on-vertex intersections not count, you can tweak that here by changing comparisons
// You can also add margin here if you want to technically count slightly outside/inside as an intersection or not
// (Note that Line isn't range bound, so it's not here. It's always true)
static boolean BoundsTestRay( float t ) {
return t >= 0;
}
static boolean BoundsTestLineSegment( float t ) {
return t >= 0 && t <= 1;
}
// internal
static PVector GetLineLineTValues( PVector aToB, PVector aDir, PVector bDir) {
float d = Determinant( aDir, bDir );
if ( Abs( d ) < PARALLEL_DETERMINANT_THRESHOLD ) {
return null;
}
tA = Determinant( aToB, bDir ) / d;
tB = Determinant( aToB, aDir ) / d;
return new PVector(tA, tB);
}
// Naming order: Ray, LineSegment, Line, Circle
//#region Rays
/// Returns whether or not two rays intersect
public static PVector Rays( Ray2D a, Ray2D b ) {
PVector t = GetLineLineTValues( PVector.sub(b.origin, a.origin), a.dir, b.dir )
if (t !=null && BoundsTestRay( t.x ) && BoundsTestRay( t.y )) {
return PVector.add(aOrigin, PVector.mult(Dir, t.x));
} else {
return null;
}
}
///// Returns whether or not two rays intersect (PVector or null)
public static PVector Rays( PVector aOrigin, PVector aDir, PVector bOrigin, PVector bDir ) {
PVector t = GetLineLineTValues(PVector.sub(b.origin, a.origin), aDir, bDir);
if (t != null && BoundsTestRay( t.x ) && BoundsTestRay( t.y ) {
return PVector.add(aOrigin, PVector.mult(Dir, t.x));
} else {
return null;
}
}
///// Returns the intersection point of two rays (if there is one)
///// "intersectionPoint">The point at which they intersect
public static PVector Rays( Ray2D a, Ray2D b) {
return Rays( a.origin, a.dir, b.origin, b.dir);
}
//#endregion
//#region Ray-LineSegment
/// Returns whether or not a ray and a line segment intersect
public static boolean RayLineSegment( Ray2D ray, LineSegment2D lineSegment ) {
return RayLineSegment( ray.origin, ray.dir, lineSegment.start, lineSegment.end );
}
/// Returns whether or not a ray and a line segment intersect
public static boolean RayLineSegment( PVector rayOrigin, PVector rayDir, PVector lineSegStart, PVector lineSegEnd ) {
return GetLineLineTValues( lineSegStart - rayOrigin, rayDir, lineSegEnd, out float tA, out float tB ) && BoundsTestRay( tA ) && BoundsTestLineSegment( tB );
}
/// Returns the intersection point of a ray and a line segment (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean RayLineSegment( PVector rayOrigin, PVector rayDir, PVector lineSegStart, PVector lineSegEnd, out PVector intersectionPoint ) {
if ( GetLineLineTValues( lineSegStart - rayOrigin, rayDir, lineSegEnd - lineSegStart, out float tA, out float tB ) && BoundsTestRay( tA ) && BoundsTestLineSegment( tB ) ) {
intersectionPoint = rayOrigin + rayDir * tA;
return true;
}
intersectionPoint = default;
return false;
}
/// Returns the intersection point of a ray and a line segment (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean RayLineSegment( Ray2D ray, LineSegment2D lineSegment, out PVector intersectionPoint ) {
return RayLineSegment( ray.origin, ray.dir, lineSegment.start, lineSegment.end, out intersectionPoint );
}
//#endregion
//#region Ray-Line
/// Returns whether or not a ray and a line intersect
public static boolean RayLine( Ray2D ray, Line2D line ) {
return RayLine( ray.origin, ray.dir, line.origin, line.dir );
}
/// Returns whether or not a ray and a line intersect
public static boolean RayLine( PVector rayOrigin, PVector rayDir, PVector lineOrigin, PVector lineDir ) {
return GetLineLineTValue( lineOrigin - rayOrigin, rayDir, lineDir, out float tA ) && BoundsTestRay( tA );
}
/// Returns the intersection point of a ray and an infinite line (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean RayLine( PVector rayOrigin, PVector rayDir, PVector lineOrigin, PVector lineDir, out PVector intersectionPoint ) {
if ( GetLineLineTValue( lineOrigin - rayOrigin, rayDir, lineDir, out float tA ) && BoundsTestRay( tA ) ) {
intersectionPoint = rayOrigin + rayDir * tA;
return true;
}
intersectionPoint = default;
return false;
}
/// Returns the intersection point of a ray and an infinite line (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean RayLine( Ray2D ray, Line2D line, out PVector intersectionPoint ) {
return RayLine( ray.origin, ray.dir, line.origin, line.dir, out intersectionPoint );
}
//#endregion
//#region Ray-Circle
///// Returns the number of intersections and the points at which a ray and a circle intersect (if they exist)
//public static int RayCircle( PVector rayOrigin, PVector rayDir, PVector circleCenter, float circleRadius, out PVector intsctPtA, out PVector intsctPtB ) {
// return GetLineCircleIntersectionPointsFiltered( rayOrigin, rayDir, circleCenter, circleRadius, t {
// return BoundsTestRay( t ), out intsctPtA, out intsctPtB );
// }
// /// Returns the number of intersections and the points at which a ray and a circle intersect (if they exist)
// public static int RayCircle( Ray2D ray, Circle circle, out PVector intsctPtA, out PVector intsctPtB ) {
// return GetLineCircleIntersectionPointsFiltered( ray.origin, ray.dir, circle.center, circle.radius, t {
// return BoundsTestRay( t ), out intsctPtA, out intsctPtB );
// }
// /// Returns the number of intersection points between ray and a circle
// public static int RayCircle( PVector rayOrigin, PVector rayDir, PVector circleCenter, float circleRadius ) {
// return GetLineCircleIntersectionCountFiltered( rayOrigin, rayDir, circleCenter, circleRadius, t {
// return BoundsTestRay( t ) );
// }
// /// Returns the number of intersection points between ray and a circle
// public static int RayCircle( Ray2D ray, Circle circle ) {
// return GetLineCircleIntersectionCountFiltered( ray.origin, ray.dir, circle.center, circle.radius, t {
// return BoundsTestRay( t ) );
// }
//#endregion
//#region LineSegments
/// Returns the intersection point of two line segments (if there is one)
/// "aStart">Line segment A start
/// "aEnd">Line segment A end
/// "bStart">Line segment B start
/// "bEnd">Line segment B end
/// "intersectionPoint">The point at which they intersect
public static boolean LineSegments( PVector aStart, PVector aEnd, PVector bStart, PVector bEnd, out PVector intersectionPoint ) {
PVector aDir = aEnd - aStart;
PVector bDir = bEnd - bStart;
PVector aToB = bStart - aStart;
if ( GetLineLineTValues( aToB, aDir, bDir, out float tA, out float tB ) && BoundsTestLineSegment( tA ) && BoundsTestLineSegment( tB ) ) {
intersectionPoint = aStart + tA * aDir;
return true;
}
intersectionPoint = default;
return false;
}
/// Returns the intersection point of two line segments (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean LineSegments( LineSegment2D a, LineSegment2D b, out PVector intersectionPoint ) {
return LineSegments( a.start, a.end, b.start, b.end, out intersectionPoint );
}
/// Returns whether or not two line segments intersect
/// "aStart">Line segment A start
/// "aEnd">Line segment A end
/// "bStart">Line segment B start
/// "bEnd">Line segment B end
public static boolean LineSegments( PVector aStart, PVector aEnd, PVector bStart, PVector bEnd ) {
return GetLineLineTValues( bStart - aStart, aEnd - aStart, bEnd - bStart, out float tA, out float tB ) && BoundsTestLineSegment( tA ) && BoundsTestLineSegment( tB );
}
/// Returns whether or not two line segments intersect
public static boolean LineSegments( LineSegment2D a, LineSegment2D b ) {
return LineSegments( a.start, a.end, b.start, b.end );
}
//#endregion
//#region LineSegment-Line
/// Returns the intersection point of a line segment and a line (if there is one)
/// "lineSegStart">Line segment start
/// "lineSegEnd">Line segment end
/// "lineOrigin">Line start
/// "lineDir">Line direction (does not have to be normalized)
/// "intersectionPoint">The point at which they intersect
public static boolean LineSegmentLine( PVector lineSegStart, PVector lineSegEnd, PVector lineOrigin, PVector lineDir, out PVector intersectionPoint ) {
PVector aDir = lineSegEnd - lineSegStart;
PVector aToB = lineOrigin - lineSegStart;
if ( GetLineLineTValue( aToB, aDir, lineDir, out float tA ) && BoundsTestLineSegment( tA ) ) {
intersectionPoint = lineSegStart + tA * aDir;
return true;
}
intersectionPoint = default;
return false;
}
/// Returns the intersection point of a line segment and a line (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean LineSegmentLine( LineSegment2D lineSegment, Line2D line, out PVector intersectionPoint ) {
return LineSegmentLine( lineSegment.start, lineSegment.end, line.origin, line.dir, out intersectionPoint );
}
/// Returns whether or not a line segment and a line intersect
/// "lineSegStart">Line segment start
/// "lineSegEnd">Line segment end
/// "lineOrigin">Line start
/// "lineDir">Line direction (does not have to be normalized)
public static boolean LineSegmentLine( PVector lineSegStart, PVector lineSegEnd, PVector lineOrigin, PVector lineDir ) {
return GetLineLineTValue( lineOrigin - lineSegStart, lineSegEnd - lineSegStart, lineDir, out float tA ) && BoundsTestLineSegment( tA );
}
/// Returns whether or not a line segment and a line intersect
public static boolean LineSegmentLine( LineSegment2D lineSegment, Line2D line ) {
return GetLineLineTValue( line.origin - lineSegment.start, lineSegment.end - lineSegment.start, line.dir, out float tA ) && BoundsTestLineSegment( tA );
}
//#endregion
//#region LineSegment-Circle
/// Returns the number of intersections and the points at which a line segment and a circle intersect (if they exist)
public static int LineSegmentCircle( PVector lineStart, PVector lineEnd, PVector circleCenter, float circleRadius, out PVector intsctPtA, out PVector intsctPtB ) {
return GetLineCircleIntersectionPointsFiltered( lineStart, lineEnd - lineStart, circleCenter, circleRadius, t {
return BoundsTestLineSegment( t ), out intsctPtA, out intsctPtB );
}
/// Returns the number of intersections and the points at which a line segment and a circle intersect (if they exist)
public static int LineSegmentCircle( LineSegment2D lineSegment, Circle circle, out PVector intsctPtA, out PVector intsctPtB ) {
return GetLineCircleIntersectionPointsFiltered( lineSegment.start, lineSegment.end - lineSegment.start, circle.center, circle.radius, t {
return BoundsTestLineSegment( t ), out intsctPtA, out intsctPtB );
}
/// Returns the number of intersection points between line segment and a circle
public static int LineSegmentCircle( PVector lineStart, PVector lineEnd, PVector circleCenter, float circleRadius ) {
return GetLineCircleIntersectionCountFiltered( lineStart, lineEnd - lineStart, circleCenter, circleRadius, t {
return BoundsTestLineSegment( t ) );
}
/// Returns the number of intersection points between line segment and a circle
public static int LineSegmentCircle( LineSegment2D lineSegment, Circle circle ) {
return GetLineCircleIntersectionCountFiltered( lineSegment.start, lineSegment.end - lineSegment.start, circle.center, circle.radius, t {
return BoundsTestLineSegment( t ) );
//#endregion
//#region Lines
/// Returns the intersection point of two infinite lines (if there is one)
/// "aOrigin">Line A origin
/// "aDir">Line A direction (does not have to be normalized)
/// "bOrigin">Line B origin
/// "bDir">Line B direction (does not have to be normalized)
/// "intersectionPoint">The point at which they intersect
public static boolean Lines( PVector aOrigin, PVector aDir, PVector bOrigin, PVector bDir, out PVector intersectionPoint ) {
PVector aToB = bOrigin - aOrigin;
if ( GetLineLineTValue( aToB, aDir, bDir, out float tA ) ) {
intersectionPoint = aOrigin + tA * aDir;
return true;
}
intersectionPoint = default;
return false;
}
/// Returns the intersection point of two infinite lines (if there is one)
/// "intersectionPoint">The point at which they intersect
public static boolean Lines( Line2D a, Line2D b, out PVector intersectionPoint ) {
return Lines( a.origin, a.dir, b.origin, b.dir, out intersectionPoint );
//#endregion
//#region Line-Circle
/// Returns the points at which an infinite line and a circle intersect (if they exist)
public static boolean LineCircle( PVector lineStart, PVector lineDir, PVector circleCenter, float circleRadius, out PVector intsctPtA, out PVector intsctPtB ) {
return GetLineCircleIntersectionPointsUnfiltered( lineStart, lineDir, circleCenter, circleRadius, out intsctPtA, out intsctPtB ) > 0;
/// Returns the points at which an infinite line and a circle intersect (if they exist)
public static boolean LineCircle( Line2D line, Circle circle, out PVector intsctPtA, out PVector intsctPtB ) {
return GetLineCircleIntersectionPointsUnfiltered( line.origin, line.dir, circle.center, circle.radius, out intsctPtA, out intsctPtB ) > 0;
/// Returns whether or not an infinite line and a circle intersect
public static boolean LineCircle( PVector lineStart, PVector lineDir, PVector circleCenter, float circleRadius ) {
return GetLineCircleIntersectionState( lineStart, lineDir, circleCenter, circleRadius );
/// Returns whether or not an infinite line and a circle intersect
public static boolean LineCircle( Line2D line, Circle circle ) {
return GetLineCircleIntersectionState( line.origin, line.dir, circle.center, circle.radius );
}
//#endregion
/// Returns the two intersection points of two circles (if they exist)
/// "intsctPtA">The first intersection point
/// "intsctPtB">The second intersection point
public static boolean Circles( Circle a, Circle b, out PVector intsctPtA, out PVector intsctPtB ) {
float distSq = DistanceSquared( a.center, b.center );
float dist = Sqrt( distSq );
boolean differentPosition = dist > 0.00001f;
float maxRad = Max( a.radius, b.radius );
float minRad = Min( a.radius, b.radius );
boolean ringsTouching = Mathf.Abs( dist - maxRad ) < minRad;
if ( ringsTouching && differentPosition ) {
float aRadSq = a.radius.Square();
float bRadSq = b.radius.Square();
float lateralOffset = ( distSq - bRadSq + aRadSq ) / ( 2 * dist );
float normalOffset = ( 0.5f / dist ) * Sqrt( 4 * distSq * aRadSq - ( distSq - bRadSq + aRadSq ).Square() );
PVector tangent = ( b.center - a.center ) / dist;
PVector normal = tangent.Rotate90CCW();
PVector chordCenter = a.center + tangent * lateralOffset;
intsctPtA = chordCenter + normal * normalOffset;
intsctPtB = chordCenter - normal * normalOffset;
return true;
}
intsctPtA = intsctPtB = default;
return false;
}
/// Returns whether or not two discs overlap
public static boolean Discs( Circle a, Circle b ) {
return DistanceSquared( a.center, b.center ) <= ( a.radius + b.radius ).Square();
/// Returns whether or not two circles overlap
public static boolean Circles( Circle a, Circle b ) {
float dist = PVector.dist( a.center, b.center );
float maxRad = Max( a.radius, b.radius );
float minRad = Min( a.radius, b.radius );
return Mathf.Abs( dist - maxRad ) < minRad;
}
// internal
const float PARALLEL_DETERMINANT_THRESHOLD = 0.00001f;
static boolean Parallel( PVector aDir, PVector bDir ) {
return Abs( Determinant( aDir, bDir ) ) < PARALLEL_DETERMINANT_THRESHOLD;
}
// internal, based on https://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm
static void GetLineCircleIntersectionValues( PVector aOrigin, PVector aDir, PVector circleCenter, float radius, out float a, out float b, out float discriminant ) {
PVector circleToLineOrigin = aOrigin - circleCenter;
a = PVector.Dot( aDir, aDir ); // ray len sq
b = 2 * PVector.Dot( circleToLineOrigin, aDir );
float c = PVector.Dot( circleToLineOrigin, circleToLineOrigin ) - radius.Square();
discriminant = b * b - 4 * a * c;
}
// internal
static boolean GetLineCircleTValues( PVector aOrigin, PVector aDir, PVector circleCenter, float radius, out float tA, out float tB ) {
GetLineCircleIntersectionValues( aOrigin, aDir, circleCenter, radius, out float a, out float b, out float discriminant );
if ( discriminant > 0 ) {
discriminant = Mathf.Sqrt( discriminant );
tA = ( -b + discriminant ) / ( 2 * a );
tB = ( -b - discriminant ) / ( 2 * a );
return true;
} else {
tA = tB = 0f;
return false;
}
}
// internal, only useful for the Line-Circle since it doesn't check T values
static boolean GetLineCircleIntersectionState( PVector aOrigin, PVector aDir, PVector circleCenter, float radius ) {
GetLineCircleIntersectionValues( aOrigin, aDir, circleCenter, radius, out float _, out float _, out float discriminant );
return discriminant > 0;
}
// internal
static int GetLineCircleIntersectionCountFiltered( PVector aOrigin, PVector aDir, PVector cCenter, float r, Func<float, bool> InValidRange ) {
int pCount = 0;
if ( GetLineCircleTValues( aOrigin, aDir, cCenter, r, out float tA, out float tB ) ) {
if ( InValidRange( tA ) ) pCount++;
if ( InValidRange( tB ) ) pCount++;
}
return pCount;
}
// internal
static int GetLineCircleIntersectionPointsFiltered( PVector aOrigin, PVector aDir, PVector cCenter, float r, Func<float, bool> InValidRange, out PVector pA, out PVector pB ) {
int pCount = 0;
void Check( float t, out PVector p ) {
if ( InValidRange( t ) ) {
p = aOrigin + aDir * t;
pCount++;
} else p = default;
}
if ( GetLineCircleTValues( aOrigin, aDir, cCenter, r, out float tA, out float tB ) ) {
Check( tA, out pA );
Check( tB, out pB );
} else {
pA = pB = default;
}
return pCount;
}
// internal
static int GetLineCircleIntersectionPointsUnfiltered( PVector aOrigin, PVector aDir, PVector cCenter, float r, out PVector pA, out PVector pB ) {
if ( GetLineCircleTValues( aOrigin, aDir, cCenter, r, out float tA, out float tB ) ) {
pA = aOrigin + aDir * tA;
pB = aOrigin + aDir * tB;
return 2;
}
pA = pB = default;
return 0;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment