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: b2dmultirange.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_basegfx.hxx"
33 #include <basegfx/range/b2drange.hxx>
34 #include <basegfx/tuple/b2dtuple.hxx>
35 #include <basegfx/polygon/b2dpolypolygon.hxx>
36 #include <basegfx/range/b2dmultirange.hxx>
37 #include <basegfx/polygon/b2dpolygontools.hxx>
38 #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
40 #include <boost/bind.hpp>
41 #include <boost/mem_fn.hpp>
48 class ImplB2DMultiRange
57 explicit ImplB2DMultiRange( const B2DRange
& rRange
) :
65 // no ranges at all, or all ranges empty
66 return maRanges
.empty() ||
67 ::std::count_if( maRanges
.begin(),
69 ::boost::mem_fn( &B2DRange::isEmpty
) )
70 == static_cast<VectorOfRanges::difference_type
>(maRanges
.size());
75 // swap in empty vector
77 maRanges
.swap( aTmp
);
82 template< typename ValueType
> bool isInside( const ValueType
& rValue
) const
84 if( !maBounds
.isInside( rValue
) )
87 // cannot use ::boost::bind here, since isInside is overloaded.
88 // It is currently not possible to resolve the overload
89 // by considering one of the other template arguments.
90 VectorOfRanges::const_iterator
aCurr( maRanges
.begin() );
91 const VectorOfRanges::const_iterator
aEnd ( maRanges
.end() );
92 while( aCurr
!= aEnd
)
93 if( aCurr
->isInside( rValue
) )
99 bool overlaps( const B2DRange
& rRange
) const
101 if( !maBounds
.overlaps( rRange
) )
104 const VectorOfRanges::const_iterator
aEnd( maRanges
.end() );
105 return ::std::find_if( maRanges
.begin(),
107 ::boost::bind
<bool>( ::boost::mem_fn( &B2DRange::overlaps
),
112 void addRange( const B2DRange
& rRange
)
114 maRanges
.push_back( rRange
);
115 maBounds
.expand( rRange
);
118 B2DRange
getBounds() const
123 B2DPolyPolygon
getPolyPolygon() const
127 // Make range vector unique ( have to avoid duplicate
128 // rectangles. The polygon clipper will return an empty
129 // result in this case).
130 VectorOfRanges aUniqueRanges
;
131 aUniqueRanges
.reserve( maRanges
.size() );
133 VectorOfRanges::const_iterator
aCurr( maRanges
.begin() );
134 const VectorOfRanges::const_iterator
aEnd ( maRanges
.end() );
135 while( aCurr
!= aEnd
)
137 // TODO(F3): It's plain wasted resources to apply a
138 // general clipping algorithm to the problem at
139 // hand. Go for a dedicated, scan-line-based approach.
140 VectorOfRanges::const_iterator
aCurrScan( aCurr
+1 );
141 VectorOfRanges::const_iterator
aFound( aEnd
);
142 while( aCurrScan
!= aEnd
)
144 if( aCurrScan
->equal( *aCurr
) ||
145 aCurrScan
->isInside( *aCurr
) )
147 // current probe is equal to aCurr, or
148 // completely contains aCurr. Thus, stop
149 // searching, because aCurr is definitely not
150 // a member of the unique rect list
160 // check whether aCurr is fully contained in one
161 // of the already added rects. If yes, we can skip
163 bool bUnique( true );
164 VectorOfRanges::const_iterator
aCurrUnique( aUniqueRanges
.begin() );
165 VectorOfRanges::const_iterator
aEndUnique ( aUniqueRanges
.end() );
166 while( aCurrUnique
!= aEndUnique
)
168 if( aCurrUnique
->isInside( *aCurr
) )
170 // fully contained, no need to add
179 aUniqueRanges
.push_back( *aCurr
);
185 VectorOfRanges::const_iterator
aCurrUnique( aUniqueRanges
.begin() );
186 const VectorOfRanges::const_iterator
aEndUnique ( aUniqueRanges
.end() );
187 while( aCurrUnique
!= aEndUnique
)
189 // simply merge all unique parts (OR)
190 aRes
.append( tools::createPolygonFromRect( *aCurrUnique
++ ) );
193 // remove redundant intersections. Note: since all added
194 // rectangles are positively oriented, this method cannot
195 // generate any holes.
196 aRes
= basegfx::tools::solveCrossovers(aRes
);
197 aRes
= basegfx::tools::stripNeutralPolygons(aRes
);
198 aRes
= basegfx::tools::stripDispensablePolygons(aRes
, false);
204 typedef ::std::vector
< B2DRange
> VectorOfRanges
;
207 VectorOfRanges maRanges
;
211 // ====================================================================
214 B2DMultiRange::B2DMultiRange() :
219 B2DMultiRange::B2DMultiRange( const B2DRange
& rRange
) :
220 mpImpl( ImplB2DMultiRange( rRange
) )
224 B2DMultiRange::~B2DMultiRange()
226 // otherwise, ImplB2DMultiRange would be an incomplete type
229 B2DMultiRange::B2DMultiRange( const B2DMultiRange
& rSrc
) :
230 mpImpl( rSrc
.mpImpl
)
234 B2DMultiRange
& B2DMultiRange::operator=( const B2DMultiRange
& rSrc
)
236 mpImpl
= rSrc
.mpImpl
;
240 bool B2DMultiRange::isEmpty() const
242 return mpImpl
->isEmpty();
245 void B2DMultiRange::reset()
250 bool B2DMultiRange::isInside( const B2DTuple
& rTuple
) const
252 return mpImpl
->isInside( rTuple
);
255 bool B2DMultiRange::isInside( const B2DRange
& rRange
) const
257 return mpImpl
->isInside( rRange
);
260 bool B2DMultiRange::overlaps( const B2DRange
& rRange
) const
262 return mpImpl
->overlaps( rRange
);
265 void B2DMultiRange::addRange( const B2DRange
& rRange
)
267 mpImpl
->addRange( rRange
);
270 B2DRange
B2DMultiRange::getBounds() const
272 return mpImpl
->getBounds();
275 B2DPolyPolygon
B2DMultiRange::getPolyPolygon() const
277 return mpImpl
->getPolyPolygon();
280 } // end of namespace basegfx