🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Calculating Corner "Normals"

Started by
5 comments, last by EnlightenedOne 5 years, 9 months ago

Hi All,

Imagine the triangle with points ABC is being scaled about its center to the points A2B2C2:

basicMath.png.5145cdba51e20ac9f81951cef8d66594.png

First off, this has been driving me crazy but does the direction/angle each corner will move in have a name? I want to call them corner normals or is the correct term corner bisectors?

Given I am operating in 2D how do I get from knowing points ABC to position B2 given an arbitrary magnitude? Under the hood I want to do this for polygons by walking along the points that define the shape but until I can do it with a triangle I am going to feel like an imbecile.

Here is what I am trying to do now to calculate B2 manually:

// Calculate the vectors

        Vector2 vectorA = posA - posB;
        Vector2 vectorB = posC - posB;

//Calculate the angle between the vectors and combine them into a single angle

        float thetaA = Mathf.Atan2(vectorA.x, vectorA.y);
        float thetaB = Mathf.Atan2(vectorB.x, vectorB.y);
        float thetaMid = (thetaA + thetaB) / 2;

//Move the point in the direction of the angle by an arbitrary factor so I can visually validate it is correct or not

        Vector2 target = new Vector2(posB.x, posB.y);
        Move(ref target, 1, thetaMid);
        newPosB = target;

        SetPositions(posA, posB, posC, newPosB);

    public static void Move(ref Vector2 target, float magnitude, float heading) {
        target.x += magnitude * Mathf.Cos(heading);
        target.y += magnitude * Mathf.Sin(heading);
    }

The above code fails as the calculation for the angle is wrong, if you can see why or have a more efficient solution please put me out of my misery! :)

Kind Regards,

EO

 

Advertisement

I dont even understand what are you trying to do do you want to scale the smaller triangle to bigger one? Or what?

Cause if so you just

vdir = normalize(center_point,vertex);

newPoint = vertex+vdir*whatever wall thickeness you want

 

I just dont get you

It seems like what you're trying to do is polygon offsetting: https://stackoverflow.com/questions/1109536/an-algorithm-for-inflating-deflating-offsetting-buffering-polygons

This can be tricky in the general case, but there are several libs/algos available that should help you linked in that thread.

(Maybe you're trying to do what you literally said -- scale a triangle away from its centroid -- in which case there are easier solutions. It just seemed like in general what you were after was offsetting)

A simple way to offset a polygon that I've used in the past is to move each vertex along the average of the normals of the edges adjacent to that vertex. eg:


//given vec2 a,b,c (counterclockwise ordered verts) and offset distance r:
vec2 n0 = Perp(b-a)/Len(b-a);//n0,n1 are outward-facing normals adjacent to b
vec2 n1 = Perp(c-b)/Len(c-b);//Perp(v) is vec2(-v.y,v.x), Len(v) is Sqrt(v.x*v.x + v.y*v.y)

vec2 n = n0 + n1;
vec2 b2 = b + n*(r / (n.x*n.x + n.y*n.y));

Note that you might need to use Perp(v)=(v.y, -v.x) depending on whether +y is up or down in your coordinate system. Anyway this will still work it'll just offset stuff inward so you'll know you need to multiply something by -1 to fix it ;)

In mathematics, scaling uniformly or homogeneously, is called homothetic transform. Reading about this article might shed some lights to the OP.

11 hours ago, EnlightenedOne said:

Given I am operating in 2D how do I get from knowing points ABC to position B2 given an arbitrary magnitude?

Don't overcomplicate this.

To scale a triangle by an arbitrary amount, use this formula:

B2 = (B - center) * scale_factor + center (where B is the vertex, and center is the average of all vertices, or whatever you want the center to be)

Your "corner normal" is therefore B - center.  Do not normalize this value, or your triangle will no longer maintain its shape when it is scaled.

If for some reason you want B2 to move by a fixed amount relative to B and you don't mind the triangle losing its shape, use this formula instead:

B2 = B + normalize(B - center) * magnitude

This has a normalized "corner normal" of normalize(B - center).

The same formula works for arbitrary polygons, with the caveat that it's possible for an arbitrary polygon to have a vertex at its center, which makes B - center a zero vector and leaves normalize(B - center) undefined.  No need to bring trigonometry into it.

Hi Everyone,

Thank you for the detailed replies, sorry I wanted to avoid explaining the full drawn out scenario by abstracting it to its base elements and in doing so I obfuscated things, I am trying to calculate coordinates off of a delaunay dual graph, I hit upon a scenario where I could make some variation in how something visually appears if I projected outward from a set of points along a particular plane.

On 10/1/2018 at 3:00 AM, _WeirdCat_ said:

normalize(center_point,vertex)

-I am not clear on what this normalize function would do subtract one param from the other and then normalise the result of that?

On 10/1/2018 at 6:33 AM, raigan said:

It seems like what you're trying to do is polygon offsetting

-Actually this is slightly off of what I was trying to do but it is something I am very interested in doing, if I create shapes from my voronoi and decide to scale them out to render a perimeter or something this will make life very easy, thanks!

On 10/1/2018 at 9:38 AM, Silence@SiD said:

In mathematics, scaling uniformly or homogeneously, is called homothetic transform. Reading about this article might shed some lights to the OP.

-Thanks for the reference I was failing to recall the word uniform.

On 10/1/2018 at 1:19 PM, a light breeze said:

B2 = (B - center) * scale_factor + center 

-This solved it for me I had tunnel vision trying to solve for an angle when the vector from the corner to the center was exactly what I needed:

        Vector2 midPoint = (pos1 + pos2 + pos3)/3;
        targetPoint = midPoint + (pos2 - midPoint) * 1.5f;

Many Thanks,

EO

 

This topic is closed to new replies.

Advertisement