I have a graph that is represented by three different sized circles, based on the presence of a given element in the result set. The first circle is always set to 100%, being this is the largest the circle can be, the other two are relative % to the largest one.
The problem is that I am trying to use css to render them and I do not know the math necessary to figure out how to make them all "stick" together along their sides.
The known pieces will be the radius of each circle, and the largest one is always returned first.
Here is an example of what I’m trying to accomplish:
How can I accomplish this mathematically such that i can supply each circle with a margin-top and margin-left that will position them in this way?
I can position the largest circle at 0,0, and the second largest at half the difference between the 2 diameters, making the center points line up. The real challenge is the third smallest circle, in knowing where to position it based on the other two circles' positions.
Build triangle with sides radius0, radius1 and radius2 and calculate the third vertex coordinate (smallest circle center). I've used formula (23) from here in my calculation. There is Delphi code, but I hope the principle is clear.
var
r0, r1, r2: Integer;
x0, x1, x2, y0, y1, y2: Integer;
a, b, c, ca: Double;
begin
//some intialization
Canvas.FillRect(ClientRect);
Randomize;
r0 := 200;
r1 := Round(r0 * (0.25 + 0.75 * Random));
r2 := Round(r1 * (0.25 + 0.75 * Random));
//circle centers' coordinates
//biggest
x0 := r0;
y0 := r0;
//second
x1 := x0 + r0 + r1;
y1 := y0;
//triangle sides
c := r0 + r1;
b := r0 + r2;
a := r1 + r2;
//x-shift
ca := (c * c + b * b - a * a) / (2.0 * c);
x2 := x0 + Round(ca);
//y-shift is the height of triangle
//Pythagor's rule
y2 := y0 + Round(Sqrt(b * b - ca * ca));
//draw calculated circles
Canvas.Ellipse(x0 - r0, y0 - r0, x0 + r0 + 1, y0 + r0 + 1);
Canvas.Ellipse(x1 - r1, y1 - r1, x1 + r1 + 1, y1 + r1 + 1);
Canvas.Ellipse(x2 - r2, y2 - r2, x2 + r2 + 1, y2 + r2 + 1);
example output:
Ok, lets go through each one... lets assume your 100% A circle has radius x (so B be would be Bx and c might be Cx, B = .7 and C = .3 as an example).
As another aside I would actually have a <div style="position: relative"></div>
and then your circles would be <div style="position: absolute, top: 0, left: 0"></div>
instead of using margin-top/margin-left
ANYWAYS. Obviously will have top/left = 0.
From your picture it looks like the centers of A and B line up... This would mean B would have left = 2x
and top = (1 - B)x
C is the hard part... I'll just put up a quick paint triangle up for reference
First lets use the Law of Cosines to find the angle at A
(B + C)² = (1 + B)² + (1 + C)² - 2(1 + B)(1 + C)cos A
cosA = (BC - B - C - 1)/(BC + B + C + 1)
Using normal Trigonometry we can also get the height...
sin A = h / (1 + C)
Using the rule
sin² A + cos² A = 1
We can combine and get
h = (1 + C) √ (1 - cos² A)
Of course to get the top we need to add 1 and minus C
top = ((1 + C) √ (1 - cos² A) + 1 - C)x
Using trig again we can get the left side...
cos A = l / (1 + C)
l = (1 + C)cos A
Of course to get left we have to add 1 and take C...
left = ((1 + C)cos A + 1 - C)x
I have created an example using border-radius to create the circles with B = .7 and C = .3 and x = 50px: http://jsfiddle.net/FelixJorkowski/xArpR/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With