예제 #1
0
        /// <summary>
        /// Constructs the optimal ITransform2D object for the supplied x and y axes.
        /// </summary>
        /// <param name="xAxis">The xAxis to use for the world to physical transform.</param>
        /// <param name="yAxis">The yAxis to use for the world to physical transform.</param>
        /// <returns>An ITransform2D derived object for converting from world to physical coordinates.</returns>
        public static ITransform2D GetTransformer( PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            ITransform2D ret = null;

            //			if (xAxis.Axis.IsLinear && yAxis.Axis.IsLinear && !xAxis.Axis.Reversed && !yAxis.Axis.Reversed)
            //				ret = new FastTransform2D( xAxis, yAxis );
            //			else
            //				ret = new DefaultTransform2D( xAxis, yAxis );

            ret = new DefaultTransform2D( xAxis, yAxis );

            return ret;
        }
예제 #2
0
        /// <summary>
        /// Construct from a fully-blown physical axis.
        /// </summary>
        /// <param name="physicalAxis">the physical axis to get initial values from.</param>
        public PageAlignedPhysicalAxis( PhysicalAxis physicalAxis )
        {
            worldMin_ = physicalAxis.Axis.WorldMin;
            worldMax_ = physicalAxis.Axis.WorldMax;
            worldLength_ = worldMax_ - worldMin_;

            if ( physicalAxis.PhysicalMin.X == physicalAxis.PhysicalMax.X )
            {
                pMin_ = physicalAxis.PhysicalMin.Y;
                pMax_ = physicalAxis.PhysicalMax.Y;
            }
            else if ( physicalAxis.PhysicalMin.Y == physicalAxis.PhysicalMax.Y )
            {
                pMin_ = physicalAxis.PhysicalMin.X;
                pMax_ = physicalAxis.PhysicalMax.X;
            }
            else
            {
                throw new FlorenceException( "Physical axis is not page aligned" );
            }

            pLength_ = pMax_ - pMin_;
        }
예제 #3
0
        /// <summary>
        /// Draws the marker on a plot surface.
        /// </summary>
        /// <param name="g">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( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            PointF point = new PointF(
                xAxis.WorldToPhysical( x_, true ).X,
                yAxis.WorldToPhysical( y_, true ).Y );

            marker_.Draw( g, (int)point.X, (int)point.Y );
        }
예제 #4
0
        /// <summary>
        /// Does all the work in drawing grid lines.
        /// </summary>
        /// <param name="g">The graphics surface on which to render.</param>
        /// <param name="axis">TODO</param>
        /// <param name="orthogonalAxis">TODO</param>
        /// <param name="a">the list of world values to draw grid lines at.</param>
        /// <param name="horizontal">true if want horizontal lines, false otherwise.</param>
        /// <param name="p">the pen to use to draw the grid lines.</param>
        private void DrawGridLines( 
			Graphics g, PhysicalAxis axis, PhysicalAxis orthogonalAxis,
			System.Collections.ArrayList a, bool horizontal, Pen p )
        {
            for (int i=0; i<a.Count; ++i)
            {
                PointF p1 = axis.WorldToPhysical((double)a[i], true);
                PointF p2 = p1;
                PointF p3 = orthogonalAxis.PhysicalMax;
                PointF p4 = orthogonalAxis.PhysicalMin;
                if (horizontal)
                {
                    p1.Y = p4.Y;
                    p2.Y = p3.Y;
                }
                else
                {
                    p1.X = p4.X;
                    p2.X = p3.X;
                }
                // note: casting all drawing was necessary for sane display. why?
                g.DrawLine( p, (int)p1.X, (int)p1.Y, (int)p2.X, (int)p2.Y );
            }
        }
예제 #5
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="xAxis">The x-axis to use for transforms</param>
 /// <param name="yAxis">The y-axis to use for transforms</param>
 public DefaultTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)
 {
     xAxis_ = xAxis;
     yAxis_ = yAxis;
 }
예제 #6
0
            /// <summary>
            /// Applies the constraint to the axes.
            /// </summary>
            /// <param name="pXAxis1">The bottom x-axis.</param>
            /// <param name="pYAxis1">The left y-axis.</param>
            /// <param name="pXAxis2">The top x-axis.</param>
            /// <param name="pYAxis2">The right y-axis.</param>
            public override void ApplyConstraint( 
				PhysicalAxis pXAxis1, PhysicalAxis pYAxis1, 
				PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
            {
                int desiredLength = (int)(pXAxis1.Axis.WorldLength / (double)this.pWorldLength_);
                int currentLength = pXAxis1.PhysicalLength;
                int delta = currentLength - desiredLength;

                int changeLeft = delta / 2;
                int changeRight = delta / 2;
                if (this.holdFixedY_ != null)
                {
                    if ( (PlotSurface2D.YAxisPosition)this.holdFixedY_ == PlotSurface2D.YAxisPosition.Left )
                    {
                        changeLeft = 0;
                        changeRight = delta;
                    }
                    else
                    {
                        changeLeft = delta;
                        changeRight = 0;
                    }
                }

                pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X+changeLeft, pXAxis1.PhysicalMin.Y );
                pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X-changeRight, pXAxis1.PhysicalMax.Y );
                pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X+changeLeft, pXAxis2.PhysicalMin.Y );
                pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X-changeRight, pXAxis2.PhysicalMax.Y );

                pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X+changeLeft, pYAxis1.PhysicalMin.Y );
                pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X+changeLeft, pYAxis1.PhysicalMax.Y );
                pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X-changeRight, pYAxis2.PhysicalMin.Y );
                pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X-changeRight, pYAxis2.PhysicalMax.Y );
            }
예제 #7
0
        /// <summary>
        /// Draw on to the supplied graphics surface against the supplied axes.
        /// </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>
        /// <remarks>TODO: block positions may be off by a pixel or so. maybe. Re-think calculations</remarks>
        public void Draw(Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            if (data_ == null || data_.GetLength(0) == 0 || data_.GetLength(1) == 0)
            {
                return;
            }

            double worldWidth          = xAxis.Axis.WorldMax - xAxis.Axis.WorldMin;
            double numBlocksHorizontal = worldWidth / this.xStep_;
            double worldHeight         = yAxis.Axis.WorldMax - yAxis.Axis.WorldMin;
            double numBlocksVertical   = worldHeight / this.yStep_;

            double physicalWidth = xAxis.PhysicalMax.X - xAxis.PhysicalMin.X;
            double blockWidth    = physicalWidth / numBlocksHorizontal;
            bool   wPositive     = true;

            if (blockWidth < 0.0)
            {
                wPositive = false;
            }
            blockWidth = Math.Abs(blockWidth) + 1;

            double physicalHeight = yAxis.PhysicalMax.Y - yAxis.PhysicalMin.Y;
            double blockHeight    = physicalHeight / numBlocksVertical;
            bool   hPositive      = true;

            if (blockHeight < 0.0)
            {
                hPositive = false;
            }
            blockHeight = Math.Abs(blockHeight) + 1;

            for (int i = 0; i < data_.GetLength(0); ++i)
            {
                for (int j = 0; j < data_.GetLength(1); ++j)
                {
                    double wX = (double)j * this.xStep_ + xStart_;
                    double wY = (double)i * this.yStep_ + yStart_;
                    if (!hPositive)
                    {
                        wY += yStep_;
                    }
                    if (!wPositive)
                    {
                        wX += xStep_;
                    }

                    if (this.center_)
                    {
                        wX -= this.xStep_ / 2.0;
                        wY -= this.yStep_ / 2.0;
                    }
                    Pen p = new Pen(this.Gradient.GetColor((data_[i, j] - this.dataMin_) / (this.dataMax_ - this.dataMin_)));
                    int x = (int)xAxis.WorldToPhysical(wX, false).X;
                    int y = (int)yAxis.WorldToPhysical(wY, false).Y;
                    g.FillRectangle(p.Brush,
                                    x,
                                    y,
                                    (int)blockWidth,
                                    (int)blockHeight);
                    //g.DrawRectangle(Pens.White,x,y,(int)blockWidth,(int)blockHeight);
                }
            }
        }
예제 #8
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
                    {
                        // Ensure that we do not go outside of the graphics capabilities
                        if ((Math.Abs(p1.X) + Math.Abs(p2.X)) < 0x4000007F && (Math.Abs(p1.Y) + Math.Abs(p2.Y)) < 0x4000007F)
                        {
                            g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y);
                        }
                    }
                }
            }
        }
예제 #9
0
        private void Init()
        {
            drawables_ = new ArrayList();
            xAxisPositions_ = new ArrayList();
            yAxisPositions_ = new ArrayList();
            zPositions_ = new ArrayList();
            ordering_ = new SortedList();

            try
            {
                FontFamily fontFamily = new FontFamily("Arial");
                TitleFont = new Font(fontFamily, 14, FontStyle.Regular, GraphicsUnit.Pixel);
            }
            catch (System.ArgumentException)
            {
                throw new FlorenceException("Error: Arial font is not installed on this system");
            }

            padding_ = 10;
            title_ = "";
            autoScaleTitle_ = false;
            autoScaleAutoGeneratedAxes_ = false;
            xAxis1_ = null;
            xAxis2_ = null;
            yAxis1_ = null;
            yAxis2_ = null;
            pXAxis1Cache_ = null;
            pYAxis1Cache_ = null;
            pXAxis2Cache_ = null;
            pYAxis2Cache_ = null;
            titleBrush_ = new SolidBrush( Color.Black );
            plotBackColor_ = Color.White;
            outerBackColor = null;
            this.legend_ = null;

            smoothingMode_ = System.Drawing.Drawing2D.SmoothingMode.None;

            axesConstraints_ = new ArrayList();
        }
예제 #10
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
                    {
                        // Ensure that we do not go outside of the graphics capabilities
                        if ((Math.Abs(p1.X) + Math.Abs(p2.X)) < 0x4000007F && (Math.Abs(p1.Y) + Math.Abs(p2.Y)) < 0x4000007F)
                        {
                            g.DrawLine(Pen, p1.X, p1.Y, p2.X, p2.Y);
                        }
                    }
                }
            }
        }
예제 #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;
                RectangleF r    = new RectangleF(xPos1.X + xoff, yPos1.Y, width - 2 * xoff, 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);
            }
        }
예제 #12
0
 private static Point WorldToPhysical(PointD world_point, PhysicalAxis xAxis, PhysicalAxis yAxis)
 {
     return new Point((int)xAxis.WorldToPhysical(world_point.X, false).X, (int)yAxis.WorldToPhysical(world_point.Y, false).Y);
 }
예제 #13
0
        /// <summary>
        /// Draws the line 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(System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            int xMin = xAxis.PhysicalMin.X;
            int xMax = xAxis.PhysicalMax.X;

            int yMin = yAxis.PhysicalMin.Y;
            int yMax = yAxis.PhysicalMax.Y;

            PointD[] world_points = new PointD[2];
            int point_index = 0;
            // intercept point on left border
            var value_at_left_border = this.Intercept + this.Slope * xAxis.Axis.WorldMin;
            if (value_at_left_border >= yAxis.Axis.WorldMin && value_at_left_border < yAxis.Axis.WorldMax)
            {
                world_points[point_index] = new PointD(xAxis.Axis.WorldMin, value_at_left_border);
                point_index += 1;
            }

            // intercept point on right border
            var value_at_right_border = this.Intercept + this.Slope * xAxis.Axis.WorldMax;
            if (value_at_right_border > yAxis.Axis.WorldMin && value_at_right_border <= yAxis.Axis.WorldMax)
            {
                world_points[point_index] = new PointD(xAxis.Axis.WorldMax, value_at_right_border);
                point_index += 1;
            }

            // intercept point on bottom border
            var value_at_bottom_border = (yAxis.Axis.WorldMin - this.Intercept) / this.Slope;
            if (value_at_bottom_border > xAxis.Axis.WorldMin && value_at_bottom_border <= xAxis.Axis.WorldMax)
            {
                world_points[point_index] = new PointD(value_at_bottom_border, yAxis.Axis.WorldMin);
                point_index += 1;
            }

            // intercept point on top border
            var value_at_top_border = (yAxis.Axis.WorldMax - this.Intercept) / this.Slope;
            if (value_at_top_border >= xAxis.Axis.WorldMin && value_at_top_border < xAxis.Axis.WorldMax)
            {
                world_points[point_index] = new PointD(value_at_top_border, yAxis.Axis.WorldMax);
            }

            var physical_point = new Point[2];
            physical_point[0] = WorldToPhysical(world_points[0], xAxis, yAxis);
            physical_point[1] = WorldToPhysical(world_points[1], xAxis, yAxis);

            g.DrawLine(this.Pen, physical_point[0], physical_point[1]);

            // todo:  clip and proper logic for flipped axis min max.
        }
예제 #14
0
        /// <summary>
        /// Applies the constraint to the axes. Must be overriden.
        /// </summary>
        /// <param name="pXAxis1">The bottom x-axis.</param>
        /// <param name="pYAxis1">The left y-axis.</param>
        /// <param name="pXAxis2">The top x-axis.</param>
        /// <param name="pYAxis2">The right y-axis.</param>
        public abstract void ApplyConstraint( 
			PhysicalAxis pXAxis1, PhysicalAxis pYAxis1, 
			PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 );
예제 #15
0
            /// <summary>
            /// Applies the constraint to the axes.
            /// </summary>
            /// <param name="pXAxis1">The bottom x-axis.</param>
            /// <param name="pYAxis1">The left y-axis.</param>
            /// <param name="pXAxis2">The top x-axis.</param>
            /// <param name="pYAxis2">The right y-axis.</param>
            public override void ApplyConstraint( 
				PhysicalAxis pXAxis1, PhysicalAxis pYAxis1, 
				PhysicalAxis pXAxis2, PhysicalAxis pYAxis2 )
            {
                int desiredLength = (int)(pYAxis1.Axis.WorldLength / this.pWorldLength_);
                int currentLength = pYAxis1.PhysicalLength;
                int delta = currentLength - desiredLength;

                int changeBottom = -delta / 2;
                int changeTop = -delta / 2;
                if (this.holdFixedX_ != null)
                {
                    if ( (PlotSurface2D.XAxisPosition)this.holdFixedX_ == PlotSurface2D.XAxisPosition.Bottom )
                    {
                        changeBottom = 0;
                        changeTop = -delta;
                    }
                    else
                    {
                        changeBottom = -delta;
                        changeTop = 0;
                    }
                }

                pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X, pYAxis1.PhysicalMin.Y+changeBottom );
                pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X, pYAxis1.PhysicalMax.Y-changeTop );
                pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X, pYAxis2.PhysicalMin.Y+changeBottom );
                pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X, pYAxis2.PhysicalMax.Y-changeTop );

                pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMin.Y+changeBottom );
                pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X, pXAxis1.PhysicalMax.Y+changeBottom );
                pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X, pXAxis2.PhysicalMin.Y-changeTop );
                pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X, pXAxis2.PhysicalMax.Y-changeTop );
            }
예제 #16
0
        /// <summary>
        /// Draws the candle plot on a GDI+ surface agains 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 )
        {
            CandleDataAdapter cd = new CandleDataAdapter( this.DataSource, this.DataMember,
                this.AbscissaData, this.OpenData, this.LowData, this.HighData, this.CloseData );

            Brush bearishBrush = new SolidBrush( BearishColor );
            Brush bullishBrush = new SolidBrush( BullishColor );

            uint offset = 0;
            if (this.centered_)
            {
                offset = (uint)(CalculatePhysicalSeparation(cd,xAxis) / 2.0f);
            }

            uint addAmount = (uint)StickWidth/2;
            uint stickWidth = (uint)StickWidth;

            if (StickWidth == AutoScaleStickWidth)
            {
                // default
                addAmount = 2;
                stickWidth = 4;

                float minDist = CalculatePhysicalSeparation( cd, xAxis );

                addAmount = (uint)(minDist / 3);
                stickWidth = addAmount * 2;
            }

            Pen	p =	new	Pen(this.color_);

            /*
            // brant hyatt proposed.
            if (this.Style == Styles.Stick)
            {
                p.Width = stickWidth;
             				addAmount = stickWidth + 2;
            }
            */

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

                PointOLHC point = (PointOLHC)cd[i];
                if ( (!double.IsNaN (point.Open)) && (!double.IsNaN(point.High)) && (!double.IsNaN (point.Low)) && (!double.IsNaN(point.Close)) )
                {
                    int xPos = (int)(xAxis.WorldToPhysical( point.X, false )).X;

                    if (xPos + offset + addAmount < xAxis.PhysicalMin.X || xAxis.PhysicalMax.X < xPos + offset - addAmount)
                    {
                        continue;
                    }

                    int yPos1 = (int)(yAxis.WorldToPhysical( point.Low, false )).Y;
                    int yPos2 = (int)(yAxis.WorldToPhysical( point.High, false )).Y;
                    int yPos3 = (int)(yAxis.WorldToPhysical( point.Open, false )).Y;
                    int yPos4 = (int)(yAxis.WorldToPhysical( point.Close, false )).Y;

                    if (this.Style == Styles.Stick)
                    {
                        /*
                        // brant hyatt proposed.
                        if (i > 0)
                        {
                            if ( ((PointOLHC)cd[i]).Close > ((PointOLHC)cd[i-1]).Close)
                            {
                                p.Color = BullishColor;
                            }
                            else
                            {
                                p.Color = BearishColor;
                            }
                        }
                        */

                        g.DrawLine( p, xPos+offset, yPos1, xPos+offset, yPos2 );
                        g.DrawLine( p, xPos-addAmount+offset, yPos3, xPos+offset, yPos3 );
                        g.DrawLine( p, xPos+offset, yPos4, xPos+addAmount+offset, yPos4 );
                    }
                    else if (this.Style == Styles.Filled)
                    {
                        g.DrawLine( p, xPos+offset, yPos1, xPos+offset, yPos2 );
                        if (yPos3 > yPos4)
                        {
                            g.FillRectangle( bullishBrush, xPos-addAmount+offset, yPos4, stickWidth, yPos3 - yPos4 );
                            g.DrawRectangle( p, xPos-addAmount+offset, yPos4, stickWidth, yPos3 - yPos4 );
                        }
                        else if (yPos3 < yPos4)
                        {
                            g.FillRectangle( bearishBrush, xPos-addAmount+offset, yPos3, stickWidth, yPos4 - yPos3 );
                            g.DrawRectangle( p, xPos-addAmount+offset, yPos3, stickWidth, yPos4 - yPos3 );
                        }
                        else
                        {
                            g.DrawLine( p, xPos-addAmount+offset, yPos3, xPos-addAmount+stickWidth+offset, yPos3 );
                        }
                    }
                }
            }
        }
예제 #17
0
        /// <summary>
        /// Updates the PlotSurface2D axes to compensate for the legend.
        /// </summary>
        /// <param name="pXAxis1">the bottom x axis</param>
        /// <param name="pYAxis1">the left y axis</param>
        /// <param name="pXAxis2">the top x axis</param>
        /// <param name="pYAxis2">the right y axis</param>
        /// <param name="plots">list of plots.</param>
        /// <param name="scale">scale parameter (for text and other)</param>
        /// <param name="padding">padding around plot within bounds.</param>
        /// <param name="bounds">graphics surface bounds</param>
        /// <param name="position">legend position</param>
        public void UpdateAxesPositions(
            PhysicalAxis pXAxis1,
            PhysicalAxis pYAxis1,
            PhysicalAxis pXAxis2,
            PhysicalAxis pYAxis2,
            ArrayList plots,
            float scale, int padding, Rectangle bounds,
            out Point position)
        {
            int leftIndent   = 0;
            int rightIndent  = 0;
            int bottomIndent = 0;
            int topIndent    = 0;

            position = new Point(0, 0);

            // now determine if legend should change any of these (legend should be fully
            // visible at all times), and draw legend.

            Rectangle legendWidthHeight = this.GetBoundingBox(new Point(0, 0), plots, scale);

            if (legendWidthHeight.Width > bounds.Width)
            {
                legendWidthHeight.Width = bounds.Width;
            }

            // (1) calculate legend position.

            // y
            position.Y = this.yOffset_;

            if (this.xAttach_ == PlotSurface2D.XAxisPosition.Bottom)
            {
                position.Y += pYAxis1.PhysicalMin.Y;
                if (this.horizontalEdgePlacement_ == Legend.Placement.Inside)
                {
                    position.Y -= legendWidthHeight.Height;
                }
            }
            else
            {
                position.Y += pYAxis1.PhysicalMax.Y;
                if (this.horizontalEdgePlacement_ == Legend.Placement.Outside)
                {
                    position.Y -= legendWidthHeight.Height;
                }
            }

            // x
            position.X = this.xOffset_;

            if (this.yAttach_ == PlotSurface2D.YAxisPosition.Left)
            {
                if (this.verticalEdgePlacement_ == Legend.Placement.Outside)
                {
                    position.X -= legendWidthHeight.Width;
                }
                position.X += pXAxis1.PhysicalMin.X;
            }
            else
            {
                if (this.verticalEdgePlacement_ == Legend.Placement.Inside)
                {
                    position.X -= legendWidthHeight.Width;
                }
                position.X += pXAxis1.PhysicalMax.X;
            }


            // determine update amounts for axes

            if (!this.neverShiftAxes_)
            {
                if (position.X < padding)
                {
                    int changeAmount = -position.X + padding;
                    // only allow axes to move away from bounds.
                    if (changeAmount > 0)
                    {
                        leftIndent = changeAmount;
                    }
                    position.X += changeAmount;
                }

                if (position.X + legendWidthHeight.Width > bounds.Right - padding)
                {
                    int changeAmount = (position.X - bounds.Right + legendWidthHeight.Width + padding);
                    // only allow axes to move away from bounds.
                    if (changeAmount > 0.0f)
                    {
                        rightIndent = changeAmount;
                    }
                    position.X -= changeAmount;
                }

                if (position.Y < padding)
                {
                    int changeAmount = -position.Y + padding;
                    // only allow axes to move away from bounds.
                    if (changeAmount > 0.0f)
                    {
                        topIndent = changeAmount;
                    }
                    position.Y += changeAmount;
                }

                if (position.Y + legendWidthHeight.Height > bounds.Bottom - padding)
                {
                    int changeAmount = (position.Y - bounds.Bottom + legendWidthHeight.Height + padding);
                    // only allow axes to move away from bounds.
                    if (changeAmount > 0.0f)
                    {
                        bottomIndent = changeAmount;
                    }
                    position.Y -= changeAmount;
                }

                // update axes.

                pXAxis1.PhysicalMin = new Point(pXAxis1.PhysicalMin.X + leftIndent, pXAxis1.PhysicalMin.Y - bottomIndent);
                pXAxis1.PhysicalMax = new Point(pXAxis1.PhysicalMax.X - rightIndent, pXAxis1.PhysicalMax.Y - bottomIndent);
                pYAxis1.PhysicalMin = new Point(pYAxis1.PhysicalMin.X + leftIndent, pYAxis1.PhysicalMin.Y - bottomIndent);
                pYAxis1.PhysicalMax = new Point(pYAxis1.PhysicalMax.X + leftIndent, pYAxis1.PhysicalMax.Y + topIndent);

                pXAxis2.PhysicalMin = new Point(pXAxis2.PhysicalMin.X + leftIndent, pXAxis2.PhysicalMin.Y + topIndent);
                pXAxis2.PhysicalMax = new Point(pXAxis2.PhysicalMax.X - rightIndent, pXAxis2.PhysicalMax.Y + topIndent);
                pYAxis2.PhysicalMin = new Point(pYAxis2.PhysicalMin.X - rightIndent, pYAxis2.PhysicalMin.Y - bottomIndent);
                pYAxis2.PhysicalMax = new Point(pYAxis2.PhysicalMax.X - rightIndent, pYAxis2.PhysicalMax.Y + topIndent);
            }
        }
예제 #18
0
        /// <summary>
        /// Draw the the PlotSurface2D and all contents [axes, drawables, and legend] on the 
        /// supplied graphics surface.
        /// </summary>
        /// <param name="g">The graphics surface on which to draw.</param>
        /// <param name="bounds">A bounding box on this surface that denotes the area on the
        /// surface to confine drawing to.</param>
        public void Draw( Graphics g, Rectangle bounds )
        {
            // Draw background
            if (outerBackColor != null && outerBackColor != Color.Transparent)
                g.FillRectangle(new SolidBrush(outerBackColor.Value), bounds);
            else if (outerBackColor == null)
            {
                if (plotBackColor_ != null)
                    g.FillRectangle(new SolidBrush(plotBackColor_.Value), bounds);
                else if (plotBackBrush_ != null)
                    g.FillRectangle(plotBackBrush_.Get(bounds), bounds);
                else
                    g.FillRectangle(new SolidBrush(Color.White), bounds);
            }

            // determine font sizes and tick scale factor.
            float scale = DetermineScaleFactor( bounds.Width, bounds.Height );

            // if there is nothing to plot, return.
            if ( drawables_.Count == 0 )
            {
                // draw title
                float x_center = (bounds.Left + bounds.Right)/2.0f;
                float y_center = (bounds.Top + bounds.Bottom)/2.0f;
                Font scaled_font;
                if (this.AutoScaleTitle)
                {
                    scaled_font = Utils.ScaleFont( titleFont_, scale );
                }
                else
                {
                    scaled_font = titleFont_;
                }
                g.DrawString( title_, scaled_font, this.titleBrush_, new PointF(x_center,y_center), titleDrawFormat_ );

                return;
            }

            // determine the [non physical] axes to draw based on the axis properties set.
            Axis xAxis1 = null;
            Axis xAxis2 = null;
            Axis yAxis1 = null;
            Axis yAxis2 = null;
            this.DetermineAxesToDraw( out xAxis1, out xAxis2, out yAxis1, out yAxis2 );

            // apply scale factor to axes as desired.

            if (xAxis1.AutoScaleTicks)
            {
                xAxis1.TickScale = scale;
            }
            if (xAxis1.AutoScaleText)
            {
                xAxis1.FontScale = scale;
            }
            if (yAxis1.AutoScaleTicks)
            {
                yAxis1.TickScale = scale;
            }
            if (yAxis1.AutoScaleText)
            {
                yAxis1.FontScale = scale;
            }
            if (xAxis2.AutoScaleTicks)
            {
                xAxis2.TickScale = scale;
            }
            if (xAxis2.AutoScaleText)
            {
                xAxis2.FontScale = scale;
            }
            if (yAxis2.AutoScaleTicks)
            {
                yAxis2.TickScale = scale;
            }
            if (yAxis2.AutoScaleText)
            {
                yAxis2.FontScale = scale;
            }

            // determine the default physical positioning of those axes.
            PhysicalAxis pXAxis1 = null;
            PhysicalAxis pYAxis1 = null;
            PhysicalAxis pXAxis2 = null;
            PhysicalAxis pYAxis2 = null;
            this.DeterminePhysicalAxesToDraw(
                bounds, xAxis1, xAxis2, yAxis1, yAxis2,
                out pXAxis1, out pXAxis2, out pYAxis1, out pYAxis2 );

            float oldXAxis2Height = pXAxis2.PhysicalMin.Y;

            // Apply axes constraints
            for (int i=0; i<axesConstraints_.Count; ++i)
            {
                ((AxesConstraint)axesConstraints_[i]).ApplyConstraint(
                    pXAxis1, pYAxis1, pXAxis2, pYAxis2 );
            }

            /////////////////////////////////////////////////////////////////////////
            // draw legend if have one.
            // Note: this will update axes if necessary.
            Point legendPosition = new Point(0,0);
            if (this.legend_ != null)
            {
                legend_.UpdateAxesPositions(
                    pXAxis1, pYAxis1, pXAxis2, pYAxis2,
                    this.drawables_, scale, this.padding_, bounds,
                    out legendPosition );
            }

            float newXAxis2Height = pXAxis2.PhysicalMin.Y;
            float titleExtraOffset = oldXAxis2Height - newXAxis2Height;

            // now we are ready to define the bounding box for the plot area (to use in clipping
            // operations.
            plotAreaBoundingBoxCache_ = new Rectangle(
                Math.Min( pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMax.X ),
                Math.Min( pYAxis1.PhysicalMax.Y, pYAxis1.PhysicalMin.Y ),
                Math.Abs( pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X + 1 ),
                Math.Abs( pYAxis1.PhysicalMin.Y - pYAxis1.PhysicalMax.Y + 1 )
            );
            bbXAxis1Cache_ = pXAxis1.GetBoundingBox();
            bbXAxis2Cache_ = pXAxis2.GetBoundingBox();
            bbYAxis1Cache_ = pYAxis1.GetBoundingBox();
            bbYAxis2Cache_ = pYAxis2.GetBoundingBox();

            // Fill in the background.
            if ( this.plotBackColor_ != null )
            {
                g.FillRectangle(
                    new System.Drawing.SolidBrush( (Color)this.plotBackColor_ ),
                    (Rectangle)plotAreaBoundingBoxCache_ );
            }
            else if (this.plotBackBrush_ != null)
            {
                g.FillRectangle(
                    this.plotBackBrush_.Get( (Rectangle)plotAreaBoundingBoxCache_ ),
                    (Rectangle)plotAreaBoundingBoxCache_ );
            }
            else if (this.plotBackImage_ != null)
            {
                g.DrawImage(
                    Utils.TiledImage( this.plotBackImage_ , new Size(
                        ((Rectangle)plotAreaBoundingBoxCache_).Width,
                        ((Rectangle)plotAreaBoundingBoxCache_).Height ) ),
                    (Rectangle)plotAreaBoundingBoxCache_ );
            }

            // draw title
            float xt = (pXAxis2.PhysicalMax.X + pXAxis2.PhysicalMin.X)/2.0f;
            float yt = bounds.Top + this.padding_ - titleExtraOffset;
            Font scaledFont;
            if (this.AutoScaleTitle)
            {
                scaledFont = Utils.ScaleFont( titleFont_, scale );
            }
            else
            {
                scaledFont = titleFont_;
            }
            g.DrawString( title_, scaledFont, this.titleBrush_,	new PointF(xt,yt), titleDrawFormat_ );

            //count number of new lines in title.
            int nlCount = 0;
            for (int i=0; i<title_.Length; ++i)
            {
                if (title_[i] == '\n')
                    nlCount += 1;
            }

            SizeF s = g.MeasureString(title_,scaledFont);
            bbTitleCache_ = new Rectangle( (int)(xt-s.Width/2), (int)(yt), (int)(s.Width), (int)(s.Height)*(nlCount+1) );

            // draw drawables..
            System.Drawing.Drawing2D.SmoothingMode smoothSave = g.SmoothingMode;

            g.SmoothingMode = this.smoothingMode_;

            bool legendDrawn = false;

            for ( int i_o = 0; i_o < ordering_.Count; ++i_o )
            {

                int i = (int)ordering_.GetByIndex(i_o);
                double zOrder = (double)ordering_.GetKey( i_o );
                if (zOrder > this.legendZOrder_)
                {
                    // draw legend.
                    if ( !legendDrawn && this.legend_ != null )
                    {
                        legend_.Draw( g, legendPosition, this.drawables_, scale );
                        legendDrawn = true;
                    }
                }

                IDrawable drawable = (IDrawable)drawables_[i];
                XAxisPosition xap = (XAxisPosition)xAxisPositions_[i];
                YAxisPosition yap = (YAxisPosition)yAxisPositions_[i];

                PhysicalAxis drawXAxis;
                PhysicalAxis drawYAxis;

                if ( xap == XAxisPosition.Bottom )
                {
                    drawXAxis = pXAxis1;
                }
                else
                {
                    drawXAxis = pXAxis2;
                }

                if ( yap == YAxisPosition.Left )
                {
                    drawYAxis = pYAxis1;
                }
                else
                {
                    drawYAxis = pYAxis2;
                }

                // set the clipping region.. (necessary for zoom)
                g.Clip = new Region((Rectangle)plotAreaBoundingBoxCache_);
                // plot.
                drawable.Draw( g, drawXAxis, drawYAxis );
                // reset it..
                g.ResetClip();
            }

            if ( !legendDrawn && this.legend_ != null )
            {
                legend_.Draw( g, legendPosition, this.drawables_, scale );
            }

            // cache the physical axes we used on this draw;
            this.pXAxis1Cache_ = pXAxis1;
            this.pYAxis1Cache_ = pYAxis1;
            this.pXAxis2Cache_ = pXAxis2;
            this.pYAxis2Cache_ = pYAxis2;

            g.SmoothingMode = smoothSave;

            // now draw axes.
            Rectangle axisBounds;
            pXAxis1.Draw( g, out axisBounds );
            pXAxis2.Draw( g, out axisBounds );
            pYAxis1.Draw( g, out axisBounds );
            pYAxis2.Draw( g, out axisBounds );

            #if DEBUG_BOUNDING_BOXES
            g.DrawRectangle( new Pen(Color.Orange), (Rectangle) bbXAxis1Cache_ );
            g.DrawRectangle( new Pen(Color.Orange), (Rectangle) bbXAxis2Cache_ );
            g.DrawRectangle( new Pen(Color.Orange), (Rectangle) bbYAxis1Cache_ );
            g.DrawRectangle( new Pen(Color.Orange), (Rectangle) bbYAxis2Cache_ );
            g.DrawRectangle( new Pen(Color.Red,5.0F),(Rectangle) plotAreaBoundingBoxCache_);
            //if(this.ShowLegend)g.DrawRectangle( new Pen(Color.Chocolate, 3.0F), (Rectangle) bbLegendCache_);
            g.DrawRectangle( new Pen(Color.DeepPink,2.0F), (Rectangle) bbTitleCache_);
            #endif
        }
예제 #19
0
        /// <summary>
        /// MouseDown method for AxisDrag interaction
        /// </summary>
        /// <param name="X">mouse X position</param>
        /// <param name="Y">mouse Y position</param>
        /// <param name="keys">mouse and keyboard modifiers</param>
        /// <param name="ps">the InteractivePlotSurface2D</param>
        public override bool DoMouseDown(int X, int Y, Modifier keys, InteractivePlotSurface2D ps)
        {
            // if the mouse is inside the plot area [the tick marks may be here,
            // and are counted as part of the axis], then don't invoke drag.
            if (ps.PlotAreaBoundingBoxCache.Contains(X, Y))
            {
                return false;
            }
            if ((keys & Modifier.Button1) != 0)
            {
                // see if hit with axis. NB Only one axis object will be returned
                ArrayList objects = ps.HitTest(new Point(X, Y));

                foreach (object o in objects)
                {
                    if (o is Florence.Axis)
                    {
                        dragging_ = true;
                        axis_ = (Axis)o;

                        if (ps.PhysicalXAxis1Cache.Axis == axis_)
                        {
                            physicalAxis_ = ps.PhysicalXAxis1Cache;
                            ps.plotCursor = CursorType.LeftRight;
                        }
                        else if (ps.PhysicalXAxis2Cache.Axis == axis_)
                        {
                            physicalAxis_ = ps.PhysicalXAxis2Cache;
                            ps.plotCursor = CursorType.LeftRight;
                        }
                        else if (ps.PhysicalYAxis1Cache.Axis == axis_)
                        {
                            physicalAxis_ = ps.PhysicalYAxis1Cache;
                            ps.plotCursor = CursorType.UpDown;
                        }
                        else if (ps.PhysicalYAxis2Cache.Axis == axis_)
                        {
                            physicalAxis_ = ps.PhysicalYAxis2Cache;
                            ps.plotCursor = CursorType.UpDown;
                        }

                        startPoint_ = new Point(X, Y);	// don't combine these - Mono
                        lastPoint_ = startPoint_;		// bug #475205 prior to 2.4
                        // evaluate focusRatio about which axis is expanded
                        float x = startPoint_.X - physicalAxis_.PhysicalMin.X;
                        float y = startPoint_.Y - physicalAxis_.PhysicalMin.Y;
                        double r = Math.Sqrt(x * x + y * y);
                        focusRatio_ = r / physicalAxis_.PhysicalLength;

                        return false;
                    }
                }
            }
            return false;
        }
예제 #20
0
        private void DeterminePhysicalAxesToDraw( Rectangle bounds, 
			Axis xAxis1, Axis xAxis2, Axis yAxis1, Axis yAxis2,
			out PhysicalAxis pXAxis1, out PhysicalAxis pXAxis2, 
			out PhysicalAxis pYAxis1, out PhysicalAxis pYAxis2 )
        {
            System.Drawing.Rectangle cb = bounds;

            pXAxis1 = new PhysicalAxis( xAxis1,
                new Point( cb.Left, cb.Bottom ), new Point( cb.Right, cb.Bottom ) );
            pYAxis1 = new PhysicalAxis( yAxis1,
                new Point( cb.Left, cb.Bottom ), new Point( cb.Left, cb.Top ) );
            pXAxis2 = new PhysicalAxis( xAxis2,
                new Point( cb.Left, cb.Top), new Point( cb.Right, cb.Top) );
            pYAxis2 = new PhysicalAxis( yAxis2,
                new Point( cb.Right, cb.Bottom ), new Point( cb.Right, cb.Top ) );

            int bottomIndent = padding_;
            if (!pXAxis1.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pXAxis1.GetBoundingBox();
                // finally determine its indentation from the bottom
                bottomIndent = bottomIndent + bb.Bottom - cb.Bottom;
            }

            int leftIndent = padding_;
            if (!pYAxis1.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pYAxis1.GetBoundingBox();
                // finally determine its indentation from the left
                leftIndent = leftIndent - bb.Left + cb.Left;
            }

            int topIndent = padding_;
            float scale = this.DetermineScaleFactor( bounds.Width, bounds.Height );
            int titleHeight;
            if (this.AutoScaleTitle)
            {
                titleHeight = Utils.ScaleFont(titleFont_, scale).Height;
            }
            else
            {
                titleHeight = titleFont_.Height;
            }

            //count number of new lines in title.
            int nlCount = 0;
            for (int i=0; i<title_.Length; ++i)
            {
                if (title_[i] == '\n')
                    nlCount += 1;
            }
            titleHeight = (int)( ((float)nlCount*0.75 + 1.0f) * (float)titleHeight);

            if (!pXAxis2.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pXAxis2.GetBoundingBox();
                topIndent = topIndent - bb.Top + cb.Top;

                // finally determine its indentation from the top
                // correct top indendation to take into account plot title
                if (title_ != "" )
                {
                    topIndent += (int)(titleHeight * 1.3f);
                }
            }

            int rightIndent = padding_;
            if (!pYAxis2.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pYAxis2.GetBoundingBox();

                // finally determine its indentation from the right
                rightIndent = (int)(rightIndent + bb.Right-cb.Right);
            }

            // now we have all the default calculated positions and we can proceed to
            // "move" the axes to their right places

            // primary axes (bottom, left)
            pXAxis1.PhysicalMin = new Point( cb.Left+leftIndent, cb.Bottom-bottomIndent );
            pXAxis1.PhysicalMax = new Point( cb.Right-rightIndent, cb.Bottom-bottomIndent );
            pYAxis1.PhysicalMin = new Point( cb.Left+leftIndent, cb.Bottom-bottomIndent );
            pYAxis1.PhysicalMax = new Point( cb.Left+leftIndent, cb.Top+topIndent );

            // secondary axes (top, right)
            pXAxis2.PhysicalMin = new Point( cb.Left+leftIndent, cb.Top+topIndent );
            pXAxis2.PhysicalMax = new Point( cb.Right-rightIndent, cb.Top+topIndent );
            pYAxis2.PhysicalMin = new Point( cb.Right-rightIndent, cb.Bottom-bottomIndent );
            pYAxis2.PhysicalMax = new Point( cb.Right-rightIndent, cb.Top+topIndent );
        }
예제 #21
0
        /// <summary>
        /// Draws the candle plot on a GDI+ surface agains 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)
        {
            CandleDataAdapter cd = new CandleDataAdapter(this.DataSource, this.DataMember,
                                                         this.AbscissaData, this.OpenData, this.LowData, this.HighData, this.CloseData);

            Brush bearishBrush = new SolidBrush(BearishColor);
            Brush bullishBrush = new SolidBrush(BullishColor);

            uint offset = 0;

            if (this.centered_)
            {
                offset = (uint)(CalculatePhysicalSeparation(cd, xAxis) / 2.0f);
            }

            uint addAmount  = (uint)StickWidth / 2;
            uint stickWidth = (uint)StickWidth;

            if (StickWidth == AutoScaleStickWidth)
            {
                // default
                addAmount  = 2;
                stickWidth = 4;

                float minDist = CalculatePhysicalSeparation(cd, xAxis);

                addAmount  = (uint)(minDist / 3);
                stickWidth = addAmount * 2;
            }

            Pen p = new     Pen(this.color_);

            /*
             * // brant hyatt proposed.
             * if (this.Style == Styles.Stick)
             * {
             *      p.Width = stickWidth;
             *      addAmount = stickWidth + 2;
             * }
             */

            for (int i = 0; i < cd.Count; ++i)
            {
                PointOLHC point = (PointOLHC)cd[i];
                if ((!double.IsNaN(point.Open)) && (!double.IsNaN(point.High)) && (!double.IsNaN(point.Low)) && (!double.IsNaN(point.Close)))
                {
                    int xPos = (int)(xAxis.WorldToPhysical(point.X, false)).X;

                    if (xPos + offset + addAmount < xAxis.PhysicalMin.X || xAxis.PhysicalMax.X < xPos + offset - addAmount)
                    {
                        continue;
                    }

                    int yPos1 = (int)(yAxis.WorldToPhysical(point.Low, false)).Y;
                    int yPos2 = (int)(yAxis.WorldToPhysical(point.High, false)).Y;
                    int yPos3 = (int)(yAxis.WorldToPhysical(point.Open, false)).Y;
                    int yPos4 = (int)(yAxis.WorldToPhysical(point.Close, false)).Y;

                    if (this.Style == Styles.Stick)
                    {
                        /*
                         * // brant hyatt proposed.
                         * if (i > 0)
                         * {
                         *      if ( ((PointOLHC)cd[i]).Close > ((PointOLHC)cd[i-1]).Close)
                         *      {
                         *              p.Color = BullishColor;
                         *      }
                         *      else
                         *      {
                         *              p.Color = BearishColor;
                         *      }
                         * }
                         */

                        g.DrawLine(p, xPos + offset, yPos1, xPos + offset, yPos2);
                        g.DrawLine(p, xPos - addAmount + offset, yPos3, xPos + offset, yPos3);
                        g.DrawLine(p, xPos + offset, yPos4, xPos + addAmount + offset, yPos4);
                    }
                    else if (this.Style == Styles.Filled)
                    {
                        g.DrawLine(p, xPos + offset, yPos1, xPos + offset, yPos2);
                        if (yPos3 > yPos4)
                        {
                            g.FillRectangle(bullishBrush, xPos - addAmount + offset, yPos4, stickWidth, yPos3 - yPos4);
                            g.DrawRectangle(p, xPos - addAmount + offset, yPos4, stickWidth, yPos3 - yPos4);
                        }
                        else if (yPos3 < yPos4)
                        {
                            g.FillRectangle(bearishBrush, xPos - addAmount + offset, yPos3, stickWidth, yPos4 - yPos3);
                            g.DrawRectangle(p, xPos - addAmount + offset, yPos3, stickWidth, yPos4 - yPos3);
                        }
                        else
                        {
                            g.DrawLine(p, xPos - addAmount + offset, yPos3, xPos - addAmount + stickWidth + offset, yPos3);
                        }
                    }
                }
            }
        }
예제 #22
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 );
                }
            }
        }
예제 #23
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="xAxis">The x-axis to use for transforms</param>
 /// <param name="yAxis">The y-axis to use for transforms</param>
 public FastTransform2D(PhysicalAxis xAxis, PhysicalAxis yAxis)
 {
     xAxis_ = new PageAlignedPhysicalAxis(xAxis);
     yAxis_ = new PageAlignedPhysicalAxis(yAxis);
 }
예제 #24
0
        /// <summary>
        /// Updates the PlotSurface2D axes to compensate for the legend.
        /// </summary>
        /// <param name="pXAxis1">the bottom x axis</param>
        /// <param name="pYAxis1">the left y axis</param>
        /// <param name="pXAxis2">the top x axis</param>
        /// <param name="pYAxis2">the right y axis</param>
        /// <param name="plots">list of plots.</param>
        /// <param name="scale">scale parameter (for text and other)</param>
        /// <param name="padding">padding around plot within bounds.</param>
        /// <param name="bounds">graphics surface bounds</param>
        /// <param name="position">legend position</param>
        public void UpdateAxesPositions( 
			PhysicalAxis pXAxis1,
			PhysicalAxis pYAxis1,
			PhysicalAxis pXAxis2,
			PhysicalAxis pYAxis2,
			ArrayList plots,
			float scale, int padding, Rectangle bounds,
			out Point position )
        {
            int leftIndent = 0;
            int rightIndent = 0;
            int bottomIndent = 0;
            int topIndent = 0;

            position = new Point(0,0);

            // now determine if legend should change any of these (legend should be fully
            // visible at all times), and draw legend.

            Rectangle legendWidthHeight = this.GetBoundingBox( new Point(0,0), plots, scale );

            if (legendWidthHeight.Width > bounds.Width)
            {
                legendWidthHeight.Width = bounds.Width;
            }

            // (1) calculate legend position.

            // y
            position.Y = this.yOffset_;

            if ( this.xAttach_ == PlotSurface2D.XAxisPosition.Bottom )
            {
                position.Y += pYAxis1.PhysicalMin.Y;
                if ( this.horizontalEdgePlacement_ == Legend.Placement.Inside )
                {
                    position.Y -= legendWidthHeight.Height;
                }
            }
            else
            {
                position.Y += pYAxis1.PhysicalMax.Y;
                if ( this.horizontalEdgePlacement_ == Legend.Placement.Outside )
                {
                    position.Y -= legendWidthHeight.Height;
                }
            }

            // x
            position.X = this.xOffset_;

            if ( this.yAttach_ == PlotSurface2D.YAxisPosition.Left )
            {
                if ( this.verticalEdgePlacement_ == Legend.Placement.Outside )
                {
                    position.X -= legendWidthHeight.Width;
                }
                position.X += pXAxis1.PhysicalMin.X;
            }
            else
            {
                if ( this.verticalEdgePlacement_ == Legend.Placement.Inside )
                {
                    position.X -= legendWidthHeight.Width;
                }
                position.X += pXAxis1.PhysicalMax.X;
            }

            // determine update amounts for axes

            if ( !this.neverShiftAxes_ )
            {
                if ( position.X < padding )
                {
                    int changeAmount = -position.X + padding;
                    // only allow axes to move away from bounds.
                    if ( changeAmount > 0 )
                    {
                        leftIndent = changeAmount;
                    }
                    position.X += changeAmount;
                }

                if ( position.X + legendWidthHeight.Width > bounds.Right - padding )
                {
                    int changeAmount = (position.X - bounds.Right + legendWidthHeight.Width + padding );
                    // only allow axes to move away from bounds.
                    if ( changeAmount > 0.0f )
                    {
                        rightIndent = changeAmount;
                    }
                    position.X -= changeAmount;
                }

                if ( position.Y < padding )
                {
                    int changeAmount = -position.Y + padding;
                    // only allow axes to move away from bounds.
                    if ( changeAmount > 0.0f )
                    {
                        topIndent = changeAmount;
                    }
                    position.Y += changeAmount;
                }

                if ( position.Y + legendWidthHeight.Height > bounds.Bottom - padding )
                {
                    int changeAmount = (position.Y - bounds.Bottom + legendWidthHeight.Height + padding );
                    // only allow axes to move away from bounds.
                    if ( changeAmount > 0.0f )
                    {
                        bottomIndent = changeAmount;
                    }
                    position.Y -= changeAmount;
                }

                // update axes.

                pXAxis1.PhysicalMin = new Point( pXAxis1.PhysicalMin.X + leftIndent, pXAxis1.PhysicalMin.Y - bottomIndent );
                pXAxis1.PhysicalMax = new Point( pXAxis1.PhysicalMax.X - rightIndent, pXAxis1.PhysicalMax.Y - bottomIndent );
                pYAxis1.PhysicalMin = new Point( pYAxis1.PhysicalMin.X + leftIndent, pYAxis1.PhysicalMin.Y - bottomIndent );
                pYAxis1.PhysicalMax = new Point( pYAxis1.PhysicalMax.X + leftIndent, pYAxis1.PhysicalMax.Y + topIndent );

                pXAxis2.PhysicalMin = new Point( pXAxis2.PhysicalMin.X + leftIndent, pXAxis2.PhysicalMin.Y + topIndent );
                pXAxis2.PhysicalMax = new Point( pXAxis2.PhysicalMax.X - rightIndent, pXAxis2.PhysicalMax.Y + topIndent );
                pYAxis2.PhysicalMin = new Point( pYAxis2.PhysicalMin.X - rightIndent, pYAxis2.PhysicalMin.Y - bottomIndent );
                pYAxis2.PhysicalMax = new Point( pYAxis2.PhysicalMax.X - rightIndent, pYAxis2.PhysicalMax.Y + topIndent );
            }
        }
예제 #25
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;
                RectangleF r = new RectangleF( xPos1.X+xoff, yPos1.Y, width-2*xoff, 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 );
            }
        }
예제 #26
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 FlorenceException("Error in TextPlot.Draw");
                }
            }
        }
예제 #27
0
        /// <summary>
        /// Draws the grid
        /// </summary>
        /// <param name="g">The graphics surface on which to draw</param>
        /// <param name="xAxis">The physical x axis to draw horizontal lines parallel to.</param>
        /// <param name="yAxis">The physical y axis to draw vertical lines parallel to.</param>
        public void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            ArrayList xLargePositions = null;
            ArrayList yLargePositions = null;
            ArrayList xSmallPositions = null;
            ArrayList ySmallPositions = null;

            if (this.horizontalGridType_ != GridType.None)
            {
                xAxis.Axis.WorldTickPositions_FirstPass( xAxis.PhysicalMin, xAxis.PhysicalMax, out xLargePositions, out xSmallPositions );
                DrawGridLines( g, xAxis, yAxis, xLargePositions, true, this.MajorGridPen );
            }

            if (this.verticalGridType_ != GridType.None)
            {
                yAxis.Axis.WorldTickPositions_FirstPass( yAxis.PhysicalMin, yAxis.PhysicalMax, out yLargePositions, out ySmallPositions );
                DrawGridLines( g, yAxis, xAxis, yLargePositions, false, this.MajorGridPen );
            }

            if (this.horizontalGridType_ == GridType.Fine)
            {
                xAxis.Axis.WorldTickPositions_SecondPass( xAxis.PhysicalMin, xAxis.PhysicalMax, xLargePositions, ref xSmallPositions );
                DrawGridLines( g, xAxis, yAxis, xSmallPositions, true, this.MinorGridPen );
            }

            if (this.verticalGridType_ == GridType.Fine)
            {
                yAxis.Axis.WorldTickPositions_SecondPass( yAxis.PhysicalMin, yAxis.PhysicalMax, yLargePositions, ref ySmallPositions );
                DrawGridLines( g, yAxis, xAxis, ySmallPositions, false, this.MinorGridPen );
            }
        }
예제 #28
0
        private void DeterminePhysicalAxesToDraw(Rectangle bounds,
                                                 Axis xAxis1, Axis xAxis2, Axis yAxis1, Axis yAxis2,
                                                 out PhysicalAxis pXAxis1, out PhysicalAxis pXAxis2,
                                                 out PhysicalAxis pYAxis1, out PhysicalAxis pYAxis2)
        {
            System.Drawing.Rectangle cb = bounds;

            pXAxis1 = new PhysicalAxis(xAxis1,
                                       new Point(cb.Left, cb.Bottom), new Point(cb.Right, cb.Bottom));
            pYAxis1 = new PhysicalAxis(yAxis1,
                                       new Point(cb.Left, cb.Bottom), new Point(cb.Left, cb.Top));
            pXAxis2 = new PhysicalAxis(xAxis2,
                                       new Point(cb.Left, cb.Top), new Point(cb.Right, cb.Top));
            pYAxis2 = new PhysicalAxis(yAxis2,
                                       new Point(cb.Right, cb.Bottom), new Point(cb.Right, cb.Top));

            int bottomIndent = padding_;

            if (!pXAxis1.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pXAxis1.GetBoundingBox();
                // finally determine its indentation from the bottom
                bottomIndent = bottomIndent + bb.Bottom - cb.Bottom;
            }

            int leftIndent = padding_;

            if (!pYAxis1.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pYAxis1.GetBoundingBox();
                // finally determine its indentation from the left
                leftIndent = leftIndent - bb.Left + cb.Left;
            }

            int   topIndent = padding_;
            float scale     = this.DetermineScaleFactor(bounds.Width, bounds.Height);
            int   titleHeight;

            if (this.AutoScaleTitle)
            {
                titleHeight = Utils.ScaleFont(titleFont_, scale).Height;
            }
            else
            {
                titleHeight = titleFont_.Height;
            }

            //count number of new lines in title.
            int nlCount = 0;

            for (int i = 0; i < title_.Length; ++i)
            {
                if (title_[i] == '\n')
                {
                    nlCount += 1;
                }
            }
            titleHeight = (int)(((float)nlCount * 0.75 + 1.0f) * (float)titleHeight);

            if (!pXAxis2.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pXAxis2.GetBoundingBox();
                topIndent = topIndent - bb.Top + cb.Top;

                // finally determine its indentation from the top
                // correct top indendation to take into account plot title
                if (title_ != "")
                {
                    topIndent += (int)(titleHeight * 1.3f);
                }
            }

            int rightIndent = padding_;

            if (!pYAxis2.Axis.Hidden)
            {
                // evaluate its bounding box
                Rectangle bb = pYAxis2.GetBoundingBox();

                // finally determine its indentation from the right
                rightIndent = (int)(rightIndent + bb.Right - cb.Right);
            }

            // now we have all the default calculated positions and we can proceed to
            // "move" the axes to their right places

            // primary axes (bottom, left)
            pXAxis1.PhysicalMin = new Point(cb.Left + leftIndent, cb.Bottom - bottomIndent);
            pXAxis1.PhysicalMax = new Point(cb.Right - rightIndent, cb.Bottom - bottomIndent);
            pYAxis1.PhysicalMin = new Point(cb.Left + leftIndent, cb.Bottom - bottomIndent);
            pYAxis1.PhysicalMax = new Point(cb.Left + leftIndent, cb.Top + topIndent);

            // secondary axes (top, right)
            pXAxis2.PhysicalMin = new Point(cb.Left + leftIndent, cb.Top + topIndent);
            pXAxis2.PhysicalMax = new Point(cb.Right - rightIndent, cb.Top + topIndent);
            pYAxis2.PhysicalMin = new Point(cb.Right - rightIndent, cb.Bottom - bottomIndent);
            pYAxis2.PhysicalMax = new Point(cb.Right - rightIndent, cb.Top + topIndent);
        }
예제 #29
0
        /// <summary>
        /// Draws the arrow on a plot surface.
        /// </summary>
        /// <param name="g">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(System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            if (this.To.X > xAxis.Axis.WorldMax || this.To.X < xAxis.Axis.WorldMin)
            {
                return;
            }

            if (this.To.Y > yAxis.Axis.WorldMax || this.To.Y < yAxis.Axis.WorldMin)
            {
                return;
            }

            double angle = this.angle_;

            if (this.angle_ < 0.0)
            {
                int mul = -(int)(this.angle_ / 360.0) + 2;
                angle = angle_ + 360.0 * (double)mul;
            }

            double normAngle = (double)angle % 360.0;               // angle in range 0 -> 360.

            Point toPoint = new Point(
                (int)xAxis.WorldToPhysical(to_.X, true).X,
                (int)yAxis.WorldToPhysical(to_.Y, true).Y);


            float xDir = (float)Math.Cos(normAngle * 2.0 * Math.PI / 360.0);
            float yDir = (float)Math.Sin(normAngle * 2.0 * Math.PI / 360.0);

            toPoint.X += (int)(xDir * headOffset_);
            toPoint.Y += (int)(yDir * headOffset_);

            float xOff = physicalLength_ * xDir;
            float yOff = physicalLength_ * yDir;

            Point fromPoint = new Point(
                (int)(toPoint.X + xOff),
                (int)(toPoint.Y + yOff));

            g.DrawLine(pen_, toPoint, fromPoint);

            Point[] head = new Point[3];

            head[0] = toPoint;

            xOff = headSize_ * (float)Math.Cos((normAngle - headAngle_ / 2.0f) * 2.0 * Math.PI / 360.0);
            yOff = headSize_ * (float)Math.Sin((normAngle - headAngle_ / 2.0f) * 2.0 * Math.PI / 360.0);

            head[1] = new Point(
                (int)(toPoint.X + xOff),
                (int)(toPoint.Y + yOff));

            float xOff2 = headSize_ * (float)Math.Cos((normAngle + headAngle_ / 2.0f) * 2.0 * Math.PI / 360.0);
            float yOff2 = headSize_ * (float)Math.Sin((normAngle + headAngle_ / 2.0f) * 2.0 * Math.PI / 360.0);

            head[2] = new Point(
                (int)(toPoint.X + xOff2),
                (int)(toPoint.Y + yOff2));

            g.FillPolygon(arrowBrush_, head);

            SizeF textSize = g.MeasureString(text_, font_);
            SizeF halfSize = new SizeF(textSize.Width / 2.0f, textSize.Height / 2.0f);

            float quadrantSlideLength = halfSize.Width + halfSize.Height;

            float quadrantF = (float)normAngle / 90.0f;           // integer part gives quadrant.
            int   quadrant  = (int)quadrantF;                     // quadrant in.
            float prop      = quadrantF - (float)quadrant;        // proportion of way through this qadrant.
            float dist      = prop * quadrantSlideLength;         // distance along quarter of bounds rectangle.

            // now find the offset from the middle of the text box that the
            // rear end of the arrow should end at (reverse this to get position
            // of text box with respect to rear end of arrow).
            //
            // There is almost certainly an elgant way of doing this involving
            // trig functions to get all the signs right, but I'm about ready to
            // drop off to sleep at the moment, so this blatent method will have
            // to do.
            PointF offsetFromMiddle = new PointF(0.0f, 0.0f);

            switch (quadrant)
            {
            case 0:
                if (dist > halfSize.Height)
                {
                    dist            -= halfSize.Height;
                    offsetFromMiddle = new PointF(-halfSize.Width + dist, halfSize.Height);
                }
                else
                {
                    offsetFromMiddle = new PointF(-halfSize.Width, -dist);
                }
                break;

            case 1:
                if (dist > halfSize.Width)
                {
                    dist            -= halfSize.Width;
                    offsetFromMiddle = new PointF(halfSize.Width, halfSize.Height - dist);
                }
                else
                {
                    offsetFromMiddle = new PointF(dist, halfSize.Height);
                }
                break;

            case 2:
                if (dist > halfSize.Height)
                {
                    dist            -= halfSize.Height;
                    offsetFromMiddle = new PointF(halfSize.Width - dist, -halfSize.Height);
                }
                else
                {
                    offsetFromMiddle = new PointF(halfSize.Width, -dist);
                }
                break;

            case 3:
                if (dist > halfSize.Width)
                {
                    dist            -= halfSize.Width;
                    offsetFromMiddle = new PointF(-halfSize.Width, -halfSize.Height + dist);
                }
                else
                {
                    offsetFromMiddle = new PointF(-dist, -halfSize.Height);
                }
                break;

            default:
                throw new FlorenceException("Programmer error.");
            }

            g.DrawString(
                text_, font_, textBrush_,
                (int)(fromPoint.X - halfSize.Width - offsetFromMiddle.X),
                (int)(fromPoint.Y - halfSize.Height + offsetFromMiddle.Y));
        }
예제 #30
0
        /// <summary>
        /// Draw the the PlotSurface2D and all contents [axes, drawables, and legend] on the
        /// supplied graphics surface.
        /// </summary>
        /// <param name="g">The graphics surface on which to draw.</param>
        /// <param name="bounds">A bounding box on this surface that denotes the area on the
        /// surface to confine drawing to.</param>
        public void Draw(Graphics g, Rectangle bounds)
        {
            // Draw background
            if (outerBackColor != null && outerBackColor != Color.Transparent)
            {
                g.FillRectangle(new SolidBrush(outerBackColor.Value), bounds);
            }
            else if (outerBackColor == null)
            {
                if (plotBackColor_ != null)
                {
                    g.FillRectangle(new SolidBrush(plotBackColor_.Value), bounds);
                }
                else if (plotBackBrush_ != null)
                {
                    g.FillRectangle(plotBackBrush_.Get(bounds), bounds);
                }
                else
                {
                    g.FillRectangle(new SolidBrush(Color.White), bounds);
                }
            }

            // determine font sizes and tick scale factor.
            float scale = DetermineScaleFactor(bounds.Width, bounds.Height);

            // if there is nothing to plot, return.
            if (drawables_.Count == 0)
            {
                // draw title
                float x_center = (bounds.Left + bounds.Right) / 2.0f;
                float y_center = (bounds.Top + bounds.Bottom) / 2.0f;
                Font  scaled_font;
                if (this.AutoScaleTitle)
                {
                    scaled_font = Utils.ScaleFont(titleFont_, scale);
                }
                else
                {
                    scaled_font = titleFont_;
                }
                g.DrawString(title_, scaled_font, this.titleBrush_, new PointF(x_center, y_center), titleDrawFormat_);

                return;
            }

            // determine the [non physical] axes to draw based on the axis properties set.
            Axis xAxis1 = null;
            Axis xAxis2 = null;
            Axis yAxis1 = null;
            Axis yAxis2 = null;

            this.DetermineAxesToDraw(out xAxis1, out xAxis2, out yAxis1, out yAxis2);

            // apply scale factor to axes as desired.

            if (xAxis1.AutoScaleTicks)
            {
                xAxis1.TickScale = scale;
            }
            if (xAxis1.AutoScaleText)
            {
                xAxis1.FontScale = scale;
            }
            if (yAxis1.AutoScaleTicks)
            {
                yAxis1.TickScale = scale;
            }
            if (yAxis1.AutoScaleText)
            {
                yAxis1.FontScale = scale;
            }
            if (xAxis2.AutoScaleTicks)
            {
                xAxis2.TickScale = scale;
            }
            if (xAxis2.AutoScaleText)
            {
                xAxis2.FontScale = scale;
            }
            if (yAxis2.AutoScaleTicks)
            {
                yAxis2.TickScale = scale;
            }
            if (yAxis2.AutoScaleText)
            {
                yAxis2.FontScale = scale;
            }

            // determine the default physical positioning of those axes.
            PhysicalAxis pXAxis1 = null;
            PhysicalAxis pYAxis1 = null;
            PhysicalAxis pXAxis2 = null;
            PhysicalAxis pYAxis2 = null;

            this.DeterminePhysicalAxesToDraw(
                bounds, xAxis1, xAxis2, yAxis1, yAxis2,
                out pXAxis1, out pXAxis2, out pYAxis1, out pYAxis2);

            float oldXAxis2Height = pXAxis2.PhysicalMin.Y;

            // Apply axes constraints
            for (int i = 0; i < axesConstraints_.Count; ++i)
            {
                ((AxesConstraint)axesConstraints_[i]).ApplyConstraint(
                    pXAxis1, pYAxis1, pXAxis2, pYAxis2);
            }

            /////////////////////////////////////////////////////////////////////////
            // draw legend if have one.
            // Note: this will update axes if necessary.
            Point legendPosition = new Point(0, 0);

            if (this.legend_ != null)
            {
                legend_.UpdateAxesPositions(
                    pXAxis1, pYAxis1, pXAxis2, pYAxis2,
                    this.drawables_, scale, this.padding_, bounds,
                    out legendPosition);
            }

            float newXAxis2Height  = pXAxis2.PhysicalMin.Y;
            float titleExtraOffset = oldXAxis2Height - newXAxis2Height;

            // now we are ready to define the bounding box for the plot area (to use in clipping
            // operations.
            plotAreaBoundingBoxCache_ = new Rectangle(
                Math.Min(pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMax.X),
                Math.Min(pYAxis1.PhysicalMax.Y, pYAxis1.PhysicalMin.Y),
                Math.Abs(pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X + 1),
                Math.Abs(pYAxis1.PhysicalMin.Y - pYAxis1.PhysicalMax.Y + 1)
                );
            bbXAxis1Cache_ = pXAxis1.GetBoundingBox();
            bbXAxis2Cache_ = pXAxis2.GetBoundingBox();
            bbYAxis1Cache_ = pYAxis1.GetBoundingBox();
            bbYAxis2Cache_ = pYAxis2.GetBoundingBox();

            // Fill in the background.
            if (this.plotBackColor_ != null)
            {
                g.FillRectangle(
                    new System.Drawing.SolidBrush((Color)this.plotBackColor_),
                    (Rectangle)plotAreaBoundingBoxCache_);
            }
            else if (this.plotBackBrush_ != null)
            {
                g.FillRectangle(
                    this.plotBackBrush_.Get((Rectangle)plotAreaBoundingBoxCache_),
                    (Rectangle)plotAreaBoundingBoxCache_);
            }
            else if (this.plotBackImage_ != null)
            {
                g.DrawImage(
                    Utils.TiledImage(this.plotBackImage_, new Size(
                                         ((Rectangle)plotAreaBoundingBoxCache_).Width,
                                         ((Rectangle)plotAreaBoundingBoxCache_).Height)),
                    (Rectangle)plotAreaBoundingBoxCache_);
            }

            // draw title
            float xt = (pXAxis2.PhysicalMax.X + pXAxis2.PhysicalMin.X) / 2.0f;
            float yt = bounds.Top + this.padding_ - titleExtraOffset;
            Font  scaledFont;

            if (this.AutoScaleTitle)
            {
                scaledFont = Utils.ScaleFont(titleFont_, scale);
            }
            else
            {
                scaledFont = titleFont_;
            }
            g.DrawString(title_, scaledFont, this.titleBrush_, new PointF(xt, yt), titleDrawFormat_);

            //count number of new lines in title.
            int nlCount = 0;

            for (int i = 0; i < title_.Length; ++i)
            {
                if (title_[i] == '\n')
                {
                    nlCount += 1;
                }
            }

            SizeF s = g.MeasureString(title_, scaledFont);

            bbTitleCache_ = new Rectangle((int)(xt - s.Width / 2), (int)(yt), (int)(s.Width), (int)(s.Height) * (nlCount + 1));

            // draw drawables..
            System.Drawing.Drawing2D.SmoothingMode smoothSave = g.SmoothingMode;

            g.SmoothingMode = this.smoothingMode_;

            bool legendDrawn = false;

            for (int i_o = 0; i_o < ordering_.Count; ++i_o)
            {
                int    i      = (int)ordering_.GetByIndex(i_o);
                double zOrder = (double)ordering_.GetKey(i_o);
                if (zOrder > this.legendZOrder_)
                {
                    // draw legend.
                    if (!legendDrawn && this.legend_ != null)
                    {
                        legend_.Draw(g, legendPosition, this.drawables_, scale);
                        legendDrawn = true;
                    }
                }

                IDrawable     drawable = (IDrawable)drawables_[i];
                XAxisPosition xap      = (XAxisPosition)xAxisPositions_[i];
                YAxisPosition yap      = (YAxisPosition)yAxisPositions_[i];

                PhysicalAxis drawXAxis;
                PhysicalAxis drawYAxis;

                if (xap == XAxisPosition.Bottom)
                {
                    drawXAxis = pXAxis1;
                }
                else
                {
                    drawXAxis = pXAxis2;
                }

                if (yap == YAxisPosition.Left)
                {
                    drawYAxis = pYAxis1;
                }
                else
                {
                    drawYAxis = pYAxis2;
                }

                // set the clipping region.. (necessary for zoom)
                g.Clip = new Region((Rectangle)plotAreaBoundingBoxCache_);
                // plot.
                drawable.Draw(g, drawXAxis, drawYAxis);
                // reset it..
                g.ResetClip();
            }

            if (!legendDrawn && this.legend_ != null)
            {
                legend_.Draw(g, legendPosition, this.drawables_, scale);
            }

            // cache the physical axes we used on this draw;
            this.pXAxis1Cache_ = pXAxis1;
            this.pYAxis1Cache_ = pYAxis1;
            this.pXAxis2Cache_ = pXAxis2;
            this.pYAxis2Cache_ = pYAxis2;

            g.SmoothingMode = smoothSave;

            // now draw axes.
            Rectangle axisBounds;

            pXAxis1.Draw(g, out axisBounds);
            pXAxis2.Draw(g, out axisBounds);
            pYAxis1.Draw(g, out axisBounds);
            pYAxis2.Draw(g, out axisBounds);

#if DEBUG_BOUNDING_BOXES
            g.DrawRectangle(new Pen(Color.Orange), (Rectangle)bbXAxis1Cache_);
            g.DrawRectangle(new Pen(Color.Orange), (Rectangle)bbXAxis2Cache_);
            g.DrawRectangle(new Pen(Color.Orange), (Rectangle)bbYAxis1Cache_);
            g.DrawRectangle(new Pen(Color.Orange), (Rectangle)bbYAxis2Cache_);
            g.DrawRectangle(new Pen(Color.Red, 5.0F), (Rectangle)plotAreaBoundingBoxCache_);
            //if(this.ShowLegend)g.DrawRectangle( new Pen(Color.Chocolate, 3.0F), (Rectangle) bbLegendCache_);
            g.DrawRectangle(new Pen(Color.DeepPink, 2.0F), (Rectangle)bbTitleCache_);
#endif
        }
예제 #31
0
        /// <summary>
        /// Draws the text on a plot surface.
        /// </summary>
        /// <param name="g">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( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            Point startPoint = new Point(
                (int)xAxis.WorldToPhysical( start_.X, true ).X,
                (int)yAxis.WorldToPhysical( start_.Y, true ).Y );

            g.DrawString(text_, font_, textBrush_,(int)startPoint.X,(int)startPoint.Y);
        }
예제 #32
0
        /// <summary>
        /// Draws the horizontal 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(System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            int xMin = xAxis.PhysicalMin.X;
            int xMax = xAxis.PhysicalMax.X;

            xMin += pixelIndent_;
            xMax -= pixelIndent_;

            float length = Math.Abs(xMax - xMin);
            float lengthDiff = length - length*scale_;
            float indentAmount = lengthDiff/2;

            xMin += (int)indentAmount;
            xMax -= (int)indentAmount;

            int yPos = (int)yAxis.WorldToPhysical( value_, false ).Y;

            g.DrawLine( pen_, new System.Drawing.Point( xMin, yPos ), new System.Drawing.Point( xMax, yPos ) );

            // todo:  clip and proper logic for flipped axis min max.
        }
예제 #33
0
        /// <summary>
        /// Calculates the physical (not world) separation between abscissa values.
        /// </summary>
        /// <param name="cd">Candle adapter containing data</param>
        /// <param name="xAxis">Physical x axis the data is plotted against.</param>
        /// <returns>physical separation between abscissa values.</returns>
        private static float CalculatePhysicalSeparation( CandleDataAdapter cd, PhysicalAxis xAxis )
        {
            if (cd.Count > 1)
            {
                int xPos1 = (int)(xAxis.WorldToPhysical( ((PointOLHC)cd[0]).X, false )).X;
                int xPos2 = (int)(xAxis.WorldToPhysical( ((PointOLHC)cd[1]).X, false )).X;
                int minDist = xPos2 - xPos1;

                if (cd.Count > 2)
                {  // to be pretty sure we get the smallest gap.
                    int xPos3 = (int)(xAxis.WorldToPhysical(((PointOLHC)cd[2]).X, false)).X;
                    if (xPos3 - xPos2 < minDist)
                    {
                        minDist = xPos3 - xPos2;
                    }

                    if (cd.Count > 3)
                    {
                        int xPos4 = (int)(xAxis.WorldToPhysical(((PointOLHC)cd[3]).X, false)).X;
                        if (xPos4 - xPos3 < minDist)
                        {
                            minDist = xPos4 - xPos3;
                        }
                    }
                }

                return minDist;
            }

            return 0.0f;
        }
예제 #34
0
        /// <summary>
        /// Draw on to the supplied graphics surface against the supplied axes.
        /// </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>
        /// <remarks>TODO: block positions may be off by a pixel or so. maybe. Re-think calculations</remarks>
        public void Draw( Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            if ( data_==null || data_.GetLength(0) == 0 || data_.GetLength(1) == 0 )
            {
                return;
            }

            double worldWidth = xAxis.Axis.WorldMax - xAxis.Axis.WorldMin;
            double numBlocksHorizontal = worldWidth / this.xStep_;
            double worldHeight = yAxis.Axis.WorldMax - yAxis.Axis.WorldMin;
            double numBlocksVertical = worldHeight / this.yStep_;

            double physicalWidth = xAxis.PhysicalMax.X - xAxis.PhysicalMin.X;
            double blockWidth = physicalWidth / numBlocksHorizontal;
            bool wPositive = true;
            if (blockWidth < 0.0)
            {
                wPositive = false;
            }
            blockWidth = Math.Abs(blockWidth)+1;

            double physicalHeight = yAxis.PhysicalMax.Y - yAxis.PhysicalMin.Y;
            double blockHeight = physicalHeight / numBlocksVertical;
            bool hPositive = true;
            if (blockHeight < 0.0)
            {
                hPositive = false;
            }
            blockHeight = Math.Abs(blockHeight)+1;

            for (int i=0; i<data_.GetLength(0); ++i)
            {
                for (int j=0; j<data_.GetLength(1); ++j)
                {
                    double wX = (double)j*this.xStep_ + xStart_;
                    double wY = (double)i*this.yStep_ + yStart_;
                    if ( !hPositive )
                    {
                        wY += yStep_;
                    }
                    if (!wPositive )
                    {
                        wX += xStep_;
                    }

                    if (this.center_)
                    {
                        wX -= this.xStep_/2.0;
                        wY -= this.yStep_/2.0;
                    }
                    Pen p = new Pen( this.Gradient.GetColor( (data_[i,j]-this.dataMin_)/(this.dataMax_-this.dataMin_) ) );
                    int x = (int)xAxis.WorldToPhysical(wX,false).X;
                    int y = (int)yAxis.WorldToPhysical(wY,false).Y;
                    g.FillRectangle( p.Brush,
                        x,
                        y,
                        (int)blockWidth,
                        (int)blockHeight);
                    //g.DrawRectangle(Pens.White,x,y,(int)blockWidth,(int)blockHeight);
                }
            }
        }
예제 #35
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 )
        {
            if (this.shadow_)
            {
                this.DrawLineOrShadow( g, xAxis, yAxis, true );
            }

            this.DrawLineOrShadow( g, xAxis, yAxis, false );
        }
예제 #36
0
            /// <summary>
            /// Applies the constraint to the axes.
            /// </summary>
            /// <param name="pXAxis1">The bottom x-axis.</param>
            /// <param name="pYAxis1">The left y-axis.</param>
            /// <param name="pXAxis2">The top x-axis.</param>
            /// <param name="pYAxis2">The right y-axis.</param>
            public override void ApplyConstraint(
                PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
                PhysicalAxis pXAxis2, PhysicalAxis pYAxis2)
            {
                double xWorldRange    = Math.Abs(pXAxis1.Axis.WorldMax - pXAxis1.Axis.WorldMin);
                double xPhysicalRange = Math.Abs(pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X);
                double xDirPixelSize  = xWorldRange / xPhysicalRange;

                double yWorldRange    = Math.Abs(pYAxis1.Axis.WorldMax - pYAxis1.Axis.WorldMin);
                double yPhysicalRange = Math.Abs(pYAxis1.PhysicalMax.Y - pYAxis1.PhysicalMin.Y);
                double yDirPixelSize  = yWorldRange / yPhysicalRange;

                double currentAspectRatio = yDirPixelSize / xDirPixelSize;

                // we want to change the current aspect ratio to be the desired.
                // to do this, we may only add the world pixel lengths.

                if (this.a_ > currentAspectRatio)
                {
                    // want to increase aspect ratio. Therefore, want to add some amount
                    // to yDirPixelSize (numerator).

                    double toAdd     = (this.a_ - currentAspectRatio) * xDirPixelSize;
                    int    newHeight =
                        (int)(Math.Abs(pYAxis1.Axis.WorldMax - pYAxis1.Axis.WorldMin) / (yDirPixelSize + toAdd));
                    int changeInHeight = (int)yPhysicalRange - newHeight;

                    int changeBottom = changeInHeight / 2;
                    int changeTop    = changeInHeight / 2;
                    if (this.holdFixedX_ != null)
                    {
                        if ((PlotSurface2D.XAxisPosition) this.holdFixedX_ == PlotSurface2D.XAxisPosition.Bottom)
                        {
                            changeBottom = 0;
                            changeTop    = changeInHeight;
                        }
                        else
                        {
                            changeBottom = changeInHeight;
                            changeTop    = 0;
                        }
                    }

                    pYAxis1.PhysicalMin = new Point(pYAxis1.PhysicalMin.X, pYAxis1.PhysicalMin.Y - changeBottom);
                    pYAxis1.PhysicalMax = new Point(pYAxis1.PhysicalMax.X, pYAxis1.PhysicalMax.Y + changeTop);
                    pYAxis2.PhysicalMin = new Point(pYAxis2.PhysicalMin.X, pYAxis2.PhysicalMin.Y - changeBottom);
                    pYAxis2.PhysicalMax = new Point(pYAxis2.PhysicalMax.X, pYAxis2.PhysicalMax.Y + changeTop);

                    pXAxis1.PhysicalMin = new Point(pXAxis1.PhysicalMin.X, pXAxis1.PhysicalMin.Y - changeBottom);
                    pXAxis1.PhysicalMax = new Point(pXAxis1.PhysicalMax.X, pXAxis1.PhysicalMax.Y - changeBottom);
                    pXAxis2.PhysicalMin = new Point(pXAxis2.PhysicalMin.X, pXAxis2.PhysicalMin.Y + changeTop);
                    pXAxis2.PhysicalMax = new Point(pXAxis2.PhysicalMax.X, pXAxis2.PhysicalMax.Y + changeTop);
                }
                else
                {
                    // want to decrease aspect ratio. Therefore, want to add some amount
                    // to xDirPixelSize (denominator).

                    double toAdd    = yDirPixelSize / this.a_ - xDirPixelSize;
                    int    newWidth =
                        (int)(Math.Abs(pXAxis1.Axis.WorldMax - pXAxis1.Axis.WorldMin) / (xDirPixelSize + toAdd));
                    int changeInWidth = (int)xPhysicalRange - newWidth;

                    int changeLeft  = changeInWidth / 2;
                    int changeRight = changeInWidth / 2;
                    if (this.holdFixedY_ != null)
                    {
                        if ((PlotSurface2D.YAxisPosition) this.holdFixedY_ == PlotSurface2D.YAxisPosition.Left)
                        {
                            changeLeft  = 0;
                            changeRight = changeInWidth;
                        }
                        else
                        {
                            changeLeft  = changeInWidth;
                            changeRight = 0;
                        }
                    }

                    pXAxis1.PhysicalMin = new Point(pXAxis1.PhysicalMin.X + changeLeft, pXAxis1.PhysicalMin.Y);
                    pXAxis1.PhysicalMax = new Point(pXAxis1.PhysicalMax.X - changeRight, pXAxis1.PhysicalMax.Y);
                    pXAxis2.PhysicalMin = new Point(pXAxis2.PhysicalMin.X + changeLeft, pXAxis2.PhysicalMin.Y);
                    pXAxis2.PhysicalMax = new Point(pXAxis2.PhysicalMax.X - changeRight, pXAxis2.PhysicalMax.Y);

                    pYAxis1.PhysicalMin = new Point(pYAxis1.PhysicalMin.X + changeLeft, pYAxis1.PhysicalMin.Y);
                    pYAxis1.PhysicalMax = new Point(pYAxis1.PhysicalMax.X + changeLeft, pYAxis1.PhysicalMax.Y);
                    pYAxis2.PhysicalMin = new Point(pYAxis2.PhysicalMin.X - changeRight, pYAxis2.PhysicalMin.Y);
                    pYAxis2.PhysicalMax = new Point(pYAxis2.PhysicalMax.X - changeRight, pYAxis2.PhysicalMax.Y);
                }
            }
예제 #37
0
 /// <summary>
 /// MouseUp method for AxisDrag interaction
 /// </summary>
 /// <param name="X">mouse X position</param>
 /// <param name="Y"> mouse Y position</param>
 /// <param name="keys"> mouse and keyboard modifiers</param>
 /// <param name="ps">the InteractivePlotSurface2D</param>
 public override bool DoMouseUp(int X, int Y, Modifier keys, InteractivePlotSurface2D ps)
 {
     if (dragging_)
     {
         dragging_ = false;
         axis_ = null;
         physicalAxis_ = null;
         lastPoint_ = new Point();
         ps.plotCursor = CursorType.LeftPointer;
     }
     return false;
 }
예제 #38
0
 /// <summary>
 /// Applies the constraint to the axes. Must be overriden.
 /// </summary>
 /// <param name="pXAxis1">The bottom x-axis.</param>
 /// <param name="pYAxis1">The left y-axis.</param>
 /// <param name="pXAxis2">The top x-axis.</param>
 /// <param name="pYAxis2">The right y-axis.</param>
 public abstract void ApplyConstraint(
     PhysicalAxis pXAxis1, PhysicalAxis pYAxis1,
     PhysicalAxis pXAxis2, PhysicalAxis pYAxis2);
예제 #39
0
        /// <summary>
        /// Draws the arrow on a plot surface.
        /// </summary>
        /// <param name="g">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( System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis )
        {
            if (this.To.X > xAxis.Axis.WorldMax || this.To.X < xAxis.Axis.WorldMin)
            {
                return;
            }

            if (this.To.Y > yAxis.Axis.WorldMax || this.To.Y < yAxis.Axis.WorldMin)
            {
                return;
            }

            double angle = this.angle_;

            if (this.angle_ < 0.0)
            {
                int mul = -(int)(this.angle_ / 360.0) + 2;
                angle = angle_ + 360.0 * (double)mul;
            }

            double normAngle = (double)angle % 360.0;   // angle in range 0 -> 360.

            Point toPoint = new Point(
                (int)xAxis.WorldToPhysical( to_.X, true ).X,
                (int)yAxis.WorldToPhysical( to_.Y, true ).Y );

            float xDir = (float)Math.Cos( normAngle * 2.0 * Math.PI / 360.0 );
            float yDir = (float)Math.Sin( normAngle * 2.0 * Math.PI / 360.0 );

            toPoint.X += (int)(xDir*headOffset_);
            toPoint.Y += (int)(yDir*headOffset_);

            float xOff = physicalLength_ * xDir;
            float yOff = physicalLength_ * yDir;

            Point fromPoint = new Point(
                (int)(toPoint.X + xOff),
                (int)(toPoint.Y + yOff) );

            g.DrawLine( pen_, toPoint, fromPoint );

            Point[] head = new Point[3];

            head[0] = toPoint;

            xOff = headSize_ * (float)Math.Cos( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
            yOff = headSize_ * (float)Math.Sin( (normAngle-headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );

            head[1] = new Point(
                (int)(toPoint.X + xOff),
                (int)(toPoint.Y + yOff) );

            float xOff2 = headSize_ * (float)Math.Cos( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );
            float yOff2 = headSize_ * (float)Math.Sin( (normAngle+headAngle_/2.0f) * 2.0 * Math.PI / 360.0 );

            head[2] = new Point(
                (int)(toPoint.X + xOff2),
                (int)(toPoint.Y + yOff2) );

            g.FillPolygon( arrowBrush_, head );

            SizeF textSize = g.MeasureString( text_, font_ );
            SizeF halfSize = new SizeF( textSize.Width / 2.0f, textSize.Height / 2.0f );

            float quadrantSlideLength = halfSize.Width + halfSize.Height;

            float quadrantF = (float)normAngle / 90.0f;       // integer part gives quadrant.
            int quadrant = (int)quadrantF;	          // quadrant in.
            float prop = quadrantF - (float)quadrant; // proportion of way through this qadrant.
            float dist = prop * quadrantSlideLength;	  // distance along quarter of bounds rectangle.

            // now find the offset from the middle of the text box that the
            // rear end of the arrow should end at (reverse this to get position
            // of text box with respect to rear end of arrow).
            //
            // There is almost certainly an elgant way of doing this involving
            // trig functions to get all the signs right, but I'm about ready to
            // drop off to sleep at the moment, so this blatent method will have
            // to do.
            PointF offsetFromMiddle = new PointF( 0.0f, 0.0f );
            switch (quadrant)
            {
                case 0:
                    if (dist > halfSize.Height)
                    {
                        dist -= halfSize.Height;
                        offsetFromMiddle = new PointF( -halfSize.Width + dist, halfSize.Height );
                    }
                    else
                    {
                        offsetFromMiddle = new PointF( -halfSize.Width, - dist );
                    }
                    break;

                case 1:
                    if (dist > halfSize.Width)
                    {
                        dist -= halfSize.Width;
                        offsetFromMiddle = new PointF( halfSize.Width, halfSize.Height - dist );
                    }
                    else
                    {
                        offsetFromMiddle = new PointF( dist, halfSize.Height );
                    }
                    break;

                case 2:
                    if (dist > halfSize.Height)
                    {
                        dist -= halfSize.Height;
                        offsetFromMiddle = new PointF( halfSize.Width - dist, -halfSize.Height );
                    }
                    else
                    {
                        offsetFromMiddle = new PointF( halfSize.Width, -dist );
                    }
                    break;

                case 3:
                    if (dist > halfSize.Width)
                    {
                        dist -= halfSize.Width;
                        offsetFromMiddle = new PointF( -halfSize.Width, -halfSize.Height + dist );
                    }
                    else
                    {
                        offsetFromMiddle = new PointF( -dist, -halfSize.Height );
                    }
                    break;

                default:
                    throw new FlorenceException( "Programmer error." );

            }

            g.DrawString(
                text_, font_, textBrush_,
                (int)(fromPoint.X - halfSize.Width - offsetFromMiddle.X),
                (int)(fromPoint.Y - halfSize.Height + offsetFromMiddle.Y) );
        }
예제 #40
0
 private static Point WorldToPhysical(PointD world_point, PhysicalAxis xAxis, PhysicalAxis yAxis)
 {
     return(new Point((int)xAxis.WorldToPhysical(world_point.X, false).X, (int)yAxis.WorldToPhysical(world_point.Y, false).Y));
 }
예제 #41
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 );
                }
            }
        }
예제 #42
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);
                }
            }
        }
예제 #43
0
        /// <summary>
        /// Draws the vertical 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(System.Drawing.Graphics g, PhysicalAxis xAxis, PhysicalAxis yAxis)
        {
            int yMin = yAxis.PhysicalMin.Y;
            int yMax = yAxis.PhysicalMax.Y;

            yMin -= pixelIndent_;
            yMax += pixelIndent_;

            float length = Math.Abs(yMax - yMin);
            float lengthDiff = length - length*scale_;
            float indentAmount = lengthDiff/2;

            yMin -= (int)indentAmount;
            yMax += (int)indentAmount;

            int xPos = (int)xAxis.WorldToPhysical( value_, false ).X;

            g.DrawLine( pen_, new System.Drawing.Point( xPos, yMin ), new System.Drawing.Point( xPos, yMax ) );

            // todo:  clip and proper logic for flipped axis min max.
        }
예제 #44
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, new Point((int)xPos.X,(int)yStart.Y), new Point((int)xPos.X,(int)yPos.Y) );
                    }
                }
            }
        }