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