INTEGRATION: CWS aw019 (1.6.22); FILE MERGED

2004/10/19 08:55:28 aw 1.6.22.2: #i34831#
2004/10/18 10:39:56 aw 1.6.22.1: #i34831#
This commit is contained in:
Pascal Junck
2004-11-03 07:37:59 +00:00
parent 8f5dc2ea99
commit fd8fe422bb

View File

@@ -2,9 +2,9 @@
* *
* $RCSfile: b2dpolypolygoncutter.cxx,v $ * $RCSfile: b2dpolypolygoncutter.cxx,v $
* *
* $Revision: 1.6 $ * $Revision: 1.7 $
* *
* last change: $Author: kz $ $Date: 2004-06-10 11:40:01 $ * last change: $Author: pjunck $ $Date: 2004-11-03 08:37:59 $
* *
* The Contents of this file are made available subject to the terms of * The Contents of this file are made available subject to the terms of
* either of the following licenses * either of the following licenses
@@ -83,11 +83,42 @@
#include <basegfx/polygon/b2dpolygontools.hxx> #include <basegfx/polygon/b2dpolygontools.hxx>
#endif #endif
#include <algorithm>
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// B2DPolygonNode implementation // B2DPolygonNode
namespace basegfx namespace basegfx
{ {
class B2DPolygonNode
{
B2DPoint maPosition;
B2DPolygonNode* mpPrevious;
B2DPolygonNode* mpNext;
B2DPolygonNode* mpListPrevious;
B2DPolygonNode* mpListNext;
public:
B2DPolygonNode(const B2DPoint& rPosition, B2DPolygonNode* pPrevious);
~B2DPolygonNode();
B2DPolygonNode* getPrevious() const { return mpPrevious; }
B2DPolygonNode* getNext() const { return mpNext; }
const B2DPoint& getPosition() const { return maPosition; }
void calcMinMaxX(double& fMaxAX, double& fMinAX) const;
void calcMinMaxY(double& fMaxAY, double& fMinAY) const;
void swapPreviousNext() { B2DPolygonNode* pZwi = mpPrevious; mpPrevious = mpNext; mpNext = pZwi; }
void swapNextPointers(B2DPolygonNode* pCand);
void addToList(B2DPolygonNode*& rpList);
void remFromList(B2DPolygonNode*& rpList);
B2DRange getRange() const;
};
B2DPolygonNode::B2DPolygonNode(const B2DPoint& rPosition, B2DPolygonNode* pPrevious) B2DPolygonNode::B2DPolygonNode(const B2DPoint& rPosition, B2DPolygonNode* pPrevious)
: maPosition(rPosition) : maPosition(rPosition)
{ {
@@ -190,47 +221,6 @@ namespace basegfx
} }
} }
bool B2DPolygonNode::getOrientation() const
{
const B2DPolygonNode* pOutmost = this;
const B2DPolygonNode* pCurrent = this->getNext();
while(pCurrent != this)
{
if(fTools::more(pOutmost->getPosition().getX(), pCurrent->getPosition().getX()))
{
if(pCurrent->getPosition().getX() < pOutmost->getPosition().getX())
{
pOutmost = pCurrent;
}
else
{
if(pCurrent->getPosition().getY() < pOutmost->getPosition().getY())
{
pOutmost = pCurrent;
}
}
}
// next node
pCurrent = pCurrent->getNext();
}
B2DVector aVec1(pOutmost->getPrevious()->getPosition() - pOutmost->getPosition());
B2DVector aVec2(pOutmost->getNext()->getPosition() - pOutmost->getPosition());
return bool(fTools::more(aVec1.getX() * aVec2.getY(), aVec1.getY() * aVec2.getX()));
}
void B2DPolygonNode::swapOrientation()
{
B2DPolygonNode* pCurrent = this;
do {
pCurrent->swapPreviousNext();
pCurrent = pCurrent->getPrevious();
} while(pCurrent != this);
}
B2DRange B2DPolygonNode::getRange() const B2DRange B2DPolygonNode::getRange() const
{ {
B2DRange aRetval; B2DRange aRetval;
@@ -243,122 +233,38 @@ namespace basegfx
return aRetval; return aRetval;
} }
bool B2DPolygonNode::isInside(const B2DPoint& rPoint, bool bWithBorder) const
{
bool bInside(false);
const B2DPolygonNode* pCurrent = this;
do
{
if(bWithBorder && pCurrent->getPosition().equal(rPoint))
{
return true;
}
B2DPolygonNode* pNext = pCurrent->getNext();
const bool bCompYA(fTools::more(pCurrent->getPosition().getY(), rPoint.getY()));
const bool bCompYB(fTools::more(pNext->getPosition().getY(), rPoint.getY()));
if(bCompYA != bCompYB)
{
const bool bCompXA(fTools::more(pCurrent->getPosition().getX(), rPoint.getX()));
const bool bCompXB(fTools::more(pNext->getPosition().getX(), rPoint.getX()));
if(bCompXA == bCompXB)
{
if(bCompXA)
{
bInside = !bInside;
}
}
else
{
double fCmp =
pNext->getPosition().getX() - (pNext->getPosition().getY() - rPoint.getY()) *
(pCurrent->getPosition().getX() - pNext->getPosition().getX()) /
(pCurrent->getPosition().getY() - pNext->getPosition().getY());
if(bWithBorder && fTools::more(fCmp, rPoint.getX()))
{
bInside = !bInside;
}
else if(fTools::moreOrEqual(fCmp, rPoint.getX()))
{
bInside = !bInside;
}
}
}
// next edge
pCurrent = pNext;
} while(pCurrent != this);
return bInside;
}
bool B2DPolygonNode::isPolygonInside(B2DPolygonNode* pPoly, bool bWithBorder) const
{
B2DPolygonNode* pTest = pPoly;
bool bAllAInside(true);
do {
bAllAInside = isInside(pTest->getPosition(), bWithBorder);
pTest = pTest->getNext();
} while(bAllAInside && pTest != pPoly);
return bAllAInside;
}
} // end of namespace basegfx } // end of namespace basegfx
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// B2DSimpleCut implementation // B2DSimpleCut
namespace basegfx namespace basegfx
{ {
void B2DSimpleCut::solve() class B2DSimpleCut
{ {
mpLeft->swapNextPointers(mpRight); B2DPolygonNode* mpLeft;
B2DPolygonNode* mpRight;
if(mbCorrectOrientation) public:
B2DSimpleCut(B2DPolygonNode* pL, B2DPolygonNode* pR)
: mpLeft(pL),
mpRight(pR)
{ {
if(mpLeft->getOrientation() != mbOrientation)
{
mpLeft->swapOrientation();
}
if(mpRight->getOrientation() != mbOrientation)
{
mpRight->swapOrientation();
}
} }
}
} // end of namespace basegfx
////////////////////////////////////////////////////////////////////////////// void solve()
// B2DClipExtraPolygonInfo implementation
namespace basegfx
{
void B2DClipExtraPolygonInfo::init(B2DPolygonNode* pNew)
{
maRange = pNew->getRange();
mbOrientation = pNew->getOrientation();
mnDepth = (mbOrientation) ? 0L : -1L;
}
void B2DClipExtraPolygonInfo::changeDepth(bool bOrientation)
{
if(bOrientation)
{ {
mnDepth++; mpLeft->swapNextPointers(mpRight);
} }
else
B2DPolygonNode* getLeft() const { return mpLeft; }
B2DPolygonNode* getRight() const { return mpRight; }
bool isSameCut(B2DPolygonNode* pA, B2DPolygonNode* pB) const
{ {
mnDepth--; return ((pA == mpLeft && pB == mpRight) || (pB == mpLeft && pA == mpRight));
} }
} };
} // end of namespace basegfx } // end of namespace basegfx
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -376,60 +282,60 @@ namespace basegfx
maPolygonList.clear(); maPolygonList.clear();
} }
void B2DPolyPolygonCutter::removeIncludedPolygons(bool bUseOr) //BFS08 void B2DPolyPolygonCutter::removeIncludedPolygons(bool bUseOr)
{ //BFS08 {
const sal_uInt32 aCount(maPolygonList.size()); //BFS08 const sal_uInt32 aCount(maPolygonList.size());
B2DClipExtraPolygonInfo* pInfos = new B2DClipExtraPolygonInfo[aCount]; //BFS08 B2DClipExtraPolygonInfo* pInfos = new B2DClipExtraPolygonInfo[aCount];
sal_uInt32 a, b; //BFS08 sal_uInt32 a, b;
//BFS08
// fill infos //BFS08 // fill infos
for(a = 0L; a < aCount; a++) //BFS08 for(a = 0L; a < aCount; a++)
{ //BFS08 {
pInfos[a].init(maPolygonList[a]); //BFS08 pInfos[a].init(maPolygonList[a]);
} //BFS08 }
//BFS08
// get all includes //BFS08 // get all includes
for(a = 0L; a < aCount; a++) //BFS08 for(a = 0L; a < aCount; a++)
{ //BFS08 {
B2DClipExtraPolygonInfo& rInfoA = pInfos[a]; //BFS08 B2DClipExtraPolygonInfo& rInfoA = pInfos[a];
//BFS08
for(b = 0L; b < aCount; b++) //BFS08 for(b = 0L; b < aCount; b++)
{ //BFS08 {
B2DClipExtraPolygonInfo& rInfoB = pInfos[b]; //BFS08 B2DClipExtraPolygonInfo& rInfoB = pInfos[b];
//BFS08
if(a != b && doRangesInclude(rInfoA.getRange(), rInfoB.getRange())) //BFS08 if(a != b && doRangesInclude(rInfoA.getRange(), rInfoB.getRange()))
{ //BFS08 {
// volume B in A, test pA, pB for inclusion, with border //BFS08 // volume B in A, test pA, pB for inclusion, with border
if(maPolygonList[a]->isPolygonInside(maPolygonList[b], true)) //BFS08 if(maPolygonList[a]->isPolygonInside(maPolygonList[b], true))
{ //BFS08 {
// pB is inside pA //BFS08 // pB is inside pA
rInfoB.changeDepth(rInfoA.getOrientation()); //BFS08 rInfoB.changeDepth(rInfoA.getOrientation());
} //BFS08 }
} //BFS08 }
} //BFS08 }
} //BFS08 }
//BFS08
// delete removable //BFS08 // delete removable
for(a = 0L, b = 0L; a < aCount; a++) //BFS08 for(a = 0L, b = 0L; a < aCount; a++)
{ //BFS08 {
B2DClipExtraPolygonInfo& rInfo = pInfos[a]; //BFS08 B2DClipExtraPolygonInfo& rInfo = pInfos[a];
//BFS08
if((bUseOr && rInfo.getDepth() != 0L) || (!bUseOr && rInfo.getDepth() < 1L)) //BFS08 if((bUseOr && rInfo.getDepth() != 0L) || (!bUseOr && rInfo.getDepth() < 1L))
{ //BFS08 {
B2DPolygonNodeVector::iterator aPosition(maPolygonList.begin() + b); //BFS08 B2DPolygonNodeVector::iterator aPosition(maPolygonList.begin() + b);
B2DPolygonNode* pCandidate = *aPosition; //BFS08 B2DPolygonNode* pCandidate = *aPosition;
maPolygonList.erase(aPosition); //BFS08 maPolygonList.erase(aPosition);
deletePolygon(pCandidate); //BFS08 deletePolygon(pCandidate);
} //BFS08 }
else //BFS08 else
{ //BFS08 {
b++; //BFS08 b++;
} //BFS08 }
} //BFS08 }
//BFS08
// delete infos //BFS08 // delete infos
delete[] pInfos; //BFS08 delete[] pInfos;
} //BFS08 }
void B2DPolyPolygonCutter::solveAllCuts(B2DSimpleCutVector& rCuts) void B2DPolyPolygonCutter::solveAllCuts(B2DSimpleCutVector& rCuts)
{ {
@@ -521,38 +427,27 @@ namespace basegfx
} while(pAct != pPolygon); } while(pAct != pPolygon);
} }
void B2DPolyPolygonCutter::addPolyPolygon(const B2DPolyPolygon& rPolyPolygon, bool bForceOrientation) void B2DPolyPolygonCutter::addPolygon(const B2DPolygon& rPolygon)
{
if(rPolygon.isClosed() && rPolygon.count() > 2)
{
B2DPolygonNode* pNew = createNewPolygon(rPolygon);
maPolygonList.push_back(pNew);
}
}
void B2DPolyPolygonCutter::addPolyPolygon(const B2DPolyPolygon& rPolyPolygon)
{ {
for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++) for(sal_uInt32 a(0L); a < rPolyPolygon.count(); a++)
{ {
B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a); B2DPolygon aCandidate = rPolyPolygon.getB2DPolygon(a);
aCandidate.removeDoublePoints(); addPolygon(aCandidate);
if(!aCandidate.isClosed() || aCandidate.count() < 3)
{
maNotClosedPolygons.append(aCandidate);
}
else
{
if(bForceOrientation)
{
B2VectorOrientation aOrientation =
tools::getOrientation(aCandidate);
if(ORIENTATION_POSITIVE != aOrientation)
{
aCandidate.flip();
}
}
B2DPolygonNode* pNew = createNewPolygon(aCandidate);
maPolygonList.push_back(pNew);
}
} }
} }
void B2DPolyPolygonCutter::getPolyPolygon(B2DPolyPolygon& rPolyPolygon) B2DPolyPolygon B2DPolyPolygonCutter::getPolyPolygon()
{ {
B2DPolyPolygon aRetval;
B2DPolygonNodeVector::iterator aCandidate(maPolygonList.begin()); B2DPolygonNodeVector::iterator aCandidate(maPolygonList.begin());
for(; aCandidate < maPolygonList.end(); aCandidate++) for(; aCandidate < maPolygonList.end(); aCandidate++)
@@ -576,7 +471,7 @@ namespace basegfx
} while(pAct != pCand); } while(pAct != pCand);
aNewPolygon.setClosed(true); aNewPolygon.setClosed(true);
rPolyPolygon.append(aNewPolygon); aRetval.append(aNewPolygon);
} }
deletePolygon(pCand); deletePolygon(pCand);
@@ -584,11 +479,7 @@ namespace basegfx
maPolygonList.clear(); maPolygonList.clear();
while(maNotClosedPolygons.count()) return aRetval;
{
rPolyPolygon.append(maNotClosedPolygons.getB2DPolygon(0L));
maNotClosedPolygons.remove(0L);
}
} }
B2DSimpleCut* B2DPolyPolygonCutter::getExistingCut(B2DSimpleCutVector& rTmpCuts, B2DPolygonNode* pA, B2DPolygonNode* pB) B2DSimpleCut* B2DPolyPolygonCutter::getExistingCut(B2DSimpleCutVector& rTmpCuts, B2DPolygonNode* pA, B2DPolygonNode* pB)
@@ -654,9 +545,10 @@ namespace basegfx
pB = pA->getNext(); pB = pA->getNext();
do { do {
if(isSamePos(pA->getPosition(), pB->getPosition())) if(pA->getPosition().equal(pB->getPosition()))
{ {
aNewCuts.push_back(new B2DSimpleCut(pA, pB, true, pCand->getOrientation())); //BFS08 aNewCuts.push_back(new B2DSimpleCut(pA, pB, true, pCand->getOrientation()));
aNewCuts.push_back(new B2DSimpleCut(pA, pB));
} }
// next B // next B
@@ -687,7 +579,7 @@ namespace basegfx
if(fTools::moreOrEqual(fMaxBY, fMinAY) // #116732# if(fTools::moreOrEqual(fMaxBY, fMinAY) // #116732#
&& fTools::moreOrEqual(fMaxAY, fMinBY)) // #116732# && fTools::moreOrEqual(fMaxAY, fMinBY)) // #116732#
{ {
if(!isSamePos(pA->getPosition(), pB->getPosition())) if(!pA->getPosition().equal(pB->getPosition()))
{ {
const B2DVector aVectorA(pA->getNext()->getPosition() - pA->getPosition()); const B2DVector aVectorA(pA->getNext()->getPosition() - pA->getPosition());
const B2DVector aVectorB(pB->getNext()->getPosition() - pB->getPosition()); const B2DVector aVectorB(pB->getNext()->getPosition() - pB->getPosition());
@@ -698,7 +590,8 @@ namespace basegfx
B2DPoint aNewPos(interpolate(pA->getPosition(), pA->getNext()->getPosition(), fCut)); B2DPoint aNewPos(interpolate(pA->getPosition(), pA->getNext()->getPosition(), fCut));
B2DPolygonNode* pCutLo = new B2DPolygonNode(aNewPos, pA); B2DPolygonNode* pCutLo = new B2DPolygonNode(aNewPos, pA);
B2DPolygonNode* pCutHi = new B2DPolygonNode(aNewPos, pB); B2DPolygonNode* pCutHi = new B2DPolygonNode(aNewPos, pB);
aNewCuts.push_back(new B2DSimpleCut(pCutLo, pCutHi, true, pCand->getOrientation())); //BFS08 aNewCuts.push_back(new B2DSimpleCut(pCutLo, pCutHi, true, pCand->getOrientation()));
aNewCuts.push_back(new B2DSimpleCut(pCutLo, pCutHi));
pA->calcMinMaxX(fMaxAX, fMinAX); pA->calcMinMaxX(fMaxAX, fMinAX);
pA->calcMinMaxY(fMaxAY, fMinAY); pA->calcMinMaxY(fMaxAY, fMinAY);
} }
@@ -708,13 +601,15 @@ namespace basegfx
{ {
// startpoint A at edge B, one new point // startpoint A at edge B, one new point
B2DPolygonNode* pCutHi = new B2DPolygonNode(pA->getPosition(), pB); B2DPolygonNode* pCutHi = new B2DPolygonNode(pA->getPosition(), pB);
aNewCuts.push_back(new B2DSimpleCut(pA, pCutHi, true, pCand->getOrientation())); //BFS08 aNewCuts.push_back(new B2DSimpleCut(pA, pCutHi, true, pCand->getOrientation()));
aNewCuts.push_back(new B2DSimpleCut(pA, pCutHi));
} }
else if(tools::isPointOnEdge(pB->getPosition(), pA->getPosition(), aVectorA, &fCut)) else if(tools::isPointOnEdge(pB->getPosition(), pA->getPosition(), aVectorA, &fCut))
{ {
// startpoint B at edge A, one new point // startpoint B at edge A, one new point
B2DPolygonNode* pCutLo = new B2DPolygonNode(pB->getPosition(), pA); B2DPolygonNode* pCutLo = new B2DPolygonNode(pB->getPosition(), pA);
aNewCuts.push_back(new B2DSimpleCut(pCutLo, pB, true, pCand->getOrientation())); //BFS08 aNewCuts.push_back(new B2DSimpleCut(pCutLo, pB, true, pCand->getOrientation()));
aNewCuts.push_back(new B2DSimpleCut(pCutLo, pB));
pA->calcMinMaxX(fMaxAX, fMinAX); pA->calcMinMaxX(fMaxAX, fMinAX);
pA->calcMinMaxY(fMaxAY, fMinAY); pA->calcMinMaxY(fMaxAY, fMinAY);
} }
@@ -863,6 +758,16 @@ namespace basegfx
return (bA1BiggerB1 == bA2BiggerB2); return (bA1BiggerB1 == bA2BiggerB2);
} }
bool B2DPolyPolygonCutter::isNextSamePos(B2DPolygonNode* pA, B2DPolygonNode* pB)
{
return pA->getNext()->getPosition().equal(pB->getNext()->getPosition());
}
bool B2DPolyPolygonCutter::isPrevSamePos(B2DPolygonNode* pA, B2DPolygonNode* pB)
{
return pA->getPrevious()->getPosition().equal(pB->getPrevious()->getPosition());
}
void B2DPolyPolygonCutter::removeDoubleIntersections() void B2DPolyPolygonCutter::removeDoubleIntersections()
{ {
double fMaxAX, fMinAX, fMaxAY, fMinAY; double fMaxAX, fMinAX, fMaxAY, fMinAY;
@@ -892,7 +797,7 @@ namespace basegfx
for(sal_uInt32 b = a + 1L; b < maPolygonList.size(); b++) for(sal_uInt32 b = a + 1L; b < maPolygonList.size(); b++)
{ {
if(doRangesIntersect(pVolumes[a], pVolumes[b])) if(pVolumes[a].overlaps(pVolumes[b]))
{ {
pCandB = maPolygonList[b]; pCandB = maPolygonList[b];
pA = pCandA; pA = pCandA;
@@ -903,7 +808,7 @@ namespace basegfx
pB = pCandB; pB = pCandB;
do { do {
if(isSamePos(pA->getPosition(), pB->getPosition())) if(pA->getPosition().equal(pB->getPosition()))
{ {
aTmpCuts.push_back(new B2DSimpleCut(pA, pB)); aTmpCuts.push_back(new B2DSimpleCut(pA, pB));
} }
@@ -936,7 +841,7 @@ namespace basegfx
if(fTools::moreOrEqual(fMaxBY, fMinAY) // #116732# if(fTools::moreOrEqual(fMaxBY, fMinAY) // #116732#
&& fTools::moreOrEqual(fMaxAY, fMinBY)) // #116732# && fTools::moreOrEqual(fMaxAY, fMinBY)) // #116732#
{ {
if(!isSamePos(pA->getPosition(), pB->getPosition())) if(!pA->getPosition().equal(pB->getPosition()))
{ {
const B2DVector aVectorA(pA->getNext()->getPosition() - pA->getPosition()); const B2DVector aVectorA(pA->getNext()->getPosition() - pA->getPosition());
const B2DVector aVectorB(pB->getNext()->getPosition() - pB->getPosition()); const B2DVector aVectorB(pB->getNext()->getPosition() - pB->getPosition());