Ejemplo n.º 1
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)
            {
                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, (int)xPos.X,(int)yStart.Y, (int)xPos.X,(int)yPos.Y );
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <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 );
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
                            Brush brush = new SolidBrush(Color.Black);
                            switch (labelTextPosition_)
                            {
                            case LabelPositions.Above:
                                g.DrawString(textData[i], font_, brush, xPos.X - size.Width / 2, yPos.Y - size.Height - Marker.Size * 2 / 3);
                                break;

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

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

                            case LabelPositions.Right:
                                g.DrawString(textData[i], font_, brush, xPos.X + Marker.Size * 2 / 3, yPos.Y - size.Height / 2);
                                break;
                            }
                        }
                    }
                }
                catch
                {
                    throw new NPlotException("Error in TextPlot.Draw");
                }
            }
        }
Ejemplo n.º 6
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());
            }
        }
Ejemplo n.º 7
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 || 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), (int)yPos1.Y, (int)(middle+width/2.0f), (int)yPos2.Y );
                    }
                    else
                    {
                        g.DrawLine( Pen, (int)xPos1.X, (int)yPos1.Y, (int)xPos2.X, (int)yPos2.Y );
                    }
                }

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

            }
        }
Ejemplo n.º 8
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 );

            }
        }
Ejemplo n.º 9
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)
            {
                Point physical = t.Transform(data[0]);

                if (drawShadow)
                {
                    g.DrawLine(shadowPen,
                               (int)(physical.X - 0.5f + this.ShadowOffset.X),
                               physical.Y + this.ShadowOffset.Y,
                               (int)(physical.X + 0.5f + this.ShadowOffset.X),
                               physical.Y + this.ShadowOffset.Y);
                }
                else
                {
                    g.DrawLine(Pen, (int)(physical.X - 0.5f), physical.Y, (int)(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.
                    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)
                    {
                        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);
                    }
                }
            }
        }
Ejemplo n.º 10
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 || 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), (int)yPos1.Y, (int)(middle + width / 2.0f), (int)yPos2.Y);
                    }
                    else
                    {
                        g.DrawLine(Pen, (int)xPos1.X, (int)yPos1.Y, (int)xPos2.X, (int)yPos2.Y);
                    }
                }

                if (!this.hideVerticalSegments_)
                {
                    g.DrawLine(Pen, (int)xPos2.X, (int)yPos2.Y, (int)xPos3.X, (int)yPos3.Y);
                }
            }
        }
Ejemplo n.º 11
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);
            }
        }
Ejemplo n.º 12
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( this.DataSource, this.DataMember, this.OrdinateData, this.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;
        }
Ejemplo n.º 13
0
        /// <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;
        }
Ejemplo n.º 14
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)
            {
                Point physical = t.Transform( data[0] );

                if (drawShadow)
                {
                    g.DrawLine( shadowPen,
                        (int)(physical.X - 0.5f + this.ShadowOffset.X),
                        physical.Y + this.ShadowOffset.Y,
                        (int)(physical.X + 0.5f + this.ShadowOffset.X),
                        physical.Y + this.ShadowOffset.Y );
                }
                else
                {
                    g.DrawLine( Pen, (int)(physical.X-0.5f), physical.Y, (int)(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.
                    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)
                    {
                        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 );
                    }
                }
            }
        }
Ejemplo n.º 15
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 );
                            Brush brush = new SolidBrush(Color.Black);
                            switch (labelTextPosition_)
                            {
                                case LabelPositions.Above:
                                    g.DrawString( textData[i], font_, brush, xPos.X-size.Width/2,yPos.Y-size.Height-Marker.Size*2/3);
                                    break;
                                case LabelPositions.Below:
                                    g.DrawString(textData[i], font_, brush, xPos.X - size.Width / 2, yPos.Y + Marker.Size * 2 / 3);
                                    break;
                                case LabelPositions.Left:
                                    g.DrawString(textData[i], font_, brush, xPos.X - size.Width - Marker.Size * 2 / 3, yPos.Y - size.Height / 2);
                                    break;
                                case LabelPositions.Right:
                                    g.DrawString(textData[i], font_, brush, xPos.X + Marker.Size * 2 / 3, yPos.Y - size.Height / 2);
                                    break;
                            }
                        }
                    }
                }
                catch
                {
                    throw new NPlotException("Error in TextPlot.Draw");
                }
            }
        }
Ejemplo n.º 16
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;
        }
Ejemplo n.º 17
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)
            {
                Point physicalBottom = t.Transform( dataBottom[i] );
                Point 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 );
                }
            }
        }
Ejemplo n.º 18
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();
            }
        }
Ejemplo n.º 19
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( this.DataSource, this.DataMember, this.OrdinateData, this.AbscissaData );

            return data.SuggestYAxis();
        }
Ejemplo n.º 20
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)
            {
                Point[] points = new Point[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)
            {
                Point[] points = new Point[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;
                Point[] points = new Point[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");
            }
        }