Page 1 sur 1

Section cube par plan automatisé

Posté : sam. 8 avr. 2017, 21:50
par Nico56
Bonsoir à toutes et à tous, j'aimerai automatiser les sections de cube par des plans avec traits de constructions (en pointillés) comme dans l'exemple donné en suivant.
A l'aide de geoespace j'arrive à déterminer les sections en construisant les points de la section appartenant à chaque arête de la même manière qu'un tracé à la main mais je me demande si il n'y a plus efficace.
Merci d'avance!
Nico

Je vous joins mon code:

Figure asymptote 0341256c629531b55fcd42bbcbfa37ca
*** Pour masquer/découvrir le code Asymptote qui a permis de créer la figure, il faut cliquer dessus. ;-) ***

CODE ASYMPTOTE de la figure ci-dessus : Tout sélectionner
  1. import geoespace_pi;
  2. settings.render=0;
  3. settings.prc=false;
  4.  
  5. size(9cm);
  6. currentprojection=obliqueX;
  7.  
  8. triple v=(0,0,4),
  9. w=(0,4,0),
  10. pA=(3,0,0),
  11. pB=pA+w,
  12. pD=(0,0,0),
  13. pC=pD+w,
  14. pE=pA+v,
  15. pF=pB+v,
  16. pG=pC+v,
  17. pH=pD+v,
  18. pK=(3pG+pH)/4,
  19. pI=(3pE+pH)/4,
  20. pJ=(pC+pF)/2
  21. ;
  22.  
  23. triple pL=intersectionDD(pI,pK,pF,pG);
  24. triple pM=intersectionDD(pL,pJ,pF,pB);
  25. triple pN=intersectionDD(pI,pK,pE,pF);
  26. triple pO=intersectionDD(pJ,pM,pG,pC);
  27. triple pQ=intersectionDD(pN,pM,pE,pA);
  28.  
  29. draw(pA--pB--pC--pG--pH--pE--pA^^pE--pF--pB^^pF--pG^^pI--pK^^pO--pM--pQ);
  30. draw(pA--pD--pC^^pD--pH^^pK--pO^^pI--pQ,dashed);
  31. draw(pK--pL--pO^^pG--pL^^pI--pN--pQ^^pE--pN,dotted);
  32.  
  33. draw(surface(pI--pK--pO--pM--pQ--cycle),pink+opacity(.2));
  34. dot(pL);
  35. dot(pM);
  36. dot(pN);
  37. dot(pO);
  38. dot(pQ);
  39.  
  40. // label("$A$",pA,SW);
  41. // label("$B$",pB,SE);
  42. // label("$C$",pC,E);
  43. // label("$D$",pD,W);
  44. // label("$E$",pE,NW);
  45. // label("$F$",pF,N);
  46. // label("$G$",pG,N);
  47. // label("$H$",pH,NW);
  48. // label("$J\in (BCG)$",(pA+pB)/2,3*S);
  49.  
  50. // dot("$K$",pK,N+W);
  51. // dot("$J$",pJ,NW);
  52. // dot("$I$",pI,NW);
  53.  
  54. shipout(bbox(.5cm,.5cm,invisible));

Re: Section cube par plan automatisé

Posté : sam. 8 avr. 2017, 23:43
par GM
Bonsoir,

geoespace étant une macro non officielle de D. Comin dont la dernière version semble être celle du 31/01/09... je l'ai récupérée sur le site syracuse et chez moi la compilation ne se passe pas bien :

Code : Tout sélectionner

geoespace.asy: 369.13: no matching function 'transverse(skeleton, real)'
Je précise que j'ai la dernière version d'Asymptote (2.41).

Re: Section cube par plan automatisé

Posté : dim. 9 avr. 2017, 19:28
par Nico56
J'avais récupéré une version modifiée de P.Ivaldi, je fournis le code.

Code : Tout sélectionner

//macros de geometrie dans l'espace par D. Comin, version du 31/01/09.
// Modifié par Philippe Ivaldi http://www.piprime.fr/ le 31/01/2010

import math;
import three;
import markers;
import geometry;
import solids;
import labelpath;
import bsp;
settings.render=0;
settings.prc=false;
real croix=0.03;
currentlight=nolight;
bool pointilles=true;

struct path3Pen {
  path3 path3;
  pen pen;
  void operator init(path3 path3, pen pen) { // constructor
    this.path3=path3;
    this.pen=pen;
  }
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// Cette procédure a été écrite par Philippe Ivaldi, elle permet la gestion des faces et arêtes cachées.                                                                                                           //
// Je ne suis que le "ravaleur besogneux du talent des autres" ...                                                                                                                                                                           //
//
face[] hidden;                                                                                  //
path3Pen[] visible;
typedef path3[] shape;                                                                                   //

void addshapes(face[] F, shape[] shp, pen drawpen=currentpen, pen fillpen=white)
{
  for(int i=0; i < shp.length; ++i)
    for(int j=0; j < shp[i].length; ++j) {
      path3 g=shp[i][j];
      face aFace=F.push(g);
      path pr=project(g);
      if(cyclic(pr)) {
        filldraw(aFace,pr,fillpen, drawpen);
      } else {
        draw(aFace,pr, drawpen);
      }
    }
}

// Return an exploded version of aPath3
// path3[0] is the piece wise straight part and path3[1] others parts.
path3[][] explode(path3 aPath3) {
  path3[][] op=new path3[2][];
  int l=length(aPath3);
  for (int j=0; j < l; ++j) {
    bool isPiecewiseStraight=true;
    int k=j;
    while(piecewisestraight(subpath(aPath3,j,k+1)) && k < l) {
      ++k;
    }
    if(k == j) {
      isPiecewiseStraight=false;
      while(!straight(aPath3,k) && k < l) {
        ++k;
      }
    }
    op[isPiecewiseStraight ? 0 : 1].push(subpath(aPath3,j,k));
  }
  return op;
}

// trace les faces de la scene entière et les arrêtes cachées
void trace(){
  add(hidden);
  if (pointilles==true){
    path3 section;
    bool isPiecewiseStraight=true;
    int j;
    for (int i=0; i < visible.length; ++i) {
      path3[][] exploded=explode(visible[i].path3);
      for (int j=0; j < exploded[0].length; ++j) {
        int l=length(exploded[0][j]);
        for (int k=0; k < l; ++k) {
          draw(project(subpath(exploded[0][j],k,k+1)),visible[i].pen+(linewidth(visible[i].pen)/1.5)+defaultbackpen);
        }
      }
      draw(project(exploded[1]),visible[i].pen+defaultbackpen);
    }
  }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////

//définit les directions
pair nord,sud,est,ouest,nouest,nest,souest,sest;
nord=(0,1);
sud=(0,-1);
est=(1,0);
ouest=(-1,0);
nouest=(-1,1);
nest=(1,1);
souest=(-1,-1);
sest=(1,-1);
//trace le point (la croix) placé en A
void pointe(triple A, pen sty=currentpen){
  triple v=invert((croix,croix),currentprojection.camera,currentprojection.target);
  triple u=invert((-croix,croix),currentprojection.camera,currentprojection.target);
  draw(project(A-v)--project(A+v),p=sty);
  draw(project(A-u)--project(A+u),p=sty);
}

//nomme et trace le point (la croix) placé en A
void nomme(picture pic=currentpicture, Label L, triple position,pair direction=sud, pen p=currentpen, filltype filltype=NoFill){
  pointe(position,p);
  label(L, project(position)+croix*direction,direction,p);
}

// insert le solide sous forme shape dans la scene pour être tracé à la fin
void insertscene(shape shp,pen remplissage=white,pen aretes=black){
  shape[] group={shp};
  addshapes(hidden, group, drawpen=aretes,fillpen=remplissage);
  if (pointilles==true){
    for (int i=0; i < shp.length; ++i) {
      visible.push(path3Pen(shp[i],aretes+defaultbackpen));
    }
  }
}
//
//aretes+dotted

//elimine les sommets redondants
triple[] elimine(triple[] som){
  for(int i=0;i<som.length-1;i=i+1){
    for(int j=i+1;j<som.length;j=j+1){
      if(som[i]==som[j]){som.delete(j);j=j-1;};
    }
  }
  return som;
}
//renvoie les sommets d'un polyedre
triple[] sommet(shape faces){
  triple[] som;
  for(int i=0;i<faces.length;i=i+1){
    for(int j=0;j<length(faces[i]);j=j+1){
      som.push(point(faces[i],j));
    };
  }
  som=elimine(som);
  return som;
}

// nomme les sommets d'un polyedre ou une liste de sommets
void nomme(shape solide, pair direction=sud ...string[] txt){
  triple[] M=elimine(sommet(solide));
  for(int i=0;i<txt.length;i=i+1){
    label(txt[i],project(M[i]),direction);
  }
}
void nomme(triple[] M, pair direction=sud ...string[] txt){
  for(int i=0;i<txt.length;i=i+1){
    label(txt[i],project(M[i]),direction);
  }
}

//trace un pavé de sommet à partir du point A et de dimensions L*l*h
//renvoie les sommets du pavé.
triple[] pave(triple A,real L, real p,real h,pen remplissage=white,pen aretes=black){
  triple[] som;
  som[0]=A;
  som[1]=A+(0,0,h);
  som[2]=A+(0,L,h);
  som[3]=A+(0,L,0);
  som[4]=som[3]+(p,0,0);
  som[5]=som[2]+(p,0,0);
  som[6]=som[1]+(p,0,0);
  som[7]=som[0]+(p,0,0);
  shape f;
  f[0]=som[0]--som[3]--som[4]--som[7]--cycle;
  f[1]=som[0]--som[1]--som[2]--som[3]--cycle;
  f[4]=som[0]--som[7]--som[6]--som[1]--cycle;
  f[2]=shift(0,L,0)*f[4];
  f[3]=shift(p,0,0)*f[1];
  f[5]=shift(0,0,h)*f[0];
  insertscene(f,remplissage,aretes);
  return som;}

//trace une pyramide de sommet S et de base le path3 B
//renvoie les sommets
triple[] pyramide(triple S, path3 B, pen remplissage=white,pen aretes=black){
  triple[] som;
  som.cyclic=true;
  for(int i=0;i<length(B);++i){
    som.push(point(B,i));
  }
  shape f;
  f[0]=B;
  for(int i=0;i<length(B);++i){
    f.push(S--som[i]--som[i+1]--cycle);
  }
  insertscene(f,remplissage,aretes);
  som.insert(0,S);
  return som;}

//trace un prisme de base ABCDE et de hauteur h
//renvoie les sommets du prisme.
triple[] prisme(real h, path3 B, pen remplissage=white,pen aretes=black){
  triple[] som;
  for(int i=0;i<length(B);i=i+1){
    som[i]=point(B,i);}
  for(int i=0;i<length(B);i=i+1){
    som[i+length(B)]=shift(unit(normal(B))*h)*point(B,i);}

  shape f;
  f[0]=B;
  f[length(B)+1]=shift(unit(normal(B))*h)*B;
  for(int i=0;i<length(B)-1;i=i+1){
    f[i+1]=som[i]--som[1+i]--som[1+i+length(B)]--som[i+length(B)]--cycle;
  }
  f[length(B)]=som[length(B)-1]--som[0]--som[length(B)]--som[2*length(B)-1]--cycle;
  insertscene(f,remplissage,aretes);
  return som;}




//place le texte txt le long de AB
void etiquette(triple C, triple D, string txt,bool dessus=true,pen sty=currentpen){
  pair A=project(C);
  pair B=project(D);
  if (dessus==true){
    label(rotate(degrees(B-A))*txt,0.5*B+0.5*A,dir(degrees(B-A)+90),sty);
  } else {
    label(rotate(degrees(B-A))*txt,0.5*B+0.5*A,dir(degrees(B-A)-90),sty);
  }
}

//trace une flèche de cotation de A à B à d mm audessus du segment avec le texte.
void cote(triple A1,triple B1, string texte, real d,bool trait=false,pen sty=black){
  pair M,N;
  pair A=project(A1);
  pair B=project(B1);
  M=A+d/10*dir(degrees(B-A)+90);
  N=B+d/10*dir(degrees(B-A)+90);
  label(rotate(degrees(N-M))*texte,0.5*N+0.5*M,dir(degrees(N-M)+90),sty);
  draw(B+d/10*dir(degrees(B-A)+90)--A+d/10*dir(degrees(B-A)+90),Arrows,p=sty);
  if(trait==true){
    draw(A--A+d/10*dir(degrees(B-A)+90),sty+0.1);
    draw(B--B+d/10*dir(degrees(B-A)+90),sty+0.1);
  }
}

//retourne un point sur un chemin avec le paramètre r entre 0 et 1
triple pointsur(path3 chemin, real r)
{
  return point(chemin,arctime(chemin,r*arclength(chemin)));
}

//retourne le milieu de [A,B].
triple milieu(triple A, triple B){
  return 0.5(A+B);
}
//code le milieu du segment [A,B]
void codemilieu(triple A1, triple B1, int trait){
  pair M=project(milieu(A1,B1));
  pair A=project(A1);
  pair B=project(B1);
  if(trait < 4)  {
    draw(A--M,invisible,StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm));
    draw(M--B,invisible,StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm));
  }
  else {if(trait ==4) {
      draw(A--M,invisible,TildeIntervalMarker(i=1,size=3mm));
      draw(M--B,invisible,TildeIntervalMarker(i=1,size=3mm));
    }else {
      draw(A--M,invisible,CircleBarIntervalMarker(1,n=0));
      draw(M--B,invisible,CircleBarIntervalMarker(1,n=0));
    }
  }
}

//code les segments définis par le tableau triple[] K={A,B,C,...} avec trait traits
void code(pen sty=invisible,int trait ... triple[] Som){
  pair[] K;
  for(int i=0;i<Som.length;i=i+1){
    K[i]=project(Som[i]);
  }
  if(trait < 4) {
    for(int i=0; i <=(K.length-2); i=i+2) { draw(K[i]--K[i+1],sty,StickIntervalMarker(1,n=trait,angle=-30,size=3mm,space=1mm));}
  }else {if(trait ==4) {
      for(int i=0; i <=(K.length-2); i=i+2) { draw(K[i]--K[i+1],sty,TildeIntervalMarker(i=1,size=3mm));}
    }else {for(int i=0; i <=(K.length-2); ++i) {draw(K[i]--K[i+1],sty,CircleBarIntervalMarker(1,n=0));}
    }
  }
}

//code les angles avec des traits
void codeangle(triple D,triple A, triple E,string txt="", int trait,pen remplissage=invisible,pen sty=currentpen,real r=0.5 ){
  real ang=aCos(dot(D-A,E-A)/(abs(D-A)*abs(E-A)));
  path3 a=arc(A,r*unit(D-A)+A,r*unit(E-A)+A,cross(D-A,E-A));
  filldraw(project(A--a--cycle),remplissage,sty);
  triple m = rotate(ang/2,A,A+cross(D-A,E-A))*(A+unit(D-A)*r);
  triple p = rotate(ang/2+4,A,A+cross(D-A,E-A))*(A+unit(D-A)*r);
  triple n = rotate(ang/2-4,A,A+cross(D-A,E-A))*(A+unit(D-A)*r);
  if(trait==1){
    draw(project(m-unit(m-A)*croix--m+unit(m-A)*croix));
  } else{
    if(trait==2){
      draw(project(m-unit(m-A)*croix--m+unit(m-A)*croix));
      draw(project(n-unit(n-A)*croix--n+unit(n-A)*croix));
    } else{
      if(trait==3){
        draw(project(m-unit(m-A)*croix--m+unit(m-A)*croix));
        draw(project(n-unit(n-A)*croix--n+unit(n-A)*croix));
        draw(project(p-unit(p-A)*croix--p+unit(p-A)*croix));
      } else {
        draw(project(circle(m,croix,cross(D-A,E-A))));
      }
    }
  }
  label(txt,project(rotate(ang/2-2,A,A+cross(D-A,E-A))*(A+unit(D-A)*(r+3croix))),E+D-2A);
}

//code les angles droits
void angledroit(triple A,triple B, triple C,real taille=0.2, pen p=black){
  triple u,v;
  u=unit(C-B);
  v=unit(A-B);
  draw(project(B)+project(taille*v)--project(B)+project(taille*(u+v))--project(B)+project(taille*u),p);
}

//trace un path3 ouvert visible sur la scene finale sans tenir compte des parties cachées ... utile ? ...
void tracepath3(path3 p, pen sty=currentpen){
  for(int i=0;i<=100;i=i+1){
    draw(project(pointsur(p,i/100))--project(pointsur(p,(i+1)/100)),sty);
  }
}

// renvoie un cercle de centre O et passant par A et de vecteur normal n.
path3 cercle(triple O, triple A, triple n){
  return circle(O,abs(A-O),n);
}
// renvoie un cercle de centre O et de rayon R de vecteur normal n.
path3 cercleR(triple O, real R, triple n){
  return circle(O,R,n);
}

//retourne le segment [AB] qui peut dépasser de a unités.
path3 segment(triple A, triple B,real a=0,pen sty=currentpen){
  path3 segment;
  segment=a*unit(A-B)+A--B+a*unit(B-A);
  return segment;
}

//renvoie le projeté de M orthogonal sur le plan passant par A,B et C
triple projortho(triple M, triple A, triple B, triple C){
  triple N,n,H;
  real a;
  n=cross(B-A,C-A);
  a=dot(n,A-M)/abs(n)^2;
  H=a*n+M;
  return H;
}


//renvoie l'intersection de de (MN) avec le plan passant par A,B et C
triple intersectionDP(triple M,triple N, triple A, triple B, triple C){
  triple n,d,I;
  real a;
  n=cross(B-A,C-A);
  d=N-M;
  a=dot(n,A-M)/dot(n,d);
  I=a*d+M;
  return I;
}

//retourne un point sur un chemin avec le paramètre r entre 0 et 1
triple pointsur(path3 chemin, real r)
{
  return point(chemin,arctime(chemin,r*arclength(chemin)));
}

//renvoie l'intersection de (MN) avec (AB)
triple intersectionDD(triple M,triple N, triple A, triple B){
  triple n,d,I;
  real a;
  n=cross(B-A,N-A);
  a=dot(n,M-B);
  if(a==0){
    I=intersectionDP(M,N,A,B,B+n);}
  return I;
}

//renvoie l'isobarycentre d'une face
triple iso(path3 face){
  triple som=(0,0,0);
  for(int i=0;i<length(face);i=i+1){
    som=som+point(face,i);
  }
  return som/length(face);
}

//renvoie le cone de revolution de base le disque de centre C et de rayon "rayon" et de "hauteur" cm
revolution conerevolution(triple C, real rayon, real hauteur,real section=1,triple axe=Z){
  revolution Cone;
  path3 gene=rayon*Y--(1-section)*rayon*Y+section*hauteur*Z;
  if(axe==Z){Cone=shift(C)*revolution(gene,Z);} else{
    triple u=cross(Z,axe);
    Cone=shift(C)*rotate(aCos(dot(Z,axe)/abs(axe)),u)*revolution(gene,Z);}
  return Cone;
}

//renvoie et trace la section plane d'un solide de révolution à une hauteur h entre 0 et 1.
path3 sectionplane(revolution r,real section, pen p=currentpen){
  skeleton s;
  //real t=aCos(1-2*section)/180;
  //r.transverse(s,reltime(r.g,t));
  r.transverse(s,reltime(r.g,section), P=currentprojection);
  //r.longitudinal(s);
  draw(s.transverse.back,p+dashed);
  draw(s.transverse.front,p);
  path3 sect;
  for(int i=0;i<s.transverse.back.length;i=i+1){sect=sect..s.transverse.back[i];}
  for(int i=0;i<s.transverse.front.length;i=i+1){sect=sect..s.transverse.front[i];}
  return sect;
}

// définit et trace une sphere/calotte spherique comme solide de revolution. k et h doivent etre entre 0 et 1, ils définissent respectivement le debut et la fin de la calotte : 0 correspond au pole sud et 1 au nord de la sphere associée.
revolution sphere(triple c=O, real rayon,real k=0,real h, int n=32){
  real x(real t){return cos(t);};
  real y(real t){return 0;};
  real z(real t){return sin(t);};
  real a = asin(2k-1);
  real b = asin(2h-1);
  path3 p =graph(x,y,z,a,b);
  revolution calotte=revolution((0,0,0),p,Z);
  return shift(c)*scale3(rayon)*calotte;
}

void trace(picture pic=currentpicture, Label L="", path3 g,
           align alignt=NoAlign, pen p=currentpen,
           arrowbar fleche=None, arrowbar barre=None, margin marge=NoMargin,
           Label legende="", marker mark=nomarker){
  draw(pic,L,project(g),alignt,p,fleche,barre,marge,legende,mark);
}

void label(string txt, triple M, pair alignt, pen p=currentpen){
  label(txt, project(M),alignt,p);
}

Re: Section cube par plan automatisé

Posté : dim. 9 avr. 2017, 20:57
par GM
Effectivement, je n'avais pas vu que j'avais aussi cette version sous un autre nom.

Cette discussion à laquelle je n'apporte pas de meilleure solution (faute de temps de chercher une solution dont la méthode pourrait peut-être être plus élégante mais certainement pas plus simple)...

... m'a permis de :
  • réaliser que plus aucun exemple ne passait sur le forum (depuis x mois ?) : une mise à jour de imagemagick (intervenue le ???) empêchait la fonction convert de bien fonctionner puisqu'il y eu apparemment des ajouts de sécurité dans

    Code : Tout sélectionner

    /etc/ImageMagick/policy.xml
    J'avais l'erreur

    Code : Tout sélectionner

    Convert : convert: not authorized `asymptote 2.39' @ error/constitute.c/ReadImage/453.
    J'ai dû ré-autoriser (en mettant une ligne en commentaire) la possibilité d'ajouter des labels pour avoir "asymptote 2.xx" sur chaque image créée.
  • ajouter geospace dans les imports autorisés ;
  • réaliser qu'en plus du problème habituel d'affichage des images 3Dsur le forum (voir figure ci-dessus)... il y a un problème supplémentaire avec les labels dans les figures 3D : j'ai dû mettre des lignes en commentaires dans l'exemple précédent.
Il me permet de rappeler aussi qu'il vaut mieux éviter de mettre du code de figures 3D entre des balises asy sur le forum !. On voit que cela ne sert à rien compte tenu des deux problèmes que j'ai évoqués !
Pour des figures 3D, se contenter de mettre le code entre les balises code et /code :

Code : Tout sélectionner

[code]Code asymptote d'une figure 3D !
Ne pas utiliser les balises asy ![/code]

Re: Section cube par plan automatisé

Posté : dim. 9 avr. 2017, 21:33
par Nico56
Ok, bien lu ;), c'était une question au cas où... Rien d'important!
Merci d'avoir répondu.
Bonne fin de soirée!
Nico