This class is responsible for interpreting the various ways you can specify data to plot objects using the DataSource, DataMember, ordinateData and AbscissaData properties. It is a bridge that provides access to this data via a single interface.
示例#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(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            Axis a = data.SuggestXAxis();

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

            PointD p1;
            PointD p2;
            PointD p3;
            PointD 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.0f;
                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);
        }
示例#2
0
        /// <summary>
        /// Draws the plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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 override void Draw(IGraphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data =
                new SequenceAdapter(DataSource, DataMember, OrdinateData, AbscissaData);

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

            // first plot the marker
            // we can do this cast, since the constructor accepts only this type!
            for (int i = 0; i < data.Count; ++i)
            {
                try
                {
                    PointD pt = data[i];
                    if (!Double.IsNaN(pt.X) && !Double.IsNaN(pt.Y))
                    {
                        PointF xPos = xAxis.WorldToPhysical(pt.X, false);
                        PointF yPos = yAxis.WorldToPhysical(pt.Y, false);
                        Marker.Draw(g, (int)xPos.X, (int)yPos.Y);
                        if (textData[i] != "")
                        {
                            SizeF size = g.MeasureString(textData[i], Font);
                            switch (LabelTextPosition)
                            {
                            case LabelPositions.Above:
                                g.DrawString(textData[i], Font, Brushes.Black,
                                             new PointF(xPos.X - size.Width / 2, yPos.Y - size.Height - Marker.Size * 2 / 3));
                                break;

                            case LabelPositions.Below:
                                g.DrawString(textData[i], Font, Brushes.Black, new PointF(xPos.X - size.Width / 2, yPos.Y + Marker.Size * 2 / 3));
                                break;

                            case LabelPositions.Left:
                                g.DrawString(textData[i], Font, Brushes.Black,
                                             new PointF(xPos.X - size.Width - Marker.Size * 2 / 3, yPos.Y - size.Height / 2));
                                break;

                            case LabelPositions.Right:
                                g.DrawString(textData[i], Font, Brushes.Black, new PointF(xPos.X + Marker.Size * 2 / 3, yPos.Y - size.Height / 2));
                                break;
                            }
                        }
                    }
                }
                catch
                {
                    throw new NPlotException("Error in TextPlot.Draw");
                }
            }
        }
示例#3
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);
        }
示例#4
0
        /// <summary>
        /// Returns a y-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable y-axis.</returns>
        public Axis SuggestYAxis()
        {
            if (this.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.0f, tmpMax);
                // TODO make 0.08 a parameter.
                a.IncreaseRange(0.08);
                return(a);
            }
            else
            {
                SequenceAdapter data =
                    new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

                return(data.SuggestYAxis());
            }
        }
示例#5
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();

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

            double offset1;
            double offset2;

            if (!center_)
            {
                offset1 = 0.0f;
                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);
        }
示例#6
0
        /// <summary>
        /// Renders the histogram.
        /// </summary>
        /// <param name="g">The Graphics surface on 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(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            float yoff;

            for (int i = 0; i < data.Count; ++i)
            {
                // (1) determine the top left hand point of the bar (assuming not centered)
                PointD 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)
                PointD p2;
                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.0f;
                    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.0f;
                double yval = 0.0f;
                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.0f;
                    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.
                PointF xPos1 = xAxis.WorldToPhysical(p1.X, false);
                PointF yPos1 = yAxis.WorldToPhysical(p1.Y, false);
                PointF xPos2 = xAxis.WorldToPhysical(p2.X, false);
                PointF yPos2 = yAxis.WorldToPhysical(p2.Y, false);

                if (isStacked_)
                {
                    currentPlot = this;
                    while (currentPlot.isStacked_)
                    {
                        currentPlot = currentPlot.stackedTo_;
                    }
                    this.baseWidth_ = currentPlot.baseWidth_;
                }

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

                float     xoff = (1.0f - baseWidth_) / 2.0f * width;
                Rectangle r    = new Rectangle((int)(xPos1.X + xoff), (int)yPos1.Y, (int)(width - 2 * xoff), (int)height);

                if (this.Filled)
                {
                    if (r.Height != 0 && r.Width != 0)
                    {
                        // room for optimization maybe.
                        g.FillRectangle(rectangleBrush_.Get(r), r);
                    }
                }

                g.DrawRectangle(Pen, r.X, r.Y, r.Width, r.Height);
            }
        }
示例#7
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 r = new Rectangle (xPos1.X+xoff, yPos1.Y, width-2*xoff, height);

                ctx.Rectangle (r);
                if (Filled) {
                    if (r.Height != 0 && r.Width != 0) {
                        // room for optimization maybe.
                        ctx.SetColor (fillColor);
                        ctx.FillPreserve ();
                    }
                }
                ctx.SetColor (borderColor);
                ctx.Stroke ();
            }
            ctx.Restore ();
        }
示例#8
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 ();
        }
示例#9
0
文件: LinePlot.cs 项目: parnham/NPlot
        /// <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);

            return data_.SuggestXAxis();
        }
示例#10
0
文件: StepPlot.cs 项目: parnham/NPlot
        /// <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 (!center_) {
                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;
        }
        /// <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( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

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

            PointD p1;
            PointD p2;
            PointD p3;
            PointD 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.0f;
                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;
        }
        /// <summary>
        /// Writes text data of the plot object to the supplied string builder. It is 
        /// possible to specify that only data in the specified range be written.
        /// </summary>
        /// <param name="sb">the StringBuilder object to write to.</param>
        /// <param name="region">a region used if onlyInRegion is true.</param>
        /// <param name="onlyInRegion">If true, only data enclosed in the provided region will be written.</param>
        public void WriteData( System.Text.StringBuilder sb, RectangleD region, bool onlyInRegion )
        {
            SequenceAdapter data_ =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            sb.Append( "Label: " );
            sb.Append( this.Label );
            sb.Append( "\r\n" );
            data_.WriteData( sb, region, onlyInRegion );
        }
示例#13
0
        /// <summary>
        /// Draws the line plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow)
        {
            Pen shadowPen = null;

            if (drawShadow)
            {
                shadowPen       = (Pen)this.Pen.Clone();
                shadowPen.Color = this.ShadowColor;
            }

            SequenceAdapter data =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

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

            int numberPoints = data.Count;

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

            // clipping is now handled assigning a clip region in the
            // graphic object before this call
            if (numberPoints == 1)
            {
                PointF physical = t.Transform(data[0]);

                if (drawShadow)
                {
                    g.DrawLine(shadowPen,
                               physical.X - 0.5f + this.ShadowOffset.X,
                               physical.Y + this.ShadowOffset.Y,
                               physical.X + 0.5f + this.ShadowOffset.X,
                               physical.Y + this.ShadowOffset.Y);
                }
                else
                {
                    g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y);
                }
            }
            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.
                    PointF p1 = t.Transform(data[i - 1]);
                    PointF 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)
                    {
                        g.DrawLine(shadowPen,
                                   p1.X + ShadowOffset.X,
                                   p1.Y + ShadowOffset.Y,
                                   p2.X + ShadowOffset.X,
                                   p2.Y + ShadowOffset.Y);
                    }
                    else
                    {
                        g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y);
                    }
                }
            }
        }
示例#14
0
        /// <summary>
        /// Draws the step plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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(Graphics g, 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);

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

                PointD p2;
                PointD 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
                    {
                        // TODO: Once log4net is set up post a message to the user that a step-plot of 1 really does not make any sense.
                        p2 = p1;
                    }

                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3   = p2;
                }

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

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

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

                if (!hideHorizontalSegments_)
                {
                    if (scale_ != 1.0f)
                    {
                        float middle = (xPos2.X + xPos1.X) / 2.0f;
                        float width  = xPos2.X - xPos1.X;
                        width *= scale_;
                        g.DrawLine(Pen, (int)(middle - width / 2.0f), yPos1.Y, (int)(middle + width / 2.0f), yPos2.Y);
                    }
                    else
                    {
                        g.DrawLine(Pen, xPos1.X, yPos1.Y, xPos2.X, yPos2.Y);
                    }
                }

                if (!hideVerticalSegments_)
                {
                    g.DrawLine(Pen, xPos2.X, yPos2.Y, xPos3.X, yPos3.Y);
                }
            }
        }
示例#15
0
        /// <summary>
        /// Writes text data of the plot object to the supplied string builder.
        /// </summary>
        /// <param name="sb">the StringBuilder object to write to.</param>
        public void WriteData(System.Text.StringBuilder sb )
        {
            SequenceAdapter data_ =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            sb.Append("[");
            sb.Append(this.Label);
            sb.AppendLine("]");
            data_.WriteData(sb);
        }
示例#16
0
        /// <summary>
        /// Draws the point plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data_ =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            float leftCutoff_ = xAxis.PhysicalMin.X - marker_.Size;
            float rightCutoff_ = xAxis.PhysicalMax.X + marker_.Size;

            for (int i=0; i<data_.Count; ++i)
            {
                var pointMarker = marker_;

                if (MarkerCallback != null)
                {
                    pointMarker = MarkerCallback(data_[i].X, data_[i].Y);
                }

                if ( !Double.IsNaN(data_[i].X) && !Double.IsNaN(data_[i].Y) )
                {
                    PointF xPos = xAxis.WorldToPhysical( data_[i].X, false);
                    if (xPos.X < leftCutoff_ || rightCutoff_ < xPos.X)
                        continue;

                    PointF yPos = yAxis.WorldToPhysical( data_[i].Y, false);
                    pointMarker.Draw(g, (int)xPos.X, (int)yPos.Y);
                    if (pointMarker.DropLine)
                    {
                        PointD yMin = new PointD( data_[i].X, Math.Max( 0.0f, yAxis.Axis.WorldMin ) );
                        PointF yStart = yAxis.WorldToPhysical( yMin.Y, false );
                        g.DrawLine(pointMarker.Pen, new Point((int)xPos.X, (int)yStart.Y), new Point((int)xPos.X, (int)yPos.Y));
                    }

                    if (LabelFont != null)
                    {
                        var markerHalfSize = (float)pointMarker.Size / 2.0f;

                        // Top-left corner
                        var yText = data_[i].Y.ToString();
                        var textSize = g.MeasureString(yText, LabelFont);
                        var labelRect = new RectangleF(xPos.X, yPos.Y,
                            textSize.Width + LabelPadding + LabelPadding,
                            textSize.Height + LabelPadding + LabelPadding);

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try bottom-left corner
                            labelRect.Y = yPos.Y - labelRect.Height;
                        }

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try bottom-right corner
                            labelRect.X = xPos.X - labelRect.Width;
                        }

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try top-right corner
                            labelRect.Y = yPos.Y;
                        }

                        g.FillRectangle(Brushes.White, labelRect);
                        g.DrawRectangle(Pens.Black, labelRect.X, labelRect.Y,
                            labelRect.Width, labelRect.Height);

                        g.DrawString(yText, LabelFont, pointMarker.FillBrush,
                            labelRect.X + LabelPadding, labelRect.Y + LabelPadding);
                    }
                }
            }
        }
示例#17
0
        /// <summary>
        /// Draws the step plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

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

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

                PointD p2;
                PointD 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
                {
                    p2 = data[i-1];
                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3 = p2;
                }

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

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

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

                if (!this.hideHorizontalSegments_)
                {
                    if (scale_ != 1.0f)
                    {
                        float middle = (xPos2.X + xPos1.X) / 2.0f;
                        float width = xPos2.X - xPos1.X;
                        width *= this.scale_;
                        g.DrawLine( Pen, (int)(middle-width/2.0f), yPos1.Y, (int)(middle+width/2.0f), yPos2.Y );
                    }
                    else
                    {
                        g.DrawLine( Pen, xPos1.X, yPos1.Y, xPos2.X, yPos2.Y );
                    }
                }

                if (!this.hideVerticalSegments_)
                {
                    g.DrawLine( Pen, xPos2.X, yPos2.Y, xPos3.X, yPos3.Y );
                }

            }
        }
示例#18
0
文件: PointPlot.cs 项目: sanyu1/NPlot
        /// <summary>
        /// Draws the point plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data_ =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            float leftCutoff_ = xAxis.PhysicalMin.X - marker_.Size;
            float rightCutoff_ = xAxis.PhysicalMax.X + marker_.Size;

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

                    PointF yPos = yAxis.WorldToPhysical( data_[i].Y, false);
                    marker_.Draw( g, (int)xPos.X, (int)yPos.Y );
                    if (marker_.DropLine)
                    {
                        PointD yMin = new PointD( data_[i].X, Math.Max( 0.0f, yAxis.Axis.WorldMin ) );
                        PointF yStart = yAxis.WorldToPhysical( yMin.Y, false );
                        g.DrawLine( marker_.Pen, new Point((int)xPos.X,(int)yStart.Y), new Point((int)xPos.X,(int)yPos.Y) );
                    }
                }
            }
        }
示例#19
0
        /// <summary>
        /// Draws the line plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow)
        {
            Pen shadowPen = null;

            if (drawShadow)
            {
                shadowPen       = (Pen)this.Pen.Clone();
                shadowPen.Color = this.ShadowColor;
            }

            SequenceAdapter data =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            int numberPoints = data.Count;

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

            // clipping is now handled assigning a clip region in the
            // graphic object before this call
            if (numberPoints == 1)
            {
                PointF physical = Transform2D.GetTransformer(xAxis, yAxis).Transform(data[0]);

                if (drawShadow)
                {
                    g.DrawLine(shadowPen,
                               physical.X - 0.5f + this.ShadowOffset.X,
                               physical.Y + this.ShadowOffset.Y,
                               physical.X + 0.5f + this.ShadowOffset.X,
                               physical.Y + this.ShadowOffset.Y);
                }
                else
                {
                    g.DrawLine(Pen, physical.X - 0.5f, physical.Y, physical.X + 0.5f, physical.Y);
                }
            }
            else
            {
                // prepare for clipping
                double leftCutoff  = xAxis.PhysicalToWorld(xAxis.PhysicalMin, false);
                double rightCutoff = xAxis.PhysicalToWorld(xAxis.PhysicalMax, false);
                if (leftCutoff > rightCutoff)
                {
                    double temp = leftCutoff;
                    leftCutoff  = rightCutoff;
                    rightCutoff = temp;
                }
                if (drawShadow)
                {
                    // correct cut-offs
                    double shadowCorrection =
                        xAxis.PhysicalToWorld(ShadowOffset, false) - xAxis.PhysicalToWorld(new Point(0, 0), false);
                    leftCutoff  -= shadowCorrection;
                    rightCutoff -= shadowCorrection;
                }

                // determine which points to plot
                double        tradingTimeOffset = 0;
                List <PointD> plotPoints        = new List <PointD>(numberPoints);
                PointD        d1 = data[0];
                PointD        d2 = d1;
                if ((d1.X >= leftCutoff) && (d1.X <= rightCutoff))
                {
                    plotPoints.Add(d1);
                }
                DateTime prevTime = (DateTime)((System.Data.DataTable) this.DataSource).Rows[0][(string)this.AbscissaData];
                for (int i = 1; i < numberPoints; ++i)
                {
                    // check to see if any values null. If so, then continue.
                    d1 = d2;
                    d2 = data[i];
                    if (Double.IsNaN(d1.X) || Double.IsNaN(d1.Y) ||
                        Double.IsNaN(d2.X) || Double.IsNaN(d2.Y))
                    {
                        continue;
                    }

                    // Get the X axis offset to strip out the non-trading time
                    d1.X -= tradingTimeOffset;
                    DateTime nextTime = (DateTime)((System.Data.DataTable) this.DataSource).Rows[i][(string)this.AbscissaData];
                    if (nextTime.TimeOfDay < prevTime.TimeOfDay)
                    {
                        tradingTimeOffset += (double)(nextTime - prevTime).Ticks;
                    }
                    prevTime = nextTime;
                    d2.X    -= tradingTimeOffset;

                    // do horizontal clipping here, to speed up
                    if ((d1.X < leftCutoff && d2.X < leftCutoff) ||
                        (rightCutoff < d1.X && rightCutoff < d2.X))
                    {
                        continue;
                    }

                    // Add a point to plot
                    plotPoints.Add(d2);
                }

                // create a transform, which takes into account the skipped time
                PhysicalAxis shunkAxis = new PhysicalAxis(new DateTimeAxis(xAxis.Axis.WorldMin, xAxis.Axis.WorldMax - tradingTimeOffset), xAxis.PhysicalMin, xAxis.PhysicalMax);
                ITransform2D t         = Transform2D.GetTransformer(shunkAxis, yAxis);

                // plot those points
                for (int i = 1; i < plotPoints.Count; i++)
                {
                    // else draw line.
                    PointF p1 = t.Transform(plotPoints[i - 1]);
                    PointF p2 = t.Transform(plotPoints[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)
                    {
                        g.DrawLine(shadowPen,
                                   p1.X + ShadowOffset.X,
                                   p1.Y + ShadowOffset.Y,
                                   p2.X + ShadowOffset.X,
                                   p2.Y + ShadowOffset.Y);
                    }
                    else
                    {
                        g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y);
                    }
                }
            }
        }
        /// <summary>
        /// Renders the histogram.
        /// </summary>
        /// <param name="g">The Graphics surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            float yoff;

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

                // (1) determine the top left hand point of the bar (assuming not centered)
                PointD 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)
                PointD p2;
                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.0f;
                    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.0f;
                double yval = 0.0f;
                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.0f;
                    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.
                PointF xPos1 = xAxis.WorldToPhysical( p1.X, false );
                PointF yPos1 = yAxis.WorldToPhysical( p1.Y, false );
                PointF xPos2 = xAxis.WorldToPhysical( p2.X, false );
                PointF yPos2 = yAxis.WorldToPhysical( p2.Y, false );

                if (isStacked_)
                {
                    currentPlot = this;
                    while (currentPlot.isStacked_)
                    {
                        currentPlot = currentPlot.stackedTo_;
                    }
                    this.baseWidth_ = currentPlot.baseWidth_;
                }

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

                float xoff = (1.0f - baseWidth_)/2.0f*width;
                Rectangle r = new Rectangle( (int)(xPos1.X+xoff), (int)yPos1.Y, (int)(width-2*xoff), (int)height );

                if (this.Filled)
                {
                    if (r.Height != 0 && r.Width != 0)
                    {
                        // room for optimization maybe.
                        g.FillRectangle( rectangleBrush_.Get(r), r );
                    }
                }

                g.DrawRectangle( Pen, r.X, r.Y, r.Width, r.Height );

            }
        }
示例#21
0
        /// <summary>
        /// Draws the line plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis, bool drawShadow )
        {
            Pen shadowPen = null;
            if (drawShadow)
            {
                shadowPen = (Pen)this.Pen.Clone();
                shadowPen.Color = this.ShadowColor;
            }

            SequenceAdapter data =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

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

            int numberPoints = data.Count;

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

            // clipping is now handled assigning a clip region in the
            // graphic object before this call
            if (numberPoints == 1)
            {
                PointF physical = t.Transform( data[0] );

                if (drawShadow)
                {
                    g.DrawLine( shadowPen,
                        physical.X - 0.5f + this.ShadowOffset.X,
                        physical.Y + this.ShadowOffset.Y,
                        physical.X + 0.5f + this.ShadowOffset.X,
                        physical.Y + this.ShadowOffset.Y );
                }
                else
                {
                    g.DrawLine( Pen, physical.X-0.5f, physical.Y, physical.X+0.5f, physical.Y);
                }
            }
            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 || rightCutoff < dx1) &&
                        (dx2 < leftCutoff || rightCutoff < dx2))
                    {
                        continue;
                    }

                    // else draw line.
                    PointF p1 = t.Transform( data[i-1] );
                    PointF 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)
                    {
                        g.DrawLine( shadowPen,
                            p1.X + ShadowOffset.X,
                            p1.Y + ShadowOffset.Y,
                            p2.X + ShadowOffset.X,
                            p2.Y + ShadowOffset.Y );
                    }
                    else
                    {
                        g.DrawLine( Pen, p1.X, p1.Y, p2.X, p2.Y );
                    }
                }
            }
        }
        /// <summary>
        /// Stack the histogram to another HistogramPlot.
        /// </summary>
        public void StackedTo(HistogramPlot hp)
        {
            SequenceAdapter data =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.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 NPlotException("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 NPlotException("Can stack HistogramPlot data only with the same X coordinates.");
                        }
                        if ( hpData[i].Y < 0.0f)
                        {
                            throw new NPlotException("Can stack HistogramPlot data only with positive Y coordinates.");
                        }
                    }
                }
                stackedTo_ = hp;
        }
示例#23
0
        /// <summary>
        /// Draws the line plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter dataTop =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataTop, this.AbscissaData );

            SequenceAdapter dataBottom =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataBottom, this.AbscissaData );

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

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

                if (physicalBottom != physicalTop)
                {
                    Rectangle r = new Rectangle( (int)(physicalBottom.X - BarWidth/2), (int)physicalTop.Y,
                        (int)BarWidth, (int)(physicalBottom.Y - physicalTop.Y) );

                    g.FillRectangle( this.rectangleBrush_.Get(r), r );
                    g.DrawRectangle( borderPen_, r );
                }
            }
        }
        /// <summary>
        /// Returns a y-axis that is suitable for drawing this plot.
        /// </summary>
        /// <returns>A suitable y-axis.</returns>
        public Axis SuggestYAxis()
        {
            if ( this.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.0f,tmpMax);
                // TODO make 0.08 a parameter.
                a.IncreaseRange( 0.08 );
                return a;
            }
            else
            {
                SequenceAdapter data =
                    new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

                return data.SuggestYAxis();
            }
        }
示例#25
0
        /// <summary>
        /// Draws the point plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            SequenceAdapter data_ =
                new SequenceAdapter(this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData);

            float leftCutoff_  = xAxis.PhysicalMin.X - marker_.Size;
            float rightCutoff_ = xAxis.PhysicalMax.X + marker_.Size;

            for (int i = 0; i < data_.Count; ++i)
            {
                var pointMarker = marker_;

                if (MarkerCallback != null)
                {
                    pointMarker = MarkerCallback(data_[i].X, data_[i].Y);
                }

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

                    PointF yPos = yAxis.WorldToPhysical(data_[i].Y, false);
                    pointMarker.Draw(g, (int)xPos.X, (int)yPos.Y);
                    if (pointMarker.DropLine)
                    {
                        PointD yMin   = new PointD(data_[i].X, Math.Max(0.0f, yAxis.Axis.WorldMin));
                        PointF yStart = yAxis.WorldToPhysical(yMin.Y, false);
                        g.DrawLine(pointMarker.Pen, new Point((int)xPos.X, (int)yStart.Y), new Point((int)xPos.X, (int)yPos.Y));
                    }

                    if (LabelFont != null)
                    {
                        var markerHalfSize = (float)pointMarker.Size / 2.0f;

                        // Top-left corner
                        var yText     = data_[i].Y.ToString();
                        var textSize  = g.MeasureString(yText, LabelFont);
                        var labelRect = new RectangleF(xPos.X, yPos.Y,
                                                       textSize.Width + LabelPadding + LabelPadding,
                                                       textSize.Height + LabelPadding + LabelPadding);

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try bottom-left corner
                            labelRect.Y = yPos.Y - labelRect.Height;
                        }

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try bottom-right corner
                            labelRect.X = xPos.X - labelRect.Width;
                        }

                        if (!g.ClipBounds.Contains(labelRect))
                        {
                            // Try top-right corner
                            labelRect.Y = yPos.Y;
                        }

                        g.FillRectangle(Brushes.White, labelRect);
                        g.DrawRectangle(Pens.Black, labelRect.X, labelRect.Y,
                                        labelRect.Width, labelRect.Height);

                        g.DrawString(yText, LabelFont, pointMarker.FillBrush,
                                     labelRect.X + LabelPadding, labelRect.Y + LabelPadding);
                    }
                }
            }
        }
示例#26
0
文件: LinePlot.cs 项目: parnham/NPlot
        /// <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_);

            // clipping is now handled assigning a clip region in the
            // graphic object before this call
            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 ();
        }
示例#27
0
        /// <summary>
        /// Draws the step plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            SequenceAdapter data =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

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

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

                PointD p2;
                PointD 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
                    {
                        // TODO: Once log4net is set up post a message to the user that a step-plot of 1 really does not make any sense.
                        p2 = p1;
                    }

                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3 = p2;
                }

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

                PointF xPos1 = xAxis.WorldToPhysical( p1.X, false );
                PointF yPos1 = yAxis.WorldToPhysical( p1.Y, false );
                PointF xPos2 = xAxis.WorldToPhysical( p2.X, false );
                PointF yPos2 = yAxis.WorldToPhysical( p2.Y, false );
                PointF xPos3 = xAxis.WorldToPhysical( p3.X, false );
                PointF 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.0f)
                    {
                        float middle = (xPos2.X + xPos1.X) / 2.0f;
                        float width = xPos2.X - xPos1.X;
                        width *= this.scale_;
                        g.DrawLine( Pen, (int)(middle-width/2.0f), yPos1.Y, (int)(middle+width/2.0f), yPos2.Y );
                    }
                    else
                    {
                        g.DrawLine( Pen, xPos1.X, yPos1.Y, xPos2.X, yPos2.Y );
                    }
                }

                if (!this.hideVerticalSegments_)
                {
                    g.DrawLine( Pen, xPos2.X, yPos2.Y, xPos3.X, yPos3.Y );
                }
            }
        }
示例#28
0
        /// <summary>
        /// Draw the filled region
        /// </summary>
        /// <param name="g">The GDI+ surface on 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( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            ITransform2D t = Transform2D.GetTransformer(xAxis, yAxis);

            Brush b = brush_;
            if (b == null)
            {
                b = areaBrush_.Get(new Rectangle(xAxis.PhysicalMin.X, yAxis.PhysicalMax.Y, xAxis.PhysicalLength, yAxis.PhysicalLength));
            }

            if (hl1_ != null && hl2_ != null)
            {
                PointF[] points = new PointF[4];
                points[0] = t.Transform(xAxis.Axis.WorldMin, hl1_.OrdinateValue);
                points[1] = t.Transform(xAxis.Axis.WorldMax, hl1_.OrdinateValue);
                points[2] = t.Transform(xAxis.Axis.WorldMax, hl2_.OrdinateValue);
                points[3] = t.Transform(xAxis.Axis.WorldMin, hl2_.OrdinateValue);

                g.FillPolygon(b, points);
            }
            else if (vl1_ != null && vl2_ != null)
            {
                PointF[] points = new PointF[4];
                points[0] = t.Transform(vl1_.AbscissaValue, yAxis.Axis.WorldMin);
                points[1] = t.Transform(vl1_.AbscissaValue, yAxis.Axis.WorldMax);
                points[2] = t.Transform(vl2_.AbscissaValue, yAxis.Axis.WorldMax);
                points[3] = t.Transform(vl2_.AbscissaValue, yAxis.Axis.WorldMin);

                g.FillPolygon(b, points);
            }
            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);

                int count = a1.Count + a2.Count;
                PointF[] points = new PointF[count];
                for (int i = 0; i < a1.Count; ++i)
                {
                    points[i] = t.Transform(a1[i]);
                }
                for (int i = 0; i < a2.Count; ++i)
                {
                    points[i + a1.Count] = t.Transform(a2[a2.Count - i - 1]);
                }

                g.FillPolygon(b, points);
            }
            else
            {
                throw new NPlotException("One of bounds was set to null");
            }
        }
示例#29
0
文件: StepPlot.cs 项目: parnham/NPlot
        /// <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);

            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 {
                        // TODO: Once log4net is set up post a message to the user that a step-plot of 1 really does not make any sense.
                        p2 = p1;
                    }

                    double offset = p1.X - p2.X;
                    p2.X = p1.X + offset;
                    p2.Y = p1.Y;
                    p3 = p2;
                }

                if (center_) {
                    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;
                }

                ctx.Save ();
                ctx.SetColor (Color);
                ctx.SetLineWidth (1);
                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 ();
            }
        }
示例#30
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( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            return data_.SuggestYAxis();
        }
示例#31
0
        /// <summary>
        /// Draws the plot on a GDI+ surface against the provided x and y axes.
        /// </summary>
        /// <param name="g">The GDI+ surface on 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 override void Draw( Graphics g, 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 );

            // first plot the marker
            // we can do this cast, since the constructor accepts only this type!
            for (int i=0; i<data.Count; ++i)
            {
                try
                {
                    PointD pt = data[i];
                    if ( !Double.IsNaN(pt.X) && !Double.IsNaN(pt.Y) )
                    {
                        PointF xPos = xAxis.WorldToPhysical( pt.X, false);
                        PointF yPos = yAxis.WorldToPhysical( pt.Y, false);
                        Marker.Draw( g, (int)xPos.X, (int)yPos.Y );
                        if ( textData[i] != "" )
                        {
                            SizeF size = g.MeasureString( textData[i], this.Font );
                            switch (labelTextPosition_)
                            {
                                case LabelPositions.Above:
                                    g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width/2,yPos.Y-size.Height-Marker.Size*2/3));
                                    break;
                                case LabelPositions.Below:
                                    g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width/2,yPos.Y+Marker.Size*2/3));
                                    break;
                                case LabelPositions.Left:
                                    g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X-size.Width-Marker.Size*2/3,yPos.Y-size.Height/2));
                                    break;
                                case LabelPositions.Right:
                                    g.DrawString( textData[i], font_, Brushes.Black, new PointF(xPos.X+Marker.Size*2/3,yPos.Y-size.Height/2));
                                    break;
                            }
                        }
                    }
                }
                catch
                {
                    throw new NPlotException("Error in TextPlot.Draw");
                }
            }
        }
示例#32
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( this.DataSource, this.DataMember, this.OrdinateDataBottom, this.AbscissaData );

            SequenceAdapter dataTop_ =
                new SequenceAdapter( this.DataSource, this.DataMember, this.OrdinateDataTop, this.AbscissaData );

            Axis axis = dataTop_.SuggestYAxis();
            axis.LUB(dataBottom_.SuggestYAxis());
            return axis;
        }
示例#33
0
文件: BarPlot.cs 项目: parnham/NPlot
        /// <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 ();
        }