| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basegfx.hxx" |
| // autogenerated file with codegen.pl |
| |
| #include "preextstl.h" |
| #include "cppunit/TestAssert.h" |
| #include "cppunit/TestFixture.h" |
| #include "cppunit/extensions/HelperMacros.h" |
| #include "postextstl.h" |
| |
| #include <basegfx/matrix/b2dhommatrix.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <basegfx/curve/b2dcubicbezier.hxx> |
| #include <basegfx/curve/b2dbeziertools.hxx> |
| #include <basegfx/polygon/b2dpolypolygontools.hxx> |
| #include <basegfx/polygon/b2dpolygonclipper.hxx> |
| #include <basegfx/polygon/b2dpolypolygon.hxx> |
| #include <basegfx/range/b2dpolyrange.hxx> |
| #include <basegfx/numeric/ftools.hxx> |
| #include <basegfx/color/bcolor.hxx> |
| #include <basegfx/color/bcolortools.hxx> |
| |
| #include <basegfx/tools/debugplotter.hxx> |
| |
| #include <iostream> |
| #include <fstream> |
| |
| using namespace ::basegfx; |
| |
| |
| namespace basegfx2d |
| { |
| |
| class b2dsvgdimpex : public CppUnit::TestFixture |
| { |
| private: |
| ::rtl::OUString aPath0; |
| ::rtl::OUString aPath1; |
| ::rtl::OUString aPath2; |
| ::rtl::OUString aPath3; |
| |
| public: |
| // initialise your test code values here. |
| void setUp() |
| { |
| // simple rectangle |
| aPath0 = ::rtl::OUString::createFromAscii( |
| "M 10 10-10 10-10-10 10-10Z" ); |
| |
| // simple bezier polygon |
| aPath1 = ::rtl::OUString::createFromAscii( |
| "m11430 0c-8890 3810 5715 6985 5715 6985 " |
| "0 0-17145-1905-17145-1905 0 0 22860-10160 " |
| "16510 6350-6350 16510-3810-11430-3810-11430z" ); |
| |
| // '@' as a bezier polygon |
| aPath2 = ::rtl::OUString::createFromAscii( |
| "m1917 1114c-89-189-233-284-430-284-167 " |
| "0-306 91-419 273-113 182-170 370-170 564 " |
| "0 145 33 259 98 342 65 84 150 126 257 126 " |
| "77 0 154-19 231-57 77-38 147-97 210-176 63" |
| "-79 99-143 109-190 38-199 76-398 114-598z" |
| "m840 1646c-133 73-312 139-537 197-225 57" |
| "-440 86-644 87-483-1-866-132-1150-392-284" |
| "-261-426-619-426-1076 0-292 67-560 200-803 " |
| "133-243 321-433 562-569 241-136 514-204 821" |
| "-204 405 0 739 125 1003 374 264 250 396 550 " |
| "396 899 0 313-88 576-265 787-177 212-386 318" |
| "-627 318-191 0-308-94-352-281-133 187-315 281" |
| "-546 281-172 0-315-67-428-200-113-133-170-301" |
| "-170-505 0-277 90-527 271-751 181-223 394" |
| "-335 640-335 196 0 353 83 470 250 13-68 26" |
| "-136 41-204 96 0 192 0 288 0-74 376-148 752" |
| "-224 1128-21 101-31 183-31 245 0 39 9 70 26 " |
| "93 17 24 39 36 67 36 145 0 279-80 400-240 121" |
| "-160 182-365 182-615 0-288-107-533-322-734" |
| "-215-201-487-301-816-301-395 0-715 124-960 " |
| "373-245 249-368 569-368 958 0 385 119 685 " |
| "357 900 237 216 557 324 958 325 189-1 389-27 " |
| "600-77 211-52 378-110 503-174 27 70 54 140 81 210z" ); |
| |
| // first part of 'Hello World' as a line polygon |
| aPath3 = ::rtl::OUString::createFromAscii( |
| "m1598 125h306v2334h-306v-1105h-1293v1105h-305v" |
| "-2334h305v973h1293zm2159 1015 78-44 85 235-91 " |
| "47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102" |
| "-4-97-12-91-19-85-26-40-16-39-18-38-20-36-22-34" |
| "-24-33-26-32-27-30-30-29-31-27-33-25-33-23-36-21" |
| "-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3" |
| "-98 11-94 17-89 24-84 31-79 37-75 22-35 23-34 24" |
| "-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35" |
| "-18 37-17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 " |
| "78 10 37 9 37 9 36 12 35 14 33 15 33 17 32 19 31 " |
| "21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 " |
| "34 18 36 30 74 23 80 17 84 10 89 3 94v78h-1277l6 " |
| "75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 " |
| "23 17 22 19 21 19 20 21 18 21 18 23 16 23 14 24 " |
| "14 26 12 26 11 27 10 28 8 59 13 63 7 67 3 80-3 81" |
| "-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l" |
| "-7-51-11-49-14-46-17-43-21-40-24-38-27-36-31-32" |
| "-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 " |
| "2-46 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32" |
| "-29 34-26 38-23 41-20 44-17 47zm1648-1293h288v" |
| "2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 " |
| "91-4 91 4 85 12 42 8 39 11 39 13 38 14 36 17 35 18 " |
| "34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 23 " |
| "34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100" |
| "-11 95-16 89-24 85-31 80-37 74-21 35-23 35-25 32-26 " |
| "32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17" |
| "-38 14-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9" |
| "-40-10-39-13-37-14-36-17-35-18-34-21-33-22-31-24-30" |
| "-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80" |
| "-24-85-17-89-11-95-3-100 3-101 11-95 17-90 24-85 30" |
| "-79 38-75 21-35 23-35 25-32 26-32 28-30 29-28 30-26 " |
| "31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z" ); |
| } |
| |
| void tearDown() |
| { |
| } |
| |
| void impex() |
| { |
| B2DPolyPolygon aPoly; |
| ::rtl::OUString aExport; |
| |
| CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D", |
| tools::importFromSvgD( aPoly, aPath0, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| const char* sExportString = "m10 10h-20v-20h20z"; |
| CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D", |
| !aExport.compareToAscii(sExportString) ); |
| CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip", |
| tools::importFromSvgD( aPoly, aExport, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D (round-trip)", |
| !aExport.compareToAscii(sExportString)); |
| |
| CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", |
| tools::importFromSvgD( aPoly, aPath1, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| |
| // Adaptions for B2DPolygon bezier change (see #i77162#): |
| // |
| // The import/export of aPath1 does not reproduce aExport again. This is |
| // correct since aPath1 contains a segment with non-used control points |
| // which gets exported now correctly as 'l' and also a point (#4, index 3) |
| // with C2 continuity which produces a 's' staement now. |
| // |
| // The old SVGexport identified nun-used ControlVectors erraneously as bezier segments |
| // because the 2nd vector at the start point was used, even when added |
| // with start point was identical to end point. Exactly for that reason |
| // i reworked the B2DPolygon to use prev, next control points. |
| // |
| // so for correct unit test i add the new exported string here as sExportStringSimpleBezier |
| // and compare to it. |
| const char* sExportStringSimpleBezier = |
| "m11430 0c-8890 3810 5715 6985 5715 6985" |
| "l-17145-1905c0 0 22860-10160 16510 6350" |
| "s-3810-11430-3810-11430z"; |
| CPPUNIT_ASSERT_MESSAGE("exporting bezier polygon to SVG-D", !aExport.compareToAscii(sExportStringSimpleBezier)); |
| |
| // Adaptions for B2DPolygon bezier change (see #i77162#): |
| // |
| // a 2nd good test is that re-importing of aExport has to create the same |
| // B2DPolPolygon again: |
| B2DPolyPolygon aReImport; |
| CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0)); |
| CPPUNIT_ASSERT_MESSAGE("re-imported polygon needs to be identical", aReImport == aPoly); |
| |
| CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2, , false, 0)); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| |
| // Adaptions for B2DPolygon bezier change (see #i77162#): |
| // |
| // same here, the corrected export with the corrected B2DPolygon is simply more efficient, |
| // so i needed to change the compare string. Also adding the re-import comparison below. |
| const char* sExportString1 = |
| "m1917 1114c-89-189-233-284-430-284-167 0-306 91-419 273s-170 370-17" |
| "0 564c0 145 33 259 98 342 65 84 150 126 257 126q115.5 0 231-57s147-97 210-176 99-143 109-190c38-199 76-398 114" |
| "-598zm840 1646c-133 73-312 139-537 197-225 57-440 86-644 87-483-1-866-132-1150-392-284-261-426-619-426-1076 0-" |
| "292 67-560 200-803s321-433 562-569 514-204 821-204c405 0 739 125 1003 374 264 250 396 550 396 899 0 313-88 576" |
| "-265 787q-265.5 318-627 318c-191 0-308-94-352-281-133 187-315 281-546 281-172 0-315-67-428-200s-170-301-170-50" |
| "5c0-277 90-527 271-751 181-223 394-335 640-335 196 0 353 83 470 250 13-68 26-136 41-204q144 0 288 0c-74 376-14" |
| "8 752-224 1128-21 101-31 183-31 245 0 39 9 70 26 93 17 24 39 36 67 36 145 0 279-80 400-240s182-365 182-615c0-2" |
| "88-107-533-322-734s-487-301-816-301c-395 0-715 124-960 373s-368 569-368 958q0 577.5 357 900c237 216 557 324 95" |
| "8 325 189-1 389-27 600-77 211-52 378-110 503-174q40.5 105 81 210z"; |
| CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0)); |
| CPPUNIT_ASSERT_MESSAGE("re-imported '@' needs to be identical", aReImport == aPoly); |
| |
| CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D", !aExport.compareToAscii(sExportString1)); |
| CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip", |
| tools::importFromSvgD( aPoly, aExport, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D (round-trip)", |
| !aExport.compareToAscii(sExportString1)); |
| |
| |
| CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D", |
| tools::importFromSvgD( aPoly, aPath3, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| const char* sExportString2 = |
| "m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293" |
| "zm2159 1015 78-44 85 235-91 47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102-4-97" |
| "-12-91-19-85-26-40-16-39-18-38-20-36-22-34-24-33-26-32-27-30-30-29-31-27-33-25-3" |
| "3-23-36-21-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3-98 11-94 17-89 24-84 3" |
| "1-79 37-75 22-35 23-34 24-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35-18 37-" |
| "17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 78 10 37 9 37 9 36 12 35 14 33 15 33 1" |
| "7 32 19 31 21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 34 18 36 30 74 23 80 " |
| "17 84 10 89 3 94v78h-1277l6 75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 23 1" |
| "7 22 19 21 19 20 21 18 21 18 23 16 23 14 24 14 26 12 26 11 27 10 28 8 59 13 63 7" |
| " 67 3 80-3 81-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l-7-51-11-49-14-46-1" |
| "7-43-21-40-24-38-27-36-31-32-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 2-4" |
| "6 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32-29 34-26 38-23 41-20 44-17 47zm1648" |
| "-1293h288v2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 91-4 91 4 85 12 42 " |
| "8 39 11 39 13 38 14 36 17 35 18 34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 " |
| "23 34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100-11 95-16 89-24 85-31 80-37" |
| " 74-21 35-23 35-25 32-26 32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17-38 1" |
| "4-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9-40-10-39-13-37-14-36-17-35-18-34-2" |
| "1-33-22-31-24-30-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80-24-85-17-89-" |
| "11-95-3-100 3-101 11-95 17-90 24-85 30-79 38-75 21-35 23-35 25-32 26-32 28-30 29" |
| "-28 30-26 31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z"; |
| CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D", |
| !aExport.compareToAscii(sExportString2)); |
| CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip", |
| tools::importFromSvgD( aPoly, aExport, false, 0 )); |
| aExport = tools::exportToSvgD( aPoly, true, true, false ); |
| CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D (round-trip)", |
| !aExport.compareToAscii(sExportString2)); |
| |
| const B2DPolygon aRect( |
| tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) )); |
| aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false, false ); |
| |
| const char* sExportStringRect = "M0 0H4000V4000H0Z"; |
| CPPUNIT_ASSERT_MESSAGE("exporting to rectangle svg-d string", |
| !aExport.compareToAscii(sExportStringRect)); |
| } |
| |
| // 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(b2dsvgdimpex); |
| CPPUNIT_TEST(impex); |
| CPPUNIT_TEST_SUITE_END(); |
| }; // class b2dsvgdimpex |
| |
| class b2dpolyrange : public CppUnit::TestFixture |
| { |
| private: |
| public: |
| void setUp() |
| {} |
| |
| void tearDown() |
| {} |
| |
| void check() |
| { |
| B2DPolyRange aRange; |
| aRange.appendElement(B2DRange(0,0,1,1),ORIENTATION_POSITIVE); |
| aRange.appendElement(B2DRange(2,2,3,3),ORIENTATION_POSITIVE); |
| |
| CPPUNIT_ASSERT_MESSAGE("simple poly range - count", |
| aRange.count() == 2); |
| CPPUNIT_ASSERT_MESSAGE("simple poly range - first element", |
| aRange.getElement(0).head == B2DRange(0,0,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("simple poly range - second element", |
| aRange.getElement(1).head == B2DRange(2,2,3,3)); |
| |
| // B2DPolyRange relies on correctly orientated rects |
| const B2DRange aRect(0,0,1,1); |
| CPPUNIT_ASSERT_MESSAGE("createPolygonFromRect - correct orientation", |
| tools::getOrientation( |
| tools::createPolygonFromRect(aRect)) == ORIENTATION_POSITIVE ); |
| } |
| |
| // 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(b2dpolyrange); |
| CPPUNIT_TEST(check); |
| CPPUNIT_TEST_SUITE_END(); |
| }; |
| |
| 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(M_PI/8.0) ); |
| aQuarterCircle = B2DCubicBezier(a10 + B2DPoint(1.0,0.0), |
| B2DPoint(B2DPoint( 1.0, h ) + B2DPoint(1.0,0.0)), |
| B2DPoint(B2DPoint( h, 1.0) + B2DPoint(1.0,0.0)), |
| a01 + B2DPoint(1.0,0.0)); |
| |
| aCusp = B2DCubicBezier(a00 + B2DPoint(2.0,0.0), |
| B2DPoint(a11 + B2DPoint(2.0,0.0)), |
| B2DPoint(a01 + B2DPoint(2.0,0.0)), |
| a10 + B2DPoint(2.0,0.0)); |
| |
| aLoop = B2DCubicBezier(a00 + B2DPoint(3.0,0.0), |
| B2DPoint(a01 + B2DPoint(3.0,0.0)), |
| B2DPoint(a10 + B2DPoint(3.0,0.0)), |
| a00 + B2DPoint(3.0,0.0)); |
| |
| aStraightLineDistinctEndPoints = B2DCubicBezier(a00 + B2DPoint(4.0,0.0), |
| B2DPoint(middle + B2DPoint(4.0,0.0)), |
| B2DPoint(middle + B2DPoint(4.0,0.0)), |
| a11 + B2DPoint(4.0,0.0)); |
| |
| aStraightLineDistinctEndPoints2 = B2DCubicBezier(a00 + B2DPoint(5.0,0.0), |
| B2DPoint(quarterDown + B2DPoint(5.0,0.0)), |
| B2DPoint(quarterUp + B2DPoint(5.0,0.0)), |
| a11 + B2DPoint(5.0,0.0)); |
| |
| aStraightLineIdenticalEndPoints = B2DCubicBezier(a00 + B2DPoint(6.0,0.0), |
| B2DPoint(a11 + B2DPoint(6.0,0.0)), |
| B2DPoint(a11 + B2DPoint(6.0,0.0)), |
| a00 + B2DPoint(6.0,0.0)); |
| |
| aStraightLineIdenticalEndPoints2 = B2DCubicBezier(a00 + B2DPoint(7.0,0.0), |
| B2DPoint(quarterDown + B2DPoint(7.0,0.0)), |
| B2DPoint(quarterUp + B2DPoint(7.0,0.0)), |
| a00 + B2DPoint(7.0,0.0)); |
| |
| aCrossing = B2DCubicBezier(a00 + B2DPoint(8.0,0.0), |
| B2DPoint(B2DPoint(2.0,2.0) + B2DPoint(8.0,0.0)), |
| B2DPoint(B2DPoint(-1.0,2.0) + B2DPoint(8.0,0.0)), |
| a10 + B2DPoint(8.0,0.0)); |
| |
| ::std::ofstream output("bez_testcases.gnuplot"); |
| DebugPlotter aPlotter( "Original curves", |
| output ); |
| |
| aPlotter.plot( aHalfCircle, |
| "half circle" ); |
| aPlotter.plot( aQuarterCircle, |
| "quarter circle" ); |
| aPlotter.plot( aCusp, |
| "cusp" ); |
| aPlotter.plot( aLoop, |
| "loop" ); |
| aPlotter.plot( aStraightLineDistinctEndPoints, |
| "straight line 0" ); |
| aPlotter.plot( aStraightLineDistinctEndPoints2, |
| "straight line 1" ); |
| aPlotter.plot( aStraightLineIdenticalEndPoints, |
| "straight line 2" ); |
| aPlotter.plot( aStraightLineIdenticalEndPoints2, |
| "straight line 3" ); |
| aPlotter.plot( aCrossing, |
| "crossing" ); |
| |
| // break up a complex bezier (loopy, spiky or self intersecting) |
| // into simple segments (left to right) |
| B2DCubicBezier aSegment = aCrossing; |
| double fExtremePos(0.0); |
| |
| aPlotter.plot( aSegment, "segment" ); |
| while(aSegment.getMinimumExtremumPosition(fExtremePos)) |
| { |
| aSegment.split(fExtremePos, 0, &aSegment); |
| aPlotter.plot( aSegment, "segment" ); |
| } |
| } |
| |
| void tearDown() |
| { |
| } |
| |
| void adaptiveByDistance() |
| { |
| ::std::ofstream output("bez_adaptiveByDistance.gnuplot"); |
| DebugPlotter aPlotter( "distance-adaptive subdivision", |
| output ); |
| |
| const double fBound( 0.0001 ); |
| B2DPolygon result; |
| |
| aHalfCircle.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "half circle"); result.clear(); |
| |
| aQuarterCircle.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "quarter circle"); result.clear(); |
| |
| aLoop.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "loop"); result.clear(); |
| |
| aStraightLineDistinctEndPoints.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 0"); result.clear(); |
| |
| aStraightLineDistinctEndPoints2.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 1"); result.clear(); |
| |
| aStraightLineIdenticalEndPoints.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 2"); result.clear(); |
| |
| aStraightLineIdenticalEndPoints2.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 3"); result.clear(); |
| |
| aCrossing.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 4"); result.clear(); |
| |
| aCusp.adaptiveSubdivideByDistance(result, fBound); |
| aPlotter.plot(result, |
| "straight line 5"); result.clear(); |
| |
| CPPUNIT_ASSERT_MESSAGE("adaptiveByDistance", true ); |
| } |
| |
| void adaptiveByAngle() |
| { |
| const double fBound( 5.0 ); |
| B2DPolygon result; |
| |
| ::std::ofstream output("bez_adaptiveByAngle.gnuplot"); |
| DebugPlotter aPlotter( "angle-adaptive subdivision", |
| output ); |
| |
| aHalfCircle.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "half circle"); result.clear(); |
| |
| aQuarterCircle.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "quarter cirle"); result.clear(); |
| |
| aLoop.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "loop"); result.clear(); |
| |
| aStraightLineDistinctEndPoints.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 0"); result.clear(); |
| |
| aStraightLineDistinctEndPoints2.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 1"); result.clear(); |
| |
| aStraightLineIdenticalEndPoints.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 2"); result.clear(); |
| |
| aStraightLineIdenticalEndPoints2.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 3"); result.clear(); |
| |
| aCrossing.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 4"); result.clear(); |
| |
| aCusp.adaptiveSubdivideByAngle(result, fBound, true); |
| aPlotter.plot(result, |
| "straight line 5"); 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); |
| } |
| |
| // 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); |
| } |
| |
| void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, double fRotate) |
| { |
| // fill rSource with a linear combination of scale, shear and rotate |
| rSource.identity(); |
| rSource.scale(fScaleX, fScaleY); |
| rSource.shearX(fShearX); |
| rSource.rotate(fRotate); |
| } |
| |
| bool impDecomposeComposeTest(double fScaleX, double fScaleY, double fShearX, double fRotate) |
| { |
| // linear combine matrix with given values |
| B2DHomMatrix aSource; |
| impFillMatrix(aSource, fScaleX, fScaleY, fShearX, fRotate); |
| |
| // decompose that matrix |
| B2DTuple aDScale; |
| B2DTuple aDTrans; |
| double fDRot; |
| double fDShX; |
| bool bWorked = aSource.decompose(aDScale, aDTrans, fDRot, fDShX); |
| |
| // linear combine another matrix with decomposition results |
| B2DHomMatrix aRecombined; |
| impFillMatrix(aRecombined, aDScale.getX(), aDScale.getY(), fDShX, fDRot); |
| |
| // if decomposition worked, matrices need to be the same |
| return bWorked && aSource == aRecombined; |
| } |
| |
| void decompose() |
| { |
| // test matrix decompositions. Each matrix decomposed and rebuilt |
| // using the decompose result should be the same as before. Test |
| // with all ranges of values. Translations are not tested since these |
| // are just the two rightmost values and uncritical |
| static double fSX(10.0); |
| static double fSY(12.0); |
| static double fR(45.0 * F_PI180); |
| static double fS(15.0 * F_PI180); |
| |
| // check all possible scaling combinations |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test A1", impDecomposeComposeTest(fSX, fSY, 0.0, 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test A2", impDecomposeComposeTest(-fSX, fSY, 0.0, 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test A3", impDecomposeComposeTest(fSX, -fSY, 0.0, 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test A4", impDecomposeComposeTest(-fSX, -fSY, 0.0, 0.0)); |
| |
| // check all possible scaling combinations with positive rotation |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test B1", impDecomposeComposeTest(fSX, fSY, 0.0, fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test B2", impDecomposeComposeTest(-fSX, fSY, 0.0, fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test B3", impDecomposeComposeTest(fSX, -fSY, 0.0, fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test B4", impDecomposeComposeTest(-fSX, -fSY, 0.0, fR)); |
| |
| // check all possible scaling combinations with negative rotation |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test C1", impDecomposeComposeTest(fSX, fSY, 0.0, -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test C2", impDecomposeComposeTest(-fSX, fSY, 0.0, -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test C3", impDecomposeComposeTest(fSX, -fSY, 0.0, -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test C4", impDecomposeComposeTest(-fSX, -fSY, 0.0, -fR)); |
| |
| // check all possible scaling combinations with positive shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test D1", impDecomposeComposeTest(fSX, fSY, tan(fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test D2", impDecomposeComposeTest(-fSX, fSY, tan(fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test D3", impDecomposeComposeTest(fSX, -fSY, tan(fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test D4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), 0.0)); |
| |
| // check all possible scaling combinations with negative shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test E1", impDecomposeComposeTest(fSX, fSY, tan(-fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test E2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test E3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), 0.0)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test E4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), 0.0)); |
| |
| // check all possible scaling combinations with positive rotate and positive shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test F1", impDecomposeComposeTest(fSX, fSY, tan(fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test F2", impDecomposeComposeTest(-fSX, fSY, tan(fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test F3", impDecomposeComposeTest(fSX, -fSY, tan(fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test F4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), fR)); |
| |
| // check all possible scaling combinations with negative rotate and positive shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test G1", impDecomposeComposeTest(fSX, fSY, tan(fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test G2", impDecomposeComposeTest(-fSX, fSY, tan(fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test G3", impDecomposeComposeTest(fSX, -fSY, tan(fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test G4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), -fR)); |
| |
| // check all possible scaling combinations with positive rotate and negative shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test H1", impDecomposeComposeTest(fSX, fSY, tan(-fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test H2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test H3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test H4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), fR)); |
| |
| // check all possible scaling combinations with negative rotate and negative shear |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test I1", impDecomposeComposeTest(fSX, fSY, tan(-fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test I2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test I3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), -fR)); |
| CPPUNIT_ASSERT_MESSAGE("decompose: error test I4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), -fR)); |
| } |
| |
| // 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(decompose); |
| 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() |
| { |
| } |
| |
| // 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); |
| } |
| |
| // 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 testBasics() |
| { |
| B2DPolygon aPoly; |
| |
| aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3)); |
| |
| CPPUNIT_ASSERT_MESSAGE("#1 first polygon point wrong", |
| aPoly.getB2DPoint(0) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("#1 first control point wrong", |
| aPoly.getPrevControlPoint(0) == B2DPoint(2,2)); |
| CPPUNIT_ASSERT_MESSAGE("#1 second control point wrong", |
| aPoly.getNextControlPoint(0) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("next control point not used", |
| aPoly.isNextControlPointUsed(0) == false); |
| |
| aPoly.setNextControlPoint(0,B2DPoint(4,4)); |
| CPPUNIT_ASSERT_MESSAGE("#1.1 second control point wrong", |
| aPoly.getNextControlPoint(0) == B2DPoint(4,4)); |
| CPPUNIT_ASSERT_MESSAGE("next control point used", |
| aPoly.isNextControlPointUsed(0) == true); |
| CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong", |
| aPoly.areControlPointsUsed() == true); |
| CPPUNIT_ASSERT_MESSAGE("getContinuityInPoint() wrong", |
| aPoly.getContinuityInPoint(0) == CONTINUITY_C2); |
| |
| aPoly.resetControlPoints(); |
| CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", |
| aPoly.getB2DPoint(0) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", |
| aPoly.getPrevControlPoint(0) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", |
| aPoly.getNextControlPoint(0) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong #2", |
| aPoly.areControlPointsUsed() == false); |
| |
| aPoly.clear(); |
| aPoly.append(B2DPoint(0,0)); |
| aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3)); |
| |
| CPPUNIT_ASSERT_MESSAGE("#2 first polygon point wrong", |
| aPoly.getB2DPoint(0) == B2DPoint(0,0)); |
| CPPUNIT_ASSERT_MESSAGE("#2 first control point wrong", |
| aPoly.getPrevControlPoint(0) == B2DPoint(0,0)); |
| CPPUNIT_ASSERT_MESSAGE("#2 second control point wrong", |
| aPoly.getNextControlPoint(0) == B2DPoint(1,1)); |
| CPPUNIT_ASSERT_MESSAGE("#2 third control point wrong", |
| aPoly.getPrevControlPoint(1) == B2DPoint(2,2)); |
| CPPUNIT_ASSERT_MESSAGE("#2 fourth control point wrong", |
| aPoly.getNextControlPoint(1) == B2DPoint(3,3)); |
| CPPUNIT_ASSERT_MESSAGE("#2 second polygon point wrong", |
| aPoly.getB2DPoint(1) == B2DPoint(3,3)); |
| } |
| // 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(testBasics); |
| 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 testIsRectangle() |
| { |
| B2DPolygon aRect1( |
| tools::createPolygonFromRect( |
| B2DRange(0,0,1,1) ) ); |
| |
| B2DPolygon aRect2; |
| aRect2.append( B2DPoint(0,0) ); |
| aRect2.append( B2DPoint(1,0) ); |
| aRect2.append( B2DPoint(1,.5)); |
| aRect2.append( B2DPoint(1,1) ); |
| aRect2.append( B2DPoint(0,1) ); |
| aRect2.setClosed(true); |
| |
| B2DPolygon aNonRect1; |
| aNonRect1.append( B2DPoint(0,0) ); |
| aNonRect1.append( B2DPoint(1,0) ); |
| aNonRect1.append( B2DPoint(1,1) ); |
| aNonRect1.append( B2DPoint(0.5,1) ); |
| aNonRect1.append( B2DPoint(0.5,0) ); |
| aNonRect1.setClosed(true); |
| |
| B2DPolygon aNonRect2; |
| aNonRect2.append( B2DPoint(0,0) ); |
| aNonRect2.append( B2DPoint(1,1) ); |
| aNonRect2.append( B2DPoint(1,0) ); |
| aNonRect2.append( B2DPoint(0,1) ); |
| aNonRect2.setClosed(true); |
| |
| B2DPolygon aNonRect3; |
| aNonRect3.append( B2DPoint(0,0) ); |
| aNonRect3.append( B2DPoint(1,0) ); |
| aNonRect3.append( B2DPoint(1,1) ); |
| aNonRect3.setClosed(true); |
| |
| B2DPolygon aNonRect4; |
| aNonRect4.append( B2DPoint(0,0) ); |
| aNonRect4.append( B2DPoint(1,0) ); |
| aNonRect4.append( B2DPoint(1,1) ); |
| aNonRect4.append( B2DPoint(0,1) ); |
| |
| B2DPolygon aNonRect5; |
| aNonRect5.append( B2DPoint(0,0) ); |
| aNonRect5.append( B2DPoint(1,0) ); |
| aNonRect5.append( B2DPoint(1,1) ); |
| aNonRect5.append( B2DPoint(0,1) ); |
| aNonRect5.setControlPoints(1,B2DPoint(1,0),B2DPoint(-11,0)); |
| aNonRect5.setClosed(true); |
| |
| CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 1", |
| tools::isRectangle( aRect1 )); |
| CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 2", |
| tools::isRectangle( aRect2 )); |
| CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 1", |
| !tools::isRectangle( aNonRect1 )); |
| CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 2", |
| !tools::isRectangle( aNonRect2 )); |
| CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 3", |
| !tools::isRectangle( aNonRect3 )); |
| CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 4", |
| !tools::isRectangle( aNonRect4 )); |
| CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 5", |
| !tools::isRectangle( aNonRect5 )); |
| } |
| |
| // 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(testIsRectangle); |
| 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() |
| { |
| } |
| |
| // 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); |
| } |
| |
| // 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() |
| { |
| } |
| |
| // 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); |
| } |
| |
| // 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() |
| { |
| } |
| |
| // 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 |
| |
| class bcolor : public CppUnit::TestFixture |
| { |
| BColor maWhite; |
| BColor maBlack; |
| BColor maRed; |
| BColor maGreen; |
| BColor maBlue; |
| BColor maYellow; |
| BColor maMagenta; |
| BColor maCyan; |
| |
| public: |
| bcolor() : |
| maWhite(1,1,1), |
| maBlack(0,0,0), |
| maRed(1,0,0), |
| maGreen(0,1,0), |
| maBlue(0,0,1), |
| maYellow(1,1,0), |
| maMagenta(1,0,1), |
| maCyan(0,1,1) |
| {} |
| |
| |
| // initialise your test code values here. |
| void setUp() |
| { |
| } |
| |
| void tearDown() |
| { |
| } |
| |
| // insert your test code here. |
| void hslTest() |
| { |
| CPPUNIT_ASSERT_MESSAGE("white", |
| tools::rgb2hsl(maWhite) == BColor(0,0,1)); |
| CPPUNIT_ASSERT_MESSAGE("black", |
| tools::rgb2hsl(maBlack) == BColor(0,0,0)); |
| CPPUNIT_ASSERT_MESSAGE("red", |
| tools::rgb2hsl(maRed) == BColor(0,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("green", |
| tools::rgb2hsl(maGreen) == BColor(120,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("blue", |
| tools::rgb2hsl(maBlue) == BColor(240,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("yellow", |
| tools::rgb2hsl(maYellow) == BColor(60,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("magenta", |
| tools::rgb2hsl(maMagenta) == BColor(300,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("cyan", |
| tools::rgb2hsl(maCyan) == BColor(180,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("third hue case", |
| tools::rgb2hsl(BColor(0,0.5,1)) == BColor(210,1,0.5)); |
| |
| CPPUNIT_ASSERT_MESSAGE("roundtrip white", |
| tools::hsl2rgb(tools::rgb2hsl(maWhite)) == maWhite); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip black", |
| tools::hsl2rgb(tools::rgb2hsl(maBlack)) == maBlack); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip red", |
| tools::hsl2rgb(tools::rgb2hsl(maRed)) == maRed); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip green", |
| tools::hsl2rgb(tools::rgb2hsl(maGreen)) == maGreen); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip blue", |
| tools::hsl2rgb(tools::rgb2hsl(maBlue)) == maBlue); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip yellow", |
| tools::hsl2rgb(tools::rgb2hsl(maYellow)) == maYellow); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip magenta", |
| tools::hsl2rgb(tools::rgb2hsl(maMagenta)) == maMagenta); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip cyan", |
| tools::hsl2rgb(tools::rgb2hsl(maCyan)) == maCyan); |
| |
| CPPUNIT_ASSERT_MESSAGE("grey10", |
| tools::rgb2hsl(maWhite*.1) == BColor(0,0,.1)); |
| CPPUNIT_ASSERT_MESSAGE("grey90", |
| tools::rgb2hsl(maWhite*.9) == BColor(0,0,.9)); |
| CPPUNIT_ASSERT_MESSAGE("red/2", |
| tools::rgb2hsl(maRed*.5) == BColor(0,1,0.25)); |
| CPPUNIT_ASSERT_MESSAGE("green/2", |
| tools::rgb2hsl(maGreen*.5) == BColor(120,1,0.25)); |
| CPPUNIT_ASSERT_MESSAGE("blue/2", |
| tools::rgb2hsl(maBlue*.5) == BColor(240,1,0.25)); |
| CPPUNIT_ASSERT_MESSAGE("yellow/2", |
| tools::rgb2hsl(maYellow*.5) == BColor(60,1,0.25)); |
| CPPUNIT_ASSERT_MESSAGE("magenta/2", |
| tools::rgb2hsl(maMagenta*.5) == BColor(300,1,0.25)); |
| CPPUNIT_ASSERT_MESSAGE("cyan/2", |
| tools::rgb2hsl(maCyan*.5) == BColor(180,1,0.25)); |
| |
| CPPUNIT_ASSERT_MESSAGE("pastel", |
| tools::rgb2hsl(BColor(.75,.25,.25)) == BColor(0,.5,.5)); |
| } |
| |
| // insert your test code here. |
| void hsvTest() |
| { |
| CPPUNIT_ASSERT_MESSAGE("white", |
| tools::rgb2hsv(maWhite) == BColor(0,0,1)); |
| CPPUNIT_ASSERT_MESSAGE("black", |
| tools::rgb2hsv(maBlack) == BColor(0,0,0)); |
| CPPUNIT_ASSERT_MESSAGE("red", |
| tools::rgb2hsv(maRed) == BColor(0,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("green", |
| tools::rgb2hsv(maGreen) == BColor(120,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("blue", |
| tools::rgb2hsv(maBlue) == BColor(240,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("yellow", |
| tools::rgb2hsv(maYellow) == BColor(60,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("magenta", |
| tools::rgb2hsv(maMagenta) == BColor(300,1,1)); |
| CPPUNIT_ASSERT_MESSAGE("cyan", |
| tools::rgb2hsv(maCyan) == BColor(180,1,1)); |
| |
| CPPUNIT_ASSERT_MESSAGE("roundtrip white", |
| tools::hsv2rgb(tools::rgb2hsv(maWhite)) == maWhite); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip black", |
| tools::hsv2rgb(tools::rgb2hsv(maBlack)) == maBlack); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip red", |
| tools::hsv2rgb(tools::rgb2hsv(maRed)) == maRed); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip green", |
| tools::hsv2rgb(tools::rgb2hsv(maGreen)) == maGreen); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip blue", |
| tools::hsv2rgb(tools::rgb2hsv(maBlue)) == maBlue); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip yellow", |
| tools::hsv2rgb(tools::rgb2hsv(maYellow)) == maYellow); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip magenta", |
| tools::hsv2rgb(tools::rgb2hsv(maMagenta)) == maMagenta); |
| CPPUNIT_ASSERT_MESSAGE("roundtrip cyan", |
| tools::hsv2rgb(tools::rgb2hsv(maCyan)) == maCyan); |
| |
| CPPUNIT_ASSERT_MESSAGE("grey10", |
| tools::rgb2hsv(maWhite*.1) == BColor(0,0,.1)); |
| CPPUNIT_ASSERT_MESSAGE("grey90", |
| tools::rgb2hsv(maWhite*.9) == BColor(0,0,.9)); |
| CPPUNIT_ASSERT_MESSAGE("red/2", |
| tools::rgb2hsv(maRed*.5) == BColor(0,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("green/2", |
| tools::rgb2hsv(maGreen*.5) == BColor(120,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("blue/2", |
| tools::rgb2hsv(maBlue*.5) == BColor(240,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("yellow/2", |
| tools::rgb2hsv(maYellow*.5) == BColor(60,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("magenta/2", |
| tools::rgb2hsv(maMagenta*.5) == BColor(300,1,0.5)); |
| CPPUNIT_ASSERT_MESSAGE("cyan/2", |
| tools::rgb2hsv(maCyan*.5) == BColor(180,1,0.5)); |
| |
| CPPUNIT_ASSERT_MESSAGE("pastel", |
| tools::rgb2hsv(BColor(.5,.25,.25)) == BColor(0,.5,.5)); |
| } |
| |
| void ciexyzTest() |
| { |
| tools::rgb2ciexyz(maWhite); |
| tools::rgb2ciexyz(maBlack); |
| tools::rgb2ciexyz(maRed); |
| tools::rgb2ciexyz(maGreen); |
| tools::rgb2ciexyz(maBlue); |
| tools::rgb2ciexyz(maYellow); |
| tools::rgb2ciexyz(maMagenta); |
| tools::rgb2ciexyz(maCyan); |
| } |
| |
| // 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(bcolor); |
| CPPUNIT_TEST(hslTest); |
| CPPUNIT_TEST(hsvTest); |
| CPPUNIT_TEST(ciexyzTest); |
| CPPUNIT_TEST_SUITE_END(); |
| }; // class b2dvector |
| |
| // ----------------------------------------------------------------------------- |
| |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dsvgdimpex); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolyrange); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dcubicbezier); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhommatrix); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhompoint); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpoint); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygon); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygontools); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolypolygon); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dquadraticbezier); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2drange); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dtuple); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dvector); |
| CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::bcolor); |
| } // 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; |
| |