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
#include "Surface.h"
#include "tritas.cpp"
#include <stdlib.h>
R TailleArete=0.1; // >0 => Taille souhaitee des
aretes du maillage
// =0 => Emploi de la fonction Taille_Ideale() (A FAIRE...)
// <0 => Emploi d'une carte de taille des aretes(A FAIRE...)
// sur un maillage de fond
int NoPoint=-1;
int NoLigne=-1;
R3 PtMIN(0.0, 0.0, 0.0); //Pt MIN par defaut Points de coordonnees extremales
R3 PtMAX(1.5, 1.1, 0.0); //Pt MAX par defaut
XPoint pxy0={0,0};
XPoint pxy;
Drawable fenoupix; //fenetre ou pixmap variable auxiliaire
int TraceTg=0; //Trace (1) ou non (0) des tangentes aux
noeuds des courbes NURBS
int TraceNormales=0; //Trace (1) ou non (0) des normales et bi-normales aux
noeuds des courbes NURBS
int NoSurface = -1;
int Ombrage = 2; //Ombrage Gouraud si 1, Filaire si 0, Gouraud-Filaire si 2
void NommerPoint( Nom & nom )
{
int nbc;
NoPoint++;
strcpy( nom, "P" );
itoa( NoPoint, nbc, nom+1 );
}
void NommerLigne( Nom & nom )
{
int nbc;
NoLigne++;
strcpy( nom, "L" );
itoa( NoLigne, nbc, nom+1 );
}
void NommerSurface( Nom & nom )
{
int nbc;
NoSurface++;
strcpy( nom, "S" );
itoa( NoSurface, nbc, nom+1 );
}
Surface::Surface() : PLSV ()
{
NommerSurface( nom );
PSuivant = NULL;
}
Surface::Surface( Nom NomSurface ) : PLSV()
{
strcpy( nom, NomSurface );
PSuivant = NULL;
}
Surface::~Surface()
{
if ( NoStEF ) delete [] NoStEF;
if ( XyzSommet ) delete [] XyzSommet;
if ( U ) delete [] U;
if ( V ) delete [] V;
if ( PC ) delete [] PC;
if ( Poids ) delete [] Poids;
if ( Courbes ) delete [] Courbes;
if ( PSuivant )
delete PSuivant;
}
R3 Surface::PointMilieuSurface(void)
{
if ( (XyzSommet == NULL) || (NoStEF == NULL) )
return R3(0,0,0);
int pos = (NbStEF*NbEF) / 2 ;
return ( (XyzSommet[ NoStEF[pos] ] + XyzSommet[ NoStEF[pos-1] ]) / 2 );
}
void Surface::PointSurface( R u, R v, R3 & P )
{
int i,j;
int k,l, m, n;
R Nu[1+64], Nv[1+64];
R denominateur = 0;
R Np2;
R denominateur2;
i = IntervalleNURBS( u, U, nbnu, degreu );
j = IntervalleNURBS( v, V, nbnv, degrev );
ValeurBaseNURBS( i, degreu, u, U, Nu );
ValeurBaseNURBS( j, degrev, v, V, Nv );
P.x = P.y = P.z = 0.0;
if ( Poids == NULL )
{
for (k=0; k<=degreu; k++)
{
l = i - degreu + k;
R3 P2(0,0,0);
for (m=0; m<=degrev; m++)
{
n = j - degrev + m;
P2 += Nv[m] * PC[l][n]->XyzSommet[0];
}
P += Nu[k] * P2;
}
}
else
{
for (k=0; k<=degreu; k++)
{
l = i - degreu + k;
R3 P2(0,0,0);
denominateur2 = 0;
for (m=0; m<=degrev; m++)
{
n = j - degrev + m;
Np2 = Nv[m] * Poids[l][n];
denominateur2 += Np2;
P2 += Np2 * PC[l][n]->XyzSommet[0];
}
P += Nu[k] * P2;
denominateur += Nu[k] * denominateur2;
}
P = P / denominateur;
}
}
int Surface::Mailler( Points * LesPoints )
{
R u, v, hu, hv;
int nbefu, nbefv; /* Nombre d'elements finis selon u et v */
bool renverse = false;
if ( TailleArete <= 0 )
return 2;
CalculNbEF( nbefu, nbefv ); /* fonction de la classe derivee */
NbEF = nbefu * nbefv;
if ( NbEF < 1 ) NbEF = 1;
NbSommet = (nbefu+1) * (nbefv+1);
XyzSommet = new R3[NbSommet];
hu = ( U[nbnu+1] - U[0] ) / nbefu;
hv = ( V[nbnv+1] - V[0] ) / nbefv;
u = U[0];
v = V[0];
for (int i=0; i<=nbefv; i++) {
u = U[0];
for (int j=0; j<=nbefu; j++) {
int pos = i*(nbefu+1)+j;
PointSurface( u, v, XyzSommet[pos] );
PtMIN = Min( PtMIN, XyzSommet[pos] );
PtMAX = Max( PtMAX, XyzSommet[pos] );
u += hu;
}
v += hv;
}
NbStEF = 4;
NoStEF = new Z[NbEF*NbStEF];
R3 vect1;
R3 vect2;
vect1 = XyzSommet[1]-XyzSommet[0];
vect2 = XyzSommet[nbefu+2]-XyzSommet[0];
if ( ( vect1.x*vect2.y - vect1.y*vect2.x ) < 0 ) /* calcul de l orientation d
une surface*/
renverse = true;
int m = 0;
int no=0;
if ( !renverse )
{
for (int i=0; i<nbefv; i++)
{
for (int j=0; j<nbefu; j++)
{
int pos = j+i*(nbefu+1);
no++;
NoStEF[m++] = pos;
NoStEF[m++] = pos + 1; /* quadrangle parcouru dans le sens de la normale si elle
est exterieure */
NoStEF[m++] = pos + nbefu + 2;
NoStEF[m++] = pos + nbefu + 1;
}
}
}
else
{
for (int i=0; i<nbefv; i++)
{
for (int j=0; j<nbefu; j++)
{
int pos = j+i*(nbefu+1);
no++;
NoStEF[m++] = pos; /* quadrangle parcouru dans l autre sens */
NoStEF[m++] = pos + nbefu + 1;
NoStEF[m++] = pos + nbefu + 2;
NoStEF[m++] = pos + 1;
}
}
}
return 0;
}
void Surface::TracerMaillage( MemoirePx3d & mpx )
{
R3 xyz;
R3 coords[4];
Z m = 0;
char texte[8];
R3 normale;
R luminosite;
R3 oeil = mpx.axoeil;
R3 ptv = mpx.axoptv;
R3 barycentre[NbEF];
Z noanc[NbEF];
R d[NbEF];
R3 tmp(0.0,0.0,0.0);
TracerPolyedre(mpx);
VuChoisirFonte ( hauttexte );
VuEpaisseur( 2 );
for (int i=0; i<NbEF ; i++)
{
barycentre[i]=tmp;
for (int j=0; j<NbStEF; j++)
{
int index = NoStEF[m++];
coords[j] = XyzSommet[index];
barycentre[i] += coords[j];
}
barycentre[i] = 0.25*barycentre[i];
d[i]=Norme2(oeil-barycentre[i]);
noanc[i]=i;
}
tritas(NbEF,d,noanc); /* suivant la distance du barycentre des quadrangles a la
pos de loeil la fonction tritas ordonne les faces */
Z pos;
for (int i=NbEF-1; i>=0 ; i--)
{
pos=noanc[i];
pos *= NbStEF;
for (int j=0; j<NbStEF; j++)
{
int index = NoStEF[pos++];
coords[j] = XyzSommet[index];
}
if ( Ombrage )
{
normale = ( coords[1] - coords[0] ) ^ ( coords[3] - coords[0] ); /* calcul des
quatres normales afin d affecter une couleur a chaque point du maillage */
luminosite = ( normale, oeil - ptv );
luminosite /= ( Norme2( normale ) * Norme2( oeil - ptv ) );
normale = ( coords[1] - coords[0] ) ^ ( coords[3] - coords[0]
);
R Ca = ( normale, oeil - ptv );
Ca /= ( Norme2( normale ) * Norme2( oeil - ptv ) );
Ca = 127+255*fabs(Ca/2);
normale = ( coords[0] - coords[1] ) ^ ( coords[2] - coords[1]
);
R Cb = ( normale, oeil - ptv );
Cb /= ( Norme2( normale ) * Norme2( oeil - ptv ) );
Cb = 127+255*fabs(Cb/2);
normale = ( coords[3] - coords[2] ) ^ ( coords[1] - coords[2]
);
R Cc = ( normale, oeil - ptv );
Cc /= ( Norme2( normale ) * Norme2( oeil - ptv ) );
Cc = 127+255*fabs(Cc/2);
normale = ( coords[0] - coords[3] ) ^ ( coords[2] - coords[3]
);
R Cd = ( normale, oeil - ptv );
Cd /= ( Norme2( normale ) * Norme2( oeil - ptv ) );
Cd = 127+255*fabs(Cd/2);
R grad = fabs(luminosite/2);
VuPaletteCouleurs( 11 );
VuCouleur( (int) (127+255*grad) );
// mpx.VuFace( 4, coords ); affichage par quadrangle
mpx.VuTriangleCouleur (coords[0],coords[1],coords[2],Ca,Cb,Cc); /* trace le
triangle en tenant compte des couleurs intermediaires entre les sommets */
mpx.VuTriangleCouleur (coords[2],coords[3],coords[0],Cc,Cd,Ca);
if (Ombrage==2)
{
VuCouleur( Orange );
VuEpaisseur( 1 );
// mpx.VuTraits( 4, coords ); affichage par quadrangle
//mpx.VuBordTriangle(coords[0],coords[1],coords[2]);
//mpx.VuBordTriangle(coords[2],coords[3],coords[0]);
}
}
else
{
VuEpaisseur( 2 );
VuCouleur( Bleu );
mpx.VuTraits( 4, coords );
}
}
xyz = PointMilieuSurface();
sprintf( texte, "*%s", nom);
VuCouleur( Noir );
mpx.VuSymbole( xyz, texte );
}
void Surface::VerifierMaillage( Points * LesPoints )
{
for (int i=0; i<=nbnu; i++)
{
for (int j=0; j<=nbnv; j++)
{
if ( (PC[i][j]->date) > this->date ) /* controle de nonmodification
posterieur au dernier calcul */
{
Mailler(LesPoints);
return;
}
}
}
}
void Surface::TracerPolyedre( MemoirePx3d & mpx )
{
VuEpaisseur( 2 );
VuCouleur( Rose );
for (int i=0; i<nbnu; i++ )
for (int j=0; j<nbnv; j++)
{
mpx.VuTrait( PC[i][j]->XyzSommet[0], PC[i+1][j]->XyzSommet[0] );
mpx.VuTrait( PC[i][j]->XyzSommet[0], PC[i][j+1]->XyzSommet[0] ); /* trace
du maillage de pts de controle */
}
for (int i=0; i<nbnu; i++ )
mpx.VuTrait( PC[i][nbnv]->XyzSommet[0], PC[i+1][nbnv]->XyzSommet[0] );
for (int j=0; j<nbnv; j++)
mpx.VuTrait( PC[nbnu][j]->XyzSommet[0], PC[nbnu][j+1]->XyzSommet[0] );
for (int i=0;i<=nbnu;i++)
for (int j=0;j<=nbnv;j++)
PC[i][j]->TracerMaillage(mpx);
}
//=============================================================================
// Classe SurfaceNURBS
//=============================================================================
SurfaceNURBS::SurfaceNURBS(Lignes *LesLignes,Points *LesPoints):Surface()
{
Nom nomP;
Ligne *Base1,*Base2;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la courbe NURBS n°1
de base ou tapez son nom : ");
if ( (Base1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez la courbe NURBS n°2
de base ou tapez son nom : ");
if ( (Base2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
nbnu=Base1->nbn;
nbnv=Base2->nbn;
degreu=Base1->degre;
degrev=Base2->degre;
//Initialisation des tableaux des points de controle et des
poids
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0]=new Pointxyz(nomP,
Base1->PC[i]->XyzSommet[0].x,
Base1->PC[i]->XyzSommet[0].y,
Base1->PC[i]->XyzSommet[0].z); /* affectation post rentree des infos par l
utilisateur */
LesPoints->Ajouter1Point(PC[i][0]);
}
for (int j=1; j<=nbnv; j++)
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][j]=new Pointxyz(nomP,
PC[i][j-1]->XyzSommet[0].x+Base2->PC[j]->XyzSommet[0].x-Base2->PC[j-1]->XyzSommet[0].x,
PC[i][j-1]->XyzSommet[0].y+Base2->PC[j]->XyzSommet[0].y-Base2->PC[j-1]->XyzSommet[0].y,
PC[i][j-1]->XyzSommet[0].z+Base2->PC[j]->XyzSommet[0].z-Base2->PC[j-1]->XyzSommet[0].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
if ( (Base1->Poids) && (Base2->Poids) )
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv]; /* creationdu tableau des noeuds s ils existent */
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((Base1->Poids[i])+(Base2->Poids[j]))/2;
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Base1->U[i];
V = new R [1+nbnv+1+degrev];
for (int j=0; j<=1+nbnv+degrev; j++)
V[j] = Base2->U[j];
Courbes = new Ligne *[2];
Courbes[0] = Base1;
Courbes[1] = Base2;
Mailler( LesPoints );
}
SurfaceNURBS::SurfaceNURBS(Points *LesPoints,Lignes *LesLignes):Surface()
{
int nbc, ncvals;
Nom NomPt;
Point * PtAvant;
char texte[48];
char carlu;
mpxInvite.VuInvite( "Frapper le DEGRE en u de la
surface NURBS" ); /* interface utilisateur habituelle */
do
{
mpxInvite.lireZ( ncvals, degreu );
if(ncvals==-1) {nbnu=0; return;}
}
while( degreu<=0 );
mpxInvite.VuInvite( "Frapper le DEGRE en v de la
surface NURBS" );
do
{
mpxInvite.lireZ( ncvals, degrev );
if(ncvals==-1) {nbnv=0; return;}
}
while( degrev<=0 );
mpxInvite.VuInvite( "Frapper le NOMBRE de POINTS en u
de la surface NURBS" );
do
{
mpxInvite.lireZ( ncvals, nbnu );
if(ncvals==-1) {nbnu=0; return;}
}
while( nbnu<=0 );
nbnu--;
mpxInvite.VuInvite( "Frapper le NOMBRE de POINTS en v
de la surface NURBS" );
do
{
mpxInvite.lireZ( ncvals, nbnv );
if(ncvals==-1) {nbnv=0; return;}
}
while( nbnv<=0 );
nbnv--;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
strcpy( texte, "Cliquer le POINT de CONTROLE[" );
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
{
itoa( i, nbc, (texte+29) );
strcat( texte, "][");
itoa( j, nbc, (texte+32) );
strcat(texte, "] ou frapper son NOM" );
mpxInvite.VuInvite( texte );
PC[i][j] = LesPoints->Points::CliquerPoint();
if( PC[i][j] == NULL ) { nbnu=0; nbnv=0; return; }
mpxInvite.VuEffacerMemoirePx();
}
U = new R[1+nbnu+1+degreu]; // declaration du tableau des
noeuds
mpxInvite.VuInvite( "Frapper la valeur des NOEUDS u (o/N)" );
carlu = mpxInvite.lire1Caractere();
mpxInvite.VuEffacerMemoirePx();
if( carlu == '@' || int(carlu)== 27 ) {nbnu=0; return;} //ABANDON
if( carlu == 'o' || carlu == 'O' || carlu == '0' )
{ //saisie des valeurs des noeuds
strcpy( texte, "Frapper la valeur du noeud U[" ); //comme pour la
saisie des lignes nurbs dans plsv
for (int i=degreu; i<=nbnu+1; i++)
{
itoa( i, nbc, (texte+29) ); //texte de l'invite
strcat( texte, "]" );
mpxInvite.VuInvite( texte ); //trace de l'invite
do {
mpxInvite.lireR( ncvals, U[i] );
if(ncvals==-1) {nbnu=0; return;} //ABANDON demande
if(i==0) break;
} while (U[i]<U[i-1]);
mpxInvite.VuEffacerMemoirePx();
}
}
else
{ // creation automatique des noeuds simples
U[degreu] = 0;
for (int i=degreu+1; i<=nbnu+1; i++)
{ U[i] = U[i-1] + Norme2( PC[i-degreu ][0]->XyzSommet[0]
- PC[i-degreu-1][0]->XyzSommet[0] ); }
}
for (int i=0; i<=degreu; i++ ) //noeud initial
{ U[i] = U[degreu]; }
for (int i=nbnu+2; i<=nbnu+1+degreu; i++) //noeud final
{ U[i]=U[nbnu+1]; }
V = new R[1+nbnv+1+degrev]; //declaration du tableau des
noeuds
mpxInvite.VuInvite( "Frapper la valeur des NOEUDS v (o/N)" );
carlu = mpxInvite.lire1Caractere();
mpxInvite.VuEffacerMemoirePx();
if( carlu == '@' || int(carlu)== 27 ) {nbnv=0; return;} //ABANDON
if( carlu == 'o' || carlu == 'O' || carlu == '0' )
{ //saisie interactive des valeurs des noeuds
strcpy( texte, "Frapper la valeur du noeud V[" );
for (int j=degrev; j<=nbnv+1; j++)
{
itoa( j, nbc, (texte+29) ); //texte de l'invite
strcat( texte, "]" );
mpxInvite.VuInvite( texte ); //trace de l'invite
do {
mpxInvite.lireR( ncvals, V[j] );
if(ncvals==-1) {nbnv=0; return;} //ABANDON demande
if(j==0) break;
} while (V[j]<V[j-1]);
mpxInvite.VuEffacerMemoirePx();
}
}
else
{ // creation automatique des noeuds simples
V[degrev] = 0;
for (int j=degrev+1; j<=nbnv+1; j++)
{ V[j] = V[j-1] + Norme2( PC[0][j-degrev ]->XyzSommet[0]
- PC[0][j-degrev-1]->XyzSommet[0] ); }
}
for (int j=0; j<=degrev; j++ ) //noeud initial
{ V[j] = V[degrev]; }
for (int j=nbnv+2; j<=nbnv+1+degrev; j++) //noeud final
{ V[j]=V[nbnv+1]; }
mpxInvite.VuInvite( "Frapper la valeur des Poids
(o/N)" );
carlu = mpxInvite.lire1Caractere();
if( carlu == '@' || int(carlu)== 27 ) {nbnv=0; return;} //ABANDON
if( carlu == 'o' || carlu == 'O' || carlu == '0' )
{
//saisie interactive des valeurs des Poids => courbe NURBS
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
strcpy( texte, "Frapper le Poids[" );
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
{
itoa( i, nbc, (texte+17) ); //texte de l'invite
strcat( texte, "][" );
itoa( j, nbc, (texte+17) );
strcat( texte, "]" );
mpxInvite.VuInvite( texte );
mpxInvite.lireR( ncvals, Poids[i][j] );
if(ncvals==-1) {nbnu=0; nbnv=0; return;} //ABANDON demande
}
}
else
{ // pas de creation des Poids => courbe polynomiale
// Poids = NULL; cela signifie non pas que les poids soient nuls mais que le
tableau des poids est vide
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=1; //valeur par defaut
}
mpxInvite.VuEffacerMemoirePx(); //on libere la varible qui
stocke les donnees d interface
Mailler(LesPoints);
}
void SurfaceNURBS::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv = (int) ( Courbes[1]->LongueurNURBS() / TailleArete + 0.5 );
}
void SurfaceNURBS::AfficherDefinition()
{
cout << "Nom de la Surface NURBS= " << nom <<endl;
}
void SurfaceNURBS::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) || (Courbes[1]->date >
this->date))
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceBezier
//=============================================================================
SurfaceBezier::SurfaceBezier(Lignes *LesLignes,Points
*LesPoints):Surface() //de maniere tres similaire a la classe precedante
{
Nom nomP;
Ligne *Base1,*Base2;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la courbe NURBS n°1
de base ou tapez son nom : ");
if ( (Base1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez la courbe NURBS n°2
de base ou tapez son nom : ");
if ( (Base2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
nbnu=Base1->nbn;
nbnv=Base2->nbn;
degreu=Base1->degre;
degrev=Base2->degre;
//Initialisation des points de controle et des poids
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0]=new Pointxyz(nomP,
Base1->PC[i]->XyzSommet[0].x,
Base1->PC[i]->XyzSommet[0].y,
Base1->PC[i]->XyzSommet[0].z);
LesPoints->Ajouter1Point(PC[i][0]);
}
for (int j=1; j<=nbnv; j++)
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][j]=new Pointxyz(nomP,
PC[i][j-1]->XyzSommet[0].x+Base2->PC[j]->XyzSommet[0].x-Base2->PC[j-1]->XyzSommet[0].x,
PC[i][j-1]->XyzSommet[0].y+Base2->PC[j]->XyzSommet[0].y-Base2->PC[j-1]->XyzSommet[0].y,
PC[i][j-1]->XyzSommet[0].z+Base2->PC[j]->XyzSommet[0].z-Base2->PC[j-1]->XyzSommet[0].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
if ( (Base1->Poids) && (Base2->Poids) )
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((Base1->Poids[i])+(Base2->Poids[j]))/2;
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=(1+nbnu+degreu)/2; i++)
U[i] = 0;
for (int i=1+(1+nbnu+degreu)/2; i<=1+nbnu+degreu; i++)
U[i] = 1;
V = new R [1+nbnv+1+degrev];
for (int j=0; j<=(1+nbnu+degreu)/2; j++)
V[j] = 0;
for (int j=1+(1+nbnu+degreu)/2; j<=1+nbnu+degreu; j++)
V[j] = 1;
Courbes = new Ligne *[2];
Courbes[0] = Base1;
Courbes[1] = Base2;
Mailler( LesPoints );
}
void SurfaceBezier::CalculNbEF( int & nbefu, int & nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv = (int) ( Courbes[1]->LongueurNURBS() / TailleArete + 0.5 );
}
void SurfaceBezier::AfficherDefinition()
{
cout << "Nom de la Surface NURBS= " << nom <<endl;
}
void SurfaceBezier::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) || (Courbes[0]->date >
this->date))
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceReglee
//=============================================================================
SurfaceReglee::SurfaceReglee(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
Ligne *Base1,*Base2;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la premiere courbe
de base ou tapez son nom : ");
if ( (Base1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez la deuxieme courbe
de base ou tapez son nom : ");
if ( (Base2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
Z deg1,deg2;
deg1=Base1->degre;
deg2=Base2->degre;
while (Base1->degre!=Base2->degre)
{
if (Base1->degre < Base2->degre)
Base1->Elevation1Degre(LesPoints);
else
Base2->Elevation1Degre(LesPoints);
if ( (deg1==Base1->degre) &&
(deg2==Base2->degre))
break;
}
if (Base1->degre!=Base2->degre)
{
mpxInvite.VuInvite( "Degré non élevable");
return;
}
nbnu=Base1->nbn; //les chemins entre les deux courbes
qui se font face sont tendus de degre 1
nbnv=1;
degreu=Base1->degre;
degrev=1;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0]=new Pointxyz(nomP,
Base1->PC[i]->XyzSommet[0].x,
Base1->PC[i]->XyzSommet[0].y,
Base1->PC[i]->XyzSommet[0].z);
LesPoints->Ajouter1Point(PC[i][0]);
NommerPoint(nomP);
PC[i][1]=new Pointxyz(nomP,
Base2->PC[i]->XyzSommet[0].x,
Base2->PC[i]->XyzSommet[0].y,
Base2->PC[i]->XyzSommet[0].z);
LesPoints->Ajouter1Point(PC[i][1]);
}
if ( (Base1->Poids) && (Base2->Poids) )
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((Base1->Poids[i])+(Base2->Poids[j]))/2;
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Base1->U[i];
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = 0;
V[2] = V[3] = 1;
Courbes = new Ligne *[1];
Courbes[0] = Base1;
Mailler( LesPoints );
}
void SurfaceReglee::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv=nbefu;
}
void SurfaceReglee::AfficherDefinition()
{
cout << "Nom de la Surface REGLEE= " << nom <<endl;
}
void SurfaceReglee::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) || (Courbes[0]->date >
this->date))
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceBilineaire
//=============================================================================
SurfaceBilineaire::SurfaceBilineaire(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
int ncvals;
Ligne *Base1,*Base2;
mpxInvite.VuInvite( "Selectionnez la premiere ligne ou
tapez son nom : ");
if ( (Base1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez la seconde ligne ou tapez son nom :
");
if ( (Base2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
degreu = 1; //les deux courbes sont ici tendues
nbnu = 1;
degrev = 1;
nbnv = 1;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
PC[0][0]=Base1->PC[0];
PC[0][1]=Base1->PC[1];
PC[1][0]=Base2->PC[0];
PC[1][1]=Base2->PC[1];
U = new R [1+nbnu+1+degreu]; //pas de noeud intermediaire
U[0] = U[1] = 0;
U[2] = U[3] = 1;
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = 0;
V[2] = V[3] = 1;
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
Poids[i][0] = Poids[i][1] = 1; //les poids sont egaux la valeur du noeud ne
compte pas ici
Courbes = new Ligne *[2];
Courbes[0] = Base1;
Courbes[1] = Base2;
Mailler( LesPoints );
}
void SurfaceBilineaire::CalculNbEF( int & nbefu, int
& nbefv )
{
R long1 = Courbes[0]->LongueurNURBS();
R long2 = Norme2( (Courbes[1]->PC[0]->XyzSommet[0]) -
(Courbes[0]->PC[0]->XyzSommet[0]) );
nbefu = (int) ( long1 / TailleArete + 0.5 );
nbefv = (int) ( long2 / TailleArete + 0.5 );
}
void SurfaceBilineaire::AfficherDefinition()
{
cout << "Nom de la Surface BILINEAIRE= " << nom
<<endl;
}
void SurfaceBilineaire::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) || (Courbes[1]->date >
this->date) )
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceExtrudee
//=============================================================================
SurfaceExtrudee::SurfaceExtrudee(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
Ligne * Base;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la courbe à
extruder ou tapez son nom : ");
if ( (Base = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Rentrez la hauteur d'extrusion :
");
mpxInvite.lireR( ncvals, Hauteur );
mpxInvite.VuEffacerMemoirePx();
degreu = Base->degre;
nbnu = Base->nbn;
degrev = 1;
nbnv = 1;
R3 tmpSCG;
R3 tmpSCU(0,0,Hauteur);
VecteurScuScg( SCU, tmpSCU, tmpSCG ); //extrude verticallement dans le SCU
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0] = new Pointxyz( nomP,
Base->PC[i]->XyzSommet[0].x,
Base->PC[i]->XyzSommet[0].y,
Base->PC[i]->XyzSommet[0].z );
LesPoints->Ajouter1Point( PC[i][0] );
NommerPoint( nomP );
PC[i][1] = new Pointxyz( nomP,
Base->PC[i]->XyzSommet[0].x + tmpSCG.x,
Base->PC[i]->XyzSommet[0].y + tmpSCG.y,
Base->PC[i]->XyzSommet[0].z + tmpSCG.z ) ;
LesPoints->Ajouter1Point( PC[i][1] );
}
U = new R [1+nbnu+1+degreu]; //ceci est la courbe libre a extruder
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Base->U[i];
V = new R [1+nbnv+1+degrev]; //la deuxieme courbe est un
chemin elementaire
V[0] = V[1] = 0;
V[2] = V[3] = 1;
if ( Base->Poids )
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
Poids[i][0] = Poids[i][1] = Base->Poids[i];
}
Courbes = new Ligne *[1];
Courbes[0] = Base;
Mailler( LesPoints );
}
void SurfaceExtrudee::CalculNbEF( int & nbefu, int
& nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv = 1 + (int) fabs( (Hauteur / TailleArete + 0.5) );
}
void SurfaceExtrudee::AfficherDefinition()
{
cout << "Nom de la Surface EXTRUDEE= " << nom
<< " Hauteur de la Surface EXTRUDEE= " << Hauteur
<<endl;
}
void SurfaceExtrudee::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) ) Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceRevolution
//=============================================================================
SurfaceRevolution::SurfaceRevolution(Lignes
*LesLignes,Points *LesPoints):Surface()
{
Nom nomP;
Ligne *Genere;
Point *PtI,*PtII;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la courbe
generatrice ou tapez son nom : ");
if ( (Genere = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Premier point definissant l'axe de revolution :
");
if ( (PtI = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
PtII = PtI;
do
{
mpxInvite.VuInvite( "Second point definissant l'axe de revolution :
");
if ( (PtII = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
}
while ( PtII == PtI );
degreu = Genere->degre;
nbnu = Genere->nbn;
degrev = 2;
nbnv = 8;
R3 A,B,P,Q,V1,V2,W1,W2,Aux; //Quelques points et vecteurs
auxiliaires
R3 Liste [nbnv+1]; //Une liste auxiliaire de R3
R lambda; //Une constante auxiliaire
//Calculs hors toute boucle
A = PtI->XyzSommet[0];
B = PtII->XyzSommet[0];
V2 = B - A;
Rayon = 0;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
//calculs intermediaires
P = Genere->PC[i]->XyzSommet[0];
V1 = P - A; //un R3 est manipulable indifferemment comme un point ou un vecteur
lambda = (V1,V2)/(V2,V2);
Q = A + lambda*V2;
W1 = P - Q;
if ((W1,W1)) //Point hors l'axe
{
Aux = W1^V2;
W2 = (Aux/Norme2(Aux))*Norme2(W1);
Rayon = Max(Rayon,Norme2(W1));
//Les 8 points du carre de controle du cercle
Liste[0] = Q+W1;
Liste[1] = Q+W1+W2;
Liste[2] = Q+W2;
Liste[3] = Q-W1+W2;
Liste[4] = Q-W1;
Liste[5] = Q-W1-W2;
Liste[6] = Q-W2;
Liste[7] = Q+W1-W2;
Liste[8] = Liste[0];
}
else //Point sur l'axe=>tous identiques
{
for (int k=0; k<=nbnv; k++)
Liste[k]=Q;
}
for (int j=0; j<=nbnv; j++)
{
NommerPoint(nomP);
PC[i][j] = new Pointxyz (nomP,Liste[j].x,Liste[j].y,Liste[j].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Genere->U[i];
V = new R [1+nbnv+1+degrev]; //valeur des noeuds du cercle est un resultat connu
V[0] = V[1] = V[2] = 0.0;
V[3] = V[4] = 0.25;
V[5] = V[6] = 0.5;
V[7] = V[8] = 0.75;
V[9] = V[10] = V[11] = 1.0;
//Existence des poids donc creation dynamique d un tableau poitant sur les poids
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
if (Genere->Poids)
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((j%2)*RAC2_2+(!(j%2)))*Genere->Poids[i]; //ici les valeurs des
poids suivent une loi modulo
}
else
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=(j%2)*RAC2_2+(!(j%2));
}
Courbes = new Ligne *[1];
Courbes[0] = Genere;
Mailler( LesPoints );
}
void SurfaceRevolution::CalculNbEF( int & nbefu, int
& nbefv )
{
nbefu= (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv=(int)( 1 + fabs( ( (2*PI*Rayon) / TailleArete + 0.5) ) );
}
void SurfaceRevolution::AfficherDefinition()
{
cout << "Nom de la surface de REVOLUTION= " << nom
<<endl;
}
void SurfaceRevolution::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) )
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceGauche
//=============================================================================
SurfaceGauche::SurfaceGauche(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
Ligne *C1, *C2, *D1, *D2;
int ncvals;
mpxInvite.VuInvite( "Selectionnez la premiere courbe
ou tapez son nom : "); //interface utilisateur habituelle
if ( (C1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez sa courbe opposée
ou tapez son nom : ");
if ( (C2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez la deuxieme courbe
ou tapez son nom : ");
if ( (D1 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Selectionnez sa courbe opposee ou
tapez son nom : ");
if ( (D2 = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
if ( (C1->nbn != C2->nbn) || (D1->nbn !=
D2->nbn) ||
(C1->degre != C2->degre) || (D1->degre != D2->degre) )
return;
degreu = C1->degre; //4 courbes 2 a 2 en face les unes
des autres
nbnu = C1->nbn;
degrev = D1->degre;
nbnv = D1->nbn;
R3 Aux;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0] = new Pointxyz( nomP,
C1->PC[i]->XyzSommet[0].x,
C1->PC[i]->XyzSommet[0].y,
C1->PC[i]->XyzSommet[0].z );
LesPoints->Ajouter1Point( PC[i][0] );
NommerPoint( nomP );
PC[i][nbnv] = new Pointxyz( nomP,
C2->PC[i]->XyzSommet[0].x,
C2->PC[i]->XyzSommet[0].y,
C2->PC[i]->XyzSommet[0].z ) ;
LesPoints->Ajouter1Point( PC[i][nbnv] );
}
for (int j=0; j<=nbnv; j++)
{
NommerPoint(nomP);
PC[0][j] = new Pointxyz( nomP,
D1->PC[j]->XyzSommet[0].x,
D1->PC[j]->XyzSommet[0].y,
D1->PC[j]->XyzSommet[0].z );
LesPoints->Ajouter1Point( PC[0][j] );
NommerPoint( nomP );
PC[nbnu][j] = new Pointxyz( nomP,
D2->PC[j]->XyzSommet[0].x,
D2->PC[j]->XyzSommet[0].y,
D2->PC[j]->XyzSommet[0].z ) ;
LesPoints->Ajouter1Point( PC[nbnu][j] );
}
R mu1, mu2; //Coefficients
for (int i=1; i<nbnu; i++)
{
mu1 = i/nbnu; //Coefficient multiplicatif des points de C1 et C2
for (int j=1; j<nbnv; j++)
{
mu2 = j/nbnv;//Coefficient multiplicatif des points de D1
et D2
Aux.x=((1-mu1)*(C1->PC[i]->XyzSommet[0].x)+
(mu1)*(C2->PC[i]->XyzSommet[0].x)
+(1-mu2)*(D1->PC[j]->XyzSommet[0].x)+
(mu2)*(D2->PC[j]->XyzSommet[0].x))/2; //c est la formule du cours a prpos
ds surfaces reglees
Aux.y=((1-mu1)*(C1->PC[i]->XyzSommet[0].y)+
(mu1)*(C2->PC[i]->XyzSommet[0].y)
+(1-mu2)*(D1->PC[j]->XyzSommet[0].y)+
+(mu2)*(D2->PC[j]->XyzSommet[0].y))/2;
Aux.z=((1-mu1)*(C1->PC[i]->XyzSommet[0].z)+
(mu1)*(C2->PC[i]->XyzSommet[0].z)
+(1-mu2)*(D1->PC[j]->XyzSommet[0].z)+
(mu2)*(D2->PC[j]->XyzSommet[0].z))/2;
NommerPoint( nomP );
PC[i][j] = new Pointxyz( nomP, Aux.x, Aux.y, Aux.z ) ;
LesPoints->Ajouter1Point( PC[i][j] );
}
}
//on unie les jeux de liens qui sont en vis a vis
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = C1->U[i];
V = new R [1+nbnv+1+degrev];
for (int j=0; j<=1+nbnv+degrev; j++)
V[j] = D1->U[j];
if ( C1->Poids && C2->Poids &&
D1->Poids && D2->Poids)
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j] =
(C1->Poids[i]+C2->Poids[i]+D1->Poids[j]+D2->Poids[j])/4;
}
Courbes = new Ligne *[4];
Courbes[0] = C1;
Courbes[1] = C2;
Courbes[2] = D1;
Courbes[3] = D2;
Mailler( LesPoints );
}
void SurfaceGauche::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv = (int) ( Courbes[2]->LongueurNURBS() / TailleArete + 0.5 );
}
void SurfaceGauche::AfficherDefinition()
{
cout << "Nom de la Surface GAUCHE= " << nom <<endl;
}
void SurfaceGauche::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) ) Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceTore
//=============================================================================
SurfaceTore::SurfaceTore(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
Ligne *Genere;
Point *PtI,*PtII;
int ncvals;
do
{
mpxInvite.VuInvite( "Selectionnez le cercle ou tapez son nom : ");
//interface utilisateur
if ( (Genere = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
}
while ( (Genere->nbn!=8) || (Genere->degre!=2) );
mpxInvite.VuInvite( "Premier point definissant l'axe
de revolution : ");
if ( (PtI = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
PtII = PtI;
do
{
mpxInvite.VuInvite( "Second point definissant l'axe de revolution :
");
if ( (PtII = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
}
while ( PtII == PtI );
degreu = Genere->degre;
nbnu = Genere->nbn;
degrev = 2;
nbnv = 8; //car ici on aurait pu faire deriver cette classe de la classe des
surfaces de revolution
R3 A,B,P,Q,V1,V2,W1,W2,Aux; //variables annexes
R3 Liste [nbnv+1]; //points de controle generes pour un point de la premiere
courbe nurbs
R lambda;
A = PtI->XyzSommet[0];
B = PtII->XyzSommet[0];
V2 = B - A;
Rayon = 0;
//Une boucle exterieure pour calculer le carre de controle
//pour chaque point de controle de la courbe generatrice
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
//Quelques points et vecteurs necessaires
P = Genere->PC[i]->XyzSommet[0];
V1 = P - A;
lambda = (V1,V2)/(V2,V2);
Q = A + lambda*V2;
W1 = P - Q;
if ((W1,W1)) //Point hors l'axe
{
Aux = W1^V2;
W2 = (Aux/Norme2(Aux))*Norme2(W1);
Rayon = Max(Rayon,Norme2(W1));
//Les 8 points du carre de controle du cercle
Liste[0] = Q+W1;
Liste[1] = Q+W1+W2;
Liste[2] = Q+W2;
Liste[3] = Q-W1+W2;
Liste[4] = Q-W1;
Liste[5] = Q-W1-W2;
Liste[6] = Q-W2;
Liste[7] = Q+W1-W2;
Liste[8] = Liste[0];
}
else //Point sur l'axe
{
for (int k=0; k<=nbnv; k++)
Liste[k]=Q;
}
for (int j=0; j<=nbnv; j++)
{
NommerPoint(nomP);
PC[i][j] = new Pointxyz (nomP,Liste[j].x,Liste[j].y,Liste[j].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Genere->U[i];
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = V[2] = 0.0;
V[3] = V[4] = 0.25;
V[5] = V[6] = 0.5;
V[7] = V[8] = 0.75;
V[9] = V[10] = V[11] = 1.0;
//Existence donc creation des poids
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
if (Genere->Poids)
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((j%2)*RAC2_2+(!(j%2)))*Genere->Poids[i]; //regle en modulo
}
else
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=(j%2)*RAC2_2+(!(j%2));
}
Courbes = new Ligne *[1];
Courbes[0] = Genere;
Mailler( LesPoints );
}
void SurfaceTore::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu= (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv=(int) (2*PI*nbefu);
}
void SurfaceTore::AfficherDefinition()
{
cout << "Nom de la Surface TORE= " << nom <<endl;
}
void SurfaceTore::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) )
Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceCylindre
//=============================================================================
SurfaceCylindre::SurfaceCylindre(Lignes * LesLignes, Points
*LesPoints):Surface()
{
Nom nomP;
Ligne * BaseC;
int ncvals;
BaseC = new LigneCercle(LesPoints);
if( BaseC->NbSommet == 0 )
return ;
LesLignes->Ajouter1Ligne( BaseC );
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Rentrez la hauteur du CYLINDRE : ");
mpxInvite.lireR( ncvals, Hauteur );
mpxInvite.VuEffacerMemoirePx();
degreu = BaseC->degre;
nbnu = BaseC->nbn;
degrev = 1;
nbnv = 1;
R3 tmpSCG;
R3 tmpSCU(0,0,Hauteur);
VecteurScuScg( SCU, tmpSCU, tmpSCG );
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
NommerPoint(nomP);
PC[i][0] = new Pointxyz( nomP,
BaseC->PC[i]->XyzSommet[0].x,
BaseC->PC[i]->XyzSommet[0].y,
BaseC->PC[i]->XyzSommet[0].z );
LesPoints->Ajouter1Point( PC[i][0] );
NommerPoint( nomP );
PC[i][1] = new Pointxyz( nomP,
BaseC->PC[i]->XyzSommet[0].x + tmpSCG.x,
BaseC->PC[i]->XyzSommet[0].y + tmpSCG.y,
BaseC->PC[i]->XyzSommet[0].z + tmpSCG.z ) ;
LesPoints->Ajouter1Point( PC[i][1] );
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = BaseC->U[i];
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = 0;
V[2] = V[3] = 1;
if ( BaseC->Poids )
{
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
for (int i=0; i<=nbnu; i++)
Poids[i][0] = Poids[i][1] = BaseC->Poids[i];
}
Courbes = new Ligne *[1];
Courbes[0] = BaseC;
Mailler( LesPoints );
}
void SurfaceCylindre::CalculNbEF( int & nbefu, int
& nbefv )
{
nbefu = (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv = 1 + (int) fabs( (Hauteur / TailleArete + 0.5) );
}
void SurfaceCylindre::AfficherDefinition()
{
cout << "Nom de la Surface CYLINDRE= " << nom
<< " Hauteur du CYLINDRE= " << Hauteur <<endl;
}
void SurfaceCylindre::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) ) Mailler(LesPoints);
}
//=============================================================================
// Classe SurfaceCone
//=============================================================================
SurfaceCone::SurfaceCone(Lignes *LesLignes,Points
*LesPoints):Surface()
{
Nom nomP;
Ligne *Genere;
Point *PtI,*PtII;
int ncvals;
do
{
mpxInvite.VuInvite( "Selectionnez la droite generatrice ou tapez son nom :
");
if ( (Genere = LesLignes->Lignes::CliquerLigne()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
}
while ( (Genere->nbn!=1) || (Genere->degre!=1) );
mpxInvite.VuInvite( "Premier point definissant l'axe
de revolution : ");
if ( (PtI = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
PtII = PtI;
do
{
mpxInvite.VuInvite( "Second point definissant l'axe de revolution :
");
if ( (PtII = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
}
while ( PtII == PtI );
degreu = Genere->degre;
nbnu = Genere->nbn;
degrev = 2;
nbnv = 8;
R3 A,B,P,Q,V1,V2,W1,W2,Aux;
R3 Liste [nbnv+1];
R lambda;
A = PtI->XyzSommet[0];
B = PtII->XyzSommet[0];
V2 = B - A;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
//calculs intermediaires
P = Genere->PC[i]->XyzSommet[0];
V1 = P - A;
lambda = (V1,V2)/(V2,V2);
Q = A + lambda*V2;
W1 = P - Q;
if ((W1,W1)) //Point hors axe
{
Aux = W1^V2;
W2 = (Aux/Norme2(Aux))*Norme2(W1);
//Les 8 points du carre de controle du cercle
Liste[0] = Q+W1;
Liste[1] = Q+W1+W2;
Liste[2] = Q+W2;
Liste[3] = Q-W1+W2;
Liste[4] = Q-W1;
Liste[5] = Q-W1-W2;
Liste[6] = Q-W2;
Liste[7] = Q+W1-W2;
Liste[8] = Liste[0];
}
else
{
for (int k=0; k<=nbnv; k++)
Liste[k]=Q;
}
for (int j=0; j<=nbnv; j++)
{
NommerPoint(nomP);
PC[i][j] = new Pointxyz (nomP,Liste[j].x,Liste[j].y,Liste[j].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Genere->U[i];
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = V[2] = 0.0;
V[3] = V[4] = 0.25;
V[5] = V[6] = 0.5;
V[7] = V[8] = 0.75;
V[9] = V[10] = V[11] = 1.0;
//Existence donc creation des poids
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
if (Genere->Poids)
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((j%2)*RAC2_2+(!(j%2)))*Genere->Poids[i]; //regle du modulo pour
les poids du cercle
}
else
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=(j%2)*RAC2_2+(!(j%2));
}
Courbes = new Ligne *[1];
Courbes[0] = Genere;
Mailler( LesPoints );
}
void SurfaceCone::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu= (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv= nbefu;
}
void SurfaceCone::AfficherDefinition()
{
cout << "Nom de la Surface CONE= " << nom <<endl;
}
void SurfaceCone::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) )
Mailler(LesPoints);
}
//=============================================================================
// Classe Sphere
//=============================================================================
SurfaceSphere::SurfaceSphere(Lignes *LesLignes,Points *LesPoints):Surface()
{
Nom nomP,nomL,nomC;
Ligne *Genere;
Point *PtI,*PtII;
int ncvals;
mpxInvite.VuInvite( "Centre de la SPHERE : ");
//interface utilisateur
if ( (PtCentre = LesPoints->Points::CliquerPoint()) == NULL )
return;
mpxInvite.VuEffacerMemoirePx();
mpxInvite.VuInvite( "Rentrez le rayon de la SPHERE : ");
mpxInvite.lireR( ncvals, Rayon );
mpxInvite.VuEffacerMemoirePx();
R aux[6]; //noeuds du demi-cercle
aux[0]=aux[1]=aux[2]=0;
aux[3]=aux[4]=0.5;
aux[5]=1;
Nom nompc[5]; //Noms des points du demi-cercle
R poidscercle[5];//Poids du demi-cercle=poids du cercle entier
Point ** PP;
PP= new Point *[5]; //Points de controle du demi-cercle=points de controle du
cercle
NommerPoint(nomP);
PP[0]=new Pointxyz(nomP,PtCentre->XyzSommet[0].x-Rayon,
PtCentre->XyzSommet[0].y,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PP[0]);
NommerPoint(nomP);
PP[1]=new Pointxyz(nomP,PtCentre->XyzSommet[0].x-Rayon,
PtCentre->XyzSommet[0].y+Rayon,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PP[1]);
NommerPoint(nomP);
PP[2]=new Pointxyz(nomP,PtCentre->XyzSommet[0].x,
PtCentre->XyzSommet[0].y+Rayon,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PP[2]);
NommerPoint(nomP);
PP[3]=new Pointxyz(nomP,PtCentre->XyzSommet[0].x+Rayon,
PtCentre->XyzSommet[0].y+Rayon,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PP[3]);
NommerPoint(nomP);
PP[4]=new Pointxyz(nomP,PtCentre->XyzSommet[0].x+Rayon,
PtCentre->XyzSommet[0].y,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PP[4]);
for (int k=0; k<=4; k++)
{
nompc[k]=PP[k]->nom;
poidscercle[k]=(k%2)*RAC2_2+(1-(k%2));
}
NommerLigne(nomL);
Genere = new LigneNURBS(LesPoints,nomL,2,5,aux,nompc,poidscercle);
LesLignes->Ajouter1Ligne(Genere);
NommerPoint(nomP);
PtI=new Pointxyz(nomP,PtCentre->XyzSommet[0].x-Rayon,
PtCentre->XyzSommet[0].y,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PtI);
NommerPoint(nomP);
PtII=new Pointxyz(nomP,PtCentre->XyzSommet[0].x+Rayon,
PtCentre->XyzSommet[0].y,
PtCentre->XyzSommet[0].z);
LesPoints->Ajouter1Point(PtII);
degreu = 2;
nbnu = 4;
degrev = 2;
nbnv = 8;
R3 A,B,P,Q,V1,V2,W1,W2,Aux;
R3 Liste [nbnv+1];
R lambda;
A = PtI->XyzSommet[0];
B = PtII->XyzSommet[0];
V2 = B - A;
Rayon = 0;
PC = new Point **[1+nbnu];
for (int i=0; i<=nbnu; i++)
PC[i] = new Point *[1+nbnv];
for (int i=0; i<=nbnu; i++)
{
//calculs intermediaires
P = Genere->PC[i]->XyzSommet[0];
V1 = P - A;
lambda = (V1,V2)/(V2,V2);
Q = A + lambda*V2;
W1 = P - Q;
if ((W1,W1)) //Point hors axe
{
Aux = W1^V2;
W2 = (Aux/Norme2(Aux))*Norme2(W1);
Rayon = Max(Rayon,Norme2(W1));
//Les 8 points du carre de controle du cercle
Liste[0] = Q+W1;
Liste[1] = Q+W1+W2;
Liste[2] = Q+W2;
Liste[3] = Q-W1+W2;
Liste[4] = Q-W1;
Liste[5] = Q-W1-W2;
Liste[6] = Q-W2;
Liste[7] = Q+W1-W2;
Liste[8] = Liste[0];
}
else
{
for (int k=0; k<=nbnv; k++)
Liste[k]=Q;
}
for (int j=0; j<=nbnv; j++)
{
NommerPoint(nomP);
PC[i][j] = new Pointxyz (nomP,Liste[j].x,Liste[j].y,Liste[j].z);
LesPoints->Ajouter1Point(PC[i][j]);
}
}
U = new R [1+nbnu+1+degreu];
for (int i=0; i<=1+nbnu+degreu; i++)
U[i] = Genere->U[i];
V = new R [1+nbnv+1+degrev];
V[0] = V[1] = V[2] = 0.0;
V[3] = V[4] = 0.25;
V[5] = V[6] = 0.5;
V[7] = V[8] = 0.75;
V[9] = V[10] = V[11] = 1.0;
//Existence donc creation des poids
Poids = new R *[1+nbnu];
for (int i=0; i<=nbnu; i++)
Poids[i] = new R[1+nbnv];
if (Genere->Poids)
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=((j%2)*RAC2_2+(1-(j%2)))*Genere->Poids[i];
}
else
{
for (int i=0; i<=nbnu; i++)
for (int j=0; j<=nbnv; j++)
Poids[i][j]=(j%2)*RAC2_2+(1-(j%2));
}
Courbes = new Ligne *[1];
Courbes[0] = Genere;
Mailler( LesPoints );
}
void SurfaceSphere::CalculNbEF( int & nbefu, int &
nbefv )
{
nbefu= (int) ( Courbes[0]->LongueurNURBS() / TailleArete + 0.5 );
nbefv=(int)( 1 + fabs( ( (2*PI*Rayon) / TailleArete + 0.5) ) );
}
void SurfaceSphere::AfficherDefinition()
{
cout << "Nom de la Surface SPHERE= " << nom
<< " Nom du Point CENTRE= " << PtCentre->nom
<< " Rayon de la SPHERE= " << Rayon <<endl;
}
void SurfaceSphere::VerifierMaillage(Points *LesPoints)
{
if( (Courbes[0]->date > this->date) )
Mailler(LesPoints);
}
//============================================================================
// Classe Surfaces
//============================================================================
Surfaces::Surfaces()
{
P1Surface=NULL;
}
Surfaces::~Surfaces()
{
#ifdef VERBOSE
cout <<"Entrée dans Surfaces" <<endl;
#endif
if (Surfaces::P1Surface != NULL )
delete P1Surface;
#ifdef VERBOSE
cout << "Sortie de ~Surfaces" << endl;
#endif
}
Surface * Surfaces::RetrouverSurface( Nom NomSf, Surface *
& SfAvant ) // retourne NULL si pas retrouve
{
Surface * SfCourant;
SfAvant=NULL;
SfCourant = P1Surface;
while ( SfCourant != NULL )
{
if ( strcmp( SfCourant->nom, NomSf )==0 )
return SfCourant;
else
{
SfAvant=SfCourant;
SfCourant=SfCourant->PSuivant;
}
}
return NULL;
}
Surface * Surfaces::CliquerSurface( void )
// retourne le pointeur sur la surface la plus proche de la souris
// NULL si la surface pas retrouvee ou abandon demande
{
int notyev, nbc;
XPoint pxy, pxymin0={-1,-1}, pxymin;
Surface *SfCourant, *SfMin;
R3 xyz, xyzm, axyz;
R d, dmin;
Nom nomSurface;
//saisie a la souris de la poignee de la Surface
SaisieT:
mpxInvite.VuSourisTexte( notyev, nbc, pxy, nomSurface );
if( notyev == 0 ) { return NULL; } //Abandon demande
if( notyev < 0 ) //souris deplacee ou bouton enfonce non
relache
{
//PB ici en 3d
xyz.x = mpxPLSV.Vuxob2px( pxy.x ); //construction du point de R2 correspondant
xyz.y = mpxPLSV.Vuyob2px( pxy.y );
xyz.z = 0;
//recherche de la Surface actuelle la plus proche du clic souris
//============================================================
dmin = 1e100;
SfMin = NULL;
SfCourant = P1Surface;
while ( SfCourant != NULL )
{
//PB PML pour ligne et non pour surface
xyzm = SfCourant->PointMilieuSurface(); //la poignee de la ligne
if( mpxPLSV.visee == 2 ) //Visee 2d
{
d = Norme2_2( xyz - SfCourant->PointMilieuSurface() );
}
else
{ //Visee 3d Un point pxy clique est une droite dans R3
//recherche du point le plus proche de cette droite
// Passage en coordonnees axonometriques du point
mpxPLSV.Vuxyzaxo( xyzm, axyz );
//distance en XY axonometriques seulement
d = sqrt( pow( xyz.x-axyz.x, 2 )
+ pow( xyz.y-axyz.y, 2 ) );
}
if ( d < dmin ) { dmin = d; SfMin = SfCourant; }
SfCourant = SfCourant->PSuivant;
}
//Verification que SfMin n'est pas trop loin du point
clique
if( SfMin != NULL )
{
//PB PML pour ligne et non pour surface
xyzm = SfMin->PointMilieuSurface();
if( mpxPLSV.visee == 2 ) //Visee 2d
{
pxymin.x = mpxPLSV.Vunupxex( xyzm.x );
pxymin.y = mpxPLSV.Vunupxey( xyzm.y );
if( abs( pxymin.x - pxy.x ) > 123
|| abs( pxymin.y - pxy.y ) > 123 ) {SfMin = NULL;}
}
else
{ //Visee 3d
mpxPLSV.Vuxyzaxo( xyzm, axyz );
pxymin.x = mpxPLSV.Vunupxex( axyz.x );
pxymin.y = mpxPLSV.Vunupxey( axyz.y );
if( abs( pxymin.x - pxy.x ) > 123
|| abs( pxymin.y - pxy.y ) > 123 )
{SfMin = NULL;}
}
if ( SfMin == NULL ) //Surface min trop loin => Accrochage a effacer
{
if( (pxymin0.x!=-1) && (pxymin0.y!=-1) )
{
//suppression du mpxAccroche de fenetre_vu
//GXxor 2 fois de suite redonne la fenetre_vu initiale
mpxAccroche.VuCombinerMemoirePxDansFenetre( GXxor,
pxy0, mpxAccroche.largeurpx, mpxAccroche.hauteurpx,
pxymin0 );
pxymin0.x = -1;
pxymin0.y = -1; //reinitialisation a vide
}
}
}
if( SfMin == NULL ) { goto SaisieT; }
//Une Surface est suffisamment proche => son accrochage
est materialise
//si ce n'est deja fait
pxymin.x -= (int) mpxAccroche.largeurpx/2;
pxymin.y -= (int) mpxAccroche.hauteurpx/2;
if( (pxymin.x!=pxymin0.x) || (pxymin.y!=pxymin0.y) )
{
if( (pxymin0.x!=-1) && (pxymin0.y!=-1) )
{
//suppression du mpxAccroche de fenetre_vu
//GXxor 2 fois de suite redonne la fenetre_vu initiale
mpxAccroche.VuCombinerMemoirePxDansFenetre( GXxor,
pxy0, mpxAccroche.largeurpx, mpxAccroche.hauteurpx,
pxymin0 );
}
//ajout du mpxAccroche a fenetre_vu
pxymin0 = pxymin;
mpxAccroche.VuCombinerMemoirePxDansFenetre( GXxor,
pxy0, mpxAccroche.largeurpx, mpxAccroche.hauteurpx,
pxymin0 );
}
goto SaisieT;
}
else if( notyev == 1 ) //clic enfonce et relache d'un bouton de la souris
{
if( (pxymin0.x!=-1) && (pxymin0.y!=-1) )
{
//suppression du mpxAccroche de fenetre_vu
//GXxor 2 fois de suite redonne la fenetre_vu initiale
mpxAccroche.VuCombinerMemoirePxDansFenetre( GXxor,
pxy0, mpxAccroche.largeurpx, mpxAccroche.hauteurpx,
pxymin0 );
}
xyz.x = mpxPLSV.Vuxob2px( pxy.x ); //Construction du point de R2 correspondant
xyz.y = mpxPLSV.Vuyob2px( pxy.y );
xyz.z = 0;
//recherche de la Surface actuelle la plus proche du clic
souris
dmin = 1e100;
SfMin = NULL;
SfCourant = P1Surface;
while ( SfCourant != NULL )
{
if( mpxPLSV.visee == 2 ) //Visee 2d
{
//PB PML pour ligne et non pour surface
d = Norme2_2( xyz - SfCourant->PointMilieuSurface() );
}
else
{ //Visee 3d Un point pxy clique est une droite dans R3
//recherche du point le plus proche de cette droite
// Passage en coordonnees axonometriques du point
mpxPLSV.Vuxyzaxo( SfCourant->PointMilieuSurface(), axyz );
//distance en XY axonometriques seulement
d = sqrt( pow( xyz.x-axyz.x , 2 )
+ pow( xyz.y-axyz.y , 2 ) );
}
if ( d < dmin ) { dmin = d; SfMin = SfCourant; }
SfCourant = SfCourant->PSuivant;
}
//verification que SfMin n'est pas trop loin du point clique
if( SfMin != NULL )
{
if( mpxPLSV.visee == 2 ) //Visee 2d
{
if( abs( mpxPLSV.Vunupxex( SfMin->PointMilieuSurface().x ) - pxy.x ) > 123
|| abs( mpxPLSV.Vunupxey( SfMin->PointMilieuSurface().y ) - pxy.y ) > 123
)
{SfMin = NULL;}
}
else
{ //Visee 3d
mpxPLSV.Vuxyzaxo( SfMin->PointMilieuSurface(), axyz );
if( abs( mpxPLSV.Vunupxex( axyz.x ) - pxy.x ) > 123
|| abs( mpxPLSV.Vunupxey( axyz.y ) - pxy.y ) > 123 )
{SfMin = NULL;}
}
}
}
else if ( notyev == 2 )
{
Surface *SfAvant;
SfMin = RetrouverSurface( nomSurface, SfAvant ); //par son nom
}
return SfMin;
}
void Surfaces::Ajouter1Surface( Surface *PSurface )
{
Surface * SfAvant;
Surface * SfNom;
SfNom=RetrouverSurface( PSurface->nom, SfAvant );
if( SfNom != NULL )
{ // La Surface etait deja dans la liste => Destruction
if (SfAvant==NULL) // Pas de Surface avant
P1Surface=SfNom->PSuivant; // La suivante de SfNom devient la premiere
else
SfAvant->PSuivant=SfNom->PSuivant;// Le suivant d'avant est le suivant de
SfNom
SfNom->PSuivant=NULL;
delete [] SfNom->NoStEF; // La Surface SfNom est detruite
delete [] SfNom->XyzSommet;
}
// La Surface n'est pas dans la liste
PSurface->PSuivant = P1Surface; // La Surface devient la premiere
P1Surface=PSurface; // Surface de la liste
}
void Surfaces::AfficherSurfaces()
{
Surface *PCourant;
cout << endl;
cout << "Affichage des SURFACES:" << endl;
PCourant = P1Surface;
while( PCourant != NULL )
{
PCourant->AfficherDefinition();
PCourant = PCourant->PSuivant;
}
}
void Surfaces::TracerSurfaces( MemoirePx3d & mpx, Points *LesPoints )
{
Surface *PCourant;
PCourant = P1Surface;
while( PCourant != NULL )
{
PCourant->VerifierMaillage( LesPoints );
PCourant->TracerMaillage(mpx);
PCourant = PCourant->PSuivant;
}
}
void Surfaces::TracerPolyedre( MemoirePx3d & mpx )
{
Surface * SfCourant = P1Surface;
while ( SfCourant )
{
SfCourant->TracerPolyedre( mpx );
SfCourant = SfCourant->PSuivant;
}
}
//============================================================================
// Identique a Ligne::IntervalleNURBS, mais avec l'object explicite U
int IntervalleNURBS( R u, R *U, int nbn, int degre) {
int min, max, milieu;
if( u >= U[1+nbn] ) return nbn; //Cas particulier!
//recherche par dichotomie
min = degre;
max = nbn+1;
Iteration:
milieu = (min+max)/2;
if( u < U[milieu] ) {
max = milieu;
goto Iteration;
} else if( u >= U[milieu+1] ) {
min = milieu;
goto Iteration;
} else {
return milieu;
}
}
//============================================================================
// Identique a Ligne::ValeurBaseNURBS, mais avec l'objet explicite U
void ValeurBaseNURBS( int i, Z NbEtape, R u, R U[], R N[] )
{
int j,k;
R g[1+64], d[1+64];//numerateur gauche et droite de N[i,j]
R s, t; //denominateur=numerateur gauche + droite!
N[0] = 1.0;
for (j=1; j<=NbEtape; j++)
{
g[j] = u - U[i+1-j]; //numerateur gauche j
d[j] = U[i+j] - u; //numerateur droite j
s=0.0;
for (k=0; k<j; k++)
{
t = N[k] / ( d[k+1] + g[j-k] ); //la somme des indices vaut j+1
N[k]= s + d[k+1] * t;
s = g[j-k] * t;
}
N[j]=s;
}
}
rant = PCourant->PSuivant;
}
}
void Surfaces::TracerPolyedre( MemoirePx3d & mpx )
{
Surface * SfCourant = P1Surface;
while ( SfCourant )
{
SfCourant->TracerPolyedre( mpx );
SfCourant = SfCourant->PSuivant;
}
}
//============================================================================
// Identique a Ligne::IntervalleNURBS, mais avec l'object explicite U
int IntervalleNURBS( R u, R *U, int nbn, int degre) {
int min, max, milieu;
if( u >= U[1+nbn] ) return nbn; //Cas particulier!
//recherche par dichotomie
min = degre;
max = nbn+1;
Iteration:
milieu = (min+max)/2;
if( u < U[milieu] ) {
max = milieu;
goto Iteration;
} else if( u >= U[milieu+1] ) {
min = milieu;
goto Iteration;
} else {
return milieu;
}
}
//============================================================================
// Identique a Ligne::ValeurBaseNURBS, mais avec l'objet explicite U
void ValeurBaseNURBS( int i, Z NbEtape, R u, R U[], R N[] )
{
int j,k;
R g[1+64], d[1+64];//numerateur gauche et droite de N[i,j]
R s, t; //denominateur=numerateur gauche + droite!
N[0] = 1.0;
for (j=1; j<=NbEtape; j++)
{
g[j] = u - U[i+1-j]; //numerateur gauche j
d[j] = U[i+j] - u; //numerateur droite j
s=0.0;
for (k=0; k<j; k++)
{
t = N[k] / ( d[k+1] + g[j-k] ); //la somme des indices vaut j+1
N[k]= s + d[k+1] * t;
s = g[j-k] * t;
}
N[j]=s;
}
}
|