public PeriodicDrawableNSphere(LocalCS cs, Geometry.NSphere nsphere, Geometry.Box box, Geometry.Unit unit)
            {
                double pi = Geometry.HalfAngle(unit);

                periodf = cs.ConvertDimension(2 * pi);

                c_rel = cs.Convert(nsphere.Center);
                r     = cs.ConvertDimension(nsphere.Radius);

                minf = c_rel.X - r;
                maxf = c_rel.X + r;

                box_minf = cs.ConvertX(box.Min[0]);
                box_maxf = cs.ConvertX(box.Max[0]);
            }
            public PeriodicDrawableRange(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, Geometry.Box box, Geometry.Unit unit)
            {
                if (points.Count < 2)
                {
                    return;
                }

                double pi = Geometry.HalfAngle(unit);

                periodf = cs.ConvertDimension(2 * pi);

                xs_orig    = new float[points.Count];
                points_rel = new PointF[points.Count];

                xs_orig[0]    = cs.ConvertX(points[0][0]);
                points_rel[0] = cs.Convert(points[0]);

                minf = points_rel[0].X;
                maxf = points_rel[0].X;

                double x0      = Geometry.NormalizedAngle(points[0][0], unit);
                double x0_prev = points[0][0];

                for (int i = 1; i < points.Count; ++i)
                {
                    xs_orig[i] = cs.ConvertX(points[i][0]);

                    double x1       = Geometry.NormalizedAngle(points[i][0], unit);
                    double dist     = x1 - x0;                              // [-2pi, 2pi]
                    double distNorm = Geometry.NormalizedAngle(dist, unit); // [-pi, pi]

                    double x0_curr = x0_prev + distNorm;
                    points_rel[i] = new PointF(cs.ConvertX(x0_curr),
                                               cs.ConvertY(points[i][1]));

                    // expand relative box X
                    if (points_rel[i].X < minf)
                    {
                        minf = points_rel[i].X;
                    }
                    if (points_rel[i].X > maxf)
                    {
                        maxf = points_rel[i].X;
                    }

                    x0_prev = x0_curr;
                    x0      = x1;
                }

                box_minf = cs.ConvertX(box.Min[0]);
                box_maxf = cs.ConvertX(box.Max[0]);
            }
            public PeriodicDrawableBox(LocalCS cs, Geometry.IRandomAccessRange <Geometry.Point> points, Geometry.Box box, Geometry.Unit unit)
            {
                double pi = Geometry.HalfAngle(unit);

                periodf = cs.ConvertDimension(2 * pi);

                xs_orig    = new float[points.Count];
                points_rel = new PointF[points.Count];

                xs_orig[0]    = cs.ConvertX(points[0][0]);
                points_rel[0] = cs.Convert(points[0]);

                minf = points_rel[0].X;
                maxf = points_rel[0].X;

                double x0 = Geometry.NormalizedAngle(points[0][0], unit);

                for (int i = 1; i < points.Count; ++i)
                {
                    xs_orig[i] = cs.ConvertX(points[i][0]);

                    double x1       = Geometry.NormalizedAngle(points[i][0], unit);
                    double dist     = x1 - x0;                              // [-2pi, 2pi]
                    double distNorm = Geometry.NormalizedAngle(dist, unit); // [-pi, pi]
                    while (distNorm < 0)
                    {
                        distNorm += 2 * Geometry.HalfAngle(unit); // [0, 2pi] - min is always lesser than max
                    }
                    double x0_curr = points[0][0] + distNorm;     // always relative to p0
                    points_rel[i] = new PointF(cs.ConvertX(x0_curr),
                                               cs.ConvertY(points[i][1]));

                    // expand relative box X
                    if (points_rel[i].X < minf)
                    {
                        minf = points_rel[i].X;
                    }
                    if (points_rel[i].X > maxf)
                    {
                        maxf = points_rel[i].X;
                    }
                }

                box_minf = cs.ConvertX(box.Min[0]);
                box_maxf = cs.ConvertX(box.Max[0]);
            }