// ------------------------------------------------------------------------------------------------ // MODULE : PlutonCommun // LANGAGE : C++ // CREATEUR : Laurent SABORET // DATE : Mercredi 22 Septembre 1993 // DESCRIPTION : // COMMENTAIRE : // SCCSID : @(#)common_b.cpp 1.1 11:49:58 18 Dec 1996 // ---------------------------------------------------------------------------- // Copyright (c) 1999 Digital Imaging Group, Inc. // For conditions of distribution and use, see copyright notice // in Flashpix.h // ---------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------ #include "common.h" // ------------------------------------------------------------------------------------------------ // Includes // -------- #include "common_b.h" #include "numbers.h" // Constantes // ---------- // Variables // --------- // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ // Fonctions internes // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ // Methodes // ------------------------------------------------------------------------------------------------ // // La classe PositionMv // // Rq : for an unknown reason, CW C++ 1.1 (DR4) doesn't accept this function in PlutonCommun.h PositionMv::PositionMv(const PositionMv& p) { h = p.h; v = p.v; } int operator ==(const PositionMv& p1, const PositionMv& p2) { return (((p1.h - p2.h) < 0.0001) && ((p1.h - p2.h) > -0.0001) && ((p1.v - p2.v) < 0.0001) && ((p1.v - p2.v) > -0.0001)); } PositionMv operator +(const PositionMv& p1, const PositionMv& p2) { PositionMv retour; retour.h = p1.h + p2.h; retour.v = p1.v + p2.v; return retour; } PositionMv operator -(const PositionMv& p1, const PositionMv& p2) { PositionMv retour; retour.h = p1.h - p2.h; retour.v = p1.v - p2.v; return retour; } PositionMv operator *(const PositionMv& p, double a) { PositionMv retour; retour.h = (float) ((double) p.h * a); retour.v = (float) ((double) p.v * a); return retour; } // Rq : for an unknown reason, CW C++ 1.1 (DR4) doesn't accept this function in PlutonCommun.h PositionMv operator -(const PositionMv& p) { return p * (-1); } // Rq : for an unknown reason, CW C++ 1.1 (DR4) doesn't accept this function in PlutonCommun.h PositionMv operator *(double a, const PositionMv& p) { return p * a; } PositionMv operator /(const PositionMv& p, double a) { PositionMv retour; retour.h = (float) ((double) p.h / a); retour.v = (float) ((double) p.v / a); return retour; } // Rq : for an unknown reason, CW C++ 1.1 (DR4) doesn't accept this function in PlutonCommun.h PositionMv::operator Position() { Position p; p.h = (short)(h < -32000 ? -32000 : (h > 32000 ? 32000 : h)); p.v = (short)(v < -32000 ? -32000 : (v > 32000 ? 32000 : v)); return p; } // Rq : for an unknown reason, CW C++ 1.1 (DR4) doesn't accept this function in PlutonCommun.h PositionMv& PositionMv::operator =(const PositionMv& positionMv) { this->h = positionMv.h; this->v = positionMv.v; return *this; } // Rend le vecteur unitaire. Renvoie false si le vecteur est nul. Boolean PositionMv::Normalise() { double norme = Norme(); if (norme == 0.0) { return false; } else { (*this) = (*this) / norme; if (h == 1.0) v = (float) 0.0; else if (v == 1.0) h = (float) 0.0; return true; } } double Distance(const PositionMv& p1, const PositionMv& p2) { PositionMv p1p2 = p2 - p1; return p1p2.Norme(); } // // La classe VecteurMv // // Renvoie H, projection de p sur la droite portee par le segment // H appartient ou pas au segment. // -> -> -> -> // *abscisse_curviligne recoit ||p1 H|| / ||p1 p2|| (dans [0,1] si H appartient au segment) PositionMv VecteurMv::ProjeteSurDroite(const PositionMv& p, float* abscisse_curviligne) { double norme_p1p2; // Norme du vecteur p1p2 PositionMv u; // Vecteur directeur unitaire de p1 vers p2 PositionMv p1p; // Vecteur p1p PositionMv H; double p1p_scalaire_u; // (p1p | u) u = p2 - p1; norme_p1p2 = u.Norme(); u = u / norme_p1p2; p1p = p - p1; p1p_scalaire_u = (p1p | u); H = p1 + p1p_scalaire_u * u; *abscisse_curviligne = (float) (p1p_scalaire_u / norme_p1p2); return H; } // Renvoie H, projection de p sur le segment. // H appartient toujours au segment. // -> -> -> -> // *abscisse_curviligne recoit ||p1 H|| / ||p1 p2|| (dans [0,1]) PositionMv VecteurMv::ProjeteSurSegment(const PositionMv& p, float* abscisse_curviligne) { PositionMv H; H = ProjeteSurDroite(p, abscisse_curviligne); // Force H a appartenir au segment if (*abscisse_curviligne < 0) { H = p1; *abscisse_curviligne = (float) 0.0; } else if (*abscisse_curviligne > 1) { H = p2; *abscisse_curviligne = (float) 1.0; } return H; } // Calcule l'intersection avec la droite (point, vecteur) IntersectionVMV VecteurMv::IntersecteDroite(const PositionMv& pointDroite, const PositionMv& vecteurDroite, ptr_PositionMv pointTrouve) { float a1, b1, c1, a2, b2, c2, determinant; // Transforme les 2 droites sous la forme "a*x + by = c" a1 = p1.v - p2.v; b1 = p2.h - p1.h; c1 = p1.v*p2.h - p1.h*p2.v; a2 = vecteurDroite.v; b2 = - vecteurDroite.h; c2 = pointDroite.h*vecteurDroite.v - pointDroite.v*vecteurDroite.h; // Calcule le determinant du systeme de 2 equations determinant = a1*b2 - a2*b1; // Cas particulier : si le determinant est nul if (FLOAT_NUL(determinant)) { if (FLOAT_NUL(a1*c2 - a2*c1)) return VMV_UneDroite; // les 2 droites sont confondues else return VMV_Vide; // les 2 droites sont paralleles } // Inverse le systeme pointTrouve->h = (b2*c1 - b1*c2) / determinant; pointTrouve->v = (a1*c2 - a2*c1) / determinant; // L'intersection des 2 droites appartient-elle au segment ? if ( (((*pointTrouve)-p1) | ((*pointTrouve)-p2)) <= 0 ) return VMV_UnPoint; else return VMV_Vide; } // // La classe RectangleMv // RectangleMv::RectangleMv(const PositionMv& coin1, const PositionMv& coin2) { if (coin1.h <= coin2.h) { coin_inf.h = coin1.h; coin_sup.h = coin2.h; } else { coin_inf.h = coin2.h; coin_sup.h = coin1.h; } if (coin1.v <= coin2.v) { coin_inf.v = coin1.v; coin_sup.v = coin2.v; } else { coin_inf.v = coin2.v; coin_sup.v = coin1.v; } } RectangleMv::RectangleMv(float x1, float y1, float x2, float y2) { if (x1 <= x2) { coin_inf.h = x1; coin_sup.h = x2; } else { coin_inf.h = x2; coin_sup.h = x1; } if (y1 <= y2) { coin_inf.v = y1; coin_sup.v = y2; } else { coin_inf.v = y2; coin_sup.v = y1; } } RectangleMv operator +(const RectangleMv& r1, const RectangleMv& r2) { RectangleMv r; r = r1; if (r.coin_inf.h > r2.coin_inf.h) r.coin_inf.h = r2.coin_inf.h; if (r.coin_inf.v > r2.coin_inf.v) r.coin_inf.v = r2.coin_inf.v; if (r.coin_sup.h < r2.coin_sup.h) r.coin_sup.h = r2.coin_sup.h; if (r.coin_sup.v < r2.coin_sup.v) r.coin_sup.v = r2.coin_sup.v; return r; } RectangleMv& RectangleMv::operator +=(const RectangleMv& r) { if (coin_inf.h > r.coin_inf.h) coin_inf.h = r.coin_inf.h; if (coin_inf.v > r.coin_inf.v) coin_inf.v = r.coin_inf.v; if (coin_sup.h < r.coin_sup.h) coin_sup.h = r.coin_sup.h; if (coin_sup.v < r.coin_sup.v) coin_sup.v = r.coin_sup.v; return *this; } // Indique si l'intersection de 2 rectangles est non vide Boolean RectangleMv::Intersecte(const RectangleMv& r) const { Boolean retour; // r est-il a gauche de this ? if (r.coin_inf.h > this->coin_sup.h) retour = false; // a droite ? else if (r.coin_sup.h < this->coin_inf.h) retour = false; // plus haut ? else if (r.coin_sup.v < this->coin_inf.v) retour = false; // plus bas ? else if (r.coin_inf.v > this->coin_sup.v) retour = false; else retour = true; return retour; } // ------------------------------------------------------------------------------------------------ // Fonctions externes // ------------------------------------------------------------------------------------------------