+input graph;
+
+%%% ----------------------------------------------------------------------------
+%%% Déclarations
+%%% ----------------------------------------------------------------------------
+
+numeric gddA[];
+numeric gddB[];
+numeric gddC[];
+numeric gddD[];
+numeric gddE[];
+numeric gddF[];
+picture gddL[]; % Table des labels TeX (btex .. etex)
+numeric gddO; % Compteur des objets
+path gddP[]; % Table des chemins (paths internes)
+string gddS[]; % Table des chaînes (noms de fichiers)
+string gddT[]; % Table des types
+numeric gddU; % Unité graphique
+string gddW; % Chaîne spécifiant le placement des objets
+
+%%% ----------------------------------------------------------------------------
+%%% Initialisations
+%%% ----------------------------------------------------------------------------
+
+% Initialisation de gddO -------------------------------------------------------
+gddO := 0;
+
+% Valeur par défaut de gddU ----------------------------------------------------
+gddU := 1cm;
+
+% Initialisation de gddW et procédure associée ---------------------------------
+gddW = "scaled gddU";
+def gddEnPlace = scantokens gddW enddef;
+
+%%% ----------------------------------------------------------------------------
+%%% Définition des objets
+%%% ----------------------------------------------------------------------------
+
+% Point ------------------------------------------------------------------------
+vardef Point(expr a,b) =
+ gddT[incr gddO] = "point";
+ gddA[gddO] = a; gddB[gddO] = b; gddO
+enddef;
+
+vardef PointDansRepere(expr x,y,o,i,j) =
+ gddT[incr gddO] = "point";
+ gddA[gddO] = gddA[o] + x*(gddA[i]-gddA[o]) + y*(gddA[j]-gddA[o]);
+ gddB[gddO] = gddB[o] + x*(gddB[i]-gddB[o]) + y*(gddB[j]-gddB[o]);
+ gddO
+enddef;
+
+vardef CoordonneesRepere(expr m,o,i,j) =
+ save x,y; numeric x,y;
+ gddA[m] = (gddA[i]-gddA[o])*x + (gddA[j]-gddA[o])*y + gddA[o];
+ gddB[m] = (gddB[i]-gddB[o])*x + (gddB[j]-gddB[o])*y + gddB[o];
+ (x,y)
+enddef;
+
+vardef Milieu(expr a,b) =
+ gddT[incr gddO] = "point";
+ gddA[gddO] = 0.5*(gddA[a]+gddA[b]);
+ gddB[gddO] = 0.5*(gddB[a]+gddB[b]);
+ gddO
+enddef;
+
+% Transformations pair <-> Point -----------------------------------------------
+def PointTOPair(expr a) = (gddA[a],gddB[a]) enddef;
+def PairTOPoint(expr p) = Point(xpart p,ypart p) enddef;
+def PairImp(expr a) = if pair a: a else: PointTOPair(a) fi enddef;
+def PointImp(expr a) = if pair a: PairTOPoint(a) else: a fi enddef;
+def Pt(expr a) = (gddA[a],gddB[a]) enddef;
+def PtR(expr a) = (gddA[a],gddB[a]) gddEnPlace enddef;
+
+
+% Addition ---------------------------------------------------------------------
+vardef AdditionAbscisses(expr a,b) = if pair a: xpart a else: gddA[a] fi + if pair b: xpart b else: gddA[b] fi enddef;
+vardef AdditionOrdonnees(expr a,b) = if pair a: ypart a else: gddB[a] fi + if pair b: ypart b else: gddB[b] fi enddef;
+vardef Addition(expr a,b) =
+ gddT[incr gddO] = "paire";
+ gddA[gddO] = AdditionAbscisses(a,b);
+ gddB[gddO] = AdditionOrdonnees(a,b);
+ gddO
+enddef;
+
+% Vecteur ----------------------------------------------------------------------
+vardef Vecteur (expr a,b) =
+ save n; n = incr gddO;
+ gddT[n] = "vecteur"; gddA[n] = PointImp(a); gddB[n] = PointImp(b); n
+enddef;
+
+
+% Segment ----------------------------------------------------------------------
+vardef Segment (expr a,b) =
+ save n; n = incr gddO;
+ gddT[n] = "segment"; gddA[n] = PointImp(a); gddB[n] = PointImp(b); n
+enddef;
+
+% Triangle ---------------------------------------------------------------------
+vardef Triangle (expr a,b,c) =
+ save n; n = incr gddO; gddT[n] = "triangle";
+ gddA[n] = PointImp(a); gddB[n] = PointImp(b); gddC[n] = PointImp(c); n
+enddef;
+
+% Droite -----------------------------------------------------------------------
+vardef Droite (expr a,b) =
+ save n; n = incr gddO;
+ gddT[n] = "droite"; gddA[n] = PointImp(a); gddB[n] = PointImp(b); n
+enddef;
+
+% Équation de droite : triplet (u,v,w) tel que ux+vy+w=0 -----------------------
+% L'équation rendue est normalisée !
+vardef EquationDroite(expr d) =
+ save u, v, w, n;
+ u := gddB[gddB[d]] - gddB[gddA[d]];
+ v := gddA[gddA[d]] - gddA[gddB[d]];
+ w := - u * gddA[gddA[d]] - v * gddB[gddA[d]];
+ n := u ++ v;
+ (u/n,v/n,w/n)
+enddef;
+
+% Ordonnée relative à une droite orientée --------------------------------------
+vardef OrdonneeRelativePointDroite(expr p, d) =
+ savec u, v, w;
+ (u,v,w) = EquationDroite(d);
+ u * gddA[p] + v * gddB[p] + w
+enddef;
+
+% Distance d'un point à une droite ---------------------------------------------
+def DistancePointDroite(expr p, d) =
+ abs(OrdonneeRelativePointDroite(p, d))
+enddef;
+
+% Projection d'un point sur une droite -----------------------------------------
+vardef ProjectionPointSurDroite(expr p, d) =
+ save u,v,w, l;
+ (u,v,w) = EquationDroite(d);
+ l := - u * gddA[p] - v * gddB[p] - w;
+ Point(gddA[p] + l * u, gddB[p] + l * v)
+enddef;
+
+% Cercles ----------------------------------------------------------------------
+vardef Cercle (expr a,b) =
+ save n; n = incr gddO;
+ gddT[n] = "cercle"; gddA[n] = PointImp(a); gddB[n] = b; n
+enddef;
+
+vardef CercleCP(expr a,b) = Cercle(a,abs(Pt(a)-Pt(b))) enddef;
+vardef CercleD(expr a,b) = CercleCP(Milieu(a,b),a) enddef;
+
+% Tangente commune extérieure à deux cercles -----------------------------------
+vardef TangenteCommuneExterieure(expr a, b) =
+ save O, A, d, f; pair O, A;
+ O = (gddB[a]/(gddB[a]-gddB[b]))[Pt(gddA[a]),Pt(gddA[b])]; % Centre de l'homothétie
+ d = abs(O-Pt(gddA[a]));
+ f := if gddA[a] < gddA[b] : 1 else: -1 fi;
+ A = Pt(gddA[a]) rotatedaround(O,angle(d+-+gddB[a],f*gddB[a]));
+ Droite(O,A)
+enddef;
+
+% Intersection de deux cercles -------------------------------------------------
+vardef IntersectionCercles(expr a, b) =
+ save d, x, y, u; pair u;
+ u = unitvector(Pt(gddA[b])-Pt(gddA[a]));
+ d = abs(Pt(gddA[a])-Pt(gddA[b]));
+ x = (gddB[a]**2-gddB[b]**2+d**2)/(2d);
+ y = gddB[a]+-+x;
+ PairTOPoint(Pt(gddA[a])+x*u+y*(u rotated 90))
+enddef;
+
+
+% Chemin -----------------------------------------------------------------------
+vardef Chemin (expr p) =
+ gddT[incr gddO] = "chemin"; gddP[gddO] = p; gddO
+enddef;
+
+% Courbe -----------------------------------------------------------------------
+vardef Courbe (expr s) =
+ gddT[incr gddO] = "courbe"; gddS[gddO] = s; gddO
+enddef;
+
+%%% ----------------------------------------------------------------------------
+%%% Définitions liées au repère
+%%% ----------------------------------------------------------------------------
+
+% Définition de l'origine ------------------------------------------------------
+origine = Point(0,0);
+
+% Définition des axes ----------------------------------------------------------
+AxeOx = Droite(origin,right);
+AxeOy = Droite(origin,up);
+
+%%% ----------------------------------------------------------------------------
+%%% Calculs MetaPost
+%%% ----------------------------------------------------------------------------
+
+vardef mpIntersectionDroites (expr a,b,c,d) =
+ save t; pair t; t = whatever [a,b]; t = whatever [c,d]; t
+enddef;
+
+%%% --------------------------------------------------------------------------
+%%% Tracés des courbes
+%%% --------------------------------------------------------------------------
+vardef gddTraceCourbe (expr f) =
+ save s; gdata(f, s, if i>1:..fi (scantokens s1,scantokens s2))
+enddef;
+
+%%% ----------------------------------------------------------------------------
+%%% Tracés des objets
+%%% ----------------------------------------------------------------------------
+
+gddExtensionDroite := 10;
+
+def gddTraceObjet expr o =
+ if gddT[o] = "triangle":
+ PointTOPair(gddA[o])--PointTOPair(gddB[o])--
+ PointTOPair(gddC[o])--cycle
+ elseif (gddT[o] = "segment") or (gddT[o] = "vecteur"):
+ PointTOPair(gddA[o])--PointTOPair(gddB[o])
+ elseif gddT[o] = "droite":
+ (gddExtensionDroite [ PointTOPair(gddA[o]), PointTOPair(gddB[o]) ]) --
+ (gddExtensionDroite [ PointTOPair(gddB[o]), PointTOPair(gddA[o]) ])
+ elseif gddT[o] = "cercle":
+ fullcircle scaled (gddB[o]*2) shifted PointTOPair(gddA[o])
+ elseif gddT[o] = "chemin":
+ gddP[o]
+ elseif gddT[o] = "courbe":
+ gddTraceCourbe (gddS[o] & ".dta")
+ fi
+enddef;
+
+def trace expr p =
+ if path p or picture p or pair p: draw (p)
+ elseif gddT[p] = "vecteur": drawarrow (gddTraceObjet p)
+ else: draw (gddTraceObjet p)
+ fi gddEnPlace
+enddef;
+
+def fleche expr p =
+ if path p or picture p: drawarrow (p)
+ elseif gddT[p] = "vecteur": drawarrow (gddTraceObjet p)
+ else: drawarrow (gddTraceObjet p)
+ fi gddEnPlace
+enddef;
+
+def colorie expr p =
+ if path p: fill p else: fill (gddTraceObjet p) fi gddEnPlace
+enddef;
+
+def fermeture expr p =
+ if path p: p else: (gddTraceObjet p) fi -- cycle
+enddef;
+
+
+%%% --------------------------------------------------------------------------
+%%% Marque et label des points
+%%% --------------------------------------------------------------------------
+gddTaillePoint := 3; % Diamètre des cercles marquant un point.
+color gddCouleurPoint; % Couleur de fond de la marque d'un point.
+gddCouleurPoint := white;
+gddTailleLabel := 1.5; % Taille d'un label.
+
+
+def gddPointe(expr p) =
+ fill (fullcircle scaled gddTaillePoint) shifted (p gddEnPlace)
+ withcolor gddCouleurPoint;
+ draw (fullcircle scaled gddTaillePoint) shifted (p gddEnPlace)
+enddef;
+
+def pointe expr p = gddPointe(if pair p: p else: PointTOPair(p) fi) enddef;
+
+vardef m_arque.@# expr p =
+ pointe p;
+ label.@#(gddL[p] scaled gddTailleLabel,PointTOPair(p) gddEnPlace);
+enddef;
+
+vardef m_a_rque.@# expr p =
+ pointe(scantokens p);
+ label.@#(lTEX(p),PointTOPair(scantokens p) gddEnPlace);
+enddef;
+
+vardef marque.@# expr p =
+ if string p: m_a_rque.@# p else: m_arque.@# p fi
+enddef;
+
+%%% --------------------------------------------------------------------------
+%%% Signes
+%%% --------------------------------------------------------------------------
+def SigneOrtho(expr a,b,c,x) =
+ (_point_(b) + x * unitvector(_point_(a)-_point_(b)))
+ -- (_point_(b) + x * unitvector(_point_(a) - _point_(b))
+ + x * unitvector(_point_(c) - _point_(b)))
+ -- (_point_(b) + x * unitvector(_point_(c) - _point_(b)))
+enddef;
+
+picture gdd_marque[];
+gdd_marque1 = image(draw (-7,-7)--(7,7));
+gdd_marque2 = image(draw (-7,-7)--(7,7); draw (-7,7)--(7,-7));
+gdd_marque3 = image(draw (-9,-7)--(5,7); draw (-5,-7)--(9,7);
+ draw (-7,7)--(7,-7));
+gdd_marque4 = image(draw (-9,-7)--(5,7); draw (-5,-7)--(9,7);
+ draw (-9,7)--(5,-7); draw (-5,7)--(9,-7));
+
+def Marque(expr a,b,n) =
+ gdd_marque[n] rotated angle(PairImp(b)-PairImp(a)) scaled (0.5/gddU)
+ shifted 0.5[PairImp(a),PairImp(b)]
+enddef;
+
+%%% --------------------------------------------------------------------------
+%%% Fenêtrage
+%%% --------------------------------------------------------------------------
+
+def Fenetre(expr xg,yg,xd,yd) =
+ gddXG := xg;
+ gddYB := yg;
+ gddXD := xd;
+ gddYH := yd;
+ extra_endfig := "gddFenetre;" & extra_endfig;
+enddef;
+
+def gddFenetre =
+ clip currentpicture to
+ ((gddXG,gddYB)--(gddXG,gddYH)--(gddXD,gddYH)--(gddXD,gddYB)--cycle)
+ gddEnPlace;
+ draw ((gddXG,gddYB)--(gddXG,gddYH)--(gddXD,gddYH)--(gddXD,gddYB)--cycle)
+ gddEnPlace withpen pencircle scaled 1 withcolor white;
+enddef;
+
+endinput
\ No newline at end of file