# [SOLVED] Point collision with cylinder

## Recommended Posts

PranKe01    122
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).
[img]http://i.imgur.com/qzFWF.png[/img]

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!

##### Share on other sites
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

##### Share on other sites
PranKe01    122
Code makes use of the Vector3D from namespace "System.Windows.Media.Media3D".

[code]

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;[/code]

Thanks luca

##### Share on other sites
Hidden
ahah i made a mistake infact, it should be [color="#1C2837"][size="2"]s = (n dot point) / ||n||^2[/size][/color]

PranKe01    122
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

##### Share on other sites
PranKe01    122
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!?

##### Share on other sites
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)

##### Share on other sites
PranKe01    122
Thank you!

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

[quote name='luca-deltodesco' timestamp='1307441954' post='4820458']
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)
[/quote]