kigdocument.noaxes() kigdocument.nogrid() # # date due circonferenze contenute una nell'altra, ma non # concentriche, costruiamo una catena di cerchi contenuti # nella regione tra le due circonferenze e tangenti tra # loro, oltre che alle due circonferenze. Tale catena # ovviamente puo' chiudersi esattamente solo in circostanze # particolari. # il "porisma di Steiner" asserisce che la proprieta' di # "chiusura" di questa catena dipende solo dalle due # circonferenze iniziali, e non dalla posizione del # primo cerchio della catena # # questa costruzione intende visualizzare concretamente # tale proprieta' # from random import Random g = Random() ncircles = g.randint(7,30) # # decidiamo all'inizio di quanti cerchi e' composta la # catena (numero casuale tra 7 e 30) # # A e B sono due punti opposti della circonferenza esterna; # Q e' un punto libero sul diametro AB che controlla di # quanto la circonferenza interna sara' eccentrica rispetto # alla circonferenza esterna. # A = Point(-1,0,name="A") B = Point(1,0,name="B") C = MidPoints(A,B) c1 = Circle(C,B) r = Line(C,B,HIDDEN) diam = Segment(A,B) Ceps = ConstrainedPoint(0.01,diam,HIDDEN) Beps = ConstrainedPoint(0.99,diam,HIDDEN) diameps = Segment(Ceps,Beps,HIDDEN) # # per motivi legati alla costruzione conviene # evitare che Q venga a coincidere con A o B # Q = ConstrainedPoint(0.2,diameps,name="Q") # # P e' un punto vincolato sulla circonferenza # esterna che controlla la posizione del # primo cerchio della catena # P = ConstrainedPoint(0.1,c1,name="P") # # per fare la costruzione e' necessario ricondursi # al caso di due circonferenze concentriche; questo # si ottiene utilizzando l'inversione circolare. # Il cerchio di inversione "invc" ha centro in Q, e passa # per B. # Viene invertita la circonferenza esterna (c1inv), che # passa per "B" e ha centro "c1invC". Tutta # la costruzione viene fatta a partire da c1inv. # Nascondiamo tutti gli oggetti necessari alla costruzione # kigdocument.hideobjects() invc = Circle(Q,B,HIDDEN) Pinv = InvertPoint(P,invc) c1inv = CircularInversion(c1,invc) c1invC = c1inv.center() # # per costruire la catena iscriviamo un poligono # regolare di "ncircles" lati e con un vertice in B # di cui utilizzeremo un suo lato ed un vertice # adiacente a B # pol = PolygonBCV(c1invC,B,ncircles) side = PolygonSide(pol,0) Vertex = PolygonVertex(pol,1) # # due vertici adiacenti del poligono vengono # usati per definire l'angolo per la rotazione # ripetuta dei cerchi della catena # mentre un secondo angolo utilizza Pinv (il # risultato dell'inversione di P) che sta sul # cerchio c1inv # angle = Angle(Vertex,c1invC,B) controlangle = Angle(B,c1invC,Pinv) # # il primo cerchio (smc) della catena ha centro # sul raggio B, "c1invC" e deve essere tangente a "c1inv" # in B e all'asse del lato del poligono; quindi il suo # centro e' equidistante dall'asse e da B e percio' sta # sulla parabola avente B come fuoco e l'asse come # direttrice # sideM = side.midpoint(internal=True) axis = Orthogonal(side,sideM) parab = ParabolaByDirectrixFocus(axis,B) # # il centro (smcC) e' quindi una delle due intersezioni # della parabola con la retta per A e B # smcC = ConicLineIntersection(parab,r,1) smc = Circle(smcC,B) # # ora costruisco tutti i cerchietti e li inverto # il primo cerchietto viene costruito con una # rotazione generica (definita dal punto P di # controllo) # gcinv = Rotate(smc,c1invC,controlangle) CircularInversion(gcinv,invc,VISIBLE) for n in range(ncircles - 1): newgcinv = Rotate(gcinv,c1invC,angle) CircularInversion(newgcinv,invc,VISIBLE) gcinv = newgcinv # # mi manca solo il cerchio interno; un suo punto # di passaggio lo costruisco facendo la simmetria # centrale di B rispetto al centro di "smc" # il risultato deve essere a sua volta invertito # Cinv = CentralSymmetry(B,smcC) c2inv = Circle(c1invC,Cinv) c2 = CircularInversion(c2inv,invc,VISIBLE)