Subversion Repositories wimsdev

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
18484 bpr 1
!set slib_header_circlepack=\
2
eps=1e-15;\
3
\
4
/* Homographies */\
5
hom(z,m)=(m[1,1]*z+m[1,2])/(m[2,1]*z+m[2,2]);\
6
/* Image du cercle de centre z et rayon r par l'homographie m */\
7
homc(z,r,m)={\
8
  my(zz=norm(z)-norm(r),dc=m[2,2]/m[2,1], cc=(zz+z*conj(dc))/conj(z+dc));\
9
  cc=hom(cc,m); [cc,sqrt(norm(hom(z+r,m)-cc))]\
10
  };\
11
/* Image de la verticale d'abcisse x0 par m */\
12
homv(x0,m)={my(dc=m[2,2]/m[2,1], cc=2*x0+real(dc)-imag(dc)*I);\
13
  cc=hom(cc,m); [cc,sqrt(norm(hom(x0,m)-cc))]};\
14
/* Image de l'horizontale d'ordonnée y0 par m */\
15
homh(y0,m)={my(dc=m[2,2]/m[2,1], cc=-real(dc)+(2*y0+imag(dc))*I);\
16
  cc=hom(cc,m); [cc,sqrt(norm(hom(y0*I,m)-cc))]};\
17
/* Homographie qui envoie [u1, u2, u3] sur [v1, v2, v3] */\
18
homog(u,v)={my(\
19
  m1=[v[2]*(v[3]-v[1]),v[1]*(v[2]-v[3]);v[3]-v[1],v[2]-v[3]],\
20
  m2=[u[2]-u[3],u[1]*(u[3]-u[2]);u[1]-u[3],u[2]*(u[3]-u[1])]);\
21
  m1*m2};\
22
\
23
/* somme des demi-angles */\
24
sangles(r,flr,lbs)=sum(j=1,#flr,atan(lbs[flr[j]]/r));\
25
\
26
/* Point à distance r1 de z1 et r2 de z2, sens direct */\
27
trois(z1,r1,z2,r2)={\
28
  my(n=norm(z2-z1),\
29
    x=(1+(sqr(r1)-sqr(r2))/n)/2,\
30
    y=sqrt(sqr(r1)/n-sqr(x)));\
31
  z1+(z2-z1)*(x+y*I)\
32
};\
33
\
34
/* Le fichier off contient la liste ff des fleurs duales.\
35
   On calcule d'abord la liste ss des fleurs primales.\
36
   On choisit l'arête 1a et son arête duale bc privilégiées.\
37
   On applique l'algo pour obtenir les rayons des autres disques.\
38
   On place les points sur les bords du rectangle.\
39
   On cherche le sommet (ou la face) de plus grand degré\
40
   ainsi que le sommet ou la face opposé. Ils sont envoyés sur\
41
   le cercle unité et un cercle concentrique plus petit.\
42
   On renvoie les quatre listes (centres et rayons pour sommets et faces) */\
43
\
44
polycircle(ff)={\
45
  my(ns=1,nf=#ff,dgs,m,f,ss,i,j,k,l,lbs,lbf,a,b,c,d,u,pts,ptf,cs,cf,\
46
    f1,fb,fc,fl,sa,ssa,w,h,scale,again,s0,f0,flip,aa,bb,cc,djs,djf,p,ma);\
47
\
48
/* Dans la version pari, les sommets sont numérotés de 1 à ns */\
49
  for (i=1, nf, for (j = 1, #ff[i], if((ff[i][j]+=1)>ns,ns=ff[i][j])));\
50
\
51
/* calcul des fleurs primales */\
52
  dgs=vector(ns); /* degrés des sommets*/\
53
  m=matrix(ns,ns);\
54
/* m[aa,bb]==i!=0 ssi (aa,bb) fait partie du bord orienté de la face i */\
55
  for(i=1, nf, f=ff[i]; for(j = 1, #f, dgs[f[j]]+=1; m[f[j],f[1+j%#f]]=i));\
56
\
57
  ma=m;\
58
  ss=vector(ns);\
59
  for(i=1, ns,\
60
    fl=vector(dgs[i]);\
61
    j=1;while(!m[i,j],j++); /* chercher une pétale */\
62
    for (l=1, dgs[i],\
63
      fl[l]=k=m[i,j];\
64
      j=1;while(m[j,i]!=k,j++)); /* chercher la pétale suivante */\
65
    ss[i]=fl;\
66
  );\
67
\
68
/* Calcul des rayons */\
69
  lbs=vector(ns,x,1);\
70
  lbf=vector(nf,x,1);\
71
\
72
  s1=ss[1]; b = s1[1]; c = s1[2];\
73
  fb=ff[b]; fc=ff[c];\
74
  for (j = 1, #fc, if (fc[j] == 1, a = fc[1+j%#fc]; break));\
75
  sa=ss[a];\
76
  lbs[1]=lbs[a]=lbf[b]=lbf[c]=eps^-2;\
77
\
78
  again = 1;\
79
  while (again, again=0;\
80
    for (i=2, ns, if (i != a,\
81
      ssa=sangles(lbs[i],ss[i],lbf);\
82
      if (abs(ssa-Pi)> eps,\
83
        lbs[i]*=tan(ssa/#ss[i])/tan(Pi/#ss[i]); again=1)));\
84
    for (i=1, nf, if (i != b && i != c,\
85
          ssa=sangles(lbf[i],ff[i],lbs);\
86
      if (abs(ssa-Pi)> eps,\
87
        lbf[i]*=tan(ssa/#ff[i])/tan(Pi/#ff[i]); again=1)))\
88
    );\
89
\
90
/* Calcul des positions */\
91
\
92
  pts=vector(ns);\
93
  ptf=vector(nf);\
94
  cs=vector(ns);\
95
  cf=vector(nf);\
96
\
97
 /* Tour du rectangle fondamental, sens horaire! */\
98
\
99
  w = 0; h = 0; k = 0; /* nombre de points calculés */\
100
\
101
  for (i = 3, #s1,\
102
    d = s1[i]; h += lbf[d]; ptf[d] = w+h*I; cf[d] = 1; k++; h += lbf[d]);\
103
  i = 1; while (fb[i] != 1, i = 1+i%#fb);\
104
  while ((d = fb[i = 1+i%#fb]) != a,\
105
    w += lbs[d]; pts[d] = w+h*I; cs[d] = 1; k++; w += lbs[d]);\
106
\
107
  /* Mise à l'échelle et stockage du rectangle */\
108
\
109
  scale = min (4 / w, 6 / h);\
110
  for (i = 1, ns, lbs[i] *= scale; pts[i] *= scale);\
111
  for (i = 1, nf, lbf[i] *= scale; ptf[i] *= scale);\
112
  w *= scale; h *= scale;\
113
\
114
  lbs[1] = lbf[b] = lbs[a] = lbf[c] = 0;\
115
  pts[1] = 0; pts[a] = w; ptf[b] = h; ptf[c] = 0;\
116
  k += 4; /* On connait 1, a, b et c, mais on ne le dit pas dans cs et cf */\
117
\
118
  i = 1; while (sa[i] != b, i = 1+i%#sa);\
119
  while ((d = sa[i = 1+i%#sa]) != c,\
120
    h -= lbf[d]; ptf[d] = w+h*I; cf[d] = 1; k++; h -= lbf[d]);\
121
  i = 1; while (fc[i] != a, i = 1+i%#fc);\
122
  while ((d = fc[i = 1+i%#fc]) != 1,\
123
    w -= lbs[d]; pts[d] = w+h*I; cs[d] = 1; k++; w -= lbs[d]);\
124
\
125
/* Ici, on a fait le tour du rectangle, donc h==w==0 (I hope) */\
126
\
127
  while(k<ns+nf,\
128
    for(aa=2,ns,if(aa!=a && cs[aa], fl = ss[aa]; for (i=1,#fl, if(cf[fl[i]],\
129
      bb = fl[i]; cc = fl[1+i%#fl];\
130
      if(!cf[cc] && cc != b && cc != c,\
131
      ptf[cc] = trois(pts[aa], sqrt(lbs[aa]^2+lbf[cc]^2),\
132
        ptf[bb], lbf[bb]+lbf[cc]);\
133
      cf[cc] = 1; k++)))));\
134
    for(aa=1,nf,if(aa!=b && aa!= c && cf[aa], fl = ff[aa]; for (i=1,#fl, if(cs[fl[i]],\
135
      bb = fl[i]; cc = fl[1+i%#fl];\
136
      if(!cs[cc] && cc != 1 && cc != a,\
137
      pts[cc] = trois(ptf[aa], sqrt(lbf[aa]^2+lbs[cc]^2),\
138
        pts[bb], lbs[bb]+lbs[cc]);\
139
      cs[cc]=1; k++))))));\
140
\
141
/* return([pts,lbs,ptf,lbf] pour le diagramme avec un rectangle */\
142
\
143
/* Détermination du point (s0 ou f0) de degré maximal */\
144
  f0=1; for(i=2,nf,if(#ff[i]>#ff[f0],f0=i));\
145
  s0=1; for(i=2,ns,if(#ss[i]>#ss[s0],s0=i));\
146
  flip = #ss[s0] > #ff[f0];\
147
/* Détermination du point (s1 ou f1) le plus éloigné de s0 ou f0 */\
148
  djs = vector(ns,i,-1); djf = vector(nf,i,-1);\
149
  d = 0; k=1; if (flip,djs[s0]=0,djf[f0]=0);\
150
  while(k<ns+nf, if((d+flip)%2,\
151
    for(s = 1, ns, if(djs[s] == d,\
152
      for(j = 1, #ss[s], if(djf[ss[s][j]] < 0,\
153
        k += 1; f1 = ss[s][j]; djf[f1] = d+1\
154
	)))),\
155
    for(f = 1, nf, if(djf[f] == d,\
156
      for(j = 1, #ff[f], if(djs[ff[f][j]] < 0,\
157
        k += 1; s1 = ff[f][j]; djs[s1] = d+1\
158
	)))));\
159
    d += 1);\
160
\
161
/* et parmi ceux-là, celui qui a le plus grand degré ? */\
162
  if((d+flip)%2,\
163
    for(s = 1, ns, if(djs[s] == d && #ss[s] > #ss[s1], s1=s)),\
164
    for(f = 1, nf, if(djf[f] == d && #ff[f] > #ff[f1], f1=f)));\
165
\
166
  d=(d+flip)%2;\
167
\
168
/* Il faut maintenant trouver l'homographie qui envoie le disque de sf0\
169
   sur le disque unité et celui de sf1 sur un disque centré en 0\
170
   de rayon plus petit */\
171
\
172
if(flip,\
173
  cc=pts[s0]; rr=lbs[s0];\
174
  m=homog(if (s0 == 1 || s0 == a,\
175
            [cc-1.23*I,cc,cc+3.78*I],\
176
            [cc-rr*exp(I), cc+rr, cc+rr*exp(1.52*I)]),[-I,1,I]),\
177
  cc=ptf[f0]; rr=lbf[f0];\
178
  m=homog(if (f0 == b || f0 == c,\
179
            [cc*I-1.23456789,cc*I,cc*I+3.78243577],\
180
	    [cc-rr*exp(I), cc+rr, cc+rr*exp(1.52*I)]),[-I,1,I]));\
181
\
182
  u=if(d%2,if(s1==1||s1==a, homv(pts[s1],m), homc(pts[s1],lbs[s1],m)),\
183
           if(f1==b||f1==c, homh(ptf[f1],m), homc(ptf[f1],lbf[f1],m)));\
184
\
185
  if(sqrt(norm(u[1]))+u[2]>1, m=[0,1;1,0]*m; u=homc(u[1],u[2],[0,1;1,0]));\
186
\
187
  r0=sqrt(norm(u[1])); t1=r0-u[2];\
188
  a1=log((1+t1)/(1-t1));\
189
  t2=r0+u[2]; a2=log((1+t2)/(1-t2)); aa=exp((a1+a2)/2);\
190
  t = (aa-1)/(aa+1); u[1]*=t/r0; /* u[1] est maintenant le centre hyper*/\
191
\
192
  m=[1,-u[1];-conj(u[1]),1]*m;\
193
  for (i=1,ns,u=if(i==1||i==a, homv(pts[i],m),homc(pts[i],lbs[i],m));\
194
    pts[i]=if(norm(u[1])<eps,0,u[1]);lbs[i]=u[2]);\
195
  for (i=1,nf,u=if(i==b||i==c, homh(ptf[i],m),homc(ptf[i],lbf[i],m));\
196
    ptf[i]=if(norm(u[1])<eps,0,u[1]);u[1];lbf[i]=u[2]);\
197
\
198
/* Une rotation pour faire plus joli */\
199
  p=if(flip,ptf[ss[s0][1]],pts[ff[f0][1]]);p/=sqrt(norm(p));\
200
  for (i=1,ns,pts[i]/=p);\
201
  for (i=1,nf,ptf[i]/=p);\
202
\
203
/* [pts,lbs,ptf,lbf] */\
204
 [matrix(#lbs,3,i,j,if(j==1,real(pts[i]),if(j==2,imag(pts[i]),lbs[i]))),\
205
  matrix(#lbf,3,i,j,if(j==1,real(ptf[i]),if(j==2,imag(ptf[i]),lbf[i]))),ma]\
206
};\