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