Tableau 3d générique

Soyez le premier à donner votre avis sur cette source.

Snippet vu 13 087 fois - Téléchargée 34 fois

Contenu du snippet

Ce code permet de gérer des tableaux 3D génériques, c'est à dire des tableaux 3D soit d'int, de float, ou même d'autres types de données :
- Création d'un tableau 3D
- Suppression d'un tableau 3D
- Vérification d'existence
- Coût en espace mémoire du tableau 3D
- Initialisation à une valeur donnée
- ...

Source / Exemple :


/////////////////////////////////////////////////////////////////////////////////////////////////
//
// tab3D.h
//
// Description
//      Classe permettant de faire de créer et gérer des tableaux 3D.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef TAB3D_H
#define TAB3D_H

/////////////////////////////////////////// CLASSE //////////////////////////////////////////////
template<class T>
class Tableau3D
{
public :
	// Constructeur/Destructeur
	Tableau3D();
	Tableau3D(int _nx, int _ny, int _nz);
	~Tableau3D();

	// Gestion de tableaux 3D
	bool Create (int _nx, int _ny, int _nz);	// Création de tableaux 3D
	void Delete ();					// Suppression de tableaux 3D
	bool Existing ();				// Existence du tableau ?
	void Initialize (T val);			// Initialisation

	// Présence dans le tableau
	bool InTable (int _nx, int _ny, int _nz );	// La case est-elle dans le tableau ?
	bool InTableX (int _nx);			// La ligne x est-elle dans le tableau ?
	bool InTableY (int _ny);			// La ligne y est-elle dans le tableau ?
	bool InTableZ (int _nz);			// La ligne z est-elle dans le tableau ?

	// Taille en mémoire du tableau
	unsigned long Memoire ();

	// Variable de sortie
	T& Extract(int _nx, int _ny, int _nz );		// Extraire la valeur après vérif. d'existence
	T ***tab3D;

private:
	T *adr1;
	T **adr2;
	int nx,ny,nz;

	T temp;

};
/////////////////////////////////////////////////////////////////////////////////////////////////

/************************************************************************************************/
/********************************** Constructeur/Destructeur ************************************/
/************************************************************************************************/

/////////////////////////////////////////////////////////////////////////////////////////////////
// Constructeur de la classe Tab3D.
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> Tableau3D<T>::Tableau3D()
{
	Tableau3D<T>::adr1=0;		nx=0;
	Tableau3D<T>::adr2=0;		ny=0;
	Tableau3D<T>::tab3D=0;		nz=0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Constructeur de la classe Tab3D.
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> Tableau3D<T>::Tableau3D(int _nx, int _ny, int _nz)
{
	Tableau3D<T>::Create(_nx,_ny,_nz);
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Destructeur de la classe Tab3D.
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> Tableau3D<T>::~Tableau3D()
{
	Tableau3D<T>::Delete();
}

/************************************************************************************************/
/************************************ Gestion de tableaux 3D ************************************/
/************************************************************************************************/

/////////////////////////////////////////////////////////////////////////////////////////////////
// Création de tableaux 3D
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::Create(int _nx, int _ny, int _nz)
{
	// Création de tableau possible
	if (_nx>0 && _ny>0 && _nz>0)
	{
		// Création du tableau
		Tableau3D<T>::adr1  = new T[_nx*_ny*_nz];
		Tableau3D<T>::adr2  = new T*[_nx*_ny];
		Tableau3D<T>::tab3D = new T**[_nx];

		// Vérification
		if (Tableau3D<T>::adr1!=0 && Tableau3D<T>::adr2!=0 && Tableau3D<T>::tab3D!=0)
		{
			// Initialisation de la taille
			nx=_nx;		ny=_ny;		nz=_nz;

			for (int j=0; j<ny*nx; j++)
				Tableau3D<T>::adr2[j]  = Tableau3D<T>::adr1 + j*nz;
			for (int i=0; i<nx; i++)
				Tableau3D<T>::tab3D[i] = Tableau3D<T>::adr2 + i*ny;

			return true;
		}
	}

	// Pas de tableau créé
	Tableau3D<T>::Delete();
	return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Suppression de tableaux 3D
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> void Tableau3D<T>::Delete()
{
	if (!Tableau3D<T>::adr1)	delete[] Tableau3D<T>::adr1;
		Tableau3D<T>::adr1=0;	nx=0;
	if (!Tableau3D<T>::adr2)	delete[] Tableau3D<T>::adr2;
		Tableau3D<T>::adr2=0;	ny=0;
	if (!Tableau3D<T>::tab3D)	delete[] Tableau3D<T>::tab3D;
		Tableau3D<T>::tab3D=0;	nz=0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Existence de tableaux 3D
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::Existing()
{
	if (Tableau3D<T>::adr1!=0)	return true;
	else				return false;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Initialisation du tableau 3D
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> void Tableau3D<T>::Initialize(T val)
{
	for (int i=0; i<nx; i++)
	for (int j=0; j<ny; j++)
	for (int k=0; k<nz; k++)
		tab3D[i][j][k] = val;
}

/************************************************************************************************/
/*********************************** Présence dans le tableau ***********************************/
/************************************************************************************************/

/////////////////////////////////////////////////////////////////////////////////////////////////
// La case est-elle dans le tableau ?
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::InTable (int _nx, int _ny, int _nz )
{
	return (Tableau3D<T>::InTableX(_nx) &&
		Tableau3D<T>::InTableY(_ny) &&
		Tableau3D<T>::InTableZ(_nz));
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// La ligne x est-elle dans le tableau ?
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::InTableX (int _nx)
{
	if (_nx<0 ||_nx>=nx)	return false;
	else			return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// La ligne y est-elle dans le tableau ?
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::InTableY (int _ny)
{
	if (_ny<0 ||_ny>=ny)	return false;
	else			return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// La ligne z est-elle dans le tableau ?
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> bool Tableau3D<T>::InTableZ (int _nz)
{
	if (_nz<0 ||_nz>=nz)	return false;
	else			return true;
}

/************************************************************************************************/
/*********************************** Taille mémoire du tableau **********************************/
/************************************************************************************************/

/////////////////////////////////////////////////////////////////////////////////////////////////
// Taille en mémoire du tableau
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> unsigned long Tableau3D<T>::Memoire()
{
	int POINTEUR=4;
	unsigned long M = nx*ny*nz*sizeof(T) + POINTEUR		// Taille de adr1
			+ nx*ny*POINTEUR     + POINTEUR		// Taille de adr2
			+ nx*POINTEUR	     + POINTEUR;	// Taille de adr2

	return M;
}

/************************************************************************************************/
/******************************** Extraction de données du tableau ******************************/
/************************************************************************************************/

/////////////////////////////////////////////////////////////////////////////////////////////////
// Extraire une donnée du tableau après vérification d'existence
/////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> T& Tableau3D<T>::Extract(int _nx, int _ny, int _nz)
{
	if (Tableau3D<T>::adr1!=0)	return tab3D[_nx][_ny][_nz];
	else				return temp;
}
	

#endif

A voir également

Ajouter un commentaire Commentaires
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
5
Pour l'allocation avec les 3 boucles imbriquées. C'est ce que tu dis oui, mais ca ne change absolument rien :) simplement cette facon de faire me semble (à moi) plus intuitive :)

Pour les exceptions, il y a de nombreuses façon plus ou moins évoluées. La plus simple consiste tout d'abord à créer une classe Cexception qui sert à toutes les exceptions. A chaque fois qu'on créer une exception, on créé un objet Cexception. Cette classe n'a besoin que du strict minimum:

class Cexception
{
public:
Cexception(const std::string & _file, unsigned int _line, const std::string & _message);
Cexception(const Cexception & _which);
~Cexception();

std::string Msg()
{
std::ostringstream oss;
oss << "Exception : " << this->file << " : " << this->line << " : " << this->message;
return oss.str();
} // retourne le message d'erreur construit à partir des différentes données

private:
std::string message;
std::string file;
unsigned int line;
};

Et donc ta fonction extract devient par exemple:
# template<class T> T& Tableau3D<T>::Extract(int _nx, int _ny, int _nz) throw (Cexception)
# {
# if (Tableau3D<T>::adr1 == 0) throw Cexception(__FILE__,__LINE__,"Tableau non initialisé");
# if ( _nx, _ny, _nz, ne sont pas correct alors) throw Cexception(__FILE__,__LINE__,"Indice de tableau invalide");
// des qu'une exception est levée la fonction est interrompue.

# // si aucune exception n'a été levée alors
# return return tab3D[_nx][_ny][_nz];
# }


et en fait tu appelles cette fonction de la facon suivante:
try
{
ton_tableau.Extract(...):
}
catch (const Cexception & err) // si une exception est levée, la fonction s'arrete et le pc vient ici.
{
std::cout << "Une exception a eu lieu : " << std::endl << err.Msg() << std::endl;
// donc ici, le déroulement normal du programme est arrêté, il faut agir en conséquence. Ca veut vouloir dire, libérer des objets dynamiques qui auraient été alloués, etc ...
}

Bon c'est le plus simple que tu puisses faire. Mais renseigne toi sur le net. Il faut notamment créer plusieurs types d'exception. Tu créer par exemple une classe abstraite Cexception, et plein d'exceptions qui en dérivent: E_range_error, E_array_not_initialized, etc...

Une chose utile a savoir, le bloc try catch est facultatif, mais si tu le mets pas et qu'il exception est levée, le programme se ferme brutalement.

Note que avant de se fermer brutalement, tu peux définir une fonction à éxécuter:
std::set_terminate(&Fonction_a_executer_avant_fermeture);
Cette fonction sera donc appelé, si l'exception n'a pas trouvé de bloc catch.

Enfin regarde sur le net. L'aide est abondante. Mais j'ai mis du temps a comprendre :)
Messages postés
26
Date d'inscription
vendredi 8 avril 2005
Statut
Membre
Dernière intervention
31 janvier 2008

Ok, je te remercie pour tes commentaires, car cela va beaucoup me servir pour tous mes fichiers de mon projet. Mais il me reste encore deux petite questions :

- Pourquoi penses-tu qu'utiliser 3 boucles for imbriquées est mieux ? je pense qu'à la fin, on alloue autant d'espace mémoire. Je pense que dans ton cas, tu alloues d'abord _nz pointeurs, et pour chacun des ces pointeurs, tu alloues _ny pointeurs, et enfin pour chaque pointeur que tu viens de créer, tu alloues _nx valeurs de <T>. Est cela ?

- Pour l'utilisation d'exceptions, je ne sais pas trop faire et je ne vois pas ce que tu veux dire. Peux tu m'expliquer un peu stp ?

Pour la surcharge, je vais y travailler (je sais surcharger l'opérateur =, mais je n'ai jamais faire avec (x,x,x), je vais donc m'y mettre ). Si tu as d'autres idées à proposer, je suis partant.

A++
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
5
# template<class T> Tableau3D<T>::Tableau3D()
# {
# Tableau3D<T>::adr1=0; nx=0;
# Tableau3D<T>::adr2=0; ny=0;
# Tableau3D<T>::tab3D=0; nz=0;
# }

Pouquoi "Tableau3D<T>::" ? Utilise plutot "this":
# template<class T> Tableau3D<T>::Tableau3D()
# {
# this->adr1=0; nx=0;
# this->adr2=0; ny=0;
# this->tab3D=0; nz=0;
# }

Enfin ca change rien. Mais c'est étonnant :)

A part ca, en ce qui concerne cette fonction:
# template<class T> T& Tableau3D<T>::Extract(int _nx, int _ny, int _nz)
# {
# if (Tableau3D<T>::adr1!=0) return tab3D[_nx][_ny][_nz];
# else return temp;
# }

J'étais également embêté pour faire ce genre de chose, je savais pas quoi retourner comme objet lorsqu'il y avait une erreur. J'utilise maintenant systématiquement les exceptions pour faire ce genre de chose. Ca permet d'écrire proprement cette fonction. Car dans ton cas, il faut systématiquement vérifié que l'objet que l'on recoit est le bon et nom ce "temp".

Ta facon d'allouer ton tableau est bizarre, mais ca, c'est un avis purement personnel :) J'aurais fais 3 boucles for imbriquées.

Bon et enfin, tu pourrais surcharger quelques opérateurs de facon a rendre ceci possible:
tableau(1,5,4) = 8;

Aller ++
Messages postés
26
Date d'inscription
vendredi 8 avril 2005
Statut
Membre
Dernière intervention
31 janvier 2008

Dites moi ce que vous en pensez et surtout ce que je pourrais rajouter à ce code, afin de le rendre utilisable par tout utilisateur voulant utiliser de tel tableau, et pourquoi pas pour une énumération spatiale quelconque. S'il y a de tels utilisateurs, n'hésitez pas à vous faire connaitre, car je travaille sur un gros projet s'intitulant : "Représentation multirésolution et déformation d'objets définis par énumération spatiale" dans le cadre de la sculpture virtuelle sur des objets purement volumique, pour ma thèse.

PS : si les ondelettes 3D de Haar vous disent quelques choses, pouvez vous me suggérer quelques idées ? Je ne peux pas en dire beaucoup pour l'instant, mais je vous donnerai quelques références d'articles que je publie pour que vous en fassiez connaissance.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.