[SOLVED] Point collision with cylinder

Started by
5 comments, last by PranKe01 12 years, 10 months ago
Hi guys,

I want to check, if a 3D-Point lies in a cylinder. I don't need any more information than true, or false :) But that isn't as easy, as I thought.
The Point got 3 coordinates: X, Y and Z. The Cylinder got following informations: startpoint, endpoint and the radius.

Right now I am calculating that for a rectangle in 2D space with following function:

[source lang="cpp"]

public static bool isBetweenPoints(Point3D point, Point3D lineStart, Point3D lineEnd) {
float deltaX = lineEnd.X - lineStart.X;
float deltaY = lineEnd.Y - lineStart.Y;
float deltaZ = lineEnd.Z - lineStart.Z;

float diagonalStartY = ((lineStart.X - point.X) * (deltaX / deltaY)) + lineStart.Y;
float diagonalEndY = ((lineEnd.X - point.X) * (deltaX / deltaY)) + lineEnd.Y;

if(deltaX / deltaY > 0) {
if(point.Y > diagonalEndY || point.Y < diagonalStartY) {
return false;
}
} else if(deltaX / deltaY < 0) {
if(point.Y < diagonalEndY || point.Y > diagonalStartY) {
return false;
}
} else {

}

return true;
}
[/source]


Here is a picture, which explains what I am doing above (I think you don't need to check the code).
qzFWF.png


I don't think that friggling that code into 3D space would make much sense...
One idea I had ist to transform the 3D problem into a 2D problem, by rotating the point and cylinder, so that the point got the Z-value 0. But I don't know how I can manage this.

So any hints about (hopefully performant) check if a point lies in a cylinder OR how to rotate the cylinder and point, so that a 2D problem remains, would be great! :)

Thanks in advance!
Advertisement
it's actually quite trivial:

let n = end - start

then

s = ((point - start) dot n) / ||n||^2
t = ||n cross (point - start)|| / ||n|

then the point is in the cylinder iff. 0 <= s <= 1 AND t <= radius
Code makes use of the Vector3D from namespace "System.Windows.Media.Media3D".


double radius = 10;


Vector3D m = Vector3D.substract(point, start);
Vector3D n = Vector3D.substract(end, start);
double s = Vector3D.DotProduct(m, n) / (n.Length * n.Length);
double t = Vector3D.CrossProduct(n, m).Length / n.Length;

if(0 <= s && s <= 1 && t <= radius){
return true;
}

return false;


Thanks luca :)
ahah i made a mistake infact, it should be [color="#1C2837"]s = (n dot point) / ||n||^2
That does not seem to work.

For example, I created following test case:

point: 10, 5, 0
start: 2, 2, 0
end: 10, 6, 0

With a radius of 10 this should return TRUE.
But with the above code, it returns FALSE.

The value of s in this case is 1.25! Note that n dot point returns 100 and the Length of n is 8.944. The value of t is 0.

The values of n are: x=8, y=4, z=0.<

Any hints, whats wrong?

Thanks :)
It looks like it makes a defference, which of both points (start and end) are the start and the end.
So when calculating n, it is a different result, when calculating end-start and start-end!
I think the result should be independent from the two points!?
that is because it should be

s = ((point - start) dot n) / ||n||^2
t = ||n cross (point - start)|| / ||n||

>.> i need to stop rushing things


(Fixed this in first response to avoid anyone trying out the wrong answer if they're looking for it too)
Thank you!

Now it works. Changed the code in previous post, too ;)


that is because it should be

s = ((point - start) dot n) / ||n||^2
t = ||n cross (point - start)|| / ||n||

>.> i need to stop rushing things


(Fixed this in first response to avoid anyone trying out the wrong answer if they're looking for it too)

This topic is closed to new replies.

Advertisement