summaryrefslogtreecommitdiff
path: root/basegfx
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2012-01-26 14:17:36 +0000
committerArmin Le Grand <alg@apache.org>2012-01-26 14:17:36 +0000
commit9bfc160463a7a90a3e4280315727c0a3d4af7882 (patch)
treee2f9f89b2425d5c77d4c5eddb4084345d542291d /basegfx
parent94d82202ab49a3dd0da2f26eb8ca85005ff2e9da (diff)
#118838# LineGeometry creation for complicated cases optimized to create single Polygons
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/source/polygon/b2dlinegeometry.cxx133
1 files changed, 85 insertions, 48 deletions
diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx
index b723cd5a63b1..575c9ba1474d 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -35,6 +35,7 @@
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <com/sun/star/drawing/LineCap.hpp>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -339,7 +340,7 @@ namespace basegfx
}
}
- B2DPolyPolygon createAreaGeometryForEdge(
+ B2DPolygon createAreaGeometryForEdge(
const B2DCubicBezier& rEdge,
double fHalfLineWidth,
bool bStartRound,
@@ -354,7 +355,6 @@ namespace basegfx
if(rEdge.isBezier())
{
// prepare target and data common for upper and lower
- B2DPolyPolygon aRetval;
B2DPolygon aBezierPolygon;
const B2DVector aPureEdgeVector(rEdge.getEndPoint() - rEdge.getStartPoint());
const double fEdgeLength(aPureEdgeVector.getLength());
@@ -386,50 +386,40 @@ namespace basegfx
// check if cut happens
const bool bCut(bCutA || bCutB);
+ B2DPoint aCutPoint;
// create left edge
if(bStartRound || bStartSquare)
{
- basegfx::B2DPolygon aStartPolygon;
-
if(bStartRound)
{
- aStartPolygon = tools::createHalfUnitCircle();
+ basegfx::B2DPolygon aStartPolygon(tools::createHalfUnitCircle());
+
aStartPolygon.transform(
tools::createScaleShearXRotateTranslateB2DHomMatrix(
fHalfLineWidth, fHalfLineWidth,
0.0,
atan2(aTangentA.getY(), aTangentA.getX()) + F_PI2,
rEdge.getStartPoint().getX(), rEdge.getStartPoint().getY()));
+ aBezierPolygon.append(aStartPolygon);
}
else // bStartSquare
{
const basegfx::B2DPoint aStart(rEdge.getStartPoint() - (aTangentA * fHalfLineWidth));
- if(bCut)
+ if(bCutB)
{
- aStartPolygon.append(rEdge.getStartPoint() + aPerpendStartB);
+ aBezierPolygon.append(rEdge.getStartPoint() + aPerpendStartB);
}
- aStartPolygon.append(aStart + aPerpendStartB);
- aStartPolygon.append(aStart + aPerpendStartA);
+ aBezierPolygon.append(aStart + aPerpendStartB);
+ aBezierPolygon.append(aStart + aPerpendStartA);
- if(bCut)
+ if(bCutA)
{
- aStartPolygon.append(rEdge.getStartPoint() + aPerpendStartA);
+ aBezierPolygon.append(rEdge.getStartPoint() + aPerpendStartA);
}
}
-
- if(bCut)
- {
- aStartPolygon.append(rEdge.getStartPoint());
- aStartPolygon.setClosed(true);
- aRetval.append(aStartPolygon);
- }
- else
- {
- aBezierPolygon.append(aStartPolygon);
- }
}
else
{
@@ -442,7 +432,7 @@ namespace basegfx
if(bCutA)
{
// calculate cut point and add
- const B2DPoint aCutPoint(rEdge.getStartPoint() + (aPerpendStartA * fCutA));
+ aCutPoint = rEdge.getStartPoint() + (aPerpendStartA * fCutA);
aBezierPolygon.append(aCutPoint);
}
else
@@ -464,46 +454,35 @@ namespace basegfx
// create right edge
if(bEndRound || bEndSquare)
{
- basegfx::B2DPolygon aEndPolygon;
-
if(bEndRound)
{
- aEndPolygon = tools::createHalfUnitCircle();
+ basegfx::B2DPolygon aEndPolygon(tools::createHalfUnitCircle());
+
aEndPolygon.transform(
tools::createScaleShearXRotateTranslateB2DHomMatrix(
fHalfLineWidth, fHalfLineWidth,
0.0,
atan2(aTangentB.getY(), aTangentB.getX()) - F_PI2,
rEdge.getEndPoint().getX(), rEdge.getEndPoint().getY()));
+ aBezierPolygon.append(aEndPolygon);
}
else // bEndSquare
{
const basegfx::B2DPoint aEnd(rEdge.getEndPoint() + (aTangentB * fHalfLineWidth));
- if(bCut)
+ if(bCutA)
{
- aEndPolygon.append(rEdge.getEndPoint() + aPerpendEndA);
+ aBezierPolygon.append(rEdge.getEndPoint() + aPerpendEndA);
}
- aEndPolygon.append(aEnd + aPerpendEndA);
- aEndPolygon.append(aEnd + aPerpendEndB);
+ aBezierPolygon.append(aEnd + aPerpendEndA);
+ aBezierPolygon.append(aEnd + aPerpendEndB);
- if(bCut)
+ if(bCutB)
{
- aEndPolygon.append(rEdge.getEndPoint() + aPerpendEndB);
+ aBezierPolygon.append(rEdge.getEndPoint() + aPerpendEndB);
}
}
-
- if(bCut)
- {
- aEndPolygon.append(rEdge.getEndPoint());
- aEndPolygon.setClosed(true);
- aRetval.append(aEndPolygon);
- }
- else
- {
- aBezierPolygon.append(aEndPolygon);
- }
}
else
{
@@ -516,7 +495,7 @@ namespace basegfx
if(bCutB)
{
// calculate cut point and add
- const B2DPoint aCutPoint(rEdge.getEndPoint() + (aPerpendEndB * fCutB));
+ aCutPoint = rEdge.getEndPoint() + (aPerpendEndB * fCutB);
aBezierPolygon.append(aCutPoint);
}
else
@@ -535,11 +514,69 @@ namespace basegfx
}
}
- // close and return
+ // close
aBezierPolygon.setClosed(true);
- aRetval.append(aBezierPolygon);
- return aRetval;
+ if(bStartRound || bEndRound)
+ {
+ // double points possible when round caps are used at start or end
+ aBezierPolygon.removeDoublePoints();
+ }
+
+ if(bCut && ((bStartRound || bStartSquare) && (bEndRound || bEndSquare)))
+ {
+ // When cut exists and both ends are extended with caps, a self-intersecting polygon
+ // is created; one cut point is known, but there is a 2nd one in the caps geometry.
+ // Solve by using tooling.
+ // Remark: This nearly never happens due to curve preparations to extreme points
+ // and maximum angle turning, but I constructed a test case and checkd that it is
+ // working propery.
+ const B2DPolyPolygon aTemp(tools::solveCrossovers(aBezierPolygon));
+ const sal_uInt32 nTempCount(aTemp.count());
+
+ if(nTempCount)
+ {
+ if(nTempCount > 1)
+ {
+ // as expected, multiple polygons (with same orientation). Remove
+ // the one which contains aCutPoint, or better take the one without
+ for (sal_uInt32 a(0); a < nTempCount; a++)
+ {
+ aBezierPolygon = aTemp.getB2DPolygon(a);
+
+ const sal_uInt32 nCandCount(aBezierPolygon.count());
+
+ for(sal_uInt32 b(0); b < nCandCount; b++)
+ {
+ if(aCutPoint.equal(aBezierPolygon.getB2DPoint(b)))
+ {
+ aBezierPolygon.clear();
+ break;
+ }
+ }
+
+ if(aBezierPolygon.count())
+ {
+ break;
+ }
+ }
+
+ OSL_ENSURE(aBezierPolygon.count(), "Error in line geometry creation, could not solve self-intersection (!)");
+ }
+ else
+ {
+ // none found, use result
+ aBezierPolygon = aTemp.getB2DPolygon(0);
+ }
+ }
+ else
+ {
+ OSL_ENSURE(false, "Error in line geometry creation, could not solve self-intersection (!)");
+ }
+ }
+
+ // return
+ return aBezierPolygon;
}
else
{
@@ -636,7 +673,7 @@ namespace basegfx
// close and return
aEdgePolygon.setClosed(true);
- return B2DPolyPolygon(aEdgePolygon);
+ return aEdgePolygon;
}
}