'Convert xy coordinates (in pixels) to barycentric coordinates (x,y,z)

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!



Solution 1:[1]

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}");
        }
    }

}

Solution 2:[2]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Makogan