#Circles

1 messages · Page 1 of 1 (latest)

sharp rose
#

This seems to fail but only in 1 direction

#

@surreal mural this fails in negative direction for some reason

#
        {
            var dir = line.c1 - line.c0;
            var centerToOrigin = line.c0 - circle.xy;
            var radiusSq = circle.z * circle.z;

            if (math.lengthsq(math.cross(new float3(dir, 0), new float3(centerToOrigin, 0))) > radiusSq) return false;

            var a = math.dot(dir, dir);
            var b = 2 * math.dot(dir, centerToOrigin);
            var c = math.dot(centerToOrigin, centerToOrigin) - radiusSq;
            var discriminant = b * b - 4 * a * c;

            return !(discriminant < 0);
        }
#

(ignore the ! instead of >= thats just rider auto cleaning it up)

surreal mural
#

so according to this image, all you need is to find distance between point and a line segment, that is it
need to check where exactly it fails

sharp rose
#

nope never mind it fails in positive as well

#

basically it works on some segments but not others

#

segments around top left fail, segments on bottom right are fine

sharp rose
#

yes

#

this from enzi and slightly modified is working as expected

public static bool SegmentCircle(float2 p1, float2 p2, float2 center, float radius)
        {
            if (IsPointInsideCircle(p1, center, radius) ||
                IsPointInsideCircle(p2, center, radius))
            {
                return true;
            }

            p1 -= center;
            p2 -= center;
            var a = math.lengthsq(p2 - p1);
            var b = 2 * (math.dot(p1.x, p2.x - p1.x) + math.dot(p1.y, p2.y - p1.y));
            var c = math.lengthsq(p1.x) + math.lengthsq(p1.y) - math.lengthsq(radius);
            var disc = math.lengthsq(b) - (4 * a * c);

            if (disc <= 0)
            {
                return false;
            }

            // var sqrtDisc = math.sqrt(disc);
            // var t1 = (-b + sqrtDisc) / (2 * a);
            // var t2 = (-b - sqrtDisc) / (2 * a);

            var t1 = (-b + (disc / b)) / (2 * a);
            var t2 = (-b - (disc / b)) / (2 * a);

            return t1 is > 0 and < 1 || t2 is > 0 and < 1;
        }```
surreal mural
#

let's try to reduce it

velvet obsidian
#

would be cool if this can get even more optimized. i already got rid of the sqrt because the pointInsideCircle check catches where it would fail

sharp rose
#

if burst can't handle it automatically (i suspect not) i'm going to redo it with 2x float4

surreal mural
#
        public static bool SegmentCircle(float2 p1, float2 p2, float2 center, float radius)
        {
            var dir = p2 - p1;
            var toCenter = center - p1;
            var r2 = radius * radius;
            var projectedPoint = p1 + math.dot(toCenter, dir) * math.normalize(dir);
            var distanceToProjectionSq = math.distancesq(projectedPoint, center);
            return r2 <= distanceToProjectionSq;
        }
sharp rose
#

same issue

surreal mural
#

🤔

#

could you give me data which is failing?

velvet obsidian
#

do you not have a test setup? ^^

sharp rose
#

circle center, radius 10

#

collection of failing segments clearly further than 10 away

velvet obsidian
#

it returns true no matter where i put the line or circle

surreal mural
#

lol, >= instead of <=

#

but I'm not sure about coaligned vectors yet, checking

velvet obsidian
#

now it's false everytime ^^

#

this code only works when p1 is inside the circle. had to normalize math.dot(toCenter, dir) toCenter and dir though, otherwise it's pointing to the end of the map

surreal mural
#

yeah, I see where it comes from, it projects point on the ray as well

swift plover
#

Get closest point on line segment, compare to radius?

#
/// Find for a given point the closest point on a line segments
/// </summary>
public static float2 GetClosestPointOnLineSegment(float2 pointA, float2 pointB, float2 P)
{
    float2 AP = P - pointA;         //Vector from A to P   
    float2 edgeA = pointB - pointA; //Vector from A to B
    float dot = math.dot(edgeA, AP);
    float edgeLengthSquared = math.lengthsq(edgeA);
    dot = math.max(dot, 0.0f);              //Check if P projection is over vectorAB 
    dot = math.min(dot, edgeLengthSquared); //Check if P projection is over vectorAB 
    float invEdgeLengthSquared = 1.0f / edgeLengthSquared;
    float frac = dot * invEdgeLengthSquared; //The normalized "distance" from a to your closest point
    return pointA + edgeA * frac;
}```
#

the use it like float2 closestAB = GetClosestPointOnLineSegment(A, B, circleCenter); return math.distance(closestAB, circleCenter) < radius

surreal mural
#

it was close, nice catch @swift plover 😄

        public static bool SegmentCircle(float2 p1, float2 p2, float2 center, float radius)
        {
            var dir = p2 - p1;
            var toCenter = center - p1;
            var r2 = radius * radius;
            var dot = math.dot(toCenter, dir);
            var lenSq = math.dot(dir, dir);
            var projectedPoint = p1 + math.clamp(dot, 0, lenSq) / lenSq * dir;
            var distanceToProjectionSq = math.distancesq(projectedPoint, center);
            return r2 >= distanceToProjectionSq;
        }
velvet obsidian
#

this works nicely

sharp rose
#

ooo

#

that's what i want to see - will get it a test shortly

velvet obsidian
#

beautiful math 😄

sharp rose
#

can confirm it works

#

thanks a lot!

surreal mural
#

now just vectorize it and get some free juice 😄

sharp rose
#

yep

vapid bobcat
#

7 hours of circles discussionKEKLEO

sharp rose
#

but successful!

surreal mural
#

I mean it was almost solved right there #1064581837055348857 message
determinant + b and determinant - b represent a fraction of the line segment that lead to the projection point. for some reason I wasn't able to wrap my head around clamping it at that moment, happens sometimes 😅

vast idol
#

I see I missed the fun