将 xy 坐标(以像素为单位)转换为重心坐标 (x,y,z)

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

这可能有点奇怪,但我有一张这样的三角形图形:

并且在测量平台中,每当点击此图形中的一个点时, 像素 中的 x,y 坐标会这样记录(x,y 的原点来自图片的左上角)

注意:点击只能在绿色三角形内。

有没有办法将这些坐标转换为相对于二维单纯形(此三角形)的重心坐标 (x,y,z)?

如果是的话,考虑到我们有 像素 .

中的 x,y,合适的方程式是什么

它们是以像素为单位还是仍然被视为笛卡尔坐标会很重要吗?

谢谢!

像素只是特定的单位,这个三角形表示仍然是笛卡尔坐标,所以你只需应用相同的公式,即(如评论中指定)this

所以你知道三角形三个顶点的坐标

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

而你想取任意点

P: {px, py}

并找到三个重心坐标 w_Aw_Bw_C 使得

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

将其转化为线性代数问题

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

待解决 {w_A,w_B,w_C}

使用下面我测试的示例代码得到以下结果

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

}