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