I have n circles that must be perfectly surrounding an ellipse as shown in the picture here :
In this picture I need to find out the position of each circle around the ellipse, and also be able to calculate the ellipse that will fit perfectly inside those surrounding circles.
The information i know is the radius of each circles (all same), and the number of circles.
Hopefully this time the post is clear. Thanks for your help. Please let me know if you need more explanation.
OK as i understand you know common radius of circles R0 and their number N and want to know inside ellipse parameters and positions of everything.
If we convert ellipse to circle then we get this:
const int N=12; // number of satelite circles
const double R=10.0; // radius of satelite circles
struct _circle { double x,y,r; } circle[N]; // satelite circles
int i;
double x,y,r,l,a,da;
x=0.0; // start pos of first satelite circle
y=0.0;
r=R;
l=r+r; // distance ang angle between satelite circle centers
a=0.0*deg;
da=divide(360.0*deg,N);
for (i=0;i<N;i++)
{
circle[i].x=x; x+=l*cos(a);
circle[i].y=y; y+=l*sin(a);
circle[i].r=r; a+=da;
}
// inside circle params
_circle c;
r=divide(0.5*l,sin(0.5*da))-R;
c.x=circle[i].x;
c.y=circle[i].y+R+r;
c.r=r;
[Edit 1]
For ellipse its a whole new challenge (took me two hours to find all quirks out)
const int N=20; // number of satelite circles
const double R=10.0; // satelite circles radius
const double E= 0.7; // ellipse distortion ry=rx*E
struct _circle { double x,y,r; _circle() { x=0; y=0; r=0.0; } } circle[N];
struct _ellipse { double x,y,rx,ry; _ellipse() { x=0; y=0; rx=0.0; ry=0.0; } } ellipse;
int i,j,k;
double l,a,da,m,dm,x,y,q,r0;
l=double(N)*R; // circle cener lines polygon length
ellipse.x =0.0; // set ellipse parameters
ellipse.y =0.0;
r0=divide(l,M_PI*sqrt(0.5*(1.0+(E*E))))-R;// aprox radius to match ellipse length for start
l=R+R; l*=l;
m=1.0; dm=1.0; x=0.0;
for (k=0;k<5;k++) // aproximate ellipse size to the right size
{
dm=fabs(0.1*dm); // each k-iteration layer is 10x times more accurate
if (x>l) dm=-dm;
for (;;)
{
ellipse.rx=r0 *m;
ellipse.ry=r0*E*m;
for (a=0.0,i=0;i<N;i++) // set circle parameters
{
q=(2.0*a)-atanxy(cos(a),sin(a)*E);
circle[i].x=ellipse.x+(ellipse.rx*cos(a))+(R*cos(q));
circle[i].y=ellipse.y+(ellipse.ry*sin(a))+(R*sin(q));
circle[i].r=R;
da=divide(360*deg,N); a+=da;
for (j=0;j<5;j++) // aproximate next position to match 2R distance from current position
{
da=fabs(0.1*da); // each j-iteration layer is 10x times more accurate
q=(2.0*a)-atanxy(cos(a),sin(a)*E);
x=ellipse.x+(ellipse.rx*cos(a))+(R*cos(q))-circle[i].x; x*=x;
y=ellipse.y+(ellipse.ry*sin(a))+(R*sin(q))-circle[i].y; y*=y; x+=y;
if (x>l) for (;;) // if too far dec angle
{
a-=da;
q=(2.0*a)-atanxy(cos(a),sin(a)*E);
x=ellipse.x+(ellipse.rx*cos(a))+(R*cos(q))-circle[i].x; x*=x;
y=ellipse.y+(ellipse.ry*sin(a))+(R*sin(q))-circle[i].y; y*=y; x+=y;
if (x<=l) break;
}
else if (x<l) for (;;) // if too short inc angle
{
a+=da;
q=(2.0*a)-atanxy(cos(a),sin(a)*E);
x=ellipse.x+(ellipse.rx*cos(a))+(R*cos(q))-circle[i].x; x*=x;
y=ellipse.y+(ellipse.ry*sin(a))+(R*sin(q))-circle[i].y; y*=y; x+=y;
if (x>=l) break;
}
else break;
}
}
// check if last circle is joined as it should be
x=circle[N-1].x-circle[0].x; x*=x;
y=circle[N-1].y-circle[0].y; y*=y; x+=y;
if (dm>0.0) { if (x>=l) break; }
else { if (x<=l) break; }
m+=dm;
}
}
Well I know its a little messy code so here is some info:
first it try to set as close ellipse rx,ry axises as possible
ellipse length should be about N*R*2
which is polygon length of lines between circle centers
try to compose circles so they are touching each other and the ellipse
I use iteration of ellipse angle for that. Problem is that circles do not touch the ellipse in their position angle thats why there is q
variable ... to compensate around ellipse normal. Look for yellowish-golden lines in image
after placing circles check if the last one is touching the first
if not interpolate the size of ellipse actually it scales the rx,ry
by m
variable up or down
you can adjust accuracy
by change of the j,k
for
s and/or change of dm,da
scaling factors
input parameter E
should be at least 0.5
and max 1.0
if not then there is high probability of misplacing circles because on very eccentric ellipses is not possible to fit circles (if N
is too low). Ideal setting is 0.7<=E<=1.0
closser to 1 the safer the algorithm is
atanxy(dx,dy)
is the same as `atan(dy/dx)
but it handles all 4 quadrants like atan2(dy,dx)
by sign analysis of dx,dy
Hope it helps
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