Example #1
0
        /// <summary>
        /// Returns an x-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable x-axis.</returns>
        public Axis SuggestXAxis()
        {
            SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            Axis a = data.SuggestXAxis();

            if (data.Count == 0)
            {
                return(a);
            }

            Point p1;
            Point p2;
            Point p3;
            Point p4;

            if (data.Count < 2)
            {
                p1    = data [0];
                p1.X -= 1.0;
                p2    = data [0];
                p3    = p1;
                p4    = p2;
            }
            else
            {
                p1 = data [0];
                p2 = data [1];
                p3 = data [data.Count - 2];
                p4 = data [data.Count - 1];
            }

            double offset1;
            double offset2;

            if (!Center)
            {
                offset1 = 0.0;
                offset2 = p4.X - p3.X;
            }
            else
            {
                offset1 = (p2.X - p1.X) / 2.0f;
                offset2 = (p4.X - p3.X) / 2.0f;
            }

            a.WorldMin -= offset1;
            a.WorldMax += offset2;

            return(a);
        }
Example #2
0
        /// <summary>
        /// Returns a y-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable y-axis.</returns>
        public Axis SuggestYAxis()
        {
            if (IsStacked)
            {
                double    tmpMax      = 0.0f;
                ArrayList adapterList = new ArrayList();

                HistogramPlot currentPlot = this;
                do
                {
                    adapterList.Add(new SequenceAdapter(
                                        currentPlot.DataSource,
                                        currentPlot.DataMember,
                                        currentPlot.OrdinateData,
                                        currentPlot.AbscissaData)
                                    );
                } while ((currentPlot = currentPlot.stackedTo) != null);

                SequenceAdapter[] adapters = (SequenceAdapter[])adapterList.ToArray(typeof(SequenceAdapter));

                for (int i = 0; i < adapters[0].Count; ++i)
                {
                    double tmpHeight = 0.0f;
                    for (int j = 0; j < adapters.Length; ++j)
                    {
                        tmpHeight += adapters[j][i].Y;
                    }
                    tmpMax = Math.Max(tmpMax, tmpHeight);
                }

                Axis a = new LinearAxis(0.0, tmpMax);
                // TODO make 0.08 a parameter.
                a.IncreaseRange(0.08);
                return(a);
            }
            else
            {
                SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);
                return(data.SuggestYAxis());
            }
        }
Example #3
0
        /// <summary>
        /// Returns an X-axis suitable for use by this plot. The axis will be one that is just long
        /// enough to show all data.
        /// </summary>
        /// <returns>X-axis suitable for use by this plot.</returns>
        public Axis SuggestXAxis()
        {
            SequenceAdapter data =
                new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            if (data.Count < 2)
            {
                return(data.SuggestXAxis());
            }

            // else

            Axis a = data.SuggestXAxis();

            Point p1 = data[0];
            Point p2 = data[1];
            Point p3 = data[data.Count - 2];
            Point p4 = data[data.Count - 1];

            double offset1;
            double offset2;

            if (!centre)
            {
                offset1 = 0;
                offset2 = p4.X - p3.X;
            }
            else
            {
                offset1 = (p2.X - p1.X) / 2;
                offset2 = (p4.X - p3.X) / 2;
            }

            a.WorldMin -= offset1;
            a.WorldMax += offset2;

            return(a);
        }
Example #4
0
 /// <summary>
 /// Stack the histogram to another HistogramPlot.
 /// </summary>
 public void StackedTo(HistogramPlot hp)
 {
     SequenceAdapter data = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);
     SequenceAdapter hpData = new SequenceAdapter (hp.DataSource, hp.DataMember, hp.OrdinateData, hp.AbscissaData);
     if (hp != null) {
         IsStacked = true;
         if (hpData.Count != data.Count) {
             throw new XwPlotException ("Can stack HistogramPlot data only with the same number of datapoints");
         }
         for (int i=0; i < data.Count; ++i) {
             if (data[i].X != hpData[i].X) {
                 throw new XwPlotException ("Can stack HistogramPlot data only with the same X coordinates");
             }
             if (hpData[i].Y < 0.0) {
                 throw new XwPlotException ("Can stack HistogramPlot data only with positive Y coordinates");
             }
         }
     }
     stackedTo = hp;
 }
Example #5
0
        /// <summary>
        /// Draws the histogram.
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            double yoff;
            SequenceAdapter data = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);

            ctx.Save ();
            ctx.SetLineWidth (1);

            for (int i=0; i<data.Count; ++i ) {

                // (1) determine the top left hand point of the bar (assuming not centered)
                Point p1 = data[i];
                if (double.IsNaN(p1.X) || double.IsNaN(p1.Y)) {
                    continue;
                }

                // (2) determine the top right hand point of the bar (assuming not centered)
                Point p2 = Point.Zero;;
                if (i+1 != data.Count) {
                    p2 = data[i+1];
                    if (double.IsNaN(p2.X) || double.IsNaN(p2.Y)) {
                        continue;
                    }
                    p2.Y = p1.Y;
                }
                else if (i != 0) {
                    p2 = data[i-1];
                    if (double.IsNaN(p2.X) || double.IsNaN(p2.Y)) {
                        continue;
                    }
                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                }
                else {
                    double offset = 1.0;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                }

                // (3) now account for plots this may be stacked on top of.
                HistogramPlot currentPlot = this;
                yoff = 0.0;
                double yval = 0.0;
                while (currentPlot.IsStacked) {
                    SequenceAdapter stackedToData = new SequenceAdapter (
                        currentPlot.stackedTo.DataSource,
                        currentPlot.stackedTo.DataMember,
                        currentPlot.stackedTo.OrdinateData,
                        currentPlot.stackedTo.AbscissaData );

                    yval += stackedToData[i].Y;
                    yoff = yAxis.WorldToPhysical (yval, false).Y;
                    p1.Y += stackedToData[i].Y;
                    p2.Y += stackedToData[i].Y;
                    currentPlot = currentPlot.stackedTo;
                }

                // (4) now account for centering
                if (Center) {
                    double offset = (p2.X - p1.X) / 2.0;
                    p1.X -= offset;
                    p2.X -= offset;
                }

                // (5) now account for BaseOffset (shift of bar sideways).
                p1.X += BaseOffset;
                p2.X += BaseOffset;

                // (6) now get physical coordinates of top two points.
                Point xPos1 = xAxis.WorldToPhysical (p1.X, false);
                Point yPos1 = yAxis.WorldToPhysical (p1.Y, false);
                Point xPos2 = xAxis.WorldToPhysical (p2.X, false);

                if (IsStacked) {
                    currentPlot = this;
                    while (currentPlot.IsStacked) {
                        currentPlot = currentPlot.stackedTo;
                    }
                    baseWidth = currentPlot.baseWidth;
                }

                double width = xPos2.X - xPos1.X;
                double height;
                if (IsStacked) {
                    height = -yPos1.Y+yoff;
                }
                else {
                    height = -yPos1.Y+yAxis.PhysicalMin.Y;
                }

                double xoff = (1.0 - baseWidth)/2.0*width;
                Rectangle bar = new Rectangle (xPos1.X+xoff, yPos1.Y, width-2*xoff, height);

                ctx.Rectangle (bar);
                if (Filled) {
                    if (bar.Height != 0 && bar.Width != 0) {
                        if (FillGradient != null) {
                            // Scale FillGradient to bar rectangle
                            double sX = bar.X + fillGradient.StartPoint.X * bar.Width;
                            double sY = bar.Y + fillGradient.StartPoint.Y * bar.Height;
                            double eX = bar.X + fillGradient.EndPoint.X * bar.Width;
                            double eY = bar.Y + fillGradient.EndPoint.Y * bar.Height;
                            LinearGradient g = new LinearGradient (sX, sY, eX, eY);
                            g.AddColorStop (0, FillGradient.StartColor);
                            g.AddColorStop (1, FillGradient.EndColor);
                            ctx.Pattern = g;
                        } else {
                            ctx.SetColor (FillColor);
                        }
                        ctx.FillPreserve ();
                    }
                }
                ctx.SetColor (BorderColor);
                ctx.Stroke ();
            }
            ctx.Restore ();
        }
Example #6
0
        /// <summary>
        /// Draws the point plot using the Drawing Context and x and y axes supplied
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public virtual void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data_ = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData );

            double leftCutoff_ = xAxis.PhysicalMin.X - marker.Size;
            double rightCutoff_ = xAxis.PhysicalMax.X + marker.Size;

            ctx.Save ();
            ctx.SetColor (marker.LineColor);
            ctx.SetLineWidth (marker.LineWidth);

            for (int i=0; i<data_.Count; ++i) {
                if (!Double.IsNaN(data_[i].X) && !Double.IsNaN(data_[i].Y)) {
                    Point xPos = xAxis.WorldToPhysical (data_[i].X, false);
                    if (xPos.X < leftCutoff_ || rightCutoff_ < xPos.X) {
                        continue;
                    }

                    Point yPos = yAxis.WorldToPhysical (data_[i].Y, false);
                    marker.Draw (ctx, xPos.X, yPos.Y);
                    if (marker.DropLine) {
                        Point yMin = new Point (data_[i].X, Math.Max (0.0, yAxis.Axis.WorldMin));
                        Point yStart = yAxis.WorldToPhysical (yMin.Y, false);
                        ctx.MoveTo (xPos.X, yStart.Y);
                        ctx.LineTo (xPos.X, yPos.Y);
                        ctx.Stroke ();
                    }
                }
            }
            ctx.Restore ();
        }
Example #7
0
        /// <summary>
        /// Draws the step plot using a Drawing Context against the provided x and y axes.
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public virtual void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data =
                new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            double leftCutoff  = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
            double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);

            ctx.Save();
            ctx.SetColor(Color);
            ctx.SetLineWidth(1);

            for (int i = 0; i < data.Count; ++i)
            {
                Point p1 = data[i];
                if (Double.IsNaN(p1.X) || Double.IsNaN(p1.Y))
                {
                    continue;
                }

                Point p2;
                Point p3;
                if (i + 1 != data.Count)
                {
                    p2 = data[i + 1];
                    if (Double.IsNaN(p2.X) || Double.IsNaN(p2.Y))
                    {
                        continue;
                    }
                    p2.Y = p1.Y;
                    p3   = data[i + 1];
                }
                else
                {
                    // Check that we are not dealing with a DataSource of 1 point.
                    // This check is done here so it is only checked on the end
                    // condition and not for every point in the DataSource.
                    if (data.Count > 1)
                    {
                        p2 = data[i - 1];
                    }
                    else
                    {
                        p2 = p1;
                    }
                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3   = p2;
                }

                if (centre)
                {
                    double offset = (p2.X - p1.X) / 2.0;
                    p1.X -= offset;
                    p2.X -= offset;
                    p3.X -= offset;
                }

                Point xPos1 = xAxis.WorldToPhysical(p1.X, false);
                Point yPos1 = yAxis.WorldToPhysical(p1.Y, false);
                Point xPos2 = xAxis.WorldToPhysical(p2.X, false);
                Point yPos2 = yAxis.WorldToPhysical(p2.Y, false);
                Point xPos3 = xAxis.WorldToPhysical(p3.X, false);
                Point yPos3 = yAxis.WorldToPhysical(p3.Y, false);

                // do horizontal clipping here, to speed up
                if ((p1.X < leftCutoff && p2.X < leftCutoff && p3.X < leftCutoff) || (p1.X > rightCutoff && p2.X > rightCutoff && p3.X > rightCutoff))
                {
                    continue;
                }

                if (!this.hideHorizontalSegments)
                {
                    if (scale != 1)
                    {
                        double middle = (xPos2.X + xPos1.X) / 2;
                        double width  = xPos2.X - xPos1.X;
                        width *= this.scale;
                        ctx.MoveTo(middle - width / 2, yPos1.Y);
                        ctx.LineTo(middle + width / 2, yPos2.Y);
                    }
                    else
                    {
                        ctx.MoveTo(xPos1.X, yPos1.Y);
                        ctx.LineTo(xPos2.X, yPos2.Y);
                    }
                    ctx.Stroke();
                }

                if (!this.hideVerticalSegments)
                {
                    ctx.MoveTo(xPos2.X, yPos2.Y);
                    ctx.LineTo(xPos3.X, yPos3.Y);
                    ctx.Stroke();
                }
            }
            ctx.Restore();
        }
Example #8
0
        /// <summary>
        /// Returns a y-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable y-axis.</returns>
        public Axis SuggestYAxis()
        {
            SequenceAdapter dataBottom_ = new SequenceAdapter( DataSource, DataMember, OrdinateDataBottom, AbscissaData );
            SequenceAdapter dataTop_ = new SequenceAdapter( DataSource, DataMember, OrdinateDataTop, AbscissaData );

            Axis axis = dataTop_.SuggestYAxis ();
            axis.LUB(dataBottom_.SuggestYAxis ());
            return axis;
        }
Example #9
0
        /// <summary>
        /// Draws the plot using the Drawing Context and X, Y axes supplied.
        /// </summary>
        public override void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            TextDataAdapter textData =
                new TextDataAdapter(this.DataSource, this.DataMember, this.TextData);

            TextLayout layout = new TextLayout();

            layout.Font = Font;

            ctx.Save();
            ctx.SetColor(Colors.Black);

            for (int i = 0; i < data.Count; ++i)
            {
                try {
                    Point p = data[i];
                    if (!Double.IsNaN(p.X) && !Double.IsNaN(p.Y))
                    {
                        Point xPos = xAxis.WorldToPhysical(p.X, false);
                        Point yPos = yAxis.WorldToPhysical(p.Y, false);
                        // first plot the marker
                        Marker.Draw(ctx, xPos.X, yPos.Y);
                        // then the label
                        if (textData[i] != "")
                        {
                            layout.Text = textData[i];
                            Size size = layout.GetSize();
                            switch (labelTextPosition)
                            {
                            case LabelPositions.Above:
                                p.X = xPos.X - size.Width / 2;
                                p.Y = yPos.Y - size.Height - Marker.Size * 2 / 3;
                                break;

                            case LabelPositions.Below:
                                p.X = xPos.X - size.Width / 2;
                                p.Y = yPos.Y + Marker.Size * 2 / 3;
                                break;

                            case LabelPositions.Left:
                                p.X = xPos.X - size.Width - Marker.Size * 2 / 3;
                                p.Y = yPos.Y - size.Height / 2;
                                break;

                            case LabelPositions.Right:
                                p.X = xPos.X + Marker.Size * 2 / 3;
                                p.Y = yPos.Y - size.Height / 2;
                                break;
                            }
                            ctx.DrawTextLayout(layout, p);
                        }
                    }
                }
                catch {
                    throw new XwPlotException("Error in TextPlot.Draw");
                }
            }
            ctx.Restore();
        }
Example #10
0
        /// <summary>
        /// Draws the line plot using the Context and Physical Axes provided
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        /// <param name="drawShadow">If true draw the shadow for the line. If false, draw line.</param>
        public void DrawLineOrShadow(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow)
        {
            SequenceAdapter data = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);

            ITransform2D t = Transform2D.GetTransformer (xAxis, yAxis);

            int numberPoints = data.Count;

            if (data.Count == 0) {
                return;
            }

            ctx.Save ();
            ctx.SetLineWidth (lineWidth);
            if (lineDash != null) {
                ctx.SetLineDash (0, lineDash);
            }

            if (numberPoints == 1) {
                Point physical = t.Transform (data[0]);

                if (drawShadow) {
                    ctx.SetColor (shadowColor);
                    ctx.MoveTo (physical.X - 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y);
                    ctx.LineTo (physical.X + 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y);
                    ctx.Stroke ();
                }
                else {
                    ctx.SetColor (lineColor);
                    ctx.MoveTo (physical.X-0.5, physical.Y);
                    ctx.LineTo (physical.X+0.5, physical.Y);
                    ctx.Stroke ();
                }
            }
            else {
                // prepare for clipping
                double leftCutoff = xAxis.PhysicalToWorld (xAxis.PhysicalMin, false);
                double rightCutoff = xAxis.PhysicalToWorld (xAxis.PhysicalMax, false);
                if (leftCutoff > rightCutoff) {
                    Utils.Swap (ref leftCutoff, ref rightCutoff);
                }
                if (drawShadow) {
                    // correct cut-offs
                    double shadowCorrection =
                        xAxis.PhysicalToWorld (ShadowOffset, false) - xAxis.PhysicalToWorld (new Point(0,0), false);
                    leftCutoff -= shadowCorrection;
                    rightCutoff -= shadowCorrection;
                }

                for (int i = 1; i < numberPoints; ++i) {
                    // check to see if any values null. If so, then continue.
                    double dx1 = data[i-1].X;
                    double dx2 = data[i].X;
                    double dy1 = data[i-1].Y;
                    double dy2 = data[i].Y;
                    if (Double.IsNaN(dx1) || Double.IsNaN(dy1) || Double.IsNaN(dx2) || Double.IsNaN(dy2)) {
                        continue;
                    }

                    // do horizontal clipping here, to speed up
                    if ((dx1 < leftCutoff && dx2 < leftCutoff) || (rightCutoff < dx1 && rightCutoff < dx2)) {
                        continue;
                    }

                    // else draw line.
                    Point p1 = t.Transform (data[i-1]);
                    Point p2 = t.Transform (data[i]);

                    // when very far zoomed in, points can fall ontop of each other,
                    // and g.DrawLine throws an overflow exception
                    if (p1.Equals(p2)) {
                        continue;
                    }

                    if (drawShadow) {
                        ctx.SetColor (shadowColor);
                        ctx.MoveTo (p1.X + ShadowOffset.X, p1.Y + ShadowOffset.Y);
                        ctx.LineTo (p2.X + ShadowOffset.X, p2.Y + ShadowOffset.Y);
                        ctx.Stroke ();
                    }
                    else {
                        ctx.SetColor (lineColor);
                        ctx.MoveTo (p1.X, p1.Y);
                        ctx.LineTo (p2.X, p2.Y);
                        ctx.Stroke ();
                    }
                }
            }
            ctx.Restore ();
        }
Example #11
0
        /// <summary>
        /// Draws the line plot using the Context and Physical Axes provided
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        /// <param name="drawShadow">If true draw the shadow for the line. If false, draw line.</param>
        public void DrawLineOrShadow(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow)
        {
            SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis);

            int numberPoints = data.Count;

            if (data.Count == 0)
            {
                return;
            }

            ctx.Save();
            ctx.SetLineWidth(lineWidth);
            if (lineDash != null)
            {
                ctx.SetLineDash(0, lineDash);
            }

            if (numberPoints == 1)
            {
                Point physical = t.Transform(data[0]);

                if (drawShadow)
                {
                    ctx.SetColor(shadowColor);
                    ctx.MoveTo(physical.X - 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y);
                    ctx.LineTo(physical.X + 0.5 + ShadowOffset.X, physical.Y + ShadowOffset.Y);
                    ctx.Stroke();
                }
                else
                {
                    ctx.SetColor(lineColor);
                    ctx.MoveTo(physical.X - 0.5, physical.Y);
                    ctx.LineTo(physical.X + 0.5, physical.Y);
                    ctx.Stroke();
                }
            }
            else
            {
                // prepare for clipping
                double leftCutoff  = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
                double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);
                if (leftCutoff > rightCutoff)
                {
                    Utils.Swap(ref leftCutoff, ref rightCutoff);
                }
                if (drawShadow)
                {
                    // correct cut-offs
                    double shadowCorrection =
                        xAxis.PhysicalToWorld(ShadowOffset, false) - xAxis.PhysicalToWorld(new Point(0, 0), false);
                    leftCutoff  -= shadowCorrection;
                    rightCutoff -= shadowCorrection;
                }

                for (int i = 1; i < numberPoints; ++i)
                {
                    // check to see if any values null. If so, then continue.
                    double dx1 = data[i - 1].X;
                    double dx2 = data[i].X;
                    double dy1 = data[i - 1].Y;
                    double dy2 = data[i].Y;
                    if (Double.IsNaN(dx1) || Double.IsNaN(dy1) || Double.IsNaN(dx2) || Double.IsNaN(dy2))
                    {
                        continue;
                    }

                    // do horizontal clipping here, to speed up
                    if ((dx1 < leftCutoff && dx2 < leftCutoff) || (rightCutoff < dx1 && rightCutoff < dx2))
                    {
                        continue;
                    }

                    // else draw line.
                    Point p1 = t.Transform(data[i - 1]);
                    Point p2 = t.Transform(data[i]);

                    // when very far zoomed in, points can fall ontop of each other,
                    // and g.DrawLine throws an overflow exception
                    if (p1.Equals(p2))
                    {
                        continue;
                    }

                    if (drawShadow)
                    {
                        ctx.SetColor(shadowColor);
                        ctx.MoveTo(p1.X + ShadowOffset.X, p1.Y + ShadowOffset.Y);
                        ctx.LineTo(p2.X + ShadowOffset.X, p2.Y + ShadowOffset.Y);
                        ctx.Stroke();
                    }
                    else
                    {
                        ctx.SetColor(lineColor);
                        ctx.MoveTo(p1.X, p1.Y);
                        ctx.LineTo(p2.X, p2.Y);
                        ctx.Stroke();
                    }
                }
            }
            ctx.Restore();
        }
Example #12
0
        /// <summary>
        /// Draws the histogram.
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            double          yoff;
            SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            ctx.Save();
            ctx.SetLineWidth(1);

            for (int i = 0; i < data.Count; ++i)
            {
                // (1) determine the top left hand point of the bar (assuming not centered)
                Point p1 = data[i];
                if (double.IsNaN(p1.X) || double.IsNaN(p1.Y))
                {
                    continue;
                }

                // (2) determine the top right hand point of the bar (assuming not centered)
                Point p2 = Point.Zero;;
                if (i + 1 != data.Count)
                {
                    p2 = data[i + 1];
                    if (double.IsNaN(p2.X) || double.IsNaN(p2.Y))
                    {
                        continue;
                    }
                    p2.Y = p1.Y;
                }
                else if (i != 0)
                {
                    p2 = data[i - 1];
                    if (double.IsNaN(p2.X) || double.IsNaN(p2.Y))
                    {
                        continue;
                    }
                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                }
                else
                {
                    double offset = 1.0;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                }

                // (3) now account for plots this may be stacked on top of.
                HistogramPlot currentPlot = this;
                yoff = 0.0;
                double yval = 0.0;
                while (currentPlot.IsStacked)
                {
                    SequenceAdapter stackedToData = new SequenceAdapter(
                        currentPlot.stackedTo.DataSource,
                        currentPlot.stackedTo.DataMember,
                        currentPlot.stackedTo.OrdinateData,
                        currentPlot.stackedTo.AbscissaData);

                    yval       += stackedToData[i].Y;
                    yoff        = yAxis.WorldToPhysical(yval, false).Y;
                    p1.Y       += stackedToData[i].Y;
                    p2.Y       += stackedToData[i].Y;
                    currentPlot = currentPlot.stackedTo;
                }

                // (4) now account for centering
                if (Center)
                {
                    double offset = (p2.X - p1.X) / 2.0;
                    p1.X -= offset;
                    p2.X -= offset;
                }

                // (5) now account for BaseOffset (shift of bar sideways).
                p1.X += BaseOffset;
                p2.X += BaseOffset;

                // (6) now get physical coordinates of top two points.
                Point xPos1 = xAxis.WorldToPhysical(p1.X, false);
                Point yPos1 = yAxis.WorldToPhysical(p1.Y, false);
                Point xPos2 = xAxis.WorldToPhysical(p2.X, false);

                if (IsStacked)
                {
                    currentPlot = this;
                    while (currentPlot.IsStacked)
                    {
                        currentPlot = currentPlot.stackedTo;
                    }
                    baseWidth = currentPlot.baseWidth;
                }

                double width = xPos2.X - xPos1.X;
                double height;
                if (IsStacked)
                {
                    height = -yPos1.Y + yoff;
                }
                else
                {
                    height = -yPos1.Y + yAxis.PhysicalMin.Y;
                }

                double    xoff = (1.0 - baseWidth) / 2.0 * width;
                Rectangle bar  = new Rectangle(xPos1.X + xoff, yPos1.Y, width - 2 * xoff, height);

                ctx.Rectangle(bar);
                if (Filled)
                {
                    if (bar.Height != 0 && bar.Width != 0)
                    {
                        if (FillGradient != null)
                        {
                            // Scale FillGradient to bar rectangle
                            double         sX = bar.X + fillGradient.StartPoint.X * bar.Width;
                            double         sY = bar.Y + fillGradient.StartPoint.Y * bar.Height;
                            double         eX = bar.X + fillGradient.EndPoint.X * bar.Width;
                            double         eY = bar.Y + fillGradient.EndPoint.Y * bar.Height;
                            LinearGradient g  = new LinearGradient(sX, sY, eX, eY);
                            g.AddColorStop(0, FillGradient.StartColor);
                            g.AddColorStop(1, FillGradient.EndColor);
                            ctx.Pattern = g;
                        }
                        else
                        {
                            ctx.SetColor(FillColor);
                        }
                        ctx.FillPreserve();
                    }
                }
                ctx.SetColor(BorderColor);
                ctx.Stroke();
            }
            ctx.Restore();
        }
Example #13
0
        /// <summary>
        /// Draws the plot using the Drawing Context and X, Y axes supplied.
        /// </summary>
        public override void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data =
                new SequenceAdapter (this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            TextDataAdapter textData =
                new TextDataAdapter (this.DataSource, this.DataMember, this.TextData);

            TextLayout layout = new TextLayout ();
            layout.Font = Font;

            ctx.Save ();
            ctx.SetColor (Colors.Black);

            for (int i=0; i<data.Count; ++i) {
                try {
                    Point p = data[i];
                    if (!Double.IsNaN(p.X) && !Double.IsNaN(p.Y)) {
                        Point xPos = xAxis.WorldToPhysical (p.X, false);
                        Point yPos = yAxis.WorldToPhysical (p.Y, false);
                        // first plot the marker
                        Marker.Draw (ctx, xPos.X, yPos.Y);
                        // then the label
                        if (textData[i] != "") {
                            layout.Text = textData[i];
                            Size size = layout.GetSize ();
                            switch (labelTextPosition) {
                            case LabelPositions.Above:
                                p.X = xPos.X-size.Width/2;
                                p.Y = yPos.Y-size.Height-Marker.Size*2/3;
                                break;
                            case LabelPositions.Below:
                                p.X = xPos.X-size.Width/2;
                                p.Y = yPos.Y+Marker.Size*2/3;
                                break;
                            case LabelPositions.Left:
                                p.X = xPos.X-size.Width-Marker.Size*2/3;
                                p.Y = yPos.Y-size.Height/2;
                                break;
                            case LabelPositions.Right:
                                p.X = xPos.X+Marker.Size*2/3;
                                p.Y = yPos.Y-size.Height/2;
                                break;
                            }
                            ctx.DrawTextLayout (layout, p);
                        }
                    }
                }
                catch {
                    throw new XwPlotException ("Error in TextPlot.Draw");
                }
            }
            ctx.Restore ();
        }
Example #14
0
        /// <summary>
        /// Returns an X-axis suitable for use by this plot. The axis will be one that is just long
        /// enough to show all data.
        /// </summary>
        /// <returns>X-axis suitable for use by this plot.</returns>
        public Axis SuggestXAxis()
        {
            SequenceAdapter data =
                new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData );

            if (data.Count < 2) {
                return data.SuggestXAxis();
            }

            // else

            Axis a = data.SuggestXAxis();

            Point p1 = data[0];
            Point p2 = data[1];
            Point p3 = data[data.Count-2];
            Point p4 = data[data.Count-1];

            double offset1;
            double offset2;

            if (!centre) {
                offset1 = 0;
                offset2 = p4.X - p3.X;
            }
            else {
                offset1 = (p2.X - p1.X)/2;
                offset2 = (p4.X - p3.X)/2;
            }

            a.WorldMin -= offset1;
            a.WorldMax += offset2;

            return a;
        }
Example #15
0
        /// <summary>
        /// Draws the step plot using a Drawing Context against the provided x and y axes.
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public virtual void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data =
                new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);

            double leftCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
            double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);

            ctx.Save ();
            ctx.SetColor (Color);
            ctx.SetLineWidth (1);

            for (int i=0; i<data.Count; ++i) {
                Point p1 = data[i];
                if (Double.IsNaN(p1.X) || Double.IsNaN(p1.Y)) {
                    continue;
                }

                Point p2;
                Point p3;
                if (i+1 != data.Count) {
                    p2 = data[i+1];
                    if (Double.IsNaN(p2.X) || Double.IsNaN(p2.Y)) {
                        continue;
                    }
                    p2.Y = p1.Y;
                    p3 = data[i+1];
                }
                else {
                    // Check that we are not dealing with a DataSource of 1 point.
                    // This check is done here so it is only checked on the end
                    // condition and not for every point in the DataSource.
                    if (data.Count > 1) {
                        p2 = data[i - 1];
                    }
                    else {
                        p2 = p1;
                    }
                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3 = p2;
                }

                if (centre) {
                    double offset = ( p2.X - p1.X ) / 2.0;
                    p1.X -= offset;
                    p2.X -= offset;
                    p3.X -= offset;
                }

                Point xPos1 = xAxis.WorldToPhysical (p1.X, false);
                Point yPos1 = yAxis.WorldToPhysical (p1.Y, false);
                Point xPos2 = xAxis.WorldToPhysical (p2.X, false);
                Point yPos2 = yAxis.WorldToPhysical (p2.Y, false);
                Point xPos3 = xAxis.WorldToPhysical (p3.X, false);
                Point yPos3 = yAxis.WorldToPhysical (p3.Y, false);

                // do horizontal clipping here, to speed up
                if ((p1.X<leftCutoff && p2.X<leftCutoff && p3.X<leftCutoff) || (p1.X>rightCutoff && p2.X>rightCutoff && p3.X>rightCutoff)) {
                    continue;
                }

                if (!this.hideHorizontalSegments) {
                    if (scale != 1) {
                        double middle = (xPos2.X + xPos1.X) / 2;
                        double width = xPos2.X - xPos1.X;
                        width *= this.scale;
                        ctx.MoveTo (middle-width/2, yPos1.Y);
                        ctx.LineTo (middle+width/2, yPos2.Y);
                    }
                    else {
                        ctx.MoveTo (xPos1.X, yPos1.Y);
                        ctx.LineTo (xPos2.X, yPos2.Y);
                    }
                    ctx.Stroke ();
                }

                if (!this.hideVerticalSegments) {
                    ctx.MoveTo (xPos2.X, yPos2.Y);
                    ctx.LineTo (xPos3.X, yPos3.Y);
                    ctx.Stroke ();
                }
            }
            ctx.Restore ();
        }
Example #16
0
        /// <summary>
        /// Returns an x-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable x-axis.</returns>
        public Axis SuggestXAxis()
        {
            SequenceAdapter data = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);

            Axis a = data.SuggestXAxis();
            if (data.Count==0) {
                return a;
            }

            Point p1;
            Point p2;
            Point p3;
            Point p4;
            if (data.Count < 2) {
                p1 = data [0];
                p1.X -= 1.0;
                p2 = data [0];
                p3 = p1;
                p4 = p2;
            }
            else {
                p1 = data [0];
                p2 = data [1];
                p3 = data [data.Count-2];
                p4 = data [data.Count-1];
            }

            double offset1;
            double offset2;

            if (!Center) {
                offset1 = 0.0;
                offset2 = p4.X - p3.X;
            }
            else {
                offset1 = (p2.X - p1.X)/2.0f;
                offset2 = (p4.X - p3.X)/2.0f;
            }

            a.WorldMin -= offset1;
            a.WorldMax += offset2;

            return a;
        }
Example #17
0
        /// <summary>
        /// Returns a y-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable y-axis.</returns>
        public Axis SuggestYAxis()
        {
            if (IsStacked) {
                double tmpMax = 0.0f;
                ArrayList adapterList = new ArrayList();

                HistogramPlot currentPlot = this;
                do {
                    adapterList.Add (new SequenceAdapter (
                        currentPlot.DataSource,
                        currentPlot.DataMember,
                        currentPlot.OrdinateData,
                        currentPlot.AbscissaData)
                    );
                } while ((currentPlot = currentPlot.stackedTo) != null);

                SequenceAdapter[] adapters = (SequenceAdapter[])adapterList.ToArray (typeof(SequenceAdapter));

                for (int i=0; i<adapters[0].Count; ++i) {
                    double tmpHeight = 0.0f;
                    for (int j=0; j<adapters.Length; ++j) {
                        tmpHeight += adapters[j][i].Y;
                    }
                    tmpMax = Math.Max (tmpMax, tmpHeight);
                }

                Axis a = new LinearAxis (0.0,tmpMax);
                // TODO make 0.08 a parameter.
                a.IncreaseRange (0.08);
                return a;
            }
            else {
                SequenceAdapter data = new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);
                return data.SuggestYAxis();
            }
        }
Example #18
0
        /// <summary>
        /// Draw the filled region
        /// </summary>
        /// <param name="g">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            ITransform2D t = Transform2D.GetTransformer (xAxis, yAxis);

            ctx.Save ();

            if (hl1 != null && hl2 != null) {
                ctx.MoveTo (t.Transform (xAxis.Axis.WorldMin, hl1.OrdinateValue));
                ctx.LineTo (t.Transform (xAxis.Axis.WorldMax, hl1.OrdinateValue));
                ctx.LineTo (t.Transform (xAxis.Axis.WorldMax, hl2.OrdinateValue));
                ctx.LineTo (t.Transform (xAxis.Axis.WorldMin, hl2.OrdinateValue));
                ctx.ClosePath ();
            } else if (vl1 != null && vl2 != null) {
                ctx.MoveTo (t.Transform (vl1.AbscissaValue, yAxis.Axis.WorldMin));
                ctx.LineTo (t.Transform (vl1.AbscissaValue, yAxis.Axis.WorldMax));
                ctx.LineTo (t.Transform (vl2.AbscissaValue, yAxis.Axis.WorldMax));
                ctx.LineTo (t.Transform (vl2.AbscissaValue, yAxis.Axis.WorldMin));
                ctx.ClosePath ();
            } else if (lp1 != null && lp2 != null) {

                SequenceAdapter a1 = new SequenceAdapter (lp1.DataSource, lp1.DataMember, lp1.OrdinateData, lp1.AbscissaData);
                SequenceAdapter a2 = new SequenceAdapter (lp2.DataSource, lp2.DataMember, lp2.OrdinateData, lp2.AbscissaData);

                // Start at first point of LinePlot 1 within plot bounds
                int start = 0;
                while (t.Transform (a1 [start]).X < xAxis.PhysicalMin.X) {
                    ++start;
                }
                Point first = t.Transform (a1 [start]);
                ctx.MoveTo (first);
                // Join LinePlot 1 points in ascending order
                Point next;
                for (int i = start+1; i < a1.Count-1; ++i) {
                    next = t.Transform (a1 [i]);
                    if (next.X > xAxis.PhysicalMax.X)
                        break;
                    ctx.LineTo (next);
                }
                // Then join LinePlot 2 points in descending order
                int end = a2.Count-1;
                while (t.Transform (a2 [end]).X > xAxis.PhysicalMax.X) {
                    --end;
                }
                for (int i = end; i > 0; --i) {
                    next = t.Transform (a2 [i]);
                    if (next.X < xAxis.PhysicalMin.X)
                        break;
                    ctx.LineTo (next);
                }
                ctx.LineTo (first);
                ctx.ClosePath ();
            }
            else {
                throw new XwPlotException ("Filled Region bounds not defined");
            }
            ctx.SetColor (FillColor);
            ctx.Fill ();
            ctx.Restore ();
        }
Example #19
0
 /// <summary>
 /// Returns a y-axis that is suitable for drawing this plot.
 /// </summary>
 /// <returns>A suitable y-axis.</returns>
 public Axis SuggestYAxis()
 {
     SequenceAdapter data_ =
         new SequenceAdapter (DataSource, DataMember, OrdinateData, AbscissaData);
     return data_.SuggestYAxis();
 }
Example #20
0
        /// <summary>
        /// Returns an Y-axis suitable for use by this plot. The axis will be one that is just long
        /// enough to show all data.
        /// </summary>
        /// <returns>Y-axis suitable for use by this plot.</returns>
        public Axis SuggestYAxis()
        {
            SequenceAdapter data = new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

            return(data.SuggestYAxis());
        }
Example #21
0
        /// <summary>
        /// Draw the filled region
        /// </summary>
        /// <param name="g">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis);

            ctx.Save();

            if (hl1 != null && hl2 != null)
            {
                ctx.MoveTo(t.Transform(xAxis.Axis.WorldMin, hl1.OrdinateValue));
                ctx.LineTo(t.Transform(xAxis.Axis.WorldMax, hl1.OrdinateValue));
                ctx.LineTo(t.Transform(xAxis.Axis.WorldMax, hl2.OrdinateValue));
                ctx.LineTo(t.Transform(xAxis.Axis.WorldMin, hl2.OrdinateValue));
                ctx.ClosePath();
            }
            else if (vl1 != null && vl2 != null)
            {
                ctx.MoveTo(t.Transform(vl1.AbscissaValue, yAxis.Axis.WorldMin));
                ctx.LineTo(t.Transform(vl1.AbscissaValue, yAxis.Axis.WorldMax));
                ctx.LineTo(t.Transform(vl2.AbscissaValue, yAxis.Axis.WorldMax));
                ctx.LineTo(t.Transform(vl2.AbscissaValue, yAxis.Axis.WorldMin));
                ctx.ClosePath();
            }
            else if (lp1 != null && lp2 != null)
            {
                SequenceAdapter a1 = new SequenceAdapter(lp1.DataSource, lp1.DataMember, lp1.OrdinateData, lp1.AbscissaData);
                SequenceAdapter a2 = new SequenceAdapter(lp2.DataSource, lp2.DataMember, lp2.OrdinateData, lp2.AbscissaData);

                // Start at first point of LinePlot 1 within plot bounds
                int start = 0;
                while (t.Transform(a1 [start]).X < xAxis.PhysicalMin.X)
                {
                    ++start;
                }
                Point first = t.Transform(a1 [start]);
                ctx.MoveTo(first);
                // Join LinePlot 1 points in ascending order
                Point next;
                for (int i = start + 1; i < a1.Count - 1; ++i)
                {
                    next = t.Transform(a1 [i]);
                    if (next.X > xAxis.PhysicalMax.X)
                    {
                        break;
                    }
                    ctx.LineTo(next);
                }
                // Then join LinePlot 2 points in descending order
                int end = a2.Count - 1;
                while (t.Transform(a2 [end]).X > xAxis.PhysicalMax.X)
                {
                    --end;
                }
                for (int i = end; i > 0; --i)
                {
                    next = t.Transform(a2 [i]);
                    if (next.X < xAxis.PhysicalMin.X)
                    {
                        break;
                    }
                    ctx.LineTo(next);
                }
                ctx.LineTo(first);
                ctx.ClosePath();
            }
            else
            {
                throw new XwPlotException("Filled Region bounds not defined");
            }
            ctx.SetColor(FillColor);
            ctx.Fill();
            ctx.Restore();
        }
Example #22
0
        /// <summary>
        /// Draws the line plot using the Drawing Context and x and y axes provided
        /// </summary>
        /// <param name="ctx">The Drawing Context with which to draw.</param>
        /// <param name="xAxis">The X-Axis to draw against.</param>
        /// <param name="yAxis">The Y-Axis to draw against.</param>
        public void Draw(Context ctx, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter dataTop = new SequenceAdapter (DataSource, DataMember, OrdinateDataTop, AbscissaData);
            SequenceAdapter dataBottom = new SequenceAdapter (DataSource, DataMember, OrdinateDataBottom, AbscissaData);

            ITransform2D t = Transform2D.GetTransformer (xAxis, yAxis);

            ctx.Save ();
            for (int i=0; i<dataTop.Count; ++i) {
                Point physicalBottom = t.Transform (dataBottom[i]);
                Point physicalTop = t.Transform (dataTop[i]);

                if (physicalBottom != physicalTop) {
                    Rectangle r = new Rectangle (physicalBottom.X - BarWidth/2, physicalTop.Y,BarWidth, (physicalBottom.Y - physicalTop.Y) );
                    ctx.SetColor (fillColor);
                    ctx.Rectangle (r);
                    ctx.FillPreserve ();
                    ctx.SetColor (borderColor);
                    ctx.Stroke ();
                }
            }
            ctx.Restore ();
        }