Files
libreoffice/basegfx/source/range/b2dmultirange.cxx
Oliver Bolte 27d39b2616 INTEGRATION: CWS pchfix02 (1.5.12); FILE MERGED
2006/09/01 17:16:38 kaib 1.5.12.1: #i68856# Added header markers and pch files
2006-09-17 07:04:43 +00:00

305 lines
9.2 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: b2dmultirange.cxx,v $
*
* $Revision: 1.6 $
*
* last change: $Author: obo $ $Date: 2006-09-17 08:04:43 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
#ifndef _BGFX_RANGE_B2DRANGE_HXX
#include <basegfx/range/b2drange.hxx>
#endif
#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif
#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX
#include <basegfx/polygon/b2dpolypolygon.hxx>
#endif
#ifndef _BGFX_RANGE_B2DMULTIRANGE_HXX
#include <basegfx/range/b2dmultirange.hxx>
#endif
#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolygontools.hxx>
#endif
#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#endif
#ifndef BOOST_BIND_HPP_INCLUDED
#include <boost/bind.hpp>
#endif
#ifndef BOOST_MEM_FN_HPP_INCLUDED
#include <boost/mem_fn.hpp>
#endif
#include <algorithm>
#include <vector>
namespace basegfx
{
class ImplB2DMultiRange
{
public:
ImplB2DMultiRange() :
maBounds(),
maRanges()
{
}
explicit ImplB2DMultiRange( const B2DRange& rRange ) :
maBounds(),
maRanges( 1, rRange )
{
}
bool isEmpty() const
{
// no ranges at all, or all ranges empty
return maRanges.empty() ||
::std::count_if( maRanges.begin(),
maRanges.end(),
::boost::mem_fn( &B2DRange::isEmpty ) )
== static_cast<VectorOfRanges::difference_type>(maRanges.size());
}
void reset()
{
// swap in empty vector
VectorOfRanges aTmp;
maRanges.swap( aTmp );
maBounds.reset();
}
template< typename ValueType > bool isInside( const ValueType& rValue ) const
{
if( !maBounds.isInside( rValue ) )
return false;
// cannot use ::boost::bind here, since isInside is overloaded.
// It is currently not possible to resolve the overload
// by considering one of the other template arguments.
VectorOfRanges::const_iterator aCurr( maRanges.begin() );
const VectorOfRanges::const_iterator aEnd ( maRanges.end() );
while( aCurr != aEnd )
if( aCurr->isInside( rValue ) )
return true;
return false;
}
bool overlaps( const B2DRange& rRange ) const
{
if( !maBounds.overlaps( rRange ) )
return false;
const VectorOfRanges::const_iterator aEnd( maRanges.end() );
return ::std::find_if( maRanges.begin(),
aEnd,
::boost::bind<bool>( ::boost::mem_fn( &B2DRange::overlaps ),
_1,
rRange ) ) != aEnd;
}
void addRange( const B2DRange& rRange )
{
maRanges.push_back( rRange );
maBounds.expand( rRange );
}
B2DRange getBounds() const
{
return maBounds;
}
B2DPolyPolygon getPolyPolygon() const
{
B2DPolyPolygon aRes;
// Make range vector unique ( have to avoid duplicate
// rectangles. The polygon clipper will return an empty
// result in this case).
VectorOfRanges aUniqueRanges;
aUniqueRanges.reserve( maRanges.size() );
VectorOfRanges::const_iterator aCurr( maRanges.begin() );
const VectorOfRanges::const_iterator aEnd ( maRanges.end() );
while( aCurr != aEnd )
{
// TODO(F3): It's plain wasted resources to apply a
// general clipping algorithm to the problem at
// hand. Go for a dedicated, scan-line-based approach.
VectorOfRanges::const_iterator aCurrScan( aCurr+1 );
VectorOfRanges::const_iterator aFound( aEnd );
while( aCurrScan != aEnd )
{
if( aCurrScan->equal( *aCurr ) ||
aCurrScan->isInside( *aCurr ) )
{
// current probe is equal to aCurr, or
// completely contains aCurr. Thus, stop
// searching, because aCurr is definitely not
// a member of the unique rect list
aFound = aCurrScan;
break;
}
++aCurrScan;
}
if( aFound == aEnd )
{
// check whether aCurr is fully contained in one
// of the already added rects. If yes, we can skip
// it.
bool bUnique( true );
VectorOfRanges::const_iterator aCurrUnique( aUniqueRanges.begin() );
VectorOfRanges::const_iterator aEndUnique ( aUniqueRanges.end() );
while( aCurrUnique != aEndUnique )
{
if( aCurrUnique->isInside( *aCurr ) )
{
// fully contained, no need to add
bUnique = false;
break;
}
++aCurrUnique;
}
if( bUnique )
aUniqueRanges.push_back( *aCurr );
}
++aCurr;
}
VectorOfRanges::const_iterator aCurrUnique( aUniqueRanges.begin() );
const VectorOfRanges::const_iterator aEndUnique ( aUniqueRanges.end() );
while( aCurrUnique != aEndUnique )
{
// simply merge all unique parts (OR)
aRes.append( tools::createPolygonFromRect( *aCurrUnique++ ) );
}
// remove redundant intersections. Note: since all added
// rectangles are positively oriented, this method cannot
// generate any holes.
aRes = ::basegfx::tools::removeAllIntersections(aRes);
aRes = ::basegfx::tools::removeNeutralPolygons(aRes, sal_True);
return aRes;
}
private:
typedef ::std::vector< B2DRange > VectorOfRanges;
B2DRange maBounds;
VectorOfRanges maRanges;
};
// ====================================================================
B2DMultiRange::B2DMultiRange() :
mpImpl()
{
}
B2DMultiRange::B2DMultiRange( const B2DRange& rRange ) :
mpImpl( ImplB2DMultiRange( rRange ) )
{
}
B2DMultiRange::~B2DMultiRange()
{
// otherwise, ImplB2DMultiRange would be an incomplete type
}
B2DMultiRange::B2DMultiRange( const B2DMultiRange& rSrc ) :
mpImpl( rSrc.mpImpl )
{
}
B2DMultiRange& B2DMultiRange::operator=( const B2DMultiRange& rSrc )
{
mpImpl = rSrc.mpImpl;
return *this;
}
bool B2DMultiRange::isEmpty() const
{
return mpImpl->isEmpty();
}
void B2DMultiRange::reset()
{
mpImpl->reset();
}
bool B2DMultiRange::isInside( const B2DTuple& rTuple ) const
{
return mpImpl->isInside( rTuple );
}
bool B2DMultiRange::isInside( const B2DRange& rRange ) const
{
return mpImpl->isInside( rRange );
}
bool B2DMultiRange::overlaps( const B2DRange& rRange ) const
{
return mpImpl->overlaps( rRange );
}
void B2DMultiRange::addRange( const B2DRange& rRange )
{
mpImpl->addRange( rRange );
}
B2DRange B2DMultiRange::getBounds() const
{
return mpImpl->getBounds();
}
B2DPolyPolygon B2DMultiRange::getPolyPolygon() const
{
return mpImpl->getPolyPolygon();
}
} // end of namespace basegfx
// eof