/// <summary> /// Create a <see cref="Pen" /> object based on the properties of this /// <see cref="LineBase" />. /// </summary> /// <param name="pane">The owner <see cref="GraphPane" /> of this /// <see cref="LineBase" />. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>A <see cref="Pen" /> object with the properties of this <see cref="LineBase" /> /// </returns> public Pen GetPen( PaneBase pane, float scaleFactor ) { return GetPen( pane, scaleFactor, null ); }
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> public override void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = Location.TransformRect( pane ); Matrix matrix = new Matrix(); if ( pixRect.Right == 0 ) pixRect.Width = 1; float angle = (float) Math.Atan( ( pixRect.Top - pixRect.Bottom ) / ( pixRect.Left - pixRect.Right ) ); matrix.Rotate( angle, MatrixOrder.Prepend ); // Move the coordinate system to local coordinates // of this text object (that is, at the specified // x,y location) matrix.Translate( -pixRect.Left, -pixRect.Top, MatrixOrder.Prepend ); PointF[] pts = new PointF[4]; pts[0] = new PointF( 0, 3 ); pts[1] = new PointF( pixRect.Width, 3 ); pts[2] = new PointF( pixRect.Width, -3 ); pts[3] = new PointF( 0, -3 ); matrix.TransformPoints( pts ); shape = "poly"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},", pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, pts[2].X, pts[2].Y, pts[3].X, pts[3].Y ); }
/// <summary> /// The <see cref="PointF"/> for this object as defined by the /// <see cref="X2"/> and <see cref="Y2"/> properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are ignored for /// this transformation (see <see cref="TransformTopLeft(PaneBase,float,float)"/>). /// </remarks> /// <value>A <see cref="PointF"/> in pixel units.</value> public PointF TransformBottomRight( PaneBase pane ) { return Transform( pane, this.X2, this.Y2, _coordinateFrame ); }
/// <summary> /// Transform this <see cref="Location"/> from the coordinate system /// as specified by <see cref="CoordinateFrame"/> to the device coordinates /// of the specified <see cref="PaneBase"/> object. /// </summary> /// <remarks> /// The returned /// <see cref="PointF"/> struct represents the top-left corner of the /// object that honors the <see cref="Location"/> properties. /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are honored in /// this transformation. /// </remarks> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that contains /// the <see cref="Axis"/> classes which will be used for the transform. /// </param> /// <param name="width">The width of the object in device pixels</param> /// <param name="height">The height of the object in device pixels</param> /// <returns>The top-left corner of the object</returns> public PointF TransformTopLeft( PaneBase pane, float width, float height ) { PointF pt = Transform( pane ); if ( _alignH == AlignH.Right ) pt.X -= width; else if ( _alignH == AlignH.Center ) pt.X -= width / 2.0F; if ( _alignV == AlignV.Bottom ) pt.Y -= height; else if ( _alignV == AlignV.Center ) pt.Y -= height / 2.0F; return pt; }
/// <summary> /// Determine if a mouse point is within the legend, and if so, which legend /// entry (<see cref="CurveItem"/>) is nearest. /// </summary> /// <param name="mousePt">The screen point, in pixel coordinates.</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="index">The index number of the <see cref="CurveItem"/> legend /// entry that is under the mouse point. The <see cref="CurveItem"/> object is /// accessible via <see cref="GraphPane.CurveList">CurveList[index]</see>. /// </param> /// <returns>true if the mouse point is within the <see cref="Legend"/> bounding /// box, false otherwise.</returns> /// <seealso cref="GraphPane.FindNearestObject"/> public bool FindPoint( PointF mousePt, PaneBase pane, float scaleFactor, out int index ) { index = -1; if ( _rect.Contains( mousePt ) ) { int j = (int)( ( mousePt.Y - _rect.Top ) / _legendItemHeight ); int i = (int)( ( mousePt.X - _rect.Left - _tmpSize / 2.0f ) / _legendItemWidth ); if ( i < 0 ) i = 0; if ( i >= _hStack ) i = _hStack - 1; int pos = i + j * _hStack; index = 0; PaneList paneList = GetPaneList( pane ); foreach ( GraphPane tmpPane in paneList ) { foreach ( CurveItem curve in tmpPane.CurveList ) { if ( curve._label._isVisible && curve._label._text != string.Empty ) { if ( pos == 0 ) return true; pos--; } index++; } } return true; } else return false; }
/// <summary> /// Transform a data point from the specified coordinate type /// (<see cref="CoordType"/>) to display device coordinates (pixels). /// </summary> /// <remarks> /// If <see paramref="pane"/> is not of type <see cref="GraphPane"/>, then /// only the <see cref="CoordType.PaneFraction"/> transformation is available. /// </remarks> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that contains /// the <see cref="Axis"/> classes which will be used for the transform. /// </param> /// <param name="x">The x coordinate that defines the point in user /// space.</param> /// <param name="y">The y coordinate that defines the point in user /// space.</param> /// <param name="coord">A <see cref="CoordType"/> type that defines the /// coordinate system in which the X,Y pair is defined.</param> /// <returns>A point in display device coordinates that corresponds to the /// specified user point.</returns> public static PointF Transform( PaneBase pane, double x, double y, CoordType coord ) { return pane.TransformCoord( x, y, coord ); }
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> public abstract void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords );
/// <summary> /// Calculate the <see cref="Legend"/> rectangle (<see cref="Rect"/>), /// taking into account the number of required legend /// entries, and the legend drawing preferences. /// </summary> /// <remarks>Adjust the size of the /// <see cref="Chart.Rect"/> for the parent <see cref="GraphPane"/> to accomodate the /// space required by the legend. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="tChartRect"> /// The rectangle that contains the area bounded by the axes, in pixel units. /// <seealso cref="Chart.Rect" /> /// </param> public void CalcRect( Graphics g, PaneBase pane, float scaleFactor, ref RectangleF tChartRect ) { // Start with an empty rectangle _rect = Rectangle.Empty; _hStack = 1; _legendItemWidth = 1; _legendItemHeight = 0; RectangleF clientRect = pane.CalcClientRect( g, scaleFactor ); // If the legend is invisible, don't do anything if ( !_isVisible ) return; int nCurve = 0; PaneList paneList = GetPaneList( pane ); _tmpSize = GetMaxHeight( paneList, g, scaleFactor ); float halfGap = _tmpSize / 2.0F, maxWidth = 0, tmpWidth, gapPix = _gap * _tmpSize; foreach ( GraphPane tmpPane in paneList ) { // Loop through each curve in the curve list // Find the maximum width of the legend labels //foreach ( CurveItem curve in tmpPane.CurveList ) //foreach ( CurveItem curve in GetIterator( tmpPane.CurveList, _isReverse ) ) int count = tmpPane.CurveList.Count; for ( int i = 0; i < count; i++ ) { CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i]; if ( curve._label._text != string.Empty && curve._label._isVisible ) { // Calculate the width of the label save the max width FontSpec tmpFont = ( curve._label._fontSpec != null ) ? curve._label._fontSpec : this.FontSpec; tmpWidth = tmpFont.GetWidth( g, curve._label._text, scaleFactor ); if ( tmpWidth > maxWidth ) maxWidth = tmpWidth; // Save the maximum symbol height for line-type curves if ( curve is LineItem && ( (LineItem)curve ).Symbol.Size > _legendItemHeight ) _legendItemHeight = ( (LineItem)curve ).Symbol.Size; nCurve++; } } if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries ) break; } float widthAvail; // Is this legend horizontally stacked? if ( _isHStack ) { // Determine the available space for horizontal stacking switch ( _position ) { // Never stack if the legend is to the right or left case LegendPos.Right: case LegendPos.Left: widthAvail = 0; break; // for the top & bottom, the axis border width is available case LegendPos.Top: case LegendPos.TopCenter: case LegendPos.Bottom: case LegendPos.BottomCenter: widthAvail = tChartRect.Width; break; // for the top & bottom flush left, the panerect less margins is available case LegendPos.TopFlushLeft: case LegendPos.BottomFlushLeft: widthAvail = clientRect.Width; break; // for inside the axis area or Float, use 1/2 of the axis border width case LegendPos.InsideTopRight: case LegendPos.InsideTopLeft: case LegendPos.InsideBotRight: case LegendPos.InsideBotLeft: case LegendPos.Float: widthAvail = tChartRect.Width / 2; break; // shouldn't ever happen default: widthAvail = 0; break; } // width of one legend entry if ( _isShowLegendSymbols ) _legendItemWidth = 3.0f * _tmpSize + maxWidth; else _legendItemWidth = 0.5f * _tmpSize + maxWidth; // Calculate the number of columns in the legend // Normally, the legend is: // available width / ( max width of any entry + space for line&symbol ) if ( maxWidth > 0 ) _hStack = (int)( ( widthAvail - halfGap ) / _legendItemWidth ); // You can never have more columns than legend entries if ( _hStack > nCurve ) _hStack = nCurve; // a saftey check if ( _hStack == 0 ) _hStack = 1; } else { if ( _isShowLegendSymbols ) _legendItemWidth = 3.0F * _tmpSize + maxWidth; else _legendItemWidth = 0.5F * _tmpSize + maxWidth; } // legend is: // item: space line space text space // width: wid 4*wid wid maxWid wid // The symbol is centered on the line // // legend begins 3 * wid to the right of the plot rect // // The height of the legend is the actual height of the lines of text // (nCurve * hite) plus wid on top and wid on the bottom // total legend width float totLegWidth = _hStack * _legendItemWidth; // The total legend height _legendItemHeight = _legendItemHeight * (float)scaleFactor + halfGap; if ( _tmpSize > _legendItemHeight ) _legendItemHeight = _tmpSize; float totLegHeight = (float)Math.Ceiling( (double)nCurve / (double)_hStack ) * _legendItemHeight; RectangleF newRect = new RectangleF(); // Now calculate the legend rect based on the above determined parameters // Also, adjust the ChartRect to reflect the space for the legend if ( nCurve > 0 ) { newRect = new RectangleF( 0, 0, totLegWidth, totLegHeight ); // The switch statement assigns the left and top edges, and adjusts the ChartRect // as required. The right and bottom edges are calculated at the bottom of the switch. switch ( _position ) { case LegendPos.Right: newRect.X = clientRect.Right - totLegWidth; newRect.Y = tChartRect.Top; tChartRect.Width -= totLegWidth + gapPix; break; case LegendPos.Top: newRect.X = tChartRect.Left; newRect.Y = clientRect.Top; tChartRect.Y += totLegHeight + gapPix; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.TopFlushLeft: newRect.X = clientRect.Left; newRect.Y = clientRect.Top; tChartRect.Y += totLegHeight + gapPix * 1.5f; tChartRect.Height -= totLegHeight + gapPix * 1.5f; break; case LegendPos.TopCenter: newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2; newRect.Y = tChartRect.Top; tChartRect.Y += totLegHeight + gapPix; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.Bottom: newRect.X = tChartRect.Left; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.BottomFlushLeft: newRect.X = clientRect.Left; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.BottomCenter: newRect.X = tChartRect.Left + ( tChartRect.Width - totLegWidth ) / 2; newRect.Y = clientRect.Bottom - totLegHeight; tChartRect.Height -= totLegHeight + gapPix; break; case LegendPos.Left: newRect.X = clientRect.Left; newRect.Y = tChartRect.Top; tChartRect.X += totLegWidth + halfGap; tChartRect.Width -= totLegWidth + gapPix; break; case LegendPos.InsideTopRight: newRect.X = tChartRect.Right - totLegWidth; newRect.Y = tChartRect.Top; break; case LegendPos.InsideTopLeft: newRect.X = tChartRect.Left; newRect.Y = tChartRect.Top; break; case LegendPos.InsideBotRight: newRect.X = tChartRect.Right - totLegWidth; newRect.Y = tChartRect.Bottom - totLegHeight; break; case LegendPos.InsideBotLeft: newRect.X = tChartRect.Left; newRect.Y = tChartRect.Bottom - totLegHeight; break; case LegendPos.Float: newRect.Location = this.Location.TransformTopLeft( pane, totLegWidth, totLegHeight ); break; } } _rect = newRect; }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="BoxObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public override bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = Location.TransformRect( pane ); return pixRect.Contains( pt ); }
/// <summary> /// Render this <see cref="GraphObj"/> object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="PaneBase"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public abstract void Draw( Graphics g, PaneBase pane, float scaleFactor );
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> public override void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = Location.TransformRect( pane ); shape = "rect"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0}", pixRect.Left, pixRect.Top, pixRect.Right, pixRect.Bottom ); }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system RectangleF pixRect = this.Location.TransformRect( pane ); // Clip the rect to just outside the PaneRect so we don't end up with wild coordinates. RectangleF tmpRect = pane.Rect; tmpRect.Inflate( 20, 20 ); pixRect.Intersect( tmpRect ); if ( Math.Abs( pixRect.Left ) < 100000 && Math.Abs( pixRect.Top ) < 100000 && Math.Abs( pixRect.Right ) < 100000 && Math.Abs( pixRect.Bottom ) < 100000 ) { // If the box is to be filled, fill it _fill.Draw( g, pixRect ); // Draw the border around the box if required _border.Draw( g, pane, scaleFactor, pixRect ); } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="LineObj"/>. /// </summary> /// <remarks>The bounding box is calculated assuming a distance /// of <see cref="GraphPane.Default.NearestTol"/> pixels around the arrow segment. /// </remarks> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public override bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = Location.TransformTopLeft( pane ); PointF pix2 = Location.TransformBottomRight( pane ); using ( Pen pen = new Pen( Color.Black, (float)GraphPane.Default.NearestTol * 2.0F ) ) { using ( GraphicsPath path = new GraphicsPath() ) { path.AddLine( pix, pix2 ); return path.IsOutlineVisible( pt, pen ); } } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="PolyObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public override bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( _points != null && _points.Length > 1 ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; using ( GraphicsPath path = MakePath( pane ) ) return path.IsVisible( pt ); } else return false; }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="GraphObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="PaneBase"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public virtual bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { GraphPane gPane = pane as GraphPane; if ( gPane != null && _isClippedToChartRect && !gPane.Chart.Rect.Contains( pt ) ) return false; return true; }
internal GraphicsPath MakePath( PaneBase pane ) { GraphicsPath path = new GraphicsPath(); bool first = true; PointF lastPt = new PointF(); foreach( PointD pt in _points ) { // Convert the coordinates from the user coordinate system // to the screen coordinate system // Offset the points by the location value PointF pixPt = Location.Transform( pane, pt.X + Location.X, pt.Y + Location.Y, Location.CoordinateFrame ); if ( Math.Abs( pixPt.X ) < 100000 && Math.Abs( pixPt.Y ) < 100000 ) { if ( first ) first = false; else path.AddLine( lastPt, pixPt ); lastPt = pixPt; } } if ( _isClosedFigure ) path.CloseFigure(); return path; }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system RectangleF pixRect = this.Location.TransformRect( pane ); if ( Math.Abs( pixRect.Left ) < 100000 && Math.Abs( pixRect.Top ) < 100000 && Math.Abs( pixRect.Right ) < 100000 && Math.Abs( pixRect.Bottom ) < 100000 ) { if ( _fill.IsVisible ) using ( Brush brush = _fill.MakeBrush( pixRect ) ) g.FillEllipse( brush, pixRect ); if ( _border.IsVisible ) using ( Pen pen = _border.GetPen( pane, scaleFactor ) ) g.DrawEllipse( pen, pixRect ); } }
/// <summary> /// Render the <see cref="Legend"/> to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphPane"/> object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // if the legend is not visible, do nothing if ( !_isVisible ) return; // Fill the background with the specified color if required _fill.Draw( g, _rect ); PaneList paneList = GetPaneList( pane ); float halfGap = _tmpSize / 2.0F; // Check for bad data values if ( _hStack <= 0 ) _hStack = 1; if ( _legendItemWidth <= 0 ) _legendItemWidth = 100; if ( _legendItemHeight <= 0 ) _legendItemHeight = _tmpSize; //float gap = pane.ScaledGap( scaleFactor ); int iEntry = 0; float x, y; // Get a brush for the legend label text using ( SolidBrush brushB = new SolidBrush( Color.Black ) ) { foreach ( GraphPane tmpPane in paneList ) { // Loop for each curve in the CurveList collection //foreach ( CurveItem curve in tmpPane.CurveList ) int count = tmpPane.CurveList.Count; for ( int i = 0; i < count; i++ ) { CurveItem curve = tmpPane.CurveList[_isReverse ? count - i - 1 : i]; if ( curve._label._text != "" && curve._label._isVisible ) { // Calculate the x,y (TopLeft) location of the current // curve legend label // assuming: // charHeight/2 for the left margin, plus legendWidth for each // horizontal column // legendHeight is the line spacing, with no extra margin above x = _rect.Left + halfGap / 2.0F + ( iEntry % _hStack ) * _legendItemWidth; y = _rect.Top + (int)( iEntry / _hStack ) * _legendItemHeight; // Draw the legend label for the current curve FontSpec tmpFont = ( curve._label._fontSpec != null ) ? curve._label._fontSpec : this.FontSpec; // This is required because, for long labels, the centering can affect the // position in GDI+. tmpFont.StringAlignment = StringAlignment.Near; if ( _isShowLegendSymbols ) { tmpFont.Draw( g, pane, curve._label._text, x + 2.5F * _tmpSize, y + _legendItemHeight / 2.0F, AlignH.Left, AlignV.Center, scaleFactor ); RectangleF rect = new RectangleF( x, y + _legendItemHeight / 4.0F, 2 * _tmpSize, _legendItemHeight / 2.0F ); curve.DrawLegendKey( g, tmpPane, rect, scaleFactor ); } else { if ( curve._label._fontSpec == null ) tmpFont.FontColor = curve.Color; tmpFont.Draw(g, pane, curve._label._text, x + 0.0F * _tmpSize, y + _legendItemHeight / 2.0F, AlignH.Left, AlignV.Center, scaleFactor); } // maintain a curve count for positioning iEntry++; } } if ( pane is MasterPane && ( (MasterPane)pane ).IsUniformLegendEntries ) break; } // Draw a border around the legend if required if ( iEntry > 0 ) this.Border.Draw( g, pane, scaleFactor, _rect ); } }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="BoxObj"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public override bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location RectangleF pixRect = Location.TransformRect( pane ); using ( GraphicsPath path = new GraphicsPath() ) { path.AddEllipse( pixRect ); return path.IsVisible( pt ); } }
private PaneList GetPaneList( PaneBase pane ) { // For a single GraphPane, create a PaneList to contain it // Otherwise, just use the paneList from the MasterPane PaneList paneList; if ( pane is GraphPane ) { paneList = new PaneList(); paneList.Add( (GraphPane)pane ); } else paneList = ( (MasterPane)pane ).PaneList; return paneList; }
/// <summary> /// Render this <see cref="TextObj"/> object to the specified <see cref="Graphics"/> device /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </summary> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = Location.Transform( pane ); // Draw the text on the screen, including any frame and background // fill elements if ( pix.X > -100000 && pix.X < 100000 && pix.Y > -100000 && pix.Y < 100000 ) { //if ( this.layoutSize.IsEmpty ) // this.FontSpec.Draw( g, pane.IsPenWidthScaled, this.text, pix.X, pix.Y, // this.location.AlignH, this.location.AlignV, scaleFactor ); //else this.FontSpec.Draw( g, pane, _text, pix.X, pix.Y, Location.AlignH, Location.AlignV, scaleFactor, _layoutArea ); } }
/// <summary> /// Transform this <see cref="Location"/> object to display device /// coordinates using the properties of the specified <see cref="GraphPane"/>. /// </summary> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that contains /// the <see cref="Axis"/> classes which will be used for the transform. /// </param> /// <returns>A point in display device coordinates that corresponds to the /// specified user point.</returns> public PointF Transform( PaneBase pane ) { return Transform( pane, _x, _y, _coordinateFrame ); }
/// <summary> /// Determines the shape type and Coords values for this GraphObj /// </summary> public override void GetCoords( PaneBase pane, Graphics g, float scaleFactor, out string shape, out string coords ) { // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = Location.Transform( pane ); PointF[] pts = _fontSpec.GetBox( g, _text, pix.X, pix.Y, Location.AlignH, Location.AlignV, scaleFactor, new SizeF() ); shape = "poly"; coords = String.Format( "{0:f0},{1:f0},{2:f0},{3:f0},{4:f0},{5:f0},{6:f0},{7:f0},", pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, pts[2].X, pts[2].Y, pts[3].X, pts[3].Y ); }
/// <summary> /// Transform the <see cref="RectangleF"/> for this object as defined by the /// <see cref="X"/>, <see cref="Y"/>, <see cref="Width"/>, and /// <see cref="Height"/> properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are honored in /// this transformation. /// </remarks> /// <value>A <see cref="RectangleF"/> in pixel units.</value> public RectangleF TransformRect( PaneBase pane ) { PointF pix1 = TransformTopLeft( pane ); PointF pix2 = TransformBottomRight( pane ); //PointF pix3 = TransformTopLeft( pane, pix2.X - pix1.X, pix2.Y - pix1.Y ); return new RectangleF( pix1.X, pix1.Y, Math.Abs(pix2.X - pix1.X), Math.Abs(pix2.Y - pix1.Y) ); }
/// <summary> /// Determine if the specified screen point lies inside the bounding box of this /// <see cref="TextObj"/>. This method takes into account rotation and alignment /// parameters of the text, as specified in the <see cref="FontSpec"/>. /// </summary> /// <param name="pt">The screen point, in pixels</param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <returns>true if the point lies in the bounding box, false otherwise</returns> public override bool PointInBox( PointF pt, PaneBase pane, Graphics g, float scaleFactor ) { if ( ! base.PointInBox(pt, pane, g, scaleFactor ) ) return false; // transform the x,y location from the user-defined // coordinate frame to the screen pixel location PointF pix = Location.Transform( pane ); return _fontSpec.PointInBox( pt, g, _text, pix.X, pix.Y, Location.AlignH, Location.AlignV, scaleFactor, this.LayoutArea ); }
/// <summary> /// The <see cref="PointF"/> for this object as defined by the /// <see cref="X"/> and <see cref="Y"/> /// properties. /// </summary> /// <remarks> /// This method transforms the location to output device pixel units. /// The <see cref="AlignH"/> and <see cref="AlignV"/> properties are ignored for /// this transformation (see <see cref="TransformTopLeft(PaneBase,float,float)"/>). /// </remarks> /// <value>A <see cref="PointF"/> in pixel units.</value> public PointF TransformTopLeft( PaneBase pane ) { return Transform( pane ); }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw( Graphics g, PaneBase pane, float scaleFactor ) { if ( _points != null && _points.Length > 1 ) { using ( GraphicsPath path = MakePath( pane ) ) { // Fill or draw the symbol as required if ( _fill.IsVisible ) { using ( Brush brush = this.Fill.MakeBrush( path.GetBounds() ) ) g.FillPath( brush, path ); } if ( _border.IsVisible ) { using ( Pen pen = _border.GetPen( pane, scaleFactor ) ) g.DrawPath( pen, path ); } } } }
/// <summary> /// Create a <see cref="Pen" /> object based on the properties of this /// <see cref="LineBase" />. /// </summary> /// <param name="pane">The owner <see cref="GraphPane" /> of this /// <see cref="LineBase" />. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> /// <param name="dataValue">The data value to be used for a value-based /// color gradient. This is only applicable if <see cref="Fill.Type">GradientFill.Type</see> /// is one of <see cref="FillType.GradientByX"/>, /// <see cref="FillType.GradientByY"/>, <see cref="FillType.GradientByZ"/>, /// or <see cref="FillType.GradientByColorValue" />. /// </param> /// <returns>A <see cref="Pen" /> object with the properties of this <see cref="LineBase" /> /// </returns> public Pen GetPen( PaneBase pane, float scaleFactor, PointPair dataValue ) { Color color = _color; if ( _gradientFill.IsGradientValueType ) color = _gradientFill.GetGradientColor( dataValue ); Pen pen = new Pen( color, pane.ScaledPenWidth( _width, scaleFactor ) ); pen.DashStyle = _style; if ( _style == DashStyle.Custom ) { if ( _dashOff > 1e-10 && _dashOn > 1e-10 ) { pen.DashStyle = DashStyle.Custom; float[] pattern = new float[2]; pattern[0] = _dashOn; pattern[1] = _dashOff; pen.DashPattern = pattern; } else pen.DashStyle = DashStyle.Solid; } return pen; }
/// <summary> /// Render this object to the specified <see cref="Graphics"/> device. /// </summary> /// <remarks> /// This method is normally only called by the Draw method /// of the parent <see cref="GraphObjList"/> collection object. /// </remarks> /// <param name="g"> /// A graphic device object to be drawn into. This is normally e.Graphics from the /// PaintEventArgs argument to the Paint() method. /// </param> /// <param name="pane"> /// A reference to the <see cref="PaneBase"/> object that is the parent or /// owner of this object. /// </param> /// <param name="scaleFactor"> /// The scaling factor to be used for rendering objects. This is calculated and /// passed down by the parent <see cref="GraphPane"/> object using the /// <see cref="PaneBase.CalcScaleFactor"/> method, and is used to proportionally adjust /// font sizes, etc. according to the actual size of the graph. /// </param> public override void Draw( Graphics g, PaneBase pane, float scaleFactor ) { // Convert the arrow coordinates from the user coordinate system // to the screen coordinate system PointF pix1 = this.Location.TransformTopLeft( pane ); PointF pix2 = this.Location.TransformBottomRight( pane ); if ( pix1.X > -10000 && pix1.X < 100000 && pix1.Y > -100000 && pix1.Y < 100000 && pix2.X > -10000 && pix2.X < 100000 && pix2.Y > -100000 && pix2.Y < 100000 ) { // calculate the length and the angle of the arrow "vector" double dy = pix2.Y - pix1.Y; double dx = pix2.X - pix1.X; float angle = (float)Math.Atan2( dy, dx ) * 180.0F / (float)Math.PI; float length = (float)Math.Sqrt( dx * dx + dy * dy ); // Save the old transform matrix Matrix transform = g.Transform; // Move the coordinate system so it is located at the starting point // of this arrow g.TranslateTransform( pix1.X, pix1.Y ); // Rotate the coordinate system according to the angle of this arrow // about the starting point g.RotateTransform( angle ); // get a pen according to this arrow properties using ( Pen pen = _line.GetPen( pane, scaleFactor ) ) //new Pen( _line._color, pane.ScaledPenWidth( _line._width, scaleFactor ) ) ) { //pen.DashStyle = _style; g.DrawLine( pen, 0, 0, length, 0 ); } // Restore the transform matrix back to its original state g.Transform = transform; } }