Barycentric coordinates

===========================

Barycentric coordinates are a mathematical concept used to represent the location of a Point inside or on a polyhedron, such as a triangle, tetrahedron, or sphere. They provide a powerful way to describe the position of points in 3D space.

Definition


In general Relativity, Barycentric coordinates are defined as a set of three numbers (α, β, γ) that represent the relative weights or proportions of each Point inside a polyhedron. These coordinates are often used in Computer graphics and Game development to calculate the position and orientation of objects within 3D scenes.

Basic Formula


The basic formula for Barycentric coordinates is given by:

β = (x - P) / P

where β is the Angle between the Point (x, y, z) and the normal Vector (P), x and y are the Screen coordinates, and z is the Height.

α = 1 - β

γ = 1 - α

Examples


Triangle Barycentric coordinates

Suppose we have a triangle ABC with vertices A(0, 0, 0), B(3, 0, 4) and C(0, 4, 5).

To calculate the Barycentric coordinates of Point P(1, 1, 2):

β = (x - xP) / Px = (1 - 1) / 0 = ∞

α = 1 - β = 1 - ∞ = 0

γ = 1 - α = 1 - 0 = 1

So, the Barycentric coordinates of Point P are infinity, zero, and one.

Tetrahedron Barycentric coordinates

Suppose we have a tetrahedron ABCD with vertices A(0, 0, 0), B(3, 0, 4) and D(2, 4, 6).

To calculate the Barycentric coordinates of Point E(1, 1, 1):

β = (x - xE) / Px = (1 - 1) / 2 = 0

α = 1 - β = 1 - 0 = 1

γ = 1 - α = 1 - 1 = 0

So, the Barycentric coordinates of Point E are zero and one.

Applications


Barycentric coordinates have many applications in Computer graphics and Game development, including:

Programming Examples


Here are some examples of how Barycentric coordinates can be implemented in programming languages such as C++ and Python:

C++:

#include <iostream>
#include <<a href="/Vector" class="missing-article">Vector</a>>

struct <a href="/Point" class="missing-article">Point</a> {
  double x, y, z;
};

std::pair<double, double, double> barycentric(<a href="/Point" class="missing-article">Point</a> p, const std::<a href="/Vector" class="missing-article">Vector</a><<a href="/Point" class="missing-article">Point</a>>& vertices) {
  for (const auto& v : vertices) {
    double beta = dot(p - v, v - p);
    if (beta > 0) {
      return {beta, v.y / abs(beta), v.z / abs(beta)};
    }
  }
  throw std::runtime_error("No valid <a href="/Barycentric_coordinates" class="missing-article">Barycentric coordinates</a> found");
}

double dot(const <a href="/Point" class="missing-article">Point</a>& u, const <a href="/Point" class="missing-article">Point</a>& v) {
  return u.x * v.x + u.y * v.y + u.z * v.z;
}

Python:

import math

class <a href="/Point" class="missing-article">Point</a>:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

def barycentric(<a href="/Point" class="missing-article">Point</a>, vertices):
    dot_product = 0.0
    for <a href="/Vertex" class="missing-article">Vertex</a> in vertices:
        v_dot_u = <a href="/Point" class="missing-article">Point</a>.x * <a href="/Vertex" class="missing-article">Vertex</a>.x + <a href="/Point" class="missing-article">Point</a>.y * <a href="/Vertex" class="missing-article">Vertex</a>.y + <a href="/Point" class="missing-article">Point</a>.z * <a href="/Vertex" class="missing-article">Vertex</a>.z
        if abs(v_dot_u) < 1e-9:  # avoid division by zero
            continue
        <a href="/Angle" class="missing-article">Angle</a> = math.acos(v_dot_u / (dot_product * dot_product))
        return <a href="/Angle" class="missing-article">Angle</a>, <a href="/Vertex" class="missing-article">Vertex</a>.y / <a href="/Angle" class="missing-article">Angle</a>, <a href="/Vertex" class="missing-article">Vertex</a>.z / <a href="/Angle" class="missing-article">Angle</a>

<a href="/Angle" class="missing-article">Angle</a>, y, z = barycentric(<a href="/Point" class="missing-article">Point</a>(0.5, 0.5, 0.5), [<a href="/Point" class="missing-article">Point</a>(3, 0, 4), <a href="/Point" class="missing-article">Point</a>(2, 4, 6)])
print(f"<a href="/Angle" class="missing-article">Angle</a>: {math.degrees(<a href="/Angle" class="missing-article">Angle</a>)} degrees")
print(f"<a href="/Barycentric_coordinates" class="missing-article">Barycentric coordinates</a>: ({y}, {z})")