office-gobmx/basegfx/test/basegfx2d.cxx

749 lines
23 KiB
C++

// autogenerated file with codegen.pl
#include <cppunit/simpleheader.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <basegfx/curve/b2dbeziertools.hxx>
#ifndef _SOLAR_H
#include <tools/solar.h> // F_PI definition, no link dependency
#endif
#include <iostream>
#include <fstream>
#include "tools.hxx"
using namespace ::basegfx;
namespace basegfx2d
{
class b2dbeziertools : public CppUnit::TestFixture
{
private:
B2DCubicBezier aHalfCircle; // not exactly, but a look-alike
B2DCubicBezier aQuarterCircle; // not exactly, but a look-alike
B2DCubicBezier aLoop; // identical endpoints, curve goes back to where it started
B2DCubicBezier aStraightLineDistinctEndPoints; // truly a line
B2DCubicBezier aStraightLineDistinctEndPoints2; // truly a line, with slightly different control points
B2DCubicBezier aStraightLineIdenticalEndPoints; // degenerate case of aLoop
B2DCubicBezier aStraightLineIdenticalEndPoints2;// degenerate case of aLoop, with slightly different control points
B2DCubicBezier aCrossing; // curve self-intersects somewhere in the middle
B2DCubicBezier aCusp; // curve has a point of undefined tangency
public:
// initialise your test code values here.
void setUp()
{
const B2DPoint a00(0.0, 0.0);
const B2DPoint a10(1.0, 0.0);
const B2DPoint a11(1.0, 1.0);
const B2DPoint a01(0.0, 1.0);
const B2DPoint middle( 0.5, 0.5 );
const B2DPoint quarterDown( 0.25, 0.25 );
const B2DPoint quarterUp( 0.75, 0.75 );
aHalfCircle = B2DCubicBezier(a00, a01, a11, a10);
// The spline control points become
//
// (R * cos(A), R * sin(A))
// (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
// (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
// (R * cos(B), R * sin(B))
//
// where h = 4/3 * R * tan ((B-A)/4)
//
// with R being the radius, A start angle and B end angle (A < B).
//
// (This calculation courtesy Carl Worth, himself based on
// Michael Goldapp and Dokken/Daehlen)
// Choosing R=1, A=0, B=pi/2
const double h( 4.0/3.0 * tan(F_PI/8.0) );
aQuarterCircle = B2DCubicBezier(a10 + B2DPoint(1.0,0.0),
B2DPoint( 1.0, h ) + B2DPoint(1.0,0.0),
B2DPoint( h, 1.0) + B2DPoint(1.0,0.0),
a01 + B2DPoint(1.0,0.0));
aCusp = B2DCubicBezier(a00 + B2DPoint(2.0,0.0),
a11 + B2DPoint(2.0,0.0),
a01 + B2DPoint(2.0,0.0),
a10 + B2DPoint(2.0,0.0));
aLoop = B2DCubicBezier(a00 + B2DPoint(3.0,0.0),
a01 + B2DPoint(3.0,0.0),
a10 + B2DPoint(3.0,0.0),
a00 + B2DPoint(3.0,0.0));
aStraightLineDistinctEndPoints = B2DCubicBezier(a00 + B2DPoint(4.0,0.0),
middle + B2DPoint(4.0,0.0),
middle + B2DPoint(4.0,0.0),
a11 + B2DPoint(4.0,0.0));
aStraightLineDistinctEndPoints2 = B2DCubicBezier(a00 + B2DPoint(5.0,0.0),
quarterDown + B2DPoint(5.0,0.0),
quarterUp + B2DPoint(5.0,0.0),
a11 + B2DPoint(5.0,0.0));
aStraightLineIdenticalEndPoints = B2DCubicBezier(a00 + B2DPoint(6.0,0.0),
a11 + B2DPoint(6.0,0.0),
a11 + B2DPoint(6.0,0.0),
a00 + B2DPoint(6.0,0.0));
aStraightLineIdenticalEndPoints2 = B2DCubicBezier(a00 + B2DPoint(7.0,0.0),
quarterDown + B2DPoint(7.0,0.0),
quarterUp + B2DPoint(7.0,0.0),
a00 + B2DPoint(7.0,0.0));
aCrossing = B2DCubicBezier(a00 + B2DPoint(8.0,0.0),
B2DPoint(2.0,2.0) + B2DPoint(8.0,0.0),
B2DPoint(-1.0,2.0) + B2DPoint(8.0,0.0),
a10 + B2DPoint(8.0,0.0));
::std::ofstream output("bez_testcases.gnuplot");
testtools::Plotter aPlotter( output );
aPlotter.plot( aHalfCircle );
aPlotter.plot( aQuarterCircle );
aPlotter.plot( aCusp );
aPlotter.plot( aLoop );
aPlotter.plot( aStraightLineDistinctEndPoints );
aPlotter.plot( aStraightLineDistinctEndPoints2 );
aPlotter.plot( aStraightLineIdenticalEndPoints );
aPlotter.plot( aStraightLineIdenticalEndPoints2 );
aPlotter.plot( aCrossing );
}
void tearDown()
{
}
void adaptiveByDistance()
{
::std::ofstream output("bez_adaptiveByDistance.gnuplot");
testtools::Plotter aPlotter( output );
const double fBound( 0.0001 );
B2DPolygon result;
adaptiveSubdivideByDistance( result, aHalfCircle, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aQuarterCircle, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aLoop, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aStraightLineDistinctEndPoints, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aStraightLineDistinctEndPoints2, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aStraightLineIdenticalEndPoints, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aStraightLineIdenticalEndPoints2, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aCrossing, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByDistance( result, aCusp, fBound );
aPlotter.plot(result); result.clear();
CPPUNIT_ASSERT_MESSAGE("adaptiveByDistance", true );
}
void adaptiveByAngle()
{
const double fBound( 5.0 );
B2DPolygon result;
::std::ofstream output("bez_adaptiveByAngle.gnuplot");
testtools::Plotter aPlotter( output );
adaptiveSubdivideByAngle( result, aHalfCircle, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aQuarterCircle, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aLoop, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aStraightLineDistinctEndPoints, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aStraightLineDistinctEndPoints2, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aStraightLineIdenticalEndPoints, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aStraightLineIdenticalEndPoints2, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aCrossing, fBound );
aPlotter.plot(result); result.clear();
adaptiveSubdivideByAngle( result, aCusp, fBound );
aPlotter.plot(result); result.clear();
CPPUNIT_ASSERT_MESSAGE("adaptiveByAngle", true );
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dbeziertools);
CPPUNIT_TEST(adaptiveByDistance); // TODO: add tests for quadratic bezier (subdivide and degree reduction)
CPPUNIT_TEST(adaptiveByAngle);
CPPUNIT_TEST_SUITE_END();
}; // class b2dcubicbezier
class b2dcubicbezier : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
// this is demonstration code
// CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dcubicbezier);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dcubicbezier
class b2dhommatrix : public CppUnit::TestFixture
{
private:
B2DHomMatrix maIdentity;
B2DHomMatrix maScale;
B2DHomMatrix maTranslate;
B2DHomMatrix maShear;
B2DHomMatrix maAffine;
B2DHomMatrix maPerspective;
public:
// initialise your test code values here.
void setUp()
{
// setup some test matrices
maIdentity.identity(); // force compact layout
maIdentity.set(0,0, 1.0);
maIdentity.set(0,1, 0.0);
maIdentity.set(0,2, 0.0);
maIdentity.set(1,0, 0.0);
maIdentity.set(1,1, 1.0);
maIdentity.set(1,2, 0.0);
maScale.identity(); // force compact layout
maScale.set(0,0, 2.0);
maScale.set(1,1, 20.0);
maTranslate.identity(); // force compact layout
maTranslate.set(0,2, 20.0);
maTranslate.set(1,2, 2.0);
maShear.identity(); // force compact layout
maShear.set(0,1, 3.0);
maShear.set(1,0, 7.0);
maShear.set(1,1, 22.0);
maAffine.identity(); // force compact layout
maAffine.set(0,0, 1.0);
maAffine.set(0,1, 2.0);
maAffine.set(0,2, 3.0);
maAffine.set(1,0, 4.0);
maAffine.set(1,1, 5.0);
maAffine.set(1,2, 6.0);
maPerspective.set(0,0, 1.0);
maPerspective.set(0,1, 2.0);
maPerspective.set(0,2, 3.0);
maPerspective.set(1,0, 4.0);
maPerspective.set(1,1, 5.0);
maPerspective.set(1,2, 6.0);
maPerspective.set(2,0, 7.0);
maPerspective.set(2,1, 8.0);
maPerspective.set(2,2, 9.0);
}
void tearDown()
{
}
void equal()
{
B2DHomMatrix aIdentity;
B2DHomMatrix aScale;
B2DHomMatrix aTranslate;
B2DHomMatrix aShear;
B2DHomMatrix aAffine;
B2DHomMatrix aPerspective;
// setup some test matrices
aIdentity.identity(); // force compact layout
aIdentity.set(0,0, 1.0);
aIdentity.set(0,1, 0.0);
aIdentity.set(0,2, 0.0);
aIdentity.set(1,0, 0.0);
aIdentity.set(1,1, 1.0);
aIdentity.set(1,2, 0.0);
aScale.identity(); // force compact layout
aScale.set(0,0, 2.0);
aScale.set(1,1, 20.0);
aTranslate.identity(); // force compact layout
aTranslate.set(0,2, 20.0);
aTranslate.set(1,2, 2.0);
aShear.identity(); // force compact layout
aShear.set(0,1, 3.0);
aShear.set(1,0, 7.0);
aShear.set(1,1, 22.0);
aAffine.identity(); // force compact layout
aAffine.set(0,0, 1.0);
aAffine.set(0,1, 2.0);
aAffine.set(0,2, 3.0);
aAffine.set(1,0, 4.0);
aAffine.set(1,1, 5.0);
aAffine.set(1,2, 6.0);
aPerspective.set(0,0, 1.0);
aPerspective.set(0,1, 2.0);
aPerspective.set(0,2, 3.0);
aPerspective.set(1,0, 4.0);
aPerspective.set(1,1, 5.0);
aPerspective.set(1,2, 6.0);
aPerspective.set(2,0, 7.0);
aPerspective.set(2,1, 8.0);
aPerspective.set(2,2, 9.0);
CPPUNIT_ASSERT_MESSAGE("operator==: identity matrix", aIdentity == maIdentity);
CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale == maScale);
CPPUNIT_ASSERT_MESSAGE("operator==: translate matrix", aTranslate == maTranslate);
CPPUNIT_ASSERT_MESSAGE("operator==: shear matrix", aShear == maShear);
CPPUNIT_ASSERT_MESSAGE("operator==: affine matrix", aAffine == maAffine);
CPPUNIT_ASSERT_MESSAGE("operator==: perspective matrix", aPerspective == maPerspective);
}
void identity()
{
B2DHomMatrix ident;
CPPUNIT_ASSERT_MESSAGE("identity", maIdentity == ident);
}
void scale()
{
B2DHomMatrix mat;
mat.scale(2.0,20.0);
CPPUNIT_ASSERT_MESSAGE("scale", maScale == mat);
}
void translate()
{
B2DHomMatrix mat;
mat.translate(20.0,2.0);
CPPUNIT_ASSERT_MESSAGE("translate", maTranslate == mat);
}
void shear()
{
B2DHomMatrix mat;
mat.shearX(3.0);
mat.shearY(7.0);
CPPUNIT_ASSERT_MESSAGE("translate", maShear == mat);
}
void multiply()
{
B2DHomMatrix affineAffineProd;
affineAffineProd.set(0,0, 9);
affineAffineProd.set(0,1, 12);
affineAffineProd.set(0,2, 18);
affineAffineProd.set(1,0, 24);
affineAffineProd.set(1,1, 33);
affineAffineProd.set(1,2, 48);
B2DHomMatrix affinePerspectiveProd;
affinePerspectiveProd.set(0,0, 30);
affinePerspectiveProd.set(0,1, 36);
affinePerspectiveProd.set(0,2, 42);
affinePerspectiveProd.set(1,0, 66);
affinePerspectiveProd.set(1,1, 81);
affinePerspectiveProd.set(1,2, 96);
affinePerspectiveProd.set(2,0, 7);
affinePerspectiveProd.set(2,1, 8);
affinePerspectiveProd.set(2,2, 9);
B2DHomMatrix perspectiveAffineProd;
perspectiveAffineProd.set(0,0, 9);
perspectiveAffineProd.set(0,1, 12);
perspectiveAffineProd.set(0,2, 18);
perspectiveAffineProd.set(1,0, 24);
perspectiveAffineProd.set(1,1, 33);
perspectiveAffineProd.set(1,2, 48);
perspectiveAffineProd.set(2,0, 39);
perspectiveAffineProd.set(2,1, 54);
perspectiveAffineProd.set(2,2, 78);
B2DHomMatrix perspectivePerspectiveProd;
perspectivePerspectiveProd.set(0,0, 30);
perspectivePerspectiveProd.set(0,1, 36);
perspectivePerspectiveProd.set(0,2, 42);
perspectivePerspectiveProd.set(1,0, 66);
perspectivePerspectiveProd.set(1,1, 81);
perspectivePerspectiveProd.set(1,2, 96);
perspectivePerspectiveProd.set(2,0, 102);
perspectivePerspectiveProd.set(2,1, 126);
perspectivePerspectiveProd.set(2,2, 150);
B2DHomMatrix temp;
temp = maAffine;
temp*=maAffine;
CPPUNIT_ASSERT_MESSAGE("multiply: both compact", temp == affineAffineProd);
temp = maPerspective;
temp*=maAffine;
CPPUNIT_ASSERT_MESSAGE("multiply: first compact", temp == affinePerspectiveProd);
temp = maAffine;
temp*=maPerspective;
CPPUNIT_ASSERT_MESSAGE("multiply: second compact", temp == perspectiveAffineProd);
temp = maPerspective;
temp*=maPerspective;
CPPUNIT_ASSERT_MESSAGE("multiply: none compact", temp == perspectivePerspectiveProd);
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dhommatrix);
CPPUNIT_TEST(equal);
CPPUNIT_TEST(identity);
CPPUNIT_TEST(scale);
CPPUNIT_TEST(translate);
CPPUNIT_TEST(shear);
CPPUNIT_TEST(multiply);
CPPUNIT_TEST_SUITE_END();
}; // class b2dhommatrix
class b2dhompoint : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dhompoint);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dhompoint
class b2dpoint : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
// this is only demonstration code
void EmptyMethod()
{
// CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dpoint);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dpoint
class b2dpolygon : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dpolygon);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dpolygon
class b2dpolygontools : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
// this is only demonstration code
void EmptyMethod()
{
// CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dpolygontools);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dpolygontools
class b2dpolypolygon : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dpolypolygon);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dpolypolygon
class b2dquadraticbezier : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
// this is only demonstration code
void EmptyMethod()
{
// CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dquadraticbezier);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dquadraticbezier
class b2drange : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2drange);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2drange
class b2dtuple : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
// this is only demonstration code
void EmptyMethod()
{
// CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dtuple);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dtuple
class b2dvector : public CppUnit::TestFixture
{
public:
// initialise your test code values here.
void setUp()
{
}
void tearDown()
{
}
// insert your test code here.
void EmptyMethod()
{
CPPUNIT_ASSERT_STUB();
}
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
CPPUNIT_TEST_SUITE(b2dvector);
CPPUNIT_TEST(EmptyMethod);
CPPUNIT_TEST_SUITE_END();
}; // class b2dvector
// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dbeziertools, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dcubicbezier, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dhommatrix, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dhompoint, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dpoint, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dpolygon, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dpolygontools, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dpolypolygon, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dquadraticbezier, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2drange, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dtuple, "basegfx2d");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(basegfx2d::b2dvector, "basegfx2d");
} // namespace basegfx2d
// -----------------------------------------------------------------------------
// this macro creates an empty function, which will called by the RegisterAllFunctions()
// to let the user the possibility to also register some functions by hand.
// NOADDITIONAL;