Home > Software design >  Convert xy coordinates (in pixels) to barycentric coordinates (x,y,z)
Convert xy coordinates (in pixels) to barycentric coordinates (x,y,z)

Time:03-11

This may be a strange one but I have a graphic of a triangle like this: triangle

and in a survey platform, whenever one click on a point in this graphic an x,y coordinates in pixels are recorded like this (the origin for x,y is from the top-left of the image)

Note: the clicking is only allowed inside the green triangle.

coordinates

Is there a way to convert these coordinates to barycentric coordinates (x,y,z) with respect to a simplex in 2D (this triangle)?

If so what is the appropriate equation given that we have the x,y in pixels.

Would it matter if they are in pixels or are they still considered Cartesian coordinates?

Thanks!

CodePudding user response:

So you know the coordinates of the three vertex of the triangle

A: {ax, ay}
B: {bx, by}
C: {cx, cy}

and you want to take an arbitrary point

P: {px, py}

and find the three barycentric coordinates w_A, w_B, w_C such that

px = w_A * ax   w_B * bx   w_C * cx
py = w_A * ay   w_B * by   w_C * cy
1  = w_A   w_B   w_C

Turn this into a linear algebra problem

| px |   | ax  bx  cx | | w_A |
| py | = | ay  by  cy | | w_B |
|  1 |   |  1   1   1 | | w_C |

to be solved for {w_A,w_B,w_C}

Use the sample code below which I tested with the following results

Triangle A: <5, 0>
Triangle B: <2.5, 5>
Triangle C: <0, 0>
Random Point: <3.169941, 0.417091>
Barycentric: (0.5922791,0.08341819,0.3243028)
Target Point: <3.169941, 0.417091>

Triangle.cs

using System.Numerics;

namespace ConsoleApp2
{
    public class Triangle
    {
        public Triangle(Vector2 a, Vector2 b, Vector2 c)
        {
            A = a;
            B = b;
            C = c;
        }

        public Vector2 A { get; set; }
        public Vector2 B { get; set; }
        public Vector2 C { get; set; }

        public Vector2 GetPoint(float w_A, float w_B, float w_C) => GetPoint((w_A, w_B, w_C));
        public Vector2 GetPoint((float w_A, float w_B, float w_C) coord)
        {
            return coord.w_A * A   coord.w_B * B   coord.w_C * C;
        }
        public (float w_A, float w_B, float w_C) GetBarycentric(Vector2 P)
        {
            float D = A.X * (B.Y - C.X)   A.Y * (B.X - C.X)   B.X * C.Y - B.Y * C.X;

            float w_A = ((B.Y - C.Y) * P.X   (C.X - B.X) * P.Y   (B.X * C.Y - B.Y * C.X)) / D;
            float w_B = ((C.Y - A.Y) * P.X   (A.X - C.X) * P.Y   (C.X * A.Y - C.Y * A.X)) / D;
            float w_C = ((A.Y - B.Y) * P.X   (B.X - A.X) * P.Y   (A.X * B.Y - A.Y * B.X)) / D;

            return (w_A, w_B, w_C);
        }

        public bool Contains(Vector2 point)
        {
            var (w_A, w_B, w_C) = GetBarycentric(point);
            return w_A>=0 && w_A<=1
                && w_B>=0 && w_B<=1
                && w_C>=0 && w_C<=1;
        }
    }
}

Program.cs

using System;
using System.Numerics;

namespace ConsoleApp2
{

    public static class Program
    {
        static readonly Random rng = new Random();

        static Vector2 RandomVector(float minValue = 0, float maxValue = 1)
        {
            return new Vector2(
                minValue   (maxValue - minValue) * (float)rng.NextDouble(),
                minValue   (maxValue - minValue) * (float)rng.NextDouble());
        }

        static void Main(string[] args)
        {
            Vector2 A = new Vector2(5f,0f);
            Vector2 B = new Vector2(2.5f,5f);
            Vector2 C = new Vector2(0f,0f);

            var triangle = new Triangle(A, B, C);

            Console.WriteLine($"Triangle A: {A}");
            Console.WriteLine($"Triangle B: {B}");
            Console.WriteLine($"Triangle C: {C}");

            Vector2 P = RandomVector(0f, 5f);

            Console.WriteLine($"Random Point: {P}");

            var (w_A, w_B, w_C) = triangle.GetBarycentric(P);
            Console.WriteLine($"Barycentric: ({w_A},{w_B},{w_C})");

            Vector2 T = triangle.GetPoint(w_A, w_B, w_C);
            Console.WriteLine($"Target Point: {T}");
        }
    }

}

CodePudding user response:

Pixels are just the specific unit, this triangle representation would still be in cartesian coordinates, so you just apply the same formula, i.e. (as specified in the comments )this

  • Related