001/**
002 * CurveTestSuite -- An suite of unit tests for the geomss.geom curves.
003 *
004 * Copyright (C) 2014-2015 by Joseph A. Huwaldt. All rights reserved.
005 *
006 * This library is free software; you can redistribute it and/or modify it under the terms
007 * of the GNU Lesser General Public License as published by the Free Software Foundation;
008 * either version 2 of the License, or (at your option) any later version.
009 *
010 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
012 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public License along with
015 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place -
016 * Suite 330, Boston, MA 02111-1307, USA. Or visit: http://www.gnu.org/licenses/lgpl.html
017 */
018package geomss.geom;
019
020import geomss.geom.nurbs.CurveFactory;
021import geomss.geom.nurbs.CurveUtils;
022import geomss.geom.nurbs.NurbsCurve;
023import jahuwaldt.js.param.Parameter;
024import jahuwaldt.tools.math.MathTools;
025import java.util.List;
026import javax.measure.quantity.Area;
027import javax.measure.quantity.Dimensionless;
028import javax.measure.quantity.Length;
029import static javax.measure.unit.NonSI.*;
030import static javax.measure.unit.SI.*;
031import static javolution.lang.MathLib.*;
032import javolution.testing.TestCase;
033import javolution.testing.TestContext;
034import javolution.testing.TestSuite;
035import javolution.text.TextBuilder;
036
037/**
038 * This class holds the {@link geomss.geom} Curve unit tests and benchmarks.
039 *
040 * <p> Modified by: Joseph A. Huwaldt </p>
041 *
042 * @author Joseph A. Huwaldt, Date: February 28, 2014
043 * @version August 31, 2015
044 */
045public class CurveTestSuite extends TestSuite {
046
047    private static final Parameter<Length> TOL = Parameter.valueOf(0.1, INCH);
048
049    @Override
050    public void run() {
051        TestContext.info("---------------------------------------");
052        TestContext.info("-- Test Suite for geomss.geom curves --");
053        TestContext.info("---------------------------------------");
054
055        //  A simple line segment.
056        String typeStr = "LineSeg";
057        TestContext.info("-- " + typeStr);
058        Point p0 = Point.valueOf(0, 0, FOOT);
059        Point p1 = Point.valueOf(2, 3, 5, METER);
060        LineSeg line1 = LineSeg.valueOf(p0, p1);
061        GenericSingleCurveTests gCrvTest = new GenericSingleCurveTests(line1, typeStr);
062        gCrvTest.isPlanar = true;
063        gCrvTest.isCircular = false;
064        gCrvTest.isLine = true;
065        gCrvTest.isDegenerate = false;
066        gCrvTest.p = p1.plus(p0.toDimension(3)).divide(2);
067        gCrvTest.pu = Vector.valueOf(Point.valueOf(2, 3, 5, METER).minus(Point.valueOf(0, 0, 0, FOOT)));
068        gCrvTest.puu = Vector.valueOf(METER, 0, 0, 0);
069        gCrvTest.voc = Parameter.valueOf(0, FOOT.inverse());
070        TestContext.test(gCrvTest);
071
072        //  Curve Arc Length test.
073        TestContext.test(new ArcLengthTest(line1, Parameter.valueOf(20.2244553903182, FOOT), typeStr));
074
075        //  Test enclosed area
076        TestContext.test(new EnclosedAreaTest(line1, Parameter.valueOf(0, Area.UNIT), typeStr));
077
078        //  Point-Curve closest test.
079        p0 = Point.valueOf(1, 1, 1);
080        TestContext.test(new PointCurveClosestTest(line1, p0, line1.getPoint(0.263157894736842), typeStr));
081
082        //  Test Curve-LineSeg intersection.
083        p0 = Point.valueOf(0.333333333333333, 1.83333333333333, 1.83333333333333, METER);
084        p1 = Point.valueOf(1.66666666666667, 1.16666666666667, 3.16666666666667, METER);
085        LineSeg line2 = LineSeg.valueOf(p0, p1);
086        TestContext.test(new CCIntersectionTest(line1, line2, line1.getPoint(0.5), typeStr + "-LineSeg"));
087
088        //  Test Curve-Plane intersection.
089        Plane pln = Plane.getXZ();
090        pln = pln.changeRefPoint(Point.valueOf(0.5, 0.5, 0.5));
091        TestContext.test(new CPlaneIntersectionTest(line1, pln, line1.getPoint(0.0508), typeStr));
092
093        //  A 2D circle through 3 points.
094        typeStr = "NURBS 2D Circular Arc";
095        TestContext.info("-- " + typeStr);
096        p0 = Point.valueOf(-1, 0);
097        p1 = Point.valueOf(0, 1.5);
098        Point p2 = Point.valueOf(1, 0);
099        Curve curve = CurveFactory.createCircularArc(p0, p1, p2);
100        gCrvTest = new GenericSingleCurveTests(curve, typeStr);
101        gCrvTest.isPlanar = true;
102        gCrvTest.isCircular = true;
103        gCrvTest.isLine = false;
104        gCrvTest.isDegenerate = false;
105        gCrvTest.p = Point.valueOf(METER, 0, 1.5);
106        gCrvTest.pu = Vector.valueOf(METER, 4.417961017824146, 0);
107        gCrvTest.puu = Vector.valueOf(METER, -3.27e-15, -18.016965743089628);
108        gCrvTest.voc = Parameter.valueOf(0, METER.inverse());
109        TestContext.test(gCrvTest);
110
111        //  Curve Arc Length test.
112        TestContext.test(new ArcLengthTest(curve, Parameter.valueOf(4.25877278332892, METER), typeStr));
113
114        //  Test enclosed area
115        TestContext.test(new EnclosedAreaTest(curve, Parameter.valueOf(-2.72350193375409, Area.UNIT), typeStr));
116
117        //  Point-Curve closest test.
118        p0 = Point.valueOf(2, 1);
119        TestContext.test(new PointCurveClosestTest(curve, p0, curve.getPoint(0.827597726725164), typeStr));
120
121        //  Test Curve-LineSeg intersection.
122        p0 = Point.valueOf(-2, 0.5, METER);
123        p1 = Point.valueOf(3, 0, METER);
124        line2 = LineSeg.valueOf(p0, p1);
125        TestContext.test(new CCIntersectionTest(curve, line2, curve.getPoint(0.100516622598477), typeStr + "-LineSeg"));
126
127        //  Test Curve-Curve intersection.
128        p0 = Point.valueOf(0.5, 1);
129        Parameter R = Parameter.valueOf(1, METER);
130        Curve curve2 = CurveFactory.createCircle(p0, R, null);
131        TestContext.test(new CCIntersectionTest(curve, curve2, curve.getPoint(0.404600667366484), typeStr + "-" + typeStr));
132
133        //  A 3D semi-circle
134        typeStr = "NURBS 3D Circular Arc";
135        TestContext.info("-- " + typeStr);
136        Point o = Point.valueOf(0, 0, 0, FOOT);
137        Parameter<Length> r = Parameter.valueOf(3, METER);
138        Vector<Dimensionless> nhat = Vector.valueOf(Dimensionless.UNIT, 0, 0, 1);
139        curve = CurveFactory.createSemiCircle(o, r, nhat);
140        gCrvTest = new GenericSingleCurveTests(curve, typeStr);
141        gCrvTest.isPlanar = true;
142        gCrvTest.isCircular = true;
143        gCrvTest.isLine = false;
144        gCrvTest.isDegenerate = false;
145        gCrvTest.p = Point.valueOf(METER, 3, 0, 0);
146        gCrvTest.pu = Vector.valueOf(METER, 0, 12, 0);
147        gCrvTest.puu = Vector.valueOf(METER, -48, 0, 0);
148        gCrvTest.voc = Parameter.valueOf(0, FOOT.inverse());
149        TestContext.test(gCrvTest);
150
151        //  Curve Arc Length test.
152        Parameter<Length> arcL = r.times(PI);                  //  Half the perimeter of a circle.
153        TestContext.test(new ArcLengthTest(curve, arcL, typeStr));
154
155        //  Test enclosed area
156        Parameter<Area> area = r.pow(2).times(PI / 2).asType(Area.class);    //  Half-circle area.
157        TestContext.test(new EnclosedAreaTest(curve, area, typeStr));
158
159        //  Point-Curve closest test.
160        p0 = Point.valueOf(1, 1, 1);
161        TestContext.test(new PointCurveClosestTest(curve, p0, curve.getPoint(0.707106781186547), typeStr));
162
163        //  Test Curve-LineSeg intersection.
164        p0 = o;
165        p1 = Point.valueOf(6, 2, 0, METER);
166        line2 = LineSeg.valueOf(p0, p1);
167        TestContext.test(new CCIntersectionTest(curve, line2, curve.getPoint(0.581152226585933), typeStr + "-LineSeg"));
168
169        //  Test Curve-Curve intersection.
170        curve2 = (Curve)curve.getTransformed(GTransform.newTranslation(1, 1, 0));
171        TestContext.test(new CCIntersectionTest(curve, curve2, curve.getPoint(0.359375), typeStr + "-Transformed Curve"));
172
173        //  Test Curve-Curve intersection.
174        o = Point.valueOf(1, 1, 0, FOOT);
175        Parameter<Length> a = Parameter.valueOf(9, FOOT);
176        Parameter<Length> b = Parameter.valueOf(3, FOOT);
177        curve2 = CurveFactory.createEllipse(o, a, b, nhat);
178        TestContext.test(new CCIntersectionTest(curve, curve2, curve.getPoint(0.545983754390616), typeStr + "-Ellipse"));
179
180        //  Test Curve-Plane intersection.
181        pln = Plane.getXZ();
182        pln = pln.changeRefPoint(Point.valueOf(0.5, 0.5, 0.5));
183        TestContext.test(new CPlaneIntersectionTest(curve, pln, curve.getPoint(0.541960108450192), typeStr));
184
185        //  A subrange curve.
186        typeStr = "3D Subrange Curve on Curve";
187        TestContext.info("-- " + typeStr);
188        PointString<Point> pstr = PointString.newInstance();
189        pstr.add(Point.valueOf(0), Point.valueOf(.5));
190        Curve pcrv = CurveFactory.fitPoints(1, pstr);
191        SubrangeCurve subrange = SubrangeCurve.newInstance(curve, pcrv);
192
193        gCrvTest = new GenericSingleCurveTests(subrange, typeStr);
194        gCrvTest.isPlanar = true;
195        gCrvTest.isCircular = true;
196        gCrvTest.isLine = false;
197        gCrvTest.isDegenerate = false;
198        gCrvTest.p = Point.valueOf(METER, 1.8, -2.4, 0);
199        gCrvTest.pu = Vector.valueOf(METER, 3.84, 2.88, 0);
200        gCrvTest.puu = Vector.valueOf(METER, -1.536, 8.448, 0);
201        gCrvTest.voc = Parameter.valueOf(0, FOOT.inverse());
202        TestContext.test(gCrvTest);
203
204        //  Curve Arc Length test.
205        double theta = PI / 2;        //  1/4 circle swept area.
206        arcL = r.times(theta);      //  1/4 the perimeter of a circle.
207        TestContext.test(new ArcLengthTest(subrange, arcL, typeStr));
208
209        //  Test enclosed area
210        //  Segment area: area = 1/2*(theta - sin(theta))*R^2
211        area = r.pow(2).times(theta - sin(theta)).divide(2).asType(Area.class);
212        TestContext.test(new EnclosedAreaTest(subrange, area, typeStr));
213
214        //  Point-Curve closest test.
215        p0 = Point.valueOf(1.5, -1, 1);
216        TestContext.test(new PointCurveClosestTest(subrange, p0, subrange.getPoint(0.697224362268005), typeStr));
217
218        //  Test Curve-LineSeg intersection.
219        p0 = Point.valueOf(0, 0, 0, FOOT);
220        p1 = Point.valueOf(6, -2, 0, METER);
221        line2 = LineSeg.valueOf(p0, p1);
222        TestContext.test(new CCIntersectionTest(subrange, line2, subrange.getPoint(0.837695546828134), typeStr + "-LineSeg"));
223
224        //  Test Curve-Curve intersection.
225        o = Point.valueOf(1, 1, 0, FOOT);
226        a = Parameter.valueOf(10, FOOT);
227        b = Parameter.valueOf(5, FOOT);
228        curve2 = CurveFactory.createEllipse(o, a, b, nhat);
229        TestContext.test(new CCIntersectionTest(subrange, curve2, subrange.getPoint(0.92679405977522), typeStr + "-Ellipse"));
230
231        //  Test Curve-Plane intersection.
232        pln = Plane.getXZ();
233        pln = pln.changeRefPoint(Point.valueOf(0.5, -1.5, 0.5));
234        TestContext.test(new CPlaneIntersectionTest(subrange, pln, subrange.getPoint(0.732050807568877), typeStr));
235
236        //  A subrange curve.
237        typeStr = "3D Curve Through Points";
238        TestContext.info("-- " + typeStr);
239        PointString<Point> str1 = PointString.newInstance();
240        str1.add(Point.valueOf(0, 0, 0), Point.valueOf(1, 1, 0), Point.valueOf(2, 1.5, 0));
241        str1.add(Point.valueOf(3, 1.75, 1), Point.valueOf(4, 2, 2));
242        curve = CurveFactory.fitPoints(3, str1);
243
244        gCrvTest = new GenericSingleCurveTests(curve, typeStr);
245        gCrvTest.isPlanar = false;
246        gCrvTest.isCircular = false;
247        gCrvTest.isLine = false;
248        gCrvTest.isDegenerate = false;
249        gCrvTest.p = Point.valueOf(METER, 2.1375567981007073, 1.5489907738067152, 0.0599427358293912);
250        gCrvTest.pu = Vector.valueOf(METER, 4.2551721869519445, 1.437044936214062, 2.2654614604729866);
251        gCrvTest.puu = Vector.valueOf(METER, -7.346919800970919, -7.414459049425268, 22.37280206421387);
252        gCrvTest.voc = Parameter.valueOf(-5.165250025112367, METER.inverse());
253        TestContext.test(gCrvTest);
254
255        //  Curve Arc Length test.
256        TestContext.test(new ArcLengthTest(curve, Parameter.valueOf(5.504184818759, METER), typeStr));
257        Parameter<Length> L1 = curve.getArcLength(1e-7);
258
259        //  Join with another segment.
260        typeStr = "Joined 3D Nurbs Curves";
261        TestContext.info("-- " + typeStr);
262        str1.clear();
263        str1.add(Point.valueOf(4, 2, 2), Point.valueOf(4, 3, 3), Point.valueOf(4, 3, 2),
264                Point.valueOf(3, 3, 2), Point.valueOf(1, 3, 2));
265        NurbsCurve crv2 = CurveFactory.fitPoints(3, str1);
266        curve = CurveUtils.connectCurves((NurbsCurve)curve, crv2);
267
268        gCrvTest = new GenericSingleCurveTests(curve, typeStr);
269        gCrvTest.isPlanar = false;
270        gCrvTest.isCircular = false;
271        gCrvTest.isLine = false;
272        gCrvTest.isDegenerate = false;
273        gCrvTest.p = Point.valueOf(METER, 4, 2, 2);
274        gCrvTest.pu = Vector.valueOf(METER, -7.431457505076182, 15.951226764720996, 35.11269837220809);
275        gCrvTest.puu = Vector.valueOf(METER, 180.46752981725663, -161.18729397512158, -569.6080810142133);
276        gCrvTest.voc = Parameter.valueOf(2.649490819105782, METER.inverse());
277        TestContext.test(gCrvTest);
278
279        //  Curve Arc Length test.
280        arcL = L1.plus(crv2.getArcLength(1e-7));
281        TestContext.test(new ArcLengthTest(curve, arcL, typeStr));
282
283        //  Approximate a set of noisy points.
284        typeStr = "Curve Approx. 2D Points";
285        TestContext.info("-- " + typeStr);
286        double[] x = {0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7,
287            0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.55,
288            1.6, 1.65, 1.7, 1.75};
289        double[] y = {1.0327, 1.0832, 0.9548, 1.0009, 0.9136, 0.8508, 0.9614, 0.9067, 0.7029,
290            0.7606, 0.7364, 0.6087, 0.5048, 0.4615, 0.4303, 0.3087, 0.0888, 0.0181, 0.0843, -0.0079,
291            -0.2066, -0.3073, -0.4174, -0.4720, -0.5499, -0.5301, -0.5602, -0.6351, -0.6817,
292            -0.7629, -0.8734, -0.9388, -0.9578, -0.9029, -1.0318, -1.0116};
293        str1 = PointString.newInstance();
294        for (int i = 0; i < x.length; ++i) {
295            double xv = x[i];
296            double yv = y[i];
297            Point p = Point.valueOf(xv, yv, METER);
298            str1.add(p);
299        }
300        curve = CurveFactory.approxPoints(3, 6, str1);
301
302        gCrvTest = new GenericSingleCurveTests(curve, typeStr);
303        gCrvTest.isPlanar = true;
304        gCrvTest.isCircular = false;
305        gCrvTest.isLine = false;
306        gCrvTest.isDegenerate = false;
307        gCrvTest.p = Point.valueOf(METER, 0.8163312552679614, 0.14070505144444262);
308        gCrvTest.pu = Vector.valueOf(METER, 1.381875231791502, -2.791859338311323);
309        gCrvTest.puu = Vector.valueOf(METER, 1.2648516559099208, -0.6841004122947583);
310        gCrvTest.voc = Parameter.valueOf(3.8318979168872107, METER.inverse());
311        TestContext.test(gCrvTest);
312
313        //  Curve Arc Length test.
314        TestContext.test(new ArcLengthTest(curve, Parameter.valueOf(2.75309413832606, METER), typeStr));
315
316    }
317
318    public static class GenericSingleCurveTests extends TestCase {
319
320        private final Curve curve;
321        private final String msg;
322        private boolean _planar, _isLine, _isCircular, _deg;
323        private Point _p;
324        private List<Vector<Length>> _ders;
325        Parameter _voc;
326
327        public boolean isPlanar, isLine, isCircular, isDegenerate;
328        public Vector<Length> pu, puu;
329        public Point p;
330        public Parameter voc;
331
332        public GenericSingleCurveTests(Curve crv, String message) {
333            curve = crv;
334            msg = message;
335        }
336
337        @Override
338        public CharSequence getDescription() {
339            return TextBuilder.newInstance().append(msg).append(": Generic");
340        }
341
342        @Override
343        public void execute() {
344            _planar = curve.isPlanar(TOL);
345            _isLine = curve.isLine(TOL);
346            _isCircular = curve.isCircular(TOL);
347            _deg = curve.isDegenerate(TOL);
348            _p = curve.getRealPoint(0.5);
349            _ders = curve.getSDerivatives(0.5, 2);
350            _voc = curve.getVariationOfCurvature(0.5);
351        }
352
353        @Override
354        public void validate() {
355            TestContext.assertEquals("curve.isPlanar()", isPlanar, _planar);
356            TestContext.assertEquals("curve.isLine()", isLine, _isLine);
357            TestContext.assertEquals("curve.isCircular()", isCircular, _isCircular);
358            TestContext.assertEquals("curve.isDegenerate()", isDegenerate, _deg);
359
360            TestContext.assertEquals("curve.getRealPoint(0.5)", true, p.isApproxEqual(_p));
361
362            Vector<Length> pv = Vector.valueOf(p);
363            TestContext.assertEquals("curve.getSDerivatives(0.5,2).get(0)", true, pv.isApproxEqual(_ders.get(0)));
364            TestContext.assertEquals("curve.getSDerivatives(0.5,2).get(1)", true, pu.isApproxEqual(_ders.get(1)));
365            TestContext.assertEquals("curve.getSDerivatives(0.5,2).get(2)", true, puu.isApproxEqual(_ders.get(2)));
366            Parameter vocTol = Parameter.valueOf(Parameter.SQRT_EPS, voc.getUnit());
367            TestContext.assertEquals("curve.getVariationOfCurvature(0.5)", true, voc.isApproxEqual(_voc, vocTol));
368        }
369    }
370
371    public static class PointCurveClosestTest extends TestCase {
372
373        private final Curve curve;
374        private final GeomPoint pnt;
375        private final String msg;
376        private final SubrangePoint expectedSP;
377        private SubrangePoint _pnt;
378
379        public PointCurveClosestTest(Curve crv, GeomPoint point, SubrangePoint expInt, String message) {
380            curve = crv;
381            pnt = point;
382            msg = message;
383            expectedSP = expInt;
384        }
385
386        @Override
387        public CharSequence getDescription() {
388            return TextBuilder.newInstance().append(msg).append(": Closest Point");
389        }
390
391        @Override
392        public void execute() {
393            _pnt = curve.getClosest(pnt, 1e-6);
394        }
395
396        @Override
397        public void validate() {
398            //  Round the parametric positions off to the significant digits used in finding the closest point.
399            double s = _pnt.getParPosition().getValue(0);
400            int place = (int)(log10(s)) - 6;
401            s = MathTools.roundToPlace(s, place);
402
403            double expS = expectedSP.getParPosition().getValue(0);
404            place = (int)(log10(expS)) - 6;
405            expS = MathTools.roundToPlace(expS, place);
406
407            TestContext.assertEquals("curve.getClosest(pnt, 1e-6)", true, MathTools.isApproxEqual(s, expS));
408        }
409    }
410
411    public static class CCIntersectionTest extends TestCase {
412
413        private final Curve curve1;
414        private final Curve curve2;
415        private final String msg;
416        private final SubrangePoint expectedSP;
417        private SubrangePoint _intPnt;
418
419        public CCIntersectionTest(Curve crv1, Curve crv2, SubrangePoint expInt, String message) {
420            curve1 = crv1;
421            curve2 = crv2;
422            msg = message;
423            expectedSP = expInt;
424        }
425
426        @Override
427        public CharSequence getDescription() {
428            return TextBuilder.newInstance().append(msg).append(": Intersect");
429        }
430
431        @Override
432        public void execute() {
433            _intPnt = ((PointString<SubrangePoint>)curve1.intersect(curve2, TOL).getFirst()).getFirst();
434        }
435
436        @Override
437        public void validate() {
438            TestContext.assertEquals("curve1.intersect(curve2)", true, expectedSP.isApproxEqual(_intPnt, TOL));
439        }
440    }
441
442    public static class CPlaneIntersectionTest extends TestCase {
443
444        private final Curve curve;
445        private final GeomPlane plane;
446        private final String msg;
447        private final SubrangePoint expectedSP;
448        private SubrangePoint _intPnt;
449
450        public CPlaneIntersectionTest(Curve crv, GeomPlane pln, SubrangePoint expInt, String message) {
451            curve = crv;
452            plane = pln;
453            msg = message;
454            expectedSP = expInt;
455        }
456
457        @Override
458        public CharSequence getDescription() {
459            return TextBuilder.newInstance().append(msg).append("-Plane: Intersect");
460        }
461
462        @Override
463        public void execute() {
464            PointString<SubrangePoint> str = curve.intersect(plane, 1e-6);
465            _intPnt = str.getFirst();
466        }
467
468        @Override
469        public void validate() {
470            //  Round the parametric positions off to the significant digits used in finding the closest point.
471            double s = _intPnt.getParPosition().getValue(0);
472            int place = (int)(log10(s)) - 6;
473            s = MathTools.roundToPlace(s, place);
474
475            double expS = expectedSP.getParPosition().getValue(0);
476            place = (int)(log10(expS)) - 6;
477            expS = MathTools.roundToPlace(expS, place);
478
479            TestContext.assertEquals("curve.intersect(plane, 1e-6)", true, MathTools.isApproxEqual(s, expS));
480        }
481    }
482
483    public static class ArcLengthTest extends TestCase {
484
485        private final Curve curve;
486        private final Parameter<Length> expectedL;
487        private final String msg;
488        private Parameter<Length> _length;
489
490        public ArcLengthTest(Curve crv, Parameter<Length> expL, String message) {
491            curve = crv;
492            msg = message;
493            expectedL = expL;
494        }
495
496        @Override
497        public CharSequence getDescription() {
498            return TextBuilder.newInstance().append(msg).append(": Arc Length");
499        }
500
501        @Override
502        public void execute() {
503            _length = curve.getArcLength(1e-6);
504        }
505
506        @Override
507        public void validate() {
508            //  Round the parametric positions off to the significant digits used in finding the closest point.            
509            Parameter<Length> tol = expectedL.times(1e-6);
510
511            TestContext.assertEquals("curve.getArcLength(1e-6)", true, _length.isApproxEqual(expectedL, tol));
512        }
513    }
514
515    public static class EnclosedAreaTest extends TestCase {
516
517        private final Curve curve;
518        private final Parameter<Area> expectedA;
519        private final String msg;
520        private Parameter<Area> _area;
521
522        public EnclosedAreaTest(Curve crv, Parameter<Area> expA, String message) {
523            curve = crv;
524            msg = message;
525            expectedA = expA;
526        }
527
528        @Override
529        public CharSequence getDescription() {
530            return TextBuilder.newInstance().append(msg).append(": Enclosed Area");
531        }
532
533        @Override
534        public void execute() {
535            _area = curve.getEnclosedArea(curve.getRealPoint(0), 1e-6);
536        }
537
538        @Override
539        public void validate() {
540            //  Round the parametric positions off to the significant digits used in finding the closest point.            
541            Parameter<Area> tol = expectedA.times(1e-6).abs();
542
543            TestContext.assertEquals("curve.getEnclosedArea(curve.getPoint(0),1e-6)",
544                    true, _area.isApproxEqual(expectedA, tol));
545        }
546    }
547
548}