markangle "3D"

Pour toute demande d'aide sur des exemples non finalisés, c'est ici.
Les exemples aboutis et intéressants seront ajoutés aux sous-forums qui suivent.

Règles du forum
Pour toute demande d'aide pour la conception (ou la confirmation d'un code) d'une figure Asymptote, c'est ici.

J'invite ceux qui ont régulièrement des questions à poser à aller dans leur panneau de l'utilisateur pour indiquer dans la signature de leurs messages :

  1. Nom du système d'exploitation (W7 ou Ubuntu 12.04 ou ...)
  2. Version d'Asymptote et éditeur utilisé pour les figures Asymptote
  3. Distribution LaTeX et éditeur utilisé pour les tex.


On va gagner du temps dans les réponses !
Avatar du membre
chellier
Messages : 104
Enregistré le : jeu. 18 mars 2010, 17:30

markangle "3D"

Message non lu par chellier » mer. 19 mai 2010, 20:36

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 4136 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
Modifié en dernier par chellier le sam. 22 mai 2010, 18:40, modifié 1 fois.

Avatar du membre
GM
Administrateur du site
Administrateur du site
Messages : 1512
Enregistré le : dim. 7 mars 2010, 14:50

Re: markangle "3D"

Message non lu par GM » jeu. 20 mai 2010, 12:46

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.
Index des fonctions - Exemple de lien donnant le résultat d'une recherche sur les mots 'arc' et 'triple' : http://asy.marris.fr/indexasy/?filtre=arc triple
Mes configurations (le 24/02/21) :
PC n°1 :Windows 10 - Asymptote(2.82)+MikTeX2.9 - Editeurs : Notepad++, TeXworks, Visual Studio Code.
PC n°2 : Ubuntu 20.04LTS - Asymptote(2.67-?? git) + TexLive2020
Mon serveur : Debian Stretch- Asymptote(2.68-16 git) + TexLive2018
Merci de préciser la votre !

Avatar du membre
chellier
Messages : 104
Enregistré le : jeu. 18 mars 2010, 17:30

Re: markangle "3D"

Message non lu par chellier » sam. 22 mai 2010, 18:42

Premier message édité : possibilité de mettre des flèches.
Terre2.png
Terre2.png (169.96 Kio) Vu 4107 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

Répondre