Need help with vector math checking if Actor is inside a Cylinder area

I’m having a hard time figuring this out, not that good at vectors, from a single vector location I’m trying to figure out how to do a “Cylinder mask made with checks” being able to orient it from that central point in order to trigger a response when actor is inside the Cylinder bounds.

Looking to do this with just vector math or math expressions as creating an actor and using collisions ain’t an option in this case.

Aiming to just being able to orient the Cylinder rotating it by the Z axis

So far I believe I’m on the right path getting the vertical height using the cylinder radius by just subtracting the Actors Z with Point Z and checking if it’s inside its radius.

Doing basically this, checking if actor is inside the radius with infinite bounds along Z plane

Not having that luck with the X/Y handling though as I’m ending up just creating a square x) by getting the distance and comparing it with the Radius too (not weight).

If this is possible, figuring out how to handle X/Y and then how to rotate it would be greadly appreciated

Feel free to ask me for more info if not explaining it properly

I suggest the following:

  1. the orientation of your cylinder is known. it is the vector of the cylinder axis

  2. we can write down the planes coordinate equation which is: n.xx + n.yy + n.z*z = d, The normal vector n is made up by n.x,n.y and n.z as its xyz coordinates. It must be a unit vector.

  3. calculate d for the plane of interest where your point of interest is on.

  4. what you want to do next is calculate the intersection point of your cylinder axis with that plane in order to measure the distance between your point of interest and the cylinder axis.

  5. therefore set up a straight light equation (of the cylinder axis) X = P + r * n where P is the centre of the cylinder and n the normal vector of your plane.

  6. fill in the equation above:
    x = P.x + r * n.x
    y = P.y + r * n.y
    z = P.t + r * n.z
    n.x * (P.x + r * n.x) + n.y * (P.y + r * n.y) + n.z * (P.z + r * n.z) = d
    → what we are interested in is
    r = (d - (n.xP.x + n.yP.y +n.zP.z)) / (n.xn.x +n.yn.y + n.zn.z)

  7. calculate X = P + r * n to find the closest point on the cylinder axis to our point of interest.

  8. by measuring the distance between X and our point of interest you can determine if it is within the radius of an infinite cylinder along the given axis.

  9. by measuring the distance between X and the center point of your cylinder you can determine if it is within the cylinder of a given length.

p.s. long post, hope i did not mess up but very confident about the approach. :slight_smile:

1 Like

You might as well just use the “Find Closest Point on Line” node and skip 1-7. :wink:

2 Likes

This definitely worked, spended all day figuring this out indeed it works! Finally created a C++ method as in BP was having a hard time recreating all the math. A hundred thanks my friend!

If anyone is ever interested ended up doing this

FVector FCylinderIntersection::FindClosestPointOnAxis(const FVector& PointOfInterest, const FVector& CylinderCenter, const FVector& CylinderAxis)
{
    FVector NormalizedCylinderAxis = CylinderAxis.GetSafeNormal();
    float d = FVector::DotProduct(NormalizedCylinderAxis, PointOfInterest - CylinderCenter);
    FVector ClosestPointOnAxis = CylinderCenter + d * NormalizedCylinderAxis;
    return ClosestPointOnAxis;
}

bool FCylinderIntersection::IsPointInsideCylinder(const FVector& PointOfInterest, const FVector& CylinderCenter, const FVector& CylinderAxis, float CylinderRadius, float CylinderLength)
{
    FVector ClosestPointOnAxis = FindClosestPointOnAxis(PointOfInterest, CylinderCenter, CylinderAxis);

    // Check if the point is within the radius of the infinite cylinder
    float DistanceToPoint = FVector::Distance(PointOfInterest, ClosestPointOnAxis);
    if (DistanceToPoint > CylinderRadius)
    {
        return false;
    }

    // Check if the point is within the cylinder of a given length
    float DistanceToCenter = FVector::Distance(ClosestPointOnAxis, CylinderCenter);
    if (DistanceToCenter > CylinderLength / 2)
    {
        return false;
    }

    return true;
}

That, properly exposed as a function library, looks like this:

With POI being the Plane position and being able to specify the axis it just works beautifully :slight_smile:

1 Like

Can you explain what you are doing with the dot product here?

Used to calculate point 4.

The input parameters are PointOfInterest (like the Plane Location), CylinderCenter and CylinderAxis (the axis direction).

CylinderAxis is normalized to obtain a unit vector (NormalizedCylinderAxis) as you suggested.

The dot product here is used to find the projection of a vector onto the cylinder’s axis, which finds the closest point on the cylinder’s axis to the given point of interest.

Calculated between NormalizedCylinderAxis and the vector representing the difference between the PointOfInterest and CylinderCenter, which is effectively projecting that difference vector onto the cylinder’s axis.

Then stored in “d”, represents how far (or how much) the closest point is along the cylinder’s axis from the cylinder center.

The ClosestPointOnAxis is then found by adding the ‘d’ multiples of NormalizedCylinderAxis to the CylinderCenter.

Then is later used in the IsPointInsideCylinder() function to determine whether the point is inside the cylinder or not by checking the distance to the closest point and comparing it with the cylinder’s radius and length my friend!

1 Like

Oh - Great! Didn’t think of the projection but that works just as well. Happy to help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.