From: jaspervdg Date: Sat, 2 Aug 2008 14:25:08 +0000 (+0000) Subject: SPCurve unit tests X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=f30a3d27abf3baff3c4cc30512d9dbf19224a65a;p=inkscape.git SPCurve unit tests --- diff --git a/build.xml b/build.xml index 224892d1a..c8a65cab3 100644 --- a/build.xml +++ b/build.xml @@ -199,7 +199,7 @@ description="generate test files" > - @@ -215,19 +215,20 @@ - + - - @@ -241,7 +242,7 @@ - @@ -252,13 +253,13 @@ - - diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index bc74c6f22..7db15cf39 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -139,7 +139,8 @@ display/test-display.cpp: $(display_test_display_includes) $(top_srcdir)/cxxtest/cxxtestgen.pl -part -o display/test-display.cpp $(display_test_display_includes) display_test_display_includes = \ - $(srcdir)/display/bezier-utils-test.h + $(srcdir)/display/bezier-utils-test.h \ + $(srcdir)/display/curve-test.h display_libtest_display_a_SOURCES = \ display/test-display.cpp \ diff --git a/src/display/bezier-utils-test.h b/src/display/bezier-utils-test.h index 4e5788983..eb2b13d7b 100644 --- a/src/display/bezier-utils-test.h +++ b/src/display/bezier-utils-test.h @@ -9,8 +9,6 @@ #define's and `using' directives of the included file. */ #include "bezier-utils.cpp" -using NR::Point; - /* (Returns false if NaN encountered.) */ static bool range_approx_equal(double const a[], double const b[], unsigned const len) { for (unsigned i = 0; i < len; ++i) { @@ -37,7 +35,7 @@ static inline double square(double const x) { the most important test is that the root-mean-square of errors in the estimation are low rather than that the control points found are the same. **/ -static void compare_ctlpts(Point const est_b[], Point const exp_est_b[]) +static void compare_ctlpts(NR::Point const est_b[], NR::Point const exp_est_b[]) { unsigned diff_mask = 0; for (unsigned i = 0; i < 4; ++i) { @@ -64,13 +62,13 @@ static void compare_ctlpts(Point const est_b[], Point const exp_est_b[]) } } -static void compare_rms(Point const est_b[], double const t[], Point const d[], unsigned const n, +static void compare_rms(NR::Point const est_b[], double const t[], NR::Point const d[], unsigned const n, double const exp_rms_error) { double sum_errsq = 0.0; for (unsigned i = 0; i < n; ++i) { - Point const fit_pt = bezier_pt(3, est_b, t[i]); - Point const diff = fit_pt - d[i]; + NR::Point const fit_pt = bezier_pt(3, est_b, t[i]); + NR::Point const diff = fit_pt - d[i]; sum_errsq += dot(diff, diff); } double const rms_error = sqrt( sum_errsq / n ); @@ -86,13 +84,13 @@ static void compare_rms(Point const est_b[], double const t[], Point const d[], class BezierUtilsTest : public CxxTest::TestSuite { public: - static Point const c[4]; + static NR::Point const c[4]; static double const t[24]; static unsigned const n; - Point d[24]; - static Point const src_b[4]; - static Point const tHat1; - static Point const tHat2; + NR::Point d[24]; + static NR::Point const src_b[4]; + static NR::Point const tHat1; + static NR::Point const tHat2; BezierUtilsTest() { @@ -112,22 +110,22 @@ public: void testCopyWithoutNansOrAdjacentDuplicates() { NR::Point const src[] = { - Point(2., 3.), - Point(2., 3.), - Point(0., 0.), - Point(2., 3.), - Point(2., 3.), - Point(1., 9.), - Point(1., 9.) + NR::Point(2., 3.), + NR::Point(2., 3.), + NR::Point(0., 0.), + NR::Point(2., 3.), + NR::Point(2., 3.), + NR::Point(1., 9.), + NR::Point(1., 9.) }; - Point const exp_dest[] = { - Point(2., 3.), - Point(0., 0.), - Point(2., 3.), - Point(1., 9.) + NR::Point const exp_dest[] = { + NR::Point(2., 3.), + NR::Point(0., 0.), + NR::Point(2., 3.), + NR::Point(1., 9.) }; g_assert( G_N_ELEMENTS(src) == 7 ); - Point dest[7]; + NR::Point dest[7]; struct tst { unsigned src_ix0; unsigned src_len; @@ -159,11 +157,11 @@ public: void testBezierPt1() { - Point const a[] = {Point(2.0, 4.0), - Point(1.0, 8.0)}; + NR::Point const a[] = {NR::Point(2.0, 4.0), + NR::Point(1.0, 8.0)}; TS_ASSERT_EQUALS( bezier_pt(1, a, 0.0) , a[0] ); TS_ASSERT_EQUALS( bezier_pt(1, a, 1.0) , a[1] ); - TS_ASSERT_EQUALS( bezier_pt(1, a, 0.5) , Point(1.5, 6.0) ); + TS_ASSERT_EQUALS( bezier_pt(1, a, 0.5) , NR::Point(1.5, 6.0) ); double const t[] = {0.5, 0.25, 0.3, 0.6}; for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) { double const ti = t[i], si = 1.0 - ti; @@ -173,17 +171,17 @@ public: void testBezierPt2() { - Point const b[] = {Point(1.0, 2.0), - Point(8.0, 4.0), - Point(3.0, 1.0)}; + NR::Point const b[] = {NR::Point(1.0, 2.0), + NR::Point(8.0, 4.0), + NR::Point(3.0, 1.0)}; TS_ASSERT_EQUALS( bezier_pt(2, b, 0.0) , b[0] ); TS_ASSERT_EQUALS( bezier_pt(2, b, 1.0) , b[2] ); - TS_ASSERT_EQUALS( bezier_pt(2, b, 0.5) , Point(5.0, 2.75) ); + TS_ASSERT_EQUALS( bezier_pt(2, b, 0.5) , NR::Point(5.0, 2.75) ); double const t[] = {0.5, 0.25, 0.3, 0.6}; for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) { double const ti = t[i], si = 1.0 - ti; - Point const exp_pt( si*si * b[0] + 2*si*ti * b[1] + ti*ti * b[2] ); - Point const pt(bezier_pt(2, b, ti)); + NR::Point const exp_pt( si*si * b[0] + 2*si*ti * b[1] + ti*ti * b[2] ); + NR::Point const pt(bezier_pt(2, b, ti)); TS_ASSERT(point_approx_equal(pt, exp_pt, 1e-11)); } } @@ -192,7 +190,7 @@ public: { TS_ASSERT_EQUALS( bezier_pt(3, c, 0.0) , c[0] ); TS_ASSERT_EQUALS( bezier_pt(3, c, 1.0) , c[3] ); - TS_ASSERT_EQUALS( bezier_pt(3, c, 0.5) , Point(4.0, 13.0/8.0) ); + TS_ASSERT_EQUALS( bezier_pt(3, c, 0.5) , NR::Point(4.0, 13.0/8.0) ); double const t[] = {0.5, 0.25, 0.3, 0.6}; for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) { double const ti = t[i], si = 1.0 - ti; @@ -208,18 +206,18 @@ public: void testComputeMaxErrorRatio() { struct Err_tst { - Point pt; + NR::Point pt; double u; double err; } const err_tst[] = { {c[0], 0.0, 0.0}, - {Point(4.0, 13.0/8.0), 0.5, 0.0}, - {Point(4.0, 2.0), 0.5, 9.0/64.0}, - {Point(3.0, 2.0), 0.5, 1.0 + 9.0/64.0}, - {Point(6.0, 2.0), 0.5, 4.0 + 9.0/64.0}, + {NR::Point(4.0, 13.0/8.0), 0.5, 0.0}, + {NR::Point(4.0, 2.0), 0.5, 9.0/64.0}, + {NR::Point(3.0, 2.0), 0.5, 1.0 + 9.0/64.0}, + {NR::Point(6.0, 2.0), 0.5, 4.0 + 9.0/64.0}, {c[3], 1.0, 0.0}, }; - Point d[G_N_ELEMENTS(err_tst)]; + NR::Point d[G_N_ELEMENTS(err_tst)]; double u[G_N_ELEMENTS(err_tst)]; for (unsigned i = 0; i < G_N_ELEMENTS(err_tst); ++i) { Err_tst const &t = err_tst[i]; @@ -230,15 +228,15 @@ public: unsigned max_ix = ~0u; double const err_ratio = compute_max_error_ratio(d, u, G_N_ELEMENTS(d), c, 1.0, &max_ix); TS_ASSERT_LESS_THAN( fabs( sqrt(err_tst[4].err) - err_ratio ) , 1e-12 ); - TS_ASSERT_EQUALS( max_ix , 4 ); + TS_ASSERT_EQUALS( max_ix , 4u ); } void testChordLengthParameterize() { /* n == 2 */ { - Point const d[] = {Point(2.9415, -5.8149), - Point(23.021, 4.9814)}; + NR::Point const d[] = {NR::Point(2.9415, -5.8149), + NR::Point(23.021, 4.9814)}; double u[G_N_ELEMENTS(d)]; double const exp_u[] = {0.0, 1.0}; g_assert( G_N_ELEMENTS(u) == G_N_ELEMENTS(exp_u) ); @@ -250,9 +248,9 @@ public: { double const exp_u[] = {0.0, 0.1829, 0.2105, 0.2105, 0.619, 0.815, 0.999, 1.0}; unsigned const n = G_N_ELEMENTS(exp_u); - Point d[n]; + NR::Point d[n]; double u[n]; - Point const a(-23.985, 4.915), b(4.9127, 5.203); + NR::Point const a(-23.985, 4.915), b(4.9127, 5.203); for (unsigned i = 0; i < n; ++i) { double bi = exp_u[i], ai = 1.0 - bi; d[i] = ai * a + bi * b; @@ -264,7 +262,7 @@ public: void testGenerateBezier() { - Point est_b[4]; + NR::Point est_b[4]; generate_bezier(est_b, d, t, n, tHat1, tHat2, 1.0); compare_ctlpts(est_b, src_b); @@ -276,16 +274,16 @@ public: void testSpBezierFitCubicFull() { - Point est_b[4]; + NR::Point est_b[4]; int splitpoints[2]; gint const succ = sp_bezier_fit_cubic_full(est_b, splitpoints, d, n, tHat1, tHat2, square(1.2), 1); TS_ASSERT_EQUALS( succ , 1 ); - Point const exp_est_b[4] = { - Point(5.000000, -3.000000), - Point(7.5753, -0.4247), - Point(4.77533, 1.22467), - Point(3, 3) + NR::Point const exp_est_b[4] = { + NR::Point(5.000000, -3.000000), + NR::Point(7.5753, -0.4247), + NR::Point(4.77533, 1.22467), + NR::Point(3, 3) }; compare_ctlpts(est_b, exp_est_b); @@ -296,15 +294,15 @@ public: void testSpBezierFitCubic() { - Point est_b[4]; + NR::Point est_b[4]; gint const succ = sp_bezier_fit_cubic(est_b, d, n, square(1.2)); TS_ASSERT_EQUALS( succ , 1 ); - Point const exp_est_b[4] = { - Point(5.000000, -3.000000), - Point(7.57134, -0.423509), - Point(4.77929, 1.22426), - Point(3, 3) + NR::Point const exp_est_b[4] = { + NR::Point(5.000000, -3.000000), + NR::Point(7.57134, -0.423509), + NR::Point(4.77929, 1.22426), + NR::Point(3, 3) }; compare_ctlpts(est_b, exp_est_b); @@ -323,22 +321,22 @@ public: }; // This is not very neat, but since we know this header is only included by the generated CxxTest file it shouldn't give any problems -Point const BezierUtilsTest::c[4] = { - Point(1.0, 2.0), - Point(8.0, 4.0), - Point(3.0, 1.0), - Point(-2.0, -4.0)}; +NR::Point const BezierUtilsTest::c[4] = { + NR::Point(1.0, 2.0), + NR::Point(8.0, 4.0), + NR::Point(3.0, 1.0), + NR::Point(-2.0, -4.0)}; double const BezierUtilsTest::t[24] = { 0.0, .001, .03, .05, .09, .13, .18, .25, .29, .33, .39, .44, .51, .57, .62, .69, .75, .81, .91, .93, .97, .98, .999, 1.0}; unsigned const BezierUtilsTest::n = G_N_ELEMENTS(BezierUtilsTest::t); -Point const BezierUtilsTest::src_b[4] = { - Point(5., -3.), - Point(8., 0.), - Point(4., 2.), - Point(3., 3.)}; -Point const BezierUtilsTest::tHat1(unit_vector( BezierUtilsTest::src_b[1] - BezierUtilsTest::src_b[0] )); -Point const BezierUtilsTest::tHat2(unit_vector( BezierUtilsTest::src_b[2] - BezierUtilsTest::src_b[3] )); +NR::Point const BezierUtilsTest::src_b[4] = { + NR::Point(5., -3.), + NR::Point(8., 0.), + NR::Point(4., 2.), + NR::Point(3., 3.)}; +NR::Point const BezierUtilsTest::tHat1(unit_vector( BezierUtilsTest::src_b[1] - BezierUtilsTest::src_b[0] )); +NR::Point const BezierUtilsTest::tHat2(unit_vector( BezierUtilsTest::src_b[2] - BezierUtilsTest::src_b[3] )); /* Local Variables: diff --git a/src/display/curve-test.h b/src/display/curve-test.h new file mode 100644 index 000000000..cca77e063 --- /dev/null +++ b/src/display/curve-test.h @@ -0,0 +1,254 @@ +#include + +#include "display/curve.h" +#include <2geom/curves.h> +#include <2geom/path.h> +#include <2geom/pathvector.h> + +class CurveTest : public CxxTest::TestSuite { +private: + Geom::Path path1; + Geom::Path path2; + Geom::Path path3; + Geom::Path path4; + +public: + CurveTest() : path4(Geom::Point(3,5)) // Just a moveto + { + // Closed path which needs a closing segment + path1.append(Geom::HLineSegment(Geom::Point(0,0),1)); + path1.append(Geom::VLineSegment(Geom::Point(1,0),1)); + path1.close(); + // Closed path that doesn't need a closing segment + path2.append(Geom::LineSegment(Geom::Point(2,0),Geom::Point(3,0))); + path2.append(Geom::BezierCurve<3>(Geom::Point(3,0),Geom::Point(2,1),Geom::Point(1,1),Geom::Point(2,0))); + path2.close(); + // Open path + path3.append(Geom::SVGEllipticalArc(Geom::Point(4,0),1,2,M_PI,false,false,Geom::Point(5,1))); + path3.append(Geom::VLineSegment(Geom::Point(5,1),2), Geom::Path::STITCH_DISCONTINUOUS); + path3.append(Geom::HLineSegment(Geom::Point(6,4),2), Geom::Path::STITCH_DISCONTINUOUS); + } + virtual ~CurveTest() {} + +// createSuite and destroySuite get us per-suite setup and teardown +// without us having to worry about static initialization order, etc. + static CurveTest *createSuite() { return new CurveTest(); } + static void destroySuite( CurveTest *suite ) { delete suite; } + + void testGetSegmentCount() + { + { // Zero segments + Geom::PathVector pv; + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.get_segment_count() , 0u); + } + { // Zero segments + Geom::PathVector pv; + pv.push_back(Geom::Path()); + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.get_segment_count() , 0u); + } + { // Individual paths + Geom::PathVector pv(1, Geom::Path()); + pv[0] = path1; + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 3u); + pv[0] = path2; + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 2u); + pv[0] = path3; + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 4u); + pv[0] = path4; + TS_ASSERT_EQUALS(SPCurve(pv).get_segment_count() , 0u); + } + { // Combination + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + pv.push_back(path4); + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.get_segment_count() , 9u); + } + } + + void testNodesInPath() + { + { // Zero segments + Geom::PathVector pv; + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.nodes_in_path() , 0u); + } + { // Zero segments + Geom::PathVector pv; + pv.push_back(Geom::Path()); + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.nodes_in_path() , 1u); + } + { // Individual paths + Geom::PathVector pv(1, Geom::Path()); + pv[0] = path1; + TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 3u); + pv[0] = path2; + TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 2u); + pv[0] = path3; + TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 5u); + pv[0] = path4; + TS_ASSERT_EQUALS(SPCurve(pv).nodes_in_path() , 1u); + } + { // Combination + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + pv.push_back(path4); + SPCurve curve(pv); + TS_ASSERT_EQUALS(curve.nodes_in_path() , 11u); + } + } + + void testIsEmpty() + { + TS_ASSERT(SPCurve(Geom::PathVector()).is_empty()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path1)).is_empty()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path2)).is_empty()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path3)).is_empty()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path4)).is_empty()); + } + + void testIsClosed() + { + TS_ASSERT(SPCurve(Geom::PathVector()).is_closed()); // An empty conjuction is true + Geom::PathVector pv(1, Geom::Path()); + TS_ASSERT(!SPCurve(pv).is_closed()); + pv[0].close(); + TS_ASSERT(SPCurve(pv).is_closed()); + TS_ASSERT(SPCurve(Geom::PathVector(1, path1)).is_closed()); + TS_ASSERT(SPCurve(Geom::PathVector(1, path2)).is_closed()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path3)).is_closed()); + TS_ASSERT(!SPCurve(Geom::PathVector(1, path4)).is_closed()); + } + + void testLastFirstSegment() + { + Geom::PathVector pv(1, path4); + TS_ASSERT_EQUALS(SPCurve(pv).first_segment() , (void*)0); + TS_ASSERT_EQUALS(SPCurve(pv).last_segment() , (void*)0); + pv[0].close(); + TS_ASSERT_DIFFERS(SPCurve(pv).first_segment() , (void*)0); + TS_ASSERT_DIFFERS(SPCurve(pv).last_segment() , (void*)0); + /* Geom::Curve can't be compared very easily (?) + Geom::PathVector pv(1, path4); + pv[0].close(); + TS_ASSERT_EQUALS(*SPCurve(pv).first_segment() , pv[0][0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_segment() , pv[0][0]); + pv[0] = path1; + TS_ASSERT_EQUALS(*SPCurve(pv).first_segment() , pv[0][0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_segment() , pv[0][2]); + pv[0] = path2; + TS_ASSERT_EQUALS(*SPCurve(pv).first_segment() , pv[0][0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_segment() , pv[0][1]); + pv[0] = path3; + TS_ASSERT_EQUALS(*SPCurve(pv).first_segment() , pv[0][0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_segment() , pv[0][3]); + pv[0] = path4; + TS_ASSERT_EQUALS(SPCurve(pv).first_segment() , (void*)0); + TS_ASSERT_EQUALS(SPCurve(pv).last_segment() , (void*)0); + pv.clear(); + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + TS_ASSERT_EQUALS(*SPCurve(pv).first_segment() , pv[0][0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_segment() , pv[2][3]);*/ + } + + void testLastFirstPath() + { + Geom::PathVector pv; + TS_ASSERT_EQUALS(SPCurve(pv).first_path() , (void*)0); + TS_ASSERT_EQUALS(SPCurve(pv).last_path() , (void*)0); + pv.push_back(path1); + TS_ASSERT_EQUALS(*SPCurve(pv).first_path() , pv[0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_path() , pv[0]); + pv.push_back(path2); + TS_ASSERT_EQUALS(*SPCurve(pv).first_path() , pv[0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_path() , pv[1]); + pv.push_back(path3); + TS_ASSERT_EQUALS(*SPCurve(pv).first_path() , pv[0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_path() , pv[2]); + pv.push_back(path4); + TS_ASSERT_EQUALS(*SPCurve(pv).first_path() , pv[0]); + TS_ASSERT_EQUALS(*SPCurve(pv).last_path() , pv[3]); + } + + void testFirstPoint() + { + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path1)).first_point() , Geom::Point(0,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path2)).first_point() , Geom::Point(2,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path3)).first_point() , Geom::Point(4,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path4)).first_point() , Geom::Point(3,5)); + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + TS_ASSERT_EQUALS(SPCurve(pv).first_point() , Geom::Point(0,0)); + pv.insert(pv.begin(), path4); + TS_ASSERT_EQUALS(SPCurve(pv).first_point() , Geom::Point(3,5)); + } + + void testLastPoint() + { + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path1)).last_point() , Geom::Point(0,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path2)).last_point() , Geom::Point(2,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path3)).last_point() , Geom::Point(8,4)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path4)).last_point() , Geom::Point(3,5)); + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + TS_ASSERT_EQUALS(SPCurve(pv).last_point() , Geom::Point(8,4)); + pv.push_back(path4); + TS_ASSERT_EQUALS(SPCurve(pv).last_point() , Geom::Point(3,5)); + } + + void testSecondPoint() + { + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path1)).second_point() , Geom::Point(1,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path2)).second_point() , Geom::Point(3,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path3)).second_point() , Geom::Point(5,1)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path4)).second_point() , Geom::Point(3,5)); + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + TS_ASSERT_EQUALS(SPCurve(pv).second_point() , Geom::Point(1,0)); + pv.insert(pv.begin(), path4); + TS_ASSERT_EQUALS(SPCurve(pv).second_point() , Geom::Point(0,0)); + } + + void testPenultimatePoint() + { + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path1)).penultimate_point() , Geom::Point(1,1)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path2)).penultimate_point() , Geom::Point(3,0)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path3)).penultimate_point() , Geom::Point(6,4)); + TS_ASSERT_EQUALS(SPCurve(Geom::PathVector(1, path4)).penultimate_point() , Geom::Point(3,5)); + Geom::PathVector pv; + pv.push_back(path1); + pv.push_back(path2); + pv.push_back(path3); + TS_ASSERT_EQUALS(SPCurve(pv).penultimate_point() , Geom::Point(6,4)); + pv.push_back(path4); + TS_ASSERT_EQUALS(SPCurve(pv).penultimate_point() , Geom::Point(8,4)); + } + + // TODO: Rest of the methods +}; + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :