At 08:35 27/05/2002, Gerald K. Dobiasovsky wrote:
From: "Morgan L. Owens" Sent: Saturday, May 25, 2002 10:27 AM
To be honest, that larger one is actually known to be broken [...] To confess further, I've found situations where the original four-circle code fails to ensure proper tangency.
I sincerely hope you didn't interprete my quip about your pars trying to beat Mathematica as some form of ironic critique.
Not at all - since I don't actually have Mathematica yet, I have to make do with what I've got :-) Just to show there's no hard feelings; here's another Kleinian circle formula. This derives from a problem by Appollonius: Given three circles in the plane, find a fourth circle tangent to the given three. There are eight solutions in general, depending on whether the given circles are to be inside or outside the tangent circle; this one just picks the solution where all three are outside (I'll use imag(p5) to make this configurable later, and figure out which circles need to have negative radii). Every circle will be tangent to at least one other, and one of the circles will be tangent to the other three - further tangencies are the responsibility of the user. This was a situation where I wish I had Mathematica to do the algebra for me. I banged my head for several hours, got stuck, went to http://mathworld.wolfram.com/, found that I'd pretty much done that, went back, realised what I was missing (two lines), fixed a coupla typos and the rest fell into place. Exercise for the reader: Solve the Appollonian problem yourself, without peeking at the code or reference materials. Parameters: real(p1), imag(p1), real(p2); centre and radius of first circle imag(p2), real(p3), imag(p3); centre and radius of second circle real(p4), imag(p4), real(p5); centre and radius of third circle Like I said, imag(p5) will be getting a use soon. I might also do some extra checking to cope with collinear given circles (i.e., the tangent circle becomes a straight line). I take no responsibility if the first three circles overlap - though the tangent circle is still constructed, I can only invert in one circle at a time, and which one is used in regions of overlap is pretty arbitrary. 4ApolloKlein1{ ax=real(p1),ay=imag(p1),ar=real(p2) bx=imag(p2),by=real(p3),br=imag(p3) cx=real(p4),cy=imag(p4),cr=real(p5) h=sqr(ax)+sqr(ay)-sqr(ar) a=2*(ar-br),b=2*(ax-bx),c=2*(ay-by),d=h-(sqr(bx)+sqr(by)-sqr(br)) e=2*(ar-cr),f=2*(ax-cx),g=2*(ay-cy),h=h-(sqr(cx)+sqr(cy)-sqr(cr)) l=(b*g-c*f) i=(d*g-c*h)/l,j=(a*g-c*e)/l,k=(b*h-d*f)/l,l=(b*e-a*f)/l m=2*(1-sqr(l)-sqr(l)) n=2*(cr+(i-cx)*j+(k-cy)*l) o=2*(cr^2-sqr(i-cx)-sqr(k-cy)) r=sqrt(sqr(n)-m*o) r1=(-n-r)/m r2=(-n+r)/m if(imag(r1)==0 && real(r1)>0) r=r1 else r=r2 endif x=i-j*r y=k-l*r ap=real(ax)+flip(ay) bp=real(bx)+flip(by) cp=real(cx)+flip(cy) p=real(x)+flip(y) arr=sqr(ar) brr=sqr(br) crr=sqr(cr) rr=sqr(r) z=pixel: : inside=0 if(|z-ap|<arr) z=ar*conj(ar/(z-ap))+ap inside=1 elseif(|z-bp|<brr) z=br*conj(br/(z-bp))+bp inside=1 elseif(|z-cp|<crr) z=cr*conj(cr/(z-cp))+cp inside=1 elseif(|z-p|<rr) z=r*conj(r/(z-p))+p inside=1 endif inside}
Still,the implementation of the formula parser was pivotal IMHO (I, at least, wouldn't have used it to such an extent without it). And I'm not sure you would see such *extensive* scripting capabilities in some modern fractal renderers without Fractint existing.
Quite probably so; I hope no-one thought I was disparaging the formula parser - I was just pointing out one way it could be improved (and who would claim that it couldn't be?) The precalc test could also be added to the above formula. Morgan L. Owens "After a buildup like that it'll probably be pretty disappointing."