1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: line.cxx,v $
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"
35 #include <tools/link.hxx>
36 #include <tools/line.hxx>
37 #include <tools/debug.hxx>
42 inline long FRound( double fVal
)
44 return( fVal
> 0.0 ? (long) ( fVal
+ 0.5 ) : -(long) ( -fVal
+ 0.5 ) );
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
63 if( Intersection( rLine
, fX
, fY
) )
65 rIntersection
.X() = FRound( fX
);
66 rIntersection
.Y() = FRound( fY
);
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
;
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. );
97 if ( ( fA
< 0. ) || ( fA
> fDen
) )
100 else if ( ( fA
> 0. ) || ( fA
< fDen
) )
105 const double fB
= fAx
* fCy
- fAy
* fCx
;
109 if ( ( fB
< 0. ) || ( fB
> fDen
) )
112 else if ( ( fB
> 0. ) || ( fB
< fDen
) )
117 const double fAlpha
= fA
/ fDen
;
119 rIntersectionX
= ( maStart
.X() + fAlpha
* fAx
);
120 rIntersectionY
= ( maStart
.Y() + fAlpha
* fAy
);
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
);
136 if( bStartInside
&& bEndInside
)
138 // line completely inside rect
139 rIntersection
.maStart
= maStart
;
140 rIntersection
.maEnd
= maEnd
;
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
)
165 rIntersection
.maStart
= aIntersect1
;
166 rIntersection
.maEnd
= aIntersect2
;
168 else if( pCurIntersection
== &aIntersect2
)
171 rIntersection
.maStart
= aIntersect1
;
173 if( ( maStart
!= aIntersect1
) && bStartInside
)
174 rIntersection
.maEnd
= maStart
;
175 else if( ( maEnd
!= aIntersect1
) && bEndInside
)
176 rIntersection
.maEnd
= maEnd
;
178 rIntersection
.maEnd
= rIntersection
.maStart
;
187 // ------------------------------------------------------------------------
189 Point
Line::NearestPoint( const Point
& rPoint
) const
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
);
203 else if( fTau
<= 1.0 )
205 aRetPt
.X() = FRound( maStart
.X() + fTau
* fDistX
);
206 aRetPt
.Y() = FRound( maStart
.Y() - fTau
* fDistY
);
217 // ------------------------------------------------------------------------
219 double Line::GetDistance( const double& rPtX
, const double& rPtY
) const
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
;
235 fDist
= hypot( maStart
.X() - rPtX
, maStart
.Y() - rPtY
);
241 fDist
= fS
* sqrt( fL2
);
244 fDist
= hypot( maEnd
.X() - rPtX
, maEnd
.Y() - rPtY
);
251 fDist
= hypot( maStart
.X() - rPtX
, maStart
.Y() - rPtY
);
256 // ------------------------------------------------------------------------
258 void Line::Enum( const Link
& rEnumLink
)
260 DBG_ASSERT( rEnumLink
.IsSet(), "This call doesn't make any sense with !rEnumLink.IsSet()" );
266 if( maStart
.X() == maEnd
.X() )
268 const long nEndY
= maEnd
.Y();
279 rEnumLink
.Call( &aEnum
);
288 rEnumLink
.Call( &aEnum
);
292 else if( maStart
.Y() == maEnd
.Y() )
294 const long nEndX
= maEnd
.X();
305 rEnumLink
.Call( &aEnum
);
314 rEnumLink
.Call( &aEnum
);
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;
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
)
339 rEnumLink
.Call( &aEnum
);
344 nD
+= nDYX
, nY
+= nYInc
;
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
)
357 rEnumLink
.Call( &aEnum
);
362 nD
+= nDYX
, nX
+= nXInc
;
369 rEnumLink
.Call( &aEnum
);