Salome HOME
This file is given from DESCARTES project
[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 /***************************************************************************
23 **  Class:   GLViewer_Geom
24 **  Descr:   
25 **  Module:  GLViewer
26 **  Created: UI team, 16.11.04
27 ****************************************************************************/
28
29 //#include <GLViewerAfx.h>
30 #include <GLViewer_Geom.h>
31
32 #define FAR_POINT 1e10  // Value used as a "very distant" co-ordinate
33 #define TOLERANCE 1e-3
34
35 //================================================================
36 // Function : GLViewer_Segment
37 // Purpose  : constructs a real segment bounded by two points
38 //================================================================
39 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt1, 
40                                     const GLViewer_Pnt& thePnt2 )
41 : myPnt1( thePnt1 ), 
42   myPnt2( thePnt2 )
43 {
44   myA = myPnt1.y() - myPnt2.y();
45   myB = myPnt2.x() - myPnt1.x();
46   myC = myPnt1.x() * myPnt2.y() - myPnt2.x() * myPnt1.y();
47 }
48
49 //================================================================
50 // Function : GLViewer_Segment
51 // Purpose  : constructs a ray starting at <thePnt> and directed
52 //            along positive X axis direction (or Y axis if vertical )
53 //================================================================
54 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt, 
55                                     const GLfloat theA, 
56                                     const GLfloat theB,
57                                     const GLfloat theC )
58 : myPnt1( thePnt ),
59   myA( theA ),
60   myB( theB ), 
61   myC( theC )
62 {
63   if ( fabs( myB ) < TOLERANCE )
64     myPnt2 = GLViewer_Pnt( myPnt1.x(), FAR_POINT );
65   else
66     myPnt2 = GLViewer_Pnt( FAR_POINT, - myA / myB * FAR_POINT - myC / myB );
67 }
68
69 //================================================================
70 // Function : GLViewer_Segment
71 // Purpose  : destructor, does nothing
72 //================================================================
73 GLViewer_Segment::~GLViewer_Segment()
74 {
75 }
76
77 //================================================================
78 // Function : HasIntersection
79 // Purpose  : detects intersection with segment <theOther>
80 //================================================================
81 bool GLViewer_Segment::HasIntersection( const GLViewer_Segment& theOther ) const
82 {
83   bool aRes = false;
84   GLfloat aDiv = myA * theOther.myB - myB * theOther.myA;
85   if ( fabs( aDiv ) > TOLERANCE )
86   {
87     GLfloat aX  = ( myB * theOther.myC - theOther.myB * myC ) / aDiv;
88     GLfloat aX11 = myPnt1.x() > myPnt2.x() ? myPnt2.x() : myPnt1.x();
89     GLfloat aX12 = myPnt1.x() > myPnt2.x() ? myPnt1.x() : myPnt2.x();
90     GLfloat aX21 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt2.x() : theOther.myPnt1.x();
91     GLfloat aX22 = theOther.myPnt1.x() > theOther.myPnt2.x() ? theOther.myPnt1.x() : theOther.myPnt2.x();
92
93     GLfloat aY  = ( myC * theOther.myA - theOther.myC * myA ) / aDiv;
94     GLfloat aY11 = myPnt1.y() > myPnt2.y() ? myPnt2.y() : myPnt1.y();
95     GLfloat aY12 = myPnt1.y() > myPnt2.y() ? myPnt1.y() : myPnt2.y();
96     GLfloat aY21 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt2.y() : theOther.myPnt1.y();
97     GLfloat aY22 = theOther.myPnt1.y() > theOther.myPnt2.y() ? theOther.myPnt1.y() : theOther.myPnt2.y();
98
99     if ( fabs( aX11 - aX12 ) > TOLERANCE )
100       aRes = aX11 < aX && aX < aX12;
101     else
102       aRes = aY11 < aY && aY < aY12;
103
104     if ( aRes )
105     {
106       if ( fabs( aX21 - aX22 ) > TOLERANCE )
107         aRes = aX21 < aX && aX < aX22;
108       else
109         aRes = aY21 < aY && aY < aY22;
110     }
111   }
112
113   return aRes;
114 }
115
116 //================================================================
117 // Function : GLViewer_Poly
118 // Purpose  : constructs a closed polygon from the given ordered list of points
119 //================================================================
120 GLViewer_Poly::GLViewer_Poly( const GLViewer_PntList* thePoints )
121 : myPoints( (GLViewer_PntList*)thePoints )
122 {
123 }
124
125 //================================================================
126 // Function : ~GLViewer_Poly
127 // Purpose  : destructor, <myPoints> mustn't be deleted here!
128 //================================================================
129 GLViewer_Poly::~GLViewer_Poly()
130 {
131 }
132
133 //================================================================
134 // Function : IsIn
135 // Purpose  : returns true if <thePnt> lies within this polygon
136 //================================================================
137 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt ) const
138 {
139   if ( !myPoints )
140     return false;
141
142   //cout << thePnt.x() << endl;
143   //cout << thePnt.y() << endl << endl;
144
145   int aNbInter = 0;
146   GLViewer_Segment aRay( thePnt, 0., 1., -thePnt.y() );
147
148   GLViewer_PntList::const_iterator it1 = myPoints->begin();
149   GLViewer_PntList::const_iterator it2 = myPoints->begin();
150   ++it2;
151   for ( ; it1 != myPoints->end(); ++it1, ++it2 )
152   {
153     if ( it2 == myPoints->end() )
154       it2 = myPoints->begin();
155     
156     if ( aRay.HasIntersection( GLViewer_Segment( *it1, *it2 ) ) )
157       aNbInter++;
158   }
159
160   return ( aNbInter % 2 == 1 );
161 }
162 /*
163 //================================================================
164 // Function : IsIn
165 // Purpose  : returns true if <thePnt> lies within this polygon
166 //================================================================
167 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt, const float tolerance ) const
168 {
169   if ( !myPoints )
170     return false;
171
172   float x = thePnt.x();
173   float y = thePnt.y();
174   bool res = false;
175   
176   GLViewer_Pnt p1( x - tolerance, y - tolerance );
177   GLViewer_Pnt p2( x - tolerance, y + tolerance );
178   GLViewer_Pnt p3( x + tolerance, y - tolerance );
179   GLViewer_Pnt p4( x + tolerance, y + tolerance );
180
181   res = ( IsInPnt( thePnt ) ||
182           IsInPnt( p1 ) || IsInPnt( p2 ) || IsInPnt( p3 ) || IsInPnt( p4 ) );
183
184   return res;
185 }
186 */
187 //================================================================
188 // Function : IsCovers
189 // Purpose  : returns true if <thePoly> covers this polygon
190 //================================================================
191 bool GLViewer_Poly::IsCovers( const GLViewer_Poly& thePoly ) const
192 {
193     if ( !myPoints || !thePoly.Count() )
194         return false;
195
196     GLViewer_PntList::const_iterator it = myPoints->begin();
197     
198     for ( ; it != myPoints->end(); ++it )
199     {
200         if( !thePoly.IsIn( *it ) )
201             return false;
202     }
203
204     return true;
205 }
206
207 //================================================================
208 // Function : IsCovers
209 // Purpose  : returns true if <theRect> covers this polygon
210 //================================================================
211 bool GLViewer_Poly::IsCovers( const GLViewer_Rect& theRect ) const
212 {
213     if ( !myPoints ) //needs check for <theRect>
214         return false;
215
216     GLViewer_PntList aList;    
217     GLViewer_PntList::iterator it = aList.begin();
218     
219     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.top() ) );
220     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.top() ) );
221     aList.insert( it, GLViewer_Pnt( theRect.right(), theRect.bottom() ) );
222     aList.insert( it, GLViewer_Pnt( theRect.left(), theRect.bottom() ) );
223
224     return IsCovers( GLViewer_Poly( &aList ) );
225 }
226
227 //================================================================
228 // Function : HasIntersection
229 // Purpose  : looks for any 
230 //================================================================
231 bool GLViewer_Poly::HasIntersection( const GLViewer_Segment& theSegment ) const
232 {
233   if ( !myPoints )
234     return false;
235
236   bool aRes = false;
237   GLViewer_PntList::const_iterator it1 = myPoints->begin();
238   GLViewer_PntList::const_iterator it2 = myPoints->begin();
239   ++it2;
240   for ( ; !aRes && it1 != myPoints->end(); ++it1, ++it2 )
241   {
242     if ( it2 == myPoints->end() )
243       it2 = myPoints->begin();
244     
245     aRes = theSegment.HasIntersection( GLViewer_Segment( *it1, *it2 ) );
246   }
247
248   return aRes;
249 }