Subversion Repositories wimsdev

Rev

Rev 17213 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
16993 bpr 1
!set slib_header_patron=default(realprecision,3);\
16886 bpr 2
normalise={v->1/sqrt(norml2(v))*v;};\
3
  /* calcule une image 2D isometrique des faces du polyedre*/\
16993 bpr 4
wedge={(a,b)->[a[2]*b[3]-a[3]*b[2],a[3]*b[1]-a[1]*b[3],a[1]*b[2]-a[2]*b[1]]};\
17156 bpr 5
depl_standard(f, xyz)={\
16993 bpr 6
  my(res2D = vector(#f),no = vector(#f),t2,w);\
16886 bpr 7
  for (k = 1, #f,\
8
    w=vector(f[k][1],i,xyz[f[k][i+1]+1,]);\
9
    my(t1=normalise(w[2]-w[1])~,n=normalise(wedge(t1,w[3]-w[1])),t2=wedge(n,t1)~);\
16993 bpr 10
    no[k]=n;\
16991 bpr 11
    res2D[k]=vector(#w,i,[w[i]*t1,w[i]*t2]));\
16993 bpr 12
  [res2D,no];\
16886 bpr 13
};\
14
deplacement_poly (a,b,f,i1,i2)={\
17039 bpr 15
  /* rotation et translation de f qui envoie l'arête joignant les sommets\
16
    numero i1 et numero i2 sur (a,b).\
16886 bpr 17
    On suppose (a,b) et (f[i1], f[i2]) de même longueur.*/\
18
  my(v1=f[i2]-f[i1],v2=b-a,v=normalise([v1*v2~,v1[1]*v2[2]-v1[2]*v2[1]]));\
19
  my(m1=[v[1],v[2];-v[2],v[1]]);\
20
  my(dec=a-f[i1]*m1);\
21
  vector(#f, i, if(i==i1,a,if(i==i2,b,f[i]*m1 + dec)));\
22
};\
23
a_gauche={(a,b,c)->(b[1]-a[1])*(c[2]-a[2])>(b[2]-a[2])*(c[1]-a[1]);}\
24
  /* 1 si le point c est à gauche (au sens strict) de la droite orientee ab*/\
25
tout_a_droite(a,b,poly)={\
17213 bpr 26
  /* 1 si tous les sommets de poly sont à droite (au sens large)\
27
  de la droite orientee ab */\
16886 bpr 28
   for (k=1,#poly,if(a_gauche(a,b,poly[k]),return(0)));\
29
   1;\
30
};\
31
interieur(pt,poly)={\
32
  /* 1 si le point pt est dans le polygone convexe ouvert dont le bord oriente\
33
   est donne par le vecteur de points poly*/\
34
  for (k=2,#poly,if(a_droite(poly[k-1],poly[k],pt),return(0)));\
17213 bpr 35
  a_droite(poly[#poly],poly[1],pt)==0\
16886 bpr 36
};\
37
intersecte(pol1, pol2)={\
38
  /* 1 si les deux polygones convexes ouverts ont une intersection non vide*/\
39
  for (k=2,#pol1,if(tout_a_droite(pol1[k-1],pol1[k],pol2),return(0)));\
40
  if (tout_a_droite(pol1[#pol1],pol1[1],pol2),return(0));\
41
  for (k=2,#pol2,if(tout_a_droite(pol2[k-1],pol2[k],pol1),return(0)));\
42
  tout_a_droite(pol2[#pol2],pol2[1],pol1)==0;\
43
};\
44
/* m est la matrice d'adjacence d'un graphe de sommets 1..#m,\
45
un arbre couvrant est une fonction de 1..#m dans lui-même qui 'aboutit' toujours à #m*/\
46
\
47
arbres_couvrants(m,but)={\
17213 bpr 48
/* si but == 0, renvoie le nombre total d'arbres couvrants\
49
 sinon, renvoie le but-ieme arbre couvrant */\
16886 bpr 50
  my(k=1,l=1,n,v=vector(#m,x,x),nb=0);\
51
  while(k,\
52
    if(m[k,l],\
53
      n=l;while(v[n]!=n,n=v[n]);if(n!=k,v[k]=l;if(k==#m-1,\
54
      nb+=1; if(nb==but, return(v)),k+=1;l=0)));\
55
    while(k>1&&l==#m,v[k]=k;k-=1;l=v[k]);if(l==#m,k-=1,v[k]=k;l+=1));\
56
    nb;\
57
};\
58
arbre_couvrant_aleatoire0(m)={arbres_couvrants(m,1+random(arbres_couvrants(m,0)));};\
59
arbre_couvrant_aleatoire1(m)={\
60
  my (n=#m, m1 = matrix(n,n),v=vector(n), reste=n, start=n, next1);\
61
  for (l = 1, n,\
62
    k = 0;\
17213 bpr 63
    for (c = 1, n, if (m[l, c], k += 1; m1[l, k] = c)); /* calcul de nombre de voisins)*/\
16886 bpr 64
    m1[l, n] = k;\
65
    );\
66
  v[n] = n;\
67
  while (reste > 1,\
68
    next1 = m1[start,1+random(m1[start,n])];\
69
    if (v[next1]==0, v[next1]=start; reste -=1);\
70
    start = next1;\
71
  );\
72
  v;\
73
};\
74
arbre_couvrant_aleatoire2(m)={\
75
/* Le même algo, implementation plus simple un peu moins efficace ?*/\
76
  my (n=#m, v=vector(n), reste=n, start=n, next1=n);\
77
  v[n] = n;\
78
  while (reste > 1,\
79
    until (m[start,next1], next1 = 1+random(n));\
80
    if (v[next1]==0, v[next1]=start; reste-=1);\
81
    start = next1;\
82
  );\
83
  v;\
84
};\
85
arbre_couvrant_aleatoire(m)={arbre_couvrant_aleatoire2(m);}\
86
{pred=(v,k)->v[if(k>2,k-1,#v)];}\
87
{succ=(v,k)->v[if(k<#v,k+1,2)];}\
88
\
17167 bpr 89
/* retourne l'indice dans f1 et f2\
90
  des sommets communs à f1 et f2 s'ils existent et 0 sinon*/\
17189 bpr 91
adj(f1,f2)={my(ns1=f1[1]+1,ns2=f2[1]+1);\
92
  for(i=2,ns1,for(j=2,ns2,\
17167 bpr 93
    if(f1[i]==f2[j],\
17189 bpr 94
      if(pred(f1,i)==succ(f2,j),return([if(i>2,i-1,ns1),if(j<ns2,j+1,2),i,j]));\
95
      if(succ(f1,i)==pred(f2,j),return([i,j,if(i<ns1,i+1,2),if(j>2,j-1,ns2)]));\
16886 bpr 96
      return(0))));\
97
  0;\
98
};\
17167 bpr 99
/* retourne les numéros des deux sommets communs à f1 et f2 s'ils existent et 0 sinon*/\
17189 bpr 100
adj1(f1,f2)={my(ns1=f1[1]+1,ns2=f2[1]+1);\
101
  for(i=2,ns1,for(j=2,ns2,\
17167 bpr 102
    if(f1[i]==f2[j],\
103
      if(pred(f1,i)==succ(f2,j),return([pred(f1,i),f1[i]]));\
104
      if(succ(f1,i)==pred(f2,j),return([f1[i],succ(f1,i)]));\
105
      return(0))));\
106
  0\
107
};\
108
adjacence={f->matrix(#f,#f,i,j,adj1(f[i],f[j]));};\
16886 bpr 109
etale(v,f,f2,ns)={\
110
  /* v est un arbre couvrant du graphe des faces,\
17213 bpr 111
  // f contient la liste des numeros des sommets des faces en 3D\
112
  // f2 contient les coordonnees 2D d'une projection\
113
  // ns est le nombre de sommets du polyedre\
114
  // le resultat est le polygone generalise (2D)\
115
  // si le deploiement associe est injectif\
16886 bpr 116
  // 0 sinon. */\
117
  my(p,r,nbs,l,n1=f[#f][1],\
118
    pat=vector(#f),s2D=matrix(2*ns-2,3),f2D=vector(#f));\
16944 bpr 119
  f2D[#f]=vector(n1+1,x,if(x==1,n1,x-2));\
16886 bpr 120
  pat[#f]=r=f2[#f];\
121
  for(k=1,#f2[#f],s2D[k,1]=r[k][1];s2D[k,2]=r[k][2];s2D[k,3]=f[#f][k+1]);\
122
  nbs = n1;\
123
  for(kk=1,#f-1,\
124
    while(f2D[kk]==0,\
125
      l=kk; while(f2D[v[l]]==0,l=v[l]);\
126
      [i1,j1,i2,j2]=adj(f[l],f[v[l]]);\
127
      n1=f[l][1];\
16944 bpr 128
      r=deplacement_poly(s2D[f2D[v[l]][j1]+1,1..2],s2D[f2D[v[l]][j2]+1,1..2],f2[l],i1-1,i2-1);\
17222 bpr 129
      for (t=1,#f,if(pat[t] && intersecte(pat[t],r),print("pseudonet")));\
16886 bpr 130
      pat[l]=r;\
131
      rr=vector(n1+1);\
132
      rr[1]=n1;\
133
      rr[i1]=f2D[v[l]][j1];\
134
      rr[i2]=f2D[v[l]][j2];\
135
      for(k=2,n1+1,if(k!=i1 && k!=i2,\
16944 bpr 136
        rr[k]=nbs; nbs+=1; s2D[nbs,1]=r[k-1][1];s2D[nbs,2]=r[k-1][2];s2D[nbs,3]=f[l][k]));\
16886 bpr 137
      f2D[l]=rr));\
138
  return([s2D,f2D,pat]);\
17167 bpr 139
};\
17213 bpr 140
/* v est un arbre couvrant du graphe de matrice d'adjacence m\
141
  ns est le nombre de sommets\
142
  renvoie l'arbre couvrant dual */\
17167 bpr 143
dual(v,m,ns)={\
144
 my(m1=matrix(ns,ns),s1,s2);\
145
 for(i=1,#m,for(j=1,#m,\
146
   if(m[i,j],m1[m[i,j][1]+1,m[i,j][2]+1]=1)));\
147
   for(l=1,#m-1,[s1,s2]=m[l,v[l]];m1[s1+1,s2+1]=m1[s2+1,s1+1]=0);\
148
  /* m1 est maintenant la matrice d'adjacence de l'arbre cherché*/\
149
  arbre_couvrant_aleatoire1(m1);\
150
};\
17213 bpr 151
/* renvoie l'indice de s dans la face f, s'il existe, 0 sinon*/\
152
cherche(f,s)={for(j=2,f[1]+1,if(f[j]==s,return(j)));0};\
153
/* dit si f contient le couple (s,t)*/\
154
cherche2(f,s,t)={for(j=2,f[1]+1,if(f[j]==s,return(succ(f,j)==t)));0};\
17167 bpr 155
ffdual(ff,ns)={\
156
  my(res=vector(ns),s,t,u);\
157
  for(i=1,ns,s=i-1;\
158
    for(j=1,#ff,if(f=cherche(ff[j],s),\
159
      t=pred(ff[j],f);\
160
      u=succ(ff[j],f);\
161
      l=List([j-1]);\
162
      while(t!=u,for(k=1,#ff,if(cherche2(ff[k],s,t),\
163
        listput(l,k-1);t=pred(ff[k],cherche(ff[k],s));break)));\
164
      break));\
165
      res[i]=concat([#l],Vec(l)));\
166
 matconcat(res~)\
16886 bpr 167
};