public PeriodicDrawableBox(LocalCS cs,
                                       Geometry.IRandomAccessRange <Geometry.Point> points,
                                       Geometry.Unit unit)
                : base(true)
            {
                int count = points.Count + 1;

                xs_orig    = new float[count];
                points_rel = new PointF[count];

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

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

                    // always relative to p0
                    double distNorm = Geometry.NormalizedAngleUnsigned(points[i][0] - points[0][0], unit); // [0, 2pi] - min is always lesser than max

                    double x_curr = points[0][0] + distNorm;                                               // always relative to p0
                    points_rel[i] = new PointF(cs.ConvertX(x_curr),
                                               cs.ConvertY(points[i][1]));
                }

                // close
                xs_orig[points.Count]    = xs_orig[0];
                points_rel[points.Count] = points_rel[0];
            }
            public PeriodicDrawablePolygon(LocalCS cs,
                                           Geometry.IRandomAccessRange <Geometry.Point> outer,
                                           IEnumerable <Geometry.IRandomAccessRange <Geometry.Point> > inners,
                                           Geometry.Box box,
                                           Geometry.Unit unit)
            {
                this.outer = new PeriodicDrawableRange(cs, outer, box, unit);

                minf     = this.outer.minf;
                maxf     = this.outer.maxf;
                periodf  = this.outer.periodf;
                box_minf = this.outer.box_minf;
                box_maxf = this.outer.box_maxf;

                this.inners = new List <PeriodicDrawableRange>();
                int i = 0;

                foreach (var inner in inners)
                {
                    this.inners.Add(new PeriodicDrawableRange(cs, inner, box, unit));

                    // expand relative box X
                    if (this.inners[i].minf < minf)
                    {
                        minf = this.inners[i].minf;
                    }
                    if (this.inners[i].maxf > maxf)
                    {
                        maxf = this.inners[i].maxf;
                    }
                }
            }
Exemple #3
0
        // For GraphicalWatch
        public static bool Draw(Graphics graphics,
                                IDrawable drawable, Geometry.Traits traits,
                                Settings settings, Colors colors)
        {
            if (drawable == null)
            {
                return(false);
            }

            if (traits != null && traits.CoordinateSystem == Geometry.CoordinateSystem.SphericalPolar)
            {
                throw new Exception("This coordinate system is not yet supported.");
            }

            if (settings.color == Color.Empty)
            {
                settings.color = DefaultColor(drawable, colors);
            }

            Geometry.Box aabb = drawable.Aabb(traits, true);
            if (aabb.IsValid())
            {
                Geometry.Unit unit = (traits != null) ? traits.Unit : Geometry.Unit.None;
                bool          fill = (traits == null);
                Drawer.DrawAxes(graphics, aabb, unit, colors, fill);
                drawable.Draw(aabb, graphics, settings, traits);
            }
            return(true);
        }
Exemple #4
0
        public static Geometry.Interval RelativeEnvelopeLon(NSphere nsphere, Geometry.Unit unit)
        {
            double cx = nsphere.Center[0];
            double r  = Math.Abs(nsphere.Radius);

            // NOTE: The radius is always in the units of the CS which is technically wrong
            return(new Geometry.Interval(cx - r, cx + r));
        }
Exemple #5
0
 public static Geometry.Interval RelativeEnvelopeLon(Geometry.IRandomAccessRange <Geometry.Point> outer,
                                                     IEnumerable <Geometry.IRandomAccessRange <Geometry.Point> > inners,
                                                     Geometry.Unit unit)
 {
     Geometry.Interval result = RelativeEnvelopeLon(outer, true, unit);
     foreach (var inner in inners)
     {
         result.Expand(RelativeEnvelopeLon(inner, true, unit));
     }
     return(result);
 }
Exemple #6
0
        public void DrawPeriodic(LocalCS cs,
                                 Geometry.Box box, Geometry.Interval interval, Geometry.Unit unit,
                                 IPeriodicDrawable drawer,
                                 bool fill, bool drawDirs, bool drawDots)
        {
            double twoPi    = Geometry.FullAngle(unit);
            float  periodf  = cs.ConvertDimensionX(twoPi);
            float  box_minf = cs.ConvertX(box.Min[0]);
            float  box_maxf = cs.ConvertX(box.Max[0]);

            float minf = cs.ConvertX(interval.Min);
            float maxf = cs.ConvertX(interval.Max);

            if (maxf >= box_minf && minf <= box_maxf)
            {
                drawer.DrawOne(this, 0, fill, drawDirs, drawDots);
            }

            // west
            float minf_i       = minf;
            float maxf_i       = maxf;
            float translationf = 0;

            while (maxf_i >= box_minf &&
                   Util.Assign(ref maxf_i, maxf_i - periodf))
            {
                translationf -= periodf;
                minf_i       -= periodf;
                //maxf_i -= periodf; // subtracted above
                if (maxf_i >= box_minf && minf_i <= box_maxf)
                {
                    drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
                }
            }
            // east
            minf_i       = minf;
            maxf_i       = maxf;
            translationf = 0;
            while (minf_i <= box_maxf &&
                   Util.Assign(ref minf_i, minf_i + periodf))
            {
                translationf += periodf;
                //minf_i += periodf; // added above
                maxf_i += periodf;
                if (maxf_i >= box_minf && minf_i <= box_maxf)
                {
                    drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
                }
            }
        }
            public PeriodicDrawablePolygon(LocalCS cs,
                                           Geometry.IRandomAccessRange <Geometry.Point> outer,
                                           IEnumerable <Geometry.IRandomAccessRange <Geometry.Point> > inners,
                                           Geometry.Unit unit,
                                           bool densify)
            {
                this.outer = new PeriodicDrawableRange(cs, outer, true, unit, densify);

                this.inners = new List <PeriodicDrawableRange>();
                foreach (var inner in inners)
                {
                    PeriodicDrawableRange pd = new PeriodicDrawableRange(cs, inner, true, unit, densify);
                    this.inners.Add(pd);
                }
            }
        public void DrawPeriodic(LocalCS cs,
                                 Geometry.Box box, Geometry.Interval interval, Geometry.Unit unit,
                                 IPeriodicDrawable drawer,
                                 bool fill, bool drawDirs, bool drawDots)
        {
            double pi       = Geometry.HalfAngle(unit);
            float  periodf  = cs.ConvertDimensionX(2 * pi);
            float  box_minf = cs.ConvertX(box.Min[0]);
            float  box_maxf = cs.ConvertX(box.Max[0]);

            float minf = cs.ConvertX(interval.Min);
            float maxf = cs.ConvertX(interval.Max);

            if (maxf >= box_minf && minf <= box_maxf)
            {
                drawer.DrawOne(this, 0, fill, drawDirs, drawDots);
            }

            // west
            float minf_i       = minf;
            float maxf_i       = maxf;
            float translationf = 0;

            while (maxf_i >= box_minf)
            {
                translationf -= periodf;
                minf_i       -= periodf;
                maxf_i       -= periodf;
                if (maxf_i >= box_minf && minf_i <= box_maxf)
                {
                    drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
                }
            }
            // east
            minf_i       = minf;
            maxf_i       = maxf;
            translationf = 0;
            while (minf_i <= box_maxf)
            {
                translationf += periodf;
                minf_i       += periodf;
                maxf_i       += periodf;
                if (maxf_i >= box_minf && minf_i <= box_maxf)
                {
                    drawer.DrawOne(this, translationf, fill, drawDirs, drawDots);
                }
            }
        }
Exemple #9
0
        // For GeometryWatch and PlotWatch
        static Geometry.Box Draw(Graphics graphics, bool ignoreTraits,
                                 IDrawable[] drawables, Geometry.Traits[] traits,
                                 Settings[] settings, Colors colors, ZoomBox zoomBox)
        {
            if (drawables.Length != traits.Length || drawables.Length != settings.Length)
            {
                throw new ArgumentOutOfRangeException("drawables.Length, traits.Length, settings.Length");
            }

            Geometry.Box box = new Geometry.Box();
            Geometry.AssignInverse(box);

            int drawnCount = 0;
            int count      = drawables.Length;

            bool[] drawnFlags = new bool[count];

            HashSet <int> dimensions = new HashSet <int>();
            HashSet <Geometry.CoordinateSystem> csystems = new HashSet <Geometry.CoordinateSystem>();
            HashSet <Geometry.Unit>             units    = new HashSet <Geometry.Unit>();

            for (int i = 0; i < count; ++i)
            {
                if (ignoreTraits)
                {
                    traits[i] = null;
                }

                if (drawables[i] != null)
                {
                    if (traits[i] != null)
                    {
                        dimensions.Add(traits[i].Dimension);
                        csystems.Add(traits[i].CoordinateSystem);
                        units.Add(traits[i].Unit);
                    }

                    Geometry.Box aabb = drawables[i].Aabb(traits[i], false);
                    Geometry.Expand(box, aabb);

                    ++drawnCount;
                    drawnFlags[i] = aabb.IsValid();
                }
            }

            if (drawnCount > 0)
            {
                if (csystems.Count > 1)
                {
                    throw new Exception("Multiple coordinate systems detected.");
                }
                if (csystems.Count > 0 && csystems.First() == Geometry.CoordinateSystem.SphericalPolar)
                {
                    throw new Exception("This coordinate system is not yet supported.");
                }
                if (units.Count > 1)
                {
                    throw new Exception("Multiple units detected.");
                }

                Geometry.Traits commonTraits = (dimensions.Count > 0 && csystems.Count > 0 && units.Count > 0)
                                                ? new Geometry.Traits(dimensions.Max(), csystems.First(), units.First())
                                                : null;

                bool fill = (commonTraits == null);

                // Fragment of the box
                if (box.IsValid() && zoomBox.IsZoomed())
                {
                    // window coordinates of the box
                    LocalCS cs = new LocalCS(box, graphics, fill);
                    box = cs.BoxFromZoomBox(zoomBox);

                    // TODO: With current approach changing the original box (resize, enlarge, etc.)
                    // may produce wierd results because zoomBox is relative to the original box.
                }

                // Axes
                if (box.IsValid())
                {
                    Geometry.Unit unit = commonTraits != null ? commonTraits.Unit : Geometry.Unit.None;
                    Drawer.DrawAxes(graphics, box, unit, colors, fill);
                }

                // Drawables
                for (int i = 0; i < count; ++i)
                {
                    if (drawables[i] != null && drawnFlags[i] == true)
                    {
                        drawables[i].Draw(box, graphics, settings[i], commonTraits);
                    }
                }

                // Scales
                if (box.IsValid())
                {
                    Drawer.DrawScales(graphics, box, colors, fill);
                }

                // CS info
                if (commonTraits != null)
                {
                    SolidBrush brush = new SolidBrush(colors.TextColor);
                    Font       font  = new Font(new FontFamily(System.Drawing.Text.GenericFontFamilies.SansSerif), 10);
                    string     str   = Geometry.Name(csystems.First());
                    if (units.First() != Geometry.Unit.None)
                    {
                        str += '[' + Geometry.Name(units.First()) + ']';
                    }
                    graphics.DrawString(str, font, brush, 0, 0);
                }

                return(box);
            }

            return(null);
        }
 public PeriodicDrawableNSphere(LocalCS cs, Geometry.NSphere nsphere, Geometry.Unit unit)
 {
     // NOTE: The radius is always in the units of the CS which is technically wrong
     c_rel = cs.Convert(nsphere.Center);
     r     = cs.ConvertDimensionX(nsphere.Radius);
 }
Exemple #11
0
        public static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit unit, Colors colors, bool fill)
        {
            if (!box.IsValid())
            {
                return(false);
            }

            LocalCS cs = new LocalCS(box, graphics, fill);

            // NOTE: the coordinates limit of MS GDI+ is 1073741951 so below
            //   avoid passing such coordinates. But instead of checking this
            //   value or similar one check whether or not an axis is range
            //   of an image.

            // Axes
            float h         = graphics.VisibleClipBounds.Height;
            float w         = graphics.VisibleClipBounds.Width;
            Pen   prime_pen = new Pen(colors.AxisColor, 1);

            if (unit == Geometry.Unit.None)
            {
                // Y axis
                float x0 = cs.ConvertX(0.0);
                if (0 <= x0 && x0 <= w)
                {
                    graphics.DrawLine(prime_pen, x0, 0, x0, h);
                }

                // X axis
                float y0 = cs.ConvertY(0.0);
                if (0 <= y0 && y0 <= h)
                {
                    graphics.DrawLine(prime_pen, 0, y0, w, y0);
                }
            }
            else
            {
                Pen anti_pen = new Pen(colors.AxisColor, 1);
                anti_pen.DashStyle   = DashStyle.Custom;
                anti_pen.DashPattern = new float[] { 5, 5 };
                double pi             = Geometry.StraightAngle(unit);
                double anti_mer       = Geometry.NearestAntimeridian(box.Min[0], -1, unit);
                double prime_mer      = anti_mer + pi;
                double next_anti_mer  = anti_mer + 2 * pi;
                double next_prime_mer = prime_mer + 2 * pi;

                float anti_mer_f     = cs.ConvertX(anti_mer);
                float anti_mer_step  = cs.ConvertX(next_anti_mer) - anti_mer_f;
                float prime_mer_f    = cs.ConvertX(prime_mer);
                float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f;

                // Antimeridians
                while (anti_mer_f <= w
                       // NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop
                       && Util.Assign(ref anti_mer_f, anti_mer_f + anti_mer_step))
                {
                    if (anti_mer_f >= 0)
                    {
                        graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h);
                    }
                }
                // Prime meridians
                bool primeMeridiansDrawn = false;
                while (prime_mer_f <= w
                       // NOTE: For bug coordinates anti_mer_step may be 0 which results in infinite loop
                       && Util.Assign(ref prime_mer_f, prime_mer_f += prime_mer_step))
                {
                    if (prime_mer_f >= 0)
                    {
                        graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h);
                        primeMeridiansDrawn = true;
                    }
                }
                // Prime meridian
                float p = cs.ConvertX(0.0);
                if (!primeMeridiansDrawn &&
                    0 <= p && p <= w)
                {
                    graphics.DrawLine(prime_pen, p, 0, p, h);
                }
                // Equator
                float e = cs.ConvertY(0.0);
                if (0 <= e && e <= h)
                {
                    graphics.DrawLine(prime_pen, 0, e, w, e);
                }
                // North pole
                float n = cs.ConvertY(pi / 2);
                if (0 <= n && n <= h)
                {
                    graphics.DrawLine(anti_pen, 0, n, w, n);
                }
                // South pole
                float s = cs.ConvertY(-pi / 2);
                if (0 <= s && s <= h)
                {
                    graphics.DrawLine(anti_pen, 0, s, w, s);
                }
            }

            return(true);
        }
            public static bool IsAntipodal(double distNorm, Geometry.Unit unit)
            {
                double pi = Geometry.HalfAngle(unit);

                return(Math.Abs(Math.Abs(distNorm) - pi) < double.Epsilon * pi);
            }
            private static PointF[] DensifyAndConvert(LocalCS cs, Geometry.Point p0, Geometry.Point p1, double length, Geometry.Unit unit)
            {
                double distNorm        = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit);
                bool   intersPole      = IsAntipodal(distNorm, unit);
                double halfPi          = Geometry.HalfAngle(unit) / 2;
                double poleLat         = p1[1] - p0[1] >= 0 ? halfPi : -halfPi;
                int    intersPoleIndex = -1;

                Geometry.Point[] densPoints = Geometry.SphericalDensify(p0, p1, length, unit);
                PointF[]         result     = new PointF[densPoints.Length + (intersPole ? 2 : 0)];
                int k = 0;

                for (int j = 0; j < densPoints.Length; ++j, ++k)
                {
                    double densDistNorm = Geometry.NormalizedAngleSigned(densPoints[j][0] - p0[0], unit);
                    densPoints[j][0] = p0[0] + densDistNorm;

                    if (intersPole &&
                        intersPoleIndex == -1 &&
                        Math.Abs(densDistNorm) > halfPi)
                    {
                        intersPoleIndex = j;
                        Geometry.Point p     = j == 0 ? p0 : densPoints[j - 1];
                        float          poleF = cs.ConvertY(poleLat);
                        result[k++] = new PointF(cs.ConvertX(p[0]), poleF);
                        result[k++] = new PointF(cs.ConvertX(densPoints[j][0]), poleF);
                    }

                    result[k] = cs.Convert(densPoints[j]);
                }

                // last segment
                if (intersPole && intersPoleIndex == -1)
                {
                    int j = densPoints.Length;
                    intersPoleIndex = j;
                    float poleF = cs.ConvertY(poleLat);
                    result[j]     = new PointF(cs.ConvertX(densPoints[j - 1][0]), poleF);
                    result[j + 1] = new PointF(cs.ConvertX(p1[0]), poleF);
                }

                return(result);
            }
            public PeriodicDrawableRange(LocalCS cs,
                                         Geometry.IRandomAccessRange <Geometry.Point> points,
                                         bool closed,
                                         Geometry.Unit unit,
                                         bool densify)
            {
                this.closed       = closed;
                this.containsPole = ContainsPole.No;

                if (points.Count < 2)
                {
                    return;
                }

                // approx. length of densified segments

                /*double densLength = Math.Min(cs.InverseConvertDimensionX(20),
                 *                           cs.InverseConvertDimensionY(20));*/
                double densLength = Geometry.FromDegree(5, unit);

                int count = points.Count + (closed ? 1 : 0);

                xs_orig    = new float[count];
                points_rel = new PointF[count];
                if (densify)
                {
                    dens_points_rel = new PointF[points.Count][];
                }

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

                Geometry.Point p0 = points[0].Clone();
                for (int i = 1; i < count; ++i)
                {
                    Geometry.Point p1 = points[i % points.Count].Clone();

                    xs_orig[i] = cs.ConvertX(p1[0]);

                    double distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit); // [-pi, pi]
                    p1[0]         = p0[0] + distNorm;
                    points_rel[i] = cs.Convert(p1);

                    if (dens_points_rel != null)
                    {
                        dens_points_rel[i - 1] = DensifyAndConvert(cs, p0, p1, densLength, unit);
                    }

                    p0 = p1;
                }

                if (closed && Math.Abs(points_rel[0].X - points_rel[points.Count].X) > 0.1)
                {
                    // Check which pole
                    double area = 0;
                    p0 = points[0].Clone();
                    for (int i = 1; i < count; ++i)
                    {
                        Geometry.Point p1       = points[i % points.Count].Clone();
                        double         distNorm = Geometry.NormalizedAngleSigned(p1[0] - p0[0], unit); // [-pi, pi]
                        p1[0] = p0[0] + distNorm;
                        area += Geometry.SphericalTrapezoidArea(p0, p1, unit);
                        p0    = p1;
                    }

                    int areaSign = Math.Sign(area);
                    int dirSign  = Math.Sign(points_rel[points.Count].X - points_rel[0].X);
                    this.containsPole = (areaSign * dirSign >= 0)
                                      ? ContainsPole.North
                                      : ContainsPole.South;
                }
            }
        public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit, bool drawDots)
        {
            PointF p = cs.Convert(point);

            DrawPoint(p);

            double pi2 = 2 * Geometry.HalfAngle(unit);
            Pen    pen = drawDots ? this.penDot : this.pen;
            // draw points on the west
            double x_tmp = point[0] - pi2;

            while (x_tmp >= box.Min[0])
            {
                p.X = cs.ConvertX(x_tmp);
                DrawPoint(p, pen);
                x_tmp -= pi2;
            }
            // draw points on the east
            x_tmp = point[0] + pi2;
            while (x_tmp <= box.Max[0])
            {
                p.X = cs.ConvertX(x_tmp);
                DrawPoint(p, pen);
                x_tmp += pi2;
            }
        }
Exemple #16
0
        // -------------------------------------------------
        // Util
        // -------------------------------------------------

        private static Geometry.Interval RelativeEnvelopeLon(Geometry.IRandomAccessRange <Geometry.Point> points, bool closed, Geometry.Unit unit)
        {
            Geometry.Interval result = null;

            if (points.Count < 1)
            {
                result = new Geometry.Interval();
                Geometry.AssignInverse(result);
                return(result);
            }

            double x0 = points[0][0];

            result = new Geometry.Interval(x0);

            int count = points.Count + (closed ? 1 : 0);

            for (int ii = 1; ii < count; ++ii)
            {
                int    i        = ii % points.Count;
                double xi       = points[i][0];
                double distNorm = Geometry.NormalizedAngleSigned(xi - x0, unit); // [-pi, pi]
                double x1       = x0 + distNorm;
                result.Expand(x1);
                x0 = x1;
            }
            return(result);
        }
        public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit)
        {
            PointF p = cs.Convert(point);

            DrawPoint(p);

            Pen penDot = (Pen)pen.Clone();

            penDot.DashStyle = DashStyle.Dot;

            double pi2 = 2 * Geometry.HalfAngle(unit);
            // draw points on the west
            double x_tmp = point[0] - pi2;

            while (x_tmp >= box.Min[0])
            {
                p.X = cs.ConvertX(x_tmp);
                DrawPoint(p, penDot);
                x_tmp -= pi2;
            }
            // draw points on the east
            x_tmp = point[0] + pi2;
            while (x_tmp <= box.Max[0])
            {
                p.X = cs.ConvertX(x_tmp);
                DrawPoint(p, penDot);
                x_tmp += pi2;
            }
        }
            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]);
            }
            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 static bool DrawAxes(Graphics graphics, Geometry.Box box, Geometry.Unit unit, Colors colors, bool fill)
        {
            if (!box.IsValid())
            {
                return(false);
            }

            LocalCS cs = new LocalCS(box, graphics, fill);
            //Geometry.Box viewBox = cs.ViewBox();

            // Axes
            float h         = graphics.VisibleClipBounds.Height;
            float w         = graphics.VisibleClipBounds.Width;
            Pen   prime_pen = new Pen(colors.AxisColor, 1);

            if (unit == Geometry.Unit.None)
            {
                // Y axis
                //if (Geometry.IntersectsX(viewBox, 0.0))
                {
                    float x0 = cs.ConvertX(0.0);
                    graphics.DrawLine(prime_pen, x0, 0, x0, h);
                }
                // X axis
                //if (Geometry.IntersectsY(viewBox, 0.0))
                {
                    float y0 = cs.ConvertY(0.0);
                    graphics.DrawLine(prime_pen, 0, y0, w, y0);
                }
            }
            else
            {
                Pen anti_pen = new Pen(colors.AxisColor, 1);
                anti_pen.DashStyle   = DashStyle.Custom;
                anti_pen.DashPattern = new float[] { 5, 5 };
                double pi             = Geometry.HalfAngle(unit);
                double anti_mer       = Geometry.NearestAntimeridian(box.Min[0], -1, unit);
                double prime_mer      = anti_mer + pi;
                double next_anti_mer  = anti_mer + 2 * pi;
                double next_prime_mer = prime_mer + 2 * pi;

                float anti_mer_f     = cs.ConvertX(anti_mer);
                float anti_mer_step  = cs.ConvertX(next_anti_mer) - anti_mer_f;
                float prime_mer_f    = cs.ConvertX(prime_mer);
                float prime_mer_step = cs.ConvertX(next_prime_mer) - prime_mer_f;

                // Antimeridians
                for (; anti_mer_f <= w; anti_mer_f += anti_mer_step)
                {
                    if (anti_mer_f >= 0)
                    {
                        graphics.DrawLine(anti_pen, anti_mer_f, 0, anti_mer_f, h);
                    }
                }
                // Prime meridians
                for (; prime_mer_f <= w; prime_mer_f += prime_mer_step)
                {
                    if (prime_mer_f >= 0)
                    {
                        graphics.DrawLine(prime_pen, prime_mer_f, 0, prime_mer_f, h);
                    }
                }
                // Equator
                float e = cs.ConvertY(0.0);
                if (0 <= e && e <= h)
                {
                    graphics.DrawLine(prime_pen, 0, e, w, e);
                }
                // North pole
                float n = cs.ConvertY(pi / 2);
                if (0 <= n && n <= h)
                {
                    graphics.DrawLine(anti_pen, 0, n, w, n);
                }
                // South pole
                float s = cs.ConvertY(-pi / 2);
                if (0 <= s && s <= h)
                {
                    graphics.DrawLine(anti_pen, 0, s, w, s);
                }
            }

            return(true);
        }
Exemple #22
0
        public void DrawPeriodicPoint(LocalCS cs, Geometry.Point point, Geometry.Box box, Geometry.Unit unit, bool drawDots)
        {
            PointF p = cs.Convert(point);

            DrawPoint(p);

            double twoPi = Geometry.FullAngle(unit);
            Pen    pen   = drawDots ? this.penDot : this.pen;

            // NOTE: Use AssignChanged becasue for big coordinates subtracting/adding
            //   twoPi doesn't change the value of x_tmp which causes infinite loop

            float  x            = Math.Min(Math.Max(p.X, 0.0f), cs.Width);
            double nPeriodsWest = (point[0] - box.Min[0]) / twoPi;
            float  pixelsWest   = x;
            double nPeriodsEast = (box.Max[0] - point[0]) / twoPi;
            float  pixelsEast   = cs.Width - x;

            if (nPeriodsWest <= pixelsWest / 5)
            {
                // draw points on the west
                double x_tmp = point[0];
                while (Util.Assign(ref x_tmp, x_tmp - twoPi) &&
                       x_tmp >= box.Min[0])
                {
                    p.X = cs.ConvertX(x_tmp);
                    DrawPoint(p, pen);
                }
            }

            if (nPeriodsEast <= pixelsEast / 5)
            {
                // draw points on the east
                double x_tmp = point[0];
                while (Util.Assign(ref x_tmp, x_tmp + twoPi) &&
                       x_tmp <= box.Max[0])
                {
                    p.X = cs.ConvertX(x_tmp);
                    DrawPoint(p, pen);
                }
            }
        }