1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // Author : OPEN CASCADE
24 //#include <GLViewerAfx.h>
26 #include "GLViewer_Geom.h"
28 #define FAR_POINT 1e10 // Value used as a "very distant" co-ordinate
29 #define TOLERANCE 1e-3
32 constructs a real segment bounded by two points
34 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt1,
35 const GLViewer_Pnt& thePnt2 )
39 myA = myPnt1.y() - myPnt2.y();
40 myB = myPnt2.x() - myPnt1.x();
41 myC = myPnt1.x() * myPnt2.y() - myPnt2.x() * myPnt1.y();
45 constructs a ray starting at <thePnt> and directed along positive X axis direction (or Y axis if vertical )
47 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt,
56 if ( fabs( myB ) < TOLERANCE )
57 myPnt2 = GLViewer_Pnt( myPnt1.x(), FAR_POINT );
59 myPnt2 = GLViewer_Pnt( FAR_POINT, - myA / myB * FAR_POINT - myC / myB );
63 destructor, does nothing
65 GLViewer_Segment::~GLViewer_Segment()
70 detects intersection with segment <theOther>
72 bool GLViewer_Segment::HasIntersection( const GLViewer_Segment& theOther ) const
75 GLfloat aDiv = myA * theOther.myB - myB * theOther.myA;
76 if ( fabs( aDiv ) > TOLERANCE )
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();
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();
90 if ( fabs( aX11 - aX12 ) > TOLERANCE )
91 aRes = aX11 < aX && aX < aX12;
93 aRes = aY11 < aY && aY < aY12;
97 if ( fabs( aX21 - aX22 ) > TOLERANCE )
98 aRes = aX21 < aX && aX < aX22;
100 aRes = aY21 < aY && aY < aY22;
108 constructs a closed polygon from the given ordered list of points
110 GLViewer_Poly::GLViewer_Poly( const GLViewer_PntList* thePoints )
111 : myPoints( (GLViewer_PntList*)thePoints )
116 destructor, <myPoints> mustn't be deleted here!
118 GLViewer_Poly::~GLViewer_Poly()
123 \return true if <thePnt> lies within this polygon
125 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt ) const
130 //cout << thePnt.x() << endl;
131 //cout << thePnt.y() << endl << endl;
134 GLViewer_Segment aRay( thePnt, 0., 1., -thePnt.y() );
136 GLViewer_PntList::const_iterator it1 = myPoints->begin();
137 GLViewer_PntList::const_iterator it2 = myPoints->begin();
139 for ( ; it1 != myPoints->end(); ++it1, ++it2 )
141 if ( it2 == myPoints->end() )
142 it2 = myPoints->begin();
144 if ( aRay.HasIntersection( GLViewer_Segment( *it1, *it2 ) ) )
148 return ( aNbInter % 2 == 1 );
151 \return true if <thePnt> lies within this polygon
154 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt, const float tolerance ) const
159 float x = thePnt.x();
160 float y = thePnt.y();
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 );
168 res = ( IsInPnt( thePnt ) ||
169 IsInPnt( p1 ) || IsInPnt( p2 ) || IsInPnt( p3 ) || IsInPnt( p4 ) );
175 \return true if <thePoly> covers this polygon
177 bool GLViewer_Poly::IsCovers( const GLViewer_Poly& thePoly ) const
179 if ( !myPoints || !thePoly.Count() )
182 GLViewer_PntList::const_iterator it = myPoints->begin();
184 for ( ; it != myPoints->end(); ++it )
186 if( !thePoly.IsIn( *it ) )
194 \return true if <theRect> covers this polygon
196 bool GLViewer_Poly::IsCovers( const GLViewer_Rect& theRect ) const
198 if ( !myPoints ) //needs check for <theRect>
201 GLViewer_PntList aList;
202 GLViewer_PntList::iterator it = aList.begin();
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() ) );
209 return IsCovers( GLViewer_Poly( &aList ) );
213 \return true if polygon has intersection with segment or ray
214 \param theSegment - segment to check intersection
216 bool GLViewer_Poly::HasIntersection( const GLViewer_Segment& theSegment ) const
222 GLViewer_PntList::const_iterator it1 = myPoints->begin();
223 GLViewer_PntList::const_iterator it2 = myPoints->begin();
225 for ( ; !aRes && it1 != myPoints->end(); ++it1, ++it2 )
227 if ( it2 == myPoints->end() )
228 it2 = myPoints->begin();
230 aRes = theSegment.HasIntersection( GLViewer_Segment( *it1, *it2 ) );