Notifications
Clear all

[Closed] Curve (not straight line) – Plane intersection

Hi to everyone, I am doing a design project for which I need to compute all the points of N number of 3D vertical curves (but not straight ones), that intersect with a plane – the plane is on XY axis. I know there is a thread in cg forum for computational geometry issues, but unless I am mistaken, there isn’t any algorithm for this task right ? Any help, pointers, advices on this one ?

Thanks in advance.

2 Replies

I figured out this method but its not working properly. The getLinePlaneIntersect function returns a bunch of collinear points. If someone has time just evaluate the code below to see
what I mean.
I use the getLinePlaneIntersect function by IllusionCatalyst.

fn getLinePlaneIntersect &p3LinePoint_1 &p3LinePoint_2 &rPlane fEpsilon:1e-4 =
 (
 	local p3LineVector = p3LinePoint_2 - p3LinePoint_1
 	local p3Vector_1 = rPlane.pos - p3LinePoint_1
 
 	local fNumer = dot rPlane.dir p3Vector_1
 	local fDenom = dot rPlane.dir p3LineVector
 
 	if ((abs fDenom) >= fEpsilon) then -- line intersects plane
 		return (p3LinePoint_1 + ((fNumer / fDenom) * p3LineVector))
 	else -- line is parallel to plane
 		return undefined
 )
 
 fn lineBetweenTwoPoints a b = (
 	spl  = SplineShape()
 	addNewSpline spl
 	addKnot spl 1 #corner #line a
 	addKnot spl 1 #corner #line b
 	updateShape spl
 	spl.wirecolor = red
 	--spl
 )
 
 fn testShape = (
 	testShape = splineShape()
 	addnewSpline testShape
 	for i = 1 to 100 by 10 do
 	(
 		addknot testShape 1 #smooth #curve [i, (i*i / 100.0), i]
 	)
 	updateShape testShape
 	testShape.wirecolor = color 255 0 0
 	testShape
 )
 
 pl = plane pos:[0, 0, 50] width:100 length:100 
 r = Ray pl.pos pl.dir
 testSh = testShape()
 INTERP = 40
 uStep = 1.0 / INTERP as float
 previous = lengthInterp testSh 0
 for u = uStep to 1.0 by uStep do (
 	current = lengthInterp testSh u
 	lineBetweenTwoPoints previous current
 	pt = getLinePlaneIntersect previous current r
 	if pt != undefined do point size:2.0 pos:pt wirecolor:green
 	previous = current
 )

Ok, so there is indeed a question in the Geometric Computing thread about finding the intersection of a 3d spline and a plane. Didn’t see it before.
I kind of figured out a way of finding the exact point of intersection of a spline and a plane, but it will not work in all cases. That collinear points that I was talking about where actually the projections of each small line fragment that I build for the interpolation of the spline on the plane… So to elliminate those, for each small line fragment that I build, I first I check if the returned point from getLinePlaneIntersect fn, lies within the distance between the first and the second vertex of that line. Then I check if the point found is actually on the plane, since the getLinePlaneIntersect function will return a point of intersection even if that point is not physically on the plane (since it computes the intersection of a plane by taking its direction vector and translation vector which do not define its physical limits). Then since there might be 1 or two points that are really really close to each other (comment this line to see what I mean), I put a count variable that stops the for loop when the first point is found – but this will not do if we want two points of intersection.
It does the job for me although there should be other more mathematically oriented ways. You can try it out:

fn getLinePlaneIntersect &p3LinePoint_1 &p3LinePoint_2 &rPlane fEpsilon:1e-6 =
   (
       local p3LineVector = p3LinePoint_2 - p3LinePoint_1
       local p3Vector_1 = rPlane.pos - p3LinePoint_1
   
       local fNumer = dot rPlane.dir p3Vector_1
       local fDenom = dot rPlane.dir p3LineVector
   
       if ((abs fDenom) >= fEpsilon) then -- line intersects plane
           return (p3LinePoint_1 + ((fNumer / fDenom) * p3LineVector))
       else -- line is parallel to plane
           return undefined
   )
   
   fn testShape = (
       testShape = splineShape()
       addnewSpline testShape
       for i = 1 to 100 by 10 do
       (
           addknot testShape 1 #smooth #curve [i, (i * i /100), i ]
       )
       updateShape testShape
       testShape.wirecolor = color 255 255 0
       testShape
   )
   
   fn isPtWithinPlane pt pl = (
       contains (box2 [pl.max.x, pl.max.y] [pl.min.x, pl.min.y]) [pt.x, pt.y]
   )
   
   pl = plane pos:[40, 0, 50] width:100 length:100 
   r = Ray pl.pos pl.dir
   testSh = $
   INTERP = 40
   uStep = 1.0 / INTERP as float
   previous = lengthInterp testSh 0.0
   count = 0
   for u = uStep to 1.0 by uStep while count < 1 do (
       current = lengthInterp testSh u
       pt = getLinePlaneIntersect previous current r
       if pt != undefined then (
           if distance previous pt <= distance previous current do (
               if isPtWithinPlane pt pl do (
                  point size:4.0 box:on pos:pt wirecolor:green
                  count += 1
               )
           )
       )
       previous = current
   )

Also I would appreaciate if someone could help write a better version that takes into consideration if two intersection points are needed. Cheers.