Find the intersection of a line with a plane: Difference between revisions
Find the intersection of a line with a plane (view source)
Revision as of 11:55, 5 December 2023
, 5 months ago→{{header|Wren}}: Added libheader.
m (→{{header|Wren}}: Added libheader.) |
|||
(35 intermediate revisions by 16 users not shown) | |||
Line 11:
=={{header|11l}}==
<
R ray_point - ray_direction * dot(ray_point - plane_point, plane_normal) / dot(ray_direction, plane_normal)
print(‘The ray intersects the plane at ’intersection_point((0.0, -1.0, -1.0), (0.0, 0.0, 10.0), (0.0, 0.0, 1.0), (0.0, 0.0, 5.0)))</
{{out}}
<pre>
The ray intersects the plane at (0, -5, 5)
</pre>
=={{header|Action!}}==
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
DEFINE REALPTR="CARD"
TYPE VectorR=[REALPTR x,y,z]
PROC PrintVector(VectorR POINTER v)
Print("(") PrintR(v.x)
Print(",") PrintR(v.y)
Print(",") PrintR(v.z)
Print(")")
RETURN
PROC Vector(REAL POINTER vx,vy,vz VectorR POINTER v)
v.x=vx v.y=vy v.z=vz
RETURN
PROC VectorSub(VectorR POINTER a,b,res)
RealSub(a.x,b.x,res.x)
RealSub(a.y,b.y,res.y)
RealSub(a.z,b.z,res.z)
RETURN
PROC VectorDot(VectorR POINTER a,b REAL POINTER res)
REAL tmp1,tmp2
RealMult(a.x,b.x,res)
RealMult(a.y,b.y,tmp1)
RealAdd(res,tmp1,tmp2)
RealMult(a.z,b.z,tmp1)
RealAdd(tmp1,tmp2,res)
RETURN
PROC VectorMul(VectorR POINTER a REAL POINTER b VectorR POINTER res)
RealMult(a.x,b,res.x)
RealMult(a.y,b,res.y)
RealMult(a.z,b,res.z)
RETURN
BYTE FUNC IsZero(REAL POINTER a)
CHAR ARRAY s(10)
StrR(a,s)
IF s(0)=1 AND s(1)='0 THEN
RETURN (1)
FI
RETURN (0)
BYTE FUNC Intersection(VectorR POINTER
rayVector,rayPoint,planeNormal,planePoint,result)
REAL tmpx,tmpy,tmpz,prod1,prod2,prod3
VectorR tmp
Vector(tmpx,tmpy,tmpz,tmp)
VectorSub(rayPoint,planePoint,tmp)
VectorDot(tmp,planeNormal,prod1)
VectorDot(rayVector,planeNormal,prod2)
IF IsZero(prod2) THEN
RETURN (1)
FI
RealDiv(prod1,prod2,prod3)
VectorMul(rayVector,prod3,tmp)
VectorSub(rayPoint,tmp,result)
RETURN (0)
PROC Test(VectorR POINTER rayVector,rayPoint,planeNormal,planePoint)
BYTE res
REAL px,py,pz
VectorR p
Vector(px,py,pz,p)
res=Intersection(rayVector,rayPoint,planeNormal,planePoint,p)
Print("Ray vector: ")
PrintVector(rayVector) PutE()
Print("Ray point: ")
PrintVector(rayPoint) PutE()
Print("Plane normal: ")
PrintVector(planeNormal) PutE()
Print("Plane point: ")
PrintVector(planePoint) PutE()
IF res=0 THEN
Print("Intersection point: ")
PrintVector(p) PutE()
ELSEIF res=1 THEN
PrintE("There is no intersection")
FI
PutE()
RETURN
PROC Main()
REAL r0,r1,r5,r10,rm1
VectorR rayVector,rayPoint,planeNormal,planePoint
Put(125) PutE() ;clear screen
ValR("0",r0) ValR("1",r1) ValR("5",r5)
ValR("10",r10) ValR("-1",rm1)
Vector(r0,rm1,rm1,rayVector)
Vector(r0,r0,r10,rayPoint)
Vector(r0,r0,r1,planeNormal)
Vector(r0,r0,r5,planePoint)
Test(rayVector,rayPoint,planeNormal,planePoint)
Vector(r1,r1,r0,rayVector)
Vector(r1,r1,r0,rayPoint)
Vector(r0,r0,r1,planeNormal)
Vector(r5,r1,r0,planePoint)
Test(rayVector,rayPoint,planeNormal,planePoint)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Find_the_intersection_of_a_line_with_a_plane.png Screenshot from Atari 8-bit computer]
<pre>
Ray vector: (0,-1,-1)
Ray point: (0,0,10)
Plane normal: (0,0,1)
Plane point: (0,0,5)
Intersection point: (0,-5,5)
Ray vector: (1,1,0)
Ray point: (1,1,0)
Plane normal: (0,0,1)
Plane point: (5,1,0)
There is no intersection
</pre>
=={{header|Ada}}==
<syntaxhighlight lang="ada">with Ada.Numerics.Generic_Real_Arrays;
with Ada.Text_IO;
procedure Intersection is
type Real is new Long_Float;
package Real_Arrays is
new Ada.Numerics.Generic_Real_Arrays (Real => Real);
use Real_Arrays;
package Real_IO is
new Ada.Text_IO.Float_IO (Num => Real);
subtype Vector_3D is Real_Vector (1 .. 3);
function Line_Plane_Intersection (Line_Vector : in Vector_3D;
Line_Point : in Vector_3D;
Plane_Normal : in Vector_3D;
Plane_Point : in Vector_3D)
return Vector_3D
is
Diff : constant Vector_3D := Line_Point - Plane_Point;
Denom : constant Real := Line_Vector * Plane_Normal;
begin
if Denom = 0.0 then
raise Constraint_Error with "Line does not intersect plane";
end if;
declare
Scale : constant Real :=
-Real'(Diff * Plane_Normal) / Denom;
Point : constant Vector_3D :=
Diff + Plane_Point + Scale * Line_Vector;
begin
return Point;
end;
end Line_Plane_Intersection;
procedure Put (V : in Vector_3D) is
use Ada.Text_IO, Real_IO;
begin
Put ("(");
Put (V (1)); Put (",");
Put (V (2)); Put (",");
Put (V (3)); Put (")");
end Put;
begin
Real_IO.Default_Exp := 0;
Real_IO.Default_Aft := 3;
Put (Line_Plane_Intersection (Line_Vector => (0.0, -1.0, -1.0),
Line_Point => (0.0, 0.0, 10.0),
Plane_Normal => (0.0, 0.0, 1.0),
Plane_Point => (0.0, 0.0, 5.0)));
end Intersection;</syntaxhighlight>
{{out}}
<pre>( 0.000,-5.000, 5.000)</pre>
=={{header|APL}}==
<syntaxhighlight lang="apl">⍝ Find the intersection of a line with a plane
⍝ The intersection I belongs to a line defined by point L and vector V, translates to:
⍝ A real parameter t exists, that satisfies I = L + tV
⍝ I belongs to the plan defined by point P and normal vector N. This means that any two points of the plane make a vector
⍝ normal to vector N. As I and P belong to the plane, the vector IP is normal to N.
⍝ This translates to: The scalar product IP.N = 0.
⍝ (P - I).N = 0 <=> (P - L - tV).N = 0
⍝ Using distributivity, then associativity, the following equations are established:
⍝ (P - L - tV).N = (P - L).N - (tV).N = (P - L).N - t(V.N) = 0
⍝ Which allows to resolve t: t = ((P - L).N) ÷ (V.N)
⍝ In APL, A.B is coded +/A x B
V ← 0 ¯1 ¯1
L ← 0 0 10
N ← 0 0 1
P ← 0 0 5
dot ← { +/ ⍺ × ⍵ }
t ← ((P - L) dot N) ÷ V dot N
I ← L + t × V
</syntaxhighlight>
{{out}}
<pre>
I
0 ¯5 5
</pre>
=={{header|Arturo}}==
{{trans|Nim}}
<syntaxhighlight lang="rebol">define :vector [x, y, z][]
addv: function [v1 :vector, v2 :vector]->
to :vector @[v1\x+v2\x, v1\y+v2\y, v1\z+v2\z]
subv: function [v1 :vector, v2 :vector]->
to :vector @[v1\x-v2\x, v1\y-v2\y, v1\z-v2\z]
mulv: function [v1 :vector, v2 :vector :floating][
if? is? :vector v2
-> return sum @[v1\x*v2\x v1\y*v2\y v1\z*v2\z]
else
-> return to :vector @[v1\x*v2, v1\y*v2, v1\z*v2]
]
intersect: function [lV, lP, pV, pP][
tdenom: mulv pV lV
if zero? tdenom -> return to :vector @[∞, ∞, ∞]
t: (mulv pV subv pP lP) / tdenom
return addv mulv lV t lP
]
coords: intersect to :vector @[0.0, neg 1.0, neg 1.0]
to :vector @[0.0, 0.0, 10.0]
to :vector @[0.0, 0.0, 1.0]
to :vector @[0.0, 0.0, 5.0]
print ["Intersection at:" coords]</syntaxhighlight>
{{out}}
<pre>Intersection at: [x:0.0 y:-5.0 z:5.0]</pre>
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">/*
; https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection#Algebraic_form
l = line vector
lo = point on the line
n = plane normal vector
Po = point on the plane
if (l . n) = 0 ; line and plane are parallel.
if (Po - lo) . n = 0 ; line is contained in the plane.
(P - Po) . n = 0 ; vector equation of plane.
P = lo + l * d ; vector equation of line.
((lo + l * d) - Po) . n = 0 ; Substitute line into plane equation.
(l . n) * d + (lo - Po) . n = 0 ; Expanding.
d = ((Po - lo) . n) / (l . n) ; solving for d.
P = lo + l * ((Po - lo) . n) / (l . n) ; solving P.
*/
intersectPoint(l, lo, n, Pn ){
if (Vector_dot(Vector_sub(Pn, lo), n) = 0) ; line is contained in the plane
return [1]
if (Vector_dot(l, n) = 0) ; line and plane are parallel
return [0]
diff := Vector_Sub(Pn, lo) ; (Po - lo)
prod1 := Vector_Dot(diff, n) ; ((Po - lo) . n)
prod2 := Vector_Dot(l, n) ; (l . n)
d := prod1 / prod2 ; d = ((Po - lo) . n) / (l . n)
return Vector_Add(lo, Vector_Mul(l, d)) ; P = lo + l * d
}
Vector_Add(v, w){
return [v.1+w.1, v.2+w.2, v.3+w.3]
}
Vector_Sub(v, w){
return [v.1-w.1, v.2-w.2, v.3-w.3]
}
Vector_Mul(v, s){
return [s*v.1, s*v.2, s*v.3]
}
Vector_Dot(v, w){
return v.1*w.1 + v.2*w.2 + v.3*w.3
}</syntaxhighlight>
Examples:<syntaxhighlight lang="autohotkey">; task
l1 := [0, -1, -1]
lo1 := [0, 0, 10]
n1 := [0, 0, 1]
Po1 := [0, 0, 5]
; line on plane
l2 := [1, 1, 0]
lo2 := [1, 1, 0]
n2 := [0, 0, 1]
Po2 := [5, 1, 0]
; line parallel to plane
l3 := [1, 1, 0]
lo3 := [1, 1, 1]
n3 := [0, 0, 1]
Po3 := [5, 1, 0]
output := ""
loop 3
{
result := ""
ip := intersectPoint(l%A_Index%, lo%A_Index%, n%A_Index%, Po%A_Index%)
for i, v in ip
result .= v ", "
output .= Trim(result, ", ") "`n"
}
MsgBox % output
return</syntaxhighlight>
{{out}}
<pre>0.000000, -5.000000, 5.000000
1 ; line on plane
0 ; line parallel to plane
</pre>
=={{header|C}}==
Straightforward application of the intersection formula, prints usage on incorrect invocation.
<syntaxhighlight lang="c">
#include<stdio.h>
Line 76 ⟶ 408:
return 0;
}
</syntaxhighlight>
Invocation and output:
<pre>
Line 84 ⟶ 416:
=={{header|C sharp|C#}}==
<
namespace FindIntersection {
Line 135 ⟶ 467:
}
}
}</
{{out}}
<pre>The ray intersects the plane at (0.00, -5.00, 5.00)</pre>
Line 141 ⟶ 473:
=={{header|C++}}==
{{trans|Java}}
<
#include <sstream>
Line 194 ⟶ 526:
return 0;
}</
{{out}}
<pre>The ray intersects the plane at (0, -5, 5)</pre>
Line 200 ⟶ 532:
=={{header|D}}==
{{trans|Kotlin}}
<
struct Vector3D {
Line 255 ⟶ 587:
auto ip = intersectPoint(rv, rp, pn, pp);
writeln("The ray intersects the plane at ", ip);
}</
{{out}}
<pre>The ray intersects the plane at (0.000000,-5.000000,5.000000)</pre>
=={{header|
{{trans|Lua}}
<syntaxhighlight lang=easylang>
proc minus . l[] r[] res[] .
len res[] 3
for i to 3
res[i] = l[i] - r[i]
.
.
func dot l[] r[] .
for i to 3
res += l[i] * r[i]
.
return res
.
proc scale f . l[] .
for i to 3
l[i] = l[i] * f
.
.
proc inter_point rv[] rp[] pn[] pp[] . res[] .
minus rp[] pp[] dif[]
prd1 = dot dif[] pn[]
prd2 = dot rv[] pn[]
scale (prd1 / prd2) rv[]
minus rp[] rv[] res[]
.
rv[] = [ 0.0 -1.0 -1.0 ]
rp[] = [ 0.0 0.0 10.0 ]
pn[] = [ 0.0 0.0 1.0 ]
pp[] = [ 0.0 0.0 5.0 ]
inter_point rv[] rp[] pn[] pp[] res[]
print res[]
</syntaxhighlight>
=={{header|Evaldraw}}==
{{trans|C}}
Makes use of the intersectionPoint function to intersect 9 lines with 1 moving plane in a realtime demo.
[[File:Evaldraw line vs plane.png|thumb|alt=Grid of 3x3 3d points intersecting a 3D plane|Shows 3x3 grid of lines intersecting a plane. Gridlines drawn between intersection points. Intersection "time" value projected from 3d intersection point to 2d screen rendering.]]
<syntaxhighlight lang="c">
struct vec{x,y,z;};
enum{GRIDRES=3} // Keep a NxN grid of intersection results.
static vec intersections[GRIDRES][GRIDRES];
static vec ipos = {0,5,-15};
static vec ileft = {-1,0,0};
static vec iup = {0,-1,0};
static vec ifor = {0,0,1};
()
{
cls(0); clz(1e32);
setcam( ipos.x, ipos.y, ipos.z,
ileft.x, ileft.y, ileft.z, // flip right basis to left
iup.x, iup.y, iup.z, // flip down basis to up
ifor.x, ifor.y, ifor.z);
t=klock(0);
vec planePoint = {0,5,0}; // Plane Position
vec pN = {cos(t),1,sin(t)}; // PlaneNormal, un-normalized
normalize(pN);
for(x=0; x<GRIDRES; x++)
for(z=0; z<GRIDRES; z++)
{
scale = 4.5; halfgrid = scale*(GRIDRES-1)/2;
vec lineVector = {0,1,0}; // Direction of line
vec linePoint ={-halfgrid+scale*x, 5, -halfgrid+scale*z};
if (vecdot( lineVector, pN ) == 0 )
{
moveto(0,0); printf("Line and Plane dont intersect.");
} else {
vec isect;
isect_time = intersectionPoint(lineVector, linePoint, pN, planePoint, isect);
intersections[x][z] = isect; // Store for drawing grid
//setcol(255,255,0); drawsph(isect.x, isect.y, isect.z, .1);
setcol(255,0,0); line(linePoint, isect);
unproject(isect);
setfont(8,12); setcol(255,255,255); printf("t=%2.1f", isect_time);
}
}
// drawgridPlane
setcol(255,0,255);
for(i=0; i<GRIDRES; i++)
for(j=0; j<GRIDRES; j++) {
vec p00 = intersections[i][j];
vec p10 = intersections[(i+1)%GRIDRES][j];
vec p01 = intersections[i][(j+1)%GRIDRES]; // oob wraps to 0 anyhow
line(p00,p10);
line(p00,p01);
}
setcol(192,192,192); moveto(0,0); printf("Line vs Plane intersection");
}
intersectionPoint(vec lineVector, vec linePoint, vec planeNormal, vec planePoint, vec isect){
vec diff; vecsub(diff,linePoint,planePoint);
vec pd; vecadd(pd, diff,planePoint);
t = -vecdot(diff,planeNormal) / vecdot(lineVector,planeNormal);
vec scaledVec; vecscalar(scaledVec, lineVector, t);
vecadd(isect, pd, scaledVec);
return t;
}
line(vec a, vec b) { moveto(a.x,a.y,a.z); lineto(b.x,b.y,b.z); }
// -------------------------------------- VECTOR MATH
vecScalar( vec out, vec a, s ) {
out.x = a.x * s;
out.y = a.y * s;
out.z = a.z * s;
}
vecAdd( vec out, vec a, vec b) {
out.x = a.x + b.x;
out.y = a.y + b.y;
out.z = a.z + b.z;
}
vecAdd( vec out, vec b) {
out.x += b.x;
out.y += b.y;
out.z += b.z;
}
vecSub( vec out, vec a, vec b) {
out.x = a.x - b.x;
out.y = a.y - b.y;
out.z = a.z - b.z;
}
vecCross( vec out, vec a, vec b) {
out.x = a.y*b.z - a.z*b.y;
out.y = a.z*b.x - a.x*b.z;
out.z = a.x*b.y - a.y*b.x;
}
vecDot( vec a, vec b) {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
length( vec v ) {
return sqrt( vecdot(v,v) );
}
normalize( vec v ) {
len = length(v);
if ( len ) { v.x /= len; v.y /= len; v.z /= len; }
}
unproject(vec pt) { // unproject a 3D screenpoint
vec from_eye; vecsub(from_eye, pt, ipos);
nx = vecdot(from_eye, ileft);
ny = vecdot(from_eye, iup);
nz = vecdot(from_eye, ifor);
if (nz <= 0.5) return; // behind eye
f = xres/2/nz; // 90 degree projection
moveto(nx*f + xres/2, ny*f + yres/2 );
}</syntaxhighlight>
=={{header|F Sharp|F#}}==
{{trans|C#}}
<
type Vector(x : double, y : double, z : double) =
Line 294 ⟶ 776:
Console.WriteLine("The ray intersects the plane at {0}", ip)
0 // return an integer exit code</
{{out}}
<pre>The ray intersects the plane at (0.00, -5.00, 5.00)</pre>
Line 300 ⟶ 782:
=={{header|Factor}}==
{{trans|11l}}
<
:: intersection-point ( rdir rpt pnorm ppt -- loc )
Line 306 ⟶ 788:
"The ray intersects the plane at " write
{ 0 -1 -1 } { 0 0 10 } { 0 0 1 } { 0 0 5 } intersection-point .</
{{out}}
<pre>
Line 313 ⟶ 795:
=={{header|FreeBASIC}}==
<
' compile with: fbc -s console
Line 379 ⟶ 861:
Print : Print "hit any key to end program"
Sleep
End</
{{out}}
<pre>line intersects the plane at (0, -5, 5)</pre>
Line 385 ⟶ 867:
=={{header|Go}}==
{{trans|Kotlin}}
<
import "fmt"
Line 426 ⟶ 908:
ip := intersectPoint(rv, rp, pn, pp)
fmt.Println("The ray intersects the plane at", ip)
}</
{{out}}
Line 435 ⟶ 917:
=={{header|Groovy}}==
{{trans|Java}}
<
private static class Vector3D {
private double x, y, z
Line 483 ⟶ 965:
println("The ray intersects the plane at $ip")
}
}</
{{out}}
<pre>The ray intersects the plane at (0.0, -5.0, 5.0)</pre>
Line 490 ⟶ 972:
{{trans|Kotlin}}
Note that V3 is implemented similarly in the external library [https://hackage.haskell.org/package/linear-1.20.7/docs/Linear-V3.html linear].
<
import Text.Printf (printf)
Line 532 ⟶ 1,014:
rp = V3 0 0 10
pn = V3 0 0 1
pp = V3 0 0 5</
{{out}}
<pre>The ray intersects the plane at (0.0, -5.0, 5.0)</pre>
Line 538 ⟶ 1,020:
=={{header|J}}==
'''Solution:'''
<
p=: mp&{: %~ -~&{. mp {:@] NB. solve
intersectLinePlane=: [ +/@:* 1 , p NB. substitute</
'''Example Usage:'''
<
Plane=: 0 0 5 ,: 0 0 1 NB. Point, Normal
Line intersectLinePlane Plane
0 _5 5</
=={{header|Java}}==
{{trans|Kotlin}}
<
private static class Vector3D {
private double x, y, z;
Line 597 ⟶ 1,079:
System.out.println("The ray intersects the plane at " + ip);
}
}</
{{out}}
<pre>The ray intersects the plane at (0.000000, -5.000000, 5.000000)</pre>
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
In the following, a 3d vector is represented by a JSON array: [x, y, z]
<syntaxhighlight lang="jq"># add as many as you please
def addVector:
transpose | add;
# . - y
def minusVector(y):
[.[0] - y[0], .[1] - y[1], .[2] - y[2]];
# scalar multiplication: . * s
def multVector(s):
map(. * s);
def dot(y):
.[0] * y[0] + .[1] * y[1] + .[2] * y[2];
def intersectPoint($rayVector; $rayPoint; $planeNormal; $planePoint):
($rayPoint | minusVector($planePoint)) as $diff
| ($diff|dot($planeNormal)) as $prod1
| ($rayVector|dot($planeNormal)) as $prod2
| $rayPoint | minusVector($rayVector | multVector(($prod1 / $prod2) )) ;
def rv : [0, -1, -1];
def rp : [0, 0, 10];
def pn : [0, 0, 1];
def pp : [0, 0, 5];
"The ray intersects the plane at:",
intersectPoint(rv; rp; pn; pp)</syntaxhighlight>
{{out}}
<pre>
The ray intersects the plane at:
[0,-5,5]
</pre>
=={{header|Julia}}==
Line 605 ⟶ 1,128:
{{trans|Python}}
<
ndotu = dot(planenorm, raydir)
if ndotu ≈ 0 error("no intersection or line is within plane") end
Line 624 ⟶ 1,147:
ψ = lineplanecollision(planenorm, planepnt, raydir, raypnt)
println("Intersection at $ψ")</
{{out}}
Line 630 ⟶ 1,153:
=={{header|Kotlin}}==
<
class Vector3D(val x: Double, val y: Double, val z: Double) {
Line 665 ⟶ 1,188:
val ip = intersectPoint(rv, rp, pn, pp)
println("The ray intersects the plane at $ip")
}</
{{out}}
Line 673 ⟶ 1,196:
=={{header|Lua}}==
<
return {x=xval, y=yval, z=zval}
end
Line 710 ⟶ 1,233:
pp = make(0.0, 0.0, 5.0)
ip = intersectPoint(rv, rp, pn, pp)
print("The ray intersects the plane at " .. tostr(ip))</
{{out}}
<pre>The ray intersects the plane at (0, -5, 5)</pre>
=={{header|Maple}}==
<
geom3d:-line(L, [geom3d:-point(p2,0,0,10), [0,-1,-1]]);
geom3d:-intersection(px,L,P);
geom3d:-detail(px);</
{{Out}}
<pre>[["name of the object",px],["form of the object",point3d],["coordinates of the point",[0,-5,5]]]</pre>
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">RegionIntersection[InfiniteLine[{0, 0, 10}, {0, -1, -1}], InfinitePlane[{0, 0, 5}, {{0, 1, 0}, {1, 0, 0}}]]</syntaxhighlight>
{{out}}
<pre>Point[{0, -5, 5}]</pre>
=={{header|MATLAB}}==
{{trans|Kotlin}}
<
pdiff = rayPoint - planePoint;
Line 731 ⟶ 1,260:
prod3 = prod1 / prod2;
point = rayPoint - rayVector * prod3;</
{{out}}
<
ans =
0 -5 5
</syntaxhighlight>
=={{header|Modula-2}}==
<
FROM RealStr IMPORT RealToStr;
FROM Terminal IMPORT WriteString,WriteLn,ReadChar;
Line 802 ⟶ 1,331:
ReadChar;
END LinePlane.</
=={{header|Nim}}==
<syntaxhighlight lang="nim">
type Vector = tuple[x, y, z: float]
Line 839 ⟶ 1,368:
planeVector = (0.0, 0.0, 1.0),
planePoint = (0.0, 0.0, 5.0))
echo "Intersection at ", coords</
{{out}}
Line 846 ⟶ 1,375:
=={{header|Perl}}==
{{trans|Raku}}
<
package Plane; sub new { my ($c, $a) = @_; my $self = { V0 => $a->{V0}, n => $a->{n} } } # point / normal
Line 873 ⟶ 1,402:
my $P = Plane->new({ V0=>[0,0,5 ], n=>[0, 0, 1]});
print 'Intersection at point: ', join(' ', line_plane_intersection($L, $P)) . "\n";
</syntaxhighlight>
{{out}}
<pre>Intersection at point: 0 -5 5</pre>
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">dot</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">intersection_point</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">line_vector</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line_point</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_normal</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_point</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line_vector</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_normal</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"no intersection"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">diff</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">line_point</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_point</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">diff</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_point</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">dot</span><span style="color: #0000FF;">(</span><span style="color: #000000;">diff</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plane_normal</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">line_vector</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">intersection_point</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">})</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">intersection_point</span><span style="color: #0000FF;">({</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">})</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">intersection_point</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- (parallel to plane)</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">intersection_point</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">})</span> <span style="color: #000080;font-style:italic;">-- (line within plane)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 897 ⟶ 1,429:
"no intersection"
"no intersection"
</pre>
=={{header|Picat}}==
{{trans|Java}}
{{works with|Picat}}
<syntaxhighlight lang="picat">
plus(U, V) = {U[1] + V[1], U[2] + V[2], U[3] + V[3]}.
minus(U, V) = {U[1] - V[1], U[2] - V[2], U[3] - V[3]}.
times(U, S) = {U[1] * S, U[2] * S, U[3] * S}.
dot(U, V) = U[1] * V[1] + U[2] * V[2] + U[3] * V[3].
intersect_point(RayVector, RayPoint, PlaneNormal, PlanePoint) = IntersectPoint =>
Diff = minus(RayPoint, PlanePoint),
Prod1 = dot(Diff, PlaneNormal),
Prod2 = dot(RayVector, PlaneNormal),
Prod3 = Prod1 / Prod2,
IntersectPoint = minus(RayPoint, times(RayVector, Prod3)).
main =>
RayVector = {0.0, -1.0, -1.0},
RayPoint = {0.0, 0.0, 10.0},
PlaneNormal = {0.0, 0.0, 1.0},
PlanePoint = {0.0, 0.0, 5.0},
IntersectPoint = intersect_point(RayVector, RayPoint, PlaneNormal, PlanePoint),
printf("The ray intersects the plane at (%f, %f, %f)\n",
IntersectPoint[1],
IntersectPoint[2],
IntersectPoint[3]
).
</syntaxhighlight>
{{out}}
<pre>
The ray intersects the plane at (0.000000, -5.000000, 5.000000)
</pre>
=={{header|Prolog}}==
{{trans|Picat}}
{{works with|GNU Prolog}}
{{works with|SWI Prolog}}
<syntaxhighlight lang="prolog">
:- initialization(main).
vector_plus(U, V, W) :-
U = p(X1, Y1, Z1),
V = p(X2, Y2, Z2),
X3 is X1 + X2,
Y3 is Y1 + Y2,
Z3 is Z1 + Z2,
W = p(X3, Y3, Z3).
vector_minus(U, V, W) :-
U = p(X1, Y1, Z1),
V = p(X2, Y2, Z2),
X3 is X1 - X2,
Y3 is Y1 - Y2,
Z3 is Z1 - Z2,
W = p(X3, Y3, Z3).
vector_times(U, S, V) :-
U = p(X1, Y1, Z1),
X2 is X1 * S,
Y2 is Y1 * S,
Z2 is Z1 * S,
V = p(X2, Y2, Z2).
vector_dot(U, V, S) :-
U = p(X1, Y1, Z1),
V = p(X2, Y2, Z2),
S is X1 * X2 + Y1 * Y2 + Z1 * Z2.
intersect_point(RayVector, RayPoint, PlaneNormal, PlanePoint, IntersectPoint) :-
vector_minus(RayPoint, PlanePoint, Diff),
vector_dot(Diff, PlaneNormal, Prod1),
vector_dot(RayVector, PlaneNormal, Prod2),
Prod3 is Prod1 / Prod2,
vector_times(RayVector, Prod3, Times),
vector_minus(RayPoint, Times, IntersectPoint).
main :-
RayVector = p(0.0, -1.0, -1.0),
RayPoint = p(0.0, 0.0, 10.0),
PlaneNormal = p(0.0, 0.0, 1.0),
PlanePoint = p(0.0, 0.0, 5.0),
intersect_point(RayVector, RayPoint, PlaneNormal, PlanePoint, p(X, Y, Z)),
format("The ray intersects the plane at (~f, ~f, ~f)\n", [X, Y, Z]).
</syntaxhighlight>
{{out}}
<pre>
The ray intersects the plane at (0.000000, -5.000000, 5.000000)
</pre>
Line 902 ⟶ 1,528:
Based on the approach at geomalgorithms.com<ref>http://geomalgorithms.com/a05-_intersect-1.html</ref>
<
from __future__ import print_function
import numpy as np
Line 928 ⟶ 1,554:
Psi = LinePlaneCollision(planeNormal, planePoint, rayDirection, rayPoint)
print ("intersection at", Psi)</
{{out}}
Line 935 ⟶ 1,561:
=={{header|R}}==
{{trans|MATLAB}}
<
pdiff <- ray_point - plane_point
Line 944 ⟶ 1,570:
return(point)
}</
{{out}}
<
[1] 0 -5 5</
=={{header|Racket}}==
{{trans|Sidef}}
<
;; {{trans|Sidef}}
;; vectors are represented by lists
Line 974 ⟶ 1,600:
(line-plane-intersection (Line '(0 0 10) '(0 -1 -1))
(Plane '(0 0 5) '(0 0 1)))
'(0 -5 5)))</
{{out}}
Line 984 ⟶ 1,610:
{{trans|Python}}
<syntaxhighlight lang="raku"
has $.P0; # point
has $.u⃗; # ray
Line 1,007 ⟶ 1,633:
Line.new( :P0(0,0,10), :u⃗(0,-1,-1) ),
Plane.new( :V0(0,0, 5), :n⃗(0, 0, 1) )
);</
{{out}}
<pre>Intersection at point: (0 -5 5)</pre>
===With a geometric algebra library===
See task [[geometric algebra]]
<syntaxhighlight lang=raku>use Clifford:ver<6.2.1>;
# We pick a (non-degenerate) projective basis and
# we define the dual and meet operators.
my $I = [∧] my ($i, $j, $k, $l) = @e;
sub prefix:<∗>($M) { $M/$I }
sub infix:<∨>($A, $B) { ∗((∗$B)∧(∗$A)) }
my $direction = -$j - $k;
# Homogeneous coordinates of (X, Y, Z) are (X, Y, Z, 1)
my $point = 10*$k + $l;
# A projective line is a bivector
my $line = $direction ∧ $point;
# A projective plane is a trivector
my $plane = (5*$k + $l) ∧ ($k*-$i∧$j∧$k);
# The intersection is the meet
my $m = $line ∨ $plane;
# Affine coordinates of (X, Y, Z, W) are (X/W, Y/W, Z/W)
say $m/($m·$l) X· ($i, $j, $k);</syntaxhighlight>
{{out}}
<pre>(0 -5 5)</pre>
=={{header|REXX}}==
===version 1===
This program does NOT handle the case when the line is parallel to or within the plane.
<
Parse Value '0 0 1' With n.1 n.2 n.3 /* Normal Vector of the plane */
Parse Value '0 0 5' With p.1 p.2 p.3 /* Point in the plane */
Line 1,032 ⟶ 1,689:
z=a.3+t*v.3
Say 'Intersection: P('||x','y','z')'</
{{out}}
Line 1,040 ⟶ 1,697:
===version 2===
handle the case that the line is parallel to the plane or lies within it.
<
Parse Value '1 2 3' With n.1 n.2 n.3
Parse Value '3 3 3' With p.1 p.2 p.3
Line 1,162 ⟶ 1,819:
End
End
Return res </
{{out}}
<pre>Plane definition: x+2*y+3*z=18
Line definition: x=3*t ; y=2+2*t ; z=4+t
Intersection: P(0.6,2.4,4.2)</pre>
=={{header|RPL}}==
≪ → rd rp pn pp
≪ rd rp pp - pn DOT * rd pn DOT /
≫ ≫ '<span style="color:blue">INTLP</span>' STO
[ 0 -1 -1 ] [ 0 0 0 ] [ 0 0 1 ] [ 0 0 5 ] <span style="color:blue">INTLP</span>
{{out}}
<pre>
1: [ 0 -5 -5 ]
</pre>
=={{header|Ruby}}==
{{trans|C#}}
<
def intersectPoint(rayVector, rayPoint, planeNormal, planePoint)
Line 1,189 ⟶ 1,857:
end
main()</
{{out}}
<pre>The ray intersects the plane at Vector[0.0, -5.0, 5.0]</pre>
Line 1,196 ⟶ 1,864:
{{trans|Kotlin}}
<
#[derive(Copy, Clone, Debug, PartialEq)]
Line 1,301 ⟶ 1,969:
println!("{:?}", intersect(rv, rp, pn, pp));
}
</syntaxhighlight>
=={{header|Scala}}==
<
val (rv, rp, pn, pp) =
(Vector3D(0.0, -1.0, -1.0), Vector3D(0.0, 0.0, 10.0), Vector3D(0.0, 0.0, 1.0), Vector3D(0.0, 0.0, 5.0))
Line 1,329 ⟶ 1,997:
println(s"The ray intersects the plane at $ip")
}</
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/oLTlNZk/0 ScalaFiddle (JavaScript)].
=={{header|Sidef}}==
{{trans|Raku}}
<
P0, # point
u⃗, # ray
Line 1,357 ⟶ 2,025:
Line(P0: [0,0,10], u⃗: [0,-1,-1]),
Plane(V0: [0,0, 5], n⃗: [0, 0, 1]),
))</
{{out}}
<pre>Intersection at point: [0, -5, 5]</pre>
Line 1,363 ⟶ 2,031:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<
Class Vector3D
Line 1,414 ⟶ 2,082:
End Sub
End Module</
{{out}}
<pre>The ray intersects the plane at (0.00, -5.00, 5.00)</pre>
Line 1,420 ⟶ 2,088:
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-vector}}
<syntaxhighlight lang="wren">import "./vector" for Vector3
var intersectPoint = Fn.new { |rayVector, rayPoint, planeNormal, planePoint|
Line 1,450 ⟶ 2,099:
}
var rv =
var rp =
var pn =
var pp =
var ip = intersectPoint.call(rv, rp, pn, pp)
System.print("The ray intersects the plane at %(ip).")</
{{out}}
<pre>
The ray intersects the plane at (0, -5, 5).
</pre>
=={{header|XPL0}}==
{{trans|Wren}}
<syntaxhighlight lang "XPL0">include xpllib;
func real IntersectPoint; real RayVector, RayPoint, PlaneNormal, PlanePoint;
real Diff(3), Prod1, Prod2, Prod3, Prod(3);
[VSub(Diff, RayPoint, PlanePoint);
Prod1:= VDot(Diff, PlaneNormal);
Prod2:= VDot(RayVector, PlaneNormal);
Prod3:= Prod1 / Prod2;
return VSub(Diff, RayPoint, VMul(Prod, RayVector, Prod3));
];
real RV, RP, PN, PP, IP;
[RV:= [0., -1., -1.];
RP:= [0., 0., 10.];
PN:= [0., 0., 1.];
PP:= [0., 0., 5.];
IP:= IntersectPoint(RV, RP, PN, PP);
Print("The ray intersects the plane at %1.1f, %1.1f, %1.1f\n", IP(0), IP(1), IP(2));
]</syntaxhighlight>
{{out}}
<pre>
The ray intersects the plane at 0.0, -5.0, 5.0
</pre>
=={{header|zkl}}==
{{trans|Raku}}{{trans|Python}}
<
class Plane{ fcn init(pxyz, normal_xyz){ var pt=pxyz, normal=normal_xyz; } }
Line 1,477 ⟶ 2,152:
//w.zipWith('+,line.ray.apply('*,si)).zipWith('+,plane.pt); // or
w.zipWith('wrap(w,r,pt){ w + r*si + pt },line.ray,plane.pt);
}</
<
Line( T(0.0, 0.0, 10.0), T(0.0, -1.0, -1.0) ),
Plane(T(0.0, 0.0, 5.0), T(0.0, 0.0, 1.0) ))
);</
{{out}}
<pre>
|