Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / GLViewer / GLViewer_Geom.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  Author : OPEN CASCADE
23 //#include <GLViewerAfx.h>
24 //
25 #include "GLViewer_Geom.h"
26
27 #define FAR_POINT 1e10  // Value used as a "very distant" co-ordinate
28 #define TOLERANCE 1e-3
29
30 /*!
31   constructs a real segment bounded by two points
32 */
33 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt1, 
34                                     const GLViewer_Pnt& thePnt2 )
35 : myPnt1( thePnt1 ), 
36   myPnt2( thePnt2 )
37 {
38   myA = myPnt1.y() - myPnt2.y();
39   myB = myPnt2.x() - myPnt1.x();
40   myC = myPnt1.x() * myPnt2.y() - myPnt2.x() * myPnt1.y();
41 }
42
43 /*!
44   constructs a ray starting at <thePnt> and directed along positive X axis direction (or Y axis if vertical )
45 */
46 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt, 
47                                     const GLfloat theA, 
48                                     const GLfloat theB,
49                                     const GLfloat theC )
50 : myPnt1( thePnt ),
51   myA( theA ),
52   myB( theB ), 
53   myC( theC )
54 {
55   if ( fabs( myB ) < TOLERANCE )
56     myPnt2 = GLViewer_Pnt( myPnt1.x(), FAR_POINT );
57   else
58     myPnt2 = GLViewer_Pnt( FAR_POINT, - myA / myB * FAR_POINT - myC / myB );
59 }
60
61 /*!
62   destructor, does nothing
63 */
64 GLViewer_Segment::~GLViewer_Segment()
65 {
66 }
67
68 /*!
69   detects intersection with segment <theOther>
70 */
71 bool GLViewer_Segment::HasIntersection( const GLViewer_Segment& theOther ) const
72 {
73   bool aRes = false;
74   GLfloat aDiv = myA * theOther.myB - myB * theOther.myA;
75   if ( fabs( aDiv ) > TOLERANCE )
76   {
77     GLfloat aX  = ( myB * theOther.myC - theOther.myB * myC ) / aDiv;
78     GLfloat aX11 = myPnt1.x() > myPnt2.x() ? myPnt2.x() : myPnt1.x();
79     GLfloat aX12 = myPnt1.x() > myPnt2.x() ? myPnt1.x() : myPnt2.x();
80     GLfloat aX21 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt2.x() : theOther.myPnt1.x();
81     GLfloat aX22 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt1.x() : theOther.myPnt2.x();
82
83     GLfloat aY  = ( myC * theOther.myA - theOther.myC * myA ) / aDiv;
84     GLfloat aY11 = myPnt1.y() > myPnt2.y() ? myPnt2.y() : myPnt1.y();
85     GLfloat aY12 = myPnt1.y() > myPnt2.y() ? myPnt1.y() : myPnt2.y();
86     GLfloat aY21 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt2.y() : theOther.myPnt1.y();
87     GLfloat aY22 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt1.y() : theOther.myPnt2.y();
88
89     if ( fabs( aX11 - aX12 ) > TOLERANCE )
90       aRes = aX11 < aX && aX < aX12;
91     else
92       aRes = aY11 < aY && aY < aY12;
93
94     if ( aRes )
95     {
96       if ( fabs( aX21 - aX22 ) > TOLERANCE )
97         aRes = aX21 < aX && aX < aX22;
98       else
99         aRes = aY21 < aY && aY < aY22;
100     }
101   }
102
103   return aRes;
104 }
105
106 /*!
107   constructs a closed polygon from the given ordered list of points
108 */
109 GLViewer_Poly::GLViewer_Poly( const GLViewer_PntList* thePoints )
110 : myPoints( (GLViewer_PntList*)thePoints )
111 {
112 }
113
114 /*!
115   destructor, <myPoints> mustn't be deleted here!
116 */
117 GLViewer_Poly::~GLViewer_Poly()
118 {
119 }
120
121 /*!
122   \return true if <thePnt> lies within this polygon
123 */
124 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt ) const
125 {
126   if ( !myPoints )
127     return false;
128
129   //cout << thePnt.x() << endl;
130   //cout << thePnt.y() << endl << endl;
131
132   int aNbInter = 0;
133   GLViewer_Segment aRay( thePnt, 0., 1., -thePnt.y() );
134
135   GLViewer_PntList::const_iterator it1 = myPoints->begin();
136   GLViewer_PntList::const_iterator it2 = myPoints->begin();
137   ++it2;
138   for ( ; it1 != myPoints->end(); ++it1, ++it2 )
139   {
140     if ( it2 == myPoints->end() )
141       it2 = myPoints->begin();
142     
143     if ( aRay.HasIntersection( GLViewer_Segment( *it1, *it2 ) ) )
144       aNbInter++;
145   }
146
147   return ( aNbInter % 2 == 1 );
148 }
149 /*!
150   \return true if <thePnt> lies within this polygon
151 */
152 /*
153 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt, const float tolerance ) const
154 {
155   if ( !myPoints )
156     return false;
157
158   float x = thePnt.x();
159   float y = thePnt.y();
160   bool res = false;
161   
162   GLViewer_Pnt p1( x - tolerance, y - tolerance );
163   GLViewer_Pnt p2( x - tolerance, y + tolerance );
164   GLViewer_Pnt p3( x + tolerance, y - tolerance );
165   GLViewer_Pnt p4( x + tolerance, y + tolerance );
166
167   res = ( IsInPnt( thePnt ) ||
168           IsInPnt( p1 ) || IsInPnt( p2 ) || IsInPnt( p3 ) || IsInPnt( p4 ) );
169
170   return res;
171 }
172 */
173 /*!
174   \return true if <thePoly> covers this polygon
175 */
176 bool GLViewer_Poly::IsCovers( const GLViewer_Poly& thePoly ) const
177 {
178     if ( !myPoints || !thePoly.Count() )
179         return false;
180
181     GLViewer_PntList::const_iterator it = myPoints->begin();
182     
183     for ( ; it != myPoints->end(); ++it )
184     {
185         if( !thePoly.IsIn( *it ) )
186             return false;
187     }
188
189     return true;
190 }
191
192 /*!
193   \return true if <theRect> covers this polygon
194 */
195 bool GLViewer_Poly::IsCovers( const GLViewer_Rect& theRect ) const
196 {
197     if ( !myPoints ) //needs check for <theRect>
198         return false;
199
200     GLViewer_PntList aList;    
201     GLViewer_PntList::iterator it = aList.begin();
202     
203     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.top() ) );
204     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.top() ) );
205     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.bottom() ) );
206     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.bottom() ) );
207
208     return IsCovers( GLViewer_Poly( &aList ) );
209 }
210
211 /*!
212   \return true if polygon has intersection with segment or ray
213   \param theSegment - segment to check intersection
214 */
215 bool GLViewer_Poly::HasIntersection( const GLViewer_Segment& theSegment ) const
216 {
217   if ( !myPoints )
218     return false;
219
220   bool aRes = false;
221   GLViewer_PntList::const_iterator it1 = myPoints->begin();
222   GLViewer_PntList::const_iterator it2 = myPoints->begin();
223   ++it2;
224   for ( ; !aRes && it1 != myPoints->end(); ++it1, ++it2 )
225   {
226     if ( it2 == myPoints->end() )
227       it2 = myPoints->begin();
228     
229     aRes = theSegment.HasIntersection( GLViewer_Segment( *it1, *it2 ) );
230   }
231
232   return aRes;
233 }