1 // Copyright (C) 2005 OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : OPEN CASCADE
22 //#include <GLViewerAfx.h>
23 #include <GLViewer_Geom.h>
25 #define FAR_POINT 1e10 // Value used as a "very distant" co-ordinate
26 #define TOLERANCE 1e-3
29 constructs a real segment bounded by two points
31 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt1,
32 const GLViewer_Pnt& thePnt2 )
36 myA = myPnt1.y() - myPnt2.y();
37 myB = myPnt2.x() - myPnt1.x();
38 myC = myPnt1.x() * myPnt2.y() - myPnt2.x() * myPnt1.y();
42 constructs a ray starting at <thePnt> and directed along positive X axis direction (or Y axis if vertical )
44 GLViewer_Segment::GLViewer_Segment( const GLViewer_Pnt& thePnt,
53 if ( fabs( myB ) < TOLERANCE )
54 myPnt2 = GLViewer_Pnt( myPnt1.x(), FAR_POINT );
56 myPnt2 = GLViewer_Pnt( FAR_POINT, - myA / myB * FAR_POINT - myC / myB );
60 destructor, does nothing
62 GLViewer_Segment::~GLViewer_Segment()
67 detects intersection with segment <theOther>
69 bool GLViewer_Segment::HasIntersection( const GLViewer_Segment& theOther ) const
72 GLfloat aDiv = myA * theOther.myB - myB * theOther.myA;
73 if ( fabs( aDiv ) > TOLERANCE )
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();
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();
87 if ( fabs( aX11 - aX12 ) > TOLERANCE )
88 aRes = aX11 < aX && aX < aX12;
90 aRes = aY11 < aY && aY < aY12;
94 if ( fabs( aX21 - aX22 ) > TOLERANCE )
95 aRes = aX21 < aX && aX < aX22;
97 aRes = aY21 < aY && aY < aY22;
105 constructs a closed polygon from the given ordered list of points
107 GLViewer_Poly::GLViewer_Poly( const GLViewer_PntList* thePoints )
108 : myPoints( (GLViewer_PntList*)thePoints )
113 destructor, <myPoints> mustn't be deleted here!
115 GLViewer_Poly::~GLViewer_Poly()
120 \return true if <thePnt> lies within this polygon
122 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt ) const
127 //cout << thePnt.x() << endl;
128 //cout << thePnt.y() << endl << endl;
131 GLViewer_Segment aRay( thePnt, 0., 1., -thePnt.y() );
133 GLViewer_PntList::const_iterator it1 = myPoints->begin();
134 GLViewer_PntList::const_iterator it2 = myPoints->begin();
136 for ( ; it1 != myPoints->end(); ++it1, ++it2 )
138 if ( it2 == myPoints->end() )
139 it2 = myPoints->begin();
141 if ( aRay.HasIntersection( GLViewer_Segment( *it1, *it2 ) ) )
145 return ( aNbInter % 2 == 1 );
148 \return true if <thePnt> lies within this polygon
151 bool GLViewer_Poly::IsIn( const GLViewer_Pnt& thePnt, const float tolerance ) const
156 float x = thePnt.x();
157 float y = thePnt.y();
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 );
165 res = ( IsInPnt( thePnt ) ||
166 IsInPnt( p1 ) || IsInPnt( p2 ) || IsInPnt( p3 ) || IsInPnt( p4 ) );
172 \return true if <thePoly> covers this polygon
174 bool GLViewer_Poly::IsCovers( const GLViewer_Poly& thePoly ) const
176 if ( !myPoints || !thePoly.Count() )
179 GLViewer_PntList::const_iterator it = myPoints->begin();
181 for ( ; it != myPoints->end(); ++it )
183 if( !thePoly.IsIn( *it ) )
191 \return true if <theRect> covers this polygon
193 bool GLViewer_Poly::IsCovers( const GLViewer_Rect& theRect ) const
195 if ( !myPoints ) //needs check for <theRect>
198 GLViewer_PntList aList;
199 GLViewer_PntList::iterator it = aList.begin();
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() ) );
206 return IsCovers( GLViewer_Poly( &aList ) );
210 \return true if polygon has intersection with segment or ray
211 \param theSegment - segment to check intersection
213 bool GLViewer_Poly::HasIntersection( const GLViewer_Segment& theSegment ) const
219 GLViewer_PntList::const_iterator it1 = myPoints->begin();
220 GLViewer_PntList::const_iterator it2 = myPoints->begin();
222 for ( ; !aRes && it1 != myPoints->end(); ++it1, ++it2 )
224 if ( it2 == myPoints->end() )
225 it2 = myPoints->begin();
227 aRes = theSegment.HasIntersection( GLViewer_Segment( *it1, *it2 ) );