# Barycentric coordinates

I am 100% new to mathematica and I don't really understand if I am doing this correctly. I have some most code except the calculation of the color. I will do that once I know I am doing this correctly. I am trying to make sure it is correct and if am not I need some direction as to what I am doing wrong. I added comments if that helps. Anything helps!

(* Triangle vertices *)

v1 = {-2.0, -2.0};
v2 = {2.0, -2.0};
v3 = {0.0, 2.0};

(* xy-space to plot *)

c1 = {1, 0, 0};
c2 = {0, 1, 0};
c3 = {0, 0, 1};

I am trying to Compute the barycentric coordiantes of a 2D point xy based on triangle vertices v1, v2, v3 and that is what I need help on because I'm not sure that I got it right.

(* Input: xy = {x, y} and global v1, v2, v2 each as {x,y} *)
(* Output: uvw = {u, v, w}, the barycentric coordinates *)

(* The entries in the linear system set-up below need set. I Determine what
values in function *)

computeBaryCoords[xy_] := (
mat = {{v1[[1]], v2[[1]], v3[[1]]}, {v1[[2]], v2[[2]], v3[[2]]}, {v1, v2, v3}};
rhs = {xy[[1]], xy[[2]], mat};
uvw = LinearSolve[mat, rhs];
Return[uvw]
);

computeColor[uvw_] := Return[ (* going to calculate colors *)];

range = 4;
plotTriangle =
Graphics[
{EdgeForm[Thick], White, Polygon[{v1, v2, v3}],
PointSize[0.05],
RGBColor[c1], Point[v1],
RGBColor[c2], Point[v2],
RGBColor[c3], Point[v3]},
Axes -> True,
PlotRange -> {{-range, range}, {-range, range}}];

Manipulate[(
uvw = computeBaryCoords[xy];
rgb = computeColor[uvw];
plotPoint =
Graphics[
{RGBColor[rgb[[1]], rgb[[2]], rgb[[3]]], PointSize[0.08],  Point[xy]}];
plotBaryCoords =
Graphics[
{Black
Text[Style["Barycentric Coordinates: ", FontSize -> 15], {0, 4}, Scaled[{1, 1}]],
Text[Style[NumberForm[uvw, 2], FontSize -> 15], {4, 4}, Scaled[{1, 1}]]}];
Show[{plotTriangle, plotPoint, plotBaryCoords}]),
{{xy, {0, 0}}, Locator}]
• Does computeBaryCoords work incorrectly? Or is it the Manipulate that misbehaves? – Michael E2 Sep 29 '17 at 1:26
• @michaelE2 I had to respost the question becuase I posted as guest and I could not comment on it. Yes I think the problem is in the computerBaryCords – user2896245 Sep 29 '17 at 1:39

computeBaryCoords[xy_] := With[
{mat = {{v1[[1]], v2[[1]], v3[[1]]}, {v1[[2]], v2[[2]], v3[[2]]}, {1, 1, 1}}},
LinearSolve[mat, Append[xy, 1]]
]

Basically, your mat and rhs were not quite right, and one should never use Return as the last expression, as it is redundant. Quick check:

coords = computeBaryCoords[{1,1}]
coords . {v1, v2, v3}

{-0.125, 0.375, 0.75}

{1., 1.}

However, I think it makes sense to make the dependencies on the vertices explicit, so I would use something like this:

BarycentricTransform[{v1_,v2_,v3_}] := TransformationFunction[
{4,3},
{{0,0,1}}
]
]

Here is an example of it in use:

bf = BarycentricTransform[{v1, v2, v3}];

bf[{{1,1}, {1,2}, {0, 1}}]
% . {v1,v2,v3}

{{-0.125, 0.375, 0.75}, {-0.25, 0.25, 1.}, {0.125, 0.125, 0.75}}

{{1., 1.}, {1., 2.}, {0., 1.}}

Update

Here's an update that works with higher dimensions:

BarycentricTransform::nonn1 = "The list of vectors should have equal length, and the number of arguments is expected to be 1 less than their length";

BarycentricTransform[v_List] := Module[{dim=Dimensions[v], res},
res = If[!MatchQ[dim, {n_, m_} /; m+1 == n],
Message[BarycentricTransform::nonn1];
$Failed, With[{mat = Inverse @ PadRight[Transpose @ v, dim + {0, 1}, 1]}, AffineTransform[{mat[[All, ;;-2]], mat[[All, -1]]}] ] ]; res /; !MatchQ[res,$Failed | _AffineTransform]
]

An example with dimension 5:

SeedRandom[1];
v = RandomReal[10, {5, 4}];
bf = BarycentricTransform[v];

pts = RandomReal[5, {3, 4}];
bf[pts]

{{5.93009, -0.958983, 4.6546, -3.60732, -5.01838}, {-1.13559, 1.21887, -0.129826, 0.174377, 0.872176}, {4.93582, -0.689189, 3.94031, -2.94722, -4.23972}}

Check that the coordinates sum to 1:

Total[bf[pts], {2}]

{1., 1., 1.}

Check that the dot product with the vectors reproduces the initial points:

bf[pts] . v == pts

True