shithub: front

Download patch

ref: 7059938e9449f161805c79a7129da5ede7a3dafe
parent: a584d29458e3fec3e1e3162068fc5ab516a2d00e
author: rodri <rgl@antares-labs.eu>
date: Mon Aug 19 17:30:14 EDT 2024

libgeometry: add lineXsphere function

--- a/sys/include/geometry.h
+++ b/sys/include/geometry.h
@@ -77,6 +77,7 @@
 Point3 crossvec3(Point3, Point3);
 double vec3len(Point3);
 Point3 normvec3(Point3);
+int lineXsphere(Point3*, Point3, Point3, Point3, double, int);
 
 /* Matrix */
 void identity(Matrix);
--- a/sys/man/2/geometry
+++ b/sys/man/2/geometry
@@ -88,6 +88,8 @@
 Point3 crossvec3(Point3 a, Point3 b);
 double vec3len(Point3 v);
 Point3 normvec3(Point3 v);
+int lineXsphere(Point3 *rp, Point3 p0, Point3 p1,
+		Point3 c, double rad, int isaray);
 .PB
 /* Matrix */
 void identity(Matrix m);
@@ -366,6 +368,25 @@
 Normalizes the vector
 .I v
 and returns a new 3D point.
+.TP
+.B lineXsphere(\fIrp\fP,\fIp0\fP,\fIp1\fP,\fIc\fP,\fIrad\fP,\fIisaray\fP)
+Finds the intersection between the line defined by
+.I p0
+and
+.I p1
+and the circle with center at
+.I c
+and a radius of
+.IR rad .
+If
+.I isaray
+is not zero, the line will be interpreted as a ray directed from
+.I p0
+to
+.IR p1 .
+The function returns the number of intersections (up to two) and, if
+.I rp
+is not nil, it is filled with the resulting points.
 .SS Matrices
 .TP
 Name
--- a/sys/src/libgeometry/point.c
+++ b/sys/src/libgeometry/point.c
@@ -216,3 +216,35 @@
 		return Pt3(0,0,0,0);
 	return Pt3(v.x/len, v.y/len, v.z/len, 0);
 }
+
+int
+lineXsphere(Point3 *rp, Point3 p0, Point3 p1, Point3 c, double r, int isaray)
+{
+	Point3 u, dp;
+	double u·dp, Δ, d;
+
+	u = normvec3(subpt3(p1, p0));
+	dp = subpt3(p1, c);
+	u·dp = dotvec3(u, dp);
+	if(isaray && u·dp > 0)	/* ignore what's behind */
+		return 0;
+
+	Δ = u·dp*u·dp - dotvec3(dp, dp) + r*r;
+	if(Δ < 0)		/* no intersection */
+		return 0;
+	else if(Δ == 0){	/* tangent */
+		if(rp != nil){
+			d = -u·dp;
+			rp[0] = addpt3(p0, mulpt3(u, d));
+		}
+		return 1;
+	}else{			/* secant */
+		if(rp != nil){
+			d = -u·dp + sqrt(Δ);
+			rp[0] = addpt3(p0, mulpt3(u, d));
+			d = -u·dp - sqrt(Δ);
+			rp[1] = addpt3(p0, mulpt3(u, d));
+		}
+		return 2;
+	}
+}
--