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

Algorithmes et structures de données Discussion :

Dessin de la partie d'une ligne passant dans un rectangle


Sujet :

Algorithmes et structures de données

  1. #1
    Invité
    Invité(e)
    Par défaut Dessin de la partie d'une ligne passant dans un rectangle
    Alors voila, je développe actuellement un jeu en 2D en C++ avec SDL.
    Je suis en ce moment entrain de faire le grappin. Ce grappin est une ligne droite, entre deux points du monde.
    Le problème est pour dessiner cette ligne : en effet, seule la partie passant à l'intérieur de l'écran doit être dessinée. Pour cela, il me faut les deux extrémités de la ligne qui va donc être dessinée.

    Un schéma si c'est pas clair :


    Le repère est situé en haut à gauche, les X positifs dirigés vers la droite et les Y positifs dirigés vers le bas.

    Comment puis-je faire pour obtenir les coordonnées des deux points représentés en vert (point1 et point2), si je connais tout le reste ?

    Pour l'instant j'ai ça, mais ça marche pas :
    http://www.nomorepasting.com/paste.php?pasteID=41432

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    C'est une question d'algo, je déplace dans le forum correspondant.

    Concernant ton problème, il suffit d'avoir l'équation de ta droite.
    Et d'y substituer les coordonnées des 4 côtés de ton écran
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    point1.x = vPosEcran.x
    point1.y = (-a * point1.x) / b
     
    point2.y = vPosEcran.y
    point2.x = (-b * point2.y) / a
     
    ... (pareil pour point3 et point4)

  3. #3
    Invité
    Invité(e)
    Par défaut
    Oui, j'ai édité pour rajouter le lien vers mon code actuel...
    Mais ya un problème : quand l'un des points est dans l'écran (ou même les deux).

  4. #4
    Invité
    Invité(e)
    Par défaut
    Avec mes derniers tests, il paraîtrai que les coordonnées X et Y du deuxième point soient inversées dans certains cas
    Je vois pas d'où ça peut venir...
    Je vais encore devoir tout relire

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Faut commencer par le commencement : puisque tu as déjà écrit du code c'est que tu as un algorithme, quel est-il ?

  6. #6
    Invité
    Invité(e)
    Par défaut
    Je cherche d'abord si l'un des points est dans l'écran.
    Si oui, on a trouvé une (ou deux) extrémités de la droite.

    Si on a pas trouvé les deux, on continue :
    On calcule l'équation réduite ( y = a * x + b ) de la droite.

    On calcule l'intersection de cette droite avec la gauche, la droite, le haut puis le bas du rectangle de l'écran.

    Il y a un truc en plus : lorsqu'on a trouvé un point dans l'écran, on définit des limites sur les abscisses des points d'intersection. Si un point et à gauche et l'autre dans l'écran, il ne peut pas y avoir de collision avec le droite (logique).

    Apparement, c'est plutôt une erreur dans mon code que dans l'algorithme... je précise que si les deux points sont dans l'écran, ou tous les deux dehors, ça marche...

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Tu devrais faire des recherches sur le mot "clipping", c'est exactement ce que tu essaie de faire.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  8. #8
    Invité
    Invité(e)
    Par défaut
    J'ai rien trouvé d'interressant sur le "clipping".
    J'ai refait en partie mon algorithme, qui ne dessine plus rien du tout
    Il ne trouve qu'un point au lieu des deux (nécessaires pour tracer un segment).

    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
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    // Prototypes
    void drawLine(SDL_Surface * ,int ,int ,int ,int ,Uint32 );
    void dot(SDL_Surface * ,int ,int ,Uint32 );
     
    // Dessin du grappin
    //   PosEcran = Position du coin en haut à gauche de l'écran par rapport au monde
    //   TailleEcran = Taille de l'écran
    //   Perso = position du premier point du grappin par rapport au monde
    //   Grappin = position du deuxième point du grappin par rapport au monde
    //   decal_x = position de l'écran par rapport à l'écran
    void drawGrappin(   vecteur2D vPosEcran,   vecteur2D vTailleEcran   ,
                        f_vecteur2D vPerso,    f_vecteur2D vGrappin     ,
                        int decal_x                                     )
    {
     
        // Les deux extrémités de la partie à dessiner
        f_vecteur2D point[2];
     
        // A et B pour l'équation réduite, inter pour les points d'intersections
        double a,b,inter;
     
        // Limites de dessin : ce sont des segments et pas des droites
        double x_limit[2];
     
        if(point[0].x<point[1].x)
        {
            x_limit[0]=point[0].x;
            x_limit[1]=point[1].x;
        }
        else
        {
            x_limit[0]=point[1].x;
            x_limit[1]=point[0].x;
        }
     
        int etat=0;
        // Etats :
        //    0 : on a trouvé aucun point
        //    1 : on a trouvé un point
        //    2 : on a trouvé les deux points
     
        // ----------------------------------------------------------------------------------------------------
        // ---------- Dans l'écran ----------------------------------------------------------------------------
        // ----------------------------------------------------------------------------------------------------
        // Si le perso est dans l'écran
        if( (vPerso.x>vPosEcran.x) && (vPerso.y>vPosEcran.y)
         && (vPerso.x<vPosEcran.x+vTailleEcran.x)
         && (vPerso.y<vPosEcran.y+vTailleEcran.y) )
        {
            point[etat].x=vPerso.x;
            point[etat].y=vPerso.y;
            etat+=1;
        }
     
        // Si le grappin est dans l'écran
        if( (vGrappin.x>vPosEcran.x) && (vGrappin.y>vPosEcran.y)
              && (vGrappin.x<vPosEcran.x+vTailleEcran.x)
              && (vGrappin.y<vPosEcran.y+vTailleEcran.y) )
        {
            point[etat].x=vGrappin.x;
            point[etat].y=vGrappin.y;
            etat+=1;
        }
     
        // ----------------------------------------------------------------------------------------------------
        // ---------- Hors de l'écran -------------------------------------------------------------------------
        // ----------------------------------------------------------------------------------------------------
        if(etat<2)
        {
            // On calcule l'équation de la droite
            //   y = a * X + b
            a = (vGrappin.y-vPerso.y)/(vGrappin.x-vPerso.x);
            b = vPerso.y-vPerso.x*a;
     
     
            // Si on n'a pas encore les deux points
            if(etat<2)
            {
                // Si le segment passe par la gauche de l'écran
                if( (x_limit[0]<vPosEcran.x) && (vPosEcran.x<x_limit[1]) )
                {
                    // On trouve l'intersection avec la gauche du rectangle de l'écran
                    inter = a * vPosEcran.x + b;
     
                    // Si c'est dans le segment, alors on a trouvé l'un des points
                    if( (inter > vPosEcran.y) && (inter < vPosEcran.y+vTailleEcran.y) )
                    {
                        point[0].x = vPosEcran.x;
                        point[0].y = inter;
                        etat+=1;
                    }
                }
            }
     
            // Si on n'a pas encore les deux points
            if(etat<2)
            {
                // Si le segment passe par la gauche de l'écran
                if( (x_limit[0]<(vPosEcran.x+vTailleEcran.x)) && ((vPosEcran.x+vTailleEcran.x)<x_limit[1]) )
                {
                    // On cherche l'intersection avec la droite de l'écran
                    inter = a * (vPosEcran.x + vTailleEcran.x) + b;
     
                    // Si c'est dans le segment, on a trouvé l'un des points
                    if( (inter > vPosEcran.y) && (inter < vPosEcran.y+vTailleEcran.y) )
                    {
                        point[etat].x = vPosEcran.x + vTailleEcran.x;
                        point[etat].y = inter;
                        etat+=1;
                    }
                }
            }
     
            // Si on n'a pas encore les deux points
            if(etat<2)
            {
                // On cherche l'intersection avec le haut de l'écran
                inter = (vPosEcran.y - b) / a;
     
                // Si cette intersection ne dépasse pas les limites
                if( (x_limit[0]<inter) && (inter<x_limit[1]) )
                {
     
                    // Si c'est dans le segment, on a trouvé l'un des points
                    if( (inter > vPosEcran.x) && (inter < vPosEcran.x+vTailleEcran.x) )
                    {
                        point[etat].x = inter;
                        point[etat].y = vPosEcran.y;
                        etat+=1;
                    }
                }
            }
     
            // Si on n'a pas encore les deux points
            if(etat<2)
            {
                // On cherche l'intersection avec le bas de l'écran
                inter = (vPosEcran.y + vTailleEcran.y - b) / a;
     
                // Si cette intersection ne dépasse pas les limites
                if( (x_limit[0]<inter) && (inter<x_limit[1]) )
                {
                    // Si c'est dans le segment, on a trouvé l'un des points
                    if( (inter > vPosEcran.x) && (inter < vPosEcran.x+vTailleEcran.x) )
                    {
                        point[etat].x = inter;
                        point[etat].y = vPosEcran.y + vTailleEcran.y;
                        etat+=1;
                    }
                }
            }
        }
     
        // Si on a les deux points, on peut dessiner
        if(etat==2)
        {
            // Dessin
            //   On enlève les coordonnées du coin de l'écran,
            //   et on rajoute le décalage
            drawLine(sScreen,
                (int)point[0].x+decal_x-vPosEcran.x,
                (int)point[0].y-vPosEcran.y,
                (int)point[1].x+decal_x-vPosEcran.x,
                (int)point[1].y-vPosEcran.y,
                     SDL_MapRGB(sScreen->format,255,0,0)
                    );
        }
        else
            cout<<"\nBug ! Etat = "<<etat;
     
    }
     
    // Fonction qui dessine un pixel
    void dot(SDL_Surface * surf,int x,int y,Uint32 color)
    {
        SDL_Rect rect;
        rect.x=x;
        rect.y=y;
        rect.w=1;
        rect.h=1;
     
        SDL_FillRect(surf,&rect,color);
    }
     
    //  Fonction qui retourne max(abs(a),abs(b))
    int abs_max(int a,int b)
    {
        if(a<0)
            a=-a;
        if(b<0)
            b=-b;
        return (a<b)?b:a;
    }
     
    // Fonction pour tracer une ligne droite
    void drawLine(SDL_Surface * surf,int x1,int y1,int x2,int y2,Uint32 color)
    {
        int div,i;
     
        // Pos contient la position actuelle sur la ligne
        // Move contient le vecteur qui est ajouté à pos pour passer au pixel suivant
        f_vecteur2D pos,move;
     
        // Position de départ
        pos.x=x1;
        pos.y=y1;
     
        // Déplacement maxi
        move.x=x2-x1;
        move.y=y2-y1;
     
        // On divise ce déplacement par la plus grande différence de coordonnées
        div = abs_max(x2-x1,y2-y1);
        move.x=move.x/div;
        move.y=move.y/div;
     
        // Maintenant, on boucle DIV fois
        for(i=0;i<div;i+=1)
        {
            // Point
            dot(surf,(int)pos.x,(int)pos.y,color);
     
            // On avance
            pos.x+=move.x;
            pos.y+=move.y;
        }
    }

  9. #9
    Membre éclairé
    Avatar de Kangourou
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    579
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 579
    Points : 859
    Points
    859
    Par défaut
    Salut,

    t'as rien trouve d'interessant sur le clipping ? C'est exactement ton probleme, pourtant.

    Essaie avc "Line Clipping", ou "clip a line", mai s y'a des trucs.

    En voila deja un, qui marche pour des polygones :
    http://astronomy.swin.edu.au/~pbourke/geometry/cliplinetopoly/

    et un autre :
    http://wiki.daimi.au.dk/cgcourse/clipping_lines.wiki?cmd=get&anchor=clipping+lines

    A+

Discussions similaires

  1. déplacer une partie d'une ligne
    Par Empty_body dans le forum Linux
    Réponses: 2
    Dernier message: 26/02/2009, 14h58
  2. Recuperer une partie d'une ligne
    Par Loenix dans le forum GTK+ avec Python
    Réponses: 2
    Dernier message: 28/11/2008, 21h48
  3. Rendre cliquable une partie d'une ligne dans un tableau
    Par Flackou dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 12/09/2008, 11h09
  4. Réponses: 3
    Dernier message: 05/09/2008, 10h32
  5. Surligner une partie d'une ligne dans un CListCtrl
    Par DavidM_81 dans le forum MFC
    Réponses: 5
    Dernier message: 05/03/2008, 16h42

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