Page d'accueil

Espace Pro      
 Mon CV                      
  CV intéractif              
  CV Classique          
  CV imprimable        
  Téléchargement      
 Mes Projets              
  Statistiques              
  C.A.O.                        
  Programmation       
  Contact                     
Espace Perso  
 Liste DVD                  
Accueil programmation | Manipulations, Schémas et Formules | Images de surfaces | Makefile | NURBS.cpp | PLSV.cpp | PLSV.h | Surface.cpp | Surface.h | Vu.cpp | Vu.h | Rn.h | LesFichiers.h

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT: Logiciel de visualisation graphique Vu pour faire
// des traces interactifs graphiques X et PostScript
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR du X : PERRONNET Alain ANALYSE NUMERIQUE UPMC PARIS NOVEMBRE 2000
// AUTEUR du PS: DOURSAT Christophe ANALYSE NUMERIQUE UPMC PARIS NOVEMBRE 1994
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//=======================================================================
//Les SPECIFICATIONS ou ENTETES de Rn et Vu
//=======================================================================
#include "Rn.h"
#include "Vu.h"

//=======================================================================
// Les DONNEES PUBLIQUES de Vu
//=======================================================================
// le numero des couleurs imposees dans la palette des couleurs
int Noir=0, Rouge=1, Vert=2, Bleu=3, Cyan=4, Jaune=5, Magenta=6, Blanc=7,
GrisSombre=8, Gris=9, GrisClair=10, Beige=11, Orange=12, Saumon=13,
Rose=14, Turquoise=15;

//Le Systeme de Coordonnees Global SCG et Utilisateur SCU
R3 SCG[4]={ R3(0,0,0), R3(1,0,0), R3(0,1,0), R3(0,0,1) };
R3 SCU[4]={ R3(0,0,0), R3(1,0,0), R3(0,1,0), R3(0,0,1) };
//Le point origine et les 3 vecteurs orthonormes du SC
//dans le Systeme de Coordonnees Generales SCG
//Au depart, le SCU est le SCG

int AccrocherGrilleSCU=1; //Mode Accrocher aux coins de la grille 0:non actif 1:actif
int CouleurGrilleSCU=Noir; //couleur de trace de la grille. si <0 pas de trace de la grille
R2 PasGrilleSCU=R2(0.2,0.2); //pas de la grille en largeur et hauteur

int CouleurChiffre=GrisSombre; //couleur de trace des chiffres des graduations sur les axes

int noforeground, nobackground; // no dans norgb des couleurs de trace et du fond
unsigned long foreground, background; // couleur X de trace et couleur du fond

int lapxfe, lhpxfe; // nombre de pixels de la fenetre en largeur et hauteur
int largbouton, hautbouton, hauttexte; //trace d'un bouton de Menu, Invite ...

//=======================================================================
// Les DONNEES PRIVEES de Vu
//=======================================================================
#define MAX_SHORT 0xFFFF // Plus grande valeur d'un entier short
#define X_COIN_FENETRE 0 // Position du COIN SUPERIEUR GAUCHE de la fenetre X
#define Y_COIN_FENETRE 0
#define CMAPSIZE 256 // Nombre de couleurs pour 8 Plans 256=2**8

static Display *display_vu; // la structure display Vu = le SERVEUR X
static int ecran_vu; // les caracteristiques de l'ecran graphique
static GC gc_vu; // le contexte graphique Vu
static XSetWindowAttributes attributs_vu; // attributs de la fenetre Vu

Window fenetre_vu0, fenetre_vu; // la fenetre Vu

//Le Drawable sera lors des traces soit fenetre_vu soit un des pixmaps
//static Drawable *fenpix_vu; //destine a servir de support des differents traces

//Les donnees pour les couleurs
static Visual *visual; // Choix du type d'utilisation de l'ecran c-a-d
// PseudoColor ou TrueColor ou ...
static int visual_class; // visual->class = PseudoColor, TrueColor,...
static R red[CMAPSIZE], green[CMAPSIZE], blue[CMAPSIZE];
// rouge vert bleu de la palette des couleurs
static unsigned long norgb[CMAPSIZE];
// numero dans la palette physique de la couleur i dans la palette des couleurs de Vu
// en PseudoColor: c'est l'identite norgb[i]=i
// la i_eme couleur de la palette Vu est celle
// de la palette physique
// en TrueColor : c'est le no dans la palette physique en lecture seule
// norgb[i]=fonction de (rouge, vert, bleu)
// cette valeur est calculee par XAllocColor
// qui determine a partir de RGB la couleur la plus
// proche parmi les couleurs de la palette physique
#define MAXPACL 14 // nombre maximal de palettes de couleurs cf VuPaletteCouleurs
static int nbpacl; // nombre de palettes de couleurs
static int nopacl; // numero de 1 a nbpacl de la palette de couleurs active
static Colormap color_map0; // palette initiale (En lecture SEULE)
static Colormap color_map; // palette courante des couleurs (en LECTURE/ECRITURE)
static int lammec, lhmmec; // nombre de mm de l'ecran en largeur et hauteur
static int lapxec, lhpxec; // nombre de pixels de l'ecran en largeur et hauteur
static R cxmmpx, cymmpx; // nombre de pixels par mm en largeur et hauteur sur l'ecran
static int n1core; //numero dans la palette des couleurs de la premiere couleur reservee
static int ndcore; //numero dans la palette des couleurs de la dernierere couleur reservee
static int n1coel; //numero dans la palette des couleurs de la premiere couleur elementaire
static int ndcoel; //numero dans la palette des couleurs de la derniere couleur elementaire
static int n1coul; //numero dans la palette des couleurs de la premiere couleur modifiable
static int ndcoul; //numero dans la palette des couleurs de la derniere couleur modifiable
static int nbcolo; // nombre de couleurs de la palette Vu ( 2 ou 256 )
static int nbepai; // nombre d'epaisseurs supplementaires des traits (>=0)
static int notytr; // type de traits: 0 continu, 1 tirete, 2 double tirete

//Les fontes X de caracteres
#define MAXFONTS 512 // nombre maximal de fontes declarables
static char **listfonts; // pointe sur le tableau des noms de fontes fourni par X
static int lhpxfo[MAXFONTS];// le nombre de pixels en hauteur de chaque fonte
static int nbfontes; // nombre de polices ou fontes de caracteres disponibles
static Font font_id; // nom de la fonte actuelle
static XFontStruct *struc_police ; // structure de la police courante
static int ascent_pol, // nombre de pixels au dessus de la ligne de base
descent_pol; // nombre de pixels au dessous de la ligne de base
static XCharStruct mesure ; // qualifiants des dimensions d'une chaine de caracteres
static int nofoca; // numero de la fonte actuelle dans X
static int nplaca, nphaca; // nombre de pixels en largeur et hauteur de la fonte actuelle
static int nphfco; // nombre de pixels en hauteur de la fonte actuelle


//Les parametres contenus dans les communs decrivant les tailles des divers menus
//dans gsmenu.inc
#define MXRECT 8 // nombre maximal de rectangles menus
#define NBCAME 80 // nombre de caracteres d'une ligne du menu
#define MXLGME 48 // nombre maximal de lignes du menu
#define NBCAHI 48 // nombre de caracteres d'une ligne de l'historique
#define MXLGHI 16 // nombre maximal de lignes de l'historique
#define NBCADO 80 // nombre de caracteres d'une ligne de la documentation
#define MXLGDO 31 // nombre maximal de lignes de la documentation
#define NBCAIN 48 // nombre de caracteres d'une ligne de l'invite
#define MXLGIN 2 // nombre maximal de lignes de l'invite
#define NBCALG 96 // nombre de caracteres d'une ligne de saisie
#define MXLGSA 1 // nombre maximal de lignes de la ligne de saisie
#define NBCAER 96 // nombre de caracteres d'une ligne des erreurs
#define MXLGER 32 // nombre maximal de lignes des erreurs


//dans lu.inc
#define NBCALI 96 // nombre de caracteres par ligne lue
#define MXKLG 256 // nombre maximal de lignes de lignes lues
#define NBCALIP10 106 // NBCALI+10 pour ajout dans kliglue du texte Ligne lue:


//Les donnees PostScript
static int lasopsc; // sortie ou non du trace en PostScript
static int modepsc;
static FILE *fpi, *fpo;
static R counb, courgb[3];
static int palcourc;
static int xpixels, ypixels;
static char *chaine[MXRECT] ;
static int longchaine[MXRECT];
static char format[255];
static int menu;
static int icolorm;
static int nbrcon, xinic, yinic, xcouc, ycouc;
static int iTe, iFa, ity, iep, iPo, ire , iRe, iel, iEl, iFP;
static char buf[512], concat[512], fontcour[512];

int decaltexte, nbepbordbouton; //trace d'un bouton
int larginvite, hautinvite, nbepbordinvite; //trace de l'invite
int couleurinvite=Jaune, couleurtexteinvite=0;
char TexteInvite[128]; //sauvegarde du texte de la ligne d'invite
char TexteClavier[128]; //texte saisi au clavier


//Les donnees pour les COURBES et les SURFACES
static const int mxsucb=64; //nombre maximal de sous-aretes d'une courbe
static const int mxsuar=16; //nombre maximal de sous-aretes d'un
//cote de triangle ou quadrangle

//=======================================================================
//DEBUT de la REALISATION des FONCTIONS de Vu
//=======================================================================

void VuPxEcran(int & lapxec, int & lhpxec)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT :RECUPERER le nombre de pixels de la largeur et hauteur de l'ecran total
// -----
//
// SORTIES :
// ---------
// lapxec : nombre de pixels de la largeur de l'ecran
// lhpxec : nombre de pixels de la hauteur de l'ecran
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
lapxec = XDisplayWidth ( display_vu, ecran_vu );
lhpxec = XDisplayHeight ( display_vu, ecran_vu );
}


void VuMMEcran(int & lammec, int & lhmmec)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : RECUPERER la largeur et hauteur de l'ecran total en MILLIMETRES
// -----
//
// SORTIES :
// ---------
// lammec : nombre de MM de la largeur de l'ecran
// lhmmec : nombre de MM de la hauteur de l'ecran
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
lammec = XDisplayWidthMM ( display_vu, ecran_vu );
lhmmec = XDisplayHeightMM ( display_vu, ecran_vu );
}


void VuInitier(void)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Initialiser le display et l'ecran X
// ce qui permet ensuite de recuperer
// le nombre de pixels en largeur et hauteur de l'ecran par Vupxecran
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
//Ouverture du Display de Vu
//=====================
display_vu = XOpenDisplay(NULL);
if ( display_vu == (Display *) NULL )
{
cout << "Initialisation Graphique X IMPOSSIBLE\n";
exit(1);
}
//cout << "Le Display est ouvert avec display_vu=" << display_vu << endl;

//Ouverture de l'ecran de Vu
//============================
ecran_vu = DefaultScreen( display_vu );
//cout << "L'ecran est ouvert avec ecran_vu=" << ecran_vu << endl;
cout << "Le display et l'ecran sont ouverts" << endl;

//INITIALISATION DES CARACTERISTIQUES DE L'ECRAN
// ==============================================
// LARGEUR ET HAUTEUR DE L'ECRAN EN MM
VuMMEcran( lammec, lhmmec );

//LARGEUR ET HAUTEUR EN PIXELS DE L'ECRAN
VuPxEcran( lapxec, lhpxec);

cout << "Largeur de l'ecran = " << lammec << " millimetres = " << lapxec << " pixels" << endl;
cout << "Hauteur de l'ecran = " << lhmmec << " millimetres = " << lhpxec << " pixels" << endl;

// nombre de pixels par mm en largeur et hauteur de l'ecran
cxmmpx = (R) lapxec / (R) lammec;
cymmpx = (R) lhpxec / (R) lhmmec;
}


void VuCouleursImposees( int & n1coel, int & ndcoel,
R red[], R green[], R blue[] )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : Definir les 16 couleurs imposees dans toute palette
----- ( procedure interne a Vu )

ENTREES :
---------
n1coel : numero de la premiere couleur imposee

MODIFIES:
---------
red, green, blue : les tableaux ROUGE VERT BLEU de la palette

SORTIES :
---------
ndcoel : numero de la derniere couleur imposee
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
// Noir
red[Noir] = 0.0 ;
green[Noir] = 0.0 ;
blue[Noir] = 0.0 ;

// Rouge
red[Rouge] = 1.0 ;
green[Rouge] = 0.0 ;
blue[Rouge] = 0.0 ;

// Vert
red[Vert] = 0.0 ;
green[Vert] = 1.0 ;
blue[Vert] = 0.0 ;

// Bleu
red[Bleu] = 0.0 ;
green[Bleu] = 0.0 ;
blue[Bleu] = 1.0 ;

// Cyan
red[Cyan] = 0.0 ;
green[Cyan] = 0.8 ;
blue[Cyan] = 0.9 ;

// Jaune
red[Jaune] = 1.0 ;
green[Jaune] = 1.0 ;
blue[Jaune] = 0.0 ;

// Magenta
red[Magenta] = 1.0 ;
green[Magenta] = 0.0 ;
blue[Magenta] = 1.0 ;

// Blanc
red[Blanc] = 1.0 ;
green[Blanc] = 1.0 ;
blue[Blanc] = 1.0 ;

// GrisSombre
red[GrisSombre] = 90./256. ;
green[GrisSombre] = 90./256. ;
blue[GrisSombre] = 100./256. ;

// Gris
red[Gris] = 170./256. ;
green[Gris] = 170./256. ;
blue[Gris] = 180./256. ;

// GrisClair
red[GrisClair] = 240./256. ;
green[GrisClair] = 240./256. ;
blue[GrisClair] = 250./256. ;

// Beige
red[Beige] = 245./256. ;
green[Beige] = 245./256. ;
blue[Beige] = 220./256. ;

// Orange
red[Orange] = 1.0;
green[Orange] = 130./256. ;
blue[Orange] = 0. ;

// Saumon
red[Saumon] = 250./256. ;
green[Saumon] = 128./256. ;
blue[Saumon] = 114./256. ;

// Rose
red[Rose] = 1.0 ;
green[Rose] = 181./256. ;
blue[Rose] = 197./256. ;

// Turquoise
red[Turquoise] = 64./256. ;
green[Turquoise] = 224./256. ;
blue[Turquoise] = 188./256. ;

/* 16 COULEURS IMPOSEES */
ndcoel = n1coel + (int) 15 ;
}

void VuColormapToRGB( Colormap color_map,
R r[], R g[], R b[], int nbcolor)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : TRANSFERER les nbcolor couleurs de la palette color_map dans les
----- tableaux r, v, b de C dans la classe PseudoColor
( procedure interne a Vu )

ENTREE :
--------
nbcolor : nombre de couleurs dans la palette des couleurs a charger

SORTIES :
---------
r, g, b : les tableaux ROUGE VERT BLEU de la palette en C
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
XColor colorcell_defs;
int i;

for ( i = 0 ; i < nbcolor ; i++ )
{
colorcell_defs.pixel = (unsigned long) i;
/* Recuperation du rouge vert bleu de la couleur i de la colormap */
XQueryColor (display_vu, color_map, &colorcell_defs);

r[i] = ( (R) colorcell_defs.red / (R) MAX_SHORT );
g[i] = ( (R) colorcell_defs.green / (R) MAX_SHORT );
b[i] = ( (R) colorcell_defs.blue / (R) MAX_SHORT );
}
}

void VuRGBtoColormap( int visual_class, int nbcells,
R red[], R green[], R blue[],
unsigned long norgb[], Colormap color_map )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : IMPOSER dans la palette des couleurs color_map modifiable
----- les couleurs red green blue tableaux C
( Fonction interne a Vu )

ENTREES :
---------
visual_class : type de visual TrueColor, PseudoColor, ...
nbcells : nombre de couleurs dans la palette des couleurs a charger
red, green, blue : les tableaux red green blue des couleurs primaires

SORTIES :
---------
norgb : numero des couleurs de la palette Vu dans la palette physique
color_map : recoit les nbcells couleurs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
unsigned long index;
XColor colorcell_defs[CMAPSIZE];

if ( (visual_class != TrueColor) && (visual_class != GrayScale) )
{ /* PseudoColor par exemple */
for ( index = 0 ; index < nbcells ; index++ )
{
norgb[index] = (unsigned long) index; // valeur ici imposee
colorcell_defs[index].pixel = (unsigned long) index;
colorcell_defs[index].red = (unsigned short) ( red[index] * (R) MAX_SHORT );
colorcell_defs[index].green = (unsigned short) ( green[index] * (R) MAX_SHORT );
colorcell_defs[index].blue = (unsigned short) ( blue[index] * (R) MAX_SHORT );
colorcell_defs[index].flags = DoRed | DoGreen | DoBlue;
colorcell_defs[index].pad = '.';
}
/* Stockage des couleurs Vu dans la colormap lecture/ecriture NON PARTAGEABLE */
XStoreColors ( display_vu, color_map, colorcell_defs, nbcells );
}
else /* TrueColor ou GrayScale */
{
for ( index = 0 ; index < nbcells ; index++ )
{
/* colorcell_defs[index].pixel = (unsigned long) index; */
colorcell_defs[index].red = (unsigned short) ( red[index] * (R) MAX_SHORT );
colorcell_defs[index].green = (unsigned short) ( green[index] * (R) MAX_SHORT );
colorcell_defs[index].blue = (unsigned short) ( blue[index] * (R) MAX_SHORT );
colorcell_defs[index].flags = DoRed | DoGreen | DoBlue;
colorcell_defs[index].pad = '.';

/* Initialisation de colorcell_defs[index].pixel par recherche X de la couleur
RGB la plus proche dans la palette physique palette lecture seule PARTAGEABLE */
XAllocColor ( display_vu, color_map, &colorcell_defs[index] );
norgb[index] = colorcell_defs[index].pixel; /* valeur ici retrouvee */
}
}
}


void VuPaletteCouleurs(int nopacoul)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Construire et charger la palette nopacoul de couleurs
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbcoul, i,j,k,l,n;
R r,v,b, c,d,d0,d1;

//protection pour un ecran noir et blanc
if( ndcoul == n1coul+1 ) return;
if( nopacoul <=0 || nopacoul > nbpacl ) nopacoul=1;
if( nopacoul == nopacl ) return;

// le nouvelle palette active
nopacl = nopacoul;

// la premiere couleur modifiable
l = n1coul;

//le nombre de couleurs a initialiser
nbcoul = ndcoul-n1coul+1;

// traitement selon le numero de palette
switch( nopacoul )
{
case 1: // La couleur varie vite et du noir est ajoute
c = 1.0;
while( l<nbcolo )
{
red[l] = c; // rouge
green[l] = 0.0;
blue[l] = 0.0;
l += 1;

red[l] = 0.0; // vert
green[l] = c;
blue[l] = 0.0;
l += 1;

red[l] = 0.0; // bleu
green[l] = 0.0;
blue[l] = c;
l += 1;

red[l] = c; // cyan
green[l] = c;
blue[l] = 0.0;
l += 1;

red[l] = 0.0; // jaune
green[l] = c;
blue[l] = c;
l += 1;

red[l] = c; // magenta
green[l] = 0.0;
blue[l] = c;
l += 1;

c -= (R) nbcolo / 6.0;
}
break;

case 2: // La couleur varie vite et du blanc est ajoute
r = 0.27;
v = 0.22;
b = 0.17;
c = 0.3;
while( l<nbcolo )
{
red[l] = c; // rouge
green[l] = v;
blue[l] = b;
l += 1;

red[l] = r; // vert
green[l] = c;
blue[l] = b;
l += 1;

red[l] = r; // bleu
green[l] = v;
blue[l] = c;
l += 1;

red[l] = c; // cyan
green[l] = c;
blue[l] = b;
l += 1;

red[l] = r; // jaune
green[l] = c;
blue[l] = c;
l += 1;

red[l] = c; // magenta
green[l] = v;
blue[l] = c;
l += 1;

r += (R) nbcolo / 6.0;
v += (R) nbcolo / 6.0;
b += (R) nbcolo / 6.0;
c += (R) nbcolo * 0.7 / 6.0;
}
break;

case 3:
//La palette des bleus
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = c;
green[l] = c;
blue[l] = 0.3 + l * d;
c -= (R) 0.28 / nbcoul;
}
break;

case 4:
//La palette des cyans
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = c;
green[l] = 0.3 + l * d;
blue[l] = 0.3 + l * d;
c -= (R) 0.28 / nbcoul; }
break;

case 5:
//La palette des verts
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = c;
green[l] = 0.3 + l * d;
blue[l] = c;
c -= (R) 0.28 / nbcoul; }
break;

case 6:
//La palette des jaunes
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = 0.3 + l * d;
green[l] = 0.3 + l * d;
blue[l] = c;
c -= (R) 0.28 / nbcoul;
}
break;

case 7:
//La palette des oranges
d = 1.0 / ndcoul;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = l * d;
green[l] = l * d / 2 + 20./256.;
blue[l] = 0.0;
}
break;

case 8:
//La palette des rouges
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = 0.3 + l * d;
green[l] = c;
blue[l] = c;
c -= (R) 0.28 / nbcoul;
}
break;

case 9:
//La palette des magentas
d = 0.7 / ndcoul;
c = 0.3;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = 0.3 + l * d;
green[l] = c;
blue[l] = 0.3 + l * d;
c -= (R) 0.28 / nbcoul;
}
break;

case 10:
//La palette des gris (du gris-noir au blanc pur)
d = 1.0 / ndcoul;
for ( l=n1coul; l<=ndcoul; l++ )
{
red[l] = l * d;
green[l] = l * d;
blue[l] = l * d;
}
break;

case 11:
//La palette Arc en ciel en fondu des couleurs
n = (int) (nbcoul/6.5+0.5); // nombre de couleurs par passage
j = (int) (n * 1.7);
for ( k=0; k<=j; k++ ) // du bleu au cyan
{
red[l] = 0;
green[l] = ( (R) k ) / j;
blue[l] = 1.0;
l += 1;
}
j = (int) (n * 0.9);
for ( k=0; k<=j; k++ ) // du cyan au vert
{
red[l] = 0;
green[l] = 1.0;
blue[l] = 1.0 - ( (R) k ) / j;
l += 1;
}
j = (int) (n * 0.9);
for ( k=0; k<=j; k++ ) // du vert au jaune
{
red[l] = ( (R) k ) / j;
green[l] = 1.0;
blue[l] = 0;
l += 1;
}
j = (int) (n * 1.7);
for ( k=0; k<=j; k++ ) // du jaune au rouge
{
red[l] = 1.0;
green[l] = 1.0 - ( (R) k ) / j;
blue[l] = 0;
l += 1;
}
j = (int) (n * 1.32);
for ( k=0; k<=j; k++ ) // du rouge au magenta
{
if(l > ndcoul ) break;
red[l] = 1.0;
green[l] = 0;
blue[l] = ( (R) k ) / j;
l += 1;
}

break;


case 12:
//La palette 12 Arc en ciel discontinue en couleurs
n = (int) (nbcoul/6.8+0.5); // nombre de nuances par couleur
for ( k=0; k<n; k++ ) // des bleus
{
d = 0.5 * ( (R) k ) / n;
red[l] = d;
green[l] = d;
blue[l] = 1.0-d/5;
l += 1;
}

for ( k=0; k<n; k++ ) // des cyans
{
d = 0.5 * ( (R) k ) / n;
red[l] = d;
green[l] = 1.0-d/5;
blue[l] = 1.0-d/5;
l += 1;
}

for ( k=0; k<n; k++ ) // des verts
{
d = 0.5 * ( (R) k ) / n;
red[l] = d;
green[l] = 1.0-d/5;
blue[l] = d;
l += 1;
}

for ( k=0; k<n; k++ ) // des jaunes
{
d = 0.5 * ( (R) k ) / n;
red[l] = 1.0-d/5;
green[l] = 1.0-d/5;
blue[l] = d;
l += 1;
}

for ( k=0; k<n; k++ ) // des oranges
{
d = 0.5 * ( (R) k ) / n;
red[l] = 1.0-d/5;
green[l] = 0.6-d/5;
blue[l] = d;
l += 1;
}

for ( k=0; k<n; k++ ) // des rouges
{
d = 0.5 * ( (R) k ) / n;
red[l] = 1.0-d/5;
green[l] = d;
blue[l] = d;
l += 1;
}

for ( k=0; k<n; k++ ) // des magentas
{
if( l > ndcoul ) break;
d = 0.5 * ( (R) k ) / n;
red[l] = 1.0-d/5;
green[l] = d;
blue[l] = 1.0-d/5;
l += 1;
}
break;

case 13:
//La palette 13 Arc en ciel avec 10 nuances pour chaque couleur
n = (int) (nbcoul/10.0+0.5); // nombre de nuances par couleur
d0 = 0.3;
d1 = 1.0 - d0;
for ( k=0; k<n; k++ )
{
// des bleus
d = d0 * ( (R) k ) / n;
red[l] = d;
green[l] = d;
blue[l] = d+d1;
l += 1;
// des cyans
red[l] = d;
green[l] = d+d1;
blue[l] = d+d1;
l += 1;
// des verts
red[l] = d;
green[l] = d+d1;
blue[l] = d;
l += 1;
// des verts turquoises
red[l] = d+ 64./256.*d1 ;
green[l] = d+224./256.*d1;
blue[l] = d+188./256.*d1;
l += 1;

// des beiges
red[l] = d+245./256.*d1;
green[l] = d+245./256.*d1;
blue[l] = d+220./256.*d1;
l += 1;
// des jaunes
red[l] = d+0.7;
green[l] = d+0.7;
blue[l] = d;
l += 1;
// des oranges
red[l] = d+1.0*d1;
green[l] = d+0.5*d1;
blue[l] = d;
l += 1;
// des saumons
red[l] = d+250./256.*d1;
green[l] = d+140./256.*d1;
blue[l] = d+105./256.*d1;
l += 1;
// des rouges
red[l] = d+d1;
green[l] = d;
blue[l] = d;
l += 1;
// des magentas
red[l] = d+d1;
green[l] = d;
blue[l] = d+d1;
l += 1;
}
break;

case 14:
//La palette 14 Bleu Blanc Rouge
n = (int) (nbcoul/2.0+0.5); // nombre de nuances par couleur
for ( k=0; k<n; k++ ) // les bleus et les cyans
{
red[l] = 0.2 + ( (R) k * 0.79 ) / n;
green[l] = 0.2 + ( (R) k * 0.79 ) / n;
blue[l] = 1.0;
l += 1;
}
for ( k=0; k<n; k++ ) // les rouges
{
if( l > ndcoul ) break;
red[l] = 1.0;
green[l] = 0.2 + ( (R) (n-k)* 0.79 ) / n;
blue[l] = 0.2 + ( (R) (n-k)* 0.79 ) / n;
l += 1;
}
break;
}

//les nbcolo couleurs sont allouees dans la colormap partageable
VuRGBtoColormap( visual_class, nbcolo,
red, green, blue,
norgb, color_map );
}


void MemoirePx::VuCreerPixmap( unsigned int largpix, unsigned int hautpix,
XPoint csgdf )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT: Creer un pixmap de largpix pixels en largeur et hautpix pixels en hauteur
// associe a fenetre_vu
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
largeurpx = largpix;
hauteurpx = hautpix;
pxcsgdf = csgdf;
mempx = XCreatePixmap( display_vu, fenetre_vu,
largeurpx, hauteurpx,
DefaultDepth( display_vu, ecran_vu ) );
VuEffacerMemoirePx(); //le pixmap a pour couleur celle du fond
visee = 0; //pas de type de visee defini
}

MemoirePx::~MemoirePx()
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT: Tuer un pixmap associe a fenetre_vu
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
//cout << "Appel XFreePixmap\n"; //pour voir quand le destructeur agit
XFreePixmap( display_vu, mempx );
}

void MemoirePxAccroche::VuCreerPixmap( unsigned int largpx, unsigned int hautpx )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT: Creer le pixmap contenant le carre de visualisation d'un accrochage
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XGCValues gcvalues;
unsigned long colour;
int nbep=3;

//creation du Pixmap avec position nulle du pixel coin superieur gauche
//cette valeur sera actualisee avant emploi dans l'accrochage
XPoint csgdf={0,0};
MemoirePx::VuCreerPixmap( largpx, hautpx, csgdf );

// le fond de pixmap a pour couleur celle du fond de la fenetre
XSetForeground( display_vu, gc_vu, background );
XFillRectangle( display_vu, mempx, gc_vu, 0, 0, largeurpx, hauteurpx );

// nbep epaisseurs supplementaires de trait pour le symbole de l'accrochage
gcvalues.line_width = nbep;
XChangeGC( display_vu, gc_vu, GCLineWidth, &gcvalues );

//le symbole d'accrochage est un carre
colour = norgb[Jaune];
//cout << "La couleur du carre d'accrochage est " << colour << endl;
XSetForeground( display_vu, gc_vu, colour );
XDrawRectangle( display_vu, mempx, gc_vu, 1, 1,
largeurpx-nbep, hauteurpx-nbep );
}

void VuChargerLaFonte( int & n, char *namefonts,
int & largpx, int & hautpx )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : CHARGER la fonte n de nom namefonts parmi les fontes disponibles
-----

MODIFIE :
---------
n : numero de la fonte de X
si fonte indisponible, c'est la premiere fonte disponible suivante

ENTREES :
---------
namefonts : nom de la fonte a charger

SORTIES :
---------
largpx : nombre de pixels en largeur de la fonte
hautpx : nombre de pixels en hauteur de la fonte
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
int i, j, ideb, ifin, ilon, direction ;
char *font, mp[3] ;

if ( ( 0 <= n ) && ( n < nbfontes ) )
{
j = 0 ;
for ( i = n ; nbfontes - 1 ; i++ )
{
font = *(listfonts + i);
strcpy( namefonts, font );
struc_police = XLoadQueryFont(display_vu, font);
if (struc_police != NULL)
{
XSetFont (display_vu, gc_vu, struc_police->fid);
if ( i != n )
{
sprintf(&format[0],"\n VuChargerLaFonte: fonte %d indisponible => remplacee par la fonte %d\n\n",n,i);
printf(format) ; n = i ;
}
j = 1 ; break ;
}
}
if ( j == 0 )
{
for ( i = 1 ; n - 1 ; i++ )
{
font = *(listfonts + n);
strcpy( namefonts, font );
struc_police = XLoadQueryFont(display_vu, font);
if (struc_police != NULL)
{
XSetFont (display_vu, gc_vu, struc_police->fid) ;
if ( i != n )
{
sprintf(&format[0],"\n VuChargerLaFonte: fonte %d indisponible => remplacee par la fonte %d\n\n",n,i);
printf(format) ; n = i ;
}
j = 1 ; break ;
}
}
}
if ( j == 0 )
{
sprintf(&format[0],"\n VuchargerLaFonte: AUCUNE FONTE N'EST DISPONIBLE\n");
printf(format) ;
}

sprintf(&format[0],"abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890") ;
XTextExtents(struc_police , format , strlen(format) , &direction ,
&ascent_pol , &descent_pol , &mesure ) ;
largpx = (int) (mesure.width / 64.0) ;
largpx = largpx + 1 ;
/* hautpx = ascent_pol + descent_pol ; VALEUR MAX TROP GRANDE */
hautpx = mesure.ascent + mesure.descent;

/* Traitement en vue du PostScript */
ideb = 0 ; ifin = 0 ;
for ( i = 1 ; i < strlen(font) ; i++ )
{ if (font[i] == '-') { if (ifin == 0) { ideb = i ; ifin = i ;
} else { ifin = i ; sprintf(format,"/%%.%ds ",ifin-ideb-1) ;
sprintf(fontcour,format,&font[ideb+1]) ;
if (strcmp("/new century schoolbook ",fontcour) == 0 ) {
sprintf(fontcour,"/NewCenturySchlbk \0") ; }
fontcour[1] = toupper(fontcour[1]) ; break ; } } }
ideb = ifin ;
for ( i = ideb + 1 ; i < strlen(font) ; i++ )
{ if (font[i] == '-') { ifin = i ; sprintf(format,"/%%.%ds ",ifin-ideb-1) ;
ilon = strlen(fontcour) ; sprintf(&fontcour[ilon],format,&font[ideb+1]) ;
fontcour[ilon+1] = toupper(fontcour[ilon+1]) ; break ; } }
ideb = ifin ;
for ( i = ideb + 1 ; i < strlen(font) ; i++ )
{ if (font[i] == '-') { ifin = i ; sprintf(format,"%.1s",&font[ideb+1]) ;
if (format[0] == 'o') { sprintf(&fontcour[strlen(fontcour)],"/Oblique ") ;
} else { if (format[0] == 'i') { sprintf(&fontcour[strlen(fontcour)],"/Italic ") ;
} else { if (format[0] == 'r') { sprintf(&fontcour[strlen(fontcour)],"/ ") ;
} else { sprintf(&fontcour[strlen(fontcour)],"/ ") ; } } } break ; } }
ideb = ifin ; ilon = 0 ;
for ( i = ideb + 1 ; i < strlen(font) ; i++ )
{ if (font[i] == '-') { ilon = ilon + 1 ;
if (ilon < 7) { ideb = i ; ifin = i ;
} else { ifin = i ;
sprintf(format,"(%%.%ds)",ifin-ideb-1) ;
sprintf(mp,format,&font[ideb+1]) ;
if (strcmp("(p)",mp) != 0 ) {
sprintf(mp,"(m)") ; }
break ; } } }
sprintf(&fontcour[strlen(fontcour)],"%d %d %s charge\n",mesure.ascent,
mesure.rbearing-mesure.lbearing,mp) ;
}
else
{
printf("VuchargerLaFonte: fonte indisponible => fonte inchangee\n");
}
/* Traitement du postscript */
if (lasopsc > 0){
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
if (lasopsc < 3){
fprintf(fpo,fontcour) ;
}
else{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],fontcour) ;
}
}
}


void VuChargerFonte( int nufont )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : charger la fonte nufont pour les traces
// -----
//
// entree :
// --------
// nufont : numero de la fonte dans X
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
if( nufont < 0 || nufont >= nbfontes )
{
cout << "Erreur ChargerFonte nufont=" << nufont << " incorrect" << endl;
return;
}

if( nofoca == nufont ) return;

//la fonte de caracteres choisie est chargee
nofoca = nufont;

//en sortie:
//nplaca largeur en pixels des caracteres de cette fonte
//nphaca hauteur en pixels des caracteres de cette fonte
VuChargerLaFonte( nofoca, listfonts[nofoca], nplaca, nphaca );

//affichage des caracteristiques de la fonte effectivement chargee
//cout << "Nom de la FONTE " << nofoca << " chargee="
// << listfonts[nofoca] << endl;
//cout << "Caracteres de " << nplaca << " pixels en largeur et "
// << nphaca << " pixels en hauteur" << endl;
}


void VuChoisirFonte( int lhpxfonte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : CHOISIR ET CHARGER UNE FONTE CORRECTE POUR Vu
// -----
//
// ENTREES:
// --------
// lhpxfonte: LA HAUTEUR LA PLUS PROCHE EN PIXELS DE LA FONTE A CHARGER
// DE PREFERENCE GRASSE et courier et roman
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int k, l, lecapx, nufont;

lecapx = 10000;
for ( k=0; k<nbfontes; k++ )
{
l = lhpxfonte - lhpxfo[k];
if ( l < 0 ) l=-l;

if ( l < lecapx )
{
nufont = k; // la fonte aura lhpxfonte pixels en hauteur
lecapx = l;
}
else if( l == lecapx
&& strstr( listfonts[k], "-adobe-" ) != NULL
&& strstr( listfonts[k], "-courier-" ) != NULL
&& strstr( listfonts[k], "-bold-" ) != NULL
&& strstr( listfonts[k], "-r-" ) != NULL )
nufont = k;
}

// CHARGEMENT DE LA FONTE TROUVEE
VuChargerFonte( nufont );
}

void VuEpaisseur( int epais )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : IMPOSER le nombre d'epaisseurs des traits

ENTREE :
--------
epais : nombre d'epaisseurs des traces a venir
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
XGCValues gcvalues;

gcvalues.line_width = epais;
XChangeGC(display_vu, gc_vu, GCLineWidth, &gcvalues);

/* Traitement du postscript :
destination : TEMPORAIRE.EPS si l'instruction est de type dessin
: chaine si l'instruction correspond a un menu */
if ( lasopsc > 0){
iep = 1 ;
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
if (lasopsc < 3){
fprintf(fpo,"%2i epais\n" , epais) ;
}
else{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],
"%2i epais\n" , epais) ;
}
}
}


void VuTypeTrait( int type )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : IMPOSER le type de trace d'un trait
//
// ENTREE :
// --------
// type : 0 LIGNE CONTINUE
// 1 LIGNE TIRETEE
// 2 LIGNE TIRETEE D'EPAISSEUR DOUBLE
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XGCValues gcvalues;

switch (type)
{
case 0 : { gcvalues.line_style = LineSolid; break; }
case 1 : { gcvalues.line_style = LineOnOffDash; break; }
default : { gcvalues.line_style = LineDoubleDash; break; }
}
XChangeGC(display_vu, gc_vu, GCLineStyle, &gcvalues);

/* Traitement du postscript :
destination : TEMPORAIRE.EPS si l'instruction est de type dessin
: chaine si l'instruction correspond a un menu */
if ( lasopsc > 0){
ity = 1 ;
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
sprintf(buf,"%2i typet\n",type) ;
if (lasopsc < 3){
fprintf(fpo,buf) ;
}
else{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}


void VuOuvrir( char *titre_fen_vu,
int lafepx, int hafepx, int nphfco )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : INITIALISER et OUVRIR la fenetre graphique X
//------ DEFINIR la largeur et hauteur PIXELS de la FENETRE A OUVRIR
// a partir du coin superieur gauche de l'ecran
// DEFINIR la palette des couleurs
// Recuperer les caracteristiques des fontes de caracteres
// CHARGER la fonte de hauteur pixels precisee
// ENTREES :
// ---------
// titre_fen_vu : titre de la fenetre Vu
// lafepx : nombre de pixels de la largeur de la fenetre a ouvrir
// hafepx : nombre de pixels de la hauteur de la fenetre a ouvrir
// nphfco : nombre de pixels en hauteur de la fonte de caracteres X a charger
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int x, y, i, j, k, nbcafo;
char *car;
char data[7];
int ntab[32];
unsigned int largeurpx, hauteurpx, bordurepx;
XGCValues gcvalues;

//Initialisation du Display et de l'ecran X sont deja faits
//===================================================

// Creation de la fenetre avec lapxfe et lhpxfe pixels en largeur et hauteur
x = (int) X_COIN_FENETRE;
y = (int) Y_COIN_FENETRE;

lapxfe = lafepx;
lhpxfe = hafepx;
xpixels = lafepx; // pour le PostScript
ypixels = hafepx;

largeurpx = (unsigned int) lafepx;
hauteurpx = (unsigned int) hafepx;
bordurepx = (unsigned int) 5 ;

fenetre_vu0 = RootWindow( display_vu, ecran_vu );
visual = DefaultVisual( display_vu, ecran_vu );
visual_class = visual->c_class; /* c_class en C++ et class en C */
cout << "Visual_classe = ";
nbcolo = visual->map_entries;

relance:
switch ( visual_class )
{
/*-----------------------------------------*/
/* Les 3 CLASSES avec PALETTES MODIFIABLES */
/*-----------------------------------------*/

case PseudoColor: /* Classe des ecrans avec 8 plans ecrans couleurs => 256 couleurs */
/*--------------- Les palettes colormap sont en Lecture/ecriture non partageables */
/* Le no couleur Vu = celui de la palette physique */
/* Tout pixel de l'ecran a un no de couleur dans la palette */
/* auquel correspond dans la palette 3 valeurs rouge vert bleu tracees */
{
cout << "PseudoColor" << endl;
/* Creation d'une nouvelle resource X de type colormap aupres du serveur X */
/* toutes les cellules de la colormap doivent etre allouees et reservees au
client X c-a-d qu'il est le seul a en disposer tant en lecture qu'en ecriture */
color_map = XCreateColormap ( display_vu, fenetre_vu0, visual, AllocAll );

/* le nombre de couleurs de la palette colormap */
nbcolo = visual->map_entries;
if (DefaultDepth(display_vu, ecran_vu) == 1)
{
/* Black and white: tout ce qui n'est pas noir est blanc */
/* La palette est blanche */
for (i = 1; i < nbcolo; i++)
{ /* au dela 0 toutes les couleurs sont blanches */
red[i] =1.0;
green[i]=1.0;
blue[i] =1.0;
}
}
else
{ /* Il y a nbcolo>2 couleurs dans la palette
Remplissage de red green blue a partir de la palette par defaut
qui est partageable donc necessairement en lecture seule */
color_map0 = DefaultColormap(display_vu, ecran_vu);
if ( nbcolo > CMAPSIZE ) nbcolo = CMAPSIZE;
VuColormapToRGB( color_map0, red, green, blue, nbcolo);
}

// le nombre de palettes de couleurs disponibles dans Vu
nbpacl = MAXPACL;

/* stockage des red green blue dans color_map la palette courante Read/Write */
n1core = (int) 0 ; /* Premiere couleur reservee (non modifiee) */
/* Derniere couleur reservee = derniere couleur elementaire */
n1coel = (int) 0 ; /* Premiere couleur elementaire pour le noir */
/* Ici aucune couleur reservee a part les couleurs elementaires*/

/* Definition des couleurs imposees pour toutes les palettes */
VuCouleursImposees( n1coel, ndcoel, red, green, blue );

/* Stockage de ces couleurs dans la palette colormap */
VuRGBtoColormap(visual_class, nbcolo,
red, green, blue, norgb, color_map);

/* le numero des couleurs reservees 0 a ndcore et modifiables ndcore + 1 a nbcolo-1 */
ndcore = ndcoel ;
n1coul = ndcore + (int) 1 ;
ndcoul = (int) nbcolo-1 ;
break;
}

case GrayScale : /* Classe des ecrans gris avec 8 plans => 256 niveaux de gris */
/*-------------- Les palettes colormap sont en Lecture/ecriture non partageables */
/* Le no couleur Vu = celui de la palette physique */
/* Tout pixel de l'ecran a un no de couleur dans la palette */
/* auquel correspond dans la palette 3 valeurs rouge vert bleu tracees */
/* Par exemple si rouge vert bleu sont connus alors */
/* intensite du gris = = 0.3*rouge + 0.59*vert + 0.11*bleu */
/* donne une bonne valeur */
{
cout << "GrayScale ATTENTION: NON teste dans Vu\n";
color_map = DefaultColormap( display_vu, ecran_vu );
nbcolo = visual->map_entries; /* nbcolo = 256; */

/* stockage des red green blue dans color_map la palette courante Read/Write */
n1core = (int) 0 ; /* Premiere couleur reservee (non modifiee) */
/* Derniere couleur reservee = derniere couleur elementaire */
n1coel = (int) 0 ; /* Premiere couleur elementaire pour le noir */
/* Ici aucune couleur reservee a part les couleurs elementaires*/
/* Definition des couleurs imposees pour toutes les palettes */
VuCouleursImposees( n1coel, ndcoel, red, green, blue );

/* le numero des couleurs reservees et modifiables */
ndcoel = (int) 1 ;
ndcore = (int) 15 ;
n1coul = (int) 16 ;
ndcoul = (int) 255 ;

// le nombre de palettes de couleurs disponibles dans Vu
nbpacl = MAXPACL;
break;
}

case DirectColor : /* Classe des ecrans avec >8 plans ecrans couleurs => >256 couleurs */
/*--------------- Les palettes colormap sont en Lecture/ecriture non partageables */
/* Tout pixel de l'ecran a un no de couleur dans la palette physique */
/* qui se decompose en 3 valeurs rouge vert bleu qui */
/* donnent le RVB trace par une fonction du type */
/* no palette= rouge + vert*2**nbplansrouge + bleu*2**(nbplansrouge+vert) */
{
cout << "DirectColor ATTENTION: NON teste dans Vu\n";
cout << "Essai de remplacer DirectColor par PseudoColor...\n";
visual->c_class=PseudoColor;
goto relance;
}

/*----------------------------------------------------------------------*/
/* Les 3 CLASSES avec une PALETTE NON MODIFIABLE (C'est celle du serveur X) */
/*----------------------------------------------------------------------*/

case StaticColor: /* idem PseudoColor: Classe ecrans avec 8 plans ecrans couleurs=>256 couleurs */
/*--------------- La palette colormap est en Lecture seule, partageable, non modifiable */
/* Le no couleur Vu = celui de la palette physique */
/* Tout pixel de l'ecran a un no de couleur dans la palette */
/* auquel correspond dans la palette 3 valeurs rouge vert bleu tracees */
{
cout << "StaticColor ATTENTION: NON teste dans Vu\n";
color_map = DefaultColormap( display_vu, ecran_vu );
nbcolo = visual->map_entries;
VuColormapToRGB( color_map, red, green, blue, nbcolo);
/* le numero des couleurs reservees et modifiables */
n1core = (int) 0 ;
n1coel = (int) 0 ;
ndcoel = (int) 1 ;
ndcore = (int) 1 ;
n1coul = (int) 1 ;
ndcoul = (int) 1 ;

// le nombre de palettes de couleurs disponibles dans Vu
nbpacl = 1;
break;
}

case StaticGray : /* idem GrayScale mais avec une colormap fixe */
/*--------------- La palette colormap est en Lecture seule, partageable, non modifiable */
/* Le no couleur Vu = celui de la palette physique */
/* Tout pixel de l'ecran a un no de gris dans la palette => trace */
{
cout << "StaticGray ATTENTION: NON teste dans Vu\n";
color_map = DefaultColormap( display_vu, ecran_vu );
nbcolo = 2;
/* le numero des couleurs reservees et modifiables */
n1core = (int) 0 ;
n1coel = (int) 0 ;
ndcoel = (int) 1 ;
ndcore = (int) 1 ;
n1coul = (int) 1 ;
ndcoul = (int) 1 ;

// le nombre de palettes de couleurs disponibles dans Vu
nbpacl = 1;
break;
}

case TrueColor : /* Classe des ecrans avec >8 plans ecrans couleurs => >256 couleurs */
/*--------------- La palette colormap est en Lecture seule partageable */
/* Le no couleur Vu est different de celui de la palette physique */
/* Tout pixel de l'ecran a un no de couleur dans la palette physique */
/* ce no se decompose en 3 valeurs rouge vert bleu qui */
/* donnent le RVB trace par une fonction du type */
/* no palette= rouge + vert*2**nbplansrouge + bleu*2**(nbplansrouge+vert) */
{
cout << "TrueColor\n";
/* Palette de couleurs en lecture seule donc partageable */
/* Recuperation de la colormap du serveur X */
color_map = DefaultColormap( display_vu, ecran_vu );

/* le nombre de couleurs de la palette Vu est celui du stockage de red,...*/
/* Attention: nbcolo n'est plus ensuite le nombre de couleurs de la palette physique! */
nbcolo = 256;

// le nombre de palettes de couleurs disponibles dans Vu
nbpacl = MAXPACL;

/* Il y a nbcolo>2 couleurs dans la palette Vu
Remplissage de red green blue a partir de la palette par defaut
qui est partageable donc necessairement en lecture seule */

/* Initialisation des red green blue du C */
n1core = (int) 0 ; /* Premiere couleur reservee (non modifiee) */
/* Derniere couleur reservee = derniere couleur elementaire */
n1coel = (int) 0 ; /* Premiere couleur elementaire pour le noir */
/* Ici aucune couleur reservee a part les couleurs elementaires*/

/* Definition des couleurs imposees */
VuCouleursImposees( n1coel, ndcoel, red, green, blue );

/* le numero des couleurs reservees 0 a ndcore et modifiables ndcore+1 a nbcolo-1 */
ndcore = ndcoel ;
n1coul = ndcore + (int) 1 ;
ndcoul = (int) nbcolo-1 ;

/* les couleurs Vu modifiables sont momentanement grises */
for (i = n1coul; i <= ndcoul; i++)
{ /* au dela de ndcore toutes les couleurs sont grises */
red[i] = (R) i / (R) ndcoul;
green[i]= (R) i / (R) ndcoul;
blue[i] = (R) i / (R) ndcoul;
}

/* les nbcolo couleurs sont allouees dans la colormap partageable */
/* le norgb[i] de chaque couleur i de la palette Vu est celui de la couleur
la plus approchante dans la palette physique */
VuRGBtoColormap( visual_class, nbcolo,
red, green, blue, norgb, color_map);
break;
}
}

/* Traitement quelquesoit la classe */
/*----------------------------------*/
cout << "Palette X initiale de " << visual->map_entries << " couleurs\n";
cout << "Palette Vu utile de " << nbcolo << " couleurs\n";
cout << "Nombre de plans des couleurs = " << DefaultDepth(display_vu,ecran_vu) << endl;
nobackground = 0;
background = (unsigned long) BlackPixel(display_vu,ecran_vu);
noforeground = 1;
foreground = (unsigned long) WhitePixel(display_vu,ecran_vu);

attributs_vu.background_pixel = background;
attributs_vu.border_pixel = foreground;
attributs_vu.backing_store = Always;
attributs_vu.colormap = color_map;

/*==========================*/
/* Creation de la fenetre X */
/*==========================*/
fenetre_vu = XCreateWindow( display_vu,
fenetre_vu0,
x, y, largeurpx, hauteurpx, bordurepx,
CopyFromParent,
InputOutput,
visual,
CWBackPixel | CWBorderPixel | CWBackingStore | CWColormap,
&attributs_vu);
//cout << "Creation de fenetre_vu=" << fenetre_vu << endl;

strcpy(data,titre_fen_vu); // le nouveau titre de la fenetre
XChangeProperty( display_vu, fenetre_vu, XA_WM_NAME, XA_STRING, 8,
PropModeReplace,(unsigned char *) data, strlen(titre_fen_vu) );

// les seuls EVENEMENTS qui interessent Vu sont indiques AU DESSOUS
// 18/ 1/1999 attributs_vu.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
// 10/10/2000 ajout de | ButtonMotionMask | ButtonReleaseMask
// 19/01/2001 ajout de | PointerMotionMask pour tout deplacement du pointeur de la souris
// sans bouton enfonce ou relache

attributs_vu.event_mask = VisibilityChangeMask | StructureNotifyMask
| ExposureMask | KeyPressMask
| ButtonPressMask | ButtonReleaseMask
| ButtonMotionMask | PointerMotionMask;

XChangeWindowAttributes( display_vu, fenetre_vu,
CWEventMask, &attributs_vu);

XMapWindow(display_vu, fenetre_vu); /* la fenetre devient visible */

//Pas de trace PostScript pour commencer
lasopsc = 0;
//cout << "Pas de PostScript au depart\n";

/*-----------------------------*/
/* Le traitement des fontes */
/*-----------------------------*/
//cout << "Traitement des fontes X\n";

listfonts = XListFonts (display_vu, "*adobe*", 1, &nbfontes);
if ( nbfontes != 0 )
font_id = XLoadFont (display_vu, *listfonts);
else
{
cout << "AUCUNE FONTE X N'EST DISPONIBLE!\n";
exit(1);
}

gcvalues.foreground = foreground;
gcvalues.background = background;
gcvalues.function = GXcopy;
gcvalues.font = font_id;
gc_vu = XCreateGC( display_vu,
fenetre_vu,
GCForeground | GCBackground | GCFunction | GCFont,
&gcvalues );
XSetFillRule( display_vu,gc_vu,WindingRule );

XSetArcMode( display_vu,gc_vu,ArcChord );

listfonts = XListFonts (display_vu, "*adobe*", MAXFONTS, &nbfontes);

/* si necessaire, on prend un filtre plus large */
if (nbfontes == 0)
listfonts = XListFonts (display_vu, "*", MAXFONTS, &nbfontes);

cout << "Nombre de fontes X disponibles = " << nbfontes << endl;

// analyse des noms des fontes
for ( k=0; k<nbfontes; k++ )
{
// le nombre de caracteres du nom de la fonte k
nbcafo = strlen( listfonts[k] );

// DECOUPE DU NOM DE LA FONTE EN CHAMPS SEPARES PAR '-'
for (i=0; i<32; i++ )
ntab[i] = nbcafo;

// le nombre ntab[i] de champs de chaque nom de fonte
i=0;
for (j=0; j<nbcafo; j++ )
{
if ( listfonts[k][j] == '-' )
{
i = i+1;
ntab[i] = j;
}
}

// HAUTEUR en PIXELS DE CHAQUE FONTE
j = ntab[8]-ntab[7]-1;
if ( j<1 || j>3 )
{
cout << "ntab[7]=" << ntab[7] << " ntab[8]=" << ntab[8] << endl;
lhpxfo[i]=-1;
cout << "SAUT DE " << listfonts[k] << endl;
continue; // saut de la police k
}
else
lhpxfo[k] = atoi( &(listfonts[k][ntab[7]+1]) );
}

//Chargement de la fonte de hauteur nphfco pixels
VuChoisirFonte( nphfco );

// definition des traits initiaux
nbepai = 1; // une epaisseur en plus
VuEpaisseur( nbepai );
//cout << "Epaisseur des traits=" << nbepai << endl;

notytr = 0; // trace de trait continu
VuTypeTrait( notytr );
//cout << "Type de trace des traits=" << notytr << endl;

//Ajuster la taille des boutons des menus
larginvite = lapxfe;
if( lapxfe > 1100 )
{
largbouton = 125; // definition ecran 1280 x 1024
hautbouton = 24;
nbepbordbouton = 2;
hauttexte = 16;
decaltexte = 4;
hautinvite = hautbouton;
}
else if( lapxfe > 900 )
{
largbouton = 100; // definition ecran 1024 x 768
hautbouton = 22;
nbepbordbouton = 2;
hauttexte = 14;
decaltexte = 4;
hautinvite = hautbouton;
}
else
{
largbouton = 90; // definition ecran 800 x 600
hautbouton = 20;
nbepbordbouton = 2;
hauttexte = 12;
decaltexte = 3;
hautinvite = hautbouton;
}
}

void VuCouleur( int icolor )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : IMPOSER pour tous les traces a venir la couleur icolor de la palette
//
// ENTREES:
// --------
// icolor : le numero de la couleur de trace dans la palette Vu actuelle
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
unsigned long colour;

// indirection necessaire pour traiter a la fois PseudoColor et TrueColor
// colour est le numero de la couleur icolor dans la palette physique de Vu
noforeground = icolor;
colour = norgb[icolor];
foreground = colour;
XSetForeground(display_vu, gc_vu, colour);

// Traitement du postscript :
// counb est ramenee sur [0,1] suivant la palette utilisee
// counb = -1 si icolor est une des couleurs non modifiable de la palette
if (lasopsc > 0)
{
if (icolorm != icolor)
{
icolorm = icolor ;
if (nbrcon > 0)
{
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
courgb[0] = red[icolor] ;
courgb[1] = green[icolor] ;
courgb[2] = blue[icolor] ;
if (icolor < n1coul)
{
counb = -1 ;
}
else
{
if (palcourc == 2)
{
/* icolor varie sur palette de 6 couleurs */
counb = ( (icolor-n1coul) % 6 ) / 5.0 ;
}
else
{
if (palcourc == 12)
{
/* icolor varie sur palette de 10 couleurs */
counb = ( (icolor-n1coul) % 10 ) / 9.0 ;
}
else
{
/* icolor varie sur palette totale */
counb = ((R) (ndcoul - icolor)) / (ndcoul - n1coul) ;
}
}
}
}
}
}

void VuPostscript( int lasops )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : IMPOSER la nouvelle option de sortie du trace du maillage en POSTSCRIPT
A NE PAS APPELER DIRECTEMENT LORSQU'ON UTILISE Vu
==========================
ENTREE :
---------
lasops : DEMANDE OU NON DE SORTIE DU TRACE DU MAILLAGE EN POSTSCRIPT
0 : PAS DE SORTIE POSTSCRIPT
NON 0 : SORTIE DU TRACE EN POSTSCRIPT
1 trace normal
2 trace normal avec menu
3 ... 10 trace dans les differents menus
-3 ...-10 effacement des differents menus
11 12 trace menu qualites ou histos (resp 1 ou 2)
-11 -12 effacement menu qualites ou histos (resp 1 ou 2)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR : DOURSAT CHRISTOPHE UPMC ANALYSE NUMERIQUE PARIS JUIN 1994
12345X7...................................................012345678*/
{
int i ;
/*int j;*/
/*char nom[3] ;*/

/* Traitement du postscript */

/* ouverture du postscript */
if ( lasops > 0 && lasopsc == 0 ) {
lasopsc = lasops ;
if (fpo != NULL) {
fclose(fpo) ;
fpo = NULL ;
}
if ( modepsc != 0 ){
if ((fpo = fopen("TEMPORAIRE.QUA","r"))!=NULL) {
fclose(fpo) ;
fpo = NULL ;
remove("TEMPORAIRE.QUA") ;
}
}
if ((fpo = fopen("TEMPORAIRE.EPS","w"))==NULL) {
printf ("Erreur de creation de fichier...Sortie immediate\n") ;
exit (1);
}
if ( modepsc != 0 ){
for (i = 0; i < 8 ; i++) chaine[i] = (char*) calloc(longchaine[i],sizeof(char)) ;
}
nbrcon = 0 ;
concat[0] = '\0' ;
iTe = 0 ; iFa = 0 ; ity = 0 ; iep = 0 ; iPo = 0 ;
ire = 0 ; iRe = 0 ; iel = 0 ; iEl = 0 ; iFP = 0 ;
}
else {
if ( lasops == 0 ) {
lasopsc = lasops ;
if (fpo != NULL) {
fprintf(fpo,concat) ;
fclose(fpo) ;
fpo = NULL ;
if ( modepsc != 0 ){
for (i = 0; i < 8 ; i++) { chaine[i] = '\0' ; free(chaine[i]) ; }
}
menu = 0 ;
}
}
else {
if ( lasops > 100) {
/* remise a zero des controles de macros */
iTe = 0 ; iFa = 0 ; ity = 0 ; iep = 0 ; iPo = 0 ;
ire = 0 ; iRe = 0 ; iel = 0 ; iEl = 0 ; iFP = 0 ;
/* effacement des differents fichiers temporaires */
if (fpo != NULL) {
fclose(fpo) ;
fpo = NULL ;
}
/* effacement du fichier temporaire des histogrammes de qualite */
if ( modepsc != 0 ){
if ((fpo = fopen("TEMPORAIRE.QUA","r"))!=NULL) {
fclose(fpo) ;
fpo = NULL ;
remove("TEMPORAIRE.QUA") ;
}
}
/* effacement du fichier temporaire postscript */
if ((fpo = fopen("TEMPORAIRE.EPS","w"))==NULL) {
printf ("Erreur de creation de fichier...Sortie immediate\n") ;
exit (1);
}
/* effacement des menus postscript */
if ( modepsc != 0 ){for (i = 0; i < 8 ; i++) *chaine[i] = '\0' ;}
lasopsc = lasopsc - 100 ;
}
else {
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
if (lasops < -1) {
/* effacement du menu correspondant */
lasopsc = Max(lasops,-11) ;
if ( modepsc != 0 ){*chaine[-lasopsc-4] = '\0' ;}
}
else{
lasopsc = Min(lasops,11) ;
if (lasopsc == 2) menu = 1 ;
}
}
}
}
}


void VuEffacer()
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : EFFACER la fenetre actuelle et tracer la fenetre avec la couleur de fond
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XClearWindow( display_vu, fenetre_vu );
XFlush( display_vu );

// Traitement du postscript :
// 101 ou 102 effacement en mode sans (1) ou avec (2) menus
if (lasopsc > 0)
{
lasopsc = 100 + lasopsc ;
VuPostscript(lasopsc) ;
}
}
 

void VuCouleurFond( int icolor )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : IMPOSER une couleur comme FOND de FENETRE
// ----- EFFACER LA FENETRE et la retracer avec la nouvelle couleur de fond
//
// ENTREES :
// ---------
// icolor : le numero dans la palette Vu de la couleur du fond
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// indirection necessaire pour traiter a la fois PseudoColor et TrueColor
// background est le numero de la couleur icolor Vu dans la palette physique
nobackground = icolor;
background = norgb[icolor];

//stockage de la couleur de fond
attributs_vu.background_pixel = background;
XChangeWindowAttributes( display_vu, fenetre_vu,
CWBackPixel | CWBorderPixel | CWBackingStore | CWColormap,
&attributs_vu);
XSetBackground( display_vu, gc_vu, background );
XSetWindowBackground( display_vu, fenetre_vu, background );

VuEffacer(); //Efface l'ecran qui prend la nouvelle couleur de fond
}


void VuNbPxTexte( char *texte, int & nbpxla, int & nbpxha )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : Retrouver les dimensions en pixels d'une chaine de caracteres

ENTREES :
---------
texte : la chaine de caracteres

SORTIES :
---------
nbpxla : le nombre de pixels de la largeur de la chaine de caracteres
nbpxha : le nombre de pixels de la hauteur de la chaine de caracteres
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
int direction, length ;

length = nudcnb( texte );
XTextExtents( struc_police , texte , length , &direction ,
&ascent_pol , &descent_pol , &mesure ) ;
nbpxla = mesure.width ;
nbpxha = mesure.ascent + mesure.descent ;
}

void VuFermer( void )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : FERMER la fenetre Vu
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
/* XUnmapWindow( display_vu, fenetre_vu); la fenetre devient invisible */
XFreeGC( display_vu, gc_vu );
XFreeColormap( display_vu, color_map );
/* XDestroyWindow( display_vu, fenetre_vu ); */
XCloseDisplay( display_vu );
}

void VuPxFenetre( int & lapxfe, int & lhpxfe )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : RECUPERER le nombre de pixels de la largeur et hauteur de
// ----- la FENETRE ACTUELLE
//
// SORTIES :
// ---------
// lapxfe : nombre de pixels de la largeur de la fenetre
// lhpxfe : nombre de pixels de la hauteur de la fenetre
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XWindowAttributes wattrib;

XGetWindowAttributes(display_vu, fenetre_vu, &wattrib);
lapxfe = wattrib.width;
lhpxfe = wattrib.height;
}

void MemoirePx::VuCombinerFenetreDansMemoirePx( int GX ,
XPoint xyfen, unsigned int largfen, unsigned int hautfen,//source
XPoint xympx ) //destination
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Combiner les pixels de la fenetre_vu dans MemoirePx selon le code GX
//----- a partir de xyfen coin superieur gauche de fenetre_vu
// dans MemoirePx.mempx a partir du coin superieur gauche xympx
//
// Les pixels du pixmap mempx (src) et la fenetre_vu (dst) se combinent selon
// la valeur de GX qui peut prendre les valeurs suivantes:
//
// GXclear 0x0 <=> 0
// GXand 0x1 <=> src AND dst src comme source
// GXandReverse 0x2 <=> src AND (NOT dst) dst comme destination
// GXcopy 0x3 <=> src
// GXandInverted 0x4 <=> (NOT src) AND dst
// GXnoop 0x5 <=> dst
// GXxor 0x6 <=> src XOR dst (XOR ou exclusif) (2 fois redonne obj)
// GXor 0x7 <=> src OR dst
// GXnor 0x8 <=> (NOT src) AND (NOT dst)
// GXequiv 0x9 <=> (NOT src) XOR dst
// GXinvert 0xa <=> (NOT dst)
// GXorReverse 0xb <=> src OR (NOT dst)
// GXcopyInverted 0xc <=> (NOT src)
// GXorInverted 0xd <=> (NOT src) OR dst
// GXnand 0xe <=> (NOT src) AND (NOT dst)
// GXset 0xf <=> 1
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// Combinaison de la fenetre_vu dans mempx
XSetFunction( display_vu, gc_vu, GX ); //activation du mode de combinaison des pixels
XCopyArea( display_vu, fenetre_vu, mempx, gc_vu,
(int) xyfen.x, (int) xyfen.y, largfen, hautfen, //source
(int) xympx.x, (int)xympx.y ); //destination
XSetFunction( display_vu, gc_vu, GXcopy ); //restauration du mode normal
}

void MemoirePx::VuCombinerMemoirePxDansFenetre( int GX,
XPoint xympx, unsigned int largmpx, unsigned int hautmpx,//source
XPoint xyfen ) //destination
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Combiner les pixels de MemoirePx dans la fenetre_vu selon le code GX
//----- a partir de xympx coin superieur gauche de MemoirePx.mempx
// avec fenetre_vu a partir du coin superieur gauche xyfen
//
// Les pixels du pixmap mempx (src) et la fenetre_vu (dst) se combinent selon
// la valeur de GX qui peut prendre les valeurs suivantes:
//
// GXclear 0x0 <=> 0
// GXand 0x1 <=> src AND dst src comme source
// GXandReverse 0x2 <=> src AND (NOT dst) dst comme destination
// GXcopy 0x3 <=> src
// GXandInverted 0x4 <=> (NOT src) AND dst
// GXnoop 0x5 <=> dst
// GXxor 0x6 <=> src XOR dst (XOR ou exclusif) (2 fois redonne obj)
// GXor 0x7 <=> src OR dst
// GXnor 0x8 <=> (NOT src) AND (NOT dst)
// GXequiv 0x9 <=> (NOT src) XOR dst
// GXinvert 0xa <=> (NOT dst)
// GXorReverse 0xb <=> src OR (NOT dst)
// GXcopyInverted 0xc <=> (NOT src)
// GXorInverted 0xd <=> (NOT src) OR dst
// GXnand 0xe <=> (NOT src) AND (NOT dst)
// GXset 0xf <=> 1
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XSetFunction( display_vu, gc_vu, GX ); //activation du mode de combinaison des pixels
XCopyArea( display_vu, mempx, fenetre_vu, gc_vu,
(int) xympx.x, (int) xympx.y, largmpx, hautmpx, // source
(int) xyfen.x, (int) xyfen.y ); // destination
XSetFunction( display_vu, gc_vu, GXcopy ); //restauration du mode normal
}

void MemoirePx::VuTexte( XPoint xy, char *texte )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER un texte a partir du pixel xy de la fenetre
// Attention: xy est ici le coin du TEXTE en BAS et A GAUCHE
//
// ENTREES:
// --------
// xy.x : le numero du pixel en largeur du debut de la chaine
// xy.y : le numero du pixel en hauteur du debut de la chaine
// texte : la chaine de caracteres a tracer
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int length;

if( xy.x <= minint ) return;
if( xy.y <= minint ) return;

length = nudcnb( texte );
XDrawString(display_vu, mempx, gc_vu, xy.x, xy.y, texte, length);

/* Traitement du postscript */
if (lasopsc > 0)
{
iTe = 1 ;
if (nbrcon > 0)
{
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
sprintf(format,"(%%.%ds) %%6i %%6i %%4.2f %%4.2f %%4.2f 0.00 T\n",length) ;
if (lasopsc < 3)
{
fprintf(fpo,format,texte,
xy.x, ypixels-xy.y,
courgb[0],courgb[1],courgb[2]) ;
}
else
{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],
format,texte,
xy.x, ypixels-xy.y,
courgb[0],courgb[1],courgb[2]) ;
}
}
}

void MemoirePx::VuSymbole( XPoint xy, char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le symbole texte avec la couleur courante
// ----- a partir du point xy en coordonnees pixel
// la chaine est decalee d'un demi caractere vers le bas et a gauche
//
// entree :
// --------
// xy.x : abscisse objet du symbole
// xy.y : ordonnee objet du symbole
// texte : la chaine de caracteres servant de symbole
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// Translation pour centrer le symbole en fonction de la fonte
xy.x -= nplaca/2 + 1;
xy.y += nphaca/2 - 2;

// Trace du texte
VuTexte( xy, texte );
}


void MemoirePx::VuEntier( XPoint xy, int entier )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de l'entier avec la couleur nc
// ----- a partir du point xy en coordonnees pixel
//
// entree :
// --------
// xy.x : abscisse objet des caracteres de la valeur de l'entier
// xy.y : ordonnee objet des caracteres de la valeur de l'entier
// entier : entier dont la valeur doit etre tracee
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbcar;
char texte[12];

// le nombre de caracteres de l'entier
itoa( entier, nbcar, texte );

// le trace de la chaine de caracteres
VuTexte( xy, texte );
}


void MemoirePx::VuReel( XPoint xy, R vR, int nbchif10 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de vR avec la couleur nc
// ----- a partir du point (x,y) en coordonnees pixel
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// xy.x : abscisse objet des caracteres de R
// xy.y : ordonnee objet des caracteres de R
// vR : valeur Rle a tracer
// nbchif10: nombre de chiffres demandes de la partie decimale
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbcar;
char texte[26];

// les caracteres finaux de vR
rtoa( vR, nbchif10, nbcar, texte );

// le trace de la chaine de caracteres
VuTexte( xy, texte );
}


void MemoirePx::VuFace( int n, XPoint *pts )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER le remplissage du polygone defini par n points pts
//
// ENTREES:
// --------
// n : nombre de sommets du polygone
// pts : coordonnees pixels des n sommets du polygone
// Si le point 0 != point n-1 alors le polygone est referme automatiquement
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int npts, i , j;

XFillPolygon(display_vu, mempx, gc_vu, pts, n, Complex, CoordModeOrigin);

// Traitement du postscript :
// instruction ps : F
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu

if (lasopsc > 0){
npts = n;
iFa = 1 ;
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
for (j = 0 ; j <= npts / 16 ; j++)
{
for (i = j * 16 ; i <= Min( npts-1 , (j+1) * 16 -1 ) ; i++)
sprintf(&buf[strlen(buf)], "%6i %6i " , pts[i].x , ypixels-pts[i].y) ;
if (j == npts / 16)
{
if (counb != -1)
{
sprintf(&buf[strlen(buf)],"%3i %4.2f %4.2f %4.2f %4.2f F\n",
npts,courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&buf[strlen(buf)],"%3i %4.2f %4.2f %4.2f 1.00 F\n",
npts,courgb[0],courgb[1],courgb[2]) ;
}
}
else
{
sprintf(&buf[strlen(buf)],"\n") ;
}
if (lasopsc < 3)
{
fprintf(fpo,buf) ;
}
else
{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
buf[0] = '\0' ;
}
}
}


void MemoirePx::VuTrait( XPoint xy1, XPoint xy2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER du point (x1,y1) PIXELS au point (x2,y2) PIXELS
//
// ENTREES :
// ---------
// xy1 : coordonnees pixels du point INITIAL (ORIGINE coin superieur gauche)
// xy2 : coordonnees pixels du point FINAL (ORIGINE coin superieur gauche)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XDrawLine( display_vu, mempx, gc_vu, xy1.x, xy1.y, xy2.x, xy2.y );

// Traitement du postscript :
// instruction ps : S
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu
if (lasopsc > 0){
buf[0] = '\0' ;
if (lasopsc < 3){
/* On essaye de rendre plus compacts les traces ps de segments consecutifs
qui sont stockes dans concat. */
if (nbrcon == 0)
{
nbrcon = 1 ;
xinic = xy1.x ;
yinic = xy1.y ;
xcouc = xy2.x ;
ycouc = xy2.y ;
if (counb != -1)
{
sprintf(&concat[0],"%6i %6i %6i %6i %3i %4.2f %4.2f %4.2f %4.2f S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
nbrcon,courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&concat[0],"%6i %6i %6i %6i %3i %4.2f %4.2f %4.2f 0.00 S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
nbrcon,courgb[0],courgb[1],courgb[2]) ;
}
}
else
{
if (xy1.x == xcouc && xy1.y == ycouc)
{
nbrcon++ ;
if (xy2.x == xinic && xy2.y == yinic){
iPo = 1 ;
/* la suite de segments est en fait un contour ferme */
if (counb != -1)
{
sprintf(&concat[strlen(concat)-26],"%3i %4.2f %4.2f %4.2f %4.2f P\n",
nbrcon,courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&concat[strlen(concat)-26],"%3i %4.2f %4.2f %4.2f 0.00 P\n",
nbrcon,courgb[0],courgb[1],courgb[2]) ;
}
// ecriture de concat
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
else
{
if (nbrcon % 16 == 0)
/* concat est deja rempli, on le vide */
{
sprintf(&concat[strlen(concat)-26],"\n\0") ;
fprintf(fpo,concat) ;
concat[0] = '\0' ;
sprintf(&concat[0]," ") ;
}
if (counb != -1)
{
sprintf(&concat[strlen(concat)-26],"%6i %6i %3i %4.2f %4.2f %4.2f %4.2f S\n",
xy2.x, ypixels-xy2.y,nbrcon,courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&concat[strlen(concat)-26],"%6i %6i %3i %4.2f %4.2f %4.2f 0.00 S\n",
xy2.x, ypixels-xy2.y,nbrcon,courgb[0],courgb[1],courgb[2]) ;
}
xcouc = xy2.x ;
ycouc = xy2.y ;
}
}
else
{
// ni suite, ni fermeture d'un polygone. c'est donc un nouveau segment

fprintf(fpo,concat) ;
nbrcon = 1 ;
xinic = xy1.x ;
yinic = xy1.y ;
xcouc = xy2.x ;
ycouc = xy2.y ;
if (counb != -1) {
sprintf(&concat[0],"%6i %6i %6i %6i %3i %4.2f %4.2f %4.2f %4.2f S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
nbrcon,courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&concat[0],"%6i %6i %6i %6i %3i %4.2f %4.2f %4.2f 0.00 S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
nbrcon,courgb[0],courgb[1],courgb[2]) ;
}
}
}
}
else
{
// Pour les menus les segments sont traces en ps tels que, un par un
if (counb != -1)
{
sprintf(&buf[0],"%6i %6i %6i %6i %4.2f %4.2f %4.2f %4.2f S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
courgb[0],courgb[1],courgb[2],counb) ;
}
else
{
sprintf(&buf[0],"%6i %6i %6i %6i %4.2f %4.2f %4.2f 0.00 S\n",
xy1.x, ypixels-xy1.y, xy2.x, ypixels-xy2.y,
courgb[0],courgb[1],courgb[2]) ;
}
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}

void MemoirePx::VuTraits( int nbpoints, XPoint *points )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : TRACER les segments points(i) points(i+1) pour i=1 a nbpoints-1

ENTREES :
---------
nbpoints : nombre de points sommets des traits
points : coordonnees pixels (INTEGER*2 !) des nbpoints points
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
{
int npts, i , j;

XDrawLines( display_vu, mempx, gc_vu, points, nbpoints, CoordModeOrigin );

/* Traitement du postscript :
instruction ps : P
destination : TEMPORAIRE.EPS si l'instruction est de type dessin
: chaine si l'instruction correspond a un menu */
if (lasopsc > 0){
iPo = 1 ;
npts = nbpoints-1;
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
for (j = 0 ; j <= npts / 16 ; j++)
{
for (i = j * 16 ; i <= Min( npts-1 , (j+1) * 16 -1 ) ; i++)
sprintf(&buf[strlen(buf)], "%6i %6i " , points[i].x , ypixels-points[i].y) ;
if (j == npts / 16) {
if (counb != -1) {
sprintf(&buf[strlen(buf)],"%3i %4.2f %4.2f %4.2f %4.2f P\n",
npts,courgb[0],courgb[1],courgb[2],counb) ;
}
else {
sprintf(&buf[strlen(buf)],"%3i %4.2f %4.2f %4.2f 0.00 P\n",
npts,courgb[0],courgb[1],courgb[2]) ;
}
}
else {
sprintf(&buf[strlen(buf)],"\n") ;
}
if (lasopsc < 3) {
fprintf(fpo,buf) ;
}
else {
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
buf[0] = '\0' ;
}
}
}

char MemoirePxInvite::lire1Caractere( void )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT: RETOURNER le caractere ASCII saisi au clavier ou
// le caractere char(27) ABANDON par clic bouton 2 de la souris
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XEvent event;
KeySym *keysym; // incidence
int nb;
char buffer[16];

while ( 1 )
{
XNextEvent( display_vu, &event );
if(event.type == ButtonRelease) //Bouton enfonce et relache
{
if (event.xbutton.button == Button2) {return char(27);} //caractere Echappement
}
else if(event.type == KeyPress) //touche enfoncee et relachee sur le clavier
{
keysym = 0;
nb = XLookupString( &event.xkey, buffer, 15, keysym, NULL );
if ( nb != 0 ) return buffer[0]; //caractere dans la table ascii
}
}
}

void VuSouris( int & notypeevt, int & nbc, XPoint & pxy1 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : RETOURNER le type et les caracteristiques d'un EVENEMENT
// ----- VARIANTE de Vusouris avec en plus le cas du bouton seulement enfonce
//
// SORTIES :
// ---------
// notypeevt: = 0 Si ABANDON demande par clic du bouton 2 de la souris
// ou par frappe de la touche Echappement ou @
// = 1 Si CLIC ENFONCE et RELACHE D'UN BOUTON DE LA SOURIS => pxy1
// =-1 Si CLIC SEULEMENT ENFONCE D'UN BOUTON DE LA SOURIS => pxy1
// =-2 Si le pointeur de la souris a bouge => pxy1
// = 2 Si FRAPPE D'UN CARACTERE AU CLAVIER
// nbc : seulement actif si notypeevt est non nul
// si notypeevt=1 nbc=numero du bouton
// si notypeevt=2 nbc=numero du caractere dans la table ASCII
// pxy1 : seulement actif si notypeevt=+-1
// coordonnees pixels du point clique par rapport au coin
// superieur gauche de la fenetre
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XEvent event;
int flag;
char buffer[20];
KeySym *keysym;

notypeevt = 0;
flag = 0; //vrai

while ( !flag )
{
XNextEvent(display_vu, &event);

if( event.type == MotionNotify )
{
//Deplacement de la souris
//nombre d'evenements dans la queue
if( XEventsQueued( display_vu, QueuedAfterFlush ) <= 0 )
{
notypeevt = -2; //c'est le dernier evenement
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nbc = 1;}
else if (event.xbutton.button == Button2) {nbc = 2;}
else {nbc = 3;}
flag=1;
}
}

else if(event.type == ButtonPress)
{
//Un bouton a ete enfonce, presse et non encore relache
//nombre d'evenements dans la queue
if( XEventsQueued( display_vu, QueuedAfterFlush ) <= 0 )
{
notypeevt = -1; //c'est le dernier evenement
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nbc = 1;}
else if (event.xbutton.button == Button2) {nbc = 2;}
else {nbc = 3;}
flag=1;
}
}

else if(event.type == ButtonRelease) //Un bouton a ete relache
{
notypeevt = 1;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nbc = 1;}
else if (event.xbutton.button == Button2) {nbc = 2; notypeevt=0;}
else {nbc = 3;}
flag=1;
}

else if(event.type == KeyPress) //Une touche du clavier a ete frappee
{
notypeevt = 2;
pxy1.x = event.xkey.x;
pxy1.y = event.xkey.y;
nbc = event.xkey.keycode;
keysym = 0;
nbc = XLookupString(&event.xkey,buffer,19,keysym,NULL);
if( nbc != 0 )
{
nbc = int(buffer[0]); //codage entier du caractere
if( nbc == 27 ) {notypeevt=0;} //caractere 'Echappement' => ABANDON
if( nbc == 64 ) {notypeevt=0;} //caractere '@' => ABANDON
flag= 1;
}
}
}
}

void MemoirePxInvite::VuSourisTexte( int & notypeevt, int & nobouton, XPoint & pxy1,
char texte[] )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : RETOURNER le type et les caracteristiques d'un EVENEMENT
// ----- VARIANTE de VuSouris avec retour eventuel d'un texte ponctue par \r
//
// SORTIES :
// ---------
// notypeevt : = 0 Si ABANDON demande par clic du bouton 2 de la souris
// ou par frappe de la touche Echappement ou @
// = 1 Si CLIC ENFONCE et RELACHE D'UN BOUTON DE LA SOURIS
// =-1 Si CLIC SEULEMENT ENFONCE D'UN BOUTON DE LA SOURIS
// = 2 Si FRAPPE d'un texte fini par \r
// nobouton : seulement actif si notypeevt est non nul
// si notypeevt=1 nobouton=numero du bouton
// si notypeevt=2 nobouton=numero du caractere dans la table ASCII
// pxy1 : seulement actif si notypeevt=+-1
// coordonnees pixels du point clique par rapport au coin
// superieur gauche de la fenetre
// texte : chaine de caracteres saisie au clavier et finie par \r
// initialisee seulement si notypeevt=2
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XEvent event;
int flag;
int nbc;
KeySym *keysym;

notypeevt = 0;
flag = 0;

while ( !flag )
{
XNextEvent(display_vu, &event);

if(event.type == MotionNotify || event.type == ButtonPress) //Un bouton a ete enfonce
{
//nombre d'evenements dans la queue
if( XEventsQueued( display_vu, QueuedAfterFlush ) <= 0 )
{
//Un bouton a ete enfonce, presse et non encore relache
notypeevt = -1;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nobouton = 1;}
else if (event.xbutton.button == Button2) {nobouton = 2;}
else {nobouton = 3;}
flag=1;
}
}

else if(event.type == ButtonRelease) //Un bouton a ete relache
{
notypeevt = 1;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nobouton = 1;}
else if (event.xbutton.button == Button2) {nobouton = 2; notypeevt=0;}
else {nobouton = 3;}
flag=1;
}

else if(event.type == KeyPress) //Une touche du clavier a ete frappee
{
notypeevt = 2;
pxy1.x = event.xkey.x;
pxy1.y = event.xkey.y;
nbc = event.xkey.keycode;
keysym = 0;
nbc = XLookupString(&event.xkey,texte,19,keysym,NULL); //texte[0] est initialise
if( nbc != 0 )
{
nbc = int(texte[0]);
if( nbc == 27 ) {notypeevt=0; return;} //caractere 'Echappement' => ABANDON
if( nbc == 64 ) {notypeevt=0; return;} //caractere '@' => ABANDON
texte[1] = '\0'; //fin de chaine
lire1LigneTexte( 1, texte );
flag= 1;
}
}
}
}

void MemoirePxInvite::VuSourisXYZ( int & notypeevt, int & nobouton, XPoint & pxy1,
R3 & XYZ )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Retourne un point de R3 par frappe au clavier de X puis Y puis Z
// ---- ou les 2 coordonnees pixels pxy1 du point cliqué a la souris
//
// SORTIES :
// ---------
// notypeevt : = 0 Si ABANDON demande par clic du bouton 2 de la souris
// ou par frappe de la touche Echappement ou @
// = 1 Si CLIC ENFONCE et RELACHE D'UN BOUTON DE LA SOURIS en pxy1
// =-1 Si CLIC SEULEMENT ENFONCE D'UN BOUTON DE LA SOURIS en pxy1
// =-2 Si deplacement du pointeur de souris en pxy1
// = 2 Si FRAPPE des 3 coordonnees X Y Z du point
// nobouton : seulement actif si notypeevt est non nul
// si notypeevt=1 alors nobouton=numero du bouton
// si notypeevt=2 alors nobouton=numero du caractere dans la table ASCII
// pxy1 : seulement actif si notypeevt=+-1 et -2
// coordonnees pixels du point clique par rapport au coin
// superieur gauche de la fenetre
// XYZ : les 3 coordonnees du point frappees au clavier seulement si notypeevt=2
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XEvent event;
int flag;
int nbc;
KeySym *keysym;
char texte[80];

notypeevt = 0;
flag = 0;

while ( !flag )
{
XNextEvent(display_vu, &event);

if(event.type == MotionNotify) //Le pointeur de SOURIS a ete deplace
{
//Un bouton a ete enfonce, presse et non encore relache
//nombre d'evenements dans la queue
if( XEventsQueued( display_vu, QueuedAfterFlush ) <= 0 )
{
notypeevt = -2;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nobouton = 1;}
else if (event.xbutton.button == Button2) {nobouton = 2;}
else {nobouton = 3;}
flag=1;
}
}
else if(event.type == ButtonPress) //Un bouton a ete enfonce
{
//Un bouton a ete enfonce, presse et non encore relache
//nombre d'evenements dans la queue
if( XEventsQueued( display_vu, QueuedAfterFlush ) <= 0 )
{
notypeevt = -1;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nobouton = 1;}
else if (event.xbutton.button == Button2) {nobouton = 2;}
else {nobouton = 3;}
flag=1;
}
}

else if(event.type == ButtonRelease) //Un bouton a ete relache
{
notypeevt = 1;
pxy1.x = event.xbutton.x;
pxy1.y = event.xbutton.y;
if (event.xbutton.button == Button1) {nobouton = 1;}
else if (event.xbutton.button == Button2) {nobouton = 2; notypeevt=0;}
else {nobouton = 3;}
flag=1;
}

else if(event.type == KeyPress) //Une touche du clavier a ete frappee
{
notypeevt = 2;
pxy1.x = event.xkey.x;
pxy1.y = event.xkey.y;
nbc = event.xkey.keycode;
keysym = 0;
nbc = XLookupString(&event.xkey,texte,19,keysym,NULL); //texte[0] est initialise
if( nbc != 0 )
{
nbc = int(texte[0]);
if( nbc == 27 ) {notypeevt=0; return;} //caractere 'Echappement' => ABANDON
if( nbc == 64 ) {notypeevt=0; return;} //caractere '@' => ABANDON
texte[1] = '\0';//fin de chaine
VuInvite( "Frapper l'abscisse du POINT X" );
lire1LigneTexte( 1, texte );

//traitement du premier caractere
if( texte[0] == '@' ) {notypeevt=0; return;} //caractere '@' => ABANDON

//transformation des caracteres en R ZZ Reel = strtod( texte, endptr ); TILT
XYZ.x = atof( texte );

VuInvite( "Frapper l'ordonnee du POINT Y" );
lireR( nbc, XYZ.y );
if( nbc == -1 ) {notypeevt=0; return;} //caractere '@' => ABANDON

VuInvite( "Frapper la cote du POINT Z" );
lireR( nbc, XYZ.z );
if( nbc == -1 ) {notypeevt=0; return;} //caractere '@' => ABANDON

flag= 1;
}
}
}
}

void VuVoir(void)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : VOIR les traces encore situes dans la memoire tampon
//
// ATTENTION: 21/1/99
// Si Vuvoir est trop souvent appele
// cela entraine un lourd trafic entre X et le fenetre manager qui doit savoir
// l'empilement des fenetres pour mettre celle de Vu au dessus
// ce qui bloque certains wm tels kde fvwm ... mais pas certains autres!
// Sur ibm dec hp sun ... et toutes les fenetres sont bloquees!!!
// Pour y remedier, tous les appels de Vuvoir ont ete supprimes
// Sur hp et PC rien ne change en execution si ce n'est que c'est plus rapide
// et SURTOUT sans blocage avec kde fvwm ... sur PC
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XRaiseWindow ( display_vu,fenetre_vu );
XFlush( display_vu );
}


void VuPause( void )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : FAIRE une PAUSE jusqu'a l'entree d'un caractere au clavier
// ou un clic enfonce et relache de l'un des boutons de la souris
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int notypeevt, bouton;
XPoint pxy;

notypeevt=-1;
do
{
VuSouris( notypeevt, bouton, pxy );
}while(notypeevt<=0);
}

void MemoirePx::VuBordRectangle( XPoint pxy, int width, int height )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER les aretes du contour d'un rectangle
//
// ENTREES :
// ---------
// pxy : coordonnees pixels du coin superieur gauche
// width : largeur en pixels du rectangle
// height : hauteur en pixels du rectangle
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XDrawRectangle(display_vu, mempx, gc_vu,pxy. x, pxy.y, width, height);

// Traitement du postscript :
// instruction ps : r
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu
if (lasopsc > 0)
{
ire = 1 ;
if (nbrcon > 0)
{
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
if (counb != -1)
{
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %4.2f %4.2f %4.2f %4.2f r\n",
width, -height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2], counb) ;
}
else
{
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %4.2f %4.2f %4.2f 0.00 r\n",
width, -height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2]) ;
}
if (lasopsc < 3)
{
fprintf(fpo,buf) ;
}
else
{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}

void MemoirePx::VuRectangle( XPoint pxy, int width, int height )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER le remplissage du contour d'un rectangle
//
// ENTREES :
// pxy : coordonnees pixels du coin superieur gauche
// width : largeur en pixels du rectangle
// height : hauteur en pixels du rectangle vers le bas
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XFillRectangle( display_vu, mempx, gc_vu,
int(pxy.x), int(pxy.y), width, height );

// Traitement du postscript :
// instruction ps : R
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu */
if (lasopsc > 0)
{
iRe = 1 ;
if (nbrcon > 0)
{
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
if (counb != -1)
{
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %4.2f %4.2f %4.2f %4.2f R\n",
width, -height, pxy.x, ypixels-pxy.y,courgb[0],courgb[1],courgb[2],counb) ;
}
else {
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %4.2f %4.2f %4.2f 1.00 R\n",
width, -height, pxy.x, ypixels-pxy.y,courgb[0],courgb[1],courgb[2]) ;
}
if (lasopsc < 3){
fprintf(fpo,buf) ;
}
else{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}


void MemoirePx::VuBordArcEllipse( XPoint pxy, int width, int height, R angle1, R angle2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER le bord d'un secteur d'une ellipse
//
// ENTREES :
// ---------
// pxy : coordonnees pixels du centre de l'ellipse
// width : demi-largeur en pixels de l'ellipse
// height : demi-hauteur en pixels de l'ellipse
// angle1 : angle de depart (a partir de l'axe Ox sens direct en degres )
// angle2 : angle du secteur a tracer (a partir de l'angle de depart en degres)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int adep , afin ;
adep = (int) (angle1 * 64) ;
afin = (int) (angle2 * 64) ;
XDrawArc(display_vu, mempx, gc_vu, pxy.x-width, pxy.y-height, width*2,
height*2, adep , afin );

// Traitement du postscript :
// instruction ps : el
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu
if (lasopsc > 0){
iel = 1 ;
if (nbrcon > 0){
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
if (angle2 >= 0){
adep = (int) angle1 ;
afin = (int) (angle1 + angle2) ;
}
else{
afin = (int) angle1 ;
adep = (int) (angle1 + angle2) ;
}
if (counb != -1) {
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %6i %6i %4.2f %4.2f %4.2f %4.2f el\n",
adep, afin, width, height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2], counb) ;
}
else {
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %6i %6i %4.2f %4.2f %4.2f 0.00 el\n",
adep, afin, width, height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2]) ;
}
if (lasopsc < 3){
fprintf(fpo,buf) ;
}
else{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}
 

void MemoirePx::VuArcEllipse( XPoint pxy, int width, int height, R angle1, R angle2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : TRACER le remplissage d'un secteur d'une ellipse
//
// ENTREES :
// ---------
// x,y : coordonnees pixels du centre de l'ellipse
// width : demi-largeur en pixels de l'ellipse
// height : demi-hauteur en pixels de l'ellipse
// angle1 : angle de depart (a partir de l'axe Ox sens direct en degres )
// angle2 : angle du secteur a tracer (a partir de l'angle de depart en degres )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int adep , afin ;

adep = (int) (angle1 * 64) ;
afin = (int) (angle2 * 64) ;
XFillArc( display_vu, mempx, gc_vu, pxy.x-width, pxy.y-height, width*2,
height*2, adep, afin );

// Traitement du postscript :
// instruction ps : El
// destination : TEMPORAIRE.EPS si l'instruction est de type dessin
// : chaine si l'instruction correspond a un menu
if (lasopsc > 0)
{
iEl = 1 ;
if (nbrcon > 0)
{
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
}
buf[0] = '\0' ;
if (angle2 >= 0){
adep = (int) angle1 ;
afin = (int) (angle1+angle2) ;
}
else
{
afin = (int) angle1 ;
adep = (int) (angle1+angle2) ;
}
if (counb != -1)
{
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %6i %6i %4.2f %4.2f %4.2f %4.2f El\n",
adep , afin , width, height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2], counb) ;
}
else
{
sprintf(&buf[strlen(buf)], "%6i %6i %6i %6i %6i %6i %4.2f %4.2f %4.2f 1.00 El\n",
adep , afin , width, height, pxy.x, ypixels-pxy.y,
courgb[0],courgb[1],courgb[2]) ;
}
if (lasopsc < 3)
{
fprintf(fpo,buf) ;
}
else
{
sprintf(&chaine[lasopsc-4][strlen(chaine[lasopsc-4])],buf) ;
}
}
}

void MemoirePx::VuBordTriangle( XPoint xys1, XPoint xys2, XPoint xys3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Trace les 3 aretes du triangle de sommets xys
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
VuTrait( xys1, xys2 );
VuTrait( xys2, xys3 );
VuTrait( xys3, xys1 );
}

void MemoirePx::VuTriangleCouleur( XPoint xys1, XPoint xys2, XPoint xys3,
R coul1, R coul2, R coul3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Trace le remplissage du triangle de sommets xys de couleurs coul
// selon les couleurs intermediaires (PALETTE 11 RECOMMANDEE)
// entrees:
//---------
// xys* : coordonnees pixels des 3 sommets
// coul* : couleur entre n1coul et ndcoul dans la palette actuelle des 3 sommets
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
//Variables locales
static R c1, c2, c3;
static R c21, c31, c32;
static int nc, nc1, nc2, nc3, ncp1;
static XPoint xy[4];
static XPoint xyf[5];

//CORPS de la FONCTION
if ( coul1<0. || coul2<0. || coul3<0. ) return;

//LES 3 SOMMETS SONT REORDONNES SELON LES COULEURS C1<=C2<=C3
if( coul1<=coul2 && coul2<=coul3 )
{ c1=coul1; xy[1]=xys1; c2=coul2; xy[2]=xys2; c3=coul3; xy[3]=xys3; }
else if( coul2<=coul3 && coul3<=coul1 )
{ c1=coul2; xy[1]=xys2; c2=coul3; xy[2]=xys3; c3=coul1; xy[3]=xys1; }
else if( coul3<=coul1 && coul1<=coul2 )
{ c1=coul3; xy[1]=xys3; c2=coul1; xy[2]=xys1; c3=coul2; xy[3]=xys2; }
else if( coul1<=coul3 && coul3<=coul2 )
{ c1=coul1; xy[1]=xys1; c2=coul3; xy[2]=xys3; c3=coul2; xy[3]=xys2; }
else if( coul3<=coul2 && coul2<=coul1 )
{ c1=coul3; xy[1]=xys3; c2=coul2; xy[2]=xys2; c3=coul1; xy[3]=xys1; }
else if( coul2<=coul1 && coul1<=coul3 )
{ c1=coul2; xy[1]=xys2; c2=coul1; xy[2]=xys1; c3=coul3; xy[3]=xys3; }

// PARTIE ENTIERE DE LA COULEUR
nc1 = (int) c1; nc2 = (int) c2; nc3 = (int) c3;

if (nc1 == nc3)
{
// LES 3 COULEURS A TRACER SONT EGALES -> TRIANGLE MONO-COULEUR
VuCouleur( nc1 );
VuFace( 3, xy+1 );
return;
}

xyf[0] = xy[1]; // le premier sommet

//RECHERCHE DE L'ARETE P13-P12 OU LA COULEUR NC1 DEVIENT NC1+1
ncp1 = nc1 + 1;
if (nc1 != nc2)
{
c21 = 1.0 / (c2 - c1);
xyf[1].x = (int) ((xy[1].x * (c2 - ncp1) + xy[2].x * (ncp1 - c1)) * c21 + 0.5);
xyf[1].y = (int) ((xy[1].y * (c2 - ncp1) + xy[2].y * (ncp1 - c1)) * c21 + 0.5);

c31 = 1.0 / (c3 - c1);
xyf[2].x = (int) ((xy[1].x * (c3 - ncp1) + xy[3].x * (ncp1 - c1)) * c31 + 0.5);
xyf[2].y = (int) ((xy[1].y * (c3 - ncp1) + xy[3].y * (ncp1 - c1)) * c31 + 0.5);

//TRACE DU TRIANGLE SOMMET 1 - P12 - P13
VuCouleur( nc1 );
VuFace( 3, xyf );

//LES QUADRANGLES SUIVANTS
xyf[0].x = xyf[2].x;
xyf[0].y = xyf[2].y;

for (nc=nc1+1; nc<=nc2-1; nc++)
{
ncp1 = nc + 1;
xyf[2].x = (int) ((xy[1].x * (c2 - ncp1) + xy[2].x * (ncp1 - c1)) * c21 + 0.5);
xyf[2].y = (int) ((xy[1].y * (c2 - ncp1) + xy[2].y * (ncp1 - c1)) * c21 + 0.5);

xyf[3].x = (int) ((xy[1].x * (c3 - ncp1) + xy[3].x * (ncp1 - c1)) * c31 + 0.5);
xyf[3].y = (int) ((xy[1].y * (c3 - ncp1) + xy[3].y * (ncp1 - c1)) * c31 + 0.5);

//TRACE DU QUADRANGLE P13-P12-P12-P13
VuCouleur( nc );
VuFace( 4, xyf );

//3->2 ET 4->1
xyf[1].x = xyf[2].x;
xyf[1].y = xyf[2].y;

xyf[0].x = xyf[3].x;
xyf[0].y = xyf[3].y;
}

if (nc2 == nc3)
{
//IL RESTE LE QUADRANGLE P13-P12-S2-S3 */
xyf[2].x = xy[2].x;
xyf[2].y = xy[2].y;

xyf[3].x = xy[3].x;
xyf[3].y = xy[3].y;

//TRACE DU QUADRANGLE P13-P12-S2-S3 */
VuCouleur( nc2 );
VuFace( 4, xyf );
return;
}

//CAS NC1<NC2<NC3 LE PENTAGONE P13-P12-S2-P23-P13
xyf[2].x = xy[2].x;
xyf[2].y = xy[2].y;
ncp1 = nc2 + 1;
c32 = (R) 1. / (c3 - c2);
xyf[3].x = (int) ((xy[2].x * (c3 - ncp1) + xy[3].x * (ncp1 - c2)) * c32 + 0.5);
xyf[3].y = (int) ((xy[2].y * (c3 - ncp1) + xy[3].y * (ncp1 - c2)) * c32 + 0.5);

xyf[4].x = (int) ((xy[1].x * (c3 - ncp1) + xy[3].x * (ncp1 - c1)) * c31 + 0.5);
xyf[4].y = (int) ((xy[1].y * (c3 - ncp1) + xy[3].y * (ncp1 - c1)) * c31 + 0.5);

//TRACE DU PENTAGONE P13-P12-SOMMET2-P23-P13
VuCouleur( nc2 );
VuFace( 5, xyf );

//4->2 ET 5->1
xyf[1].x = xyf[3].x;
xyf[1].y = xyf[3].y;

xyf[0].x = xyf[4].x;
xyf[0].y = xyf[4].y;
goto L50;
}

//CAS : NC1=NC2<NC3 LE QUADRANGLE SOMMET1-SOMMET2-P23-P13
//xyf[0] = xy[1]; deja fait
xyf[1].x = xy[2].x;
xyf[1].y = xy[2].y;
ncp1 = nc2 + 1;
c31 = (R) 1.0 / (c3 - c1);
c32 = (R) 1.0 / (c3 - c2);
xyf[2].x = (int) ((xy[2].x * (c3 - ncp1) + xy[3].x * (ncp1 - c2)) * c32 + 0.5);
xyf[2].y = (int) ((xy[2].y * (c3 - ncp1) + xy[3].y * (ncp1 - c2)) * c32 + 0.5);

xyf[3].x = (int) ((xy[1].x * (c3 - ncp1) + xy[3].x * (ncp1 - c1)) * c31 + 0.5);
xyf[3].y = (int) ((xy[1].y * (c3 - ncp1) + xy[3].y * (ncp1 - c1)) * c31 + 0.5);

//TRACE DU QUADRANGLE SOMMET1-SOMMET2-P23-P13
VuCouleur( nc2 );
VuFace( 4, xyf );

//3->2 ET 4->1
xyf[1].x = xyf[2].x;
xyf[1].y = xyf[2].y;

xyf[0].x = xyf[3].x;
xyf[0].y = xyf[3].y;

//LES QUADRANGLES P13-P23-P23-P13
L50:
for (nc=nc2+1; nc<=nc3-1; nc++)
{
ncp1 = nc + 1;
xyf[2].x = (int) ((xy[2].x * (c3 - ncp1) + xy[3].x * (ncp1 - c2)) * c32 + 0.5);
xyf[2].y = (int) ((xy[2].y * (c3 - ncp1) + xy[3].y * (ncp1 - c2)) * c32 + 0.5);

xyf[3].x = (int) ((xy[1].x * (c3 - ncp1) + xy[3].x * (ncp1 - c1)) * c31 + 0.5);
xyf[3].y = (int) ((xy[1].y * (c3 - ncp1) + xy[3].y * (ncp1 - c1)) * c31 + 0.5);

//TRACE DU QUADRANGLE P13-P23-P23-P13
VuCouleur( nc );
VuFace( 4, xyf );
//3->2 ET 4->1
xyf[1].x = xyf[2].x;
xyf[1].y = xyf[2].y;

xyf[0].x = xyf[3].x;
xyf[0].y = xyf[3].y;
}

//LE TRIANGLE P13-P12-SOMMET 3
xyf[2].x = xy[3].x;
xyf[2].y = xy[3].y;

//TRACE DU TRIANGLE P13-P23-SOMMET 3
VuCouleur( nc3 );
VuFace( 3, xyf );
}


void VuInitierps( int modeps )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : INITIALISER le POSTSCRIPT

ENTREE :
---------
modeps : 0 mode standard bibliotheque Vu
1 mode Mefisto
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR : DOURSAT CHRISTOPHE UPMC ANALYSE NUMERIQUE PARIS JUIN 1994
12345X7..........................................................012345678*/
{
int lasops ;
lasopsc = 0;
modepsc = modeps ;
icolorm = ndcoul + 1 ;
counb = 0.0 ;
courgb[0] = 0.0 ; courgb[1] = 0.0 ; courgb[2] = 0.0 ;
/* initialisation des pointeurs et variables postscript */
fpi = NULL ;
fpo = NULL ;
menu = 0 ;
if ( modepsc != 0 ){
/* Initialisation des tailles des chaines-tampons des menus
Nombre de caracteres a reserver par instruction PS
1 rectangle = 35
1 segment = 35
1 changement epaisseur trait = 10
1 chaine texte = 24 + long chaine
Par menu il y a :
2 rectangles (un fond et un contour)
2 segments de bordure
3 changements d'epaisseur (maximum)
n chaines de caracteres
(n-1) segments entre les chaines de caracteres
+ 50 de securite */

/* Documentation */
longchaine[0] = 2*35 + 2*35 + 3*10 + MXLGDO*(NBCADO+24) + (MXLGDO-1) * 35 + 50 ;
/* Historique */
longchaine[1] = 2*35 + 2*35 + 3*10 + MXLGHI*(NBCAHI+24) + (MXLGHI-1) * 35 + 50 ;
/* Menu */
longchaine[2] = 2*35 + 2*35 + 3*10 + MXLGME*(NBCAME+24) + (MXLGME-1) * 35 + 50 ;
/* Lignes lues */
longchaine[3] = 2*35 + 2*35 + 3*10 + MXKLG *(NBCALI+24) + 50 ;
/* Invite */
longchaine[4] = 2*35 + 2*35 + 3*10 + MXLGIN*(NBCAIN+24) + (MXLGIN-1) * 35 + 50 ;
/* Ligne de saisie */
longchaine[5] = 2*35 + 2*35 + 3*10 + MXLGSA*(NBCALG+24) + (MXLGSA-1) * 35 + 50 ;
/* Erreur */
longchaine[6] = 2*35 + 2*35 + 3*10 + MXLGER*(NBCAER+24) + (MXLGER-1) * 35 + 50 ;
/* Histogrammes et Qualites : 1+32 rectangles et chaines de caracters de 72 */
longchaine[7] = 35 +32*35 + 32*( 72 +24) + 50 ;
}
/* effacement si necessaire du fichier ps */
lasops = 0 ;
VuPostscript(lasops) ;
/* ouverture du futur fichier ps */
lasops = 1 ;
VuPostscript(lasops) ;
}

void VuImprimerps( char nomfichier[] )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT: IMPRIMER nomfichier.eps

ENTREE:
-------
nomfichier: CHAINE DE CARACTERE
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR : DOURSAT CHRISTOPHE UPMC ANALYSE NUMERIQUE PARIS JUIN 1994
12345X7..........................................................012345678*/
{
int nbc, length ;

length = nudcnb( nomfichier );
buf[0] = '\0' ;
nbc = length ;
sprintf(format,"%%.%ds.eps", nbc) ;
sprintf(buf,format,nomfichier) ;
/* changement du titre si possible */
/* if ((fpi = fopen(buf,"r+"))!=NULL) {
rewind(fpi) ;
for (i=1 ; i<9 ; i++) { fgets(buf,255,fpi) ; }
buf[0] = '\0' ;
sprintf(format,"%%.%ds.eps) /titre exch def\n",nbc) ;
sprintf(buf,format,nomfichier) ;
fprintf(fpi,"(%s",buf) ;
fclose(fpi) ;
} */

// ******************************** ATTENTION **************************************
// ORDRE D'IMPRESSION DEPENDANT TYPE IMPRIMANTE ET SYSTEME
// ******************************** ATTENTION **************************************
sprintf(format,"lpr -Ppastis %%.%ds.eps",nbc) ;/* ATTENTION ici LINUX PC LAN */

/* sprintf(format,"lp -dlaserhp %%.%ds.eps",nbc) ; */ /* ATTENTION ici HP */
/* sprintf(format,"lpr %%.%ds.eps",nbc) ; */ /* ajouter -Plaser ? */
/* sprintf(format,"/bin/prf -trans %%.%ds.eps",nbc) ; */ /* Apollo LaserWriterII */

// ******************************** ATTENTION **************************************
sprintf(buf,format,nomfichier) ;
nbc = system(buf) ;
}

void VuSauverps( char nomfichier[], int & length )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : CONCATENER LES DONNEES DE DESSIN PS CONTENUES DANS TEMPORAIRE.EPS
----- AVEC LES PROCEDURES PS ET LES DIVERS MENUS EVENTUELS
DANS nomfichier.eps

ENTREE :
--------
nomfichier: CHAINE DE CARACTERES

SORTIE:
-------
length : <0 si erreur rencontree, 0 sinon
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR : DOURSAT CHRISTOPHE UPMC ANALYSE NUMERIQUE PARIS JUIN 1994
12345X7..........................................................012345678*/
{ int i;
char cpwd[100];
char *ligne, *car;
int an, mo, jo;

/* verification des fichiers */
length = nudcnb( nomfichier );
fprintf(fpo,concat) ;
nbrcon = 0 ;
concat[0] = '\0' ;
i = 0 ;
if (fpi != NULL)
{
fclose(fpi) ;
fpi = NULL ;
}
sprintf(format,"%%.%ds.eps",length) ;
sprintf(buf,format,nomfichier) ;
if ((fpi = fopen(buf,"w"))==NULL)
{
printf ("Erreur de creation de fichier\n") ;
i = 1 ;
length = -2 ;
}

if ( i == 0 )
{
if (fpo != NULL)
{
fclose(fpo) ;
}
fpo = fpi ;
i = 0 ;
fpi = NULL ;
if ((fpi = fopen("TEMPORAIRE.EPS","r"))==NULL)
{
printf ("Erreur d'ouverture de fichier\n") ;
i = 1 ;
length = -2 ;
}
}

if ( i == 0 )
{
lasopsc = 0 ;
/* ecriture du dictionnaire de procedures PS utilisees */
fprintf(fpo,"%%!PS-Adobe\n") ;
if ( modepsc == 0 )
{
fprintf(fpo,"%%%%Creator: Vu\n") ;
}
else
{
fprintf(fpo,"%%%%Creator: Mefisto\n") ;
sprintf(buf,"LOGNAME") ;
i = 100 ;
ValVarEnv( buf, &i, cpwd, &an) ; // dans Util.cpp
sprintf(format,"%%%%%%%%User: %%.%ds\n",an) ;
for (i=0 ; (i<an) && (*(cpwd+i)!='.') ; i++) ;
sprintf(format,"%%%%%%%%User: %%.%ds\n",i) ;
fprintf(fpo,format,cpwd) ;
}
sprintf(format,"%%%%%%%%Title: %%.%ds",length) ;
sprintf(buf,format,nomfichier) ;
fprintf(fpo,"%s\n",buf) ;
LaDate(&an,&mo,&jo) ; // dans Util.cpp
fprintf(fpo,"%%%%CreationDate: %2i/%2i/%2i\n",jo,mo,an) ;
fprintf(fpo,"%%%%BoundingBox: 0 0 %5i %5i\n",xpixels,ypixels) ;
fprintf(fpo,"%%%%EndComments\n\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo,"%% A NE PAS CHANGER\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," mark\n") ;
fprintf(fpo," /tex where { pop /texval true def }{ /texval false def } ifelse\n") ;
fprintf(fpo," /texdvips where { pop /texdvipsval true def /texval true def }\n") ;
fprintf(fpo," { /texdvipsval false def } ifelse\n") ;
fprintf(fpo," /ptcm 28.3464566929134 def /cm {ptcm mul} def\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo,"%% OPTIONS UTILISATEURS\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo,"%% OPTION COULEUR\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," %% trace couleur (true) ou n&b = palette gris (false)\n") ;
fprintf(fpo,"true /couleur exch def %% remis systematiquement a true si le fichier est envoye sur\n") ;
fprintf(fpo," %% une imprimante couleur referencee (cf. Options Imprim.)\n\n") ;
fprintf(fpo," %% couleur de fond : true = noir false = blanc\n") ;
fprintf(fpo,"false /fondcou exch def %% remis systematiquement a false si couleur = false\n") ;
fprintf(fpo," %% sauf si imprimante couleur referencee\n\n") ;
fprintf(fpo,"%% RECADRAGE\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," 0 /zoomxmin exch def %% \n") ;
fprintf(fpo,"%5i /zoomxmax exch def %% definition du rectangle de zoom choisi\n",xpixels) ;
fprintf(fpo," 0 /zoomymin exch def %% a utiliser pour recadrer la figure\n") ;
fprintf(fpo,"%5i /zoomymax exch def %%\n\n",ypixels) ;
fprintf(fpo," %% encadrement automatique des zones de trace\n") ;
fprintf(fpo,"false /autoreca exch def %% taper dans le fichier autoreca pour definir la limite\n") ;
fprintf(fpo," %% entre deux zones a encadrer\n\n") ;
fprintf(fpo,"%% OPTIONS DE TRACE\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," %% largeur du trait de trace ]0,+oo[, 1 etant la norme.\n") ;
fprintf(fpo," -1 /lartrait exch def %% le code -1 (valeur par defaut) permet de conserver la meme\n") ;
fprintf(fpo," %% largeur de trait et d'ecriture quelque soit le zoom.\n\n") ;
if ( modepsc != 0 ){
fprintf(fpo," %% option de trace que maillage : 0\n") ;
if ( menu ){
fprintf(fpo," 2 /tracemen exch def %% avec legende qualite : 1\n") ;
} else {
if ( strlen(chaine[7]) != 0 ){
fprintf(fpo," 1 /tracemen exch def %% avec legende qualite : 1\n") ;
} else {
fprintf(fpo," 0 /tracemen exch def %% avec legende qualite : 1\n") ;
}
}
fprintf(fpo," %% avec menus : 2\n") ;
fprintf(fpo," %% par defaut : si il y a un menu 2\n") ;
fprintf(fpo," %% sinon : si qualite 1, 0 sinon\n\n") ;
}
fprintf(fpo," %% option de trace des facettes 0 fil de fer\n") ;
fprintf(fpo," 2 /tracecou exch def %% 1 faces blanches\n") ;
fprintf(fpo," %% 2 faces de couleur\n\n") ;
fprintf(fpo," true /traceecr exch def %% option de trace des chaines de caracteres\n\n") ;
fprintf(fpo,"%% OPTIONS DE MISE EN PAGE\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," true /tracecad exch def %% trace d'un cadre true ou false\n") ;
fprintf(fpo," %% \n") ;
fprintf(fpo," 4 /epcadre exch def %% epaisseur du cadre\n\n") ;
if ( modepsc != 0 ){
if ( menu ){
fprintf(fpo,"false /tracelog exch def %% trace du logo Mefisto : par defaut false si menu true sinon\n") ;
} else {
fprintf(fpo," true /tracelog exch def %% trace du logo Mefisto : par defaut false si menu true sinon\n") ;
}
}
fprintf(fpo," 1 /xpolog exch def %% position horizontale du logo Mefisto -1 gauche 1 droite\n") ;
fprintf(fpo," -1 /ypolog exch def %% position verticale du logo Mefisto -1 bas 1 haut\n") ;
fprintf(fpo," %% position par defaut 1 -1 coin bas droit\n\n") ;

/* *********************************** ATTENTION ***********************************************************
DONNEES DEPENDANTES TYPE IMPRIMANTE
*********************************** ATTENTION ******************************************************** */

fprintf(fpo,"%% OPTIONS DEPENDANTES DE L'IMPRIMANTE\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo,"texval not {\n") ;
fprintf(fpo," 27.0 cm /vsize exch def %% hauteur max de la zone de trace sur A4 < 29.7cm\n") ;
fprintf(fpo," 19.0 cm /hsize exch def %% largeur max de la zone de trace sur A4 < 21.0cm\n") ;
fprintf(fpo,"} if\n\n") ;
fprintf(fpo,"version (2010.113) eq { %% palette grise pour LaserWriter II (salle apollo)\n") ;
fprintf(fpo," 0.0 /gsefo exch def %% niveau du gris le plus fonce pour segment 0 = noir\n") ;
fprintf(fpo," 0.8 /gsecl exch def %% clair 1 = blanc\n") ;
fprintf(fpo," 0.1 /gfafo exch def %% niveau du gris le plus fonce pour faces 0 = noir\n") ;
fprintf(fpo," 1.0 /gfacl exch def %% clair 1 = blanc\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo,"version (2011.110) eq { %% palette grise pour LaserJet4 (salle HP)\n") ;
fprintf(fpo," 0.1 /gsefo exch def %% niveau du gris le plus fonce pour segment 0 = noir\n") ;
fprintf(fpo," 0.9 /gsecl exch def %% clair 1 = blanc\n") ;
fprintf(fpo," 0.5 /gfafo exch def %% niveau du gris le plus fonce pour faces 0 = noir\n") ;
fprintf(fpo," 1.0 /gfacl exch def %% clair 1 = blanc\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo,"version (xxxx.xxx) eq { %% palette grise pour LaserWriterII (salle Mac)\n") ;
fprintf(fpo," 0.1 /gsefo exch def %% niveau du gris le plus fonce pour segment 0 = noir\n") ;
fprintf(fpo," 0.9 /gsecl exch def %% clair 1 = blanc\n") ;
fprintf(fpo," 0.5 /gfafo exch def %% niveau du gris le plus fonce pour faces 0 = noir\n") ;
fprintf(fpo," 1.0 /gfacl exch def %% clair 1 = blanc\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo,"version (2013.104) eq { %% couleur pour jet d'encre couleur\n") ;
fprintf(fpo," /couleur true def\n") ;
fprintf(fpo,"}{ %% palette grise par defaut\n") ;
fprintf(fpo," 0.0 /gsefo exch def %% niveau du gris le plus fonce pour segment 0 = noir\n") ;
fprintf(fpo," 0.9 /gsecl exch def %% clair 1 = blanc\n") ;
fprintf(fpo," 0.5 /gfafo exch def %% niveau du gris le plus fonce pour faces 0 = noir\n") ;
fprintf(fpo," 1.0 /gfacl exch def %% clair 1 = blanc\n") ;
fprintf(fpo,"} ifelse } ifelse } ifelse } ifelse\n\n") ;
/* ******************************** ATTENTION **************************************** */
fprintf(fpo,"%% OPTION FONTES\n") ;
fprintf(fpo,"%%=======================================================================\n") ;
fprintf(fpo," %% fontes par defaut (a mettre sous la forme par ex\n") ;
fprintf(fpo,"/Courier /fontm0 exch def %% de /Courier-BoldItalic /Helvetica ...)\n") ;
fprintf(fpo,"/Helvetica /fontp0 exch def %% * /fontm0 est la fonte monospaced\n") ;
fprintf(fpo," %% * /fontp0 est la fonte proportional\n\n") ;
fprintf(fpo," %% de /Courier-BoldItalic /Helvetica ...)\n\n") ;
fprintf(fpo,"false /bavard exch def %% bavard a true indique les chaines de caracteres\n") ;
fprintf(fpo," %% ou la police choisie n'existe pas\n\n") ;
fprintf(fpo,"%%=======================================================================\n\n") ;
fprintf(fpo,"%%%%BeginProcSet \n") ;
fprintf(fpo,"%%%%\n") ;
fprintf(fpo,"%%%% Auto-encadrement\n") ;
fprintf(fpo,"autoreca{ %% definition des macros servant a l'auto-encadrement\n") ;
fprintf(fpo," /nbrcad 0 def\n") ;
fprintf(fpo," /c@rli {currentlinewidth} def\n") ;
fprintf(fpo," /initcad{/nbrcad nbrcad 1 add def /xmin{dup}def /ymin{dup}def /xmax{dup}def /ymax{dup}def}def\n") ;
fprintf(fpo," initcad\n") ;
fprintf(fpo," /t@stxy{2 copy 2 copy /n c@rli 2 div def\n") ;
fprintf(fpo," n sub dup ymin le{/ymin exch def}{pop}ifelse n sub dup xmin le{/xmin exch def}{pop}ifelse\n") ;
fprintf(fpo," n add dup ymax ge{/ymax exch def}{pop}ifelse n add dup xmax ge{/xmax exch def}{pop}ifelse}def\n") ;
fprintf(fpo," /t@stx@{2 copy dup ymin le{/ymin exch def}{pop}ifelse dup xmin le{/xmin exch def}{pop}ifelse\n") ;
fprintf(fpo," dup ymax ge{/ymax exch def}{pop}ifelse dup xmax ge{/xmax exch def}{pop}ifelse}def\n") ;
fprintf(fpo," /m@veto {t@stxy moveto}def\n") ;
fprintf(fpo," /m@v@to {2 copy t@stx@ moveto}def\n") ;
fprintf(fpo," /m@v@t@ {2 copy 2 copy 2 copy tfont add t@stx@ t@stx@ moveto}def\n") ;
fprintf(fpo," /sh@w {3 2 roll dup show stringwidth 3 2 roll add 3 1 roll add exch t@stx@}def\n") ;
fprintf(fpo," /l@neto {t@stxy lineto}def\n") ;
fprintf(fpo," /l@n@to {2 copy t@stx@ lineto}def\n") ;
fprintf(fpo," /rl@neto{2 copy currentpoint 3 2 roll add 3 1 roll add exch t@stxy pop pop rlineto}def\n") ;
fprintf(fpo," /rl@n@to{2 copy currentpoint 3 2 roll add 3 1 roll add exch t@stx@ rlineto}def\n") ;
fprintf(fpo," /t@stel{6 copy /ycent exch def /xcent exch def /hautel exch def /largel exch def\n") ;
fprintf(fpo," 2 copy exch dup truncate 0 ge{90 idiv 1 add}{90 idiv}ifelse\n") ;
fprintf(fpo," exch dup truncate 0 ge{90 idiv}{90 idiv 1 sub}ifelse\n") ;
fprintf(fpo," 2 copy exch sub 1 add 3 1 roll 1 exch {90 mul exch} for\n") ;
fprintf(fpo," 2 add {dup cos largel mul xcent add exch sin hautel mul ycent add t@stxy pop pop} repeat}def\n") ;
fprintf(fpo," /t@st@l{6 copy /ycent exch def /xcent exch def /hautel exch def /largel exch def\n") ;
fprintf(fpo," 2 copy exch dup truncate 0 ge{90 idiv 1 add}{90 idiv}ifelse\n") ;
fprintf(fpo," exch dup truncate 0 ge{90 idiv}{90 idiv 1 sub}ifelse\n") ;
fprintf(fpo," 2 copy exch sub 1 add 3 1 roll 1 exch {90 mul exch} for\n") ;
fprintf(fpo," 2 add {dup cos largel mul xcent add exch sin hautel mul ycent add t@stx@} repeat}def\n") ;
fprintf(fpo," /autoreca{xmin xmax ymin ymax initcad}def\n") ;
fprintf(fpo," /encadre {xmin xmax ymin ymax 1 epais\n") ;
fprintf(fpo," /font0 /Courier-Bold findfont [15 0 0 17 0 0] makefont definefont pop\n") ;
fprintf(fpo," lartrait -1 eq {/font0 /font0 findfont reduc scalefont definefont pop} if\n") ;
fprintf(fpo," /taillefonte{ dup /tfont exch 17 div 14 mul reduc mul def 14.0 div /font0 findfont exch scalefont setfont } bind def\n") ;
fprintf(fpo," 17 taillefonte /hsi (1234567890) stringwidth pop def\n") ;
fprintf(fpo," /tab {hsi 0 rmoveto dup stringwidth pop neg 0 rmoveto show} def\n") ;
fprintf(fpo," /hsize hsi 4 mul (1 : ) stringwidth pop add def\n") ;
fprintf(fpo," /vsize tfont nbrcad 1 add mul 1.2 mul def /angle 0 def\n") ;
fprintf(fpo," texval {\n") ;
fprintf(fpo," /xorig zoomxmin tracecad{epcadre sub}if def /yorig zoomymin tracecad{epcadre sub}if def\n") ;
fprintf(fpo," /cadrepath{newpath\n") ;
fprintf(fpo," xorig yorig vsize sub moveto zoomxmax tracecad{epcadre add}if yorig vsize sub lineto\n") ;
fprintf(fpo," zoomxmax tracecad{epcadre add}if zoomymax tracecad{epcadre add}if lineto\n") ;
fprintf(fpo," xorig zoomymax tracecad{epcadre add}if lineto\n") ;
fprintf(fpo," closepath} def cadrepath clip\n") ;
fprintf(fpo," }{ nbrcad 4 mul copy\n") ;
fprintf(fpo," /xxmin{dup}def /yymin{dup}def /xxmax{dup}def /yymax{dup}def\n") ;
fprintf(fpo," /t@stx@{ dup yymax ge{/yymax exch def}{pop}ifelse dup yymin le{/yymin exch def}{pop}ifelse\n") ;
fprintf(fpo," dup xxmax ge{/xxmax exch def}{pop}ifelse dup xxmin le{/xxmin exch def}{pop}ifelse}def\n") ;
fprintf(fpo," nbrcad { t@stx@ } repeat 14 taillefonte\n") ;
fprintf(fpo," /xxmin xxmin tfont 1.2 mul sub def /xxmax xxmax tfont 1.2 mul add def\n") ;
fprintf(fpo," /yymin yymin tfont 1.2 mul sub def /yymax yymax tfont 1.2 mul add def\n") ;
fprintf(fpo," yymin zoomymin sub dup vsize ge {/yorig zoomymin vsize add def /xorig zoomxmin def pop}\n") ;
fprintf(fpo," {zoomymax yymax sub dup vsize ge {/yorig zoomymax def /xorig zoomxmin def pop pop}\n") ;
fprintf(fpo," {xxmin zoomxmin sub dup vsize ge {/angle 90 def /xorig zoomxmin def /yorig zoomymin def pop pop pop}\n") ;
fprintf(fpo," {zoomxmax xxmax sub dup vsize ge {/angle 90 def /xorig zoomxmax vsize sub def\n") ;
fprintf(fpo," /yorig zoomymax hsize sub def pop pop pop pop}\n") ;
fprintf(fpo," {/angle 90 def /xorig zoomxmax vsize sub def /yorig zoomymax hsize sub def\n") ;
fprintf(fpo," 2 copy ge {pop /xorig zoomxmin def /yorig zoomymin def}{exch pop} ifelse\n") ;
fprintf(fpo," 2 copy ge {pop /angle 0 def /yorig zoomymax def /xorig zoomxmin def}{exch pop} ifelse\n") ;
fprintf(fpo," ge {/angle 0 def /yorig zoomymin vsize add def /xorig zoomxmin def}if}ifelse}ifelse}ifelse}ifelse\n") ;
fprintf(fpo," gsave xorig yorig moveto angle rotate hsize 0 rlineto 0 vsize neg rlineto hsize neg 0 rlineto closepath\n") ;
fprintf(fpo," 1.0 setgray fill grestore\n") ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo," /sh@w {gsave tfont -0.1 mul dup rmoveto dup stringwidth pop tfont 0.2 mul add dup 0 rlineto\n") ;
fprintf(fpo," 0 tfont 1.2 mul rlineto neg 0 rlineto closepath 1.0 setgray fill grestore show}def\n") ;
fprintf(fpo," nbrcad -1 1{5 1 roll\n") ;
fprintf(fpo," /ymax exch 10 mul round 10 div def /ymin exch 10 mul round 10 div def\n") ;
fprintf(fpo," /xmax exch 10 mul round 10 div def /xmin exch 10 mul round 10 div def\n") ;
fprintf(fpo," newpath\n") ;
fprintf(fpo," xmin c@rli 2 div sub ymin c@rli 2 div sub moveto xmax c@rli 2 div add ymin c@rli 2 div sub lineto\n") ;
fprintf(fpo," xmax c@rli 2 div add ymax c@rli 2 div add lineto xmin c@rli 2 div sub ymax c@rli 2 div add lineto\n") ;
fprintf(fpo," closepath stroke\n") ;
fprintf(fpo," 20 taillefonte xmin ymax moveto tfont dup 0.1 mul exch -1.1 mul rmoveto\n") ;
fprintf(fpo," /st 2 string def dup st cvs sh@w 14 taillefonte\n") ;
fprintf(fpo," gsave xmin c@rli sub ymin c@rli sub moveto\n") ;
fprintf(fpo," tfont dup 0.1 mul exch -1.1 mul rmoveto /st 10 string def xmin st cvs sh@w grestore\n") ;
fprintf(fpo," gsave xmin c@rli sub ymin c@rli sub translate 90 rotate\n") ;
fprintf(fpo," tfont dup 0.1 mul exch 0.1 mul moveto /st 10 string def ymin st cvs sh@w grestore\n") ;
fprintf(fpo," gsave xmax c@rli add ymax c@rli add moveto\n") ;
fprintf(fpo," /st 10 string def xmax st cvs dup stringwidth pop neg tfont 0.1 mul sub tfont 0.1 mul rmoveto\n") ;
fprintf(fpo," sh@w grestore\n") ;
fprintf(fpo," gsave xmax c@rli add ymax c@rli add translate 90 rotate\n") ;
fprintf(fpo," /st 10 string def ymax st cvs dup stringwidth pop neg tfont 0.1 mul sub tfont -1.1 mul moveto\n") ;
fprintf(fpo," sh@w grestore 17 taillefonte\n") ;
fprintf(fpo," gsave xorig yorig moveto angle rotate dup 1 add tfont mul -1.2 mul 0 exch rmoveto\n") ;
fprintf(fpo," st cvs show ( : ) show xmin st cvs tab xmax st cvs tab ymin st cvs tab ymax st cvs tab grestore\n") ;
fprintf(fpo," } for\n") ;
fprintf(fpo," gsave xorig yorig moveto angle rotate 0 tfont -1.2 mul rmoveto\n") ;
fprintf(fpo," (1 : ) stringwidth rmoveto (xmin) tab (xmax) tab (ymin) tab (ymax) tab\n") ;
fprintf(fpo," } def\n") ;
fprintf(fpo,"}{ %% macros strandard\n") ;
fprintf(fpo," /m@veto {moveto} bind def /m@v@to {moveto} bind def /m@v@t@ {moveto} bind def\n") ;
fprintf(fpo," /sh@w {show} bind def /l@neto {lineto} bind def /l@n@to {lineto} bind def\n") ;
fprintf(fpo," /rl@neto{rlineto} bind def /rl@n@to {rlineto} bind def /t@stel { } def\n") ;
fprintf(fpo," /t@st@l { } def /autoreca{ } def /encadre{ } def\n") ;
fprintf(fpo,"} ifelse\n") ;
fprintf(fpo,"%%%%\n") ;
fprintf(fpo,"%%%% Procedures de trace\n") ;
fprintf(fpo,"lartrait 0 eq{ /str@k { } def }{ /str@k { stroke } bind def } ifelse\n") ;
fprintf(fpo,"couleur not { /fondcou false def } if \n") ;
fprintf(fpo,"fondcou {\n") ;
fprintf(fpo," /s@tc@u { setrgbcolor } bind def\n") ;
if ( modepsc != 0 ){
fprintf(fpo," /s@tcou { setrgbcolor } bind def\n") ;
}
fprintf(fpo," /setc@u { setrgbcolor } bind def\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo," /s@tc@u { %% inversion du blanc en noir et blanc en noir\n") ;
fprintf(fpo," 3 copy add add dup 0 eq { pop pop pop pop 1.0 1.0 1.0 }\n") ;
fprintf(fpo," { 3 eq { pop pop pop 0.0 0.0 0.0 } if } ifelse\n") ;
fprintf(fpo," setrgbcolor\n") ;
fprintf(fpo," } bind def\n") ;
if ( modepsc != 0 ){
fprintf(fpo," /s@tcou { %% inversion du noir en blanc\n") ;
fprintf(fpo," 3 copy add add 0 eq { pop pop pop 1.0 1.0 1.0 } if\n") ;
fprintf(fpo," setrgbcolor\n") ;
fprintf(fpo," } bind def\n") ;
}
fprintf(fpo," /setc@u { %% inversion du blanc en noir (pour T)\n") ;
fprintf(fpo," 3 copy add add 3 eq { pop pop pop 0.0 0.0 0.0 } if\n") ;
fprintf(fpo," setrgbcolor\n") ;
fprintf(fpo," } bind def\n") ;
fprintf(fpo,"} ifelse\n") ;
fprintf(fpo,"couleur { %% couleur\n") ;
fprintf(fpo,"/setcose{ pop s@tc@u } bind def\n") ;
fprintf(fpo,"/setcofa{ pop s@tc@u } bind def\n") ;
fprintf(fpo,"}{ %% Noir&Blanc : palette de gris\n") ;
fprintf(fpo,"/setcose{\n") ;
fprintf(fpo," dup 1 exch sub gsefo mul exch gsecl mul add setgray pop pop pop\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/setcofa{\n") ;
fprintf(fpo," dup 1 exch sub gfafo mul exch gfacl mul add setgray pop pop pop\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"} ifelse\n") ;
if ( iep != 0 ){
fprintf(fpo,"/epais{ %% epaisseur du trait pile : num\n") ;
fprintf(fpo," reduc mul setlinewidth\n") ;
fprintf(fpo,"} bind def\n") ;
}
fprintf(fpo,"/S{ %% trace d'une suite de segments couleurs pile : xn yn .. x0 y0 n coul\n") ;
fprintf(fpo," gsave setcose newpath 3 1 roll m@veto { l@neto } repeat str@k grestore\n") ;
fprintf(fpo,"} bind def\n") ;
if ( iPo != 0 ){
fprintf(fpo,"/P{ %% trace d'un polygone ferme en couleur pile : xn yn .. x0 y0 n coul\n") ;
fprintf(fpo," gsave setcose newpath 3 1 roll m@veto 1 sub { l@neto } repeat closepath str@k grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iFa != 0 ){
fprintf(fpo,"/F{ %% remplissage d'une facette pile : xn yn .. x1 y1 n coul\n") ;
fprintf(fpo," gsave setcofa newpath 3 1 roll m@v@to 1 sub { l@n@to } repeat closepath\n") ;
fprintf(fpo," tracecou dup 0 ne { 1 eq { 1 setgray } if fill }{ pop } ifelse grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iFP != 0 ){
fprintf(fpo,"/FP{ %% facette et polygone pile : xn yn .. x1 y1 n coul_pol coul_fac\n") ;
fprintf(fpo," gsave setcofa 5 -1 roll dup 6 1 roll 2 mul 5 add 4 roll\n") ;
fprintf(fpo," newpath 3 1 roll m@veto 1 sub { l@neto } repeat closepath\n") ;
fprintf(fpo," gsave tracecou dup 0 ne { 1 eq { 1 setgray } if fill }{ pop } ifelse grestore\n") ;
fprintf(fpo," setcose str@k grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( ire != 0 ){
fprintf(fpo,"/r{ %% trace du bord d'un rectangle en coul pile : dx dy x y coul\n") ;
fprintf(fpo," gsave setcose 0 setlinejoin newpath\n") ;
fprintf(fpo," m@veto 0 exch 0 exch 2 copy neg 6 2 roll rl@neto rl@neto rl@neto closepath\n") ;
fprintf(fpo," str@k grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iRe != 0 ){
fprintf(fpo,"/R{ %% remplissage d'un rectangle en coul pile : dx dy x y coul\n") ;
fprintf(fpo," gsave setcofa newpath\n") ;
fprintf(fpo," m@v@to 0 exch 0 exch 2 copy neg 6 2 roll rl@n@to rl@n@to rl@n@to closepath\n") ;
fprintf(fpo," fill grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iel != 0 ){
fprintf(fpo,"/el{ %% trace d'une ellipse en coul pile : angle_deb angle_fin largeur hauteur x y coul\n") ;
fprintf(fpo," gsave setcose t@stel /savematrix matrix currentmatrix def\n") ;
fprintf(fpo," newpath translate scale 0 0 1 5 3 roll arc\n") ;
fprintf(fpo," savematrix setmatrix str@k grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iEl != 0 ){
fprintf(fpo,"/El{ %% remplissage d'une ellipse en coul pile : angle_deb angle_fin largeur hauteur x y coul\n") ;
fprintf(fpo," gsave setcofa t@st@l /savematrix matrix currentmatrix def\n") ;
fprintf(fpo," newpath translate scale 0 0 1 5 3 roll arc\n") ;
fprintf(fpo," savematrix setmatrix fill grestore\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( ity != 0 ){
fprintf(fpo,"/typet{ %% type de trait (continu tirete 1 ou 2\n") ;
fprintf(fpo," [[] [4 4] [4 4]] exch get 0 setdash\n") ;
fprintf(fpo,"} bind def\n") ;
}
if ( iTe != 0 ){
fprintf(fpo,"traceecr { %% trace effectif des chaines de caracteres\n") ;
fprintf(fpo,"couleur { %% couleur\n") ;
fprintf(fpo," /T{ pop setc@u m@v@t@ sh@w } bind def\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo," /T{ setgray pop pop pop m@v@t@ sh@w } bind def\n") ;
fprintf(fpo,"} ifelse\n") ;
fprintf(fpo,"}{ %% Pas de trace des chaines de caracteres\n") ;
fprintf(fpo," /T{ 7 { pop } repeat } bind def\n") ;
fprintf(fpo,"} ifelse\n") ;
}
fprintf(fpo,"/cadrepath{ %% definition du cadre de trace pile : xmin ymin xmax ymax\n") ;
fprintf(fpo," newpath 4 copy moveto 3 1 roll exch lineto 4 2 roll lineto lineto closepath\n") ;
fprintf(fpo,"} bind def\n\n") ;
fprintf(fpo,"%%%%EndProcSet \n\n") ;
fprintf(fpo,"texval not { %% orientation du dessin sur A4\n") ;
fprintf(fpo," 21.0 cm 2 div 29.7 cm 2 div translate\n") ;
fprintf(fpo," vsize hsize gt {\n") ;
fprintf(fpo," zoomxmax zoomxmin sub zoomymax zoomymin sub gt {\n") ;
fprintf(fpo," 90 rotate vsize hsize /vsize exch def /hsize exch def } if\n") ;
fprintf(fpo," }{\n") ;
fprintf(fpo," zoomxmax zoomxmin sub zoomymax zoomymin sub lt {\n") ;
fprintf(fpo," 90 rotate vsize hsize /vsize exch def /hsize exch def } if\n") ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo,"} if \n") ;
fprintf(fpo,"/reduc %% calcul du coeff de reduction du a un eventuel zoom\n") ;
fprintf(fpo," vsize zoomymax zoomymin sub div hsize zoomxmax zoomxmin sub div ge {\n") ;
fprintf(fpo," zoomxmax zoomxmin sub %5i div\n",xpixels) ;
fprintf(fpo," vsize %5i div hsize %5i div 2 copy le { div mul }{pop pop} ifelse\n",ypixels,xpixels) ;
fprintf(fpo," }{\n") ;
fprintf(fpo," zoomymax zoomymin sub %5i div\n",ypixels) ;
fprintf(fpo," hsize %5i div vsize %5i div 2 copy le { div mul }{pop pop} ifelse\n",xpixels,ypixels) ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo,"def\n") ;
fprintf(fpo,"lartrait -1 eq {\n") ;
fprintf(fpo," /reduclog reduc def\n") ;
fprintf(fpo," texval { /reduc reduc reductex mul def } if\n") ;
fprintf(fpo,"}{\n") ;
fprintf(fpo," /reduclog reduc texval {reductex mul} if def /reduc lartrait def\n") ;
fprintf(fpo,"} ifelse\n") ;
fprintf(fpo,"/epcadre epcadre reduc mul def\n") ;
fprintf(fpo,"texval not\n") ;
fprintf(fpo,"{ %% sortie directe sur imprimante\n") ;
fprintf(fpo," vsize zoomymax zoomymin sub epcadre 2 mul add div hsize zoomxmax zoomxmin sub epcadre 2 mul add div\n") ;
fprintf(fpo," 2 copy gt { exch } if pop dup scale\n") ;
fprintf(fpo," zoomxmin zoomxmax add 2 div neg zoomymin zoomymax add 2 div neg translate\n") ;
fprintf(fpo,"}\n") ;
fprintf(fpo,"{ %% integration sur TeX\n") ;
fprintf(fpo," /bavard false def\n") ;
fprintf(fpo," texdvipsval\n") ;
fprintf(fpo," { %% integration par DVIPS et DVI2PS\n") ;
fprintf(fpo," -1 -1 scale\n") ;
fprintf(fpo," zoomxmax neg tracecad {epcadre sub} if zoomymin neg tracecad {epcadre add} if translate\n") ;
fprintf(fpo," }\n") ;
fprintf(fpo," { %% integration par TEXTURES\n") ;
fprintf(fpo," zoomxmin neg tracecad {epcadre add} if zoomymin neg tracecad {epcadre add} if translate\n") ;
fprintf(fpo," }\n") ;
fprintf(fpo," ifelse\n") ;
fprintf(fpo,"}\n") ;
fprintf(fpo,"ifelse\n") ;
fprintf(fpo,"gsave\n") ;
fprintf(fpo,"zoomxmin zoomymin zoomxmax zoomymax cadrepath clip newpath\n") ;
fprintf(fpo,"/charge { %% Chargement d'une fonte. pile : /police /corps (/ si normal) /style (/ si roman) haut larg (.) (mono ou prop)\n") ;
fprintf(fpo," /mat [10 0 0 10 0 0] def /mats [10 0 0 10 0 0] def 6 3 roll\n") ;
fprintf(fpo," /g@t {getinterval} bind def /p@t {putinterval} bind def\n") ;
fprintf(fpo," /sty exch 20 string cvs def /cor exch 20 string cvs def /pol exch 30 string cvs def\n") ;
fprintf(fpo," /lpo pol length def /lco cor length def /lst sty length def /fon 71 string def\n") ;
fprintf(fpo," fon 0 pol p@t lco lst add 0 ne\n") ;
fprintf(fpo," {fon lpo (-) p@t fon lpo 1 add cor p@t fon lpo 1 add lco add sty p@t}{/lpo lpo 1 sub def} ifelse\n") ;
fprintf(fpo," bavard{/err 100 string def err 0 fon 0 lpo lco lst 1 add add add g@t p@t} if\n") ;
fprintf(fpo," lst 0 ne{sty 0 1 g@t (O) eq {mats 2 mats 3 get 0.25 mul put} if\n") ;
fprintf(fpo," sty 0 1 g@t (I) eq {mats 2 mats 3 get 0.2 mul put} if} if\n") ;
fprintf(fpo," fon 0 lpo lco lst 1 add add add g@t cvn FontDirectory exch known\n") ;
fprintf(fpo," {/lfo lpo lco lst 1 add add add def bavard {err 50 (OK) p@t err counttomark 1 roll} if}\n") ;
fprintf(fpo," {fon 0 lpo lco 1 add add g@t cvn FontDirectory exch known {true}{\n") ;
fprintf(fpo," fon 0 lpo g@t cvn FontDirectory exch known {/cor () def /lco 0 def true}\n") ;
fprintf(fpo," {/cor (Roman) def /lco 5 def fon 0 fon lpo 1 add cor p@t\n") ;
fprintf(fpo," lpo lco 1 add add g@t cvn FontDirectory exch known\n") ;
fprintf(fpo," {true}{/cor () def /lco 0 def false} ifelse } ifelse } ifelse\n") ;
fprintf(fpo," {fon lpo (-) p@t fon lpo 1 add cor p@t fon lpo 1 add lco add sty p@t\n") ;
fprintf(fpo," lst 0 ne {fon 0 lpo lco lst 1 add add add g@t cvn FontDirectory exch known}{false}ifelse\n") ;
fprintf(fpo," {/lfo lpo lco lst 1 add add add def\n") ;
fprintf(fpo," bavard {err 50 (--> ) p@t err 54 fon 0 lfo g@t p@t err counttomark 1 roll } if }\n") ;
fprintf(fpo," {lco 0 ne {/lfo lpo lco 1 add add def}{/lfo lpo def} ifelse /mat mats def\n") ;
fprintf(fpo," bavard {err 50 (--> ) p@t err 54 fon 0 lfo g@t p@t\n") ;
fprintf(fpo," lst 0 ne{err 54 lfo add ( /penche/) p@t} if err counttomark 1 roll} if } ifelse }\n") ;
fprintf(fpo," {dup dup /fon exch (m) eq {fontm0}{fontp0}ifelse 71 string cvs def /lfo fon length def /mat mats def\n") ;
fprintf(fpo," bavard {(m) eq {err 50 (--> fontm0 par defaut) p@t}{err 50 (--> fontp0 par defaut) p@t}ifelse\n") ;
fprintf(fpo," lst 0 ne{err 71 ( /penche/) p@t} if err counttomark 1 roll}{pop} ifelse } ifelse\n") ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo," pop fon 0 lfo g@t cvn findfont mat makefont setfont newpath 0 0 moveto\n") ;
fprintf(fpo," (abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890) true charpath flattenpath pathbbox\n") ;
fprintf(fpo," 4 1 roll exch pop exch sub exch 4 1 roll exch 1.0 mul exch div 3 1 roll 1.0 mul dup /tfont exch def exch div\n") ;
fprintf(fpo," dup mat 2 mat 2 get 4 -1 roll mul put mat 3 mat 3 get 4 -1 roll mul put mat 0 mat 0 get 4 -1 roll mul put\n") ;
fprintf(fpo," fon 0 lfo g@t cvn findfont mat makefont setfont\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,fontcour) ;
fprintf(fpo,"fondcou { gsave zoomxmin zoomymin zoomxmax zoomymax cadrepath 0 setgray fill grestore } if\n") ;
fprintf(fpo,"0 setlinecap\n") ;
fprintf(fpo,"1 setlinejoin\n") ;
do { ligne = fgets(buf,255,fpi) ;
if ( ligne == buf ){
fprintf(fpo,"%s",buf) ;
}
} while ( ligne == buf ) ;
fclose(fpi) ;
fpi = NULL ;

if ( modepsc != 0 ){
/* ecriture des legendes qualites ou isovaleurs */
if ( strlen(chaine[7]) != 0 ){
fprintf(fpo,"\n%%%% Debut : Legende des qualites ou des isovaleurs\n\n") ;
fprintf(fpo,"tracemen 1 eq tracecou 2 eq and { %% test sur le trace effectif\n") ;
fprintf(fpo,"%%%% Redefinition locale pour la legende des qualites ou des isovaleurs\n") ;
fprintf(fpo,"/epais{ %% epaisseur du trait pile : num\n") ;
fprintf(fpo," setlinewidth\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/S{ %% trace d'un segment pile : x2 y2 x1 y1 coul\n") ;
fprintf(fpo," gsave setcose newpath m@veto l@neto stroke grestore\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/R{ %% remplissage d'un rectangle en coul pile : dx dy x y coul\n") ;
fprintf(fpo," gsave couleur { pop s@tcou\n") ;
fprintf(fpo," }{ dup 1 exch sub gfafo mul exch gfacl mul add setgray pop pop pop\n") ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo," newpath m@veto 0 exch 0 exch 2 copy neg 6 2 roll rl@neto rl@neto rl@neto\n") ;
fprintf(fpo," closepath gsave fill grestore 0 setgray 0.5 epais stroke grestore\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/T{ %% impression chaine de caracteres\n") ;
fprintf(fpo," couleur { pop setrgbcolor }{ setgray pop pop pop } ifelse\n") ;
fprintf(fpo," m@v@t@ sh@w\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"0 setlinecap\n") ;
fprintf(fpo,"0 setlinejoin\n\n") ;
fprintf(fpo,"%%%% Legende\n") ;
fprintf(fpo,chaine[7]) ;
fprintf(fpo,"} if\n") ;
fprintf(fpo,"\n%%%% Fin : Legende des qualites ou des isovaleurs\n") ;
}

/* ecriture des menus */
if ( menu ){
fprintf(fpo,"\n%%%% Debut : Menus\n\n") ;
fprintf(fpo,"tracemen 2 eq { %% test sur le trace effectif\n") ;
fprintf(fpo,"%%%% Redefinition locale pour les menus\n") ;
fprintf(fpo,"/epais{ %% epaisseur du trait pile : num\n") ;
fprintf(fpo," dup 4 ge { 0.2 setgray }{ 0 setgray } ifelse setlinewidth\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/S{ %% trace d'un segment pile : x2 y2 x1 y1 coul\n") ;
fprintf(fpo," gsave couleur { pop s@tc@u }{ pop pop pop pop } ifelse\n") ;
fprintf(fpo," newpath moveto lineto stroke grestore\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/R{ %% remplissage d'un rectangle en coul pile : dx dy x y coul\n") ;
fprintf(fpo," gsave couleur { pop setrgbcolor }\n") ;
fprintf(fpo," { dup 1 exch sub gfafo mul exch gfacl mul add setgray pop pop pop\n") ;
fprintf(fpo," } ifelse\n") ;
fprintf(fpo," newpath moveto 0 exch 0 exch 2 copy neg 6 2 roll rl@neto rl@neto rl@neto\n") ;
fprintf(fpo," closepath gsave fill grestore 0 setgray 0.5 epais stroke grestore\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"/T{ %% impression chaine de caracteres\n") ;
fprintf(fpo," couleur { pop setrgbcolor }{ setgray pop pop pop } ifelse\n") ;
fprintf(fpo," m@v@t@ sh@w\n") ;
fprintf(fpo,"} bind def\n") ;
fprintf(fpo,"0 setlinecap\n") ;
fprintf(fpo,"0 setlinejoin\n\n") ;
car = "(" ;
for ( i = 0 ; i < strlen(chaine[5]) ; i++ ){
if ( chaine[5][i] == *car ){
sprintf(&chaine[5][i],"%s%s",
"(? .)",
&chaine[5][i+98]);
}
}
for ( i = 0 ; i < 7 ; i++ ){
if ( strlen(chaine[i]) != 0 ){
switch (i){
case 0 :
sprintf(format,"Documentation") ;
break ;
case 1 :
sprintf(format,"Historique") ;
break ;
case 2 :
sprintf(format,"Menu") ;
break ;
case 3 :
sprintf(format,"Lignes lues") ;
break ;
case 4 :
sprintf(format,"Invite") ;
break ;
case 5 :
sprintf(format,"Ligne de saisie") ;
break ;
case 6 :
sprintf(format,"Erreur") ;
break ;
}
fprintf(fpo,"\n%%%% Debut : %s\n",format) ;
fprintf(fpo,chaine[i]) ;
fprintf(fpo,"%%%% Fin : %s\n",format) ;
}
}
fprintf(fpo,"} if\n") ;
}
}
fprintf(fpo,"%%\n") ;
fprintf(fpo,"grestore\n") ;
fprintf(fpo,"tracecad { %% then trace d'un cadre\n") ;
fprintf(fpo," gsave zoomxmin epcadre sub zoomymin epcadre sub\n") ;
fprintf(fpo," zoomxmax epcadre add zoomymax epcadre add cadrepath clip\n") ;
fprintf(fpo," zoomxmin epcadre 2 div sub zoomymin epcadre 2 div sub\n") ;
fprintf(fpo," zoomxmax epcadre 2 div add zoomymax epcadre 2 div add cadrepath\n") ;
fprintf(fpo," epcadre setlinewidth str@k grestore\n") ;
fprintf(fpo,"} if\n") ;
if ( modepsc != 0 )
{
fprintf(fpo,"tracelog { %% then trace du logo\n") ;
fprintf(fpo," gsave /taille 45 reduclog mul def /ZapfChancery-MediumItalic findfont taille scalefont setfont\n") ;
fprintf(fpo," /tailbl taille 16 div def /larlog (Me\\256sto) stringwidth pop tailbl 6 mul add def\n") ;
fprintf(fpo," /haulog taille tailbl 3 mul add def\n") ;
fprintf(fpo," /rays{ gsave larlog 2 div haulog neg translate\n") ;
fprintf(fpo," newpath 121 {larlog 2 mul 0 moveto 0 0 lineto 0.5 rotate larlog 2 mul 0 lineto closepath\n") ;
fprintf(fpo," fill 0 0 moveto 1.0 rotate } repeat grestore\n") ;
fprintf(fpo," } bind def\n") ;
fprintf(fpo," zoomxmax zoomxmin add larlog sub 2 div zoomxmax zoomxmin sub larlog sub 2 div xpolog mul add\n") ;
fprintf(fpo," zoomymax zoomymin add haulog add 2 div zoomymax zoomymin sub haulog sub 2 div ypolog mul add\n") ;
fprintf(fpo," translate 0 0 moveto larlog haulog neg 0 exch 0 exch 2 copy neg 6 2 roll\n") ;
fprintf(fpo," rlineto rlineto rlineto closepath gsave fondcou {0}{1} ifelse setgray fill grestore\n") ;
fprintf(fpo," 1 reduclog mul setlinewidth fondcou {1}{0} ifelse setgray stroke\n") ;
fprintf(fpo," tailbl 2 mul taille 0.75 mul tailbl add neg translate 0 0 moveto\n") ;
fprintf(fpo," gsave (Me\\256sto) true charpath clip rays grestore gsave (Me) stringwidth pop 0 rmoveto\n") ;
fprintf(fpo," (e) stringwidth pop (\\302) stringwidth pop add 2 div neg 0 rmoveto\n") ;
fprintf(fpo," (\\302) true charpath clip rays grestore grestore\n") ;
fprintf(fpo,"} if\n") ;
}
fprintf(fpo,"encadre\n") ;
fprintf(fpo,"gsave grestore\n") ;
fprintf(fpo,"texval not { showpage } if\n") ;
fprintf(fpo,"bavard{\n") ;
fprintf(fpo," 1 cm 28.7 cm translate /Courier findfont 10 scalefont setfont\n") ;
fprintf(fpo," 0 -15 moveto (FONTE DEMANDEE FONTE UTILISEE) show\n") ;
fprintf(fpo," 0 -30 moveto counttomark {dup show stringwidth pop neg -15 rmoveto} repeat\n") ;
fprintf(fpo," showpage\n") ;
fprintf(fpo,"} if\n") ;
fprintf(fpo,"cleartomark\n") ;
fclose(fpo) ;
fpo = NULL ;
if ( modepsc != 0 )
{ for (i = 0; i < 8 ; i++) {chaine[i] = '\0'; free(chaine[i]);} }
remove("TEMPORAIRE.EPS") ;
menu = 0 ;

/* sauvegarde du fichier temporaire des histogrammes de qualite */
if ( modepsc != 0 )
{
if ( (fpi = fopen("TEMPORAIRE.QUA","r")) != NULL )
{
sprintf(format,"%%.%ds.qua",length) ;
sprintf(buf,format,nomfichier) ;
fpo = NULL ;
if ((fpo = fopen(buf,"w"))==NULL)
{
printf ("Erreur d'ouverture de fichier\n") ;
length = -1 ;
}
else
{
do{
ligne = fgets(buf,255,fpi) ;
if ( ligne == buf )
{
fprintf(fpo,"%s",buf) ;
}
} while ( ligne == buf ) ;
fclose(fpi) ;
fpi = NULL ;
fclose(fpo) ;
fpo = NULL ;
length = 0 ;
remove("TEMPORAIRE.QUA") ;
}
}
else
length = 0 ;
}
}
}

int nbchiffre1R( R r )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer l'exposant de 10 d'un nombre R r tel que
// ----- r = rr * 10**nbchiffre1R avec 1 <= rr < 10
//
// entree:
// -------
// r : le nombre R
//
// sortie:
// -------
// nbchiffre1R : l'exposant de 10 du nombre R
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris Novembre 2000
//2345x7..........................................................012
{
R rr;
int nbchir;

//protection du cas zero
if( r == 0 ) return 0;

nbchir = 0;
rr = r;
if( rr <0 ) rr=-rr;

boucle:
if( rr >= 10.0 )
{
//R plus grand que 10
nbchir = nbchir + 1;
rr = rr / 10;
goto boucle;
}
else if( rr < 1.0 )
{
//R plus petit que 0.1
nbchir = nbchir - 1;
rr = rr * 10;
goto boucle;
}

//ici rr est un R compris entre 1 et 10
return nbchir;
}


void VuGraduation( R rmin, R rmax,
R &premier, R &pas, int &nbpas, int &nbchif )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcule la graduation a tracer entre rmin et rmax
// ----- pour obtenir une lecture aisee (peu de decimales tracees)
// avec a peu pres 10 nombres reels a tracer
//
// entrees:
// --------
// rmin, rmax: mininmum et maximum de la graduation
//
// sorties:
// --------
// premier: premier R a tracer
// pas : entre 2 nombres a tracer
// nbpas : nombre de pas
// nbchif : nombre de decimales a tracer
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R dixnbe, r;
int nbe, n1;

//10 nombres a peu pres sont a tracer
pas = ( rmax - rmin ) / 10;

//exposant de 10 du pas
nbe = nbchiffre1R( pas );

//la puissance de 10 de pas
if( nbe >= 0 )
dixnbe = pow(10.0,nbe);
else
dixnbe = 1.0 / pow(10.0,-nbe);

//le premier chiffre significatif de pas
n1 = (int) (pas / dixnbe);

//le second chiffre significatif de pas sous la forme 0.n2
r = ( pas - n1 * dixnbe ) / dixnbe;

//le nombre n1.n2
r = n1 + r;

//le vrai pas
n1 = (int) (r+0.5);

//valeur plus lisible
if( n1 >= 3 && n1 <= 7 ) n1 = 5;
if( n1 >= 8 ) n1 = 10;
pas = n1 * dixnbe;

//le plus grand multiple de pas < rmin
premier = ( (int) ( rmin / pas ) ) * pas;

//le nombre de pas
nbpas = (int)( (rmax-rmin) / pas + 0.5) + 1;

//le nombre de decimales a tracer pour chaque R
nbchif = Max( nbchiffre1R(rmin), nbchiffre1R(rmax) )
- nbchiffre1R(pas) + 1;

return;
}

inline int MemoirePx2d::Vunupxex( R xob )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : retourne le numero du pixel ( abscisse ) de xob dans la fenetre
// -----
//
// entree :
// --------
// xob : abscisse objet du point
//
// sortie :
// --------
// Vunupxex : numero du pixel ou abscisse px du point d'abscisse objet xob
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int x;

// transformation xob => px x
x = (int) (axobpx * xob + bxobpx + 0.5);

// protection contre une valeur absolue trop grande
// et detection d'un point largement hors fenetre
if ( x <= minint || x >= maxint ) x = minint;

// la valeur finale
return x;
}


inline int MemoirePx2d::Vunupxey( R yob )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : retourne le numero du pixel ( ordonnee ) de yob dans la fenetre
// -----
//
// entree :
// --------
// yob : ordonnee objet du point
//
// sortie :
// --------
// Vunupxey : numero du pixel ou ordonnee px du point d'ordonnee objet yob
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int y;

// transformation yob => px y
y = (int) (ayobpx * yob + byobpx + 0.5);

// protection contre une valeur absolue trop grande
// et detection d'un point largement hors fenetre
if( y <= minint || y >= maxint ) y = minint;

// la valeur finale
return y;
}


R MemoirePx2d::Vuxob2px( int nxpx )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : retourne la valeur de l'abscisse objet 2d d'un pixel d'abscisse
// ----- nxpx de la fenetre actuelle px x => x ob
// fonction inverse de Vunupxex
//
// entree :
// --------
// nxpx : abscisse pixel du point
//
// sortie :
// --------
// Vuxob2px : ordonnee objet 2d du pixel de la fenetre actuelle
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// transformation px x => x ob
return (R) ( ( nxpx - bxobpx ) / axobpx );
}


R MemoirePx2d::Vuyob2px( int nypx )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : retourne la valeur de l'ordonnee objet 2d d'un pixel d'ordonnee
// ----- nypx de la fenetre actuelle px y => y ob
// fonction inverse de Vunupxey
//
// entree :
// --------
// nypx : ordonnee pixel du point
//
// sortie :
// --------
// Vuyob2px : ordonnee objet 2d du pixel de la fenetre actuelle
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// transformation px y => y ob
return (R) ( ( nypx - byobpx ) / ayobpx );
}


void MemoirePx2d::VuFenetre2d( R xutmin, R xutmax,
R yutmin, R yutmax )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : definir la mise a l'echelle pour voir la fenetre actuelle
// ----- selon les coordonnees objet 2d donnees ici
// selon un repere a priori non orthonorme
// et stocker les coefficients de conversion
//
// entrees :
// ---------
// xutmin : abscisse objet de la gauche de la fenetre
// xutmax : abscisse objet de la droite de la fenetre
// yutmin : ordonnee objet du bas de la fenetre
// yutmax : ordonnee objet du haut de la fenetre
//
// sorties :
// ---------
// tous les coefficients sont stockes dans les donnees de la classe
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
if( xutmin > xutmax ) Echange(xutmin,xutmax);
if( yutmin > yutmax ) Echange(yutmin,yutmax);
if( xutmin == xutmax )
{
cout << "Appel VuFenetre2d incorrect: x min = x max =" << xutmin;
return;
}

if( yutmin == yutmax )
{
cout << "Appel VuFenetre2d incorrect: y min = y max =" << yutmin;
return;
}

// fenetre correcte
visee = 2; //mode de visee 2d
xobmin = xutmin;
xobmax = xutmax;
yobmin = yutmin;
yobmax = yutmax;

// calculs des coefficients de la transformation x objet => pixels x
// xob -> x pixels Vunupxex(x) = axobpx * x + bxobpx
axobpx = R(largeurpx) / ( xobmax - xobmin );
bxobpx = - axobpx * xobmin;

// calculs des coefficients de la transformation y objet => pixels y
// yob -> y pixels Vunupxey(y) = ayobpx * y + byobpx
ayobpx = R(hauteurpx) / ( yobmin - yobmax );
byobpx = - ayobpx * yobmax;
}


void MemoirePx2d::VuIsoFenetre2d( R xobjmi, R xobjmx,
R yobjmi, R yobjmx )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : definir la mise a l'echelle pour voir la fenetre actuelle
// ----- selon les coordonnees objet donnees ici
// selon un repere orthonorme => le plus grand ecart en x ou y
// est ajuste a la largeur ou hauteur
// de la fenetre
// stocker les coefficients de conversion
//
// entrees :
// ---------
// xobjmi : abscisse objet de la gauche de la fenetre
// xobjmx : abscisse objet de la droite de la fenetre
// yobjmi : ordonnee objet du bas de la fenetre
// yobjmx : ordonnee objet du haut de la fenetre
//
// sorties :
// ---------
// tous les coefficients sont stockes dans les donnees membres de la classe
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R r;
R ex, ey, xutmin, xutmax, yutmin, yutmax;

//protection contre une erreur de donnees
if( xobjmi > xobjmx ) Echange(xobjmi,xobjmx);
if( yobjmi > yobjmx ) Echange(yobjmi,yobjmx);

if( xobjmi == xobjmx )
{
cout << "Appel VuIsoFenetre2d incorrect: x min=" << xobjmi
<< " = x max =" << xobjmx << endl;
return;
}
if( yobjmi == yobjmx )
{
cout << "Appel VuIsoFenetre2d incorrect: y min=" << yobjmi
<< " = y max =" << yobjmx << endl;
return;
}

// rapport largeur fenetre / hauteur fenetre corrige
// par le rapport des dimensions d'un pixel (largeur et hauteur)
r = R(largeurpx) / R(hauteurpx) * cymmpx / cxmmpx;

// recherche de la plus grande des 2 dimensions en mode objet
ex = xobjmx - xobjmi;
ey = yobjmx - yobjmi;
if( ex >= ey*r )
{
// xob min et max realisent la gauche et la droite de la fenetre
xutmin = xobjmi;
xutmax = xobjmx;
ey = ex / r; // hauteur objet mise a l'echelle
yutmin = ( yobjmi + yobjmx - ey ) * 0.5; //centrage en hauteur
yutmax = yutmin + ey;
}
else
{
// yob min et max realisent le bas et le haut de la fenetre
yutmin = yobjmi;
yutmax = yobjmx;
ex = ey * r; // largeur objet mise a l'echelle
xutmin = ( xobjmi + xobjmx - ex ) * 0.5; //centrage en largeur
xutmax = xutmin + ex;
}

// calcul des coefficients des transformations objet->pixels
VuFenetre2d( xutmin, xutmax, yutmin, yutmax );
}


void MemoirePx2d::VuTexte( R2 xy, char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres du texte
// ----- a partir du point (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entree :
// --------
// xy : abscisse ordonnee objet2d du texte a tracer
// texte : les caracteres a tracer
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbcar;
XPoint pxy;

// le nombre de caracteres du texte
// a partir de la fin arret au premier caractere non blanc rencontre
nbcar = nudcnb( texte );
if( nbcar <= 0 ) return;

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( xy.x );
pxy.y = Vunupxey( xy.y );
if( pxy.x <= minint || pxy.y <= minint ) return;

// trace effectif
MemoirePx::VuTexte( pxy, texte );
}


void MemoirePx2d::VuSymbole( R2 xy, char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le texte
// ----- a partir du point (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
// la chaine est decalee d'un demi caractere vers le bas et a gauche
//
// entree :
// --------
// xy : abscisse ordonnee objet2d du symbole
// texte : la chaine de caracteres servant de symbole
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy;

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( xy.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( xy.y );
if( pxy.y <= minint ) return;

MemoirePx::VuSymbole( pxy, texte );
}


void MemoirePx2d::VuEntier( R2 xy, int entier )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de l'entier
// ----- a partir du point (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entree :
// --------
// xy : abscisse ordonnee objet2d des caracteres de la valeur de l'entier
// entier : entier dont la valeur doit etre tracee precedee de '.'
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbcar;
XPoint pxy;
char txt[12];

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( xy.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( xy.y );
if( pxy.y <= minint ) return;

// translation pour centrer le .
pxy.x -= nplaca/2;
pxy.y += 2;

// le caractere '.' precede le numero
strcpy( txt, "." );

// le nombre de caracteres de l'entier
itoa( entier, nbcar, (txt+1) );

// le trace de la chaine des nbcar+1 caracteres
MemoirePx::VuTexte( pxy, txt );
}


void MemoirePx2d::VuReel( R2 xy, R vR, int nbchif10 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de vR
// ----- a partir du point (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// xy : abscisse ordonnee objet2d des caracteres de vR
// vR : valeur Rle a tracer
// nbchif10: nombre de chiffres demandes de la partie decimale
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy;
int nbcar;
char txt[26];

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( xy.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( xy.y );
if( pxy.y <= minint ) return;

// translation pour centrer le .
pxy.x -= nplaca/2;
pxy.y += 2;

// le caractere '.' precede le numero
strcpy( txt, "." );

// les caracteres finaux de vR
rtoa( vR, nbchif10, nbcar, (txt+1) );

// le trace de la chaine de caracteres
MemoirePx::VuTexte( pxy, txt );
}

void MemoirePx2d::VuTrait( R2 xy1, R2 xy2 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le trait 2d de (x1,y1) a (x2,y2)
// ----- attention (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// xy1 : 1-ere extremite du trait
// xy2 : 2-eme extremite du trait
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy1, pxy2;

// transformation en pixels
pxy1.x = Vunupxex( xy1.x);
if( pxy1.x <= minint ) return;

pxy2.x = Vunupxex( xy2.x );
if( pxy2.x <= minint ) return;

pxy1.y = Vunupxey( xy1.y );
if( pxy1.y <= minint ) return;

pxy2.y = Vunupxey( xy2.y );
if( pxy2.y <= minint ) return;

// trace effectif
MemoirePx::VuTrait( pxy1, pxy2 );
}


void MemoirePx2d::VuTraits( int nbs, R2 xy[] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les segments de droite (x(i),y(i)) (x(i+1),y(i+1))
// ----- pour i=1 a nbs
//
// attention (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// nbs : nombre de sommets des traits a tracer
// xy : abscisse et ordonnee objet des nbs sommets des traits
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint xypx[512];
int i, nx, ny;

// verification
if( nbs <= 2 ) return;
if( nbs > 512 )
{
cout << "Augmenter 512 dans MemoirePx2d::VuTraits()\n";
return;
}

// transformation en pixels dans la fenetre Vu
for ( i=0; i<nbs; i++ )
{
nx = Vunupxex( xy[i].x );
// si le numero pixel est incorrect abandon du trace de la face
if( nx <= minint ) return;
ny = Vunupxey( xy[i].y );
if( ny <= minint ) return;
xypx[i].x = nx;
xypx[i].y = ny;
}

// trace effectif des traits
MemoirePx::VuTraits( nbs, xypx );
}


void MemoirePx2d::VuVecteur( R2 xypt, R2 xyvect )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer le vecteur xyvect a partir d'un point de coordonnees xypt
// -----
// entrees:
// --------
// xypt : X Y du point
// xyvect : X Y du vecteur
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//...................................................................
{
R2 xy;
XPoint pxy1, pxy2;

// les coordonnees en pixels sur l'ecran du point
pxy1.x = Vunupxex( xypt.x );
pxy1.y = Vunupxey( xypt.y );

// le vecteur en ce point
xy = xypt + xyvect;

// les coordonnees en pixels sur l'ecran de la pointe du vecteur
pxy2.x = Vunupxex( xy.x );
pxy2.y = Vunupxey( xy.y );

// le trace du vecteur
MemoirePx::VuTrait( pxy1, pxy2 );
}


void MemoirePx2d::VuAxes( )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer les axes et la grille du SCU en 2d
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Mars 2001
//...................................................................
{
R ecartx, ecarty, x, y, premierx, premiery, yaxeX;
char texte[16];
int i, nbcar, nbpasx, nbpasy;

//choix d'une petite fonte
VuChoisirFonte( 12 );

//l'ecran a pour coordonnees xobmin xobmax et yobmin yobmax
//ecart en % definit la marge entre les axes et le bord de l'ecran
ecartx = (xobmax-xobmin) * 0.01;
ecarty = (yobmax-yobmin) * 0.01;

//la valeur des graduations en X et en Y
//calcul du nombre de pas entre xobmin et xobmax en largeur
nbpasx = int(( xobmax - xobmin ) / PasGrilleSCU.x ) + 1;
premierx = SCU[0].x + int((xobmin-SCU[0].x)/PasGrilleSCU.x+1) * PasGrilleSCU.x;

//calcul du nombre de pas entre yobmin et yobmax en hauteur
nbpasy = int(( yobmax - yobmin ) / PasGrilleSCU.y ) + 1;
premiery = SCU[0].y + int((yobmin-SCU[0].y)/PasGrilleSCU.y+1) * PasGrilleSCU.y;

//le trace des lignes verticales X=Cte de la grille du SCU
//==================================================
if( CouleurGrilleSCU>=0 )
{
VuCouleur( CouleurGrilleSCU );
VuEpaisseur( 0 );
for (i=0; i<=nbpasx; i++)
{
//l'abscisse de la ligne verticale a tracer
x = premierx + i * PasGrilleSCU.x;
//le trait vertical en ce point
VuTrait( R2(x,yobmin), R2(x,yobmax) );
}
}

//le trace de l'axe des X
//=======================
VuEpaisseur( 2 );
VuCouleur( Rouge );
yaxeX=yobmin+ecarty*4;
VuTrait( R2(xobmax,yaxeX), R2(xobmin,yaxeX) );
//le caractere X en fin de ligne
VuTexte( R2(xobmax-ecartx*6,yaxeX+ecarty), "-X->" );
//le trace des graduations sur l'axe des X
VuEpaisseur( 0 );
y = yaxeX;
for (i=0; i<=nbpasx; i++)
{
//l'abscisse du nombre a tracer
x = premierx + i * PasGrilleSCU.x;
//le trait vertical en ce point
VuCouleur( Rouge );
VuTrait( R2(x,y-ecarty), R2(x,y+ecarty) );
//la valeur de l'abscisse avec 2 chiffres decimaux
rtoa( x, 2, nbcar, texte );
VuCouleur( CouleurChiffre );
VuTexte( R2(x-ecartx*2,y+ecarty*0.5), texte );
}

//le trace des lignes horizontales Y=Cte de la grille du SCU
//====================================================
if( CouleurGrilleSCU>=0 )
{
VuCouleur( CouleurGrilleSCU );
VuEpaisseur( 0 );
x = xobmin + ecartx;
for (i=0; i<=nbpasy; i++)
{
//l'abscisse du nombre a tracer
y = premiery + i * PasGrilleSCU.y;
//le trait vertical en ce point
VuTrait( R2(xobmin,y), R2(xobmax,y) );
}
}

//le trace de l'axe des Y
//=======================
VuEpaisseur( 2 );
VuCouleur( Vert );
VuTrait( R2(xobmin+ecartx,yobmin), R2(xobmin+ecartx,yobmax) );
//le caractere Y
VuTexte( R2(xobmin-ecartx*2,yobmax-ecarty*10), "Y" );
//le trace des graduations sur l'axe des Y
VuEpaisseur( 0 );
x = xobmin + ecartx;
for (i=0; i<=nbpasy; i++)
{
//l'abscisse du nombre a tracer
y = premiery + i * PasGrilleSCU.y;
//le trait vertical en ce point
VuCouleur( Vert );
VuTrait( R2(x-ecartx,y), R2(x+ecartx,y) );
//la valeur de l'ordonnee avec 2 chiffres decimaux
rtoa( y, 2, nbcar, texte );
VuCouleur( CouleurChiffre );
VuTexte( R2(xobmin,y+ecarty*0.3), texte );
}
}


void MemoirePx2d::VuCourbeP3H( int nca, int nepa, R porear,
int ncotg, int neptg, int ntrtg,
R2 xys1, R2 xys2,
R2 xytg1, R2 xytg2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer la courbe 2d interpolation P3-HERMITE passant par
// ----- les 2 sommets xys1 et xys2 et tangente aux vecteurs xyztg1 et xyztg2
// Attention la direction de la tangente en xys2 est xys2->xys1
// entrees:
// --------
// nca : numero de la couleur des aretes a tracer
// <0 pas de trace des aretes de la courbe
// nepa : nombre d'epaisseurs a ajouter au trait d'une arete
// porear : pourcentage de reduction du trace d'une arete 0.0<=porear<=100.0
// nctg : >=0 numero de la couleur des 2 tangentes a tracer
// < 0 pas de trace des 2 tangentes
// neptg : >=0 nombre d'epaisseurs a ajouter au trait d'une tg
// ntrtg : trace en continu(0) ou pointille (1) ou double pointille(2)
// xys1 : X et Y du sommet 1
// xys2 : X et Y du sommet 2
// xytg1 : X et Y de la tangente au sommet 1 dans la direction s1->s2
// xytg2 : X et Y de la tangente au sommet 2 dans la direction s2->s1
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//...................................................................
{
int i, nx1, ny1, nx2, ny2, nbsuba;
R reduction, reductio1, h, p, u;
XPoint xypx[1+mxsucb];

// si couleur negative => retour
if( nca < 0 ) return;

// la reduction de l'arete entre 0 et 1
// 0.005 = 0.01/3 car trace ici dans l'element de reference
// et non par rapprochement du barycentre comme dans le cas d'ef p1
reduction = porear * 0.00333;
reductio1 = 1.0 - reduction;

// recherche du nombre de subdivisions de l'ef reduit de reference [0,1]
// selon le nombre de pixels obtenus apres mise a l'echelle pixels
// =========================================================
// transformation en pixels dans la fenetre du sommet 1
nx1 = Vunupxex( xys1[0] );
if( nx1 <= minint ) return;
// si le numero pixel est incorrect abandon du trace de l'arete
ny1 = Vunupxey( xys1[1] );
if( ny1 <= minint ) return;

// transformation en pixels dans la fenetre du sommet 2
nx2 = Vunupxex( xys2[0] );
if( nx1 <= minint ) return;
// si le numero pixel est incorrect abandon du trace de l'arete
ny2 = Vunupxey( xys2[1] );
if( ny1 <= minint ) return;

// nombre de subdivision en aretes de la courbe P3 Hermite
nbsuba = Max( abs(nx2-nx1), abs(ny2-ny1) );
if( nbsuba == 0 ) return;
nbsuba = Min( Max(2,nbsuba/8), mxsucb );

//les coordonnees xy pixels des sommets des sous-aretes
h = ( reductio1 - reduction ) / nbsuba;
u = reduction;
for ( i=0; i<=nbsuba; i++ )
{
xypx[i].x = Vunupxex( ValeurP3H( u, xys1[0],xys2[0], xytg1[0],xytg2[0] ) );
xypx[i].y = Vunupxey( ValeurP3H( u, xys1[1],xys2[1], xytg1[1],xytg2[1] ) );
u = u + h;
}

//le trace des nbsuba sous aretes
VuCouleur( nca );
VuEpaisseur( nepa );
MemoirePx::VuTraits( 1+nbsuba, xypx );

// trace eventuel des tangentes aux 2 sommets
if( ncotg >= 0 )
{
VuCouleur( ncotg );
VuTypeTrait( ntrtg );
VuEpaisseur( neptg );
VuVecteur( xys1, xytg1 );
VuVecteur( xys2, xytg2 );
}
}


void MemoirePx2d::VuFace( int nbs, R2 xy[] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace la face 2d de sommets (x,y)
// -----
// attention (x,y) en coordonnees objet 2d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// nbs : nombre de sommets de la face a tracer
// xy : abscisse ordonnee objet des nbs sommets de la face
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
int nbsp, nx ,ny;
XPoint xypx[512];

// verification
if( nbs <= 2 ) return;
if( nbs > 512 )
{
cout << "Augmenter 512 dans MemoirePx2d::VuFace()\n";
return;
}

// transformation en pixels dans la fenetre
for ( nbsp=0; nbsp<nbs; nbsp++ )
{
nx = Vunupxex( xy[nbsp].x );
if( nx <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
ny = Vunupxey( xy[nbsp].y );
if( ny <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
xypx[nbsp].x = nx;
xypx[nbsp].y = ny;
}

// fermeture des aretes du polygone de la face
if( xypx[nbs-1].x != xypx[0].x || xypx[nbs-1].y != xypx[0].y )
{
// fermeture du polygone
xypx[nbs].x = xypx[0].x;
xypx[nbs].y = xypx[0].y;
nbsp = nbs + 1;
}
else
// polygone deja ferme
nbsp = nbs;

// trace effectif du remplissage de la face sans le contour
MemoirePx::VuFace( nbsp, xypx );
}

void MemoirePx2d::VuBordTriangle( R2 xys1, R2 xys2, R2 xys3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Trace les 3 aretes du triangle de sommets xys
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
VuTrait( xys1, xys2 );
VuTrait( xys2, xys3 );
VuTrait( xys3, xys1 );
}

void MemoirePx2d::VuTriangleCouleur( R2 xys1, R2 xys2, R2 xys3,
R couleur1, R couleur2, R couleur3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le triangle de sommets xys1, xys2, xys3 de couleurs 1 2 3
// ----- selon les couleurs intermediaires (PALETTE 11 RECOMMANDEE)
// entrees:
// --------
// couleur i: couleur entre n1coul et ndcoul dans la palette actuelle
// xys i : coordonnees du sommet i=1,2,3
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint xypx1, xypx2, xypx3;
int nx, ny;

// Sommet 1
//=========
// transformation en pixels dans la fenetre
nx = Vunupxex( xys1.x );
if( nx <= minint ) return;
ny = Vunupxey( xys1.y );
if( ny <= minint ) return;
xypx1.x = nx;
xypx1.y = ny;

// Sommet 2
//=========
// transformation en pixels dans la fenetre
nx = Vunupxex( xys2.x );
if( nx <= minint ) return;
ny = Vunupxey( xys2.y );
if( ny <= minint ) return;
xypx2.x = nx;
xypx2.y = ny;

// Sommet 3
//=========
// transformation en pixels dans la fenetre
nx = Vunupxex( xys3.x );
if( nx <= minint ) return;
ny = Vunupxey( xys3.y );
if( ny <= minint ) return;
xypx3.x = nx;
xypx3.y = ny;

// TRACE EFFECTIF DU REMPLISSAGE DU TRIANGLE SELON DES COULEURS PROGRESSIVES
MemoirePx::VuTriangleCouleur( xypx1, xypx2, xypx3,
couleur1, couleur2, couleur3 );
}


void MemoirePx3d::VuLonLat( R deglon, R deglat )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : definir oeil en fonction de longitude et latitude
// ----- traiter le cas ou point vise = oeil
//
// entrees :
// ---------
// deglon : degres de longitude compris entre 0 et 360 degres
// deglat : degres de latitude compris entre -90 et 90 degres
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R axodis, r, radlon, radlat, coslon, sinlon, coslat, sinlat, rxy;

// distance actuelle entre l'oeil et le point vise ptv
axodis = sqrt( pow( axoeil[0]-axoptv[0] , 2 )
+ pow( axoeil[1]-axoptv[1] , 2 )
+ pow( axoeil[2]-axoptv[2] , 2 ) );
// protection dans le cas ou oeil = ptv
if( axodis <= 0 )
{
axodis = sqrt( pow(axoptv[0],2) + pow(axoptv[1],2) + pow(axoptv[2],2) );
if( axodis <= 1e-10 ) axodis = 1.0;
axodis = axodis * 10.0;
}

// longitude et latitude en radians de la nouvelle position de l'oeil
r = atan(1.0) / 45.0;
radlon = deglon * r;
radlat = deglat * r;
coslon = cos( radlon );
sinlon = sin( radlon );
coslat = cos( radlat );
sinlat = sin( radlat );

// rayon dans le plan xy
rxy = axodis * coslat;

// position de l'oeil
axoeil[0] = axoptv[0] + rxy * coslon;
axoeil[1] = axoptv[1] + rxy * sinlon;
axoeil[2] = axoptv[2] + axodis * sinlat;
}


void MemoirePx3d::VumataxoId( void )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: La matrice axomat vaut l'Identite dans R3x3
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
axomat[0] = 1.0; axomat[3] = 0.0; axomat[6] = 0.0;
axomat[1] = 0.0; axomat[4] = 1.0; axomat[7] = 0.0;
axomat[2] = 0.0; axomat[5] = 0.0; axomat[8] = 1.0;
}


void MemoirePx3d::Vumataxo(void)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//but : construction de la matrice de la projection axonometrique
//----- a partir des 3 coordonnees du point vise ptv
// des 3 coordonnees position de l'oeil
//sortie :
//--------
//axomat[3,3] dans les donnees membres de la classe Vu
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R axodis, r;

if( visee == 0 ) //mode visee non defini
{// pas d'axonometrie => transformation selon la matrice identite
VumataxoId();
}
else if( visee > 2 ) //mode visee en 3d
{
// axonometrie par ptv, oeil
// =========================
// la matrice de passage xyz => axoxyz
if( xyzide( axoptv, axoeil ) == true )
{
// ptv = oeil => longitude 30 degres latitude 20 degres imposees
// ----------
VuLonLat( 30.0, 20.0 );
}

// ptv different de oeil
// ---------------------
axomat[6] = axoeil[0] - axoptv[0];
axomat[7] = axoeil[1] - axoptv[1];
axomat[8] = axoeil[2] - axoptv[2];
axodis = sqrt( pow(axomat[6],2)+pow(axomat[7],2)+pow(axomat[8],2) );
axomat[6] = axomat[6] / axodis;
axomat[7] = axomat[7] / axodis;
axomat[8] = axomat[8] / axodis;

axomat[0] =-axomat[7];
axomat[1] = axomat[6];
axomat[2] = 0;

r = sqrt( pow(axomat[0],2) + pow(axomat[1],2) );
if( r >= 1e-3 )
{
// z n'est pas colineaire a ptv - oeil
// -----------------------------------
axomat[0] = axomat[0] / r;
axomat[1] = axomat[1] / r;

axomat[3] = -axomat[1] * axomat[8];
axomat[4] = axomat[0] * axomat[8];
axomat[5] = axomat[1] * axomat[6] - axomat[0] * axomat[7];
}
else if( axoeil[2] >= axoptv[2] )
{
// z est colineaire a ptv - oeil oeil au dessus de ptv
// -------------------------------------------------
// e1=x
// e2=y
// e3=z
VumataxoId();
}
else
{
// z est colineaire a ptv - oeil oeil au dessous de ptv
// -------------------------------------------------
// e1=-x
// e2= y
// e3=-z
VumataxoId();
axomat[0] = -1.0;
axomat[8] = -1.0;
}
}
}


void MemoirePx3d::VuPtVuLonLat( R3 ptv, R deglon, R deglat )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : definir point vise et oeil en fonction de longitude et latitude
// ----- traiter le cas ou point vise = oeil
// definir la nouvelle matrice d'axonometrie
//
// entrees :
// ---------
// ptv : position du point vise
// deglon : degres de longitude compris entre 0 et 360 degres
// deglat : degres de latitude compris entre -90 et 90 degres
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R axodis, r, radlon, radlat, coslon, coslat, sinlon, sinlat, rxy;

// la distance entre l'oeil et le point vise ptv
axodis = sqrt( pow((axoeil.x-axoptv.x),2) +
pow((axoeil.y-axoptv.y),2) +
pow((axoeil.z-axoptv.z),2) );

// protection dans le cas ou oeil = ptv
if( axodis <= 0 )
{
axodis = sqrt( pow(axoptv.x,2) + pow(axoptv.y,2) + pow(axoptv.z,2) );
if( axodis <= 1e-10 ) axodis = 1.0;
axodis = axodis * 10.0;
}

// longitude et latitude en radians de la nouvelle position de l'oeil
r = atan(1.0) / 45.0;
radlon = deglon * r;
radlat = deglat * r;
coslon = cos( radlon );
sinlon = sin( radlon );
coslat = cos( radlat );
sinlat = sin( radlat );
// rayon dans le plan xy
rxy = axodis * coslat;

// le point vise
axoptv = ptv;

// la position de l'oeil
axoeil.x = axoptv.x + rxy * coslon;
axoeil.y = axoptv.y + rxy * sinlon;
axoeil.z = axoptv.z + axodis * sinlat;

// le calcul de la matrice axomat
visee = 3;
Vumataxo();

// la definition de la fenetre en largeur et hauteur
VuIsoFenetre2d( -axolar, axolar, -axohau, axohau );
visee = 3; //surcharge de visee=2 issu de VuFenetre2d
}


void MemoirePx3d::Vuxyzaxo( R3 xyz, R3 & axyz )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees axonometriques
// ----- a partir des 3 coordonnees du point xyz
//
// entree :
// --------
// xyz : les 3 coordonnees dans le repere initial
//
// sortie :
// --------
// axyz : les 3 coordonnees dans le repere axonometrique
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x, y, z;
// protection pour appel avec xyz = axyz

x = xyz[0] - axoptv[0];
y = xyz[1] - axoptv[1];
z = xyz[2] - axoptv[2];

axyz[0] = axomat[0] * x + axomat[1] * y + axomat[2] * z;
axyz[1] = axomat[3] * x + axomat[4] * y + axomat[5] * z;
axyz[2] = axomat[6] * x + axomat[7] * y + axomat[8] * z;
}


void MemoirePx3d::Vuaxoxyz( R3 axyz, R3 & xyz )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees dans le repere xyz
// ----- a partir des 3 coordonnees axonometriques
//
// entree :
// --------
// axyz : les 3 coordonnees dans le repere axonometrique
//
// sortie :
// --------
// xyz : les 3 coordonnees dans le repere initial des objets
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x,y,z;
// protection pour appel avec axyz = xyz

x = axyz[0];
y = axyz[1];
z = axyz[2];

xyz[0] = axomat[0] * x + axomat[3] * y + axomat[6] * z + axoptv[0];
xyz[1] = axomat[1] * x + axomat[4] * y + axomat[7] * z + axoptv[1];
xyz[2] = axomat[2] * x + axomat[5] * y + axomat[8] * z + axoptv[2];
}


void MemoirePx3d::VuAxonometrie( R3 axptv, R3 axeil,
R axlar, R axhau, R axarr, R axava )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : construction de la matrice de la projection axonometrique
// ----- a partir des 3 coordonnees du point vise ptv
// des 3 coordonnees position de l'oeil
// de la largeur et hauteur de la fenetre ecran
// de la profondeur et avance dans la direction de visee
//
// entrees:
// --------
// axptv : xyz du point vise
// axeil : xyz de l'oeil
// axlar : largeur/2 vue sur l'ecran (en valeur absolue )
// axhau : hauteur/2 vue sur l'ecran
// axarr : distance a ptv du plan arriere de section
// axava : distance a ptv du plan avant de section
//
// sorties: donnees membres
// --------
// visee : numero du type de la visee
// 0 si non initialise
// 2 si initialise en 2d
// 3 si axonometrie 3d par ptv oeil axoarr et axoava
// axolar : largeur/2 vue sur l'ecran (en valeur absolue )
// axohau : hauteur/2 vue sur l'ecran
// axoarr : distance a ptv du plan arriere de section
// axoava : distance a ptv du plan avant de section
// axoptv : xyz du point vise
// axoeil : xyz de l'oeil
// axomat : matrice de la transformation (xyzaxo = axomat * (xyz - ptv))
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
// initialisation des donnees membres de MemoirePx3d
visee = 3;
axolar = axlar; axohau = axhau;
axoarr = axarr; axoava = axava;
axoptv = axptv; axoeil = axeil;

// calcul de la matrice axomat
Vumataxo();

// definition de la fenetre en largeur et hauteur
VuIsoFenetre2d( -axolar, axolar, -axohau, axohau );

//surcharge de visee=2 modifie dans VuFenetre2d
visee = 3;
}

void MemoirePx3d::VuHexaedre( R3 PtMIN, R3 PtMAX )
//Definir l'axonometrie pour voir l'hexaedre PtMIN-PtMAX
//Tracer les axes et la grille
{
//cout << "Entree VuHexaedre PtMIN=" << PtMIN << " PtMAX=" << PtMAX << endl;
//Mise en ordre eventuelle des MIN et MAX
if( PtMAX.x < PtMIN.x ) { Echange(PtMAX.x, PtMIN.x); }
if( PtMAX.y < PtMIN.y ) { Echange(PtMAX.y, PtMIN.y); }
if( PtMAX.z < PtMIN.z ) { Echange(PtMAX.z, PtMIN.z); }

if( PtMIN.z != PtMAX.z )
{
if( visee != 3 ) //Trace en 3d
{
//Trace en mode objet 3d Visee par defaut
axoptv.x = (PtMIN.x+PtMAX.x) * 0.5; //Point VU le centre de l'hexaedre
axoptv.y = (PtMIN.y+PtMAX.y) * 0.5;
axoptv.z = (PtMIN.z+PtMAX.z) * 0.5;

axoeil = axoptv + 3 * (PtMAX - PtMIN); //OEIL assez loin

axolar = ( PtMAX.x - PtMIN.x + PtMAX.y - PtMIN.y ) * 0.45;
axohau = ( PtMAX.z - PtMIN.z ) * 0.85;
axoarr = 0.0;
axoava = 0.0;

VuAxonometrie( axoptv, axoeil, axolar, axohau, axoarr, axoava );
}

//Trace de l'hexaedre englobant PtMIN, PtMAX, de la grille du plan XY du SCU
//couleur grille et des chiffres, Point XYZ minimales, Point XYZ maximales
VuAxes( PtMIN, PtMAX );
}
else
{
//Trace en mode objet 2d
if( visee != 2 )
{
R ex=(PtMAX.x - PtMIN.x)*0.05, ey=(PtMAX.y - PtMIN.y)*0.05;
VuIsoFenetre2d( PtMIN.x-ex, PtMAX.x+ex, PtMIN.y-ey, PtMAX.y+ey );
}

//trace des axes X Y et de la grille du SCU
MemoirePx2d::VuAxes();
}
}

void MemoirePx3d::VuTrait( R3 xyz1, R3 xyz2 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le trait 3d de (x1,y1,z1) a (x2,y2,z2) avec la couleur nc
// -----
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// nc : numero de la couleur du trait a tracer
// xyz1 : 1-ere extremite du trait
// xyz2 : 2-eme extremite du trait
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R3 axyz1, axyz2;
XPoint pxy1, pxy2;

if( visee==2 ) //si visee 2d
{
MemoirePx2d::VuTrait( XY(xyz1), XY(xyz2) );
return;
}

// transformation en coordonnees axonometriques
Vuxyzaxo( xyz1, axyz1 );
Vuxyzaxo( xyz2, axyz2 );

// si un point est exterieur aux 2 plans le trait n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz1.z < axoarr ) return;
if( axyz1.z > axoava ) return;
if( axyz2.z < axoarr ) return;
if( axyz2.z > axoava ) return;
}

// transformation en pixels dans la fenetre
pxy1.x = Vunupxex( axyz1.x );
if( pxy1.x <= minint ) return;

pxy1.y = Vunupxey( axyz1.y );
if( pxy1.y <= minint ) return;

pxy2.x = Vunupxex( axyz2.x );
if( pxy2.x <= minint ) return;
pxy2.y = Vunupxey( axyz2.y );
if( pxy2.y <= minint ) return;

// trace effectif
MemoirePx::VuTrait( pxy1, pxy2 );
}

void MemoirePx3d::VuTraits( int nbs, R3 xyzs[] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les aretes de nbs sommets xyzs
// -----
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entree :
// --------
// nbs : nombre de sommets de la face a tracer
// xyzs : abscisse, ordonnee, cote des nbs sommets
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint xypx[512];
R3 axyz;
int nbsp;

// verification
if( nbs <= 2 ) return;
if( nbs > 512 )
{
cout << "Augmenter 512 dans MemoirePx3d::VuTraits()\n";
return;
}

if( visee==2 ) //si visee 2d
{
// transformation en pixels dans la fenetre Vu
for ( nbsp=0; nbsp<nbs; nbsp++ )
{
xypx[nbsp].x = Vunupxex( xyzs[nbsp].x );
// si le numero pixel est incorrect abandon du trace de la face
if( xypx[nbsp].x <= minint ) return;
xypx[nbsp].y = Vunupxey( xyzs[nbsp].y );
if( xypx[nbsp].y <= minint ) return;
}
}
else
{
// visee3d: mise en forme des xyzs des sommets en mode pixel
for ( nbsp=0; nbsp<nbs; nbsp++ )
{
// transformation de xyz en coordonnees axonometriques axyz
Vuxyzaxo( xyzs[nbsp], axyz );
// si un point est exterieur aux 2 plans de section
// alors la face n'est pas tracee
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// transformation en pixels dans la fenetre
xypx[nbsp].x = Vunupxex( axyz.x );
if( xypx[nbsp].x <= minint ) return;

// si le numero pixel est incorrect abandon du trace de la face
xypx[nbsp].y = Vunupxey( axyz.y );
if( xypx[nbsp].y <= minint ) return;
}
}

// trace effectif des traits
MemoirePx::VuTraits( nbs, xypx );
}

void MemoirePx3d::VuFace( int nbs, R3 xyz[] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le remplissage de la face de nbs sommets XYZ
// -----
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entree :
// --------
// nbs : nombre de sommets de la face a tracer
// xyz : abscisse, ordonnee, cote des nbs sommets de la face
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint xypx[512];
R3 axyz;
int nbsp;

// verification de debordement
if( nbs <= 2 ) return;
if( nbs >= 512 )
{
cout << "Augmenter 512 dans MemoirePx3d::VuFace()\n";
return;
}

if( visee==2 )
{
// visee 2d: mise en forme des coordonnees des sommets en mode pixel
for ( nbsp=0; nbsp<nbs; nbsp++ )
{
// transformation en pixels dans la fenetre
xypx[nbsp].x = Vunupxex( xyz[nbsp].x );
if( xypx[nbsp].x <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
xypx[nbsp].y = Vunupxey( xyz[nbsp].y );
if( xypx[nbsp].y <= minint ) return;
}
}
else
{
// visee 3d: mise en forme des coordonnees des sommets en mode pixel
for ( nbsp=0; nbsp<nbs; nbsp++ )
{
// transformation de xyz en coordonnees axonometriques axyz
Vuxyzaxo( xyz[nbsp], axyz );
// si un point est exterieur aux 2 plans de section
// alors la face n'est pas tracee
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// transformation en pixels dans la fenetre
xypx[nbsp].x = Vunupxex( axyz.x );
if( xypx[nbsp].x <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
xypx[nbsp].y = Vunupxey( axyz.y );
if( xypx[nbsp].y <= minint ) return;
}
}

// fermeture des aretes du polygone de la face
if( xypx[nbs-1].x != xypx[0].x || xypx[nbs-1].y != xypx[0].y )
{
// fermeture du polygone
xypx[nbs].x = xypx[0].x;
xypx[nbs].y = xypx[0].y;
nbsp = nbs + 1;
}
else
// polygone deja ferme
nbsp = nbs;

// trace effectif du remplissage de la face sans le contour
MemoirePx::VuFace( nbsp, xypx );
}


void MemoirePx3d::VuBordTriangle( R3 xyzs1, R3 xyzs2, R3 xyzs3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Trace les 3 aretes du triangle de sommets xyzs
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
if( visee==2 )
{
MemoirePx2d::VuTrait( XY(xyzs1), XY(xyzs2) );
MemoirePx2d::VuTrait( XY(xyzs2), XY(xyzs3) );
MemoirePx2d::VuTrait( XY(xyzs3), XY(xyzs1) );
}
else
{
VuTrait( xyzs1, xyzs2 );
VuTrait( xyzs2, xyzs3 );
VuTrait( xyzs3, xyzs1 );
}
}

void MemoirePx3d::VuTexte( R3 xyz, char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres du texte
// ----- a partir du point (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entree :
// --------
// xyz : abscisse ordonnee cote du coin inferieur gauche du texte
// texte : les caracteres a tracer
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy;
int nbcar;
R3 axyz;

// nombre de caracteres du texte
nbcar = nudcnb( texte );
if( nbcar <= 0 ) return;

if( visee==2 )
{
// visee 2d: transformation en pixels dans la fenetre
pxy.x = Vunupxex( xyz.x );
if( pxy.x <= minint ) return;
pxy.y = Vunupxey( xyz.y );
if( pxy.y <= minint ) return;
}
else
{
// visee 3d: transformation en coordonnees axonometriques
Vuxyzaxo( xyz, axyz );

// si le point est exterieur aux 2 plans le texte n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz.z < axoarr ) return;
if( axyz.z > axoava ) return;
}

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( axyz.y );
if( pxy.y <= minint ) return;
}

// trace effectif
MemoirePx::VuTexte( pxy, texte );
}


void MemoirePx3d::VuSymbole( R3 xyz, char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le texte
// ----- a partir du point (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
// la chaine est decale d'un demi caractere vers le bas et a gauche
//
// entree :
// --------
// xyz : abscisse ordonnee cote du symbole
// texte : la chaine de caracteres servant de symbole
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R3 axyz;
XPoint pxy;

if( visee==2 )
{
// transformation en pixels dans la fenetre
pxy.x = Vunupxex( xyz.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( xyz.y );
if( pxy.y <= minint ) return;
}
else
{
// transformation en coordonnees axonometriques
Vuxyzaxo( xyz, axyz );

// si le point est exterieur aux 2 plans le texte n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz.z < axoarr ) return;
if( axyz.z > axoava ) return;
}

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( axyz.y );
if( pxy.y <= minint ) return;
}

// trace effectif
MemoirePx::VuSymbole( pxy, texte );
}


void MemoirePx3d::VuEntier( R3 xyz, int entier )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de la valeur de entier
// ----- a partir du point (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// xyz : abscisse ordonnee cote des caracteres de la valeur de l'entier
// entier : l'entier dont la valeur doit etre tracee
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy;
R3 axyz;

if( visee==2 )
{
// visee 2d: transformation en pixels dans la fenetre
pxy.x = Vunupxex( xyz.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( xyz.y );
if( pxy.y <= minint ) return;
}
else
{
// visee 3d: transformation en coordonnees axonometriques
Vuxyzaxo( xyz, axyz );

// si le point est exterieur aux 2 plans le texte n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz.z < axoarr ) return;
if( axyz.z > axoava ) return;
}

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz.x );
if( pxy.x <= minint ) return;

pxy.y = Vunupxey( axyz.y );
if( pxy.y <= minint ) return;
}

// trace de la chaine des caracteres
MemoirePx::VuEntier( pxy, entier);
}


void MemoirePx3d::VuReel( R3 xyz, R vR, int nbchif10 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace les caracteres de la valeur de R avec la couleur nc
// ----- a partir du point xyz en coordonnees objet 3d
// la transformation en pixels est assuree dans ce sp
// les autres caracteristiques du trace sont celles actuelles
//
// entrees:
// --------
// nc : numero de la couleur des caracteres de la valeur de R
// xyz : abscisse ordonnee cote des caracteres de la valeur de R
// vR : le R dont la valeur doit etre tracee
// nbchif10: nombre de chiffres demandes de la partie decimale
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R3 axyz;
XPoint pxy;

if( visee==2 )
{
// visee 2d: transformation en pixels dans la fenetre
pxy.x = Vunupxex( xyz.x );
if( pxy.x <= minint ) return;
pxy.y = Vunupxey( xyz.y );
if( pxy.y <= minint ) return;
}
else
{
// transformation en coordonnees axonometriques
Vuxyzaxo( xyz, axyz );

// si le point est exterieur aux 2 plans le texte n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz.z < axoarr ) return;
if( axyz.z > axoava ) return;
}
// visee 3d: transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz.x );
if( pxy.x <= minint ) return;
pxy.y = Vunupxey( axyz.y );
if( pxy.y <= minint ) return;
}

// trace du R
MemoirePx::VuReel( pxy, vR, nbchif10 );
}


void MemoirePx3d::VuVecteur( R3 xyzpt, R3 xyzvect )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer le vecteur xyzvect a partir d'un point de coordonnees xyzpt
// -----
// entrees:
// --------
// xyzpt : X Y Z du point
// xyzvect : X Y Z du vecteur
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//...................................................................
{
R3 axyz;
XPoint pxy1, pxy2;

if( visee==2 )
{
// visee 2d: les coordonnees en pixels du point
pxy1.x = Vunupxex( xyzpt.x );
pxy1.y = Vunupxey( xyzpt.y );

// les coordonnees en pixels de la pointe du vecteur
pxy2.x = Vunupxex( xyzpt.x + xyzvect.x );
pxy2.y = Vunupxey( xyzpt.y + xyzvect.y );
}
else
{
// visee 3d: les coordonnees en pixels sur l'ecran du point
Vuxyzaxo( xyzpt, axyz );
pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );
// les coordonnees en pixels sur l'ecran de la pointe du vecteur au point xyzpt
Vuxyzaxo( xyzpt + xyzvect, axyz );
pxy2.x = Vunupxex( axyz.x );
pxy2.y = Vunupxey( axyz.y );
}

// le trace du vecteur
MemoirePx::VuTrait( pxy1, pxy2 );
}

void MemoirePx3d::VuAxes( R3 PtMin, R3 PtMax )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer l'hexaedre PtMin-PtMax
// ----- Tracer la grille du SCU actuel selon ses pas
//
// entrees:
// --------
// PtMin : XYZ minimales de l'hexaedre
// PtMax : XYZ maximales de l'hexaedre
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Avril 2001
//...................................................................
{
R ecart, x, y, z;
R premierx, premiery, premierz, dernierx, derniery;
R pas, pasx, pasy, pasz;
char texte[16];
int i, nbcar, nbpasx, nbpasy, nbpasz, nbchif10;
R3 pt0, pt1;

//Une fonte assez petite pour les chiffres
VuChoisirFonte( 10 );

//Ajustage de pasx pasy pasz par rapport a PtMin et PtMax
//=================================================
VuGraduation( PtMin.x, PtMax.x, premierx, pasx, nbpasx, nbchif10 );
VuGraduation( PtMin.y, PtMax.y, premiery, pasy, nbpasy, nbchif10 );
VuGraduation( PtMin.z, PtMax.z, premierz, pasz, nbpasz, nbchif10 );

pas = Max( pasx, pasy, pasz );
nbpasx = int(nbpasx * pasx / pas + 1);
nbpasy = int(nbpasy * pasy / pas + 1);
nbpasz = int(nbpasz * pasz / pas + 1);

PtMin.x=premierx;
PtMax.x=premierx + nbpasx * pas;
PtMin.y=premiery;
PtMax.y=premiery + nbpasy * pas;
PtMin.z=premierz;
PtMax.z=premierz + nbpasz * pas;

ecart = pas * 0.15; //longueur du trait des graduations
VuEpaisseur( 0 );

//Trace des lignes des faces dans les plans XOY XOZ YOZ de l'hexaedre
//=============================================================
int ncohexaedre=Gris;
if( ncohexaedre >= 0 )
{
VuCouleur( ncohexaedre );
for (i=0; i<=nbpasx; i++)
{
x = premierx + i * pas;
//ligne du plan XoY // Y
VuTrait( R3(x, PtMin.y, PtMin.z), R3(x, PtMax.y, PtMin.z) );
//ligne du plan XoZ // Z
VuTrait( R3(x, PtMin.y, PtMin.z), R3(x, PtMin.y, PtMax.z) );
}

for (i=0; i<=nbpasy; i++)
{
//l'abscisse du nombre a tracer
y = premiery + i * pas;
//la ligne du plan XoY // axe X
VuTrait( R3(PtMin.x, y, PtMin.z), R3(PtMax.x, y, PtMin.z) );
//la ligne du plan YoZ // axe Z
VuTrait( R3(PtMin.x, y, PtMin.z), R3(PtMin.x, y, PtMax.z) );
}

for (i=0; i<=nbpasz; i++)
{
//l'abscisse du nombre a tracer
z = premierz + i * pas;
//la ligne du plan XoZ // axe X
VuTrait( R3(PtMin.x, PtMin.y, z), R3(PtMax.x, PtMin.y, z) );
//la ligne du plan YoZ // axe Y
VuTrait( R3(PtMin.x, PtMin.y, z), R3(PtMin.x, PtMax.y, z) );
}
}

//Trace rouge de l'axe des X
//==========================
VuCouleur( Rouge );
VuTexte( R3(PtMax.x, PtMin.y, PtMin.z), " X" ); //le caractere X
VuTrait( R3(PtMax.x, PtMin.y, PtMin.z), PtMin );
VuTrait( R3(PtMin.x, PtMax.y, PtMin.z), R3(PtMax.x, PtMax.y, PtMin.z) );
VuTrait( R3(PtMin.x, PtMin.y, PtMax.z), R3(PtMax.x, PtMin.y, PtMax.z) );

//Trace des graduations sur l'axe des X
for (i=0; i<=nbpasx; i++)
{
//l'abscisse du nombre a tracer
x = premierx + i * pas;
VuCouleur( Rouge ); //graduation sur l'axe X
VuTrait( R3(x, PtMin.y, PtMin.z), R3(x, PtMin.y+ecart, PtMin.z) );
VuTrait( R3(x, PtMin.y, PtMin.z), R3(x, PtMin.y, PtMin.z+ecart) );
//la valeur de l'abscisse
rtoa( x, nbchif10, nbcar, texte );
VuCouleur( CouleurChiffre );
VuSymbole( R3(x, PtMin.y, PtMin.z), texte );
}

//Trace vert de l'axe des Y
//=========================
VuCouleur( Vert );
VuTexte( R3(PtMin.x,PtMax.y,PtMin.z), " Y" ); //le caractere Y
VuTrait( R3(PtMin.x,PtMax.y,PtMin.z), PtMin );
VuTrait( R3(PtMax.x,PtMin.y,PtMin.z), R3(PtMax.x,PtMax.y,PtMin.z) );
VuTrait( R3(PtMin.x,PtMin.y,PtMax.z), R3(PtMin.x,PtMax.y,PtMax.z) );

//le trace des graduations sur l'axe des Y
for (i=0; i<=nbpasy; i++)
{
//l'ordonnee du nombre a tracer
y = premiery + i * pas;
VuCouleur( Vert ); //graduation sur l'axe Y
VuTrait( R3(PtMin.x, y, PtMin.z), R3(PtMin.x+ecart, y, PtMin.z) );
VuTrait( R3(PtMin.x, y, PtMin.z), R3(PtMin.x, y, PtMin.z+ecart) );
//la valeur de l'ordonnee
rtoa( y, nbchif10, nbcar, texte );
VuCouleur( CouleurChiffre );
VuSymbole( R3(PtMin.x, y, PtMin.z), texte );
}

//Trace bleu de l'axe des Z
//=========================
VuCouleur( Bleu );
VuTexte( R3(PtMin.x, PtMin.y, PtMax.z), " Z" ); //le caractere Z
VuTrait( R3(PtMin.x, PtMin.y, PtMax.z), PtMin );
VuTrait( R3(PtMax.x, PtMin.y, PtMin.z), R3(PtMax.x, PtMin.y, PtMax.z) );
VuTrait( R3(PtMin.x, PtMax.y, PtMin.z), R3(PtMin.x, PtMax.y, PtMax.z) );

//Trace des graduations sur l'axe des Z
for (i=1; i<=nbpasz; i++)
{
//la cote du nombre a tracer
z = premierz + i * pas;
VuCouleur( Bleu ); //graduation sur l'axe Z
VuTrait( R3(PtMin.x+ecart, PtMin.y, z), R3(PtMin.x, PtMin.y, z) );
VuTrait( R3(PtMin.x, PtMin.y+ecart, z), R3(PtMin.x, PtMin.y, z) );
//la valeur de la cote
rtoa( z, nbchif10, nbcar, texte );
VuCouleur( CouleurChiffre );
VuSymbole( R3(PtMin.x,PtMin.y,z), texte );
}

//Trace des lignes de la grille du plan XY du SCU actuel
//=================================================
if( CouleurGrilleSCU >= 0 )
{
VuCouleur( CouleurGrilleSCU );
ecart = Max( PtMax.x-PtMin.x, PtMax.y-PtMin.y, PtMax.z-PtMin.z );
nbpasx = int( ecart / PasGrilleSCU.x + 1);
nbpasy = int( ecart / PasGrilleSCU.y + 1);
R ecart2 = ecart * 2.5;

for (i=-nbpasx; i<=nbpasx; i++)
{
//ligne X=Cte dans le plan XY du SCU
pas = i * PasGrilleSCU.x;
pt0.x = SCU[0].x + pas * SCU[1].x - ecart * SCU[2].x;
pt0.y = SCU[0].y + pas * SCU[1].y - ecart * SCU[2].y;
pt0.z = SCU[0].z + pas * SCU[1].z - ecart * SCU[2].z;

pt1.x = pt0.x + ecart2 * SCU[2].x;
pt1.y = pt0.y + ecart2 * SCU[2].y;
pt1.z = pt0.z + ecart2 * SCU[2].z;

//recherche des points d'intersection de la droite pt0-pt1
//avec les 6 plans de l'hexaedre PtMin PtMax
if( IntersectionDroiteHexaedre( PtMin, PtMax, pt0, pt1 ) )
VuTrait( pt0, pt1 );
}

for (i=-nbpasy; i<=nbpasy; i++)
{
//ligne Y=Cte du plan XY du SCU
pas = i * PasGrilleSCU.y;
pt0.x = SCU[0].x + pas * SCU[2].x - ecart * SCU[1].x;
pt0.y = SCU[0].y + pas * SCU[2].y - ecart * SCU[1].y;
pt0.z = SCU[0].z + pas * SCU[2].z - ecart * SCU[1].z;

pt1.x = pt0.x + ecart2 * SCU[1].x;
pt1.y = pt0.y + ecart2 * SCU[1].y;
pt1.z = pt0.z + ecart2 * SCU[1].z;

//recherche des points d'intersection de la droite pt0-pt1
//avec les 6 plans de l'hexaedre PtMin PtMax
if( IntersectionDroiteHexaedre( PtMin, PtMax, pt0, pt1 ) )
VuTrait( pt0, pt1 );
}
}
}


void MemoirePx3d::VuCourbeP3H( int nca, int nepa, R porear,
int ncotg, int neptg, int ntrtg,
R3 xyzs1, R3 xyzs2,
R3 xyztg1, R3 xyztg2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// But : Tracer la courbe 3d interpolation P3-HERMITE passant par
// ----- les 2 sommets xyzs1 et xyzs2 et tangente aux vecteurs xyztg1 et xyztg2
// Attention la direction de la tangente en xyzs2 est xyzs2->xyzs1
// entrees:
// --------
// nca : numero de la couleur des aretes a tracer
// <0 pas de trace des aretes de la courbe
// nepa : nombre d'epaisseurs a ajouter au trait d'une arete
// porear : pourcentage de reduction du trace d'une arete 0.0<=porear<=100.0
// nctg : >=0 numero de la couleur des 2 tangentes a tracer
// < 0 pas de trace des 2 tangentes
// neptg : >=0 nombre d'epaisseurs a ajouter au trait d'une tg
// ntrtg : trace en continu(0) ou pointille (1) ou double pointille(2)
// xyzs1 : X Y Z du sommet 1
// xyzs2 : X Y Z du sommet 2
// xyztg1 : X Y Z de la tangente au sommet 1 dans la direction s1->s2
// xyztg2 : X Y Z de la tangente au sommet 2 dans la direction s2->s1
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//...................................................................
{
int i, j, nx1, ny1, nx2, ny2, nbsuba;
R reduction, reductio1, h, p, u;
XPoint xypx[1+mxsucb];
R3 xyz, axyz;

// si couleur negative => retour
if( nca < 0 ) return;

// la reduction de l'arete entre 0 et 1
reduction = porear * 0.005;
reductio1 = 1.0 - reduction;

// recherche du nombre de subdivisions de l'ef reduit de reference [0,1]
// selon le nombre de pixels obtenus apres mise a l'echelle pixels
// =========================================================
// transformation en coordonnees axonometriques du sommet 1
Vuxyzaxo( xyzs1, axyz );
// transformation en pixels dans la fenetre du sommet 1
nx1 = Vunupxex( axyz[0] );
if( nx1 <= minint ) return;
// si le numero pixel est incorrect abandon du trace de l'arete
ny1 = Vunupxey( axyz[1] );
if( ny1 <= minint ) return;

// transformation en coordonnees axonometriques du sommet 2
Vuxyzaxo( xyzs2, axyz );
// transformation en pixels dans la fenetre du sommet 2
nx2 = Vunupxex( xyzs2[0] );
if( nx2 <= minint ) return;
// si le numero pixel est incorrect abandon du trace de l'arete
ny2 = Vunupxey( xyzs2[1] );
if( ny2 <= minint ) return;

// nombre de subdivision en aretes de la courbe P3 Hermite
nbsuba = Max( abs(nx2-nx1), abs(ny2-ny1) );
if( nbsuba == 0 ) return;
nbsuba = Min( Max(2,nbsuba/3), mxsucb );

//les coordonnees xy pixels des sommets des sous-aretes
h = ( reductio1 - reduction ) / nbsuba;
u = reduction;
for ( i=0; i<=nbsuba; i++ )
{
//le i-eme sommet des sous-aretes de la courbe
for ( j=0; j<3; j++)
xyz[j] = ValeurP3H( u, xyzs1[j],xyzs2[j], xyztg1[j],xyztg2[j] );

// transformation en coordonnees axonometriques
Vuxyzaxo( xyz, axyz );

// si le point est exterieur aux 2 plans le triangle n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr || axyz[2] > axoava )
{
//le trace des i sous aretes
if( i>1 ) MemoirePx::VuTraits( i, xypx );
return;
}
}

// transformation en pixels dans la fenetre sans test de sortie
xypx[i].x = Vunupxex( axyz[0] );
xypx[i].y = Vunupxey( axyz[1] );

u = u + h;
}

//le trace des nbsuba sous aretes
VuCouleur( nca );
VuEpaisseur( nepa );
MemoirePx::VuTraits( 1+nbsuba, xypx );

// trace eventuel des tangentes aux 2 sommets
if( ncotg >= 0 )
{
VuCouleur( ncotg );
VuEpaisseur( neptg );
VuTypeTrait( ntrtg );
VuVecteur( xyzs1, xyztg1 );
VuVecteur( xyzs2, xyztg2 );
}
}


void MemoirePx3d::VuTriangleCouleur( R3 xyzs1, R3 xyzs2, R3 xyzs3,
R couleur1, R couleur2, R couleur3 )
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : trace le triangle de sommets xyzs1, xyzs2, xyzs3 de couleurs 1 2 3
// ----- selon les couleurs intermediaires (PALETTE 11 RECOMMANDEE)
// entrees:
// --------
// couleur i: couleur entre n1coul et ndcoul dans la palette actuelle i=1,2,3
// xyzs i : coordonnees du sommet i=1,2,3
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R3 axyz;
XPoint xypx[3];

if( visee==2 ) //visee 2d
{
// Sommet 0
//=========
// transformation en pixels dans la fenetre
xypx[0].x = Vunupxex( xyzs1.x );
if( xypx[0].x <= minint ) return;
xypx[0].y = Vunupxey( xyzs1.y );
if( xypx[0].y <= minint ) return;

// Sommet 1
//=========
// transformation en pixels dans la fenetre
xypx[1].x = Vunupxex( xyzs2.x );
if( xypx[1].x <= minint ) return;
xypx[1].y = Vunupxey( xyzs2.y );
if( xypx[1].y <= minint ) return;

// Sommet 2
//=========
// transformation en pixels dans la fenetre
xypx[2].x = Vunupxex( xyzs3.x );
if( xypx[2].x <= minint ) return;
xypx[2].y = Vunupxey( xyzs3.y );
if( xypx[2].y <= minint ) return;
}
else
{
// Sommet 0
//=========
// transformation en coordonnees axonometriques
Vuxyzaxo( xyzs1, axyz );

// si le point est exterieur aux 2 plans le triangle n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// transformation en pixels dans la fenetre
xypx[0].x = Vunupxex( axyz[0] );
if( xypx[0].x <= minint ) return;
xypx[0].y = Vunupxey( axyz[1] );
if( xypx[0].y <= minint ) return;

// Sommet 1
//=========
// transformation en coordonnees axonometriques
Vuxyzaxo( xyzs2, axyz );

// si le point est exterieur aux 2 plans le triangle n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// transformation en pixels dans la fenetre
xypx[1].x = Vunupxex( axyz[0] );
if( xypx[1].x <= minint ) return;
xypx[1].y = Vunupxey( axyz[1] );
if( xypx[1].y <= minint ) return;

// Sommet 2
//=========
// transformation en coordonnees axonometriques
Vuxyzaxo( xyzs3, axyz );

// si le point est exterieur aux 2 plans le triangle n'est pas trace
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// transformation en pixels dans la fenetre
xypx[2].x = Vunupxex( axyz[0] );
if( xypx[2].x <= minint ) return;
xypx[2].y = Vunupxey( axyz[1] );
if( xypx[2].y <= minint ) return;
}

// TRACE EFFECTIF DU REMPLISSAGE DU TRIANGLE SELON DES COULEURS PROGRESSIVES
MemoirePx::VuTriangleCouleur( xypx[0], xypx[1], xypx[2],
couleur1, couleur2, couleur3 );
}

R MemoirePx3d::CouleurEclairage( R3 normal )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : la couleur est proportionnelle au cosinus de l'angle
// ----- entre la normale au point et les directions des eclairages
// definis par les lampes (ou l'oeil) et le point vu
// entree :
// --------
// normal : les 3 coordonnees du vecteur normal
//
// sortie :
// --------
// rcoul : valeur Reelle de la couleur entre n1coul et ndcoul
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique upmc Paris aout 1998
//.....................................................
{
int i;
R s, rcoul;

if( nblampe <= 0 )
{
//pas de lampe => l'oeil sert de lampe
s = sqrt( pow(axoeil[0]-axoptv[0],2) +
pow(axoeil[1]-axoptv[1],2) +
pow(axoeil[2]-axoptv[2],2) );
rcoul = ( (axoeil[0]-axoptv[0]) * normal[0] +
(axoeil[1]-axoptv[1]) * normal[1] +
(axoeil[2]-axoptv[2]) * normal[2] ) / s;
if( rcoul < 0 ) rcoul = -rcoul;
}
else
{
//au moins une lampe => couleur moyenne des eclairages
rcoul = 0;
for (i=0; i<nblampe; i++)
{
s = sqrt( pow(axolampe[i][0]-axoptv[0],2) +
pow(axolampe[i][1]-axoptv[1],2) +
pow(axolampe[i][2]-axoptv[2],2) );
if( s <= 0 ) s=1.0;

s = ( (axolampe[i][0]-axoptv[0]) * normal[0]
+ (axolampe[i][1]-axoptv[1]) * normal[1]
+ (axolampe[i][2]-axoptv[2]) * normal[2] ) / s;
if (s < 0 ) s=-s;
rcoul = Max( rcoul, s );
}
}
return (R) n1coul + (ndcoul-n1coul) * rcoul;
}


//fonction interne a la fonction VuTriangle3s3n et VuQuadrangle4s4n
void tgnoarno( R3 xyzn1, R3 xyzs1, R3 xyzs2,
R & x, R & y, R & z )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Calculer le vecteur orthogonal a la normale xyzn1 et
// ----- appartenant au plan defini par cette normale et l'arete xyzs1->xyzs2
// entrees:
// xyzn1 : X Y Z de la normale au sommet xyzs1
// xyzs1 : X Y Z du sommet 1
// xyzs2 : X Y Z du sommet 2 extremite de l'arete
// sorties:
// x : abscisse de ce vecteur orthonormal a la normale et au plan
// y : ordonnee de ce vecteur orthonormal a la normale et au plan
// z : cote de ce vecteur orthonormal a la normale et au plan
// la norme de ce vecteur est egale a la longueur de l'arete xyzs1->xyzs2
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
R3 arete, tg, binormale;
R s;

//les 3 composantes de la tangente a l'arete s1->s2
arete[0] = xyzs2[0] - xyzs1[0];
arete[1] = xyzs2[1] - xyzs1[1];
arete[2] = xyzs2[2] - xyzs1[2];

//les 3 composantes du vecteur orthogonal a arete et xyzn1
binormale = arete ^ xyzn1;

//les 3 composantes du vecteur orthogonal a la normale et binormale
tg = xyzn1 ^ binormale;

//la normalisation a la longueur de l'arete de la tangente a l'arete
s = sqrt( pow(tg[0],2) + pow(tg[1],2) + pow(tg[2],2) );

if( s > 0 )
{
//la normalisation du vecteur orthogonal a la longueur de l'arete
s = sqrt( pow(arete[0],2) + pow(arete[1],2) + pow(arete[2],2) ) / s;
x = tg[0] * s;
y = tg[1] * s;
z = tg[2] * s;
}
else
{
//erreur: normale et arete sont colineaires => vecteur=arete
x = xyzs2[0] - xyzs1[0];
y = xyzs2[1] - xyzs1[1];
z = xyzs2[2] - xyzs1[2];
}
}


//fonction interne a la fonction VuTriangleHCT
//numero du sommet i,j dans la decomposition en n*n sous triangles
inline int nustri(int i, int j) {return i + j*(j+1)/2;}


void MemoirePx3d::VuTriangleHCT( int lcritr, int ncf, R porefa,
int ncsa, int nca, int neparf,
int ncotgf, int neptgf, int ntrtgf,
R x[9], R y[9], R z[9] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Trace le triangle HCT-reduit de sommets et tangentes rangees
// ----- dans les tableaux x,y,z (sommets 1 a 3, tangentes 4 a 9) et
// selon la couleur ncf pour la face et nca pour les aretes
//
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans cette fonction
// les autres caracteristiques du trace sont celles actuelles
// entrees:
// lcritr :=0 prise en compte de la normale et des eclairages
// sur un decoupage en sous triangles du triangle et
// les fonctions de base de l'ef HCT reduit
// dans ce cas ncf est inactif
// Palette de couleurs 3 a 9 recommandee
// >0 prise en compte de la couleur ncf sur tout le triangle
// ncf : numero de la couleur de remplissage de la face a tracer
// si lcritr>0 inactif sinon
// <0 pas de trace de l'interieur de la face
// porefa : pourcentage de reduction du trace du triangle par rapport
// au barycentre ( 0.0<=porefa<100.0 )
// nca : >=0 numero de la couleur des 3 aretes du triangle
// <0 pas de trace des 3 aretes du triangle
// ncsa : >=0 numero de la couleur des aretes des n*n sous-triangles
// <0 pas de trace des aretes des n*n sous-triangles
// neparf : nombre d'epaisseurs en plus de trace des aretes du triangle
// ncotgf : >=0 numero de la couleur de trace des tangentes
// < 0 pas de trace des tangentes
// neptgf : nombre d'epaisseurs supplementaires du trace des tangentes
// ntrtgf : numero du type de trait de trace des tangentes
// 0 continu, 1: tirete, 2: doublement tirete
// x : abscisse objet des 3 sommets et 6 tangentes a la face
// y : ordonnee objet des 3 sommets et 6 tangentes a la face
// z : cote objet des 3 sommets et 6 tangentes a la face
// x, y, z: a ranger selon l'ordre suivant
// au sommet1, au sommet2, au sommet3,
// au sommet1 la tangente1 selon s1->s2
// au sommet1 la tangente2 selon s1->s3
// au sommet2 la tangente1 selon s2->s3
// au sommet2 la tangente2 selon s2->s1
// au sommet3 la tangente1 selon s3->s1
// au sommet3 la tangente2 selon s3->s2
// ce choix permet une boucle sur les tangentes par les sommets
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Octobre 2000
//.....................................................
{
static const int mxsubt=(mxsuar+1)*(mxsuar+2)/2;
R rcoult[mxsubt];
short int xtpx[mxsubt];
short int ytpx[mxsubt];

XPoint pxy1, pxy2;
XPoint xypx[4];
R profon[3];
R3 xyz, axyz;
R3 cnorfa;
int i, j, k, kk, i1, i2, ierr;
int nbsuba, nbpx;
int nx, ny, nx1, ny1, nx2, ny2, ns1, ns2, ns3;
R reduction, reductio1, h, p, u, v;

// si couleur negative => retour
if( ncf < 0 && nca < 0 ) return;

// la reduction de la face entre 0 et 1
// 0.005 = 0.01/3 car trace ici dans l'element de reference
// et non par rapprochement du barycentre comme dans le cas d'ef p1
reduction = porefa * 0.00333;
reductio1 = 1.0 - reduction;

// recherche du nombre de subdivisions de l'ef reduit de reference
// selon le nombre de pixels obtenus apres mise a l'echelle pixels
// recherche des 2 sommets de la face les plus eloignes de l'oeil
// ========================================================
nbpx = 0;

for ( i=0; i<3; i++)
{
// transformation en coordonnees axonometriques
xyz[0] = x[i];
xyz[1] = y[i];
xyz[2] = z[i];
Vuxyzaxo( xyz, axyz );

//si un point est exterieur aux 2 plans la face n'est pas tracee
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// la distance a l'oeil du sommet i
profon[i] = axyz[2];

// transformation en pixels dans la fenetre
nx = Vunupxex( axyz[0] );
if( nx <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
ny = Vunupxey( axyz[1] );
if( ny <= minint ) return;
// les coordonnees pixel du sommet i
xypx[i].x = nx;
xypx[i].y = ny;

if( i > 0 )
{
i1 = abs( xypx[i].x-xypx[i-1].x );
i2 = abs( xypx[i].y-xypx[i-1].y );
nbpx = Max( nbpx, Max(i1,i2) );
}

// les coordonnees pixels du point: sommet i + premiere tangente
i1 = 3 + 2 * i;
xyz.x = x[i] + x[i1];
xyz.y = y[i] + y[i1];
xyz.z = z[i] + z[i1];
Vuxyzaxo( xyz, axyz );

pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );
nbpx = Max( nbpx, Max(abs(pxy1.x-nx) , abs(pxy1.y-ny)) );
}

if( nbpx == 0 ) return;

// nombre de subdivisions de chacune des 3 aretes du triangle
nbsuba = Min( Max(2,nbpx/8), mxsuar );

// calcul des images p3 des sommets du maillage de la face reduite
// trace des sous-ef, image p3 des sous-ef de l'ef de reference
// =========================================================
h = ( reductio1 - reduction ) / nbsuba;

// recherche du sommet k+1 du triangle le plus eloigne de l'oeil
// pour traiter l'algorithme du peintre
p = profon[0];
k = 0;
if( profon[1] < p )
{ p = profon[1];
k = 1;
}
if( profon[2] < p )
{ p = profon[2];
k = 2;
// permutation des sommets pour amener ce sommet 2 en position 0
pecm33( x );
pecm33( y );
pecm33( z );
}

if( k == 1 )
{
// permutation des sommets pour amener ce sommet 1 en position 0
peci33( x );
peci33( y );
peci33( z );
}

// les coordonnees x y z et la couleur rcoult des sommets
// des sous triangles du triangle rectangle unite
v = reduction;
k =-1;
for (j=0; j<=nbsuba; j++)
{
u = reduction + j * h;
v = reduction;
for (i=0; i<=j; i++)
{
k = k + 1;
// les 3 coordonnes HCT au point (u,v)
xyzhct( u, v, x, y, z, xyz[0], xyz[1], xyz[2] );

// les coordonnees en pixels du sommet k
Vuxyzaxo( xyz, axyz );
xtpx[k] = Vunupxex( axyz[0] );
ytpx[k] = Vunupxey( axyz[1] );

// la couleur du sommet k
if( lcritr == 0 )
{
// les 3 coordonnes HCT de la normale au point (u,v)
norhct( u, v, x, y, z, cnorfa, ierr );

// calcul de la couleur en ce point a partir
// de la normale et des eclairages
rcoult[k] = CouleurEclairage( cnorfa );
}

// passage au point suivant
u = u - h;
v = v + h;
}
}

// trace eventuel des 2 tangentes du sommet 0 le plus eloigne
if( ncotgf >= 0 )
{
// la couleur de trace des tangentes
VuCouleur( ncotgf );
// les epaisseurs de trace des tangentes
VuEpaisseur( neptgf );
// trace en continu(0) ou pointille (1) ou double pointille(2)
VuTypeTrait( ntrtgf );

// au sommet 0
xyz.x = x[0]; xyz.y = y[0]; xyz.z = z[0];
// les coordonnees en pixels sur l'ecran
Vuxyzaxo( xyz, axyz );
pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );

for( j=1; j<=2; j++)
{
// la j-eme tangente au sommet 0 existe
xyz.x = x[0] + x[2+j];
xyz.y = y[0] + y[2+j];
xyz.z = z[0] + z[2+j];

// les coordonnees en pixels sur l'ecran de la pointe de la tg
Vuxyzaxo( xyz, axyz );
pxy2.x = Vunupxex( axyz.x );
pxy2.y = Vunupxey( axyz.y );

// le trace de la tangente
MemoirePx::VuTrait( pxy1, pxy2 );
}
}

// trace des sous triangles et des sous aretes des 3 cotes du triangle
for (j=1; j<=nbsuba; j++)
{
for (i=1; i<=j; i++)
{
//les coordonnees pixels des 3 sommets du premier sous-triangle
ns1 = nustri(i-1,j-1); // j selon la seconde diagonale
ns2 = nustri(i-1,j ); // i en ordonnee
ns3 = nustri(i ,j );

xypx[0].x = xtpx[ns1];
xypx[1].x = xtpx[ns2];
xypx[2].x = xtpx[ns3];
xypx[3].x = xtpx[ns1];

xypx[0].y = ytpx[ns1];
xypx[1].y = ytpx[ns2];
xypx[2].y = ytpx[ns3];
xypx[3].y = ytpx[ns1];

// trace du remplissage du sous-triangle
if( ncf >= 0 )
{
if( lcritr == 0 )
{
// trace du sous-triangle selon la couleur rcoult aux 3 sommets
MemoirePx::VuTriangleCouleur( xypx[0], xypx[1], xypx[2],
rcoult[ns1], rcoult[ns2], rcoult[ns3] );
}
else
{
// trace du sous-triangle avec la couleur ncf
VuCouleur( ncf );
MemoirePx::VuFace( 4, xypx );
}
if( ncsa >= 0 )
{
VuEpaisseur( 0 );
VuCouleur( ncsa );
MemoirePx::VuBordTriangle( xypx[0], xypx[1], xypx[2] );
}
}

// trace de l'arete de la sous face d'une des 3 aretes du triangle
if( nca >= 0 )
{
if( i == 1 )
{
// l'arete 1 du triangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xypx[0].x;
pxy1.y = xypx[0].y;
pxy2.x = xypx[1].x;
pxy2.y = xypx[1].y;
MemoirePx::VuTrait( pxy1, pxy2 );
}

if( j == nbsuba )
{
// l'arete 2 du triangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xypx[1].x;
pxy1.y = xypx[1].y;
pxy2.x = xypx[2].x;
pxy2.y = xypx[2].y;
MemoirePx::VuTrait( pxy1, pxy2 );
}

if( i == j )
{
// l'arete 2 du triangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xypx[2].x;
pxy1.y = xypx[2].y;
pxy2.x = xypx[0].x;
pxy2.y = xypx[0].y;
MemoirePx::VuTrait( pxy1, pxy2 );
}
}

// les coordonnees pixels des 3 sommets du second sous-triangle
if( i != j )
{
ns2 = nustri(i,j-1); // seul le sommet ns2 change
xypx[1].x = xtpx[ ns2 ];
xypx[1].y = ytpx[ ns2 ];

// trace de la sous-face triangulaire
if( ncf >= 0 )
{
if( lcritr == 0 )
{
// trace selon la couleur aux 3 sommets du triangle
MemoirePx::VuTriangleCouleur( xypx[0], xypx[1], xypx[2],
rcoult[ns1], rcoult[ns2], rcoult[ns3] );
}
else
{
// trace du triangle suivant la couleur ncf
VuCouleur( ncf );
MemoirePx::VuFace( 4, xypx );
}

if( ncsa >= 0 )
{
VuEpaisseur( 0 );
VuCouleur( ncsa );
MemoirePx::VuBordTriangle( xypx[0], xypx[1], xypx[2] );
}
}
}
}
}

// trace eventuel des tangentes aux sommets
if( ncotgf >= 0 )
{
// la couleur de trace pointille ou non des tangentes
VuCouleur( ncotgf );
// le nombre d'epaisseur du trait des tangentes
VuEpaisseur( neptgf );
// trace en continu(0) ou pointille (1) ou double pointille(2)
VuTypeTrait( ntrtgf );

k = 4;
for (i=1; i<=2; i++)
{
// le sommet i
xyz.x = x[i];
xyz.y = y[i];
xyz.z = z[i];

// les coordonnees en pixels sur l'ecran
Vuxyzaxo( xyz, axyz );
pxy1.x = Vunupxex( axyz[0] );
pxy1.y = Vunupxey( axyz[1] );

for (j=1; j<=2; j++)
{
// la j-eme tangente au sommet i
k = k + 1;
xyz.x = x[i] + x[k];
xyz.y = y[i] + y[k];
xyz.z = z[i] + z[k];

// les coordonnees en pixels sur l'ecran de la pointe de la tg
Vuxyzaxo( xyz, axyz );
pxy2.x = Vunupxex( axyz.x );
pxy2.y = Vunupxey( axyz.y );

// le trace de la tangente
MemoirePx::VuTrait( pxy1, pxy2 );
}
}
}
}


void MemoirePx3d::VuTriangleHCT( int lcritr, int ncf, R porefa,
int ncsa, int nca, int neparf,
int ncotgf, int neptgf, int ntrtgf,
int nost[3], R3 xyzst[],
int notg[6], R3 xyztg[] )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Trace le triangle HCT-reduit de sommets et tangentes rangees
// ----- dans les tableaux x,y,z (sommets 1 a 3, tangentes 4 a 9) et
// selon la couleur ncf pour la face et nca pour les aretes
//
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans cette fonction
// les autres caracteristiques du trace sont celles actuelles
// entrees:
// --------
// lcritr :=0 prise en compte de la normale et des eclairages
// sur un decoupage en sous triangles du triangle et
// les fonctions de base de l'ef HCT reduit
// dans ce cas ncf est inactif
// Palette de couleurs 3 a 9 recommandee
// >0 prise en compte de la couleur ncf sur tout le triangle
// ncf : numero de la couleur de remplissage de la face a tracer
// si lcritr>0 inactif sinon
// <0 pas de trace de l'interieur de la face meme si lcritr=0
// porefa : pourcentage de reduction du trace du triangle par rapport
// au barycentre ( 0.0<=porefa<100.0 )
// nca : >=0 numero de la couleur des 3 aretes du triangle
// <0 pas de trace des 3 aretes du triangle
// ncsa : >=0 numero de la couleur des aretes des n*n sous-triangles
// <0 pas de trace des aretes des n*n sous-triangles
// neparf : nombre d'epaisseurs en plus de trace des aretes du triangle
// ncotgf : >=0 numero de la couleur de trace des tangentes
// < 0 pas de trace des tangentes
// neptgf : nombre d'epaisseurs supplementaires du trace des tangentes
// ntrtgf : numero du type de trait de trace des tangentes
// 0 continu, 1: tirete, 2: doublement tirete vu.nc
// nost : numero des 3 sommets dans le tableau xyzst (de 1 a Nombre de sommets)
// xyzst: X Y Z des sommets
// notg : numero des 2 tangentes en chacun des 3 sommets du triangle
// (de 1 a Nombre de sommets) avec 3 cas >0 =0 et <0 possibles
// 1: au sommet1 la tangente1 est selon s1->s2
// 2: au sommet1 la tangente2 est selon s1->s3
// 3: au sommet2 la tangente1 est selon s2->s3
// 4: au sommet2 la tangente2 est selon s2->s1
// 5: au sommet3 la tangente1 est selon s3->s1
// 6: au sommet3 la tangente2 est selon s3->s2
// attention:
// - un numero negatif de tg demande l'inversion des signes
// des 3 composantes de la tangente
// - un numero nul de tg entraine une tangente egale a l'arete correspondante
//
// Dans la suite de cette fonction sont formes 3 tableaux X[9], Y[9], Z[9]
// contenant respectivement l'abscisse X, l'ordonnee Y et la cote Z
// pour calculer rapidement la valeur de HCT(u,v)
// x : abscisse objet des 3 sommets et 6 tangentes a la face
// y : ordonnee objet des 3 sommets et 6 tangentes a la face
// z : cote objet des 3 sommets et 6 tangentes a la face
// x, y, z: a ranger selon l'ordre suivant
// au sommet1, au sommet2, au sommet3,
// au sommet1 la tangente1 selon s1->s2
// au sommet1 la tangente2 selon s1->s3
// au sommet2 la tangente1 selon s2->s3
// au sommet2 la tangente2 selon s2->s1
// au sommet3 la tangente1 selon s3->s1
// au sommet3 la tangente2 selon s3->s2
// ce choix permet une boucle sur les tangentes par les sommets
// et un appel de VuTriangleHCT
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
R x[9];
R y[9];
R z[9];
int i, j, k, kk, i1;

// si couleur negative => retour
if( ncf < 0 && nca < 0 ) return;

// construction des tableaux X Y Z des 3 sommets et 6 tangentes
// selon le codage indique dans les commentaires
for ( i=0; i<3; i++ )
{
k = nost[i] - 1;
x[i] = xyzst[k][0];
y[i] = xyzst[k][1];
z[i] = xyzst[k][2];
}

j = 0;
for ( i=0; i<3; i++ )
{
k = notg[j]; // tangente 1 au sommet i+1 selon st i-> st i+1
if( k == 0 )
{ // tangente = arete i->i+1
if( i == 2 )
i1=0;
else
i1=i+1;

k = nost[i ] - 1;
kk = nost[i1] - 1;
x[3+j] = xyzst[kk][0] - xyzst[k][0];
y[3+j] = xyzst[kk][1] - xyzst[k][1];
z[3+j] = xyzst[kk][2] - xyzst[k][2];
}
else if ( k < 0 )
{ // tangente = - tg j
k = -k -1;
x[3+j] = -xyztg[k][0];
y[3+j] = -xyztg[k][1];
z[3+j] = -xyztg[k][2];
}
else
{ // tangente = + tg j
k = k - 1;
x[3+j] = xyztg[k][0];
y[3+j] = xyztg[k][1];
z[3+j] = xyztg[k][2];
}
j = j + 1;


k = notg[j]; // tangente 2 au sommet i+1 selon st i-> st i-1
if( k == 0 )
{ // tangente = arete i->i-1
if( i == 0 )
i1=2;
else
i1=i-1;

k = nost[i ] - 1;
kk = nost[i1] - 1;
x[3+j] = xyzst[kk][0] - xyzst[k][0];
y[3+j] = xyzst[kk][1] - xyzst[k][1];
z[3+j] = xyzst[kk][2] - xyzst[k][2];
}
else if ( k < 0 )
{ // tangente = - tg j
k = -k -1;
x[3+j] = -xyztg[k][0];
y[3+j] = -xyztg[k][1];
z[3+j] = -xyztg[k][2];
}
else
{ // tangente = + tg j
k = k - 1;
x[3+j] = xyztg[k][0];
y[3+j] = xyztg[k][1];
z[3+j] = xyztg[k][2];
}
j = j + 1;
}

// le trace effectif
VuTriangleHCT( lcritr, ncf, porefa,
ncsa, nca, neparf,
ncotgf, neptgf, ntrtgf,
x, y, z );
}


void MemoirePx3d::VuQuadrangleDVS( int lcritr, int ncf, R porefa,
int ncsa, int nca, int neparf,
int ncotgf, int neptgf, int ntrtgf,
R x[12], R y[12], R z[12] )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Trace le quadrangle dVS-reduit de sommets et tangentes rangees
// ----- dans les tableaux x,y,z (sommets 1 a 4, tangentes 5 a 12) et
// selon la couleur ncf pour la face et nca pour les aretes
//
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans cette fonction
// les autres caracteristiques du trace sont celles actuelles
// entrees:
// lcritr :=0 prise en compte de la normale et des eclairages
// sur un decoupage en sous quadrangles du quadrangle et
// les fonctions de base de l'ef DVS reduit
// dans ce cas ncf est inactif
// Palettes de couleurs 3 a 10 recommandees
// >0 prise en compte de la couleur ncf sur tout le quadrangle
// ncf : numero de la couleur de remplissage de la face a tracer
// si lcritr>0 inactif sinon
// <0 pas de trace de l'interieur de la face
// porefa : pourcentage de reduction du trace du quadrangle par rapport
// au barycentre ( 0.0<=porefa<100.0 )
// nca : >=0 numero de la couleur des 4 aretes du quadrangle
// <0 pas de trace des 4 aretes du quadrangle
// ncsa : >=0 numero de la couleur des aretes des n*n sous-quadrangles
// <0 pas de trace des aretes des n*n sous-quadrangles
// neparf : nombre d'epaisseurs en plus de trace des aretes du quadrangle
// ncotgf : >=0 numero de la couleur de trace des tangentes
// < 0 pas de trace des tangentes
// neptgf : nombre d'epaisseurs supplementaires du trace des tangentes
// ntrtgf : numero du type de trait de trace des tangentes
// 0 continu, 1: tirete, 2: doublement tirete
//
// x, y, z: composantes de x y z rangees selon l'ordre suivant
// au sommet1, au sommet2, au sommet3, puis
// au sommet1 la tangente1 selon s1->s2
// au sommet1 la tangente2 selon s1->s3
// au sommet2 la tangente1 selon s2->s3
// au sommet2 la tangente2 selon s2->s1
// au sommet3 la tangente1 selon s3->s4
// au sommet3 la tangente2 selon s3->s2
// au sommet4 la tangente1 selon s4->s1
// au sommet4 la tangente2 selon s4->s3
// ce choix permet une boucle sur les tangentes par les sommets
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
R rcoulq[1+mxsuar][1+mxsuar];
short int xpx[1+mxsuar][1+mxsuar];
short int ypx[1+mxsuar][1+mxsuar];

XPoint xypx[5], pxy, pxy1, pxy2;
R profon[4];
R3 xyz, axyz;
R3 cnorfa;
int i, j, k, kk, i1, i2, ierr;
int nbsuba, nbpx;
int ns1, ns2, ns3;
R reduction, reductio1, h, p, u, v;

// si couleur negative => retour
if( ncf < 0 && nca < 0 ) return;

// la reduction de la face entre 0 et 1
// 0.005 = 0.01/3 car trace ici dans l'element de reference
// et non par rapprochement du barycentre comme dans le cas d'ef p1
reduction = porefa * 0.00333;
reductio1 = 1.0 - reduction;

// recherche du nombre de subdivisions de l'ef reduit de reference
// selon le nombre de pixels obtenus apres mise a l'echelle pixels
// recherche des 2 sommets de la face les plus eloignes de l'oeil
// ========================================================
nbpx = 0;

for ( i=0; i<4; i++)
{
// transformation en coordonnees axonometriques
xyz[0] = x[i];
xyz[1] = y[i];
xyz[2] = z[i];
Vuxyzaxo( xyz, axyz );

//si un point est exterieur aux 2 plans la face n'est pas tracee
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[2] < axoarr ) return;
if( axyz[2] > axoava ) return;
}

// la distance a l'oeil du sommet i
profon[i] = axyz[2];

// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz.x );
if( pxy.x <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
pxy.y = Vunupxey( axyz.y );
if( pxy.y <= minint ) return;
// les coordonnees pixel du sommet i
xypx[i] = pxy;

if( i > 0 )
{
i1 = abs( xypx[i].x-xypx[i-1].x );
i2 = abs( xypx[i].y-xypx[i-1].y );
nbpx = Max( nbpx, Max(i1,i2) );
}

// les coordonnees pixels du point: sommet i + premiere tangente
i1 = 4 + 2 * i;
xyz[0] = x[i] + x[i1];
xyz[1] = y[i] + y[i1];
xyz[2] = z[i] + z[i1];
Vuxyzaxo( xyz, axyz );
pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );
nbpx = Max( nbpx, Max(abs(pxy1.x-pxy.x) , abs(pxy1.y-pxy.y)) );
}

if( nbpx == 0 ) return;

// nombre de subdivisions de chacune des 3 aretes du triangle
nbsuba = Min( Max(2,nbpx/8), mxsuar );

// calcul des images p3 des sommets du maillage de la face reduite
// trace des sous-ef, image p3 des sous-ef de l'ef de reference
// =========================================================
h = ( reductio1 - reduction ) / nbsuba;

// recherche du sommet k du quadrangle le plus eloigne de l'oeil
// pour traiter l'algorithme du peintre
p = profon[0];
k = 0;
if( profon[1] < p )
{
p = profon[1];
k = 1;
}
if( profon[2] < p )
{
p = profon[2];
k = 2;
}
if( profon[3] < p )
{
p = profon[3];
k = 3;
// permutation des sommets pour amener ce sommet 3 en position 0
pecm44( x );
pecm44( y );
pecm44( z );
pecm4r( profon );
}

if( k == 1 )
{
// permutation des sommets pour amener ce sommet 1 en position 0
peci44( x );
peci44( y );
peci44( z );
peci4r( profon );
}
else if( k == 2 )
{
// permutation des sommets pour amener ce sommet 2 en position 0
pec244( x );
pec244( y );
pec244( z );
pec24r( profon );
}

if( profon[3] < profon[1] )
{
// inversion du sens des 4 sommets
// ainsi l'arete la plus eloignee est l'arete 1 du quadrangle
// ce qui conduit a tracer ses sous quadrangles adjacents d'abord
pe44in( x );
pe44in( y );
pe44in( z );
pe4inv( profon );
}

// les coordonnees x y des sommets des sous carres du carre unite
v = reduction;
for (j=0; j<=nbsuba; j++)
{
u = reduction;
for (i=0; i<=nbsuba; i++)
{
xyzdvs( u, v, x, y, z, xyz[0], xyz[1], xyz[2] );
// les coordonnees en pixels du sommet k
Vuxyzaxo( xyz, axyz );
xpx[i][j] = Vunupxex( axyz[0] );
ypx[i][j] = Vunupxey( axyz[1] );

if( lcritr == 0 )
{
// les 3 coordonnes HCT de la normale au point (u,v)
nordvs( u, v, x, y, z, cnorfa, ierr );

// calcul de la couleur en ce point a partir
// de la normale et des eclairages
rcoulq[i][j] = CouleurEclairage( cnorfa );
}

// passage au point suivant
u = u + h;
}
v = v + h;
}

// trace eventuel des 2 tangentes aux 2 sommets de l'arete la plus eloignee
if( ncotgf >= 0 )
{
// la couleur de trace des tangentes
VuCouleur( ncotgf );
// les epaisseurs de trace des tangentes
VuEpaisseur( neptgf );
// trace en continu(0) ou pointille (1) ou double pointille(2)
VuTypeTrait( ntrtgf );

k=3;
for (i=0; i<=1; i++)
{ // au sommet i
xyz.x = x[i];
xyz.y = y[i];
xyz.z = z[i];

// les coordonnees en pixels sur l'ecran
Vuxyzaxo( xyz, axyz );
pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );

for( j=1; j<=2; j++)
{
// la j-eme tangente au sommet i
k = k + 1;
xyz.x = x[i] + x[k];
xyz.y = y[i] + y[k];
xyz.z = z[i] + z[k];

// les coordonnees en pixels sur l'ecran de la pointe de la tg
Vuxyzaxo( xyz, axyz );
pxy2.x = Vunupxex( axyz.x );
pxy2.y = Vunupxey( axyz.y );

// le trace de la tangente
MemoirePx::VuTrait( pxy1, pxy2 );
}
}
}

// trace des sous quadrangles et des sous aretes des 4 cotes du quadrangle
for (i=1; i<=nbsuba; i++)
{
for (j=1; j<=nbsuba; j++)
{
//les coordonnees pixels des 4 sommets du sous-quadrangle
xypx[4].x = xpx[i-1][j-1];
xypx[4].y = ypx[i-1][j-1];

xypx[0].x = xypx[4].x;
xypx[0].y = xypx[4].y;

xypx[1].x = xpx[i ][j-1];
xypx[1].y = ypx[i ][j-1];

xypx[2].x = xpx[i ][j ];
xypx[2].y = ypx[i ][j ];

xypx[3].x = xpx[i-1][j ];
xypx[3].y = ypx[i-1][j ];

// trace du sous-quadrangle
if( ncf >= 0 )
{
if( lcritr == 0 )
{
// trace selon la couleur aux 3 sommets du triangle 012
VuEpaisseur( 0 );
MemoirePx::VuTriangleCouleur( xypx[0], xypx[1], xypx[2],
rcoulq[i-1][j-1], rcoulq[i][j-1], rcoulq[i][j] );
// trace selon la couleur aux 3 sommets du triangle 230
MemoirePx::VuTriangleCouleur( xypx[2], xypx[3], xypx[0],
rcoulq[i][j], rcoulq[i-1][j], rcoulq[i-1][j-1] );
}
else
{
// trace du sous-quadrangle avec la couleur ncf
VuCouleur( ncf );
MemoirePx::VuFace( 5, xypx );
}

if( ncsa >= 0 ) //les aretes du sous quadrangle
{
VuEpaisseur( 0 );
VuCouleur( ncsa );
MemoirePx::VuTraits( 5, xypx );
}
}

// trace de l'arete de la sous face d'une des 4 aretes du quadangle
if( nca >= 0 )
{
if( j == 1 )
{
// l'arete 1 du quadrangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xpx[i-1][0];
pxy1.y = ypx[i-1][0];
pxy2.x = xpx[i ][0];
pxy2.y = ypx[i ][0];
MemoirePx::VuTrait( pxy1, pxy2 );
}

if( i == nbsuba )
{
// l'arete 2 du quadrangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xpx[nbsuba][j-1];
pxy1.y = ypx[nbsuba][j-1];
pxy2.x = xpx[nbsuba][j ];
pxy2.y = ypx[nbsuba][j ];
MemoirePx::VuTrait( pxy1, pxy2 );
}

if( j == nbsuba )
{
// l'arete 3 du quadrangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xpx[i-1][nbsuba];
pxy1.y = ypx[i-1][nbsuba];
pxy2.x = xpx[i ][nbsuba];
pxy2.y = ypx[i ][nbsuba];
MemoirePx::VuTrait( pxy1, pxy2 );
}

if( i == 1 )
{
// l'arete 4 du quadrangle trace plein avec neparf epaisseurs
VuCouleur( nca );
VuTypeTrait( 0 );
VuEpaisseur( neparf );
pxy1.x = xpx[0][j-1];
pxy1.y = ypx[0][j-1];
pxy2.x = xpx[0][j ];
pxy2.y = ypx[0][j ];
MemoirePx::VuTrait( pxy1, pxy2 );
}
}
}
}

// trace eventuel des tangentes aux sommets
if( ncotgf >= 0 )
{
// la couleur de trace pointille ou non des tangentes
VuCouleur( ncotgf );
// le nombre d'epaisseur du trait des tangentes
VuEpaisseur( neptgf );
// trace en continu(0) ou pointille (1) ou double pointille(2)
VuTypeTrait( ntrtgf );

k = 7;
for (i=2; i<=3; i++)
{
// le sommet i
xyz.x = x[i];
xyz.y = y[i];
xyz.z = z[i];

// les coordonnees en pixels sur l'ecran
Vuxyzaxo( xyz, axyz );
pxy1.x = Vunupxex( axyz.x );
pxy1.y = Vunupxey( axyz.y );

for (j=1; j<=2; j++)
{
// la j-eme tangente au sommet i
k = k + 1;
xyz.x = x[i] + x[k];
xyz.y = y[i] + y[k];
xyz.z = z[i] + z[k];

// les coordonnees en pixels sur l'ecran de la pointe de la tg
Vuxyzaxo( xyz, axyz );
pxy2.x = Vunupxex( axyz.x );
pxy2.y = Vunupxey( axyz.y );

// le trace de la tangente
MemoirePx::VuTrait( pxy1, pxy2 );
}
}
}
}


void MemoirePx3d::VuQuadrangleDVS( int lcritr, int ncf, R porefa,
int ncsa, int nca, int neparf,
int ncotgf, int neptgf, int ntrtgf,
int nost[4], R3 xyzst[],
int notg[8], R3 xyztg[] )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Trace le quadrangle dVS-reduit de sommets et tangentes rangees
// ----- dans les tableaux x,y,z (sommets 1 a 4, tangentes 5 a 12) et
// selon la couleur ncf pour la face et nca pour les aretes
//
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans cette fonction
// les autres caracteristiques du trace sont celles actuelles
// entrees:
// lcritr :=0 prise en compte de la normale et des eclairages
// sur un decoupage en sous quadrangles du quadrangle et
// les fonctions de base de l'ef HCT reduit
// dans ce cas ncf est inactif
// Palette de couleurs 3 a 9 recommandee
// >0 prise en compte de la couleur ncf sur tout le quadrangle
// ncf : numero de la couleur de remplissage de la face a tracer
// si lcritr>0 inactif sinon
// <0 pas de trace de l'interieur de la face
// porefa : pourcentage de reduction du trace du quadrangle par rapport
// au barycentre ( 0.0<=porefa<100.0 )
// nca : >=0 numero de la couleur des 4 aretes du quadrangle
// <0 pas de trace des 4 aretes du quadrangle
// ncsa : >=0 numero de la couleur des aretes des n*n sous-quadrangles
// <0 pas de trace des aretes des n*n sous-quadrangles
// neparf : nombre d'epaisseurs en plus de trace des aretes du quadrangle
// ncotgf : >=0 numero de la couleur de trace des tangentes
// < 0 pas de trace des tangentes
// neptgf : nombre d'epaisseurs supplementaires du trace des tangentes
// ntrtgf : numero du type de trait de trace des tangentes
// 0 continu, 1: tirete, 2: doublement tirete
// nost : numero des 4 sommets dans le tableau xyzst (de 1 a Nombre de sommets)
// xyzst: X Y Z des sommets
// notg : numero des 2 tangentes en chacun des 4 sommets du quadrangle
// (de 1 a Nombre de sommets) avec 3 cas >0 =0 et <0 possibles
// 1: au sommet1 la tangente1 est selon s1->s2
// 2: au sommet1 la tangente2 est selon s1->s3
// 3: au sommet2 la tangente1 est selon s2->s3
// 4: au sommet2 la tangente2 est selon s2->s1
// 5: au sommet3 la tangente1 est selon s3->s4
// 6: au sommet3 la tangente2 est selon s3->s2
// 7: au sommet4 la tangente1 est selon s4->s1
// 8: au sommet4 la tangente2 est selon s4->s3
// attention:
// - un numero negatif de tg demande l'inversion des signes
// des 3 composantes de la tangente
// - un numero nul de tg entraine une tangente egale a l'arete correspondante
//
// Dans la suite de cette fonction sont formes 3 tableaux X[12], Y[12], Z[12]
// contenant respectivement l'abscisse X, l'ordonnee Y et la cote Z
// pour calculer rapidement la valeur de HCT(u,v)
// x : abscisse objet des 4 sommets et 8 tangentes a la face
// y : ordonnee objet des 4 sommets et 8 tangentes a la face
// z : cote objet des 4 sommets et 8 tangentes a la face
// x, y, z: a ranger selon l'ordre suivant
// au sommet1, au sommet2, au sommet3,
// au sommet1 la tangente1 selon s1->s2
// au sommet1 la tangente2 selon s1->s3
// au sommet2 la tangente1 selon s2->s3
// au sommet2 la tangente2 selon s2->s1
// au sommet3 la tangente1 selon s3->s4
// au sommet3 la tangente2 selon s3->s2
// au sommet4 la tangente1 selon s4->s1
// au sommet4 la tangente2 selon s4->s3
// ce choix permet une boucle sur les tangentes par les sommets
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
R x[12];
R y[12];
R z[12];
int i, j, k, kk, i1;

// si couleur negative => retour
if( ncf < 0 && nca < 0 ) return;

// construction des tableaux X Y Z des 4 sommets et 8 tangentes
// selon le codage indique dans les commentaires
for ( i=0; i<4; i++ )
{
k = nost[i] - 1;
x[i] = xyzst[k].x;
y[i] = xyzst[k].y;
z[i] = xyzst[k].z;
}

j = 0;
for ( i=0; i<4; i++ )
{
k = notg[j]; // tangente 1 au sommet i selon st i-> st i+1
if( k == 0 )
{ // tangente = arete i->i+1
if( i == 3 )
i1=0;
else
i1=i+1;

k = nost[i ] - 1;
kk = nost[i1] - 1;
x[4+j] = xyzst[kk][0] - xyzst[k][0];
y[4+j] = xyzst[kk][1] - xyzst[k][1];
z[4+j] = xyzst[kk][2] - xyzst[k][2];
}
else if ( k < 0 )
{ // tangente = - tg j
k = -k -1;
x[4+j] = -xyztg[k][0];
y[4+j] = -xyztg[k][1];
z[4+j] = -xyztg[k][2];
}
else
{ // tangente = + tg j
k = k - 1;
x[4+j] = xyztg[k][0];
y[4+j] = xyztg[k][1];
z[4+j] = xyztg[k][2];
}
j = j + 1;


k = notg[j]; // tangente 2 au sommet i selon st i-> st i-1
if( k == 0 )
{ // tangente = arete i->i-1
if( i == 0 )
i1=3;
else
i1=i-1;

k = nost[i ] - 1;
kk = nost[i1] - 1;
x[4+j] = xyzst[kk][0] - xyzst[k][0];
y[4+j] = xyzst[kk][1] - xyzst[k][1];
z[4+j] = xyzst[kk][2] - xyzst[k][2];
}
else if ( k < 0 )
{ // tangente = - tg j
k = -k -1;
x[4+j] = -xyztg[k][0];
y[4+j] = -xyztg[k][1];
z[4+j] = -xyztg[k][2];
}
else
{ // tangente = + tg j
k = k - 1;
x[4+j] = xyztg[k][0];
y[4+j] = xyztg[k][1];
z[4+j] = xyztg[k][2];
}
j = j + 1;
}

// le trace effectif
VuQuadrangleDVS( lcritr, ncf, porefa,
ncsa, nca, neparf,
ncotgf, neptgf, ntrtgf,
x, y, z );
}


void MemoirePx3d::VuTriangle3s3n( int lcritr, int nca, int nepa, int ncn, int nepn,
R3 xyzs1, R3 xyzs2, R3 xyzs3,
R3 xyzn1, R3 xyzn2, R3 xyzn3 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Trace le triangle defini par les 3 coordonnees de ses 3 sommets
// ----- et des 3 normales aux sommets selon le code lcritr
//
// attention (x,y,z) en coordonnees objet 3d
// la transformation en pixels est assuree dans cette fonction
// les autres caracteristiques du trace sont celles actuelles
// entrees:
// lcritr : =-1 pas de trace de la face du triangle
// = 0 trace du triangle avec une couleur obtenue selon
// l'eclairage et a partir de la normale moyenne des 3 normales
// = 1 trace du triangle avec une couleur obtenue selon
// l'eclairage et a partir des 3 normales aux sommets
// = 2 trace du triangle avec une couleur obtenue selon
// l'eclairage et les 6 tangentes obtenues a partir
// des 3 aretes et des 3 normales puis triangle HCT
// nca : >=0 numero de la couleur des 3 aretes du triangle
// < 0 pas de trace des 3 aretes du triangle
// nepa : >=0 nombre d'epaisseurs en plus de trace des aretes du triangle
// ncn : >=0 numero de la couleur des normales aux sommets
// <0 pas de trace des aretes des n*n sous-triangles
// nepn : >=0 nombre d'epaisseurs en plus de trace des normales
// xyzs1 : X Y Z du sommet 1
// xyzs2 : X Y Z du sommet 2
// xyzs3 : X Y Z du sommet 3
// xyzn1 : X Y Z de la normale au sommet 1
// xyzn2 : X Y Z de la normale au sommet 2
// xyzn3 : X Y Z de la normale au sommet 3
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
XPoint xypx[4], pxy;
R3 axyz[3];
R coul[3];
R3 tg, normale, binormale;
R x[9], y[9], z[9];
R s;
int i, ncf;

// Passage en coordonnees axonometriques
Vuxyzaxo( xyzs1, axyz[0] );
Vuxyzaxo( xyzs2, axyz[1] );
Vuxyzaxo( xyzs3, axyz[2] );

for ( i=0; i<3; i++ )
{
//si un point est exterieur aux 2 plans la face n'est pas tracee
if( axoarr != 0 || axoava != 0 )
{
// axoarr et axoava sont actifs
if( axyz[i][2] < axoarr ) return;
if( axyz[i][2] > axoava ) return;
}
// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz[i].x );
if( pxy.x <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
pxy.y = Vunupxey( axyz[i].y );
if( pxy.y <= minint ) return;
// les coordonnees pixel du sommet i
xypx[i] = pxy;
}

// les coordonnees pixel du sommet 4=0
xypx[3] = xypx[0];

switch ( lcritr )
{
case -1 : break; // pas de trace de la face

case 0 : // trace selon la normale moyenne
normale[0] = ( xyzn1[0]+xyzn2[0]+xyzn3[0] ) / 3.0;
normale[1] = ( xyzn1[1]+xyzn2[1]+xyzn3[1] ) / 3.0;
normale[2] = ( xyzn1[2]+xyzn2[2]+xyzn3[2] ) / 3.0;
// calcul de la couleur en ce point a partir
// de la normale et des eclairages
ncf = (int) CouleurEclairage( normale );
// trace effectif des traits
VuCouleur( ncf );
MemoirePx::VuFace( 4, xypx );
break;

case 1 : // trace selon les normales aux 3 sommets
VuEpaisseur( nepa );
coul[0] = (int) CouleurEclairage( xyzn1 );
coul[1] = (int) CouleurEclairage( xyzn2 );
coul[2] = (int) CouleurEclairage( xyzn3 );
MemoirePx::VuTriangleCouleur( xypx[0], xypx[1], xypx[2],
coul[0], coul[1], coul[2] );
if( nca>=0 ) MemoirePx::VuBordTriangle( xypx[0], xypx[1], xypx[2] );
goto Normales;

case 2 : // trace selon les 6 tangentes deduites des 3 normales
// construction des coordonnees des 3 sommets
x[0] = xyzs1[0];
y[0] = xyzs1[1];
z[0] = xyzs1[2];

x[1] = xyzs2[0];
y[1] = xyzs2[1];
z[1] = xyzs2[2];

x[2] = xyzs3[0];
y[2] = xyzs3[1];
z[2] = xyzs3[2];

//au sommet s1 les 3 composantes du vecteur normal a la normale xyzn1
//et appartenant au plan defini par cette normale et l'arete s1->s2
tgnoarno( xyzn1, xyzs1, xyzs2, x[3], y[3], z[3] );

//au sommet s1 les 3 composantes du vecteur normal a la normale xyzn1
//et appartenant au plan defini par cette normale et l'arete s1->s3
tgnoarno( xyzn1, xyzs1, xyzs3, x[4], y[4], z[4] );

//au sommet s2 les 3 composantes du vecteur normal a la normale xyzn2
//et appartenant au plan defini par cette normale et l'arete s2->s3
tgnoarno( xyzn2, xyzs2, xyzs3, x[5], y[5], z[5] );

//au sommet s2 les 3 composantes du vecteur normal a la normale xyzn2
//et appartenant au plan defini par cette normale et l'arete s2->s1
tgnoarno( xyzn2, xyzs2, xyzs1, x[6], y[6], z[6] );

//au sommet s3 les 3 composantes du vecteur normal a la normale xyzn3
//et appartenant au plan defini par cette normale et l'arete s3->s1
tgnoarno( xyzn3, xyzs3, xyzs1, x[7], y[7], z[7] );

//au sommet s3 les 3 composantes du vecteur normal a la normale xyzn3
//et appartenant au plan defini par cette normale et l'arete s3->s2
tgnoarno( xyzn3, xyzs3, xyzs2, x[8], y[8], z[8] );

//le trace du triangle HCT
VuTriangleHCT( 0, 0, 0.0, -1, nca, nepa, -1, 0, 0, x, y, z );
goto Normales;
}

// trace des aretes du triangle
if ( nca >= 0 )
{
VuEpaisseur( nepa );
VuCouleur( nca );
MemoirePx::VuTraits( 4, xypx );
}

// trace des normales aux 3 sommets du triangle
Normales:
if ( ncn >= 0 )
{
// le point au bout de la normale du sommet 1
normale[0] = xyzs1[0]+ xyzn1[0];
normale[1] = xyzs1[1]+ xyzn1[1];
normale[2] = xyzs1[2]+ xyzn1[2];
Vuxyzaxo( normale, axyz[0] );

// le point au bout de la normale du sommet 2
normale[0] = xyzs2[0]+ xyzn2[0];
normale[1] = xyzs2[1]+ xyzn2[1];
normale[2] = xyzs2[2]+ xyzn2[2];
Vuxyzaxo( normale, axyz[1] );

// le point au bout de la normale du sommet 3
normale[0] = xyzs3[0]+ xyzn3[0];
normale[1] = xyzs3[1]+ xyzn3[1];
normale[2] = xyzs3[2]+ xyzn3[2];
Vuxyzaxo( normale, axyz[2] );

VuEpaisseur( nepn );
VuCouleur( ncn );
for ( i=0; i<3; i++ )
{
// transformation en pixels dans la fenetre
pxy.x = Vunupxex( axyz[i].x );
if( pxy.x <= minint ) return;
// si le numero pixel est incorrect abandon du trace de la face
pxy.y = Vunupxey( axyz[i].y );
if( pxy.y <= minint ) return;
MemoirePx::VuTrait( xypx[i], pxy );
}
}
}

void MemoirePxMenu::VuBoutonCadre( XPoint pxy4, int largbouton, int hautbouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer le cadre d'un bouton de menu avec son eclairage
// ---- en haut a gauche et un ombrage en bas a droite
//
// entrees:
// pxy4 : coordonnees pixels du coin superieur gauche du bouton
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Decembre 2000
//..................................................................
{
XPoint pxy1, pxy2, pxy3;

pxy1.x = pxy4.x; pxy1.y = pxy4.y + hautbouton-1;
pxy2.x = pxy4.x + largbouton-1; pxy2.y = pxy1.y;
pxy3.x = pxy2.x; pxy3.y = pxy4.y;

VuCouleur( Noir ); //arete ombragee de droite et en bas du bouton
VuTrait( pxy1, pxy2 ); //1-er trait horizontal bas
VuTrait( pxy2, pxy3 ); //1-er trait vertical droit
VuCouleur( Blanc ); //arete eclairee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //1-er trait horizontal haut
VuTrait( pxy4, pxy1 ); //1-er trait vertical gauche

VuCouleur( Noir ); //arete ombragee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //2-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //2-eme trait vertical droit
VuCouleur( Blanc ); //arete eclairee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //2-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //2-eme trait vertical gauche

VuCouleur( GrisSombre ); //arete ombragee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //3-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //3-eme trait vertical droit
VuCouleur( GrisClair ); //arete eclairee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //3-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //3-eme trait vertical gauche

VuCouleur( Gris ); //arete ombragee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //4-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //4-eme trait vertical droit
//arete eclairee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //4-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //4-eme trait vertical gauche
}


void MemoirePxMenu::VuBoutonCadreActif( XPoint pxy4, int largbouton, int hautbouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer le cadre d'un bouton enfonce du menu avec son eclairage
// ---- en haut a gauche et un ombrage en bas a droite
//
// entrees:
// pxy4 : coordonnees pixels du coin superieur gauche du bouton
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Decembre 2000
//..................................................................
{
XPoint pxy1, pxy2, pxy3;

pxy1.x = pxy4.x; pxy1.y = pxy4.y + hautbouton-1;
pxy2.x = pxy4.x + largbouton-1; pxy2.y = pxy1.y;
pxy3.x = pxy2.x; pxy3.y = pxy4.y;

VuCouleur( Blanc ); //arete eclairee de droite et en bas du bouton
VuTrait( pxy1, pxy2 ); //1-er trait horizontal bas
VuTrait( pxy2, pxy3 ); //1-er trait vertical droit
VuCouleur( Noir ); //arete ombragee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //1-er trait horizontal haut
VuTrait( pxy4, pxy1 ); //1-er trait vertical gauche

VuCouleur( Blanc ); //arete eclairee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //2-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //2-eme trait vertical droit
VuCouleur( Noir ); //arete ombragee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //2-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //2-eme trait vertical gauche

VuCouleur( GrisClair ); //arete eclairee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //3-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //3-eme trait vertical droit
VuCouleur( GrisSombre ); //arete ombragee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //3-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //3-eme trait vertical gauche

VuCouleur( Gris ); //arete eclairee de droite et en bas du bouton
pxy1.x++; pxy1.y--; pxy2.x--; pxy2.y--;
pxy3.x--; pxy3.y++; pxy4.x++; pxy4.y++;
VuTrait( pxy1, pxy2 ); //4-eme trait horizontal bas
VuTrait( pxy2, pxy3 ); //4-eme trait vertical droit
//arete ombragee de la gauche et du haut du bouton
VuTrait( pxy3, pxy4 ); //4-eme trait horizontal haut
VuTrait( pxy4, pxy1 ); //4-eme trait vertical gauche
}

void MemoirePxMenu::VuBoutonMenu( char *textebouton, int couleurbouton,
int hauttexte, int decaltexte,
XPoint pxy0, int largbouton, int hautbouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer un bouton de menu avec son texte et un eclairage
// ---- en haut a gauche et un ombrage en bas a droite
//
// entrees:
// textebouton : caracteres du texte du bouton
// couleurbouton: couleur du fond d'un bouton
// hauttexte : nombre de pixels en hauteur de la fonte des caracteres
// decaltexte : nombre de pixels de decalage du texte par rapport a la
// base et gauche du bouton
// pxy0 : coordonnees pixels du coin superieur gauche du bouton
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Decembre 2000
//..................................................................
{
XPoint pxy;

//Trace du rectangle central du bouton
VuEpaisseur( 0 ); //de 1 pixel
VuTypeTrait( 0 ); //continu
VuCouleur( couleurbouton );
VuRectangle( pxy0, largbouton, hautbouton );

VuChoisirFonte( hauttexte ); //trace du texte en noir
VuCouleur( Noir );
pxy.x = pxy0.x + decaltexte + 3;
pxy.y = pxy0.y - decaltexte - 3 + hautbouton;
VuTexte( pxy, textebouton );

VuBoutonCadre( pxy0, largbouton, hautbouton ); //le cadre du bouton
}

void MemoirePxMenu::VuBoutonMenuActif( char *textebouton, int couleurbouton,
int hauttexte, int decaltexte,
XPoint pxy0, int largbouton, int hautbouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer un bouton de menu avec son texte et un eclairage inverse
// ---- c-a-d en bas a droite et un ombrage en haut a gauche
// Produire un effet de bouton enfonce / VuBoutonMenu
//
// entrees:
// textebouton : caracteres du texte du bouton
// couleurbouton: couleur du fond d'un bouton
// pxy0 : coordonnees pixels du coin superieur gauche du bouton
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
// hauttexte : nombre de pixels en hauteur de la fonte des caracteres
// decaltexte : nombre de pixels de decalage du texte par rapport a la
// base et gauche du bouton
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Decembre 2000
//..................................................................
{
XPoint pxy;

//le rectangle central du bouton est trace
VuEpaisseur( 0 ); //de 1 pixel
VuTypeTrait( 0 ); //continu
VuCouleur( couleurbouton );
VuRectangle( pxy0, largbouton, hautbouton );

VuChoisirFonte( hauttexte ); //trace du texte
VuCouleur( Blanc ); //texte en blanc

pxy.x = pxy0.x + decaltexte + 3;
pxy.y = pxy0.y - decaltexte - 3 + hautbouton ;
VuTexte( pxy, textebouton );
VuBoutonCadreActif( pxy0, largbouton, hautbouton );
}

void MemoirePxMenu::VuMenuHorizontal( int nbbouton, char **textebouton,
int largbouton, int couleurbouton,
XPoint pxy0,
int & largmenu, int & hautmenu, int & nobouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer un menu horizontal compose de nbbouton et retourner
// ---- le numero du bouton choisi par clic d'un bouton ou frappe
// de l'unique majuscule du texte de l'un des boutons du menu
//
// entrees:
// nbbouton : nombre de boutons du menu horizontal
// textebouton : caracteres du texte de chacun des boutons du menu
// textebouton[nbbouton][]
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
// couleurbouton : couleur du fond d'un bouton
// nbepbordbouton: nombre d'epaisseurs du trait du bord d'un bouton
// hauttexte : nombre de pixels en hauteur de la fonte des caracteres
// decaltexte : nombre de pixels de decalage du texte par rapport a la
// base et gauche du bouton
// pxy0 : coordonnees pixels du coin superieur gauche du menu
//
// sorties:
// largmenu: nombre de pixels de la largeur totale du menu
// hautmenu: nombre de pixels de la hauteur totale du menu
// nobouton: numero du bouton choisi par l'utilisateur
// =-1 => demande d'abandon de l'entree d'un bouton
// >=0 => numero du bouton choisi
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
XPoint pxy;
int i, j, n, notyev, nbc;

//le contenu du menu est efface
XSetForeground(display_vu, gc_vu, background);
pxy.x=0; pxy.y=0;
VuRectangle( pxy, lapxfe, lhpxfe );

//le trace des boutons du menu
pxy = pxy0;
for (i=0; i<nbbouton; i++)
{
VuBoutonMenu( textebouton[i], couleurbouton, hauttexte, decaltexte,
pxy, largbouton, hautbouton );
pxy.x += largbouton;
}

//ajout du menu a fenetre_vu et affichage dans la fenetre
largmenu = largbouton * nbbouton;
hautmenu = hautbouton;
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largmenu, hautmenu,
pxy0 );

Evenement: //===========================================================

VuSouris( notyev, nbc, pxy ); //en attente d'evenement clavier ou souris
switch( notyev ) //calcul du numero du bouton clique du menu horizontal
{
case 0: //ABANDON demande
nobouton = -1;
return;

case 1: //clic enfonce et relache du bouton nbc de la souris en pxy
if ( pxy.x<pxy0.x || pxy.x>pxy0.x+largmenu
|| pxy.y<pxy0.y || pxy.y>pxy0.y+hautmenu )
{ nobouton=-1; return; }
else
nobouton = (pxy.x-pxy0.x) / largbouton;
break;

case 2: //frappe au clavier du caractere ascii nbc
if( nbc>96 && nbc<123 ) nbc=nbc-32; //passage de lettre minuscule en majuscule
if( nbc<65 || nbc>91 ) goto Evenement;
//ici le caractere est une lettre majuscule
for (i=0; i<nbbouton; i++)
{
//recherche de la majuscule du texte du bouton i
for (j=0; j<strlen(textebouton[i]); j++)
{
n = (int) textebouton[i][j];
if( n>=65 && n<=91 ) break;
}
if( n == nbc ) { nobouton = i; break; }
}
goto Evenement;

default: goto Evenement;
}

//Trace du bouton choisi
pxy0.x += largbouton*nobouton;
VuBoutonMenuActif( textebouton[nobouton], Cyan, hauttexte, decaltexte,
pxy0, largbouton, hautbouton );
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largbouton, hautbouton,
pxy0 );
}

void MemoirePxMenu::VuMenuVertical( int nbbouton, char **textebouton,
int largbouton, int couleurbouton,
XPoint pxy0,
int & largmenu, int & hautmenu, int & nobouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer un menu vertical compose de nbbouton et retourner
// ---- le numero du bouton choisi par clic d'un bouton ou frappe
// de l'unique majuscule du texte de l'un des boutons du menu
//
// entrees:
// nbbouton : nombre de boutons du menu horizontal
// textebouton : caracteres du texte de chacun des boutons du menu
// textebouton[nbbouton][]
// largbouton : nombre de pixels en largeur d'un bouton
// hautbouton : nombre de pixels en hauteur d'un bouton
// nbepbordbouton: nombre d'epaisseurs du trait du bord d'un bouton
// couleurbouton : couleur du fond d'un bouton
// hauttexte : nombre de pixels en hauteur de la fonte des caracteres
// decaltexte : nombre de pixels de decalage du texte par rapport a la
// base et gauche du bouton
// pxy0 : coordonnees pixels du coin superieur gauche du menu
//
// sorties:
// largmenu: nombre de pixels de la largeur totale du menu
// hautmenu: nombre de pixels de la hauteur totale du menu
// nobouton: numero du bouton choisi par l'utilisateur
// =-1 => demande d'abandon de l'entree d'un bouton
// >=0 => numero du bouton choisi
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
XPoint pxy;
int i, j, n, notyev, nbc;

//le trace des boutons du menu
pxy = pxy0;
for (i=0; i<nbbouton; i++)
{
VuBoutonMenu( textebouton[i], couleurbouton, hauttexte, decaltexte,
pxy, largbouton, hautbouton );
pxy.y += hautbouton;
}

//ajout du menu a fenetre_vu et affichage dans la fenetre
largmenu = largbouton;
hautmenu = hautbouton * nbbouton;
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largmenu, hautmenu,
pxy0 );

Evenement: //===========================================================

VuSouris( notyev, nbc, pxy ); //en attente d'evenement clavier ou souris

switch( notyev ) //calcul du numero du bouton clique du menu horizontal
{
case 0: //ABANDON demande
nobouton = -1;
return;

case 1: //clic enfonce et relache du bouton nbc de la souris en (nx,ny)
if ( pxy.x<pxy0.x || pxy.x>pxy0.x+largmenu
|| pxy.y<pxy0.y || pxy.y>pxy0.y+hautmenu )
{ nobouton = -1; return; }
else
{ nobouton = (pxy.y-pxy0.y) / hautbouton; break; }

case 2: //frappe au clavier du caractere ascii nbc
if( nbc>96 && nbc<123 ) nbc=nbc-32; //passage de lettre minuscule en majuscule
if( nbc<65 || nbc>91 ) goto Evenement;
//ici le caractere est une lettre majuscule
for (i=0; i<nbbouton; i++)
{
//recherche de la majuscule du texte du bouton i
for (j=0; j<strlen(textebouton[i]); j++)
{
n = (int) textebouton[i][j];
if( n>=65 && n<=91 ) break;
}
if( n == nbc ) { nobouton = i; goto BoutonActif; }
}
goto Evenement;

default: goto Evenement;
}

//Trace du bouton choisi
BoutonActif:
pxy0.y += hautbouton*nobouton;
VuBoutonMenuActif( textebouton[nobouton], Cyan, hauttexte, decaltexte,
pxy0, largbouton, hautbouton );
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largbouton, hautbouton,
pxy0 );
}

void MemoirePxMenu::VuMenuLateral( int nbbouton, char **textebouton,
int largbouton, int couleurbouton,
XPoint pxy0,
int & largmenu, int & hautmenu, int & nobouton )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Tracer un menu lateral a un menu vertical compose de nbbouton et
// ---- retourner le numero du bouton choisi par clic d'un bouton ou
// frappe de l'unique majuscule du texte de l'un des boutons du menu
//
// entrees:
// nbbouton: nombre de boutons du menu horizontal
// textebouton: caracteres du texte de chacun des boutons du menu
// textebouton[nbbouton][]
// largbouton: nombre de pixels en largeur d'un bouton
// hautbouton: nombre de pixels en hauteur d'un bouton
// couleurbouton: couleur du fond d'un bouton
// hauttexte: nombre de pixels en hauteur de la fonte des caracteres
// decaltexte: nombre de pixels de decalage du texte par rapport a la
// base et gauche du bouton
// pxy0: coordonnees pixels du coin superieur gauche du menu
//
// sorties:
// largmenu: nombre de pixels de la largeur totale du menu
// hautmenu: nombre de pixels de la hauteur totale du menu
// nobouton: numero du bouton choisi par l'utilisateur
// =-1 => demande d'abandon de l'entree d'un bouton
// >=0 => numero du bouton choisi
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
XPoint pxy;
int i, j, n, notyev, nbc;

//Ajustage du menu a gauche si debordement a droite
if( (pxy0.x+largbouton) > lapxfe ) //menu lateral mis a gauche du menu vertical
{ pxy0.x -= 2 * largbouton; }

//le trace des boutons du menu
pxy = pxy0;
for (i=0; i<nbbouton; i++)
{
VuBoutonMenu( textebouton[i], couleurbouton, hauttexte, decaltexte,
pxy, largbouton, hautbouton );
pxy.y += hautbouton;
}

//ajout du menu a fenetre_vu et affichage dans la fenetre
largmenu = largbouton;
hautmenu = hautbouton * nbbouton;
//ajout du menu a fenetre_vu et affichage dans la fenetre
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largmenu, hautmenu,
pxy0 );

Evenement: //===========================================================

VuSouris( notyev, nbc, pxy ); //en attente d'evenement clavier ou souris

switch( notyev ) //calcul du numero du bouton clique du menu horizontal
{
case 0: //ABANDON demande
nobouton = -1;
return;

case 1: //clic enfonce et relache du bouton nbc de la souris en (nx,ny)
if ( pxy.x<pxy0.x || pxy.x>pxy0.x+largmenu
|| pxy.y<pxy0.y || pxy.y>pxy0.y+hautmenu )
{ nobouton = -1; return; }
else
{ nobouton = (pxy.y-pxy0.y) / hautbouton; break; }

case 2: //frappe au clavier du caractere ascii nbc
if( nbc>96 && nbc<123 ) nbc=nbc-32; //passage de lettre minuscule en majuscule
if( nbc<65 || nbc>91 ) goto Evenement;
//ici le caractere est une lettre majuscule
for (i=0; i<nbbouton; i++)
{
//recherche de la majuscule du texte du bouton i
for (j=0; j<strlen(textebouton[i]); j++)
{
n = (int) textebouton[i][j];
if( n>=65 && n<=91 ) break;
}
if( n == nbc ) { nobouton = i; goto BoutonActif; }
}
goto Evenement;

default: goto Evenement;
}

//Trace du bouton choisi
BoutonActif:
pxy0.y += hautbouton*nobouton;
VuBoutonMenuActif( textebouton[nobouton], Cyan, hauttexte, decaltexte,
pxy0, largbouton, hautbouton );
VuCombinerMemoirePxDansFenetre( GXcopy, //GXcopy <=> src
pxy0, largbouton, hautbouton,
pxy0 );
}


void MemoirePx::VuEffacerMemoirePx( void )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but: Effacer le contenu de MemoirePx (mais pas dans la fenetre_vu)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
XPoint pxy0={0,0};

//effacement de la MemoirePx avec la couleur de fond
VuCouleur( nobackground );
VuRectangle( pxy0, largeurpx, hauteurpx );
}


void MemoirePxInvite::VuInvite( char *texteinvite )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Tracer un texte comme invite dans la fenetre en bas et a gauche
//
// variables globales:
// texteinvite : caracteres du texte de chacun de l'invite
// larginvite : nombre de pixels en largeur de l'invite
// hautinvite : nombre de pixels en hauteur de l'invite
// nbepbordinvite : nombre d'epaisseurs du trait du bord de l'invite
// couleurinvite : couleur du fond de l'invite
// couleurtexteinvite: couleur du texte de l'invite
// hauttexte : nombre de pixels en hauteur de la fonte des caracteres
// decaltexte : nombre de pixels de decalage du texte par rapport a la
// base et gauche du invite
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Auteur : Perronnet Alain analyse numerique UPMC Paris Novembre 2000
//..................................................................
{
XPoint pxy0invite={0,0}; //coin superieur gauche dans l'invite

//La couleur du fond efface l'ancien texte
//VuEffacerMemoirePx();

//sauvegarde du texte de l'invite
strcpy( TexteInvite, texteinvite );

//trace du bouton de la nouvelle invite
VuBoutonMenu( texteinvite, couleurinvite, hauttexte, decaltexte,
pxy0invite, larginvite, hautinvite );

//copie de l'invite dans fenetre_vu avec GXcopy (0x3) <=> src
XPoint pxyfenetre={0,short(lhpxfe-hautinvite+1)};
VuCombinerMemoirePxDansFenetre( GXcopy,
pxy0invite, larginvite, hautinvite,
pxyfenetre );
}

void MemoirePxInvite::VuLigneClavier( char *LigneClavier )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : Concatener TexteInvite et LigneClavier et tracer en ligne
// ----- basse du menu
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
char LigneBasseMenu[256];
XPoint pxy0={0,0};

//l'invite est effacee et le trace se fait dans invite
VuEffacerMemoirePx();

//concatenation de l'invite et de la ligne saisie au clavier
strcpy( LigneBasseMenu, TexteInvite );
strcat( LigneBasseMenu, " = " );
strcat( LigneBasseMenu, LigneClavier );

//le trace du bouton de la nouvelle invite
VuBoutonMenu( LigneBasseMenu, couleurinvite, hauttexte, decaltexte,
pxy0, larginvite, hautinvite );

//ajout du menu a fenetre_vu et affichage de fenetre_vu
XPoint pxy1={0,lhpxfe-hautinvite};
VuCombinerMemoirePxDansFenetre( GXcopy,
pxy0, larginvite, hautinvite, //source
pxy1 ); //destination
}


void MemoirePxInvite::lire1LigneTexte( int no1car, char *ChaineCar )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : saisir interactivement une ligne de caracteres sur le clavier
// ----- a partir du no1car-eme caractere de ChaineCar
// entree :
// no1car : numero du premier caractere a lire dans ChaineCar de 0 a strlen-1
// pour commencer au debut choisir no1car=0
// sortie :
// ChaineCar: la ligne des caracteres lus a partir de no1car et terminee par '\0'
// '@\0' en cas d'abandon demande par @ ou echappement
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//auteur : alain perronnet analyse numerique upmc paris decembre 2000
//3456---------------------------------------------------------------
{
char carlu; //pour C++ carlu est un caractere par exemple '3'
int nascii; //nascii=int('3')=50 est l'entier no du caractere Ascii

if( no1car > 0 ) VuLigneClavier( ChaineCar );

while(1)
{
//en attente de lecture d'un caractere
carlu = lire1Caractere();
nascii = (int) carlu;

//le caractere carlu de numero ASCII nascii a ete lu au clavier
switch( nascii )
{
case 64: // caractere 64 '@'
case 27: // caractere 27 Echappement
strcpy(ChaineCar,"@"); return;

case 13 : // caractere 13 '\r' retour chariot
ChaineCar[no1car] = '\0'; return;

case 8: // caractere backspace <-
case 127: // caractere suppression
if( no1car>0 ) {no1car--;}
ChaineCar[no1car]='\0';
break;
}

if( nascii < 32 || nascii > 126 ) continue; //un caractere incorrect

//trace de la ligne lue en suite de la ligne d'invite
ChaineCar[no1car] = carlu; no1car++;
ChaineCar[no1car] = '\0';
VuLigneClavier( ChaineCar );
}
}

void MemoirePxInvite::lireZ( int & ncvals, Z & entier )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//but : lire une chaine de caracteres representant un entier
//----- retourner la valeur de l'entier
//
//sortie :
//--------
//ncvals : 1 l'entier est initialise
// -1 abandon de la lecture par entree de @ ou Echappement
//entier : la valeur de l' entier lu si ncvals=1
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//auteur : perronnet alain analyse numerique upmc paris decembre 2000
//------------------------------------------------------------------
{
int nocar, lesigne=1, nascii;
char car;

Clavier:
lire1LigneTexte( 0, TexteClavier );//lecture d'une chaine frappee au clavier

//traitement du premier caractere
nocar = 0;
if( TexteClavier[nocar] == '@' ) {ncvals = -1; entier=0; return;}
if( TexteClavier[nocar] == '-' ) {lesigne = -1; nocar++;}
if( TexteClavier[nocar] == '+' ) {lesigne = 1; nocar++;}

nascii = (int) TexteClavier[nocar];
if( nascii < 48 || nascii > 57 ) goto Clavier; //48 est '0' et 57 est '9'
entier = char(nascii - 48);
nocar++;

//traitement des chiffres suivants
for (char *c=&TexteClavier[nocar]; *c; c++ )
{
nascii = (int) *c;
if( nascii < 48 || nascii > 57 ) break;

//*c est un chiffre
entier = entier * 10 + (nascii-48);
}

ncvals = 1;
entier = entier * lesigne; //ajout du signe de l'entier
}

void MemoirePxInvite::lireR( int & ncvals, R & Reel )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//but : lire une chaine de caracteres representant un Reel et
//----- retourner la valeur du Reel de type R
//
//sortie :
//--------
//ncvals : 1 le Reel est initialise
// -1 abandon de la lecture par entree de @ ou Echappement
//Reel : la valeur du Reel lu si ncvals=1
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//auteur : perronnet alain analyse numerique upmc paris decembre 2000
//------------------------------------------------------------------
{
char *c;

lire1LigneTexte( 0, TexteClavier );

//traitement du premier caractere
if( TexteClavier[0] == '@' ) {ncvals = -1; Reel=0; return;}

//recherche de ';'
//c=strstr(TexteClavier,";");
//cout << "c=" << c;
//if( c ) *c = '\0';

//transformation des caracteres en R
//Reel = strtod( TexteClavier, endptr ); TILT
Reel = atof( TexteClavier );
ncvals = 1;
//cout << "lireR: Reel=" << Reel << endl;
}

void MemoirePxInvite::lireXYZ( int & ncvals, R3 & XYZ )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//but : lire une chaine de caracteres representant un XYZ
//----- c-a-d 3 reels avec invite pour X puis Y puis Z
// retourner la valeur du XYZ de type R3
// la demande est toujours satisfaite car pas de retour tant que
// la valeur du XYZ est incorrecte sauf @ demandant l'abandon
//
//sortie :
//--------
//ncvals : 1 le XYZ est initialise
// -1 abandon de la lecture par entree de @ ou Echappement
//XYZ : la valeur du XYZ de type R3 lu
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//auteur : perronnet alain analyse numerique upmc paris decembre 2000
//------------------------------------------------------------------
{
VuEffacerMemoirePx();
VuInvite( "Frapper l'abscisse du POINT X" );
lireR( ncvals, XYZ.x );
if( ncvals == -1 ) return;

VuEffacerMemoirePx();
VuInvite( "Frapper l'ordonnee du POINT Y" );
lireR( ncvals, XYZ.y );
if( ncvals == -1 ) return;

VuEffacerMemoirePx();
VuInvite( "Frapper la cote du POINT Z" );
lireR( ncvals, XYZ.z );
if( ncvals == -1 ) return;

VuEffacerMemoirePx();
}

// =======================================================================
// Les FONCTIONS UTILITAIRES
// =======================================================================

int nudcnb( char *texte )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Retourner le nombre de caracteres avant le caractere '\0' dans texte
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR: PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS OCTOBRE 2000
//..........................................................................
{
int i;

i=0;
while ( *(texte+i) != '\0' && i < 1024 ) {i+=1;}
// cout << "nudcnb retourne la valeur " <<i << endl;
if ( i < 1024 )
return i;
else
return 0; // '\0' est ici suppose non retrouve
}

char *strstrtab( char **tabcar, int nbvtab, char *mot )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Retourner le pointeur sur le premier caractere de mot retrouve dans tabcar
// tableau de nbvtab chaines de caracteres et NULL si non retrouve
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR: PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS Decembre 2000
//............................................................
{
char *c, *m;

c = *tabcar;
for (int i=0; i<nbvtab; i++)
{
cout << "strstrtab: c=" << c << " *c=" << *c << " *mot=" << *mot << endl;
m = strstr(c,mot);
cout << "m=" << m << endl;
if( m != NULL ) return m;
c += nudcnb( c );
c++;
}
cout << "non retrouve" << endl;
return NULL;
}


void itoa( int entier, int & nbcar, char * texte )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Retourner le nombre et les caracteres du texte de l'entier
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR: PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS OCTOBRE 2000
//..........................................................................
{ int n;

if( entier==0 )
{ //cas particulier du zero
nbcar = 1;
strcpy( texte, "0" );
return;
}

//Ici l'entier est non nul
nbcar = 0;
if ( entier < 0 ) // le traitement du signe -
{
entier = -entier;
nbcar = 1;
*texte = '-';
}

n = entier; // le nombre de chiffres
while ( n != 0 )
{
nbcar += 1;
n = n / 10;
}

*(texte+nbcar) = '\0'; // le caractere '\0'
n = nbcar;

while ( entier != 0 )
{
n = n - 1;
*(texte+n) = (char) ( (int) '0' + entier % 10 );
entier = entier / 10;
}
}


void rtoa( R vreel, int nbchif10, int & nbcar, char * texte )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Retourner le nombre et les caracteres du texte de vreel
// avec nbchif10 nombre de chiffres de la partie decimale
// Forme normalisee du texte: -0.partie10Eexposant10
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR: PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS OCTOBRE 2000
//..........................................................................
{
int n, exposant10, partie10;

if ( vreel == 0.0 ) // traitement special du zero
{
nbchif10 = 1;
*(texte+1) = '0'; // le premier chiffre
*(texte+2) = '.';
*(texte+3) = '0';
*(texte+4) = '\0'; // fin de chaine
nbcar = 4;
return;
}

if ( vreel < 0 ) // le traitement du signe - du R
{
vreel = -vreel;
*texte = '-';
}
else
{
*texte = '+';
}

*(texte+1) = '0'; // le premier chiffre
*(texte+2) = '.';
*(texte+3) = '\0'; // fin de chaine
nbcar = 3;

exposant10 = 0;
while ( vreel >= 1.0 )
{
exposant10 += 1; // exposant de 10 positif
vreel = vreel / 10.0;
}

while ( vreel < 0.1 )
{
exposant10 -= 1; // exposant de 10 negatif
vreel = vreel * 10.0;
}

// ici 0.1 <= vreel < 1.0
// calcul de vreel * 10 ** nbchif10
if ( nbchif10 <= 0 ) nbchif10=1;
for ( n=1; n<=nbchif10; n++ ) vreel = vreel * 10;

// l'entier derriere 0. partie decimale de vreel
partie10 = int( vreel+0.5 );

// rangement dans texte de la partie decimale
itoa( partie10, n, (texte+nbcar) );
nbcar += n;

if ( exposant10 != 0 )
{
// Ajout derriere de "e"
strcat( texte, "e" );
nbcar += 1;

// rangement dans texte de l'exposant de 10
itoa( exposant10, n, (texte+nbcar) );
nbcar += n;
}

//cout << "Sortie rtoa vreel=" << vreel << " nbcar=" << nbcar << " texte=";
//for (n=0; n<nbcar; n++) cout << *(texte+n);
//cout << endl;
}

R Secondes1970()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Retourne le nombre de secondes depuis le 1/1/1970 minuit
// les micro-secondes factices ont pour but de dissocier 2 appels
// memes tres rapproches et notamment dans la meme seconde
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//AUTEUR : PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS MARS 1996
//345X7..........................................................01234567890
{
nbs1970 = nbs1970 + 1 ;
return R( time( NULL ) + nbs1970 * 0.000001 );
}


R Tempscpu( R *tclock )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Retourne le temps CPU utilise
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//AUTEUR : PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS NOVEMBRE 1994
//12345X7..........................................................012345678*/
{
return ( (R) clock() ) / CLOCKS_PER_SEC ;
}


void NomOrdinateurHote( char *host, int *nbcar)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Retourne le nom de l'ordinateur hote
// -----
// SORTIES :
// ---------
// host : nom de l'ordinateur hote
// nbcar : nombre de caracteres du nom de l'ordinateur hote
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//AUTEUR : P LAUG ou F. HECHT INRIA DECEMBRE 1994
//12345X7..........................................................012345678*/
{
char name[80];

if (gethostname(name, 80) != 0 )
{
fprintf(stderr, "nom de l'ordinateur hote a declarer\n") ;
return ;
}
*nbcar = strlen(name) ;
strcpy( host, name );
}


void LaDate( int *a, int *m, int *j )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : Retourne la date du jour en an mois jour
-----
SORTIES :
---------
a : annee
m : mois
j : jour
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR: P LAUG ou F. HECHT INRIA DECEMBRE 1994
12345X7..........................................................012345678*/
{
time_t timevar;
struct tm *pttm;

timevar=time(&timevar);
pttm = localtime(&timevar);

*a = pttm->tm_year;
*m = pttm->tm_mon+1;
*j = pttm->tm_mday ;

return;
}

void HeureMinuteSeconde( int *h, int *m, int *s, int *millis )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BUT : Retourne l'heure en heure minute seconde et millisecondes
-----
SORTIES :
---------
h : heure
m : minute
s : seconde
millis : millisecondes
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AUTEUR : P LAUG ou F. HECHT INRIA DECEMBRE 1994
12345X7..........................................................012345678*/
{
time_t timevar;
struct tm *pttm;

timevar=time(&timevar);
pttm = localtime(&timevar);
*h = pttm->tm_hour;
*m = pttm->tm_min;
*s = pttm->tm_sec;
*millis = 0;

return;
}


void ValVarEnv( char *nom, int *lval_admis,
char *val, int *lval_trouve )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// BUT : Retourne la valeur de la variable d'environnement nom
// -----
// ENTREES :
// ---------
// nom : nom de la variable d'environnement termine par '\0'
// lval_admis : nombre maximal de caracteres admis pour sa valeur
// SORTIES :
// ---------
// val : la chaine de caracteres valeur de la variable d'environnement
// lval_trouve : < 0 si le nom de la variable n'est pas trouvee
// > strlen(nom) si la valeur de la variable a ete tronquee
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//AUTEUR: P LAUG ou F. HECHT INRIA Mars 1991
//12345X7..........................................................012345678
{
char *ptenv;
int i ;

ptenv = getenv(nom) ;
if (ptenv == NULL)
{
*lval_trouve = -1 ; /* variable d'environnement non trouvee */
return ;
}
for (i=0 ; *(ptenv+i)!='\0' ; i++)
if (i<*lval_admis) *(val+i) = *(ptenv+i) ;
*lval_trouve = i ;

return;
}


void ProduitVectoriel( R3 v1, R3 v2, R3 & v3 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer le vecteur v3 = v1 produit vectoriel v2
// -----
// entrees:
// --------
// v1, v2 : 2 vecteurs de R3
//
// sortie :
// --------
// v3 : le vecteur v1 produit vectoriel v2
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
v3[ 0 ] = v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ];
v3[ 1 ] = v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ];
v3[ 2 ] = v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ];
}


bool xyzide( R3 xyz1, R3 xyz2 )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : identifier ou non 2 points definis par 3 coordonnees
// -----
// entrees:
// --------
// xyz1 : le premier point
// xyz2 : le second point
//
// sortie :
// --------
// true si les 2 points sont juges identiques, false sinon
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// AUTEUR: PERRONNET ALAIN ANALYSE NUMERIQUE UPMC PARIS OCTOBRE 2000
//..........................................................................
{
R r1, r2;

// comparaison des 3 coordonnees
for ( int k=0; k<3; k++ )
{
r1 = fabs( xyz1[k] );
r2 = fabs( xyz2[k] );
if ( r1 <= epzero )
{
if ( r2 > epzero ) return false;
}
else
{
if( r2 <= epzero )
{
return false;
}
else
{
if( fabs(xyz1[k]-xyz2[k]) > r1*epsxyz ) return false;
}
}
}

// les 2 points xyz1 et xyz2 sont identiques
return true;
}


R ValeurP3H( R u, R f0, R f1, R tg0, R tg1 )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur d'interpolation du polynome P3 HERMITE
// ----- d'une fonction valant f0 en 0, f1 en 1 et
// de derivee tg0 en 0 et -derivee tg1 en 1
// C'EST A DIRE
// VALP3H(0) = F0 = F(0)
// VALP3H(1) = F1 = F(1)
// d VALP3H / du (0)(1-0) = T0 = DF(0) (1-0)
// d VALP3H / du (1)(0-1) = T1 = DF(1) (0-1) = -DF(1)
// ATTENTION: d VALP3H / du (1) = -T1 ...!
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Alain Perronnet analyse numerique upmc paris Novembre 2000
//2345x7..........................................................012
{
R u2, u3, v;

u2 = u * u;
u3 = u * u2;
v = 3*u2 - 2*u3;
return ( v * (f1 - f0) + f0 + (u3-u2) * (tg0 - tg1) + tg0 * (u - u2) );
}


void peci33( R x[9] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : permutation circulaire des 3 sommets et 6 tangentes croisees;
// ----- du triangle hct lorsque le sommet 2 devient le sommet 1;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : Alain Perronnet analyse numerique upmc paris Novembre 2000
//2345x7..........................................................012
{
R u;

u = x[0];
x[0] = x[1];
x[1] = x[2];
x[2] = u;

u = x[3];
x[3] = x[5];
x[5] = x[7];
x[7] = u;

u = x[4];
x[4] = x[6];
x[6] = x[8];
x[8] = u;

return;
}


void pecm33( R x[9] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : permutation circulaire des 3 sommets et 6 tangentes croisees;
// ----- du triangle hct lorsque le sommet 3 devient le sommet 1;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[0];
x[0] = x[2];
x[2] = x[1];
x[1] = u;

u = x[3];
x[3] = x[7];
x[7] = x[5];
x[5] = u;

u = x[6];
x[6] = x[4];
x[4] = x[8];
x[8] = u;

return;
}


void vfbhct( R u, R v, R fb[9] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur au point [u,v] des 9 fonctions de base de l'ef
// ----- du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
//
// sortie :
// --------
// fb : la valeur au point [u,v] des 9 fonctions de base
// du hct reduit rangees selon k
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R l1, l2, l3, l1l1, l2l2, l3l3;
R cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9, cb10;

if( v*2 >= 1-u && v >= 1-2*u )
{

//le point [u,v] est dans le sous triangle e1;
//===========================================;
// e1 = 0.0;
// e2 = 1.0;
// e3 =-1.0;
//les coordonnees barycentriques du point [u,v] du triangle rectangle unite;
l1 = 1.0 - u - v;
l2 = u;
l3 = v;

//les produits des coordonnees barycentriques;
l1l1 = l1 * l1;
l2l2 = l2 * l2;
l3l3 = l3 * l3;

cb1 = l1l1 * l1;
cb2 = l2l2 * l2;
cb3 = l3l3 * l3;
cb4 = l1l1 * l3;
cb5 = l1l1 * l2;
cb6 = l2l2 * l1;
cb7 = l2l2 * l3;
cb8 = l3l3 * l2;
cb9 = l3l3 * l1;
cb10 = l1 * l2 * l3;

fb[0] = -cb1 + 6 * (cb4 + cb5);
fb[1] = cb1 + cb2 - 1.5 * (cb4+cb5) + 3 * (cb6+cb7+cb10);
fb[2] = cb1 + cb3 - 1.5 * (cb4+cb5) + 3 * (cb8+cb9+cb10);
fb[4] = 2 * cb4 + 0.5 * (cb5-cb1);
fb[3] = 0.5 * (cb4-cb1) + 2 * cb5;
fb[6] = 0.5 * (cb1-cb4) - cb5 + cb6 + cb10;
fb[5] = 0.25 * (cb5-cb4) + cb7 + 0.5 * cb10;
fb[8] = 0.25 * (cb4-cb5) + cb8 + 0.5 * cb10;
fb[7] = 0.5 * (cb1-cb5) - cb4 + cb9 + cb10;

return;
}

if( v >= u && v <= 1-2*u )
{

//le point [u,v] est dans le sous triangle e2;
//=====================================;
// e1 = 1.0;
// e2 =-1.0;
// e3 = 0.0;
//les coordonnees barycentriques du point [u,v]
//du triangle rectangle unite permutees circulairement;
l1 = u;
l2 = v;
l3 = 1.0 - u - v;
//les produits des coordonnees barycentriques;
l1l1 = l1 * l1;
l2l2 = l2 * l2;
l3l3 = l3 * l3;

cb1 = l1l1 * l1;
cb2 = l2l2 * l2;
cb3 = l3l3 * l3;
cb4 = l1l1 * l3;
cb5 = l1l1 * l2;
cb6 = l2l2 * l1;
cb7 = l2l2 * l3;
cb8 = l3l3 * l2;
cb9 = l3l3 * l1;
cb10 = l1 * l2 * l3;

fb[1] = 0.5 * cb1 + 3 * cb4 + 4.5 * cb5;
fb[2] =-0.5 * cb1 + cb2 + 1.5 * cb5 + 3 * (cb6+cb7);
fb[0] = cb1 + cb3 + 3 * (cb8+cb9-cb5) + 6 * cb10;
fb[6] = 0.5 * (cb4+cb5);
fb[5] =-0.25 * cb1 + 0.5 * cb4 + 1.25 * cb5;
fb[8] = 0.25 * (cb1-cb5) - 0.5 * cb4 + cb6 + cb10;
fb[7] = 0.5 * (cb4-cb1) + cb5 + cb7 - cb10;
fb[4] = 0.5 * (cb1-cb4) - cb5 + cb8 + 2 * cb10;
fb[3] = 0.5 * (cb4-cb5) + cb9 + cb10;

return;
}

//le point [u,v] est dans le sous triangle e3;
//=====================================;
// e1 =-1.0;
// e2 = 0.0;
// e3 = 1.0;
//les coordonnees barycentriques du point [u,v]
//du triangle rectangle unite permutees circulairement;
l1 = v;
l2 = 1.0 - u - v;
l3 = u;
//les produits des coordonnees barycentriques;
l1l1 = l1 * l1;
l2l2 = l2 * l2;
l3l3 = l3 * l3;

cb1 = l1l1 * l1;
cb2 = l2l2 * l2;
cb3 = l3l3 * l3;
cb4 = l1l1 * l3;
cb5 = l1l1 * l2;
cb6 = l2l2 * l1;
cb7 = l2l2 * l3;
cb8 = l3l3 * l2;
cb9 = l3l3 * l1;
cb10 = l1 * l2 * l3;

fb[2] = 0.5 * cb1 + 4.5 * cb4 + 3 * cb5;
fb[0] = cb1 + cb2 + 3 * (cb6+cb7-cb4) + 6 * cb10;
fb[1] = -0.5 * cb1 + cb3 + 1.5 * cb4 + 3 * (cb8+cb9);
fb[8] = -0.25 * cb1 + 1.25 * cb4 + 0.5 * cb5;
fb[7] = 0.5 * (cb4+cb5);
fb[4] = 0.5 * (cb5-cb4) + cb6 + cb10;
fb[3] = 0.5 * (cb1-cb5) - cb4 + cb7 + 2 * cb10;
fb[6] = cb4 + 0.5 * (cb5-cb1) + cb8 - cb10;
fb[5] = 0.25 * (cb1-cb4) - 0.5 * cb5 + cb9 + cb10;

return;
}


void xyhct( R u, R v, R x[9], R y[9],
R & xhct, R & yhct )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur de l'interpolation au point [u,v]
// ----- du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 9 degres de liberte stockes dans x et y
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y : valeurs des 9 degres de liberte rangees selon k pour x et y
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//
// sorties:
// --------
// xhct : abscisse hct au point [u,v] du triangle rectangle unite
// yhct : ordonnee hct au point [u,v] du triangle rectangle unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R fb[9];

//valeur des 9 fonctions de base hct au point [u,v];
vfbhct( u, v, fb );

//les coordonnees x et y pour le point [u,v] de l'interpolation hct;
xhct = 0.0;
yhct = 0.0;
for (int i=0; i<9; i++)
{
xhct = xhct + fb[i] * x[i];
yhct = yhct + fb[i] * y[i];
}
return;
}


void xyzhct( R u, R v, R x[9], R y[9], R z[9],
R & xhct, R & yhct, R & zhct )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur de l'interpolation au point [u,v]
// ----- du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 9 degres de liberte stockes dans x y z
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ \
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entrees:
// --------
// u, v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 9 degres de liberte rangees selon k pour x, y, z
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//
// sorties:
// --------
// xhct : abscisse hct au point [u,v] du triangle rectangle unite
// yhct : ordonnee hct au point [u,v] du triangle rectangle unite
// zhct : cote hct au point [u,v] du triangle rectangle unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R fb[9];

//valeur des 9 fonctions de base hct au point [u,v];
vfbhct( u, v, fb );

//les coordonnees x et y pour le point [u,v] de l'interpolation hct;
xhct = 0.0;
yhct = 0.0;
zhct = 0.0;
for (int i=0; i<9; i++)
{
xhct = xhct + fb[i] * x[i];
yhct = yhct + fb[i] * y[i];
zhct = zhct + fb[i] * z[i];
}
return;
}


void dduhct( R u, R v, R ddufb[9] )
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur au point [u,v] de la derivee par rapport
// ----- au parametre u des 9 fontions de base de l'ef
// du triangle rectangle unite hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// cf article de m. bernardou et k.hassan [1981]
//
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// sortie :
// --------
// ddufb : la derivee par rapport a u des 9 fonctions de base
// du hct reduit rangees selon k
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris octobre 1996
//2345x7..........................................................012
{
R l1, l2, l3;
R cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9, cb10;

if( v*2 >= 1-u && v >= 1-2*u )
{
//le point [u,v] est dans le sous triangle e1;
//=====================================;
//les coordonnees barycentriques du point [u,v] du triangle rectangle unite;
l1 = 1.0 - u - v;
l2 = u;
l3 = v;

cb1 = -3 * l1 * l1;
cb2 = 3 * l2 * l2;
//cb3 = 0;
cb4 = -2 * l1 * l3;
cb5 =(-2 * l2 + l1 ) * l1;
cb6 =( 2 * l1 - l2 ) * l2;
cb7 = 2 * l2 * l3;
cb8 = l3 * l3;
cb9 = - l3 * l3;
cb10 =( l1 - l2 ) * l3;

ddufb[0] = -cb1 + 6 * (cb4 + cb5);
ddufb[1] = cb1 + cb2 - 1.5 * (cb4+cb5) + 3 * (cb6+cb7+cb10);
ddufb[2] = cb1 - 1.5 * (cb4+cb5) + 3 * (cb8+cb9+cb10);
ddufb[4] = 2 * cb4 + 0.5 * (cb5-cb1);
ddufb[3] = 0.5 * (cb4-cb1) + 2 * cb5;
ddufb[6] = 0.5 * (cb1-cb4) - cb5 + cb6 + cb10;
ddufb[5] = 0.25 * (cb5-cb4) + cb7 + 0.5 * cb10;
ddufb[8] = 0.25 * (cb4-cb5) + cb8 + 0.5 * cb10;
ddufb[7] = 0.5 * (cb1-cb5) - cb4 + cb9 + cb10;

return;
}

if( v >= u && v <= 1-2*u )
{

//le point [u,v] est dans le sous triangle e2
//=====================================
//les coordonnees barycentriques du point [u,v] du triangle
//rectangle unite permutees circulairement
l1 = u;
l2 = v;
l3 = 1.0 - u - v;

cb1 = 3 * l1 * l1;
//cb2 = 0;
cb3 = -3 * l3 * l3;
cb4 =( 2 * l3 - l1 ) * l1;
cb5 = 2 * l1 * l2;
cb6 = l2 * l2;
cb7 = - l2 * l2;
cb8 = -2 * l3 * l2;
cb9 =(-2 * l1 + l3 ) * l3;
cb10 =( l3 - l1 ) * l2;

ddufb[1] = 0.5 * cb1 + 3 * cb4 + 4.5 * cb5;
ddufb[2] =-0.5 * cb1 + 1.5 * cb5 + 3 * (cb6+cb7);
ddufb[0] = cb1 + cb3 + 3 * (cb8+cb9-cb5) + 6 * cb10;
ddufb[6] = 0.5 * (cb4+cb5);
ddufb[5] =-0.25 * cb1 + 0.5 * cb4 + 1.25 * cb5;
ddufb[8] = 0.25 * (cb1-cb5) - 0.5 * cb4 + cb6 + cb10;
ddufb[7] = 0.5 * (cb4-cb1) + cb5 + cb7 - cb10;
ddufb[4] = 0.5 * (cb1-cb4) - cb5 + cb8 + 2 * cb10;
ddufb[3] = 0.5 * (cb4-cb5) + cb9 + cb10;

return;
}

//le point [u,v] est dans le sous triangle e3
//=====================================
//les coordonnees barycentriques du point [u,v] du
//triangle rectangle unite permutees circulairement;
l1 = v;
l2 = 1.0 - u - v;
l3 = u;

//cb1 = 0;
cb2 = -3 * l2 * l2;
cb3 = 3 * l3 * l3;
cb4 = l1 * l1;
cb5 = - l1 * l1;
cb6 = -2 * l2 * l1;
cb7 =(-2 * l3 + l2 ) * l2;
cb8 =( 2 * l2 - l3 ) * l3;
cb9 = 2 * l3 * l1;
cb10 =( l2 - l3 ) * l1;

ddufb[2] = 4.5 * cb4 + 3 * cb5;
ddufb[0] = cb2 + 3 * (cb6+cb7-cb4) + 6 * cb10;
ddufb[1] = cb3 + 1.5 * cb4 + 3 * (cb8+cb9);
ddufb[8] = 1.25 * cb4 + 0.5 * cb5;
ddufb[7] = 0.5 * (cb4+cb5);
ddufb[4] = 0.5 * (cb5-cb4) + cb6 + cb10;
ddufb[3] = -0.5 * cb5 - cb4 + cb7 + 2 * cb10;
ddufb[6] = cb4 + 0.5 * cb5 + cb8 - cb10;
ddufb[5] = -0.25 * cb4 - 0.5 * cb5 + cb9 + cb10;

return;
}


void ddvhct( R u, R v, R ddvfb[9] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur au point [u,v] des 9 fontions de base de l'ef
// ----- du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
//
// sortie :
// --------
// ddvfb : la derivee par rapport a v des 9 fonctions de base
// du hct reduit rangees selon k
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris octobre 1996
//2345x7............................................012
{
R l1, l2, l3;
R cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9, cb10;

if( v*2 >= 1-u && v >= 1-2*u )
{

//le point [u,v] est dans le sous triangle e1;
//=====================================;
//les coordonnees barycentriques du point [u,v] du triangle rectangle unite;
l1 = 1.0 - u - v;
l2 = u;
l3 = v;

cb1 = -3 * l1 * l1;
//cb2 = 0;
cb3 = 3 * l3 * l3;
cb4 =(-2 * l3 + l1 ) * l1;
cb5 = -2 * l1 * l2;
cb6 = - l2 * l2;
cb7 = l2 * l2;
cb8 = 2 * l3 * l2;
cb9 =( 2 * l1 - l3 ) * l3;
cb10 =( l1 - l3 ) * l2;

ddvfb[0] = -cb1 + 6 * (cb4 + cb5);
ddvfb[1] = cb1 - 1.5 * (cb4+cb5) + 3 * (cb6+cb7+cb10);
ddvfb[2] = cb1 + cb3 - 1.5 * (cb4+cb5) + 3 * (cb8+cb9+cb10);
ddvfb[4] = 2 * cb4 + 0.5 * (cb5-cb1);
ddvfb[3] = 0.5 * (cb4-cb1) + 2 * cb5;
ddvfb[6] = 0.5 * (cb1-cb4) - cb5 + cb6 + cb10;
ddvfb[5] = 0.25 * (cb5-cb4) + cb7 + 0.5 * cb10;
ddvfb[8] = 0.25 * (cb4-cb5) + cb8 + 0.5 * cb10;
ddvfb[7] = 0.5 * (cb1-cb5) - cb4 + cb9 + cb10;

return;
}

if( v >= u && v <= 1-2*u )
{
//le point [u,v] est dans le sous triangle e2;
//=====================================;
//les coordonnees barycentriques du point [u,v] du
//triangle rectangle unite permutees circulairement
l1 = u;
l2 = v;
l3 = 1.0 - u - v;

//cb1 = 0;
cb2 = 3 * l2 * l2;
cb3 =-3 * l3 * l3;
cb4 =-l1 * l1;
cb5 = l1 * l1;
cb6 = 2 * l1 * l2;
cb7 =( 2 * l3 - l2 ) * l2;
cb8 =(-2 * l2 + l3 ) * l3;
cb9 = -2 * l3 * l1;
cb10 =( l3 - l2 ) * l1;

ddvfb[1] = 3 * cb4 + 4.5 * cb5;
ddvfb[2] = cb2 + 1.5 * cb5 + 3 * (cb6+cb7);
ddvfb[0] = cb3 + 3 * (cb8+cb9-cb5) + 6 * cb10;
ddvfb[6] = 0.5 * (cb4+cb5);
ddvfb[5] = 0.5 * cb4 + 1.25 * cb5;
ddvfb[8] =-0.25 * cb5 - 0.5 * cb4 + cb6 + cb10;
ddvfb[7] = 0.5 * cb4 + cb5 + cb7 - cb10;
ddvfb[4] =-0.5 * cb4 - cb5 + cb8 + 2 * cb10;
ddvfb[3] = 0.5 * (cb4-cb5) + cb9 + cb10;

return;
}

//le point [u,v] est dans le sous triangle e3;
//=====================================;
//les coordonnees barycentriques du point [u,v] du triangle rectangle unite;
//permutees circulairement;
l1 = v;
l2 = 1.0 - u - v;
l3 = u;

cb1 = 3 * l1 * l1;
cb2 = -3 * l2 * l2;
//cb3 = 0;
cb4 = 2 * l1 * l3;
cb5 =( 2 * l2 - l1 ) * l1;
cb6 =( l2 - 2 * l1 ) * l2;
cb7 = -2 * l2 * l3;
cb8 = -l3 * l3;
cb9 = l3 * l3;
cb10 =( l2 - l1 ) * l3;

ddvfb[2] = 0.5 * cb1 + 4.5 * cb4 + 3 * cb5;
ddvfb[0] = cb1 + cb2 + 3 * (cb6+cb7-cb4) + 6 * cb10;
ddvfb[1] = -0.5 * cb1 + 1.5 * cb4 + 3 * (cb8+cb9);
ddvfb[8] = -0.25 * cb1 + 1.25 * cb4 + 0.5 * cb5;
ddvfb[7] = 0.5 * (cb4+cb5);
ddvfb[4] = 0.5 * (cb5-cb4) + cb6 + cb10;
ddvfb[3] = 0.5 * (cb1-cb5) - cb4 + cb7 + 2 * cb10;
ddvfb[6] = cb4 + 0.5 * (cb5-cb1) + cb8 - cb10;
ddvfb[5] = 0.25 * (cb1-cb4) - 0.5 * cb5 + cb9 + cb10;

return;
}


void tguhct( R u, R v, R x[9], R y[9], R z[9],
R & tgxhct, R & tgyhct, R & tgzhct )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur des 3 composantes de la derivee en u
// ----- de l'interpolation au point [u,v]
// du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 9 degres de liberte stockes dans x y z
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entrees:
// --------
// u, v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 9 degres de liberte rangees selon k pour x, y, z
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//
// sorties:
// --------
// tgxhct : abscisse au point [u,v] de la tg
// tgyhct : ordonnee au point [u,v] de la tg
// tgzhct : cote au point [u,v] de la tg
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R derufb[9];

//valeur de la derivee selon u des 9 fonctions de base hct au point [u,v];
dduhct( u, v, derufb );

//les composantes de la tg selon u au point [u,v] de l'interpolation hct;
tgxhct = 0.0;
tgyhct = 0.0;
tgzhct = 0.0;
for (int i=0; i<9; i++)
{
tgxhct = tgxhct + derufb[i] * x[i];
tgyhct = tgyhct + derufb[i] * y[i];
tgzhct = tgzhct + derufb[i] * z[i];
}
return;
}

 

void tgvhct( R u, R v, R x[9], R y[9], R z[9],
R & tgxhct, R & tgyhct, R & tgzhct )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur des 3 composantes de la derivee en v
// ----- de l'interpolation au point [u,v]
// du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 9 degres de liberte stockes dans x y z
// cf article de m. bernardou et k.hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entrees:
// --------
// u, v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 9 degres de liberte rangees selon k pour x, y, z
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//
// sorties:
// --------
// tgxhct : abscisse au point [u,v] de la tg
// tgyhct : ordonnee au point [u,v] de la tg
// tgzhct : cote au point [u,v] de la tg
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R dervfb[9];

//valeur de la derivee selon v des 9 fonctions de base hct au point [u,v];
ddvhct( u, v, dervfb );

//les composantes de la tg selon v au point [u,v] de l'interpolation hct;
tgxhct = 0.0;
tgyhct = 0.0;
tgzhct = 0.0;
for (int i=0; i<9; i++)
{
tgxhct = tgxhct + dervfb[i] * x[i];
tgyhct = tgyhct + dervfb[i] * y[i];
tgzhct = tgzhct + dervfb[i] * z[i];
}
return;
}


void norhct( R u, R v, R x[9], R y[9], R z[9],
R3 & normale, int & ierr )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;
// but : calculer la valeur au point [u,v] des 3 composantes de la normale
// ----- orthogonale aux 2 tangentes en u et v de l'interpolation
// du triangle rectangle unite Hsieh-Clough-Tocher reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 9 degres de liberte stockes dans x y z
// cf article de M. Bernardou et K.Hassan [1981]
// ^
// | v
// |
// s3=[0,1]
// x
// | \ \
// | \ ^
// - \ \
// | \ \
// | \ \
// | e2 \ \
// | \ e1 \
// ^ / \ ^
// | / \ \
// | / e3 \ \
// x----->------------<-----x ----> u
// s1=[0,0] s2=[1,0]
//
// entrees:
// --------
// u, v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 9 degres de liberte rangees selon k pour x, y, z
// k=1 f[s1], k=2 f[s2], k=3 f[s3],
// k=4 df[s1][s2-s1], k=5 df[s1][s3-s1],
// k=6 df[s2][s3-s2], k=7 df[s2][s1-s2],
// k=8 df[s3][s1-s3], k=9 df[s3][s2-s3]
//
// sorties:
// --------
// normale: 3 composantes de la normale unitaire au point [u,v]
// ierr : 1 si les 2 tangentes sont colinaires
// 0 si pas d'erreur
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R3 tgu, tgv;
R s;

//les 3 composantes de la tg en u
tguhct( u, v, x, y, z, tgu[0], tgu[1], tgu[2] );

//les 3 composantes de la tg en v
tgvhct( u, v, x, y, z, tgv[0], tgv[1], tgv[2] );

//les 3 composantes de la normale unitaire
normale = tgu ^ tgv;

//la norme du vecteur normal
s = Norme2( normale );
if( s <= 0 )
{
//erreur: 2 tangentes colineaires;
ierr = 1;
}
else
{
ierr = 0;
normale = normale / s; //normale a pour norme 1
}
}

void pecm4r( R x[4] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : permuter circulairement les valeurs 0 1 2 3 => 1 2 3 0
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R u;

u = x[0];
x[0] = x[3];
x[3] = x[2];
x[2] = x[1];
x[1] = u;
}

void peci4r( R x[4] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : permuter circulairement les valeurs 0 1 2 3 => 3 0 1 2
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R u;

u = x[0];
x[0] = x[1];
x[1] = x[2];
x[2] = x[3];
x[3] = u;
}

void pe4inv( R x[4] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : INVERSER L'ORDRE 1 2 3 4 EN 1 4 3 2 DES 4 VALEURS DU TABLEAU
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[1];
x[1] = x[3];
x[3] = u;
}

void pec24r( R x[4] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Permuter circulairement les valeurs 0<->2 1<->3
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R u;

u = x[0];
x[0] = x[2];
x[2] = u;

u = x[1];
x[1] = x[3];
x[3] = u;
}

void peci44( R x[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : le sommet 1 du quadrangle dvs devient le sommet 0
// ----- et dans le sens direct les permutations des sommets
// et tangentes croisees suivent
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[0];
x[0] = x[1];
x[1] = x[2];
x[2] = x[3];
x[3] = u;

u = x[ 4];
x[ 4] = x[ 6];
x[ 6] = x[ 8];
x[ 8] = x[10];
x[10] = u;

u = x[ 5];
x[ 5] = x[ 7];
x[ 7] = x[ 9];
x[ 9] = x[11];
x[11] = u;
}


void pec244( R x[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : le sommet 2 du quadrangle dvs devient le sommet 0
// ----- et dans le sens direct les permutations des sommets
// et tangentes croisees suivent
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[0];
x[0] = x[2];
x[2] = u;

u = x[1];
x[1] = x[3];
x[3] = u;

u = x[ 4];
x[ 4] = x[ 8];
x[ 8] = u;

u = x[ 5];
x[ 5] = x[ 9];
x[ 9] = u;

u = x[ 6];
x[ 6] = x[10];
x[10] = u;

u = x[ 7];
x[ 7] = x[11];
x[11] = u;
}


void pe44in( R x[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : INVERSER L'ORDRE 1 2 3 4 EN 1 4 3 2 DES 4 SOMMETS ET TANGENTES
// du quadrangle DVS
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[1];
x[1] = x[3];
x[3] = u;

u = x[4];
x[4] = x[5];
x[5] = u;

u = x[ 6];
x[ 6] = x[11];
x[11] = u;

u = x[ 7];
x[ 7] = x[10];
x[10] = u;

u = x[ 8];
x[ 8] = x[ 9];
x[ 9] = u;
}

void pecm44( R x[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : le sommet 3 du quadrangle dvs devient le sommet 0
// ----- et dans le sens direct les permutations des sommets
// et tangentes croisees suivent
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain upmc analyse numerique paris octobre 1996
//2345x7..........................................................012
{
R u;

u = x[0];
x[0] = x[3];
x[3] = x[2];
x[2] = x[1];
x[1] = u;

u = x[ 4];
x[ 4] = x[10];
x[10] = x[ 8];
x[ 8] = x[ 6];
x[ 6] = u;

u = x[ 5];
x[ 5] = x[11];
x[11] = x[ 9];
x[ 9] = x[ 7];
x[ 7] = u;
}


void ddudvs( R u, R v, R dudvsr[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur au point [u,v] du carre unite de la derivee
// ----- par rapport au parametre u des 12 fonctions de base de
// l'interpolation c1 de Fraeijs de veubeke Sander reduite
// [derivee normale p1 sur les 4 cotes]
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
//
// entrees:
// --------
// u,v : valeurs des 2 parametres sur le carre unite [ 0<u,v<1 ]
//
// sorties:
// --------
// dudvsr : valeur au point [u,v] des 12 fonctions de base selon l'ordre k
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris octobre 1996
//2345x7..........................................................012
{
R uu, uv, vv;

uu = u * u;
uv = u * v;
vv = v * v;

// calcul de p1
dudvsr[ 0] = - 6 * u + 6 * uu + 3 * vv;
dudvsr[ 1] = 6 * u - 6 * uu - 3 * vv;
dudvsr[ 2] = 3 * vv;
dudvsr[ 3] = - 3 * vv;
dudvsr[ 4] = 1 - 4 * u + 3 * uu + 0.5 * vv;
dudvsr[ 5] = - v + vv;
dudvsr[ 6] = v - vv;
dudvsr[ 7] = 2 * u - 3 * uu - 0.5 * vv;
dudvsr[ 8] = 0.5 * vv;
dudvsr[ 9] = vv;
dudvsr[10] = - vv;
dudvsr[11] = - 0.5 * vv;

if( v > 1.-u )
{
// calcul de p2
dudvsr[ 0] = dudvsr[ 0] - 3 + 6 * v + 6 * u - 6 * uv - 3 * vv - 3 * uu;
dudvsr[ 1] = dudvsr[ 1] + 3 - 6 * v - 6 * u + 6 * uv + 3 * vv + 3 * uu;
dudvsr[ 2] = dudvsr[ 2] - 3 + 6 * v + 6 * u - 6 * uv - 3 * vv - 3 * uu;
dudvsr[ 3] = dudvsr[ 3] + 3 - 6 * v - 6 * u + 6 * uv + 3 * vv + 3 * uu;
dudvsr[ 4] = dudvsr[ 4] -1.5 + 2 * v + 3 * u - 2 * uv -0.5 * vv -1.5 * uu;
dudvsr[ 5] = dudvsr[ 5] - 1 + 2 * v + u - uv - vv;
dudvsr[ 6] = dudvsr[ 6] + 1 - 2 * v - u + uv + vv;
dudvsr[ 7] = dudvsr[ 7] +0.5 - v - 2 * u + 2 * uv +0.5 * vv +1.5 * uu;
dudvsr[ 8] = dudvsr[ 8] -0.5 + v + 2 * u - 2 * uv -0.5 * vv -1.5 * uu;
dudvsr[ 9] = dudvsr[ 9] + v - uv - vv;
dudvsr[10] = dudvsr[10] - v + uv + vv;
dudvsr[11] = dudvsr[11] +1.5 - 2 * v - 3 * u + 2 * uv +0.5 * vv +1.5 * uu;
}

if( v > u )
{
dudvsr[ 0] = dudvsr[ 0] + 6 * uv - 3 * vv - 3 * uu;
dudvsr[ 1] = dudvsr[ 1] - 6 * uv + 3 * vv + 3 * uu;
dudvsr[ 2] = dudvsr[ 2] + 6 * uv - 3 * vv - 3 * uu;
dudvsr[ 3] = dudvsr[ 3] - 6 * uv + 3 * vv + 3 * uu;
dudvsr[ 4] = dudvsr[ 4] - v + u + 2 * uv -0.5 * vv -1.5 * uu;
dudvsr[ 5] = dudvsr[ 5] + v - u + uv - vv;
dudvsr[ 6] = dudvsr[ 6] - v + u - uv + vv;
dudvsr[ 7] = dudvsr[ 7] - 2 * uv +0.5 * vv +1.5 * uu;
dudvsr[ 8] = dudvsr[ 8] + 2 * uv -0.5 * vv -1.5 * uu;
dudvsr[ 9] = dudvsr[ 9] + uv - vv;
dudvsr[10] = dudvsr[10] - uv + vv;
dudvsr[11] = dudvsr[11] + v - u- 2 * uv +0.5 * vv +1.5 * uu;
}
}


void ddvdvs( R u, R v, R dvdvsr[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur au point [u,v] du carre unite de la derivee
// ----- par rapport au parametre v des 12 fonctions de base de
// l'interpolation c1 de Fraeijs de Veubeke Sander reduite
// [derivee normale p1 sur les 4 cotes]
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0];
// entrees:
// --------
// u,v : valeurs des 2 parametres sur le carre unite [ 0<u,v<1 ]
// sorties:
// --------
// dvdvsr : valeur au point [u,v] des 12 fonctions de base selon l'ordre k
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris octobre 1996
//2345x7..........................................................012
{
R uu, uv, vv;

uu = u * u;
uv = u * v;
vv = v * v;

dvdvsr[ 0] = -6 * v + 6 * uv + 3 * vv;
dvdvsr[ 1] = - 6 * uv + 3 * vv;
dvdvsr[ 2] = 6 * uv - 3 * vv;
dvdvsr[ 3] = 6 * v - 6 * uv - 3 * vv;
dvdvsr[ 4] = - v + uv;
dvdvsr[ 5] = 1 - u -3 * v + 2 * uv + 1.5 * vv;
dvdvsr[ 6] = u - v - 2 * uv+1.5 * vv;
dvdvsr[ 7] = - uv;
dvdvsr[ 8] = uv;
dvdvsr[ 9] = 2 * uv -1.5 * vv;
dvdvsr[10] = 2 * v - 2 * uv -1.5 * vv;
dvdvsr[11] = v - uv;

if( v > 1.-u )
{
// calcul de p2;
dvdvsr[ 0] = dvdvsr[ 0] -3 + 6 * u + 6 * v - 3 * uu - 6 * uv - 3 * vv;
dvdvsr[ 1] = dvdvsr[ 1] +3 - 6 * u - 6 * v + 3 * uu + 6 * uv + 3 * vv;
dvdvsr[ 2] = dvdvsr[ 2] -3 + 6 * u + 6 * v - 3 * uu - 6 * uv - 3 * vv;
dvdvsr[ 3] = dvdvsr[ 3] +3 - 6 * u - 6 * v + 3 * uu + 6 * uv + 3 * vv;
dvdvsr[ 4] = dvdvsr[ 4] -1 + 2 * u + v - uu - uv;
dvdvsr[ 5] = dvdvsr[ 5]-1.5+ 2 * u + 3 * v -0.5* uu - 2 * uv -1.5* vv;
dvdvsr[ 6] = dvdvsr[ 6]+1.5 -2 * u - 3 * v +0.5* uu + 2 * uv +1.5* vv;
dvdvsr[ 7] = dvdvsr[ 7] - u + uu + uv;
dvdvsr[ 8] = dvdvsr[ 8] + u - uu - uv;
dvdvsr[ 9] = dvdvsr[ 9]-0.5 + u + 2 * v -0.5* uu - 2 * uv -1.5* vv;
dvdvsr[10] = dvdvsr[10]+0.5 - u - 2 * v +0.5* uu+ 2 * uv +1.5* vv;
dvdvsr[11] = dvdvsr[11] +1 -2 * u - v + uu+ uv;
}

if( v > u )
{
dvdvsr[ 0] = dvdvsr[ 0] +3 * uu - 6 * uv +3 * vv;
dvdvsr[ 1] = dvdvsr[ 1] -3 * uu + 6 * uv -3 * vv;
dvdvsr[ 2] = dvdvsr[ 2] +3 * uu - 6 * uv +3 * vv;
dvdvsr[ 3] = dvdvsr[ 3] -3 * uu + 6 * uv -3 * vv;
dvdvsr[ 4] = dvdvsr[ 4] - u + v + uu - uv;
dvdvsr[ 5] = dvdvsr[ 5] + u - v +0.5 * uu - 2 * uv +1.5 * vv;
dvdvsr[ 6] = dvdvsr[ 6] - u + v -0.5 * uu + 2 * uv -1.5 * vv;
dvdvsr[ 7] = dvdvsr[ 7] - uu + uv;
dvdvsr[ 8] = dvdvsr[ 8] + uu - uv;
dvdvsr[ 9] = dvdvsr[ 9] +0.5 * uu - 2 * uv +1.5 * vv;
dvdvsr[10] = dvdvsr[10] -0.5 * uu + 2 * uv -1.5 * vv;
dvdvsr[11] = dvdvsr[11] + u - v - uu + uv;
}
}


void tgudvs( R u, R v, R x[12], R y[12], R z[12],
R & xtgdvs, R & ytgdvs, R & ztgdvs )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur de la derivee en u de l'interpolation
// ----- au point [u,v] du carre unite de Fraeijs de Veubeke Sander reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 12 degres de liberte stockes dans x y z
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 12 degres de liberte rangees selon k pour x y z
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
// sorties:
// --------
// xtgdvs : abscisse de la tg selon u au point [u,v] du carre unite
// ytgdvs : ordonnee de la tg selon u au point [u,v] du carre unite
// ztgdvs : cote de la tg selon u au point [u,v] du carre unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R derufb[12];

//valeur des 12 fonctions de base dvs au point [u,v]
ddudvs( u, v, derufb );

//les coordonnees x y z pour le point [u,v] de l'interpolation dvs
xtgdvs = 0.0;
ytgdvs = 0.0;
ztgdvs = 0.0;
for (int i=0; i<12; i++)
{
xtgdvs = xtgdvs + derufb[i] * x[i];
ytgdvs = ytgdvs + derufb[i] * y[i];
ztgdvs = ztgdvs + derufb[i] * z[i];
}
}


void tgvdvs( R u, R v, R x[12], R y[12], R z[12],
R & xtgdvs, R & ytgdvs, R & ztgdvs )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;
// but : calculer la valeur de la derivee en v de l'interpolation
// ----- au point [u,v] du carre unite de Fraeijs de Veubeke Sander reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 12 degres de liberte stockes dans x y z
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 12 degres de liberte rangees selon k pour x y z
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
// sorties:
// --------
// xtgdvs : abscisse de la tg selon v au point [u,v] du carre unite
// ytgdvs : ordonnee de la tg selon v au point [u,v] du carre unite
// ztgdvs : cote de la tg selon v au point [u,v] du carre unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R derufb[12];

//valeur des 12 fonctions de base dvs au point [u,v];
ddvdvs( u, v, derufb );

//les coordonnees x y z pour le point [u,v] de l'interpolation dvs
xtgdvs = 0.0;
ytgdvs = 0.0;
ztgdvs = 0.0;
for (int i=0; i<12; i++)
{
xtgdvs = xtgdvs + derufb[i] * x[i];
ytgdvs = ytgdvs + derufb[i] * y[i];
ztgdvs = ztgdvs + derufb[i] * z[i];
}
}


void vfbdvs( R u, R v, R fbdvsr[12] )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;
// but : calculer la valeur au point [u,v] du carre unite des
// ----- 12 fonctions de base de l'interpolation c1 de
// Fraeijs de Veubeke Sander reduite
// [derivee normale p1 sur les 4 cotes]
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entrees:
// --------
// u,v : valeurs des 2 parametres sur le carre unite [ 0<u,v<1 ]
// sorties:
// --------
// fbdvsr : valeur au point [u,v] des 12 fonctions de base selon l'ordre k
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R uu, uv, vv, uuu, vvv, uvv, uuv;

uv = u * v;
uu = u * u;
vv = v * v;

uuu = u * uu;
vvv = v * vv;
uvv = u * vv;
uuv = uu * v;

// calcul de p1
fbdvsr[ 0] = 1-3*uu-3*vv+3*uvv+2*uuu+vvv;
fbdvsr[ 1] = 3*uu-3*uvv-2*uuu+vvv;
fbdvsr[ 2] = 3*uvv-vvv;
fbdvsr[ 3] = 3*vv-3*uvv-vvv;
fbdvsr[ 4] = u-2*uu-0.5*vv+0.5*uvv+uuu;
fbdvsr[ 5] = v-uv-1.5*vv+uvv+0.5*vvv;
fbdvsr[ 6] = uv-0.5*vv-uvv+0.5*vvv;
fbdvsr[ 7] = uu-0.5*uvv-uuu;
fbdvsr[ 8] = 0.5*uvv;
fbdvsr[ 9] = uvv-0.5*vvv;
fbdvsr[10] = vv-uvv-0.5*vvv;
fbdvsr[11] = 0.5*vv-0.5*uvv;

if( v > 1.0-u )
{
// calcul de p2
fbdvsr[ 0] = fbdvsr[ 0]+1 -3 * u-3 * v+6 * uv+ 3 * uu+3 * vv-3 * uuv- 3 * uvv- uuu- vvv;
fbdvsr[ 1] = fbdvsr[ 1]-1 +3 * u+3 * v-6 * uv- 3 * uu-3 * vv+3 * uuv+ 3 * uvv+ uuu+ vvv;
fbdvsr[ 2] = fbdvsr[ 2]+1 -3 * u-3 * v+6 * uv+ 3 * uu+3 * vv-3 * uuv- 3 * uvv- uuu- vvv;
fbdvsr[ 3] = fbdvsr[ 3]-1 +3 * u+3 * v-6 * uv- 3 * uu-3 * vv+3 * uuv+ 3 * uvv+ uuu+ vvv;

fbdvsr[ 4] = fbdvsr[ 4]+0.5-1.5*u- v+2 * uv+1.5* uu+0.5*vv - uuv-0.5* uvv-0.5*uuu;
fbdvsr[ 5] = fbdvsr[ 5]+0.5- u-1.5*v+2 * uv+0.5 * uu+1.5 * vv-0.5 * uuv - uvv-0.5 * vvv;
fbdvsr[ 6] = fbdvsr[ 6]-0.5+ u+1.5*v-2 * uv-0.5 * uu-1.5 * vv+0.5 * uuv+ uvv+0.5 * vvv;

fbdvsr[ 7] = fbdvsr[ 7] +0.5 * u - uv- uu + uuv+0.5 * uvv+0.5* uuu;
fbdvsr[ 8] = fbdvsr[ 8] -0.5 * u + uv+ uu - uuv-0.5 * uvv-0.5 * uuu;
fbdvsr[ 9] = fbdvsr[ 9] -0.5 * v+ uv+ vv-0.5 * uuv-uvv-0.5 * vvv;
fbdvsr[10] = fbdvsr[10] +0.5 * v- uv- vv+0.5 * uuv+uvv+0.5 * vvv;
fbdvsr[11] = fbdvsr[11]-0.5+1.5 * u+ v-2 * uv-1.5 * uu-0.5 * vv+ uuv+0.5 * uvv+0.5 * uuu;
}

if( v > u )
{
// calcul de p3
fbdvsr[ 0] = fbdvsr[ 0]+3 * uuv-3 * uvv- uuu+ vvv;
fbdvsr[ 1] = fbdvsr[ 1]-3 * uuv+3 * uvv+ uuu- vvv;
fbdvsr[ 2] = fbdvsr[ 2]+3 * uuv-3 * uvv- uuu+ vvv;
fbdvsr[ 3] = fbdvsr[ 3]-3 * uuv+3 * uvv+ uuu- vvv;
fbdvsr[ 4] = fbdvsr[ 4]- uv+0.5 * uu+0.5 * vv+ uuv-0.5 * uvv-0.5 * uuu;
fbdvsr[ 5] = fbdvsr[ 5]+ uv-0.5 * uu-0.5 * vv+0.5 * uuv- uvv+0.5 * vvv;
fbdvsr[ 6] = fbdvsr[ 6]- uv+0.5 * uu+0.5 * vv-0.5 * uuv+ uvv-0.5 * vvv;
fbdvsr[ 7] = fbdvsr[ 7]- uuv+0.5 * uvv+0.5 * uuu;
fbdvsr[ 8] = fbdvsr[ 8]+ uuv-0.5 * uvv-0.5 * uuu;
fbdvsr[ 9] = fbdvsr[ 9]+0.5 * uuv- uvv+0.5 * vvv;
fbdvsr[10] = fbdvsr[10]-0.5 * uuv+ uvv-0.5 * vvv;
fbdvsr[11] = fbdvsr[11]+ uv-0.5 * uu-0.5 * vv- uuv+0.5 * uvv+0.5 * uuu;
}
}


void xydvs( R u, R v, R x[12], R y[12],
R & xdvs, R & ydvs )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur de l'interpolation au point [u,v]
// ----- du carre unite de Fraeijs de Veubeke Sander reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 12 degres de liberte stockes dans x y z
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y: valeurs des 12 degres de liberte rangees selon k pour x y
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
// sorties:
// --------
// xdvs : abscisse dvs au point [u,v] du carre unite
// ydvs : ordonnee dvs au point [u,v] du carre unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R fb[12];

//valeur des 12 fonctions de base dvs au point [u,v];
vfbdvs( u, v, fb );

//les coordonnees x y z pour le point [u,v] de l'interpolation dvs;
xdvs = 0.0;
ydvs = 0.0;
for (int i=0; i<12; i++)
{
xdvs = xdvs + fb[i] * x[i];
ydvs = ydvs + fb[i] * y[i];
}
}


void xyzdvs( R u, R v, R x[12], R y[12], R z[12],
R & xdvs, R & ydvs, R & zdvs )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer la valeur de l'interpolation au point [u,v]
// ----- du carre unite de Fraeijs de Veubeke Sander reduit
// [reduit => derivee normale p1 sur les 3 cotes]
// et pour les 12 degres de liberte stockes dans x y z
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entree :
// --------
// u,v : valeurs des 2 parametres sur le triangle rectangle unite
// [ 0=<u,v<=1 et v<=1-u ]
// x, y, z: valeurs des 12 degres de liberte rangees selon k pour x y z
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
// sorties:
// --------
// xdvs : abscisse dvs au point [u,v] du carre unite
// ydvs : ordonnee dvs au point [u,v] du carre unite
// zdvs : cote dvs au point [u,v] du carre unite
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris mai 1996
//2345x7..........................................................012
{
R fb[12];

//valeur des 12 fonctions de base dvs au point [u,v];
vfbdvs( u, v, fb );

//les coordonnees x y z pour le point [u,v] de l'interpolation dvs;
xdvs = 0.0;
ydvs = 0.0;
zdvs = 0.0;
for (int i=0; i<12; i++)
{
xdvs = xdvs + fb[i] * x[i];
ydvs = ydvs + fb[i] * y[i];
zdvs = zdvs + fb[i] * z[i];
}
}


void nordvs( R u, R v, R x[12], R y[12], R z[12],
R3 & normale, int ierr )
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++;
// but : calculer le vecteur normal unitaire au point [u,v] du carre unite
// ----- de l'interpolation c1 de Fraeijs de Veubeke Sander reduite
// [derivee normale p1 sur les 4 cotes]
// ^ v
// |
// |
// |
// s4=[0,1] s3=[1,1]
// x----->------------<---x
// | \ p1+p2+p3 / |
// | \ / |
// - \ / -
// | \ / |
// | \ / |
// | p1+p3 / \ p1+p2 |
// | / \ |
// ^ / \ ^
// | / \ |
// | / p1 \|
// x----->----------<-----x ------------> u
// s1=[0,0] s2=[1,0]
// entrees:
// --------
// u,v : valeurs des 2 parametres sur le carre unite [ 0<u,v<1 ]
// x, y, z: valeurs des 12 degres de liberte rangees selon k pour x y z
// k=1 f[s1], k=2 f[s2], k=3 f[s3], k=4 f[s4],
// k=5 df[s1][s2-s1], k=6 df[s1][s4-s1], k=7 df[s2][s3-s2], k=8 df[s2][s1-s2],
// k=9 df[s3][s4-s3], k=10 df[s3][s2-s3], k=11 df[s4][s1-s4], k=12 df[s4][s3-s4]
// sorties:
// --------
// normale: 3 composantes de la normale unitaire au point [u,v]
// ierr : 1 si les 2 tangentes sont colinaires
// 0 si pas d'erreur
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique upmc paris aout 1998
//2345x7..........................................................012
{
R s;
R3 tgu, tgv;

//les 3 composantes de la tg en u
tgudvs( u, v, x, y, z, tgu[0], tgu[1], tgu[2] );

//les 3 composantes de la tg en v
tgvdvs( u, v, x, y, z, tgv[0], tgv[1], tgv[2] );

//les 3 composantes de la normale unitaire
normale = tgu ^ tgv;

//la norme du vecteur normal
s = Norme2( normale );
if( s <= 0 )
{
//erreur: 2 tangentes colineaires;
ierr = 1;
}
else
{
ierr = 0;
normale = normale / s; //normale a pour norme 1
}
}

int IntersectionDroiteHexaedre( R3 PtMin, R3 PtMax, R3 & pt0, R3 & pt1 )
//Retourner 0 si pas d'intersection entre la droite pt0-pt1 et l'hexaedre PtMin-PtMax
// 1 et les coordonnees dans pt0 pt1 des points d'intersection de la droite
// avec l'hexaedre PtMin-PtMax
{
R a;
int i;

for (i=0; i<3; i++)
{
//le point de coordonnee i minimale est toujours le point pt0
if( pt0[i] > pt1[i] ) Echange( pt0, pt1 );

if( pt1[i] < PtMin[i] || pt0[i] > PtMax[i] ) return 0; // 0 intersection

//intersection avec le plan Xi=PtMin[i]
if( pt1[i] != pt0[i] )
{
a = ( PtMin[i] - pt0[i] ) / ( pt1[i] - pt0[i] ); //le coefficient du vecteur pt1-pt0
if( 0<a && a<=1 ) pt0 = pt0 + a * (pt1 - pt0); //le nouveau point sur la droite
}

//intersection avec le plan Xi=PtMax[i]
if( pt1[i] != pt0[i] )
{
a = ( PtMax[i] - pt0[i] ) / ( pt1[i] - pt0[i] ); //le coefficient du vecteur pt1-pt0
if( 0<=a && a<1 ) pt1 = pt0 + a * (pt1 - pt0); //le nouveau point sur la droite
}
}
return 1; //Pt d'intersection calcule
}


int Point3Axe3( R3 p1, R3 p2, R3 p3, R3 axe[3] )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : a partir de 3 points former les axes orthonormes tels que
// ----- axe( . , 1 ) = p1p2 / norme( p1p2 )
// axe( . , 3 ) = axe( . , 1 ) produit vectoriel p1p3 / norme(p1p3)
// axe( . , 2 ) = axe( . , 3 ) produit vectoriel axe( . , 1 )
// retourner 1 si les 3 points sont alignes ou confondus, 0 sinon
//
// entrees:
// --------
// p1 p2 p3 : les 3 points
//
// sorties:
// --------
// axe : axe[i][j]=j-eme coordonnee du i-eme axe orthonorme
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique paris upmc avril 2001
// ..................................................................
{
int i;

axe[0] = p2 - p1;
if( NormeA1( axe[0] ) == 0 ) return 1; //normalisation du vecteur a 1

axe[1] = p3 - p1;
ProduitVectoriel( axe[0], axe[1], axe[2] );
if( NormeA1( axe[2] ) == 0 ) return 1;

ProduitVectoriel( axe[2], axe[0], axe[1] );
if( NormeA1( axe[1] ) == 0 ) return 1;

return 0;
}

int NormeA1( R3 & v )
//Rendre la norme du vecteur egale a 1 sauf si le vecteur est nul
//Retourner 1 si le vecteur est normalise a 1
// 0 si le vecteur est nul
{ R s;

s = Norme2( v ); //la norme du vecteur
if( s>0 )
{
v = v / s; //la normalisation a 1
return 1;
}
else
return 0;
}

void ScgScu( R3 SCU[], R3 xyzscg, R3 & xyzscu )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du point dans le SCU
// ----- a partir des 3 coordonnees du point dans le SCG
// translation des origines faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// xyzscg : les 3 coordonnees du point dans le repere SCG
//
// sortie :
// --------
// xyzscu : les 3 coordonnees du point dans le repere SCU
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x, y, z; // protection pour appel avec xyzscg = xyzscu

x = xyzscg.x - SCU[0].x;
y = xyzscg.y - SCU[0].y;
z = xyzscg.z - SCU[0].z;

xyzscu.x = SCU[1].x * x + SCU[1].y * y + SCU[1].z * z;
xyzscu.y = SCU[2].x * x + SCU[2].y * y + SCU[2].z * z;
xyzscu.z = SCU[3].x * x + SCU[3].y * y + SCU[3].z * z;
}

void ScuScg( R3 SCU[], R3 xyzscu, R3 & xyzscg )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du xyzecteur dans le SCG
// ----- a partir des 3 coordonnees du xyzecteur dans le SCU
// translation des origines faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// xyzscu : les 3 coordonnees du point dans le repere SCU
//
// sortie :
// --------
// xyzscg : les 3 coordonnees du point dans le repere SCG
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x,y,z; // protection pour appel avec xyzscu = xyzscg

x = xyzscu[0];
y = xyzscu[1];
z = xyzscu[2];

xyzscg.x = SCU[1].x * x + SCU[2].x * y + SCU[3].x * z + SCU[0].x;
xyzscg.y = SCU[1].y * x + SCU[2].y * y + SCU[3].y * z + SCU[0].y;
xyzscg.z = SCU[1].z * x + SCU[2].z * y + SCU[3].z * z + SCU[0].z;
}

void VecteurScgScu( R3 SCU[], R3 vscg, R3 & vscu )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du vecteur dans le SCU
// ----- a partir des 3 coordonnees du vecteur dans le SCG
// translation des origines non faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// vscg : les 3 coordonnees du vecteur dans le repere SCG
//
// sortie :
// --------
// vscu : les 3 coordonnees du vecteur dans le repere SCU
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x, y, z; // protection pour appel avec vscg = vscu

x = vscg.x; // - SCU[0].x;
y = vscg.y; // - SCU[0].y;
z = vscg.z; // - SCU[0].z;

vscu.x = SCU[1].x * x + SCU[1].y * y + SCU[1].z * z;
vscu.y = SCU[2].x * x + SCU[2].y * y + SCU[2].z * z;
vscu.z = SCU[3].x * x + SCU[3].y * y + SCU[3].z * z;
}

void VecteurScuScg( R3 SCU[], R3 vscu, R3 & vscg )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du vecteur dans le SCG
// ----- a partir des 3 coordonnees du vecteur dans le SCU
// translation des origines non faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// vscu : les 3 coordonnees du vecteur dans le repere SCU
//
// sortie :
// --------
// vscg : les 3 coordonnees du vecteur dans le repere SCG
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x,y,z; // protection pour appel avec vscu = vscg

x = vscu[0];
y = vscu[1];
z = vscu[2];

vscg.x = SCU[1].x * x + SCU[2].x * y + SCU[3].x * z; // + SCU[0].x; pour Pt
vscg.y = SCU[1].y * x + SCU[2].y * y + SCU[3].y * z; // + SCU[0].y;
vscg.z = SCU[1].z * x + SCU[2].z * y + SCU[3].z * z; // + SCU[0].z;
}

 

 

 

 

 


/*
void dedvsr( R3 xyzs[], R3 xyzt[], int nosoel[12],
R u, R v, R direcu, R direcv,
R3 derive )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer les 3 coordonnees de la derivee dvsr[u,v][direcu,direcv]
// ----- sur le quadrangle de sommets et tangentes de numeros dans nosoel
// entrees:
// --------
// mnxyzs : adresse mcn de la premiere coordonnee du premier sommet
// mnxyzt : adresse mcn de la premiere coordonnee de la premiere tg
// nosoel : numero des 4 sommets et des 8 tangentes de l'ef
// quadrangle: no sommet1, ns2 , ns3, ns4,
// no tangente1[s1s2], nt2[s1s3], nt3[s2s3], nt4[s2s1],
// no tangente5[s3s4], nt6[s3s2], nt7[s4s1], nt8[s4s3]
// ce choix permet une boucle sur les tangentes par les sommets
// u,v : valeur des 2 parametres dans [0,1] de l'ef de Veubeke Sander reduit
// direcu : abscisse de la direction de la derivee a calculer
// direcv : ordonnee de la direction de la derivee a calculer
// sorties:
// --------
// derive : les 3 composantes de la derivee dvsr[u,v][direcu,direcv]
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain analyse numerique upmc paris novembre 1996
//2345x...........................................................012
{
R xu, xv, yu, yv, zu, zv;

//calcul des 3 coordonnees des sommets et tangentes de cet ef dvsr;
xyzstg[ mnxyzs-3, mnxyzt-3, 4, nosoel, 1,;
% x, y, z ];

//calcul de la derivee / u au point [u,v] des fonctions de base;
ddudvs[ u,v, dudvsr ];

//calcul de la derivee / v au point [u,v] des fonctions de base;
ddvdvs[ u,v, dvdvsr ];

//calcul de la derivee dvsr[u,v][direcu,direcv];
xu = 0;
xv = 0;
yu = 0;
yv = 0;
zu = 0;
zv = 0;
do 10 i=1,12;
xu = xu + dudvsr[i] * x[i];
xv = xv + dvdvsr[i] * x[i];
yu = yu + dudvsr[i] * y[i];
yv = yv + dvdvsr[i] * y[i];
zu = zu + dudvsr[i] * z[i];
zv = zv + dvdvsr[i] * z[i];
10 }

//prise en compte de la direction;
derive[1] = xu * direcu + xv * direcv;
derive[2] = yu * direcu + yv * direcv;
derive[3] = zu * direcu + zv * direcv;
}
*/
 

if( pt1[i] < PtMin[i] || pt0[i] > PtMax[i] ) return 0; // 0 intersection

//intersection avec le plan Xi=PtMin[i]
if( pt1[i] != pt0[i] )
{
a = ( PtMin[i] - pt0[i] ) / ( pt1[i] - pt0[i] ); //le coefficient du vecteur pt1-pt0
if( 0<a && a<=1 ) pt0 = pt0 + a * (pt1 - pt0); //le nouveau point sur la droite
}

//intersection avec le plan Xi=PtMax[i]
if( pt1[i] != pt0[i] )
{
a = ( PtMax[i] - pt0[i] ) / ( pt1[i] - pt0[i] ); //le coefficient du vecteur pt1-pt0
if( 0<=a && a<1 ) pt1 = pt0 + a * (pt1 - pt0); //le nouveau point sur la droite
}
}
return 1; //Pt d'intersection calcule
}


int Point3Axe3( R3 p1, R3 p2, R3 p3, R3 axe[3] )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : a partir de 3 points former les axes orthonormes tels que
// ----- axe( . , 1 ) = p1p2 / norme( p1p2 )
// axe( . , 3 ) = axe( . , 1 ) produit vectoriel p1p3 / norme(p1p3)
// axe( . , 2 ) = axe( . , 3 ) produit vectoriel axe( . , 1 )
// retourner 1 si les 3 points sont alignes ou confondus, 0 sinon
//
// entrees:
// --------
// p1 p2 p3 : les 3 points
//
// sorties:
// --------
// axe : axe[i][j]=j-eme coordonnee du i-eme axe orthonorme
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : alain perronnet analyse numerique paris upmc avril 2001
// ..................................................................
{
int i;

axe[0] = p2 - p1;
if( NormeA1( axe[0] ) == 0 ) return 1; //normalisation du vecteur a 1

axe[1] = p3 - p1;
ProduitVectoriel( axe[0], axe[1], axe[2] );
if( NormeA1( axe[2] ) == 0 ) return 1;

ProduitVectoriel( axe[2], axe[0], axe[1] );
if( NormeA1( axe[1] ) == 0 ) return 1;

return 0;
}

int NormeA1( R3 & v )
//Rendre la norme du vecteur egale a 1 sauf si le vecteur est nul
//Retourner 1 si le vecteur est normalise a 1
// 0 si le vecteur est nul
{ R s;

s = Norme2( v ); //la norme du vecteur
if( s>0 )
{
v = v / s; //la normalisation a 1
return 1;
}
else
return 0;
}

void ScgScu( R3 SCU[], R3 xyzscg, R3 & xyzscu )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du point dans le SCU
// ----- a partir des 3 coordonnees du point dans le SCG
// translation des origines faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// xyzscg : les 3 coordonnees du point dans le repere SCG
//
// sortie :
// --------
// xyzscu : les 3 coordonnees du point dans le repere SCU
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x, y, z; // protection pour appel avec xyzscg = xyzscu

x = xyzscg.x - SCU[0].x;
y = xyzscg.y - SCU[0].y;
z = xyzscg.z - SCU[0].z;

xyzscu.x = SCU[1].x * x + SCU[1].y * y + SCU[1].z * z;
xyzscu.y = SCU[2].x * x + SCU[2].y * y + SCU[2].z * z;
xyzscu.z = SCU[3].x * x + SCU[3].y * y + SCU[3].z * z;
}

void ScuScg( R3 SCU[], R3 xyzscu, R3 & xyzscg )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du xyzecteur dans le SCG
// ----- a partir des 3 coordonnees du xyzecteur dans le SCU
// translation des origines faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// xyzscu : les 3 coordonnees du point dans le repere SCU
//
// sortie :
// --------
// xyzscg : les 3 coordonnees du point dans le repere SCG
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x,y,z; // protection pour appel avec xyzscu = xyzscg

x = xyzscu[0];
y = xyzscu[1];
z = xyzscu[2];

xyzscg.x = SCU[1].x * x + SCU[2].x * y + SCU[3].x * z + SCU[0].x;
xyzscg.y = SCU[1].y * x + SCU[2].y * y + SCU[3].y * z + SCU[0].y;
xyzscg.z = SCU[1].z * x + SCU[2].z * y + SCU[3].z * z + SCU[0].z;
}

void VecteurScgScu( R3 SCU[], R3 vscg, R3 & vscu )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du vecteur dans le SCU
// ----- a partir des 3 coordonnees du vecteur dans le SCG
// translation des origines non faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// vscg : les 3 coordonnees du vecteur dans le repere SCG
//
// sortie :
// --------
// vscu : les 3 coordonnees du vecteur dans le repere SCU
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x, y, z; // protection pour appel avec vscg = vscu

x = vscg.x; // - SCU[0].x;
y = vscg.y; // - SCU[0].y;
z = vscg.z; // - SCU[0].z;

vscu.x = SCU[1].x * x + SCU[1].y * y + SCU[1].z * z;
vscu.y = SCU[2].x * x + SCU[2].y * y + SCU[2].z * z;
vscu.z = SCU[3].x * x + SCU[3].y * y + SCU[3].z * z;
}

void VecteurScuScg( R3 SCU[], R3 vscu, R3 & vscg )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calcul des 3 coordonnees du vecteur dans le SCG
// ----- a partir des 3 coordonnees du vecteur dans le SCU
// translation des origines non faite
// entrees:
// --------
// SCU : Origine, 3 vecteurs orthonormes de coordonnees dans le SCG
// vscu : les 3 coordonnees du vecteur dans le repere SCU
//
// sortie :
// --------
// vscg : les 3 coordonnees du vecteur dans le repere SCG
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
R x,y,z; // protection pour appel avec vscu = vscg

x = vscu[0];
y = vscu[1];
z = vscu[2];

vscg.x = SCU[1].x * x + SCU[2].x * y + SCU[3].x * z; // + SCU[0].x; pour Pt
vscg.y = SCU[1].y * x + SCU[2].y * y + SCU[3].y * z; // + SCU[0].y;
vscg.z = SCU[1].z * x + SCU[2].z * y + SCU[3].z * z; // + SCU[0].z;
}

 

 

 

 

 


/*
void dedvsr( R3 xyzs[], R3 xyzt[], int nosoel[12],
R u, R v, R direcu, R direcv,
R3 derive )
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// but : calculer les 3 coordonnees de la derivee dvsr[u,v][direcu,direcv]
// ----- sur le quadrangle de sommets et tangentes de numeros dans nosoel
// entrees:
// --------
// mnxyzs : adresse mcn de la premiere coordonnee du premier sommet
// mnxyzt : adresse mcn de la premiere coordonnee de la premiere tg
// nosoel : numero des 4 sommets et des 8 tangentes de l'ef
// quadrangle: no sommet1, ns2 , ns3, ns4,
// no tangente1[s1s2], nt2[s1s3], nt3[s2s3], nt4[s2s1],
// no tangente5[s3s4], nt6[s3s2], nt7[s4s1], nt8[s4s3]
// ce choix permet une boucle sur les tangentes par les sommets
// u,v : valeur des 2 parametres dans [0,1] de l'ef de Veubeke Sander reduit
// direcu : abscisse de la direction de la derivee a calculer
// direcv : ordonnee de la direction de la derivee a calculer
// sorties:
// --------
// derive : les 3 composantes de la derivee dvsr[u,v][direcu,direcv]
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// auteur : perronnet alain analyse numerique upmc paris novembre 1996
//2345x...........................................................012
{
R xu, xv, yu, yv, zu, zv;

//calcul des 3 coordonnees des sommets et tangentes de cet ef dvsr;
xyzstg[ mnxyzs-3, mnxyzt-3, 4, nosoel, 1,;
% x, y, z ];

//calcul de la derivee / u au point [u,v] des fonctions de base;
ddudvs[ u,v, dudvsr ];

//calcul de la derivee / v au point [u,v] des fonctions de base;
ddvdvs[ u,v, dvdvsr ];

//calcul de la derivee dvsr[u,v][direcu,direcv];
xu = 0;
xv = 0;
yu = 0;
yv = 0;
zu = 0;
zv = 0;
do 10 i=1,12;
xu = xu + dudvsr[i] * x[i];
xv = xv + dvdvsr[i] * x[i];
yu = yu + dudvsr[i] * y[i];
yv = yv + dvdvsr[i] * y[i];
zu = zu + dudvsr[i] * z[i];
zv = zv + dvdvsr[i] * z[i];
10 }

//prise en compte de la direction;
derive[1] = xu * direcu + xv * direcv;
derive[2] = yu * direcu + yv * direcv;
derive[3] = zu * direcu + zv * direcv;
}
*/