-1

I'm trying to determine if an infinite cylinder and circle intersect in 3D space. This has been asked here: Finding the intersection of the Circle and Infinite Cylinder in 3D space

However, only a mathematician can understand the response by Yves Daoust. There is another response by MBo, which I have coded (below). Unfortunately, testing shows that it doesn't work properly. I'm looking for help with this that a non-mathematician can understand. Thanks in advance!

// cylinderLoc = infinite cylinder location (any location on the cylinder axis)
// cylinderDir = infinite cylinder direction (normalized)
// cylinderRadius = infinite cylinder radius
// circleLoc = circle location (circle center)
// circleDir = circle direction (normalized direction of the circle plane)
// circleRadius = circle radius
bool cylinderIntersectCircle(
    Vector3 cylinderLoc, Vector3 cylinderDir, double cylinderRadius,
    Vector3 circleLoc, Vector3 circleDir, double circleRadius)
{
    // get the perpendicular distance from the circle center to the cylinder axis
    Vector3 diff = Vector3.Subtract(circleLoc, cylinderLoc);
    diff = Vector3.Cross(cylinderDir, diff);
    double distance = diff.Length(); // the length is also called the magnitude

    // get the dot product (cosine) between the cylinder and circle directions
    double dot = Vector3.Dot(cylinderDir, circleDir);

    // determine if the cylinder and circle intersect
    return (distance <= cylinderRadius + circleRadius * Abs(dot));
}

UPDATE: Here is a picture showing what might make is simpler. I need that "sweet spot" where the circle rim is deepest into the footprint that the cylinder has on the circle's plane. The direction from the circle center that takes it closest to the cylinder footprint. Cylinder / circle intersection

UPDATE 2: Here are some sample numbers for MBo to see that demonstrate his algorithm returning false when it should return true. Below it is a picture of the result. I made each object a different color to help. The camera is rotated 180 degrees for a better view (looking at the back). The green frame is "distance". The blue frame is "cylinderRadius + circleRadius * Abs(dot)".

cylinderLoc = ( 0.0, 0.0, 0.0 )
cylinderDir = ( 0.0, 1.0, 0.0 )
cylinderRadius = 0.3

circleLoc = ( -0.25, 0.0, -0.5 )
circleDir = ( -0.6, -0.5, 0.6245 )
circleRadius = 0.45
// get the perpendicular distance from the circle center to the cylinder axis
Vector3 diff = Vector3.Subtract(circleLoc, cylinderLoc);
// ---> diff = ( -0.25, 0.0, -0.5 ) - ( 0.0, 0.0, 0.0 )
// ---> diff = ( -0.25, 0.0, -0.5 )
diff = Vector3.Cross(cylinderDir, diff);
// ---> diff = cross(( 0.0, 1.0, 0.0 ), ( -0.25, 0.0, -0.5 ))
// ---> cross.x = 1.0 * -0.5  -  0.0  * 0.0   = -0.5
// ---> cross.y = 0.0 * -0.25 - -0.5  * 0.0   =  0.0
// ---> cross.z = 0.0 *  0.0  - -0.25 * 1.0   =  0.25
// ---> diff = ( -0.5, 0.0, 0.25 ));
double distance = diff.Length(); // the length is also called the magnitude
// ---> distance = Sqrt(-0.5 * -0.5 + 0.0 * 0.0 + 0.25 * 0.25)
// ---> distance = Sqrt(0.25 + 0.0 + 0.0625)
// ---> distance = Sqrt(0.3125)
// ---> distance = 0.55901699437494742410229341718282 (0.559 is close enough)

// get the dot product (cosine) between the cylinder and circle directions
double dot = Vector3.Dot(cylinderDir, circleDir);
// ---> dot = dot((0.0, 1.0, 0.0), (-0.6, -0.5, 0.6245))
// ---> dot = 0.0 * -0.6 + 1.0 * -0.5 + 0.0 * 0.6245
// ---> dot = -0.5

// determine if the cylinder and circle intersect
return (distance <= cylinderRadius + circleRadius * Abs(dot));
// ---> return (0.559 <= 0.3 + 0.45 * Abs(-0.5));
// ---> return (0.559 <= 0.525);
// ---> This returns false, but the circle does in fact intersect the cylinder.

enter image description here

msedore
  • 91
  • 2
  • 10
  • It can be simpler. Express it in code rather than in math lingo. If you could do that, a programmer can actually make use of it. I'd really appreciate it if you can do that. – msedore Apr 28 '20 at 20:48
  • It's not laziness. Most people have no idea how to understand math jargon. It couldn't possibly be that much code. I appreciate the help, but I'm afraid it's no help at all if I can't understand it. – msedore Apr 28 '20 at 21:23
  • 1
    Does this answer your question? [Finding the intersection of the Circle and Infinite Cylinder in 3D space](https://stackoverflow.com/questions/38841967/finding-the-intersection-of-the-circle-and-infinite-cylinder-in-3d-space) – Sneftel Apr 28 '20 at 23:12
  • My opening statement shows that same link. As I stated, math jargon isn't very useful to a non-mathematician. I need code, or something close. Saying things like "parametric equation of the circle" means nothing to me. – msedore Apr 28 '20 at 23:17
  • 1
    Well, to be fair, all university IT/programming programs I know of (Sweden) begin with courses in mathematics: calculus, multivariable calculus, linear algebra, vector analysis, complex analysis, ... And the parametric equation of a circle is given in the very first course of the first term. – Andreas Rejbrand Apr 29 '20 at 11:26
  • "Only a mathematician" - I was taught about conic sections in high school. If this math is over your head you can't solve this problem. – duffymo Apr 29 '20 at 12:08
  • duffymo, don't underestimate what people can do with little understanding of math terms. I created my own 3D rendering engine, with lighting, normal maps, etc. It supports skeletal rigging and animation. I can import a model of Lara Croft and a motion file, and make her dance. I created my own shaders. I am working on intersections and containments with points, rays, lines, triangles, planes, circles, spheres, boxes, frustums, and capsules. I have almost all combinations working flawlessly now. I did all of this without knowing terms such as "parametric equation of the circle". – msedore Apr 29 '20 at 12:27

2 Answers2

0

I've made quick test - literal implementation in Delphi of my answer in cited topic and results look correct.

Cylinder radius 2 is along OX, circle center at by=5.

For circle normal along OX (parallel cylinder, commented bdx, bdy in code) intersection exists for circle radius br = 4 and 5 and no intersection for br = 2.

For circle normal inclined by 45 (bdx, bdy = 0.707 in code) intersection exists for circle radius br = 5 and no intersection for br = 2, 4 (in the last case projection of circle radius becomes ~2.8 < 3).

Could you check your function with the same data sets?
Are you direction vectors really normalized?

Also note that this approach gives only fact of intersection, for the closest point we should work a bit more.

var
  ax, ay, az, bx, by, bz: Double;
  adx, ady, adz, bdx, bdy, bdz, ar, br: Double;
  cdx, cdy, cdz, vpx, vpy, vpz, vplen: Double;
  adot: Double;
begin
  ax := 0;
  ay := 0;
  az := 0;
  bx := 3;
  by := 5;
  bz := 0;
  adx := 1;
  ady := 0;
  adz := 0;
  bdx := 0.7071;
  bdy := 0.7071;
  //bdx := 1
  //bdy := 0;
  bdz := 0;
  ar := 2;
  br := 5; //2,4
  cdx := bx - ax;
  cdy := by - ay;
  cdz := bz - az;
  vpx := ady * cdz - adz * cdy;
  vpy := adz * cdx - adx * cdz;
  vpz := adx * cdy - ady * cdx;
  vplen := sqrt(vpx * vpx + vpy * vpy + vpz * vpz);
  adot := Abs(adx * bdx + ady * bdy + adz * bdz);
  if vplen <= ar + br * adot then
    Caption := 'Intersection'
  else
    Caption := 'No';
MBo
  • 77,366
  • 5
  • 53
  • 86
  • Thanks for the response. Yes, my directions are normalized. I'm running tests in my own 3D engine. I'm testing intersections and containments with points, rays, lines, triangles, planes, circles, spheres, boxes, frustums, and capsules (ray/cylinder and 2 points/spheres). I process and render two objects moving about randomly, and make them red whenever they intersect. I have almost all object combinations working flawlessly. I'm still working on the circles, and need the infinite cylinder working to intersect a capsule. The code above is sorta close, but not accurate. How's it look to you? – msedore Apr 29 '20 at 08:52
  • MBo, I added "UPDATE 2" to my post that shows some sample numbers returning false when they should return true. Please take a look and see if you spot any flaws. – msedore Apr 29 '20 at 11:25
  • Thanks for the sample. Seems I wrongly make circle contraction in all directions. Will rethink when possible. – MBo Apr 29 '20 at 12:27
0

A picture says a thousand words. This is what I have come up with for now. It's not 100% perfect, but it's pretty close. The magenta dots in the picture can all be calculated, meaning that the yellow lines can be calculated. Simply see if the yellow line intersects the cylinder, which is easy to do.

  • Get the perpendicular direction from the cylinder axis location to the plane of the circle.
  • Cross it with the cylinder axis to get the horizontal crosshair.
  • Cross that with the cylinder axis to get the vertical crosshair.
  • Offset the cylinder axis by its radius along the vertical crosshair in both directions.
  • Intersect both axis (rays) with the plane of the circle for the two end points of the ellipse.
  • We are essentially in 2D now:
  • These two points are on the plane of the circle. Connect them for the long axis of the ellipse.
  • Find the closest point on that line to the circle center. Map it to the circle radius.
  • Take the line from the circle center to the ellipse center. Map it to the circle radius.
  • The center of these two locations is the magenta dot in the picture. Map it to the circle radius.
  • The circle center to this location is the yellow line. Intersect it with the cylinder.

enter image description here

msedore
  • 91
  • 2
  • 10