merge the formfield patch from ooo-build
[ooovba.git] / tools / source / generic / line.cxx
blob10a3b7b014c5dde0d6ea69e06bc4437b601df90c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: line.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #define _LINE_CXX
35 #include <tools/link.hxx>
36 #include <tools/line.hxx>
37 #include <tools/debug.hxx>
39 #include <cstdlib>
40 #include <math.h>
42 inline long FRound( double fVal )
44 return( fVal > 0.0 ? (long) ( fVal + 0.5 ) : -(long) ( -fVal + 0.5 ) );
47 // --------
48 // - Line -
49 // --------
51 double Line::GetLength() const
53 return hypot( maStart.X() - maEnd.X(), maStart.Y() - maEnd.Y() );
56 // ------------------------------------------------------------------------
58 BOOL Line::Intersection( const Line& rLine, Point& rIntersection ) const
60 double fX, fY;
61 BOOL bRet;
63 if( Intersection( rLine, fX, fY ) )
65 rIntersection.X() = FRound( fX );
66 rIntersection.Y() = FRound( fY );
67 bRet = TRUE;
69 else
70 bRet = FALSE;
72 return bRet;
75 // ------------------------------------------------------------------------
77 BOOL Line::Intersection( const Line& rLine, double& rIntersectionX, double& rIntersectionY ) const
79 const double fAx = maEnd.X() - maStart.X();
80 const double fAy = maEnd.Y() - maStart.Y();
81 const double fBx = rLine.maStart.X() - rLine.maEnd.X();
82 const double fBy = rLine.maStart.Y() - rLine.maEnd.Y();
83 const double fDen = fAy * fBx - fAx * fBy;
84 BOOL bOk = FALSE;
86 if( fDen != 0. )
88 const double fCx = maStart.X() - rLine.maStart.X();
89 const double fCy = maStart.Y() - rLine.maStart.Y();
90 const double fA = fBy * fCx - fBx * fCy;
91 const BOOL bGreater = ( fDen > 0. );
93 bOk = TRUE;
95 if ( bGreater )
97 if ( ( fA < 0. ) || ( fA > fDen ) )
98 bOk = FALSE;
100 else if ( ( fA > 0. ) || ( fA < fDen ) )
101 bOk = FALSE;
103 if ( bOk )
105 const double fB = fAx * fCy - fAy * fCx;
107 if ( bGreater )
109 if ( ( fB < 0. ) || ( fB > fDen ) )
110 bOk = FALSE;
112 else if ( ( fB > 0. ) || ( fB < fDen ) )
113 bOk = FALSE;
115 if( bOk )
117 const double fAlpha = fA / fDen;
119 rIntersectionX = ( maStart.X() + fAlpha * fAx );
120 rIntersectionY = ( maStart.Y() + fAlpha * fAy );
125 return bOk;
128 // ------------------------------------------------------------------------
130 BOOL Line::Intersection( const Rectangle& rRect, Line& rIntersection ) const
132 const BOOL bStartInside = rRect.IsInside( maStart );
133 const BOOL bEndInside = rRect.IsInside( maEnd );
134 BOOL bRet = TRUE;
136 if( bStartInside && bEndInside )
138 // line completely inside rect
139 rIntersection.maStart = maStart;
140 rIntersection.maEnd = maEnd;
142 else
144 // calculate intersections
145 const Point aTL( rRect.TopLeft() ), aTR( rRect.TopRight() );
146 const Point aBR( rRect.BottomRight() ), aBL( rRect.BottomLeft() );
147 Point aIntersect1, aIntersect2;
148 Point* pCurIntersection = &aIntersect1;
150 if( Intersection( Line( aTL, aTR ), *pCurIntersection ) )
151 pCurIntersection = &aIntersect2;
153 if( Intersection( Line( aTR, aBR ), *pCurIntersection ) )
154 pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;
156 if( pCurIntersection && Intersection( Line( aBR, aBL ), *pCurIntersection ) )
157 pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;
159 if( pCurIntersection && Intersection( Line( aBL, aTL ), *pCurIntersection ) )
160 pCurIntersection = ( pCurIntersection == &aIntersect1 ) ? &aIntersect2 : NULL;
162 if( !pCurIntersection )
164 // two intersections
165 rIntersection.maStart = aIntersect1;
166 rIntersection.maEnd = aIntersect2;
168 else if( pCurIntersection == &aIntersect2 )
170 // one intersection
171 rIntersection.maStart = aIntersect1;
173 if( ( maStart != aIntersect1 ) && bStartInside )
174 rIntersection.maEnd = maStart;
175 else if( ( maEnd != aIntersect1 ) && bEndInside )
176 rIntersection.maEnd = maEnd;
177 else
178 rIntersection.maEnd = rIntersection.maStart;
180 else
181 bRet = FALSE;
184 return bRet;
187 // ------------------------------------------------------------------------
189 Point Line::NearestPoint( const Point& rPoint ) const
191 Point aRetPt;
193 if ( maStart != maEnd )
195 const double fDistX = maEnd.X() - maStart.X();
196 const double fDistY = maStart.Y() - maEnd.Y();
197 const double fTau = ( ( maStart.Y() - rPoint.Y() ) * fDistY -
198 ( maStart.X() - rPoint.X() ) * fDistX ) /
199 ( fDistX * fDistX + fDistY * fDistY );
201 if( fTau < 0.0 )
202 aRetPt = maStart;
203 else if( fTau <= 1.0 )
205 aRetPt.X() = FRound( maStart.X() + fTau * fDistX );
206 aRetPt.Y() = FRound( maStart.Y() - fTau * fDistY );
208 else
209 aRetPt = maEnd;
211 else
212 aRetPt = maStart;
214 return aRetPt;
217 // ------------------------------------------------------------------------
219 double Line::GetDistance( const double& rPtX, const double& rPtY ) const
221 double fDist;
223 if( maStart != maEnd )
225 const double fDistX = maEnd.X() - maStart.X();
226 const double fDistY = maEnd.Y() - maStart.Y();
227 const double fACX = maStart.X() - rPtX;
228 const double fACY = maStart.Y() - rPtY;
229 const double fL2 = fDistX * fDistX + fDistY * fDistY;
230 const double fR = ( fACY * -fDistY - fACX * fDistX ) / fL2;
231 const double fS = ( fACY * fDistX - fACX * fDistY ) / fL2;
233 if( fR < 0.0 )
235 fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );
237 if( fS < 0.0 )
238 fDist *= -1.0;
240 else if( fR <= 1.0 )
241 fDist = fS * sqrt( fL2 );
242 else
244 fDist = hypot( maEnd.X() - rPtX, maEnd.Y() - rPtY );
246 if( fS < 0.0 )
247 fDist *= -1.0;
250 else
251 fDist = hypot( maStart.X() - rPtX, maStart.Y() - rPtY );
253 return fDist;
256 // ------------------------------------------------------------------------
258 void Line::Enum( const Link& rEnumLink )
260 DBG_ASSERT( rEnumLink.IsSet(), "This call doesn't make any sense with !rEnumLink.IsSet()" );
262 Point aEnum;
263 long nX;
264 long nY;
266 if( maStart.X() == maEnd.X() )
268 const long nEndY = maEnd.Y();
270 nX = maStart.X();
271 nY = maStart.Y();
273 if( nEndY > nY )
275 while( nY <= nEndY )
277 aEnum.X() = nX;
278 aEnum.Y() = nY++;
279 rEnumLink.Call( &aEnum );
282 else
284 while( nY >= nEndY )
286 aEnum.X() = nX;
287 aEnum.Y() = nY--;
288 rEnumLink.Call( &aEnum );
292 else if( maStart.Y() == maEnd.Y() )
294 const long nEndX = maEnd.X();
296 nX = maStart.X();
297 nY = maStart.Y();
299 if( nEndX > nX )
301 while( nX <= nEndX )
303 aEnum.X() = nX++;
304 aEnum.Y() = nY;
305 rEnumLink.Call( &aEnum );
308 else
310 while( nX >= nEndX )
312 aEnum.X() = nX--;
313 aEnum.Y() = nY;
314 rEnumLink.Call( &aEnum );
318 else
320 const long nDX = labs( maEnd.X() - maStart.X() );
321 const long nDY = labs( maEnd.Y() - maStart.Y() );
322 const long nStartX = maStart.X();
323 const long nStartY = maStart.Y();
324 const long nEndX = maEnd.X();
325 const long nEndY = maEnd.Y();
326 const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
327 const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
329 if( nDX >= nDY )
331 const long nDYX = ( nDY - nDX ) << 1;
332 const long nDY2 = nDY << 1;
333 long nD = nDY2 - nDX;
335 for( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
337 aEnum.X() = nX;
338 aEnum.Y() = nY;
339 rEnumLink.Call( &aEnum );
341 if( nD < 0L )
342 nD += nDY2;
343 else
344 nD += nDYX, nY += nYInc;
347 else
349 const long nDYX = ( nDX - nDY ) << 1;
350 const long nDY2 = nDX << 1;
351 long nD = nDY2 - nDY;
353 for( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
355 aEnum.X() = nX;
356 aEnum.Y() = nY;
357 rEnumLink.Call( &aEnum );
359 if( nD < 0L )
360 nD += nDY2;
361 else
362 nD += nDYX, nX += nXInc;
366 // last point
367 aEnum.X() = nEndX;
368 aEnum.Y() = nEndY;
369 rEnumLink.Call( &aEnum );