| # Ternary diagram / ternary plot calculations• | **Ternary diagram / ternary plot calculations**
on Jan 20, 2016 at 6:19:23 pm |
To all masters of expressions & math!
I'm trying to create a ternary diagram where a dot layer would have three slider controls in which all 3 percentage values would be calculated from the dot's position on the diagram.
I already knew I wouldn't be able to figure out how to do get this to properly work, so I tried to at least create something extremely simple which would help me in reading the diagram and guess working it and then enter the displayed values manually - so I'd fake it. But this didn't work either, so I'm back at 0 and rethinking if I could maybe get it to work the way it should.
Is there someone who understands the math behind ternary diagrams and can fairly easily come up with the formula which I could put into 3 sliders to spit out the percentage?
Thanks a ton.
Just to let you know what I've been trying, here's my fake guess work expression:
For the y axis I mapped my points on the composition to 0 and 100% by interpolating the y position into percentages which get updated when I move the dot. I put this expression into a slider to display the percentage:
`y0 = 620;`
y100 = 450;
yR = position[1];
Math.round((linear(yR, y0, y100,100,0))/5)*5
Did the same for the x axis but I soon realised this his nowhere close to even helping me guess the correct values for my dot ;) so as I said, I will have to scratch all this.
• | **Re: Ternary diagram / ternary plot calculations** on Jan 20, 2016 at 9:13:14 pm |
Reading up on the ternary plot, I came to the following conclusion.
(Lets say that the percentage values run as follows: A horizontally at the base from right to left, B from lower left to top and C from top to lower right.) A, B and C are referring both to the percentages and the directions the percentages are plotted here
1) You need only two of the three values to locate the spot, for the third value C will always be C = 100-A-B.
2) This being the case, you could always start from the same corner (which would be 0,0) and use two vectors to calculate the position, thus
3) starting from lower right corner, move the amount of A*S (S = the length of the base or side) of the diagram to the left, then
4) move B% along the direction of side B, the formula for such move being x = S*B*cos(60) and y = S*B*sin(60)
Thus, from the origin point at the bottom right corner, the dot position should be at
x = -A*S + S*B*Math.cos(60)
y = S*B*Mat.sin(60)
That is, if I got that right. I didn't test my theory. • | **Re: Ternary diagram / ternary plot calculations** on Jan 20, 2016 at 9:38:19 pm |
Thank you so much Kalle,
I need to test this and see if the math works out, but I'm still missing a piece. As I understand your post, it would check the current X & Y position of the dot and spit out a coordinate, correct? How can I convert that X/Y information into the percentages for A and B?
• | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 9:21:39 am |
Hi Patrick,
No, it is supposed to generate the x and y positions from the percentages A and B. • | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 12:23:11 pm |
I think that Patrick wants the converse: given a reference triangle and a point in that triangle with comp coordinates [x,y], find the coordinates of the point in the triangle system (barycentric coordinates).
What the "formulas" look like will depend much on how you have parametrized the triangle. For instance in one case you know the coordinates of the 3 summits of the triangle, in another case you know the bottom left corner and the length of a side, and if you use a shape layer you'll know the center and outer radius. So you should tell more about your framework.
Xavier. • | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 6:57:12 pm |
Hmm, okay. What are the slider controls for then? Storing the results?
If that is the case, you would have to calculate the distances of the point to each side of the triangle. That's a different math problem...
• | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 7:05:08 pm |
Along these lines:
The dot's coordinates are (px, py)
The origin point is at the horizontal center of the base.
a = length of side of triangle
which makes the height of the triangle:
h = a*sin(60)
Distance from left side:
d1 = abs(h*px - py + h)/sqrt(h*h+1)
Distance from right side:
d2 = abs(-h*px - py + h)/sqrt(h*h+1)
Distance from base:
d3 = py
The three percentages would then be:
A = d1/(d1+d2+d3)*100
B = d2/(d1+d2+d3)*100
C = d3/(d1+d2+d3)*100
All theoretical. If there's an error somewhere, it's gonna be fun to try and find it. • | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 7:15:14 pm |
There might be a problem with the divisor sqrt(h*h+1). That's how the distance calculation equation ended up with b = -1, but it still doesn't make sense to me. Seems like there should be something there that depends on the length of the triangle's side instead of 1. (Just thinking aloud.) • | **Re: Ternary diagram / ternary plot calculations** on Jan 21, 2016 at 7:46:45 pm |
Yeah -- the left and right side distance calculations are messed up. I'll have to take another look at them.
• | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 10:22:10 am |
Thank you so much Kalle. At least I can follow along the lines of your math, but I couldn't come up with it myself! ;) • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 10:25:46 am |
Yes, the sliders are just there to store the results so that I can easily use these as text sources to display the percentage in the animation.
I used the 3 slider controls in the dot layer so that the expression can always easily reference to it's own layer position and that it's all in one place. • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 10:20:16 am |
"I think that Patrick wants the converse: given a reference triangle and a point in that triangle with comp coordinates [x,y], find the coordinates of the point in the triangle system (barycentric coordinates)."
Exactly that is what I'm looking for: I want to animate the dot, and I'm looking for an expression that calculates the percentages for A and B at that position.
Thanks, Xavier.
Actually it doesn't really matter how it is set it up, because I could easily change it. I would just have to make sure it fits. So if there's a workflow that would make it easier to get this going, let me know.
Right now, the triangle is an imported .ai vector and the easiest way from here would be to use the coordinates of the 3 summits. • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 1:28:10 pm |
The distance calculation between a point and a line can be found here:
Mathwold, Point-Line Distance
Since we know all the points (the corners that create the line and the point that we want to know the distance of), the solution lies here:
and in this formula:
• | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 2:58:56 pm |
oh my :) • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 5:25:31 pm |
The expression below is for a text layer (display all 3 coordinates in 1 single text) :
`A = thisComp.layer("A").transform.position.value;`
B = thisComp.layer("B").transform.position.value;
C = thisComp.layer("C").transform.position.value;
M = thisComp.layer("Point").transform.position.value;
AB = sub(B,A); if (AB.length<3) AB.push(0);
BC = sub(C,B); if (BC.length<3) BC.push(0);
CA = sub(A,C); if (CA.length<3) CA.push(0);
AM = sub(M,A); if (AM.length<3) AM.push(0);
u = cross(AB, CA);
U = dot(u,u);
c = dot(u, cross(AM, AB))/U*100;
b = dot(u, cross(AM, CA))/U*100;
a = 100-(b+c);
letters= ["a", "b", "c"];
values = [a,b,c];
for (k=0; k<3; k++) letters[k] += " : " + (values[k]<10 ? " " : "") + values[k].toFixed(1) + "%";
letters.join("\n");
It's not optimal as it does unnecessary calculations, but trying to optimize would make it less compact.
Xavier
• | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 6:29:11 pm |
Xavier got there before me :)
Anyways, attached is my humble approach which is not quite as compact.
I've used the coordinates that show on the diagram, so they need to be modified for a triangle that has different corner coordinates.
Also, there's no code checking that the dot is not outside the triangle, but I figured you will animate it so that that doesn't occur.
9698_ternarydiagram.aep.zip • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 7:47:38 pm |
Thank you, thank you, thank you, for your generous help!
Next beer's on me! :) • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 7:46:30 pm |
Wow! Both you guys are amazing. You just made my day.
Now I need to backtrace what you did, trying to understand the math and expressions behind it, but it's awesome already. I tried both solutions and they both work nicely!
I have the problem that I didn't get Xaviers solution to work. I tried this one first, because I could easily integrate into my existing comp. Now the percentages are all of. In a clean composition it works like a charm. But I'll go ahead and try to figure out what's going on there.
Just to be sure, @Xavier: I could also just add [x,y] values for each one of the ABC variables instead of linking layers to the expression, correct? • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 7:56:32 pm |
PS.
OK direct input of the coordinates works of course.
I just wanted to let you know whats happening where I integrated it into my comp:
In the center of the triangle I get
a: 100, b: 100, and c:-100
and for example at the lower left corner (A) I get
a: 164, b: 65, and c: -129
I'll continue to search for what happens. But maybe this already triggers for you what could be going wrong here. • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 8:00:15 pm |
OK I found it: I was relying on getting the summits XY positions from INFO window XY values, which were not the same as the true positions of the summits inside the comp
I got this working now, but how can the Info window be wrong? Any clue? • | **Re: Ternary diagram / ternary plot calculations** on Jan 22, 2016 at 8:31:45 pm |
I can't tell.
The expression i gave assumes that all point coordinates A, B, C and M are in the same system. Depending on your set up you might have to use one of the space transform functions (toComp/fromComp etc).
Also, that expression is unnecessarily heavy. If you have lots of points you can change it to this one, which does the same thing without extra stuff:
`A = thisComp.layer("A").transform.position.value;`
B = thisComp.layer("B").transform.position.value;
C = thisComp.layer("C").transform.position.value;
M = thisComp.layer("Point").transform.position.value;
AB = sub(B,A);
BC = sub(C,B);
CA = sub(A,C);
AM = sub(M,A);
u = AB[0]*CA[1]-AB[1]*CA[0];
c = 100 * (AM[0]*AB[1]-AM[1]*AB[0]) / u;
b = 100 * (AM[0]*CA[1]-AM[1]*CA[0]) / u;
a = 100-(b+c);
letters= ["a", "b", "c"];
values = [a,b,c];
for (k=0; k<3; k++) letters[k] += " : " + (values[k]<10 ? " " : "") + values[k].toFixed(1) + "%";
letters.join("\n");
Xavier • | **Re: Ternary diagram / ternary plot calculations** on Jan 24, 2016 at 11:22:37 am |
Thank you Xavier, and thank you also for the slimmed down version! I'll keep both of them for future references. This is so much better having the real values and just have them animate over time than to fake something messing around with trial and error until it would have looked somewhat realistic. Guess I'll need to get back to school ;)
I have found the problem as mentioned above. It does have something to do with the setup - as it seems it comes from an anchor point relation which makes the position values differ from the composition coordinates, and at first I took a read out from the info panel X/Y to set up my points, which messed it all up. • | **Re: Ternary diagram / ternary plot calculations** on Jan 25, 2016 at 11:37:58 am |
Yes, if the A,B,C points are somewhere deep inside a shape layer and the point M is sommewhere else, you are stuck as i think it is not possible to convert A, B, C in that case. At least i dont know how to do it.
It should be fine otherwise.
Side note: i just noticed that the variable called BC is not even used, so you can erase the corresponding line even in the "slimmed" version.
Xavier
| |