25#include <osl/diagnose.h>
27#include <com/sun/star/drawing/Position3D.hpp>
28#include <com/sun/star/drawing/DoubleSequence.hpp>
33using ::basegfx::B2DRectangle;
34using ::basegfx::B2DTuple;
47bool lcl_CLIPt(
double fDenom,
double fNum,
double & fTE,
double & fTL)
86bool lcl_clip2d(B2DTuple& rPoint0, B2DTuple& rPoint1,
const B2DRectangle& rRectangle)
104 if( lcl_CLIPt(
aDirection.getX(), rRectangle.getMinX() - rPoint0.getX(), fTE, fTL) )
105 if( lcl_CLIPt(-
aDirection.getX(), rPoint0.getX() - rRectangle.getMaxX(), fTE, fTL) )
106 if( lcl_CLIPt(
aDirection.getY(), rRectangle.getMinY() - rPoint0.getY(), fTE, fTL) )
107 if( lcl_CLIPt(-
aDirection.getY(), rPoint0.getY() - rRectangle.getMaxY(), fTE, fTL) )
113 rPoint1.setX( rPoint0.getX() + fTL *
aDirection.getX() );
114 rPoint1.setY( rPoint0.getY() + fTL *
aDirection.getY() );
119 rPoint0.setX( rPoint0.getX() + fTE *
aDirection.getX() );
120 rPoint0.setY( rPoint0.getY() + fTE *
aDirection.getY() );
130bool lcl_clip2d_(drawing::Position3D& rPoint0, drawing::Position3D& rPoint1,
const B2DRectangle& rRectangle)
132 B2DTuple aP0(rPoint0.PositionX,rPoint0.PositionY);
133 B2DTuple aP1(rPoint1.PositionX,rPoint1.PositionY);
134 bool bRet = lcl_clip2d( aP0, aP1, rRectangle );
136 rPoint0.PositionX = aP0.getX();
137 rPoint0.PositionY = aP0.getY();
138 rPoint1.PositionX = aP1.getX();
139 rPoint1.PositionY = aP1.getY();
144unsigned int round_up_nearest_pow2(
unsigned int v)
157void lcl_addPointToPoly( drawing::PolyPolygonShape3D& rPoly
158 ,
const drawing::Position3D& rPos
159 , sal_Int32 nPolygonIndex
160 , std::vector< sal_Int32 >& rResultPointCount
161 , sal_Int32 nReservePointCount )
165 OSL_FAIL(
"The polygon index needs to be > 0");
170 if(nPolygonIndex >= rPoly.SequenceX.getLength() )
172 rPoly.SequenceX.realloc(nPolygonIndex+1);
173 rPoly.SequenceY.realloc(nPolygonIndex+1);
174 rPoly.SequenceZ.realloc(nPolygonIndex+1);
175 rResultPointCount.resize(nPolygonIndex+1,0);
178 drawing::DoubleSequence* pOuterSequenceX = &rPoly.SequenceX.getArray()[nPolygonIndex];
179 drawing::DoubleSequence* pOuterSequenceY = &rPoly.SequenceY.getArray()[nPolygonIndex];
180 drawing::DoubleSequence* pOuterSequenceZ = &rPoly.SequenceZ.getArray()[nPolygonIndex];
182 sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
183 sal_Int32 nSeqLength = pOuterSequenceX->getLength();
185 if( nSeqLength <= nNewResultPointCount )
187 sal_Int32 nReallocLength = nReservePointCount >
SAL_MAX_INT16 ? round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount;
188 if( nNewResultPointCount > nReallocLength )
190 nReallocLength = nNewResultPointCount;
191 OSL_FAIL(
"this should not be the case to avoid performance problems");
193 pOuterSequenceX->realloc(nReallocLength);
194 pOuterSequenceY->realloc(nReallocLength);
195 pOuterSequenceZ->realloc(nReallocLength);
198 double* pInnerSequenceX = pOuterSequenceX->getArray();
199 double* pInnerSequenceY = pOuterSequenceY->getArray();
200 double* pInnerSequenceZ = pOuterSequenceZ->getArray();
202 pInnerSequenceX[nNewResultPointCount-1] = rPos.PositionX;
203 pInnerSequenceY[nNewResultPointCount-1] = rPos.PositionY;
204 pInnerSequenceZ[nNewResultPointCount-1] = rPos.PositionZ;
205 rResultPointCount[nPolygonIndex]=nNewResultPointCount;
208void lcl_addPointToPoly( std::vector<std::vector<css::drawing::Position3D>>& rPoly
209 ,
const drawing::Position3D& rPos
210 , sal_Int32 nPolygonIndex
211 , std::vector< sal_Int32 >& rResultPointCount
212 , sal_Int32 nReservePointCount )
216 OSL_FAIL(
"The polygon index needs to be > 0");
223 rPoly.resize(nPolygonIndex+1);
224 rResultPointCount.resize(nPolygonIndex+1,0);
227 std::vector<css::drawing::Position3D>* pOuterSequence = &rPoly[nPolygonIndex];
229 sal_Int32 nNewResultPointCount = rResultPointCount[nPolygonIndex]+1;
230 sal_Int32 nSeqLength = pOuterSequence->size();
232 if( nSeqLength <= nNewResultPointCount )
234 sal_Int32 nReallocLength = nReservePointCount >
SAL_MAX_INT16 ? round_up_nearest_pow2(nNewResultPointCount) * 2 : nReservePointCount;
235 if( nNewResultPointCount > nReallocLength )
237 nReallocLength = nNewResultPointCount;
238 OSL_FAIL(
"this should not be the case to avoid performance problems");
240 pOuterSequence->resize(nReallocLength);
243 css::drawing::Position3D* pInnerSequence = pOuterSequence->data();
245 pInnerSequence[nNewResultPointCount-1] = rPos;
246 rResultPointCount[nPolygonIndex]=nNewResultPointCount;
253 , drawing::PolyPolygonShape3D& aResult
254 ,
bool bSplitPiecesToDifferentPolygons )
256 aResult.SequenceX.realloc(0);
257 aResult.SequenceY.realloc(0);
258 aResult.SequenceZ.realloc(0);
260 if(!rPolygon.SequenceX.hasElements())
266 ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() );
267 if( rRectangle.isInside( a2DRange ) )
274 a2DRange.intersect( rRectangle );
275 if( a2DRange.isEmpty() )
280 std::vector< sal_Int32 > aResultPointCount;
283 drawing::Position3D
aFrom;
284 drawing::Position3D
aTo;
286 sal_Int32 nNewPolyIndex = 0;
287 sal_Int32 nOldPolyCount = rPolygon.SequenceX.getLength();
288 for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ )
290 sal_Int32 nOldPointCount = rPolygon.SequenceX[nOldPolyIndex].getLength();
294 drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
296 for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
300 if( lcl_clip2d_(aFrom, aTo, rRectangle) )
307 lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
312 if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
314 if( nNewPolyIndex < aResult.SequenceX.getLength()
315 && aResultPointCount[nNewPolyIndex]>0 )
318 lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount );
320 lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
327 for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
329 drawing::DoubleSequence* pOuterSequenceX = &aResult.SequenceX.getArray()[nPolygonIndex];
330 drawing::DoubleSequence* pOuterSequenceY = &aResult.SequenceY.getArray()[nPolygonIndex];
331 drawing::DoubleSequence* pOuterSequenceZ = &aResult.SequenceZ.getArray()[nPolygonIndex];
333 sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
334 pOuterSequenceX->realloc(nUsedPointCount);
335 pOuterSequenceY->realloc(nUsedPointCount);
336 pOuterSequenceZ->realloc(nUsedPointCount);
342 , std::vector<std::vector<css::drawing::Position3D>>& aResult
343 ,
bool bSplitPiecesToDifferentPolygons )
353 ::basegfx::B2DRange a2DRange( a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY() );
354 if( rRectangle.isInside( a2DRange ) )
361 a2DRange.intersect( rRectangle );
362 if( a2DRange.isEmpty() )
367 std::vector< sal_Int32 > aResultPointCount;
370 drawing::Position3D
aFrom;
371 drawing::Position3D
aTo;
373 sal_Int32 nNewPolyIndex = 0;
374 sal_Int32 nOldPolyCount = rPolygon.size();
375 for(sal_Int32 nOldPolyIndex=0; nOldPolyIndex<nOldPolyCount; nOldPolyIndex++, nNewPolyIndex++ )
377 sal_Int32 nOldPointCount = rPolygon[nOldPolyIndex].size();
381 drawing::Position3D aLast(rRectangle.getMinX()-1.0,rRectangle.getMinY()-1.0, 0.0 );
383 for(sal_Int32 nOldPoint=1; nOldPoint<nOldPointCount; nOldPoint++)
387 if( lcl_clip2d_(aFrom, aTo, rRectangle) )
394 lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
399 if( bSplitPiecesToDifferentPolygons && nOldPoint!=1 )
401 if( nNewPolyIndex <
static_cast<sal_Int32
>(aResult.size())
402 && aResultPointCount[nNewPolyIndex]>0 )
405 lcl_addPointToPoly( aResult, aFrom, nNewPolyIndex, aResultPointCount, nOldPointCount );
407 lcl_addPointToPoly( aResult, aTo, nNewPolyIndex, aResultPointCount, nOldPointCount );
414 for( sal_Int32 nPolygonIndex = aResultPointCount.size(); nPolygonIndex--; )
416 std::vector<css::drawing::Position3D>* pOuterSequence = &aResult[nPolygonIndex];
418 sal_Int32 nUsedPointCount = aResultPointCount[nPolygonIndex];
419 pOuterSequence->resize(nUsedPointCount);
static void clipPolygonAtRectangle(const css::drawing::PolyPolygonShape3D &rPolygon, const ::basegfx::B2DRectangle &rRectangle, css::drawing::PolyPolygonShape3D &aResult, bool bSplitPiecesToDifferentPolygons=true)
This class uses the Liang-Biarsky parametric line-clipping algorithm as described in: Computer Graphi...
OOO_DLLPUBLIC_CHARTTOOLS::basegfx::B3DRange getBoundVolume(const css::drawing::PolyPolygonShape3D &rPolyPoly)
OOO_DLLPUBLIC_CHARTTOOLS css::drawing::Position3D getPointFromPoly(const std::vector< std::vector< css::drawing::Position3D > > &rPolygon, sal_Int32 nPointIndex, sal_Int32 nPolyIndex)
get a single Point from a Polygon
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
css::drawing::Direction3D aDirection