Page 1 sur 1

markangle "3D"

Posté : mer. 19 mai 2010, 20:36
par chellier
Edit du 22/05/10 : possibilité de mettre des flèches

Bonsoir,
je ne sais pas si ça a déjà été fait (j'ai pas trouvé), mais j'ai tenté de modifier la fonction drawrightangle de Philippe Ivaldy pour le cas général. J'ai eu un peu de mal, notamment pour le placement du label. Alors je propose la solution que j'ai trouvée ici, si ça peut intéresser quelqu'un, ou si quelqu'un voit des améliorations à faire (merci d'en faire profiter...).

Code : Tout sélectionner

// trace l'angle (MA,MB) en 3D, si cc=false, trace "l'autre" arc
void markangle3D(picture pic=currentpicture,
          Label L="",
                    triple M, triple A, triple B,
          bool cc=true,
                    real radius=0,
                    pen p=currentpen,
                    pen fillpen=nullpen,
          arrowbar3 arrow=None,
                    projection P=currentprojection)
{
  p=linejoin(0)+linecap(0)+p;
  if (radius==0) radius=arrowfactor*sqrt(2);
  transform3 T=shift(-M);
  triple OA=radius/sqrt(2)*unit(T*A),
    OB=radius/sqrt(2)*unit(T*B);
  path3 pl=M--OA--OB;
  triple V=normal(pl);
  path3 _p; real k;
  if (cc) k=1;
  else k=-1;
  picture pic_;
  _p=arc(M,OA,OB,k*V);
    if (fillpen!=nullpen) draw(pic_, surface(O--_p--cycle), fillpen);
  draw(pic_, Label(L,align=k*unit(OA+OB)), _p, p=p, arrow);
  add(pic,pic_,M);
}


En bonus, une figure qui peut intéresser peut-être des profs de troisième. Pour l'adapter, en gros, il n'y a qu'à modifier la latitude, la longitude et les labels :
Terre.png
Terre.png (169.74 Kio) Vu 6517 fois

Code : Tout sélectionner

size(6*cm,0);
usepackage("fourier","upright");
import solids;
settings.render=0; // à commenter si besoin
settings.prc=false; // à commenter si besoin
//------------------------------------------------------------------------------------------
// trace l'angle (MA,MB) en 3D, si cc=false, trace "l'autre" arc
void markangle3D(picture pic=currentpicture,
          Label L="",
                    triple M, triple A, triple B,
          bool cc=true,
                    real radius=0,
                    pen p=currentpen,
                    pen fillpen=nullpen,
                    projection P=currentprojection)
{
  p=linejoin(0)+linecap(0)+p;
  if (radius==0) radius=arrowfactor*sqrt(2);
  transform3 T=shift(-M);
  triple OA=radius/sqrt(2)*unit(T*A),
    OB=radius/sqrt(2)*unit(T*B);
  path3 pl=M--OA--OB;
  triple V=normal(pl);
  path3 _p; real k;
  if (cc) k=1;
  else k=-1;
  picture pic_;
  _p=arc(M,OA,OB,k*V); draw(pic_, Label(L,align=k*unit(OA+OB)), _p, p=p);
    if (fillpen!=nullpen) draw(pic_, surface(O--_p--cycle), fillpen);
  add(pic,pic_,M);
}

// Draw right angle (MA,MB) in 3D -- Fonction de Philippe Ivaldi
void drawrightangle(picture pic=currentpicture,
                    triple M, triple A, triple B,
                    real radius=0,
                    pen p=currentpen,
                    pen fillpen=nullpen,
                    projection P=currentprojection)
{
  p=linejoin(0)+linecap(0)+p;
  if (radius==0) radius=arrowfactor*sqrt(2);
  transform3 T=shift(-M);
  triple OA=radius/sqrt(2)*unit(T*A),
    OB=radius/sqrt(2)*unit(T*B),
    OC=OA+OB;
  path3 _p=OA--OC--OB;
  picture pic_;
    draw(pic_, _p, p=p);
    if (fillpen!=nullpen) draw(pic_, surface(O--_p--cycle), fillpen);
  add(pic,pic_,M);
}

//-----------------------------------------------------------------------
// --------------------------- À modifier -----------------------------
currentprojection = orthographic(-20,70,15);
currentlight=nolight;
real lat=23.44; // latitude : + --> N, - --> S
real long=-50; // longitude : + --> W, - --> E
pen pSphere=paleblue; // +opacity(.4)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

triple pO=(0,0,0), pN=(0,0,1), pS=(0,0,-1), pX=(1,0,0), pY=(0,1,0);

revolution Terre=sphere(O,1,n=4*nslice);
draw(Terre.silhouette());
draw(surface(Terre), pSphere);

// Méridien de Greenwich
draw(arc(pO,pN,pS,-X),.7bp+red);

// Équateur
skeleton e;
Terre.transverse(e,reltime(Terre.g,.5));
draw(e.transverse.front,.7*linewidth(bp));
draw(e.transverse.back,.7*bp+dashed);

// parallèle
skeleton s;
Terre.transverse(s,reltime(Terre.g,(90+lat)/180));
draw(s.transverse.front);
draw(s.transverse.back,dashed);

// méridien
transform3 R=rotate(90-long,Z), r=rotate(-lat,Y);
triple pA=r*pX, pM=R*pX, pL=R*pA, pH=(0,0,Sin(lat)*length(pO--pL));
// demi-méridien
draw(arc(pO,pN,pM));
// méridien en entier
//path3 MNS=pN--pM--pS--cycle;
//triple VN=normal(MNS);
//draw(arc(pO,pN,pS,VN));

// ------------- Tracés en pointillés ----------------
// "Origine"
draw(pO--pY,linetype("4 4"));

draw(pN--pS,dashed);
draw(pO--pM^^pO--pL,linetype("4 4"));
draw(pH--pL,linetype("4 4"));

// ------------- Labels -------------
dot("$O$",pO,W); dot("$N$",pN,N); dot("$S$",pS,S); dot("$G$",pY,SW);
dot("$M$",pM,SE); dot("$L$",pL,NE); dot("$H$",pH,W);
label(scale(.6)*"\'Equateur",rotate(-80,Z)*pM,S);
label(scale(.6)*"Tropique du Cancer",rotate(-80,Z)*pL,S);
label(scale(.6)*"M\'eridien de Greenwich",rotate(-25,X)*pY,E,red);

// ------------- Marques des angles --------------
markangle3D(scale(.7)*Label(format("$%f^\circ$",abs(lat))),pO,pL,pM,radius=15*mm,fillpen=magenta);
markangle3D(scale(.7)*Label(format("$%f^\circ$",abs(long))),pO,pM,pY,radius=15*mm,fillpen=.5*green);
drawrightangle(pH,pL,pO,radius=3*mm);

//------------------------------------------
shipout(bbox(1mm,invisible));


Christophe

Re: markangle "3D"

Posté : jeu. 20 mai 2010, 12:46
par GM
Une réaction pour dire... c'est joli. :-)
(même si je n'ai pas le temps ... de regarder le code maintenant)
Merci.

Je laisse le message, ici, pour l'instant mais on pourra le basculer plus tard dans le forum thématique 3D... si tu ne reçois pas de plainte pour ton code. :D
La fin d'année est un peu chargée ... donc j'ai seulement le temps de m'occuper des urgences pendant les 6 semaines qui viennent mais je mettrai un peu d'ordre en juillet dans les forums thématiques.

Re: markangle "3D"

Posté : sam. 22 mai 2010, 18:42
par chellier
Premier message édité : possibilité de mettre des flèches.
Terre2.png
Terre2.png (169.96 Kio) Vu 6488 fois

Code : Tout sélectionner

size(6*cm,0);
usepackage("fourier","upright");
import solids;
settings.render=0; // à commenter si besoin
settings.prc=false; // à commenter si besoin
//------------------------------------------------------------------------------------------
// trace l'angle (MA,MB) en 3D, si cc=false, trace "l'autre" arc
void markangle3D(picture pic=currentpicture,
          Label L="",
                    triple M, triple A, triple B,
          bool cc=true,
                    real radius=0,
                    pen p=currentpen,
                    pen fillpen=nullpen,
          arrowbar3 arrow=None,
                    projection P=currentprojection)
{
  p=linejoin(0)+linecap(0)+p;
  if (radius==0) radius=arrowfactor*sqrt(2);
  transform3 T=shift(-M);
  triple OA=radius/sqrt(2)*unit(T*A),
    OB=radius/sqrt(2)*unit(T*B);
  path3 pl=M--OA--OB;
  triple V=normal(pl);
  path3 _p; real k;
  if (cc) k=1;
  else k=-1;
  picture pic_;
  _p=arc(M,OA,OB,k*V);
    if (fillpen!=nullpen) draw(pic_, surface(O--_p--cycle), fillpen);
  draw(pic_, Label(L,align=k*unit(OA+OB)), _p, p=p, arrow);
  add(pic,pic_,M);
}

// Draw right angle (MA,MB) in 3D -- Fonction de Philippe Ivaldi
void drawrightangle(picture pic=currentpicture,
                    triple M, triple A, triple B,
                    real radius=0,
                    pen p=currentpen,
                    pen fillpen=nullpen,
                    projection P=currentprojection)
{
  p=linejoin(0)+linecap(0)+p;
  if (radius==0) radius=arrowfactor*sqrt(2);
  transform3 T=shift(-M);
  triple OA=radius/sqrt(2)*unit(T*A),
    OB=radius/sqrt(2)*unit(T*B),
    OC=OA+OB;
  path3 _p=OA--OC--OB;
  picture pic_;
    draw(pic_, _p, p=p);
    if (fillpen!=nullpen) draw(pic_, surface(O--_p--cycle), fillpen);
  add(pic,pic_,M);
}

//-----------------------------------------------------------------------------------------

// ------------------ À modifier -------------------
currentprojection = orthographic(-20,70,15);
currentlight=nolight;
real lat=23.44; // latitude : + --> N, - --> S
real long=-50; // longitude : + --> W, - --> E
pen pSphere=paleblue; // +opacity(.4)
//--------------------------------------------------

triple pO=(0,0,0), pN=(0,0,1), pS=(0,0,-1), pX=(1,0,0), pY=(0,1,0);

revolution Terre=sphere(O,1,n=4*nslice);
draw(Terre.silhouette());
draw(surface(Terre), pSphere);

// Méridien de Greenwich
draw(arc(pO,pN,pS,-X),.7bp+red);

// Équateur
skeleton e;
Terre.transverse(e,reltime(Terre.g,.5));
draw(e.transverse.front,.7*linewidth(bp));
draw(e.transverse.back,.7*bp+dashed);

// parallèle
skeleton s;
Terre.transverse(s,reltime(Terre.g,(90+lat)/180));
draw(s.transverse.front);
draw(s.transverse.back,dashed);

// méridien
transform3 R=rotate(90-long,Z), r=rotate(-lat,Y);
triple pA=r*pX, pM=R*pX, pL=R*pA, pH=(0,0,Sin(lat)*length(pO--pL));
// demi-méridien
draw(arc(pO,pN,pM));
// méridien en entier
//path3 MNS=pN--pM--pS--cycle;
//triple VN=normal(MNS);
//draw(arc(pO,pN,pS,VN));

// ------------- Tracés en pointillés ----------------
// "Origine"
draw(pO--pY,linetype("4 4"));

draw(pN--pS,dashed);
draw(pO--pM^^pO--pL,linetype("4 4"));
draw(pH--pL,linetype("4 4"));

// ------------- Labels -------------
dot("$O$",pO,W); dot("$N$",pN,N); dot("$S$",pS,S); dot("$G$",pY,SW);
dot("$M$",pM,SE); dot("$L$",pL,NE); dot("$H$",pH,W);
label(scale(.6)*"\'Equateur",rotate(-80,Z)*pM,S);
label(scale(.6)*"Tropique du Cancer",rotate(-80,Z)*pL,S);
label(scale(.6)*"M\'eridien de Greenwich",rotate(-25,X)*pY,E,red);

// ------------- Marques des angles --------------
markangle3D(scale(.7)*Label(format("$%f^\circ$",abs(lat))),pO,pM,pL,radius=15*mm,fillpen=magenta,Arrow3);
markangle3D(scale(.7)*Label(format("$%f^\circ$",abs(long))),pO,pY,pM,radius=15*mm,fillpen=.5*green,Arrow3);
drawrightangle(pH,pL,pO,radius=3*mm);

//------------------------------------------
shipout(bbox(1mm,invisible));


Christophe