IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Template d'un constructeur d'une classe et pointeur


Sujet :

Langage C++

  1. #21
    Membre régulier Avatar de Nadd
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 160
    Points : 95
    Points
    95
    Par défaut
    Pour être honnête, je n'avais pas envie de devoir travailler avec des copies de points pour la triangulation, mais avec les points d'origine, ce qui implique de devoir travailler avec des fonctions qui permettent de n'utiliser que les deux premières composantes puisque la troisième n'est pas nulle ni négligeable pour le rendu final. Ou alors je n'ai toujours pas compris votre idée... Il s'agit bien de les copier, d'annuler l'une des composantes et de trianguler ?

  2. #22
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Ah, tu peux travailler sur des pointeurs / itérateurs sur la collection de ton nuage de points, ce qui évite la copie et permet en plus de garder une trace de la composante y, mais l'idée est de se dire que la composante y n'est, effectivement, pas négligeable pour le rendu final, mais n'intervient purement et simplement pas dans la triangulation.

    Il "suffit" donc que ta fonction de triangulation travaille avec les valeurs de x() et de z(), sans s'intéresser à celle de y(), et c'est tout

    Comme j'essayais de le dire la tout de suite, ce n'est pas parce que la composante y de ton point n'est pas utilisée qu'elle n'existe pas, bien au contraire... Il suffit "simplement" que tu décides de ne pas l'utiliser dans ton algorithme de triangulation
    [EDIT]
    Maintenant, cela peut peut etre impliquer le fait d'avoir une fonction "bis" de calcul de la normale qui pourrait etre proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    double normForTriangulation(vertex *u)
    (const Point & origin)
    {
        double result = (origin.x()*origin.x() +
                         origin.z()*origin.z());
        return sqrt(result);
    }
    si la prise en compte de la composante y occasionne des erreurs de calcul
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #23
    Membre régulier Avatar de Nadd
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 160
    Points : 95
    Points
    95
    Par défaut
    Il "suffit" donc que ta fonction de triangulation travaille avec les valeurs de x() et de z(), sans s'intéresser à celle de y(), et c'est tout.
    Effectivement, mais je trouvais plus esthétique d'effectuer les calculs sur des tableaux de coordonnées 2D avec des boucles plutôt que des appels des fonctions x() et y().

    Maintenant, cela peut peut etre impliquer le fait d'avoir une fonction "bis" de calcul de la normale qui pourrait etre proche de [...] si la prise en compte de la composante y occasionne des erreurs de calcul.
    En fait, il y a tout un tas d'autres fonctions qui nécessitent la même flexibilité que la fonction qui calcule la norme d'un vecteur : il y a aussi le produit scalaire de deux vecteurs, le produit vectoriel de deux vecteurs, la distance entre deux vecteurs, etc. Fonctions qui doivent fonctionner aussi bien en 2D qu'en 3D. L'avantage des templates, c'était justement d'avoir à éviter de dédoubler toutes ces fonctions qui font la même chose à une composante près.

  4. #24
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    A ce moment là, il devient peut etre intéressant de se rappeler ce que disait
    Citation Envoyé par David Wheeler
    all problems in computer science can be solved by another level of indirection .


    Ce n'est plus "point" qui se templatise, mais un foncteur qui sera spécialisé pour la récupération des valeurs, sous une forme proche de (on peut reprendre l'idée de ton énumération )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    template<int maxDim>
    struct getter;
    template <>
    struct getter<3>
    {
        enum {max=3};
        double get(Point const & p, int index) const
        {
             switch(index)
             {
                 case 0 :
                     result = p.x();
                     break;
                 case 1 :
                     result = p.y();
                     break;
                 case 2 :
                     result = p.z();
                     break;
             }
        }
    };template <>
    struct getter<2>
    {
        double get(Point const & p, int index) const
        {
             double result;
             switch(index)
             {
                 case 0 :
                     result = p.x();
                     break;
                 case 1 :
                     result = p.z();
                     break;
             }
        }
    };
    Et tu templatise, effectivement, les foncteurs qui t'intéressent, par exemple sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    template <int dim>
    struct normalizer
    {
        enum {dimCount = dim};
        double operator()(Point const & p)
        {
             double result = 0.0;
             for(int i = 0; i< dimCount; ++i)
             {
                 double temp = getter<dimCount>().get(p,i);
                 temp *=temp;
                 resut += temp;
             }
             return sqrt(result);
        }
    };
    De cette manière, tu dégage ta classe Point d'une responsabilité qu'il ne doit pas avoir (le fait de savoir si tu travailles dans une contexte 2D ou 3D) et tous les foncteurs susceptibles d'être adaptés en fonction du contexte pourront l'être
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #25
    Membre régulier Avatar de Nadd
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 160
    Points : 95
    Points
    95
    Par défaut
    J'adopte... à moitié !

    L'idée du foncteur est très intéressante ! Ayant implémenté le foncteur getter, j'ai tout de même préféré conserver l'aspect fonction template pour le calcule de la norme, de la distance, etc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<dimension dim>
    inline double norm(point *u)
    {
    	double sum = 0.;
    	for(int i = 0; i < dim; ++i)
    		sum += pow(getter<dim>().get(u, i), 2);
    	return sqrt(sum);
    };
    Dans votre proposition, quel est le rôle joué par l'énumération ?

    Le fait de dissocier le soucis de d'avoir si l'on travaille en 2D ou en 3D de la classe point me semble effectivement cohérent.

    Ceci dit, je me pose une dernière question : pourquoi ne pas intégrer à la classe point une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    double get(size_t index) const
    {
    	double result = 0.;
    	switch(index)
    	{
    	case 0:
    		result = x();
    		break;
    	case 1:
    		result = y();
    		break;
    	case 2:
    		result = z();
    		break;
    	}
    	return result;
    }
    Puisque dans ma triangulation, seules les coordonnées x() et y() m'intéressent, il suffirait d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(size_t i = 0; i < 2; ++i)
    {
    	double c = v->get(i);
    	// DO SOMETHING
    }
    Bien entendu, la technique du foncteur reste plus flexible puisqu'elle permet de cibler les coordonnées d'intérêt avec plus de robustesse.

    Merci beaucoup pour l'aide que vous m'avez apportée.

  6. #26
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Nadd Voir le message
    J'adopte... à moitié !

    L'idée du foncteur est très intéressante ! Ayant implémenté le foncteur getter, j'ai tout de même préféré conserver l'aspect fonction template pour le calcule de la norme, de la distance, etc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<dimension dim>
    inline double norm(point *u)
    {
    	double sum = 0.;
    	for(int i = 0; i < dim; ++i)
    		sum += pow(getter<dim>().get(u, i), 2);
    	return sqrt(sum);
    };
    Dans votre proposition, quel est le rôle joué par l'énumération ?
    C'est surtout une habitude qui permet, en cas de besoin, de disposer d'une constante de compilation qui représente la valeur de l'entier fournis en paramètre template

    Dans le cas présent, elle permet "juste" d'avoir un nom clairement défini dans la boucle
    Ceci dit, je me pose une dernière question : pourquoi ne pas intégrer à la classe point une fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    double get(size_t index) const
    {
    	double result = 0.;
    	switch(index)
    	{
    	case 0:
    		result = x();
    		break;
    	case 1:
    		result = y();
    		break;
    	case 2:
    		result = z();
    		break;
    	}
    	return result;
    }
    Parce que, la classe Point n'étant pas template, tu ne pourrais pas utiliser une boucle pour récupérer les coordonnées, or, j'ai cru comprendre que le fait d'avoir la composante y pourrait poser problème pour la triangulation
    Puisque dans ma triangulation, seules les coordonnées x() et y() m'intéressent, il suffirait d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for(size_t i = 0; i < 2; ++i)
    {
    	double c = v->get(i);
    	// DO SOMETHING
    }
    Ce sont les coordonnées x() et z() qui t'intéressent pour la triangulation, y() étant l'axe "vertical", non

    Cela impliquerait que tu devrait utiliser get(0) pour avoir x() et get(2) pour avoir z(), et c'est, justement, pour cela que je conseille une spécialisation de foncteur qui permet de n'avoir que x() et z() en get(0) et get(1)
    Bien entendu, la technique du foncteur reste plus flexible puisqu'elle permet de cibler les coordonnées d'intérêt avec plus de robustesse.
    Tout à fait...

    Avec l'énorme avantage que si, un jour, il faut envisager "une autre solution", il te suffira de créer la spécialisation qui convient

    Tu veilles donc à rester en mesure de respecter le fameux "OCP" (open close principle) qui est, faut il le rappeler, l'un des cinq principes vantés par les méthodes SOLID et autre agile
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #27
    Membre régulier Avatar de Nadd
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 160
    Points : 95
    Points
    95
    Par défaut
    Ce sont les coordonnées x() et z() qui t'intéressent pour la triangulation, y() étant l'axe "vertical", non ?
    Le format adopté par le fichier d'entrée est le format : X Y Z, où (X,Y) représentent les coordonnées dans le plan et Z l'élévation du point. Ce n'est pas standard, mais c'est la convention qui nous a été imposée.

    EDIT: Après réflexion, et puisque le programme le permet, nous avons décidé d'adopter la convention universelle. Après tout, cela n'implique que la modification de deux lignes de code (l'une pour le getter et l'autre pour la récupération des données).

    Encore une fois, merci beaucoup pour votre aide.

    Bien à vous,

    Nicolas.

  8. #28
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Nadd Voir le message
    Le format adopté par le fichier d'entrée est le format : X Y Z, où (X,Y) représentent les coordonnées dans le plan et Z l'élévation du point. Ce n'est pas standard, mais c'est la convention qui nous a été imposée.
    Ils sont malins, eux !!!

    Mais bon, parfois, on a des gens qui refusent la facilité
    EDIT: Après réflexion, et puisque le programme le permet, nous avons décidé d'adopter la convention universelle. Après tout, cela n'implique que la modification de deux lignes de code (l'une pour le getter et l'autre pour la récupération des données).
    Cela me semble beaucoup plus sage, d'autant plus que, autrement, il me semble que tu aurais du chipoter pour passer les coordonnées dans le bon ordre à openGL, non
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #29
    Membre régulier Avatar de Nadd
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 160
    Points : 95
    Points
    95
    Par défaut
    Cela me semble beaucoup plus sage, d'autant plus que, autrement, il me semble que tu aurais du chipoter pour passer les coordonnées dans le bon ordre à openGL, non ?
    Tout à fait !

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 11
    Dernier message: 26/02/2015, 01h20
  2. Prototype du constructeur d'une classe template
    Par Meseira dans le forum Langage
    Réponses: 11
    Dernier message: 05/01/2011, 08h47
  3. Réponses: 2
    Dernier message: 04/12/2005, 21h10
  4. Réponses: 5
    Dernier message: 20/11/2005, 11h15
  5. Réponses: 3
    Dernier message: 06/11/2005, 18h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo