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++Builder Discussion :

Sélection d'objets pour un logiciel de type AutoCAD


Sujet :

C++Builder

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut Sélection d'objets pour un logiciel de type AutoCAD
    Bonjour,

    Je souhaite développer un logiciel de CAD.
    Quel est le principe des sélections d'objet?
    Par exemple, comment sélectionner une ligne en un clic de souris n'importe où sur la ligne?

    Merci

  2. #2
    Membre expérimenté Avatar de 10_GOTO_10
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    887
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 887
    Points : 1 531
    Points
    1 531
    Par défaut
    Bon courage, c'est pas gagné...

    Il faut calculer la distance entre le clic souris et chaque ligne (problème de géométrie simple), puis prendre la plus proche.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Tu me confirmes ce que je pensais.
    Ce ne serait pas trop compliqué s'il n'y avait que des ligne...
    Merci

  4. #4
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Bonjour,

    je pense que tu devrais travailler en vectoriel.

    Donc une droite serait représentée par : OM = t.u
    ou u est un vecteur directeur et t un réel qui te permet de parcourir la droite

    Un segment serait représenté par : OM = t.u
    avec t cette fois borné ce qui te permet de parcourir seulement le segment

    Cela vaut en 2D comme en 3D. En 3D, s'ajoute aussi le problème de la projection de tes éléments sur un plan 2D (l'écran).

    Mettons que nous soyons en 2D.

    Tu cliques sur un point de ton segment : tu recupères un point M(Mx,My) (Mx et My replacé dans le repère Oxy);

    M appartient au segment OM=t.u (ou t est un reel borné et u(Ux, Uy)).

    si Mx / Ux = My / Uy et si tM = Mx / Ux appartient à l'interval qui limite t.

    (pour être plus cool sur le point cliqué tu peut faire un truc du style Mx / Ux ~ My / Uy comme ça t'est pas obligé de cliqué exactement sur le segment).

    Pour une droite, juste la 1ere condition te sera nécessaire (étant donné que t n'est pas borné pour une droite).

    Pour représenter un rectangle (ensemble de 4 segments agencés spécifiquement) et le sélectionner à partir d'un point d'un de ses cotés, tu n'as qu'a testé l'appartenance à 1 des 4 segments qui le constitue. (pour cela, crée toi une classe segment, une classe rectangle).

    Pour des formes plus complexes, essaie de te ratacher à des formes plus simples comme le segment, etc.

    Pour tester l'appartenance d'un point cliqué M(Mx, My) à un cercle de centre C(Cx,Cy) et de rayon R, tu compare la distance MC et R. (on reste en vectoriel).

    En 3D, c tout pareil. Tu as juste en plus la phase de conversion des coordonnées 2d de la souris en 3d...

    J'espère que je suis pas hors sujet.

    Flo.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Non seulement, ta solution n’est pas hors sujet, mais elle me semble très pertinente !

    Un détail : faut-il crée une structure ‘vecteur’ ( X, Y, angle, distance) ou existe-t-il un type de donnée?

    Connais-tu une adresse où on peut voir du code ?

    Merci beaucoup pour ton post.

  6. #6
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    En, complément de ce qu'à dit Flo. tu peux aussi consulter le Post-it
    de JEG et sa jAPI ! A consommer sans aucune modération !

    A titre perso, je travaille avec (x,y,z) dans le genre :

    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
    class T3DPoint
    {
    public :
    //Pour le sélectionner
    bool Sel;
    //Coordonnées 3D
    int x;
    int y;
    int z;
    //Coordonnées du point à l'écran
    //pour éviter, dans certains cas, d'avoir à tout calculer à chaque fois
    atx;
    aty;
    //etc..
    };
    A plus !

  7. #7
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Salut,

    tu n'as pas précisé si tu voulais travailler en 2D ou 3D.
    Je choisis donc la 2D (mais c'est généralisable).

    Si ton problème était le mien, la classe de base serait TCoords comme le souligne henderson (avec son T3DPoint) .

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class TCoords
    {
    public:
    int x;
    int y;
    TCoords(int new_x, int new_y);
    };
    Ensuite la classe TSegment , par exemple, est à mon sens fondamentale (en fait ça serait plus un TVecteur).
    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
     
    class TSegment
    {
    private:
       // vecteur directeur du segment calculé à la construction du segment 
       TCoords vecteur_directeur;
     
       // un des 2 points extremes du segment calculé à la construction du segment 
       TCoords premier_point_du_segment;
     
     public:
     
       // constructeur d'un TSegment défini par les coordonnées des points extremes premier_point et second_point
       TSegment(TCoords premier_point, TCoords second_point);
     
        // pour voir si un point fait parti du segment
        bool IsInsideSegment(TCoords point);
    };
    dans le *.cpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    TSegment::TSegment(TCoords premier_point, TCoords second_point)
    {
          premier_point_du_segment.x = premier_point.x;
          premier_point_du_segment.y = premier_point.y;
     
          vecteur_directeur.x = second_point.x - premier_point.x;
          vecteur_directeur.y = second_point.y - premier_point.y;
    }
    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
     
    bool TSegment::IsInsideSegment(TCoords point)
    {
          TCoords vecteur;
     
          // calcul du vecteur definit par point et premier_point_du_segment
          vecteur.x = point.x - premier_point_du_segment.x;
          vecteur.y = point.y - premier_point_du_segment.y;
     
           // calcul des 2 ratios (1 par axe). C'est le
           // Mx / Ux et My / Uy de tout a l'heure
           double tx = (double)vecteur.x /  (double)vecteur_directeur.x;
           double ty = (double)vecteur.y /  (double)vecteur_directeur.y;
     
            // on verifie qu'ils sont égaux à la tolérance prés (j'ai mis 0.1 mais à toi de voir quelle valeur convient le mieux). C'est le
           // Mx / Ux ~ My / Uy de tout a l'heure
           // sinon renvoie false
           if(abs(tx - ty) > 0.1)
              return false;
     
           // ensuite on vérifie le  tM = Mx / Ux qui doit appartenir à [0;1]
           // la le vecteur directeur du segment à la longueur du segment donc t est compris entre 0 et 1 (c plus simple comme ça)
           // sinon renvoie false
           if((tx > 1.0) || (tx < 0.0))
              return false;
     
           // point appartient bien au segment, renvoie true
           return true;
    }
    pour le TQuadrilatère (qui inclut le trapèze, le carré, le rectangle, le losange et le parallélograme)
    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
     
    class TQuadrilatère 
    {
    private:
        // 2 segments suffisent pour définir un quadrilatère et ses sous-sections
        // mais pour faire plus simple j'en mets 4
       TSegment cotes_opposes[4];
     
    public:
        // constructeur du'un qualdrilatère à partir de ses 4 sommets
        TQuadrilatère(TCoords points[4]);
     
         // verification si un point appartient bien qau quadrilatere
         bool IsPointOnQuadrilatere(TCoords point);
    };
    dans le *.cpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TQuadrilatère::TQuadrilatère(TCoords points[4])
    {
           cotes_opposes[0].x = points[0].x - points[1].x;
           cotes_opposes[1].x = points[1].x - points[2].x;
           cotes_opposes[2].x = points[2].x - points[3].x;
           cotes_opposes[2].x = points[3].x - points[0].x;
     
           // .... et pareil avec les .y
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    bool TQuadrilatère::IsPointOnQuadrilatere(TCoords point)
    {
          bool OnQuadrilatere = false;
     
          // verifie l'appartenance à 1 des 4 segments
          for(int iSegment = 0; iSegment < 4; iSegment++)
               OnQuadrilatere  |= cotes_opposes[iSegment].IsInsideSegment(point)
     
           return OnQuadrilatere;
     
    }

    Bon j'ai fait tout ça vite... mais le principe devrais t'aider pour commencer.
    Tu as là tout ce qu'il te faut pour les segments, carre, rectangle, trapeze etc...

    Ya plus qu'à.

    Une TForm, une TImage.

    Et c'est parti.

    Si je peux encore t'aider, n'hésite pas.

    Flo.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    UN TRES GRAND MERCI A TOUS!!!!

    Magnifique

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    un seul tout petit pb dans le code de Flo. : abs retourne un entier.


    Ligne à remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if(fabs(tx - ty) > 0.1)
    Sans oublier
    Sinon tout fonctionne à merveille. Du caviar!
    Merci encore.

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    Il y a aussi une autre solution qui reste vrai pour n'importe quel objet graphique,
    et qui consiste à sélectionner l'objet par le biais de ses sommets. Le choix entre
    déplacer le sommet ou déplacer l'objet peut alors être fixé à l'aide des touches alt
    ou ctrl du paramètre Shift de la OnMouseDown du Control (TForm, TPaintBox etc..).
    Si on suppose une représentation par vues (haut, bas, gauche... et 3D) pour des
    objets 3D, alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    bool __fastcall T3DPoint::HasFocus(int X, int Y)
    {
    //On travaille ici sur la position écran du point et non sur ses (x,y,z)
    int minx = atx - 3;
    int maxx = atx + 3;
    int miny = aty - 3;
    int maxy = aty + 3;
    return ((X >= minx) && (X < maxx) && (Y >= miny) && (Y < maxy)); 
    }
    Comme cette fonction est sollicitée par les objets graphiques pour chacun de leurs sommets,
    on en déduit l'objet qui est sélectionné mais aussi un sommet de l'objet en particulier.

    A noter que dans mon cas, j'avais opté pour une modélisation du cercle par (n) points, ce
    qui avait l'avantage de pouvoir représenter ce cercle sous n'importe quel angle, en 3D.
    Sans doute à ne pas faire mais existe t-il mieux ?

    On peut aussi utiliser des poignées en tant que sommets d'un rectangle dans lequel s'incrit
    l'objet graphique ou bien également en calculant son isobarycentre, et ce, toujours à partir
    des positions écran.

    Toujours faire attention également à l'ordre d'apparition des objets graphiques. Il peut
    arriver qu'un contour soit contenu dans un autre ! Le problème disparait avec la sélection
    des sommets sauf si deux objets ont, à un moment donné de leur représentation, une position
    écran identique pour l'un de leurs sommets, ce qui, en soi, est parfois judicieux d'exploiter !

    Bien entendu, tout dépend si l'utilisateur peut remodeler l'objet graphique, en modifiant
    la position d'un sommet, par exemple !

    A plus !

  11. #11
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Oui effectivement.
    Cela me semble même encore plus simple que ma 1ere solution.

    La construction des classes serait donc differente.
    On oublie TSegment puisque les objets graphiques sont définis par leurs sommets.

    Peut-être, pour une utilisation plus aisée, on peut même essayer de combiner les 2 représentations (de sorte à ne pas être limité aux sommets d'un objet, surtout si ils sont confondus).

    Pour le cercle (respectivement la sphère), on peut utiliser le carré (le cube) qui le contient. Du coup sélectionner un cercle ou une sphère revient à sélectionner un carré ou un cube (qu'on pourra représenter graphiquement par une couleur sombre pour qu'il n'altére pas la vue globale de la scène (voir même utiliser un checkbox pour afficher ou cacher ces boites englobantes)). On se ramène ainsi à un problème plus facile que le n points de henderson peut-être.

    Qu'en pensez-vous ?

    Flo.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Pour bien cerner la problématique, il ne faut pas penser la sélection uniquement comme une recherche de l'objet pointé, mais aussi comme un accrochage.
    Par exemple l'utilisateur doit pouvoir tracer une ligne d'un point à un autre qui est la projection perpendiculaire à un objet, ou qui est un point quelconque sur l'objet (accrochage "proche"). Dans ce cas, l'utilisateur ne pointera pas le sommet de l'objet mais la zonne de l'objet qui l'intéresse.

    Je pense que les solutions sont complémentaires:
    -la solution de Henderson pour les accrochages extrémités
    -la solution de Flo pour le reste (accrochage proche, perpendiculaire, centre, milieu...etc...)

    Le problème des objets confondus (ou si proches qu'ils semblent l'être) peut être résolu par la fonction "multipic": premier objet en surbrillance, passage au second par molette ou clic droit, validation de l'objet choisi par clic gauche.

  13. #13
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Et sinon par quelle méthode as-tu géré les cercles ?

    Plus j'y réfléchis et plus mon histoire de carré (ou cube) englobant me parait le meilleur compromis entre simplicité et efficacité pour sélectionner un cercle (ou une sphère). Avec un checkbox pour cacher ou afficher ces boites englobantes. Du coup cela te permettrais même de travailler avec des ellipses ou des ellipsoides.

    Tu aurais une classe TCercle qui hériterait de la classe TCarre (ou TQuadrilatere), tu déduis les membres hérités de TCarre (les 4 sommets du carre ou ses 4 segments / vecteurs) à partir du centre et du rayon du cercle, sachant que le coté du carré sera égal à la moitié du rayon, etc.

    Je suis curieux de voir le résultat final de ton travail (juste l'exe) si c'est possible

    Tiens nous au courant de ton avancement.

    Flo.

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Je vous tiendrai au courant.
    Mais c'est le début du début... j'essaie de rassembler les techniques avant de me lancer dans l'aventure.

    Je ne comprend pas bien ton histoire de TCercle fils de TCarre... pourquoi tout ça?
    Un cercle doit être reconnu (ta méthode par distance au centre me semble efficace) et doit proposer 5 poignées (le centre et 4 sur le cercle (droite, gauche, haut et bas)).

    Pour mon projet, en particulier, un cercle restera toujours un cercle (pas d'étirement). Et je pense m'orienter vers une décomposition en segment (compatibilité de formats et intégration de courbes dans des polylignes).

  15. #15
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Euh oui pardon autant pour moi,

    j'avais pas bien saisi ton post sur l'importance de l'accrochage. J'étais resté sur la simple sélection d'objets graphiques.

    D'où le drame ... .

    Mille pardons.

    A+.

    Flo.

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2004
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    ...ben, euh, yapadmal!!!
    Je suis confus.

    Ton aide m'a été précieuse et je réalise que je ne t'ai pas répondu: c'est bien de la 2D.

    Merci donc,
    Laurent

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Creation de type Objets pour projet en JDBC
    Par Nelmech dans le forum Schéma
    Réponses: 2
    Dernier message: 08/04/2013, 17h06
  2. Rech. Logiciel de type DeepFreeze pour Windows 7
    Par megamario dans le forum Autres Logiciels
    Réponses: 0
    Dernier message: 16/08/2011, 10h07
  3. Existe t il un type objet pour mysql
    Par une_tite_question dans le forum Requêtes
    Réponses: 4
    Dernier message: 09/04/2008, 14h49
  4. Structure Type pour un logiciel
    Par eclesia dans le forum Langage
    Réponses: 2
    Dernier message: 08/01/2007, 22h50
  5. [Tkinter] sélection d'objet pour déplacement
    Par airod dans le forum Tkinter
    Réponses: 7
    Dernier message: 18/05/2006, 09h40

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