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

 C++ Discussion :

Coder une paire de points aléatoire sur un volume


Sujet :

C++

  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Points : 2
    Points
    2
    Par défaut Coder une paire de points aléatoire sur un volume
    Bonjour à tous,

    Je débute en langage C++ et j'aurais besoin d'un coup de pouce de votre part, pour un code.

    Je souhaite pouvoir calculer la perte d'énergie d'une particule traversant un volume. J'ai déjà la partie du code qui calcule l'énergie perdue. Ce dont j'ai besoin est la modélisation du volume et des points d'entrées et sorties de la particule.

    Plus clairement, l'idée où je bloque est la suivante :

    - créer un repère cartésien
    - créer une boite, en forme de parallépipède, composée de 6 faces centrée sur le repère
    - Un point de coordonnées (x1,y1) sera généré aléatoirement sur une des 6 faces
    - Un second point de coordonnées (x2,y2) sera aussi généré aléatoirement sur une des 6 faces
    - Un segment sera tracé entre ces deux points


    Voici l'ébauche algorithmique du programme :

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    double Dim_BOX[3];
     
    //Définition de la boite :
     
    Dim_BOX[0] = 10 ; // axe x
    Dim_BOX[1] = 10 ; // axe y
    Dim_BOX[2] = 500 ; //axe z
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 1
    x1_face1 = rand() % Dim_BOX[0] ;
    y1_face1 = rand() % Dim_BOX[2] ;
    x2_face1 = rand() % Dim_BOX[0] ;
    y2_face1 = rand() % Dim_BOX[2] ;
     
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 2
    x1_face2 = rand() % Dim_BOX[0] ;
    y1_face2 = rand() % Dim_BOX[2] ;
    x2_face2 = rand() % Dim_BOX[0] ;
    y2_face2 = rand() % Dim_BOX[2] ;
     
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 3
    x1_face3 = rand() % Dim_BOX[1] ;
    y1_face3 = rand() % Dim_BOX[2] ;
    x2_face3 = rand() % Dim_BOX[1] ;
    y2_face3 = rand() % Dim_BOX[2] ;
     
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 4
    x1_face4 = rand() % Dim_BOX[1] ;
    y1_face4 = rand() % Dim_BOX[2] ;
    x2_face4 = rand() % Dim_BOX[1] ;
    y2_face4 = rand() % Dim_BOX[2] ;
     
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 5
    x1_face5 = rand() % Dim_BOX[0] ;
    y1_face5 = rand() % Dim_BOX[1] ;
    x2_face5 = rand() % Dim_BOX[0] ;
    y2_face5 = rand() % Dim_BOX[1] ;
     
     
    // Génération aléatoire des coordonnées (x1,y1) et (x2,y2) sur la face 6
    x1_face6 = rand() % Dim_BOX[0] ;
    y1_face6 = rand() % Dim_BOX[1] ;
    x2_face6 = rand() % Dim_BOX[0] ;
    y2_face6 = rand() % Dim_BOX[1] ;
    Le problème ensuite vient du fait que je ne vois pas comment je peux m'assurer que les 2 points (entrée et sortie) de la boite sont bien situés sur les faces du volume et comment tracer le segment entre ces 2 points ?

    Si quelque chose n'est pas clair, n'hésitez pas.

    Je vous remercie par avance pour votre contribution,

    Bien cordialement,

    Syuhkua

  2. #2
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Bonjour,

    tu veux réaliser ton travail en mode console ou tu compte utiliser une librairie graphique ? Tu programme en C ou en C++ ? Utilise tu la POO ?
    Sans librairie graphique tu ne pourra pas effectuer d'affichage 3D, donc pas d'affichage du segment. Par contre nous allons pouvoir calculer ses coordonnées.

    Créer un repère cartésien :
    Pour nous faciliter la vie nous allons créer une class Point3D :
    Point3D.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Point3d
    {
    private:
        double x;
        double y;
        double z;
    public
        Point3D();
        Point3D(double x, double y, double z);
     
        double getX() {return this->x;}
        double getY() {return this->y;}
        double getZ() {return this->z;}
    }
    Créer une boite, en forme de parallélépipède, composée de 6 faces centrée sur le repère :
    Une boite c'est quoi ? Un centre, une hauteur, une largeur et une longueur par exemple.
    Tu peut créer une class boite donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Boite
    {
    private:
        Point3D centre;
        double height;
        double width;
        double high;
    }
    Comment avoir un point sur une face ?
    On peut imaginer une méthode de la class Boite qui retourne le Point3D central d'une face.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Point3D getFace(int idFace);
    idFace est un nombre aléatoire entre 0 et 5.
    Nous avons donc un point sur une des faces. Bon d'après ton énoncé tu à beaucoup de chance car ce point aura forcement une composante nulle puisque la boite est centré sur l'origine.
    Tu n'a donc plus qu'a trouver la composante nulle et ne pas la modifier. Les deux autres composantes peuvent prendre des valeurs aléatoire comprises entre mois la largeur/2 et plus la largeur/2.
    Et voila tu a un point sur une face
    Même chose pour le deuxième point en faisant attention de ne pas prendre la même face !

    Pour le segment, on utilisera une droite paramétrique :
    droite = P1 + r(P2-P1); si 0<r<1 alors tu est dans la boite sinon tu est à l'extérieur.

    Voilou


    EDIT :
    Si tu veux que ton code fonctionne même si ta boite n'est pas centré, il te suffit d'effectuer une translation du centre de ta boite vers l'origine, faire les calcules et retranslater dans le sens inverse

  3. #3
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Salut Robinsondesbois,

    Merci de ta réponse. En m'inspirant de ce que tu as dit, j'ai réalisé le code suivant.

    Qu'en penses-tu ?


    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    int main(void)
    {
    	srand((unsigned)time(NULL));
     
    	Lecture_BB_muon(); // lecture des LET et Range des muons
     
     
    	Point3D Dim_BOX = { 10, 10, 500}, BeginMuon ;
     
     
     
     
    	/* Etape 2 : définition des faces du volume */
    	vector<Point3D> TabMuon;
     
    	// choix d'une position Random uniquement sur la face 1
    	BeginMuon.x = -Dim_BOX.x/2 + rand()/double(RANDMAX) * Dim_BOX.x;
    	BeginMuon.y =  0 ; 
    	BeginMuon.z = -Dim_BOX.z/2 + rand()/double(RANDMAX) * Dim_BOX.z; 
    	TabMuon.push_back(BeginMuon);
     
    	// choix d'une position Random uniquement sur la face 2
    	BeginMuon.x = -Dim_BOX.x/2 + rand()/double(RANDMAX) * Dim_BOX.x;
    	BeginMuon.y =  Dim_BOX.y;
    	BeginMuon.z = -Dim_BOX.z/2 + rand()/double(RANDMAX) * Dim_BOX.z;
    	TabMuon.push_back(BeginMuon);
     
    	// choix d'une position Random uniquement sur la face 3
    	BeginMuon.x =  Dim_BOX.x;
    	BeginMuon.y = -Dim_BOX.y/2 + rand()/double(RANDMAX) * Dim_BOX.y; 
    	BeginMuon.z = -Dim_BOX.z/2 + rand()/double(RANDMAX) * Dim_BOX.z; 
    	TabMuon.push_back(BeginMuon);
     
    	// choix d'une position Random uniquement sur la face 4
    	BeginMuon.x =  0 ;
    	BeginMuon.y = -Dim_BOX.y/2 + rand()/double(RANDMAX) * Dim_BOX.y; 
    	BeginMuon.z = -Dim_BOX.z/2 + rand()/double(RANDMAX) * Dim_BOX.z; 
    	TabMuon.push_back(BeginMuon);
     
    	// choix d'une position Random uniquement sur la face 5
    	BeginMuon.x = -Dim_BOX.x/2 + rand()/double(RANDMAX) * Dim_BOX.x;
    	BeginMuon.y = -Dim_BOX.y/2 + rand()/double(RANDMAX) * Dim_BOX.y;
    	BeginMuon.z = 0 ;
    	TabMuon.push_back(BeginMuon);
     
    	 // choix d'une position Random uniquement sur la face 6
    	BeginMuon.x = -Dim_BOX.x/2 + rand()/double(RANDMAX) * Dim_BOX.x;
    	BeginMuon.y = -Dim_BOX.y/2 + rand()/double(RANDMAX) * Dim_BOX.y;
    	BeginMuon.z =  Dim_BOX.z; 
    	TabMuon.push_back(BeginMuon);
     
     
    	/* Etape 3 : création du segment entre les points d'incidence et de sortie de la particule dans le volume */
    	float dx, dy, dz, dist;
    	// Equation paramétrée 
    	for(int i = 0; i < TabMuon.size(); i++)
    	{
    		for(int j=0; j < TabMuon.size(); j++)
    		{
    			if(i != j)
    			{
    				for(int k = 0; k < 14 ; k++)
    				{
    				dx = TabMuon[i].x - TabMuon[j].x;
    				dy = TabMuon[i].y - TabMuon[j].y;
    				dz = TabMuon[i].z - TabMuon[j].z;
    				dist = sqrt(dx*dx + dy*dy + dz*dz);
    				//Eperdu[i] = NRJmuon[i] - EpourEiApresDist(NRJmuon[i], Dim_BOX.z);
    				Eperdu[k] = NRJmuon[k] - EpourEiApresDist(NRJmuon[k], dist);
    				printf("\nEi = %.2le MeV\tDepot = %.2le MeV\t(cad %.2lf fC)\n", NRJmuon[k], Eperdu[k], Eperdu[k] * 44.6);
    				}
    			}
    		}
    	}
     
    return 0 ;
     
    }

  4. #4
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Bonjour,

    Ton code génère 6 points aléatoire (1 par face) et calcul les distance entre tous ces points. Ne voulais tu pas seulement deux points ?
    Quel est le cadre de ce projet ? C'est pour progresser en C++ ou c'est pour faire des calculs d'énergie ?
    Si c'est pour progresser en C++ peut-tu nous envoyer tous ton code pour qu'on puisse avoir une critique plus poussée.

    Par exemple je ne sais pas comment tu à codé ces fonctions/objets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Lecture_BB_muon(); // lecture des LET et Range des muons
     
     
    	Point3D Dim_BOX = { 10, 10, 500}, BeginMuon ;
    Sinon ce code me semble relativement propre?

  5. #5
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    L'objectif de se programme est de modéliser de manière simple le dépot d'énergie d'une particule.

    Effectivement tu as raison, je voudrais calculer et afficher uniquement le dépot d'énergie pour un seul rayon entre deux points (un d'entrée et un de sortie) du volume (j'inclue aussi le cas comme celui où les points sont sur la même face).

    Du coup, dans le code actuel je ne vois pas ce que je pourrais modifier dans ma triple boucle pour y arriver.

    Aurais-tu des idées ?

    Syuhkua

  6. #6
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Désolé pour cette réponse tardive,

    Alors, comment avoir seulement deux points : Tu génère deux valeur aléatoire u et v différente entre 0 et 6. Ses valeurs correspondrons aux indices des points sur lesquels tu va faire les calculs.
    Ensuite ton traitement devra ressembler à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for(int k = 0; k < 14 ; k++)
    {
    	dx = TabMuon[u].x - TabMuon[v].x;
    	dy = TabMuon[u].y - TabMuon[v].y;
    	dz = TabMuon[u].z - TabMuon[v].z;
    	dist = sqrt(dx*dx + dy*dy + dz*dz);
    	Eperdu[k] = NRJmuon[k] - EpourEiApresDist(NRJmuon[k], dist);
    	printf("\nEi = %.2le MeV\tDepot = %.2le MeV\t(cad %.2lf fC)\n", NRJmuon[k], Eperdu[k], Eperdu[k] * 44.6);
    }
    voili voilou

  7. #7
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Mars 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2014
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Merci de ta réponse Robinson.

    Mais si tu regardes le code, c'est ce que j'ai déja fait avec i et 6 non ?

    En fait pour la suite de mon projet la méthode va être un peu changée. Il est essentiel que la distribution des points soit isotrope. Donc que la génération des points soit équiprobable sur toute la sphère.
    Le plan est le suivant :

    1) Générer 2 points aléatoires sur la sphère centrée sur le centre du volume parallélépipédique

    2) Paramétrer le segment entre ces 2 points

    3) Tester si le segment traverse une des 6 faces du volume.

    4a) Si oui, alors la particule a bien traversé le volume. On détermine la distance entre les point d'entrée et de sortie sur la ou les faces du volume. Puis on calcule le dépot d'énergie le long de cette distance avec la fonction "Eperdu"

    4b) Si non, alors la particule n'a pas traversé le volume. Rien ne se passe.

    Là ou je bloque c'est entre le 2ème et 3ème point.

    Voilà ce que j'ai fait :


    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
    int main(void)
    {
    	srand((unsigned)time(NULL));
     
    	Lecture_BB_muon(); // lecture des LET et Range des muons
     
    	/* Etape 1 : creation de la boite centrée en 0, 0, 0 */
    	Point3D Dim_BOX = { 10, 10, 500}, BeginMuon ; 
    	vector<Point3D> TabMuonSphere, TabMuonFace;
     
     
    	/* Etape 2 : Centre et rayon de la sphere*/
    	/* Ici centre = {0, 0, 0}. Pour le rayon, si on definit la figure
    	par une liste de sommet S1, S2, S3..., on calculera la distance du point le plus
    	loin du centre i.e  R = max(||Si||) */ 
    	double dx = Dim_BOX.x/2, dy = Dim_BOX.y/2, dz = Dim_BOX.z/2;
    	double R = sqrt(dx*dx+ dy*dy + dz*dz);
     
    	/* Etape 2 : generation des points sur la sphere */
    	double theta, psi;
    	theta = rand()/(double)RAND_MAX*2*PI; // azimuth
    	psi = rand()/(double)RAND_MAX*PI; // latitude
    	BeginMuon.x = R*sin(psi)*cos(theta)  ; BeginMuon.y = R*sin(psi)*sin(theta); BeginMuon.z = R*cos(psi) ;
    	TabMuonSphere.push_back(BeginMuon);
     
    	theta = rand()/(double)RAND_MAX*2*PI; // azimuth
    	psi = rand()/(double)RAND_MAX*PI; // latitude
    	BeginMuon.x = R*sin(psi)*cos(theta)  ; BeginMuon.y = R*sin(psi)*sin(theta); BeginMuon.z = R*cos(psi) ;
    	TabMuonSphere.push_back(BeginMuon);

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 142
    Points : 109
    Points
    109
    Par défaut
    Pour ton test et sans faire de maths trop compliquées tu peux : tester si la droite est parallèle à une face (ce qui ne devrait presque jamais arriver) ou deux faces (encore plus rare...) sortir ces plans de la discussion suivante :
    calculer les coordonnées des (6 au max) points d intersections de la trajectoire de la particule avec les plan engendrés par les faces puis les virer s'ils ne sont pas sur la face. Il t'en restera soit 0 (pas d'intersection, soit 2).

    Par contre, si ta boite a une (ou pire deux) dimension(s) très petite(s) par rapport aux autres... ton 'tir' va rater très(-très) souvent ta boite !

    T’intéresses tu réellement aux rayons qui ne vont pas traverser ton volume ?
    Si la réponse est non, et si le plan que tu annonces n'est pas fixé, tu peux 'mimer' l'isotropie, avec :
    1) tirer au sort la face entrante en pondérant le tirage avec les aires des faces.
    2) tirer au sort un point au hasard (tirage uniforme) sur la face.
    3) tirer au sort la face sortante en pondérant le tirage avec les aires des traces (sur une sphère centrée sur le point choisi en 2)) des 5 faces candidates comme faces de sortie.
    4) tirer au sort un point sur la face de sortie choisie en 3) (tirage uniforme).
    C'est plus long mais ça laisse de côté la possibilité de rater la boite...

  9. #9
    Membre habitué Avatar de robinsondesbois
    Homme Profil pro
    Etudiant
    Inscrit en
    Avril 2012
    Messages
    171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Haute Loire (Auvergne)

    Informations professionnelles :
    Activité : Etudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2012
    Messages : 171
    Points : 173
    Points
    173
    Par défaut
    Bonjour,

    Pour générer un point aléatoire sur une sphère tu peut utiliser cette formule honteusement pompé sur wikipédia.
    x = r * cos(theta) * cos (phi)
    y = r * cos(theta) * sin(phi)
    z = r * sin(theta)
    r étant le rayon.

    Une fois que tu as tes deux points tu peut tester la collision entre un quad (carré) et une droite.

Discussions similaires

  1. Réponses: 8
    Dernier message: 09/05/2008, 21h08
  2. Réponses: 7
    Dernier message: 23/11/2007, 06h35
  3. Erreur aléatoire sur une fonction
    Par defluc dans le forum Firebird
    Réponses: 8
    Dernier message: 10/09/2007, 16h34
  4. Réponses: 2
    Dernier message: 27/03/2007, 18h58
  5. Requete sur une table qui pointe 2 fois sur une autre
    Par Satch dans le forum Langage SQL
    Réponses: 1
    Dernier message: 10/01/2006, 08h48

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