1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 // MARKER(update_precomp.py): autogen include statement, do not remove 30 #include "precompiled_basegfx.hxx" 31 // autogenerated file with codegen.pl 32 33 #include "preextstl.h" 34 #include "cppunit/TestAssert.h" 35 #include "cppunit/TestFixture.h" 36 #include "cppunit/extensions/HelperMacros.h" 37 #include "postextstl.h" 38 39 #include <basegfx/matrix/b2dhommatrix.hxx> 40 #include <basegfx/polygon/b2dpolygon.hxx> 41 #include <basegfx/polygon/b2dpolygontools.hxx> 42 #include <basegfx/curve/b2dcubicbezier.hxx> 43 #include <basegfx/curve/b2dbeziertools.hxx> 44 #include <basegfx/polygon/b2dpolypolygontools.hxx> 45 #include <basegfx/polygon/b2dpolygonclipper.hxx> 46 #include <basegfx/polygon/b2dpolypolygon.hxx> 47 #include <basegfx/range/b2dpolyrange.hxx> 48 #include <basegfx/numeric/ftools.hxx> 49 #include <basegfx/color/bcolor.hxx> 50 #include <basegfx/color/bcolortools.hxx> 51 52 #include <basegfx/tools/debugplotter.hxx> 53 54 #include <iostream> 55 #include <fstream> 56 57 using namespace ::basegfx; 58 59 60 namespace basegfx2d 61 { 62 63 class b2dsvgdimpex : public CppUnit::TestFixture 64 { 65 private: 66 ::rtl::OUString aPath0; 67 ::rtl::OUString aPath1; 68 ::rtl::OUString aPath2; 69 ::rtl::OUString aPath3; 70 71 public: 72 // initialise your test code values here. 73 void setUp() 74 { 75 // simple rectangle 76 aPath0 = ::rtl::OUString::createFromAscii( 77 "M 10 10-10 10-10-10 10-10Z" ); 78 79 // simple bezier polygon 80 aPath1 = ::rtl::OUString::createFromAscii( 81 "m11430 0c-8890 3810 5715 6985 5715 6985 " 82 "0 0-17145-1905-17145-1905 0 0 22860-10160 " 83 "16510 6350-6350 16510-3810-11430-3810-11430z" ); 84 85 // '@' as a bezier polygon 86 aPath2 = ::rtl::OUString::createFromAscii( 87 "m1917 1114c-89-189-233-284-430-284-167 " 88 "0-306 91-419 273-113 182-170 370-170 564 " 89 "0 145 33 259 98 342 65 84 150 126 257 126 " 90 "77 0 154-19 231-57 77-38 147-97 210-176 63" 91 "-79 99-143 109-190 38-199 76-398 114-598z" 92 "m840 1646c-133 73-312 139-537 197-225 57" 93 "-440 86-644 87-483-1-866-132-1150-392-284" 94 "-261-426-619-426-1076 0-292 67-560 200-803 " 95 "133-243 321-433 562-569 241-136 514-204 821" 96 "-204 405 0 739 125 1003 374 264 250 396 550 " 97 "396 899 0 313-88 576-265 787-177 212-386 318" 98 "-627 318-191 0-308-94-352-281-133 187-315 281" 99 "-546 281-172 0-315-67-428-200-113-133-170-301" 100 "-170-505 0-277 90-527 271-751 181-223 394" 101 "-335 640-335 196 0 353 83 470 250 13-68 26" 102 "-136 41-204 96 0 192 0 288 0-74 376-148 752" 103 "-224 1128-21 101-31 183-31 245 0 39 9 70 26 " 104 "93 17 24 39 36 67 36 145 0 279-80 400-240 121" 105 "-160 182-365 182-615 0-288-107-533-322-734" 106 "-215-201-487-301-816-301-395 0-715 124-960 " 107 "373-245 249-368 569-368 958 0 385 119 685 " 108 "357 900 237 216 557 324 958 325 189-1 389-27 " 109 "600-77 211-52 378-110 503-174 27 70 54 140 81 210z" ); 110 111 // first part of 'Hello World' as a line polygon 112 aPath3 = ::rtl::OUString::createFromAscii( 113 "m1598 125h306v2334h-306v-1105h-1293v1105h-305v" 114 "-2334h305v973h1293zm2159 1015 78-44 85 235-91 " 115 "47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102" 116 "-4-97-12-91-19-85-26-40-16-39-18-38-20-36-22-34" 117 "-24-33-26-32-27-30-30-29-31-27-33-25-33-23-36-21" 118 "-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3" 119 "-98 11-94 17-89 24-84 31-79 37-75 22-35 23-34 24" 120 "-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35" 121 "-18 37-17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 " 122 "78 10 37 9 37 9 36 12 35 14 33 15 33 17 32 19 31 " 123 "21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 " 124 "34 18 36 30 74 23 80 17 84 10 89 3 94v78h-1277l6 " 125 "75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 " 126 "23 17 22 19 21 19 20 21 18 21 18 23 16 23 14 24 " 127 "14 26 12 26 11 27 10 28 8 59 13 63 7 67 3 80-3 81" 128 "-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l" 129 "-7-51-11-49-14-46-17-43-21-40-24-38-27-36-31-32" 130 "-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 " 131 "2-46 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32" 132 "-29 34-26 38-23 41-20 44-17 47zm1648-1293h288v" 133 "2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 " 134 "91-4 91 4 85 12 42 8 39 11 39 13 38 14 36 17 35 18 " 135 "34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 23 " 136 "34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100" 137 "-11 95-16 89-24 85-31 80-37 74-21 35-23 35-25 32-26 " 138 "32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17" 139 "-38 14-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9" 140 "-40-10-39-13-37-14-36-17-35-18-34-21-33-22-31-24-30" 141 "-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80" 142 "-24-85-17-89-11-95-3-100 3-101 11-95 17-90 24-85 30" 143 "-79 38-75 21-35 23-35 25-32 26-32 28-30 29-28 30-26 " 144 "31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z" ); 145 } 146 147 void tearDown() 148 { 149 } 150 151 void impex() 152 { 153 B2DPolyPolygon aPoly; 154 ::rtl::OUString aExport; 155 156 CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D", 157 tools::importFromSvgD( aPoly, 158 aPath0 )); 159 aExport = tools::exportToSvgD( aPoly ); 160 const char* sExportString = "m10 10h-20v-20h20z"; 161 CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D", 162 !aExport.compareToAscii(sExportString) ); 163 CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip", 164 tools::importFromSvgD( aPoly, 165 aExport )); 166 aExport = tools::exportToSvgD( aPoly ); 167 CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D (round-trip)", 168 !aExport.compareToAscii(sExportString)); 169 170 CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", 171 tools::importFromSvgD( aPoly, 172 aPath1 )); 173 aExport = tools::exportToSvgD( aPoly ); 174 175 // Adaptions for B2DPolygon bezier change (see #i77162#): 176 // 177 // The import/export of aPath1 does not reproduce aExport again. This is 178 // correct since aPath1 contains a segment with non-used control points 179 // which gets exported now correctly as 'l' and also a point (#4, index 3) 180 // with C2 continuity which produces a 's' staement now. 181 // 182 // The old SVGexport identified nun-used ControlVectors erraneously as bezier segments 183 // because the 2nd vector at the start point was used, even when added 184 // with start point was identical to end point. Exactly for that reason 185 // i reworked the B2DPolygon to use prev, next control points. 186 // 187 // so for correct unit test i add the new exported string here as sExportStringSimpleBezier 188 // and compare to it. 189 const char* sExportStringSimpleBezier = 190 "m11430 0c-8890 3810 5715 6985 5715 6985" 191 "l-17145-1905c0 0 22860-10160 16510 6350" 192 "s-3810-11430-3810-11430z"; 193 CPPUNIT_ASSERT_MESSAGE("exporting bezier polygon to SVG-D", !aExport.compareToAscii(sExportStringSimpleBezier)); 194 195 // Adaptions for B2DPolygon bezier change (see #i77162#): 196 // 197 // a 2nd good test is that re-importing of aExport has to create the same 198 // B2DPolPolygon again: 199 B2DPolyPolygon aReImport; 200 CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport)); 201 CPPUNIT_ASSERT_MESSAGE("re-imported polygon needs to be identical", aReImport == aPoly); 202 203 CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2 )); 204 aExport = tools::exportToSvgD( aPoly ); 205 206 // Adaptions for B2DPolygon bezier change (see #i77162#): 207 // 208 // same here, the corrected export with the corrected B2DPolygon is simply more efficient, 209 // so i needed to change the compare string. Also adding the re-import comparison below. 210 const char* sExportString1 = 211 "m1917 1114c-89-189-233-284-430-284-167 0-306 91-419 273s-170 370-17" 212 "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" 213 "-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-" 214 "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" 215 "-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" 216 "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" 217 "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" 218 "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" 219 "8 325 189-1 389-27 600-77 211-52 378-110 503-174q40.5 105 81 210z"; 220 CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport)); 221 CPPUNIT_ASSERT_MESSAGE("re-imported '@' needs to be identical", aReImport == aPoly); 222 223 CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D", !aExport.compareToAscii(sExportString1)); 224 CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip", 225 tools::importFromSvgD( aPoly, 226 aExport )); 227 aExport = tools::exportToSvgD( aPoly ); 228 CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D (round-trip)", 229 !aExport.compareToAscii(sExportString1)); 230 231 232 CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D", 233 tools::importFromSvgD( aPoly, 234 aPath3 )); 235 aExport = tools::exportToSvgD( aPoly ); 236 const char* sExportString2 = 237 "m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293" 238 "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" 239 "-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" 240 "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" 241 "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-" 242 "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" 243 "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 " 244 "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" 245 "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" 246 " 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" 247 "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" 248 "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" 249 "-1293h288v2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 91-4 91 4 85 12 42 " 250 "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 " 251 "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" 252 " 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" 253 "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" 254 "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-" 255 "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" 256 "-28 30-26 31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z"; 257 CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D", 258 !aExport.compareToAscii(sExportString2)); 259 CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip", 260 tools::importFromSvgD( aPoly, 261 aExport )); 262 aExport = tools::exportToSvgD( aPoly ); 263 CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D (round-trip)", 264 !aExport.compareToAscii(sExportString2)); 265 266 const B2DPolygon aRect( 267 tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) )); 268 aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false); 269 270 const char* sExportStringRect = "M0 0H4000V4000H0Z"; 271 CPPUNIT_ASSERT_MESSAGE("exporting to rectangle svg-d string", 272 !aExport.compareToAscii(sExportStringRect)); 273 } 274 275 // Change the following lines only, if you add, remove or rename 276 // member functions of the current class, 277 // because these macros are need by auto register mechanism. 278 279 CPPUNIT_TEST_SUITE(b2dsvgdimpex); 280 CPPUNIT_TEST(impex); 281 CPPUNIT_TEST_SUITE_END(); 282 }; // class b2dsvgdimpex 283 284 class b2dpolyrange : public CppUnit::TestFixture 285 { 286 private: 287 public: 288 void setUp() 289 {} 290 291 void tearDown() 292 {} 293 294 void check() 295 { 296 B2DPolyRange aRange; 297 aRange.appendElement(B2DRange(0,0,1,1),ORIENTATION_POSITIVE); 298 aRange.appendElement(B2DRange(2,2,3,3),ORIENTATION_POSITIVE); 299 300 CPPUNIT_ASSERT_MESSAGE("simple poly range - count", 301 aRange.count() == 2); 302 CPPUNIT_ASSERT_MESSAGE("simple poly range - first element", 303 aRange.getElement(0).head == B2DRange(0,0,1,1)); 304 CPPUNIT_ASSERT_MESSAGE("simple poly range - second element", 305 aRange.getElement(1).head == B2DRange(2,2,3,3)); 306 307 // B2DPolyRange relies on correctly orientated rects 308 const B2DRange aRect(0,0,1,1); 309 CPPUNIT_ASSERT_MESSAGE("createPolygonFromRect - correct orientation", 310 tools::getOrientation( 311 tools::createPolygonFromRect(aRect)) == ORIENTATION_POSITIVE ); 312 } 313 314 // Change the following lines only, if you add, remove or rename 315 // member functions of the current class, 316 // because these macros are need by auto register mechanism. 317 318 CPPUNIT_TEST_SUITE(b2dpolyrange); 319 CPPUNIT_TEST(check); 320 CPPUNIT_TEST_SUITE_END(); 321 }; 322 323 class b2dbeziertools : public CppUnit::TestFixture 324 { 325 private: 326 B2DCubicBezier aHalfCircle; // not exactly, but a look-alike 327 B2DCubicBezier aQuarterCircle; // not exactly, but a look-alike 328 B2DCubicBezier aLoop; // identical endpoints, curve goes back to where it started 329 B2DCubicBezier aStraightLineDistinctEndPoints; // truly a line 330 B2DCubicBezier aStraightLineDistinctEndPoints2; // truly a line, with slightly different control points 331 B2DCubicBezier aStraightLineIdenticalEndPoints; // degenerate case of aLoop 332 B2DCubicBezier aStraightLineIdenticalEndPoints2;// degenerate case of aLoop, with slightly different control points 333 B2DCubicBezier aCrossing; // curve self-intersects somewhere in the middle 334 B2DCubicBezier aCusp; // curve has a point of undefined tangency 335 336 337 public: 338 // initialise your test code values here. 339 void setUp() 340 { 341 const B2DPoint a00(0.0, 0.0); 342 const B2DPoint a10(1.0, 0.0); 343 const B2DPoint a11(1.0, 1.0); 344 const B2DPoint a01(0.0, 1.0); 345 const B2DPoint middle( 0.5, 0.5 ); 346 const B2DPoint quarterDown( 0.25, 0.25 ); 347 const B2DPoint quarterUp( 0.75, 0.75 ); 348 349 aHalfCircle = B2DCubicBezier(a00, a01, a11, a10); 350 351 // The spline control points become 352 // 353 // (R * cos(A), R * sin(A)) 354 // (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A)) 355 // (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B)) 356 // (R * cos(B), R * sin(B)) 357 // 358 // where h = 4/3 * R * tan ((B-A)/4) 359 // 360 // with R being the radius, A start angle and B end angle (A < B). 361 // 362 // (This calculation courtesy Carl Worth, himself based on 363 // Michael Goldapp and Dokken/Daehlen) 364 365 // Choosing R=1, A=0, B=pi/2 366 const double h( 4.0/3.0 * tan(M_PI/8.0) ); 367 aQuarterCircle = B2DCubicBezier(a10 + B2DPoint(1.0,0.0), 368 B2DPoint(B2DPoint( 1.0, h ) + B2DPoint(1.0,0.0)), 369 B2DPoint(B2DPoint( h, 1.0) + B2DPoint(1.0,0.0)), 370 a01 + B2DPoint(1.0,0.0)); 371 372 aCusp = B2DCubicBezier(a00 + B2DPoint(2.0,0.0), 373 B2DPoint(a11 + B2DPoint(2.0,0.0)), 374 B2DPoint(a01 + B2DPoint(2.0,0.0)), 375 a10 + B2DPoint(2.0,0.0)); 376 377 aLoop = B2DCubicBezier(a00 + B2DPoint(3.0,0.0), 378 B2DPoint(a01 + B2DPoint(3.0,0.0)), 379 B2DPoint(a10 + B2DPoint(3.0,0.0)), 380 a00 + B2DPoint(3.0,0.0)); 381 382 aStraightLineDistinctEndPoints = B2DCubicBezier(a00 + B2DPoint(4.0,0.0), 383 B2DPoint(middle + B2DPoint(4.0,0.0)), 384 B2DPoint(middle + B2DPoint(4.0,0.0)), 385 a11 + B2DPoint(4.0,0.0)); 386 387 aStraightLineDistinctEndPoints2 = B2DCubicBezier(a00 + B2DPoint(5.0,0.0), 388 B2DPoint(quarterDown + B2DPoint(5.0,0.0)), 389 B2DPoint(quarterUp + B2DPoint(5.0,0.0)), 390 a11 + B2DPoint(5.0,0.0)); 391 392 aStraightLineIdenticalEndPoints = B2DCubicBezier(a00 + B2DPoint(6.0,0.0), 393 B2DPoint(a11 + B2DPoint(6.0,0.0)), 394 B2DPoint(a11 + B2DPoint(6.0,0.0)), 395 a00 + B2DPoint(6.0,0.0)); 396 397 aStraightLineIdenticalEndPoints2 = B2DCubicBezier(a00 + B2DPoint(7.0,0.0), 398 B2DPoint(quarterDown + B2DPoint(7.0,0.0)), 399 B2DPoint(quarterUp + B2DPoint(7.0,0.0)), 400 a00 + B2DPoint(7.0,0.0)); 401 402 aCrossing = B2DCubicBezier(a00 + B2DPoint(8.0,0.0), 403 B2DPoint(B2DPoint(2.0,2.0) + B2DPoint(8.0,0.0)), 404 B2DPoint(B2DPoint(-1.0,2.0) + B2DPoint(8.0,0.0)), 405 a10 + B2DPoint(8.0,0.0)); 406 407 ::std::ofstream output("bez_testcases.gnuplot"); 408 DebugPlotter aPlotter( "Original curves", 409 output ); 410 411 aPlotter.plot( aHalfCircle, 412 "half circle" ); 413 aPlotter.plot( aQuarterCircle, 414 "quarter circle" ); 415 aPlotter.plot( aCusp, 416 "cusp" ); 417 aPlotter.plot( aLoop, 418 "loop" ); 419 aPlotter.plot( aStraightLineDistinctEndPoints, 420 "straight line 0" ); 421 aPlotter.plot( aStraightLineDistinctEndPoints2, 422 "straight line 1" ); 423 aPlotter.plot( aStraightLineIdenticalEndPoints, 424 "straight line 2" ); 425 aPlotter.plot( aStraightLineIdenticalEndPoints2, 426 "straight line 3" ); 427 aPlotter.plot( aCrossing, 428 "crossing" ); 429 430 // break up a complex bezier (loopy, spiky or self intersecting) 431 // into simple segments (left to right) 432 B2DCubicBezier aSegment = aCrossing; 433 double fExtremePos(0.0); 434 435 aPlotter.plot( aSegment, "segment" ); 436 while(aSegment.getMinimumExtremumPosition(fExtremePos)) 437 { 438 aSegment.split(fExtremePos, 0, &aSegment); 439 aPlotter.plot( aSegment, "segment" ); 440 } 441 } 442 443 void tearDown() 444 { 445 } 446 447 void adaptiveByDistance() 448 { 449 ::std::ofstream output("bez_adaptiveByDistance.gnuplot"); 450 DebugPlotter aPlotter( "distance-adaptive subdivision", 451 output ); 452 453 const double fBound( 0.0001 ); 454 B2DPolygon result; 455 456 aHalfCircle.adaptiveSubdivideByDistance(result, fBound); 457 aPlotter.plot(result, 458 "half circle"); result.clear(); 459 460 aQuarterCircle.adaptiveSubdivideByDistance(result, fBound); 461 aPlotter.plot(result, 462 "quarter circle"); result.clear(); 463 464 aLoop.adaptiveSubdivideByDistance(result, fBound); 465 aPlotter.plot(result, 466 "loop"); result.clear(); 467 468 aStraightLineDistinctEndPoints.adaptiveSubdivideByDistance(result, fBound); 469 aPlotter.plot(result, 470 "straight line 0"); result.clear(); 471 472 aStraightLineDistinctEndPoints2.adaptiveSubdivideByDistance(result, fBound); 473 aPlotter.plot(result, 474 "straight line 1"); result.clear(); 475 476 aStraightLineIdenticalEndPoints.adaptiveSubdivideByDistance(result, fBound); 477 aPlotter.plot(result, 478 "straight line 2"); result.clear(); 479 480 aStraightLineIdenticalEndPoints2.adaptiveSubdivideByDistance(result, fBound); 481 aPlotter.plot(result, 482 "straight line 3"); result.clear(); 483 484 aCrossing.adaptiveSubdivideByDistance(result, fBound); 485 aPlotter.plot(result, 486 "straight line 4"); result.clear(); 487 488 aCusp.adaptiveSubdivideByDistance(result, fBound); 489 aPlotter.plot(result, 490 "straight line 5"); result.clear(); 491 492 CPPUNIT_ASSERT_MESSAGE("adaptiveByDistance", true ); 493 } 494 495 void adaptiveByAngle() 496 { 497 const double fBound( 5.0 ); 498 B2DPolygon result; 499 500 ::std::ofstream output("bez_adaptiveByAngle.gnuplot"); 501 DebugPlotter aPlotter( "angle-adaptive subdivision", 502 output ); 503 504 aHalfCircle.adaptiveSubdivideByAngle(result, fBound, true); 505 aPlotter.plot(result, 506 "half circle"); result.clear(); 507 508 aQuarterCircle.adaptiveSubdivideByAngle(result, fBound, true); 509 aPlotter.plot(result, 510 "quarter cirle"); result.clear(); 511 512 aLoop.adaptiveSubdivideByAngle(result, fBound, true); 513 aPlotter.plot(result, 514 "loop"); result.clear(); 515 516 aStraightLineDistinctEndPoints.adaptiveSubdivideByAngle(result, fBound, true); 517 aPlotter.plot(result, 518 "straight line 0"); result.clear(); 519 520 aStraightLineDistinctEndPoints2.adaptiveSubdivideByAngle(result, fBound, true); 521 aPlotter.plot(result, 522 "straight line 1"); result.clear(); 523 524 aStraightLineIdenticalEndPoints.adaptiveSubdivideByAngle(result, fBound, true); 525 aPlotter.plot(result, 526 "straight line 2"); result.clear(); 527 528 aStraightLineIdenticalEndPoints2.adaptiveSubdivideByAngle(result, fBound, true); 529 aPlotter.plot(result, 530 "straight line 3"); result.clear(); 531 532 aCrossing.adaptiveSubdivideByAngle(result, fBound, true); 533 aPlotter.plot(result, 534 "straight line 4"); result.clear(); 535 536 aCusp.adaptiveSubdivideByAngle(result, fBound, true); 537 aPlotter.plot(result, 538 "straight line 5"); result.clear(); 539 540 CPPUNIT_ASSERT_MESSAGE("adaptiveByAngle", true ); 541 } 542 543 // Change the following lines only, if you add, remove or rename 544 // member functions of the current class, 545 // because these macros are need by auto register mechanism. 546 547 CPPUNIT_TEST_SUITE(b2dbeziertools); 548 CPPUNIT_TEST(adaptiveByDistance); // TODO: add tests for quadratic bezier (subdivide and degree reduction) 549 CPPUNIT_TEST(adaptiveByAngle); 550 CPPUNIT_TEST_SUITE_END(); 551 }; // class b2dcubicbezier 552 553 554 class b2dcubicbezier : public CppUnit::TestFixture 555 { 556 public: 557 // initialise your test code values here. 558 void setUp() 559 { 560 } 561 562 void tearDown() 563 { 564 } 565 566 // insert your test code here. 567 void EmptyMethod() 568 { 569 // this is demonstration code 570 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1); 571 } 572 573 // Change the following lines only, if you add, remove or rename 574 // member functions of the current class, 575 // because these macros are need by auto register mechanism. 576 577 CPPUNIT_TEST_SUITE(b2dcubicbezier); 578 CPPUNIT_TEST(EmptyMethod); 579 CPPUNIT_TEST_SUITE_END(); 580 }; // class b2dcubicbezier 581 582 583 class b2dhommatrix : public CppUnit::TestFixture 584 { 585 private: 586 B2DHomMatrix maIdentity; 587 B2DHomMatrix maScale; 588 B2DHomMatrix maTranslate; 589 B2DHomMatrix maShear; 590 B2DHomMatrix maAffine; 591 B2DHomMatrix maPerspective; 592 593 public: 594 // initialise your test code values here. 595 void setUp() 596 { 597 // setup some test matrices 598 maIdentity.identity(); // force compact layout 599 maIdentity.set(0,0, 1.0); 600 maIdentity.set(0,1, 0.0); 601 maIdentity.set(0,2, 0.0); 602 maIdentity.set(1,0, 0.0); 603 maIdentity.set(1,1, 1.0); 604 maIdentity.set(1,2, 0.0); 605 606 maScale.identity(); // force compact layout 607 maScale.set(0,0, 2.0); 608 maScale.set(1,1, 20.0); 609 610 maTranslate.identity(); // force compact layout 611 maTranslate.set(0,2, 20.0); 612 maTranslate.set(1,2, 2.0); 613 614 maShear.identity(); // force compact layout 615 maShear.set(0,1, 3.0); 616 maShear.set(1,0, 7.0); 617 maShear.set(1,1, 22.0); 618 619 maAffine.identity(); // force compact layout 620 maAffine.set(0,0, 1.0); 621 maAffine.set(0,1, 2.0); 622 maAffine.set(0,2, 3.0); 623 maAffine.set(1,0, 4.0); 624 maAffine.set(1,1, 5.0); 625 maAffine.set(1,2, 6.0); 626 627 maPerspective.set(0,0, 1.0); 628 maPerspective.set(0,1, 2.0); 629 maPerspective.set(0,2, 3.0); 630 maPerspective.set(1,0, 4.0); 631 maPerspective.set(1,1, 5.0); 632 maPerspective.set(1,2, 6.0); 633 maPerspective.set(2,0, 7.0); 634 maPerspective.set(2,1, 8.0); 635 maPerspective.set(2,2, 9.0); 636 } 637 638 void tearDown() 639 { 640 } 641 642 void equal() 643 { 644 B2DHomMatrix aIdentity; 645 B2DHomMatrix aScale; 646 B2DHomMatrix aTranslate; 647 B2DHomMatrix aShear; 648 B2DHomMatrix aAffine; 649 B2DHomMatrix aPerspective; 650 651 // setup some test matrices 652 aIdentity.identity(); // force compact layout 653 aIdentity.set(0,0, 1.0); 654 aIdentity.set(0,1, 0.0); 655 aIdentity.set(0,2, 0.0); 656 aIdentity.set(1,0, 0.0); 657 aIdentity.set(1,1, 1.0); 658 aIdentity.set(1,2, 0.0); 659 660 aScale.identity(); // force compact layout 661 aScale.set(0,0, 2.0); 662 aScale.set(1,1, 20.0); 663 664 aTranslate.identity(); // force compact layout 665 aTranslate.set(0,2, 20.0); 666 aTranslate.set(1,2, 2.0); 667 668 aShear.identity(); // force compact layout 669 aShear.set(0,1, 3.0); 670 aShear.set(1,0, 7.0); 671 aShear.set(1,1, 22.0); 672 673 aAffine.identity(); // force compact layout 674 aAffine.set(0,0, 1.0); 675 aAffine.set(0,1, 2.0); 676 aAffine.set(0,2, 3.0); 677 aAffine.set(1,0, 4.0); 678 aAffine.set(1,1, 5.0); 679 aAffine.set(1,2, 6.0); 680 681 aPerspective.set(0,0, 1.0); 682 aPerspective.set(0,1, 2.0); 683 aPerspective.set(0,2, 3.0); 684 aPerspective.set(1,0, 4.0); 685 aPerspective.set(1,1, 5.0); 686 aPerspective.set(1,2, 6.0); 687 aPerspective.set(2,0, 7.0); 688 aPerspective.set(2,1, 8.0); 689 aPerspective.set(2,2, 9.0); 690 691 CPPUNIT_ASSERT_MESSAGE("operator==: identity matrix", aIdentity == maIdentity); 692 CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale == maScale); 693 CPPUNIT_ASSERT_MESSAGE("operator==: translate matrix", aTranslate == maTranslate); 694 CPPUNIT_ASSERT_MESSAGE("operator==: shear matrix", aShear == maShear); 695 CPPUNIT_ASSERT_MESSAGE("operator==: affine matrix", aAffine == maAffine); 696 CPPUNIT_ASSERT_MESSAGE("operator==: perspective matrix", aPerspective == maPerspective); 697 } 698 699 void identity() 700 { 701 B2DHomMatrix ident; 702 703 CPPUNIT_ASSERT_MESSAGE("identity", maIdentity == ident); 704 } 705 706 void scale() 707 { 708 B2DHomMatrix mat; 709 mat.scale(2.0,20.0); 710 CPPUNIT_ASSERT_MESSAGE("scale", maScale == mat); 711 } 712 713 void translate() 714 { 715 B2DHomMatrix mat; 716 mat.translate(20.0,2.0); 717 CPPUNIT_ASSERT_MESSAGE("translate", maTranslate == mat); 718 } 719 720 void shear() 721 { 722 B2DHomMatrix mat; 723 mat.shearX(3.0); 724 mat.shearY(7.0); 725 CPPUNIT_ASSERT_MESSAGE("translate", maShear == mat); 726 } 727 728 void multiply() 729 { 730 B2DHomMatrix affineAffineProd; 731 732 affineAffineProd.set(0,0, 9); 733 affineAffineProd.set(0,1, 12); 734 affineAffineProd.set(0,2, 18); 735 affineAffineProd.set(1,0, 24); 736 affineAffineProd.set(1,1, 33); 737 affineAffineProd.set(1,2, 48); 738 739 B2DHomMatrix affinePerspectiveProd; 740 741 affinePerspectiveProd.set(0,0, 30); 742 affinePerspectiveProd.set(0,1, 36); 743 affinePerspectiveProd.set(0,2, 42); 744 affinePerspectiveProd.set(1,0, 66); 745 affinePerspectiveProd.set(1,1, 81); 746 affinePerspectiveProd.set(1,2, 96); 747 affinePerspectiveProd.set(2,0, 7); 748 affinePerspectiveProd.set(2,1, 8); 749 affinePerspectiveProd.set(2,2, 9); 750 751 B2DHomMatrix perspectiveAffineProd; 752 753 perspectiveAffineProd.set(0,0, 9); 754 perspectiveAffineProd.set(0,1, 12); 755 perspectiveAffineProd.set(0,2, 18); 756 perspectiveAffineProd.set(1,0, 24); 757 perspectiveAffineProd.set(1,1, 33); 758 perspectiveAffineProd.set(1,2, 48); 759 perspectiveAffineProd.set(2,0, 39); 760 perspectiveAffineProd.set(2,1, 54); 761 perspectiveAffineProd.set(2,2, 78); 762 763 B2DHomMatrix perspectivePerspectiveProd; 764 765 perspectivePerspectiveProd.set(0,0, 30); 766 perspectivePerspectiveProd.set(0,1, 36); 767 perspectivePerspectiveProd.set(0,2, 42); 768 perspectivePerspectiveProd.set(1,0, 66); 769 perspectivePerspectiveProd.set(1,1, 81); 770 perspectivePerspectiveProd.set(1,2, 96); 771 perspectivePerspectiveProd.set(2,0, 102); 772 perspectivePerspectiveProd.set(2,1, 126); 773 perspectivePerspectiveProd.set(2,2, 150); 774 775 B2DHomMatrix temp; 776 777 temp = maAffine; 778 temp*=maAffine; 779 CPPUNIT_ASSERT_MESSAGE("multiply: both compact", temp == affineAffineProd); 780 781 temp = maPerspective; 782 temp*=maAffine; 783 CPPUNIT_ASSERT_MESSAGE("multiply: first compact", temp == affinePerspectiveProd); 784 785 temp = maAffine; 786 temp*=maPerspective; 787 CPPUNIT_ASSERT_MESSAGE("multiply: second compact", temp == perspectiveAffineProd); 788 789 temp = maPerspective; 790 temp*=maPerspective; 791 CPPUNIT_ASSERT_MESSAGE("multiply: none compact", temp == perspectivePerspectiveProd); 792 } 793 794 void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, double fRotate) 795 { 796 // fill rSource with a linear combination of scale, shear and rotate 797 rSource.identity(); 798 rSource.scale(fScaleX, fScaleY); 799 rSource.shearX(fShearX); 800 rSource.rotate(fRotate); 801 } 802 803 bool impDecomposeComposeTest(double fScaleX, double fScaleY, double fShearX, double fRotate) 804 { 805 // linear combine matrix with given values 806 B2DHomMatrix aSource; 807 impFillMatrix(aSource, fScaleX, fScaleY, fShearX, fRotate); 808 809 // decompose that matrix 810 B2DTuple aDScale; 811 B2DTuple aDTrans; 812 double fDRot; 813 double fDShX; 814 bool bWorked = aSource.decompose(aDScale, aDTrans, fDRot, fDShX); 815 816 // linear combine another matrix with decomposition results 817 B2DHomMatrix aRecombined; 818 impFillMatrix(aRecombined, aDScale.getX(), aDScale.getY(), fDShX, fDRot); 819 820 // if decomposition worked, matrices need to be the same 821 return bWorked && aSource == aRecombined; 822 } 823 824 void decompose() 825 { 826 // test matrix decompositions. Each matrix decomposed and rebuilt 827 // using the decompose result should be the same as before. Test 828 // with all ranges of values. Translations are not tested since these 829 // are just the two rightmost values and uncritical 830 static double fSX(10.0); 831 static double fSY(12.0); 832 static double fR(45.0 * F_PI180); 833 static double fS(15.0 * F_PI180); 834 835 // check all possible scaling combinations 836 CPPUNIT_ASSERT_MESSAGE("decompose: error test A1", impDecomposeComposeTest(fSX, fSY, 0.0, 0.0)); 837 CPPUNIT_ASSERT_MESSAGE("decompose: error test A2", impDecomposeComposeTest(-fSX, fSY, 0.0, 0.0)); 838 CPPUNIT_ASSERT_MESSAGE("decompose: error test A3", impDecomposeComposeTest(fSX, -fSY, 0.0, 0.0)); 839 CPPUNIT_ASSERT_MESSAGE("decompose: error test A4", impDecomposeComposeTest(-fSX, -fSY, 0.0, 0.0)); 840 841 // check all possible scaling combinations with positive rotation 842 CPPUNIT_ASSERT_MESSAGE("decompose: error test B1", impDecomposeComposeTest(fSX, fSY, 0.0, fR)); 843 CPPUNIT_ASSERT_MESSAGE("decompose: error test B2", impDecomposeComposeTest(-fSX, fSY, 0.0, fR)); 844 CPPUNIT_ASSERT_MESSAGE("decompose: error test B3", impDecomposeComposeTest(fSX, -fSY, 0.0, fR)); 845 CPPUNIT_ASSERT_MESSAGE("decompose: error test B4", impDecomposeComposeTest(-fSX, -fSY, 0.0, fR)); 846 847 // check all possible scaling combinations with negative rotation 848 CPPUNIT_ASSERT_MESSAGE("decompose: error test C1", impDecomposeComposeTest(fSX, fSY, 0.0, -fR)); 849 CPPUNIT_ASSERT_MESSAGE("decompose: error test C2", impDecomposeComposeTest(-fSX, fSY, 0.0, -fR)); 850 CPPUNIT_ASSERT_MESSAGE("decompose: error test C3", impDecomposeComposeTest(fSX, -fSY, 0.0, -fR)); 851 CPPUNIT_ASSERT_MESSAGE("decompose: error test C4", impDecomposeComposeTest(-fSX, -fSY, 0.0, -fR)); 852 853 // check all possible scaling combinations with positive shear 854 CPPUNIT_ASSERT_MESSAGE("decompose: error test D1", impDecomposeComposeTest(fSX, fSY, tan(fS), 0.0)); 855 CPPUNIT_ASSERT_MESSAGE("decompose: error test D2", impDecomposeComposeTest(-fSX, fSY, tan(fS), 0.0)); 856 CPPUNIT_ASSERT_MESSAGE("decompose: error test D3", impDecomposeComposeTest(fSX, -fSY, tan(fS), 0.0)); 857 CPPUNIT_ASSERT_MESSAGE("decompose: error test D4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), 0.0)); 858 859 // check all possible scaling combinations with negative shear 860 CPPUNIT_ASSERT_MESSAGE("decompose: error test E1", impDecomposeComposeTest(fSX, fSY, tan(-fS), 0.0)); 861 CPPUNIT_ASSERT_MESSAGE("decompose: error test E2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), 0.0)); 862 CPPUNIT_ASSERT_MESSAGE("decompose: error test E3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), 0.0)); 863 CPPUNIT_ASSERT_MESSAGE("decompose: error test E4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), 0.0)); 864 865 // check all possible scaling combinations with positive rotate and positive shear 866 CPPUNIT_ASSERT_MESSAGE("decompose: error test F1", impDecomposeComposeTest(fSX, fSY, tan(fS), fR)); 867 CPPUNIT_ASSERT_MESSAGE("decompose: error test F2", impDecomposeComposeTest(-fSX, fSY, tan(fS), fR)); 868 CPPUNIT_ASSERT_MESSAGE("decompose: error test F3", impDecomposeComposeTest(fSX, -fSY, tan(fS), fR)); 869 CPPUNIT_ASSERT_MESSAGE("decompose: error test F4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), fR)); 870 871 // check all possible scaling combinations with negative rotate and positive shear 872 CPPUNIT_ASSERT_MESSAGE("decompose: error test G1", impDecomposeComposeTest(fSX, fSY, tan(fS), -fR)); 873 CPPUNIT_ASSERT_MESSAGE("decompose: error test G2", impDecomposeComposeTest(-fSX, fSY, tan(fS), -fR)); 874 CPPUNIT_ASSERT_MESSAGE("decompose: error test G3", impDecomposeComposeTest(fSX, -fSY, tan(fS), -fR)); 875 CPPUNIT_ASSERT_MESSAGE("decompose: error test G4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), -fR)); 876 877 // check all possible scaling combinations with positive rotate and negative shear 878 CPPUNIT_ASSERT_MESSAGE("decompose: error test H1", impDecomposeComposeTest(fSX, fSY, tan(-fS), fR)); 879 CPPUNIT_ASSERT_MESSAGE("decompose: error test H2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), fR)); 880 CPPUNIT_ASSERT_MESSAGE("decompose: error test H3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), fR)); 881 CPPUNIT_ASSERT_MESSAGE("decompose: error test H4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), fR)); 882 883 // check all possible scaling combinations with negative rotate and negative shear 884 CPPUNIT_ASSERT_MESSAGE("decompose: error test I1", impDecomposeComposeTest(fSX, fSY, tan(-fS), -fR)); 885 CPPUNIT_ASSERT_MESSAGE("decompose: error test I2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), -fR)); 886 CPPUNIT_ASSERT_MESSAGE("decompose: error test I3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), -fR)); 887 CPPUNIT_ASSERT_MESSAGE("decompose: error test I4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), -fR)); 888 } 889 890 // Change the following lines only, if you add, remove or rename 891 // member functions of the current class, 892 // because these macros are need by auto register mechanism. 893 894 CPPUNIT_TEST_SUITE(b2dhommatrix); 895 CPPUNIT_TEST(equal); 896 CPPUNIT_TEST(identity); 897 CPPUNIT_TEST(scale); 898 CPPUNIT_TEST(translate); 899 CPPUNIT_TEST(shear); 900 CPPUNIT_TEST(multiply); 901 CPPUNIT_TEST(decompose); 902 CPPUNIT_TEST_SUITE_END(); 903 904 }; // class b2dhommatrix 905 906 907 class b2dhompoint : public CppUnit::TestFixture 908 { 909 public: 910 // initialise your test code values here. 911 void setUp() 912 { 913 } 914 915 void tearDown() 916 { 917 } 918 919 // insert your test code here. 920 void EmptyMethod() 921 { 922 } 923 924 // Change the following lines only, if you add, remove or rename 925 // member functions of the current class, 926 // because these macros are need by auto register mechanism. 927 928 CPPUNIT_TEST_SUITE(b2dhompoint); 929 CPPUNIT_TEST(EmptyMethod); 930 CPPUNIT_TEST_SUITE_END(); 931 }; // class b2dhompoint 932 933 934 class b2dpoint : public CppUnit::TestFixture 935 { 936 public: 937 // initialise your test code values here. 938 void setUp() 939 { 940 } 941 942 void tearDown() 943 { 944 } 945 946 // insert your test code here. 947 // this is only demonstration code 948 void EmptyMethod() 949 { 950 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1); 951 } 952 953 // Change the following lines only, if you add, remove or rename 954 // member functions of the current class, 955 // because these macros are need by auto register mechanism. 956 957 CPPUNIT_TEST_SUITE(b2dpoint); 958 CPPUNIT_TEST(EmptyMethod); 959 CPPUNIT_TEST_SUITE_END(); 960 }; // class b2dpoint 961 962 963 class b2dpolygon : public CppUnit::TestFixture 964 { 965 public: 966 // initialise your test code values here. 967 void setUp() 968 { 969 } 970 971 void tearDown() 972 { 973 } 974 975 // insert your test code here. 976 void testBasics() 977 { 978 B2DPolygon aPoly; 979 980 aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3)); 981 982 CPPUNIT_ASSERT_MESSAGE("#1 first polygon point wrong", 983 aPoly.getB2DPoint(0) == B2DPoint(3,3)); 984 CPPUNIT_ASSERT_MESSAGE("#1 first control point wrong", 985 aPoly.getPrevControlPoint(0) == B2DPoint(2,2)); 986 CPPUNIT_ASSERT_MESSAGE("#1 second control point wrong", 987 aPoly.getNextControlPoint(0) == B2DPoint(3,3)); 988 CPPUNIT_ASSERT_MESSAGE("next control point not used", 989 aPoly.isNextControlPointUsed(0) == false); 990 991 aPoly.setNextControlPoint(0,B2DPoint(4,4)); 992 CPPUNIT_ASSERT_MESSAGE("#1.1 second control point wrong", 993 aPoly.getNextControlPoint(0) == B2DPoint(4,4)); 994 CPPUNIT_ASSERT_MESSAGE("next control point used", 995 aPoly.isNextControlPointUsed(0) == true); 996 CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong", 997 aPoly.areControlPointsUsed() == true); 998 CPPUNIT_ASSERT_MESSAGE("getContinuityInPoint() wrong", 999 aPoly.getContinuityInPoint(0) == CONTINUITY_C2); 1000 1001 aPoly.resetControlPoints(); 1002 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", 1003 aPoly.getB2DPoint(0) == B2DPoint(3,3)); 1004 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", 1005 aPoly.getPrevControlPoint(0) == B2DPoint(3,3)); 1006 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear", 1007 aPoly.getNextControlPoint(0) == B2DPoint(3,3)); 1008 CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong #2", 1009 aPoly.areControlPointsUsed() == false); 1010 1011 aPoly.clear(); 1012 aPoly.append(B2DPoint(0,0)); 1013 aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3)); 1014 1015 CPPUNIT_ASSERT_MESSAGE("#2 first polygon point wrong", 1016 aPoly.getB2DPoint(0) == B2DPoint(0,0)); 1017 CPPUNIT_ASSERT_MESSAGE("#2 first control point wrong", 1018 aPoly.getPrevControlPoint(0) == B2DPoint(0,0)); 1019 CPPUNIT_ASSERT_MESSAGE("#2 second control point wrong", 1020 aPoly.getNextControlPoint(0) == B2DPoint(1,1)); 1021 CPPUNIT_ASSERT_MESSAGE("#2 third control point wrong", 1022 aPoly.getPrevControlPoint(1) == B2DPoint(2,2)); 1023 CPPUNIT_ASSERT_MESSAGE("#2 fourth control point wrong", 1024 aPoly.getNextControlPoint(1) == B2DPoint(3,3)); 1025 CPPUNIT_ASSERT_MESSAGE("#2 second polygon point wrong", 1026 aPoly.getB2DPoint(1) == B2DPoint(3,3)); 1027 } 1028 // Change the following lines only, if you add, remove or rename 1029 // member functions of the current class, 1030 // because these macros are need by auto register mechanism. 1031 1032 CPPUNIT_TEST_SUITE(b2dpolygon); 1033 CPPUNIT_TEST(testBasics); 1034 CPPUNIT_TEST_SUITE_END(); 1035 }; // class b2dpolygon 1036 1037 1038 class b2dpolygontools : public CppUnit::TestFixture 1039 { 1040 public: 1041 // initialise your test code values here. 1042 void setUp() 1043 { 1044 } 1045 1046 void tearDown() 1047 { 1048 } 1049 1050 // insert your test code here. 1051 // this is only demonstration code 1052 void testIsRectangle() 1053 { 1054 B2DPolygon aRect1( 1055 tools::createPolygonFromRect( 1056 B2DRange(0,0,1,1) ) ); 1057 1058 B2DPolygon aRect2; 1059 aRect2.append( B2DPoint(0,0) ); 1060 aRect2.append( B2DPoint(1,0) ); 1061 aRect2.append( B2DPoint(1,.5)); 1062 aRect2.append( B2DPoint(1,1) ); 1063 aRect2.append( B2DPoint(0,1) ); 1064 aRect2.setClosed(true); 1065 1066 B2DPolygon aNonRect1; 1067 aNonRect1.append( B2DPoint(0,0) ); 1068 aNonRect1.append( B2DPoint(1,0) ); 1069 aNonRect1.append( B2DPoint(1,1) ); 1070 aNonRect1.append( B2DPoint(0.5,1) ); 1071 aNonRect1.append( B2DPoint(0.5,0) ); 1072 aNonRect1.setClosed(true); 1073 1074 B2DPolygon aNonRect2; 1075 aNonRect2.append( B2DPoint(0,0) ); 1076 aNonRect2.append( B2DPoint(1,1) ); 1077 aNonRect2.append( B2DPoint(1,0) ); 1078 aNonRect2.append( B2DPoint(0,1) ); 1079 aNonRect2.setClosed(true); 1080 1081 B2DPolygon aNonRect3; 1082 aNonRect3.append( B2DPoint(0,0) ); 1083 aNonRect3.append( B2DPoint(1,0) ); 1084 aNonRect3.append( B2DPoint(1,1) ); 1085 aNonRect3.setClosed(true); 1086 1087 B2DPolygon aNonRect4; 1088 aNonRect4.append( B2DPoint(0,0) ); 1089 aNonRect4.append( B2DPoint(1,0) ); 1090 aNonRect4.append( B2DPoint(1,1) ); 1091 aNonRect4.append( B2DPoint(0,1) ); 1092 1093 B2DPolygon aNonRect5; 1094 aNonRect5.append( B2DPoint(0,0) ); 1095 aNonRect5.append( B2DPoint(1,0) ); 1096 aNonRect5.append( B2DPoint(1,1) ); 1097 aNonRect5.append( B2DPoint(0,1) ); 1098 aNonRect5.setControlPoints(1,B2DPoint(1,0),B2DPoint(-11,0)); 1099 aNonRect5.setClosed(true); 1100 1101 CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 1", 1102 tools::isRectangle( aRect1 )); 1103 CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 2", 1104 tools::isRectangle( aRect2 )); 1105 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 1", 1106 !tools::isRectangle( aNonRect1 )); 1107 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 2", 1108 !tools::isRectangle( aNonRect2 )); 1109 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 3", 1110 !tools::isRectangle( aNonRect3 )); 1111 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 4", 1112 !tools::isRectangle( aNonRect4 )); 1113 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 5", 1114 !tools::isRectangle( aNonRect5 )); 1115 } 1116 1117 // Change the following lines only, if you add, remove or rename 1118 // member functions of the current class, 1119 // because these macros are need by auto register mechanism. 1120 1121 CPPUNIT_TEST_SUITE(b2dpolygontools); 1122 CPPUNIT_TEST(testIsRectangle); 1123 CPPUNIT_TEST_SUITE_END(); 1124 }; // class b2dpolygontools 1125 1126 1127 class b2dpolypolygon : public CppUnit::TestFixture 1128 { 1129 public: 1130 // initialise your test code values here. 1131 void setUp() 1132 { 1133 } 1134 1135 void tearDown() 1136 { 1137 } 1138 1139 // insert your test code here. 1140 void EmptyMethod() 1141 { 1142 } 1143 1144 // Change the following lines only, if you add, remove or rename 1145 // member functions of the current class, 1146 // because these macros are need by auto register mechanism. 1147 1148 CPPUNIT_TEST_SUITE(b2dpolypolygon); 1149 CPPUNIT_TEST(EmptyMethod); 1150 CPPUNIT_TEST_SUITE_END(); 1151 }; // class b2dpolypolygon 1152 1153 1154 class b2dquadraticbezier : public CppUnit::TestFixture 1155 { 1156 public: 1157 // initialise your test code values here. 1158 void setUp() 1159 { 1160 } 1161 1162 void tearDown() 1163 { 1164 } 1165 1166 // insert your test code here. 1167 // this is only demonstration code 1168 void EmptyMethod() 1169 { 1170 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1); 1171 } 1172 1173 // Change the following lines only, if you add, remove or rename 1174 // member functions of the current class, 1175 // because these macros are need by auto register mechanism. 1176 1177 CPPUNIT_TEST_SUITE(b2dquadraticbezier); 1178 CPPUNIT_TEST(EmptyMethod); 1179 CPPUNIT_TEST_SUITE_END(); 1180 }; // class b2dquadraticbezier 1181 1182 1183 class b2drange : public CppUnit::TestFixture 1184 { 1185 public: 1186 // initialise your test code values here. 1187 void setUp() 1188 { 1189 } 1190 1191 void tearDown() 1192 { 1193 } 1194 1195 // insert your test code here. 1196 void EmptyMethod() 1197 { 1198 } 1199 1200 // Change the following lines only, if you add, remove or rename 1201 // member functions of the current class, 1202 // because these macros are need by auto register mechanism. 1203 1204 CPPUNIT_TEST_SUITE(b2drange); 1205 CPPUNIT_TEST(EmptyMethod); 1206 CPPUNIT_TEST_SUITE_END(); 1207 }; // class b2drange 1208 1209 1210 class b2dtuple : public CppUnit::TestFixture 1211 { 1212 public: 1213 // initialise your test code values here. 1214 void setUp() 1215 { 1216 } 1217 1218 void tearDown() 1219 { 1220 } 1221 1222 // insert your test code here. 1223 // this is only demonstration code 1224 void EmptyMethod() 1225 { 1226 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1); 1227 } 1228 1229 // Change the following lines only, if you add, remove or rename 1230 // member functions of the current class, 1231 // because these macros are need by auto register mechanism. 1232 1233 CPPUNIT_TEST_SUITE(b2dtuple); 1234 CPPUNIT_TEST(EmptyMethod); 1235 CPPUNIT_TEST_SUITE_END(); 1236 }; // class b2dtuple 1237 1238 1239 class b2dvector : public CppUnit::TestFixture 1240 { 1241 public: 1242 // initialise your test code values here. 1243 void setUp() 1244 { 1245 } 1246 1247 void tearDown() 1248 { 1249 } 1250 1251 // insert your test code here. 1252 void EmptyMethod() 1253 { 1254 } 1255 1256 // Change the following lines only, if you add, remove or rename 1257 // member functions of the current class, 1258 // because these macros are need by auto register mechanism. 1259 1260 CPPUNIT_TEST_SUITE(b2dvector); 1261 CPPUNIT_TEST(EmptyMethod); 1262 CPPUNIT_TEST_SUITE_END(); 1263 }; // class b2dvector 1264 1265 class bcolor : public CppUnit::TestFixture 1266 { 1267 BColor maWhite; 1268 BColor maBlack; 1269 BColor maRed; 1270 BColor maGreen; 1271 BColor maBlue; 1272 BColor maYellow; 1273 BColor maMagenta; 1274 BColor maCyan; 1275 1276 public: 1277 bcolor() : 1278 maWhite(1,1,1), 1279 maBlack(0,0,0), 1280 maRed(1,0,0), 1281 maGreen(0,1,0), 1282 maBlue(0,0,1), 1283 maYellow(1,1,0), 1284 maMagenta(1,0,1), 1285 maCyan(0,1,1) 1286 {} 1287 1288 1289 // initialise your test code values here. 1290 void setUp() 1291 { 1292 } 1293 1294 void tearDown() 1295 { 1296 } 1297 1298 // insert your test code here. 1299 void hslTest() 1300 { 1301 CPPUNIT_ASSERT_MESSAGE("white", 1302 tools::rgb2hsl(maWhite) == BColor(0,0,1)); 1303 CPPUNIT_ASSERT_MESSAGE("black", 1304 tools::rgb2hsl(maBlack) == BColor(0,0,0)); 1305 CPPUNIT_ASSERT_MESSAGE("red", 1306 tools::rgb2hsl(maRed) == BColor(0,1,0.5)); 1307 CPPUNIT_ASSERT_MESSAGE("green", 1308 tools::rgb2hsl(maGreen) == BColor(120,1,0.5)); 1309 CPPUNIT_ASSERT_MESSAGE("blue", 1310 tools::rgb2hsl(maBlue) == BColor(240,1,0.5)); 1311 CPPUNIT_ASSERT_MESSAGE("yellow", 1312 tools::rgb2hsl(maYellow) == BColor(60,1,0.5)); 1313 CPPUNIT_ASSERT_MESSAGE("magenta", 1314 tools::rgb2hsl(maMagenta) == BColor(300,1,0.5)); 1315 CPPUNIT_ASSERT_MESSAGE("cyan", 1316 tools::rgb2hsl(maCyan) == BColor(180,1,0.5)); 1317 CPPUNIT_ASSERT_MESSAGE("third hue case", 1318 tools::rgb2hsl(BColor(0,0.5,1)) == BColor(210,1,0.5)); 1319 1320 CPPUNIT_ASSERT_MESSAGE("roundtrip white", 1321 tools::hsl2rgb(tools::rgb2hsl(maWhite)) == maWhite); 1322 CPPUNIT_ASSERT_MESSAGE("roundtrip black", 1323 tools::hsl2rgb(tools::rgb2hsl(maBlack)) == maBlack); 1324 CPPUNIT_ASSERT_MESSAGE("roundtrip red", 1325 tools::hsl2rgb(tools::rgb2hsl(maRed)) == maRed); 1326 CPPUNIT_ASSERT_MESSAGE("roundtrip green", 1327 tools::hsl2rgb(tools::rgb2hsl(maGreen)) == maGreen); 1328 CPPUNIT_ASSERT_MESSAGE("roundtrip blue", 1329 tools::hsl2rgb(tools::rgb2hsl(maBlue)) == maBlue); 1330 CPPUNIT_ASSERT_MESSAGE("roundtrip yellow", 1331 tools::hsl2rgb(tools::rgb2hsl(maYellow)) == maYellow); 1332 CPPUNIT_ASSERT_MESSAGE("roundtrip magenta", 1333 tools::hsl2rgb(tools::rgb2hsl(maMagenta)) == maMagenta); 1334 CPPUNIT_ASSERT_MESSAGE("roundtrip cyan", 1335 tools::hsl2rgb(tools::rgb2hsl(maCyan)) == maCyan); 1336 1337 CPPUNIT_ASSERT_MESSAGE("grey10", 1338 tools::rgb2hsl(maWhite*.1) == BColor(0,0,.1)); 1339 CPPUNIT_ASSERT_MESSAGE("grey90", 1340 tools::rgb2hsl(maWhite*.9) == BColor(0,0,.9)); 1341 CPPUNIT_ASSERT_MESSAGE("red/2", 1342 tools::rgb2hsl(maRed*.5) == BColor(0,1,0.25)); 1343 CPPUNIT_ASSERT_MESSAGE("green/2", 1344 tools::rgb2hsl(maGreen*.5) == BColor(120,1,0.25)); 1345 CPPUNIT_ASSERT_MESSAGE("blue/2", 1346 tools::rgb2hsl(maBlue*.5) == BColor(240,1,0.25)); 1347 CPPUNIT_ASSERT_MESSAGE("yellow/2", 1348 tools::rgb2hsl(maYellow*.5) == BColor(60,1,0.25)); 1349 CPPUNIT_ASSERT_MESSAGE("magenta/2", 1350 tools::rgb2hsl(maMagenta*.5) == BColor(300,1,0.25)); 1351 CPPUNIT_ASSERT_MESSAGE("cyan/2", 1352 tools::rgb2hsl(maCyan*.5) == BColor(180,1,0.25)); 1353 1354 CPPUNIT_ASSERT_MESSAGE("pastel", 1355 tools::rgb2hsl(BColor(.75,.25,.25)) == BColor(0,.5,.5)); 1356 } 1357 1358 // insert your test code here. 1359 void hsvTest() 1360 { 1361 CPPUNIT_ASSERT_MESSAGE("white", 1362 tools::rgb2hsv(maWhite) == BColor(0,0,1)); 1363 CPPUNIT_ASSERT_MESSAGE("black", 1364 tools::rgb2hsv(maBlack) == BColor(0,0,0)); 1365 CPPUNIT_ASSERT_MESSAGE("red", 1366 tools::rgb2hsv(maRed) == BColor(0,1,1)); 1367 CPPUNIT_ASSERT_MESSAGE("green", 1368 tools::rgb2hsv(maGreen) == BColor(120,1,1)); 1369 CPPUNIT_ASSERT_MESSAGE("blue", 1370 tools::rgb2hsv(maBlue) == BColor(240,1,1)); 1371 CPPUNIT_ASSERT_MESSAGE("yellow", 1372 tools::rgb2hsv(maYellow) == BColor(60,1,1)); 1373 CPPUNIT_ASSERT_MESSAGE("magenta", 1374 tools::rgb2hsv(maMagenta) == BColor(300,1,1)); 1375 CPPUNIT_ASSERT_MESSAGE("cyan", 1376 tools::rgb2hsv(maCyan) == BColor(180,1,1)); 1377 1378 CPPUNIT_ASSERT_MESSAGE("roundtrip white", 1379 tools::hsv2rgb(tools::rgb2hsv(maWhite)) == maWhite); 1380 CPPUNIT_ASSERT_MESSAGE("roundtrip black", 1381 tools::hsv2rgb(tools::rgb2hsv(maBlack)) == maBlack); 1382 CPPUNIT_ASSERT_MESSAGE("roundtrip red", 1383 tools::hsv2rgb(tools::rgb2hsv(maRed)) == maRed); 1384 CPPUNIT_ASSERT_MESSAGE("roundtrip green", 1385 tools::hsv2rgb(tools::rgb2hsv(maGreen)) == maGreen); 1386 CPPUNIT_ASSERT_MESSAGE("roundtrip blue", 1387 tools::hsv2rgb(tools::rgb2hsv(maBlue)) == maBlue); 1388 CPPUNIT_ASSERT_MESSAGE("roundtrip yellow", 1389 tools::hsv2rgb(tools::rgb2hsv(maYellow)) == maYellow); 1390 CPPUNIT_ASSERT_MESSAGE("roundtrip magenta", 1391 tools::hsv2rgb(tools::rgb2hsv(maMagenta)) == maMagenta); 1392 CPPUNIT_ASSERT_MESSAGE("roundtrip cyan", 1393 tools::hsv2rgb(tools::rgb2hsv(maCyan)) == maCyan); 1394 1395 CPPUNIT_ASSERT_MESSAGE("grey10", 1396 tools::rgb2hsv(maWhite*.1) == BColor(0,0,.1)); 1397 CPPUNIT_ASSERT_MESSAGE("grey90", 1398 tools::rgb2hsv(maWhite*.9) == BColor(0,0,.9)); 1399 CPPUNIT_ASSERT_MESSAGE("red/2", 1400 tools::rgb2hsv(maRed*.5) == BColor(0,1,0.5)); 1401 CPPUNIT_ASSERT_MESSAGE("green/2", 1402 tools::rgb2hsv(maGreen*.5) == BColor(120,1,0.5)); 1403 CPPUNIT_ASSERT_MESSAGE("blue/2", 1404 tools::rgb2hsv(maBlue*.5) == BColor(240,1,0.5)); 1405 CPPUNIT_ASSERT_MESSAGE("yellow/2", 1406 tools::rgb2hsv(maYellow*.5) == BColor(60,1,0.5)); 1407 CPPUNIT_ASSERT_MESSAGE("magenta/2", 1408 tools::rgb2hsv(maMagenta*.5) == BColor(300,1,0.5)); 1409 CPPUNIT_ASSERT_MESSAGE("cyan/2", 1410 tools::rgb2hsv(maCyan*.5) == BColor(180,1,0.5)); 1411 1412 CPPUNIT_ASSERT_MESSAGE("pastel", 1413 tools::rgb2hsv(BColor(.5,.25,.25)) == BColor(0,.5,.5)); 1414 } 1415 1416 void ciexyzTest() 1417 { 1418 tools::rgb2ciexyz(maWhite); 1419 tools::rgb2ciexyz(maBlack); 1420 tools::rgb2ciexyz(maRed); 1421 tools::rgb2ciexyz(maGreen); 1422 tools::rgb2ciexyz(maBlue); 1423 tools::rgb2ciexyz(maYellow); 1424 tools::rgb2ciexyz(maMagenta); 1425 tools::rgb2ciexyz(maCyan); 1426 } 1427 1428 // Change the following lines only, if you add, remove or rename 1429 // member functions of the current class, 1430 // because these macros are need by auto register mechanism. 1431 1432 CPPUNIT_TEST_SUITE(bcolor); 1433 CPPUNIT_TEST(hslTest); 1434 CPPUNIT_TEST(hsvTest); 1435 CPPUNIT_TEST(ciexyzTest); 1436 CPPUNIT_TEST_SUITE_END(); 1437 }; // class b2dvector 1438 1439 // ----------------------------------------------------------------------------- 1440 1441 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dsvgdimpex); 1442 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolyrange); 1443 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dcubicbezier); 1444 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhommatrix); 1445 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhompoint); 1446 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpoint); 1447 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygon); 1448 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygontools); 1449 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolypolygon); 1450 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dquadraticbezier); 1451 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2drange); 1452 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dtuple); 1453 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dvector); 1454 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::bcolor); 1455 } // namespace basegfx2d 1456 1457 1458 // ----------------------------------------------------------------------------- 1459 1460 // this macro creates an empty function, which will called by the RegisterAllFunctions() 1461 // to let the user the possibility to also register some functions by hand. 1462 // NOADDITIONAL; 1463 1464