// param specify reference or name of axis. public void Add(IPlot p, XAxisPosition xp, YAxisPosition yp) { plots_.Add(p); xAxisPositions_.Add(xp); yAxisPositions_.Add(yp); UpdateAxes(); }
public void AddPointPlot( IEnumerable <TX> xSeries, XAxisPosition xpos, IEnumerable <TY> ySeries, YAxisPosition ypos, MarkerType _markerType, int MarkerSize, Color MarkerColor, bool MarkerFilled, bool ShowLabelInLegend) { NPlot.PointPlot plot = new NPlot.PointPlot(); plot.AbscissaData = xSeries; plot.OrdinateData = ySeries; plot.Marker = new NPlot.Marker(ToNPlotMarkerType(_markerType), MarkerSize, MarkerColor); plot.ShowInLegend = ShowLabelInLegend; MyPlot my = new MyPlot(); my.plot = plot; my.XAxisPosition = xpos == XAxisPosition.Bottom ? NPlot.PlotSurface2D.XAxisPosition.Bottom : NPlot.PlotSurface2D.XAxisPosition.Top; my.YAxisPosition = ypos == YAxisPosition.Left ? NPlot.PlotSurface2D.YAxisPosition.Left : NPlot.PlotSurface2D.YAxisPosition.Right; plots.Add(my); }
/// <summary> /// Returns the x-axis associated with a given plot. /// </summary> /// <param name="plot">the plot to get associated x-axis.</param> /// <returns>the axis associated with the plot.</returns> public Axis WhichXAxis(IPlot plot) { int index = drawables_.IndexOf(plot); XAxisPosition p = (XAxisPosition)xAxisPositions_[index]; return((xAxisOverrides_[index] != null) ? (Axis)xAxisOverrides_[index] : (p == XAxisPosition.Bottom) ? this.xAxis1_ : this.xAxis2_); }
/// <summary> /// Default constructor. /// </summary> public Legend() { xAttach_ = XAxisPosition.Top; yAttach_ = YAxisPosition.Right; xOffset_ = 10; yOffset_ = 1; verticalEdgePlacement_ = Placement.Outside; horizontalEdgePlacement_ = Placement.Inside; neverShiftAxes_ = false; }
public void CreateXLog10Axis(XAxisPosition xpos) { if (xpos == XAxisPosition.Bottom) { _XAxisBottomType = AxisType.log10; } else { _XAxisTopType = AxisType.log10; } }
internal override void RenderAxis() { XAxisPosition position = (XAxisPosition)GetValue(XAxisPositionProperty); Point tickPosition; StreamGeometryContext lineContext = axisLineGeometry.Open(); if (!IsInnermost) { Point axisStart = new Point(MinTransformed * Scale - Offset - axisLine.StrokeThickness / 2, yPosition); lineContext.BeginFigure(axisStart, false, false); lineContext.LineTo(new Point(MaxTransformed * Scale - Offset + axisLine.StrokeThickness / 2, yPosition), true, false); } lineContext.Close(); StreamGeometryContext ticksContext = axisTicksGeometry.Open(); if (TicksVisible) { for (int i = 0; i < TicksTransformed.Length; ++i) { tickPosition = TickStartPosition(i); ticksContext.BeginFigure(tickPosition, false, false); if (position == XAxisPosition.Bottom) { tickPosition.Y = tickPosition.Y + TickLength; } if (position == XAxisPosition.Top) { tickPosition.Y = tickPosition.Y - TickLength; } ticksContext.LineTo(tickPosition, true, false); ticksContext.BeginFigure(tickPosition, false, false); tickPosition.Y = tickPosition.Y; ticksContext.LineTo(tickPosition, true, false); } } ticksContext.Close(); interactionPad.Width = Math.Max(AxisTotalLength - AxisPadding.Total(), 1); interactionPad.Height = AxisThickness; if (position == XAxisPosition.Bottom) { interactionPad.SetValue(Canvas.TopProperty, yPosition); } else { interactionPad.SetValue(Canvas.TopProperty, yPosition - AxisThickness); } double xPosition = Scale * MinTransformed - Offset; interactionPad.SetValue(Canvas.LeftProperty, xPosition); base.RenderAxis(); }
// X- Achsen public void CreateXLinearAxis(XAxisPosition xpos) { if (xpos == XAxisPosition.Bottom) { _XAxisBottomType = AxisType.linear; } else { _XAxisTopType = AxisType.linear; } }
/// <summary> /// Returns the x-axis associated with a given plot. /// </summary> /// <param name="plot">the plot to get associated x-axis.</param> /// <returns>the axis associated with the plot.</returns> public Axis WhichXAxis(IPlot plot) { int index = drawables_.IndexOf(plot); XAxisPosition p = (XAxisPosition)xAxisPositions_[index]; if (p == XAxisPosition.Bottom) { return(xAxis1_); } else { return(xAxis2_); } }
/// <summary> /// Adds a drawable object to the plot surface against the specified axes. If /// the object is an IPlot, the PlotSurface2D axes will also be updated. /// </summary> /// <param name="p">the IDrawable object to add to the plot surface</param> /// <param name="xp">the x-axis to add the plot against.</param> /// <param name="yp">the y-axis to add the plot against.</param> /// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param> public void Add(IDrawable p, XAxisPosition xp, YAxisPosition yp, int zOrder) { drawables_.Add(p); xAxisPositions_.Add(xp); yAxisPositions_.Add(yp); zPositions_.Add((double)zOrder); // fraction is to make key unique. With 10 million plots at same z, this buggers up.. double fraction = (double)(++uniqueCounter_) / 10000000.0f; ordering_.Add((double)zOrder + fraction, drawables_.Count - 1); // if p is just an IDrawable, then it can't affect the axes. if (p is IPlot) { UpdateAxes(false); } }
public void CreateXLabelAxis( IEnumerable <double> xSeries, IEnumerable <string> xSeriesLabels, XAxisPosition xpos ) { if (xpos == XAxisPosition.Bottom) { _XAxisBottomType = AxisType.label; _XAxisBottomSeries = xSeries; _XAxisBottomLabels = xSeriesLabels; } else { _XAxisTopType = AxisType.label; _XAxisTopSeries = xSeries; _XAxisTopLabels = xSeriesLabels; } }
// Zu plotende Funktionen definieren public void AddLinePlot( IEnumerable <TX> xSeries, XAxisPosition xpos, IEnumerable <TY> ySeries, YAxisPosition ypos, Color _color, string Label, bool ShowLabelInLegend) { NPlot.LinePlot plot = new NPlot.LinePlot(ySeries, xSeries); plot.ShowInLegend = ShowLabelInLegend; plot.Label = Label; plot.Color = _color; MyPlot my = new MyPlot(); my.plot = plot; my.XAxisPosition = xpos == XAxisPosition.Bottom ? NPlot.PlotSurface2D.XAxisPosition.Bottom : NPlot.PlotSurface2D.XAxisPosition.Top; my.YAxisPosition = ypos == YAxisPosition.Left ? NPlot.PlotSurface2D.YAxisPosition.Left : NPlot.PlotSurface2D.YAxisPosition.Right; plots.Add(my); }
private void Init() { plots_ = new System.Collections.ArrayList(); xAxisPositions_ = new System.Collections.ArrayList(); yAxisPositions_ = new System.Collections.ArrayList(); FontFamily fontFamily = new FontFamily("Arial"); TitleFont = new Font(fontFamily, 14, FontStyle.Regular, GraphicsUnit.Pixel); padding_ = 10; title_ = ""; autoScale_ = true; minorGridPen_ = new Pen(Color.LightGray); float[] pattern = { 1.0f, 2.0f }; minorGridPen_.DashPattern = pattern; majorGridPen_ = new Pen(Color.LightGray); xAxis1_ = null; xAxis2_ = null; yAxis1_ = null; yAxis2_ = null; pXAxis1Cache_ = null; pYAxis1Cache_ = null; pXAxis2Cache_ = null; pYAxis2Cache_ = null; titleBrush_ = new SolidBrush(Color.Black); plotBackColor_ = Color.White; showLegend_ = false; legendOffsetXAxis_ = XAxisPosition.Top; legendOffsetYAxis_ = YAxisPosition.Right; legendOffsetX_ = 10.0f; legendOffsetY_ = 1.0f; legendBorderStyle_ = Legend.BorderType.Shadow; verticalEdgeLegendPlacement_ = Legend.Placement.Outside; horizontalEdgeLegendPlacement_ = Legend.Placement.Inside; }
private void UpdateAxes() { // make sure our lists exist if (plots_.Count == 0 || xAxisPositions_.Count == 0 || yAxisPositions_.Count == 0) { throw new System.Exception("UpdateAxes called from function other than Add."); } int last = plots_.Count - 1; if (last != xAxisPositions_.Count - 1 || last != yAxisPositions_.Count - 1) { throw new System.Exception("plots and axis position arrays our of sync"); } IPlot p = (IPlot)plots_[last]; XAxisPosition xap = (XAxisPosition)xAxisPositions_[last]; YAxisPosition yap = (YAxisPosition)yAxisPositions_[last]; if (xap == XAxisPosition.Bottom) { if (xAxis1_ == null) { xAxis1_ = p.SuggestXAxis(); xAxis1_.TicksAngle = -Math.PI / 2.0f; } else { xAxis1_.LUB(p.SuggestXAxis()); } } if (xap == XAxisPosition.Top) { if (xAxis2_ == null) { xAxis2_ = p.SuggestXAxis(); xAxis2_.TicksAngle = Math.PI / 2.0f; } else { xAxis2_.LUB(p.SuggestXAxis()); } } if (yap == YAxisPosition.Left) { if (yAxis1_ == null) { yAxis1_ = p.SuggestYAxis(); yAxis1_.TicksAngle = Math.PI / 2.0f; } else { yAxis1_.LUB(p.SuggestYAxis()); } } if (yap == YAxisPosition.Right) { if (yAxis2_ == null) { yAxis2_ = p.SuggestYAxis(); yAxis2_.TicksAngle = -Math.PI / 2.0f; } else { yAxis2_.LUB(p.SuggestYAxis()); } } }
/// <summary> /// Constructor /// </summary> /// <param name="a">Aspect Ratio</param> /// <param name="holdFixedX">When adjusting the position of axes, the specified axis will never be moved.</param> /// <param name="holdFixedY">When adjusting the position of axes, the specified axis will never be moved.</param> public AspectRatio(double a, XAxisPosition holdFixedX, YAxisPosition holdFixedY) { this.a_ = a; this.holdFixedX_ = holdFixedX; this.holdFixedY_ = holdFixedY; }
/// <summary> /// Specify the Axes to attach the legend to. /// </summary> /// <param name="xa">Specify which horizontal axis the legend should be attached to.</param> /// <param name="ya">Specify which vertical axis the legend should be attached to.</param> public void AttachTo(XAxisPosition xa, YAxisPosition ya) { xAttach_ = xa; yAttach_ = ya; }
/// <summary> /// Adds a drawable object to the plot surface against the specified axes. If /// the object is an IPlot, the PlotSurface2D axes will also be updated. /// </summary> /// <param name="p">the IDrawable object to add to the plot surface</param> /// <param name="xp">the x-axis to add the plot against.</param> /// <param name="yp">the y-axis to add the plot against.</param> /// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param> public void Add(IDrawable p, XAxisPosition xp, YAxisPosition yp, int zOrder) { Add(p, xp, yp, zOrder, null, null); }
private void UpdateAxes(bool recalculateAll) { if (drawables_.Count != xAxisPositions_.Count || drawables_.Count != yAxisPositions_.Count) { throw new NPlotException("plots and axis position arrays our of sync"); } int position = 0; // if we're not recalculating axes using all iplots then set // position to last one in list. if (!recalculateAll) { position = drawables_.Count - 1; if (position < 0) { position = 0; } } if (recalculateAll) { xAxis1_ = null; yAxis1_ = null; xAxis2_ = null; yAxis2_ = null; } for (int i = position; i < drawables_.Count; ++i) { // only update axes if this drawable is an IPlot. if (!(drawables_[position] is IPlot)) { continue; } IPlot p = (IPlot)drawables_[position]; XAxisPosition xap = (XAxisPosition)xAxisPositions_[position]; YAxisPosition yap = (YAxisPosition)yAxisPositions_[position]; if (xap == XAxisPosition.Bottom) { if (xAxis1_ == null) { xAxis1_ = p.SuggestXAxis(); if (xAxis1_ != null) { xAxis1_.TicksAngle = -(float)Math.PI / 2.0f; } } else { xAxis1_.LUB(p.SuggestXAxis()); } if (xAxis1_ != null) { xAxis1_.MinPhysicalLargeTickStep = 50; if (AutoScaleAutoGeneratedAxes) { xAxis1_.AutoScaleText = true; xAxis1_.AutoScaleTicks = true; xAxis1_.TicksIndependentOfPhysicalExtent = true; } else { xAxis1_.AutoScaleText = false; xAxis1_.AutoScaleTicks = false; xAxis1_.TicksIndependentOfPhysicalExtent = false; } } } if (xap == XAxisPosition.Top) { if (xAxis2_ == null) { xAxis2_ = p.SuggestXAxis(); if (xAxis2_ != null) { xAxis2_.TicksAngle = (float)Math.PI / 2.0f; } } else { xAxis2_.LUB(p.SuggestXAxis()); } if (xAxis2_ != null) { xAxis2_.MinPhysicalLargeTickStep = 50; if (AutoScaleAutoGeneratedAxes) { xAxis2_.AutoScaleText = true; xAxis2_.AutoScaleTicks = true; xAxis2_.TicksIndependentOfPhysicalExtent = true; } else { xAxis2_.AutoScaleText = false; xAxis2_.AutoScaleTicks = false; xAxis2_.TicksIndependentOfPhysicalExtent = false; } } } if (yap == YAxisPosition.Left) { if (yAxis1_ == null) { yAxis1_ = p.SuggestYAxis(); if (yAxis1_ != null) { yAxis1_.TicksAngle = (float)Math.PI / 2.0f; } } else { yAxis1_.LUB(p.SuggestYAxis()); } if (yAxis1_ != null) { if (AutoScaleAutoGeneratedAxes) { yAxis1_.AutoScaleText = true; yAxis1_.AutoScaleTicks = true; yAxis1_.TicksIndependentOfPhysicalExtent = true; } else { yAxis1_.AutoScaleText = false; yAxis1_.AutoScaleTicks = false; yAxis1_.TicksIndependentOfPhysicalExtent = false; } } } if (yap == YAxisPosition.Right) { if (yAxis2_ == null) { yAxis2_ = p.SuggestYAxis(); if (yAxis2_ != null) { yAxis2_.TicksAngle = -(float)Math.PI / 2.0f; } } else { yAxis2_.LUB(p.SuggestYAxis()); } if (yAxis2_ != null) { if (AutoScaleAutoGeneratedAxes) { yAxis2_.AutoScaleText = true; yAxis2_.AutoScaleTicks = true; yAxis2_.TicksIndependentOfPhysicalExtent = true; } else { yAxis2_.AutoScaleText = false; yAxis2_.AutoScaleTicks = false; yAxis2_.TicksIndependentOfPhysicalExtent = false; } } } } }
/// <summary> /// Constructor, which defines an horizontal axis and the physical /// y position it should be drawn at. /// </summary> /// <param name="axis">The x-axis for which the y position is to be specified.</param> /// <param name="yPosition">The [physical] y position of the axis.</param> public AxisPosition(XAxisPosition axis, double yPosition) { position_ = yPosition; xAxisPosition_ = axis; }
/// <summary> /// Constructor /// </summary> /// <param name="a">Aspect Ratio</param> /// <param name="holdFixedX"> /// When adjusting the position of axes, the specified axis will never /// be moved. /// </param> public AspectRatio(double a, XAxisPosition holdFixedX) { a_ = a; holdFixedX_ = holdFixedX; }
/// <summary> /// Constructor, which defines an horizontal axis and the physical /// y position it should be drawn at. /// </summary> /// <param name="axis">The x-axis for which the y position is to be specified.</param> /// <param name="yPosition">The [physical] y position of the axis.</param> public Position(XAxisPosition axis, int yPosition) { position_ = yPosition; xAxisPosition_ = axis; }
public void LegendAttachTo(XAxisPosition xa, YAxisPosition ya) { ps_.LegendAttachTo(xa, ya); }
/// <summary> /// Adds a drawable object to the plot surface against the specified axes. If /// the object is an IPlot, the PlotSurface2D axes will also be updated. /// </summary> /// <param name="p">the IDrawable object to add to the plot surface</param> /// <param name="xp">the x-axis to add the plot against.</param> /// <param name="yp">the y-axis to add the plot against.</param> /// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param> public void Add( IDrawable p, XAxisPosition xp, YAxisPosition yp, int zOrder ) { drawables_.Add( p ); xAxisPositions_.Add( xp ); yAxisPositions_.Add( yp ); zPositions_.Add((double)zOrder); // fraction is to make key unique. With 10 million plots at same z, this buggers up.. double fraction = (double)(++uniqueCounter_)/10000000.0f; ordering_.Add( (double)zOrder + fraction, drawables_.Count - 1 ); // if p is just an IDrawable, then it can't affect the axes. if ( p is IPlot ) { UpdateAxes( false ); } }
/// <summary> /// Draw the the PlotSurface and contents (axes, drawables, and legend) using the /// Drawing Context supplied and the bounding rectangle for the PlotSurface to cover /// </summary> /// <param name="ctx">The Drawing Context with which to draw.</param> /// <param name="bounds">The rectangle within which to draw</param> public void Draw(Context ctx, Rectangle bounds) { Point titleOrigin = Point.Zero; ctx.Save(); // determine font sizes and tick scale factor. double scale = DetermineScaleFactor(bounds.Width, bounds.Height); // if there is nothing to plot, draw title and return. if (drawables.Count == 0) { // draw title //TODO: Title should be centred here - not its origin Point origin = Point.Zero; titleOrigin.X = bounds.Width / 2; titleOrigin.Y = bounds.Height / 2; DrawTitle(ctx, titleOrigin, scale); ctx.Restore(); 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; 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; DeterminePhysicalAxesToDraw( bounds, XAxis1, XAxis2, YAxis1, YAxis2, out pXAxis1, out pXAxis2, out pYAxis1, out pYAxis2); double 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 (legend != null) { legend.UpdateAxesPositions( pXAxis1, pYAxis1, pXAxis2, pYAxis2, drawables, scale, Padding, bounds, out legendPosition); } double newXAxis2Height = pXAxis2.PhysicalMin.Y; double titleExtraOffset = oldXAxis2Height - newXAxis2Height; // now we are ready to define the clipping region 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(); Rectangle plotBounds = (Rectangle)plotAreaBoundingBoxCache; // set the clipping region.. (necessary for zoom) // Note: although clipping is enforced by the clip region, it is probably more efficient // for each Drawable to check against the plotBounds and not draw if points are outside. // This hasn't yet been implemented ctx.Save(); ctx.Rectangle(plotBounds); ctx.Clip(); // Fill in the plot background. if (plotBackImage != null) { // Ensure plotBounds has integer size for correct tiling/drawing plotBounds.Width = Math.Truncate(plotBounds.Width); plotBounds.Height = Math.Truncate(plotBounds.Height); ctx.DrawImage(Utils.TiledImage(plotBackImage, plotBounds.Size), plotBounds); } else if (plotBackGradient != null) { // Scale plotBackGradient to plotBounds double startX = plotBounds.X + (plotBackGradient.StartPoint.X * plotBounds.Width); double startY = plotBounds.Y + (plotBackGradient.StartPoint.Y * plotBounds.Height); double endX = plotBounds.X + (plotBackGradient.EndPoint.X * plotBounds.Width); double endY = plotBounds.Y + (plotBackGradient.EndPoint.Y * plotBounds.Height); LinearGradient g = new LinearGradient(startX, startY, endX, endY); g.AddColorStop(0, plotBackGradient.StartColor); g.AddColorStop(1, plotBackGradient.EndColor); ctx.Rectangle(plotBounds); ctx.Pattern = g; ctx.Fill(); } else { ctx.Rectangle(plotBounds); ctx.SetColor(plotBackColor); ctx.Fill(); } // draw title at centre of Physical X-axis and at top of plot titleOrigin.X = (pXAxis2.PhysicalMax.X + pXAxis2.PhysicalMin.X) / 2.0; titleOrigin.Y = bounds.Top + Padding - titleExtraOffset; Size s = DrawTitle(ctx, titleOrigin, scale); bbTitleCache = new Rectangle(titleOrigin.X - s.Width / 2, titleOrigin.Y, s.Width, s.Height); // draw drawables.. 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 > legendZOrder) { // draw legend. if (!legendDrawn && legend != null) { legend.Draw(ctx, legendPosition, 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; } drawable.Draw(ctx, drawXAxis, drawYAxis); } if (!legendDrawn && legend != null) { legend.Draw(ctx, legendPosition, drawables, scale); } ctx.Restore(); // end of clipping region // cache the physical axes we used on this draw; pXAxis1Cache = pXAxis1; pYAxis1Cache = pYAxis1; pXAxis2Cache = pXAxis2; pYAxis2Cache = pYAxis2; // now draw axes. Rectangle axisBounds; pXAxis1.Draw(ctx, out axisBounds); pXAxis2.Draw(ctx, out axisBounds); pYAxis1.Draw(ctx, out axisBounds); pYAxis2.Draw(ctx, out axisBounds); #if DEBUG_BOUNDING_BOXES ctx.SetColor(Colors.Orange); ctx.Rectangle((Rectangle)bbXAxis1Cache); ctx.Rectangle((Rectangle)bbXAxis2Cache); ctx.Rectangle((Rectangle)bbYAxis1Cache); ctx.Rectangle((Rectangle)bbYAxis2Cache); ctx.Stroke(); ctx.SetColor(Colors.Red); ctx.Rectangle((Rectangle)plotAreaBoundingBoxCache); ctx.Rectangle((Rectangle)bbTitleCache); ctx.Stroke(); #endif ctx.Restore(); }
/// <summary> /// Adds a drawable object to the plot surface against the specified axes. If /// the object is an IPlot, the PlotSurface2D axes will also be updated. /// </summary> /// <param name="p">the IDrawable object to add to the plot surface</param> /// <param name="xp">the x-axis to add the plot against.</param> /// <param name="yp">the y-axis to add the plot against.</param> /// <param name="zOrder">The z-ordering when drawing (objects with lower numbers are drawn first)</param> public void Add(IDrawable p, XAxisPosition xp, YAxisPosition yp, int zOrder) { ps_.Add(p, xp, yp, zOrder); }
/// <summary> /// Adds a drawable object to the plot surface against the specified axes with /// z-order of 0. If the object is an IPlot, the PlotSurface2D axes will also /// be updated. /// </summary> /// <param name="p">the IDrawable object to add to the plot surface</param> /// <param name="xp">the x-axis to add the plot against.</param> /// <param name="yp">the y-axis to add the plot against.</param> public void Add(IDrawable p, XAxisPosition xp, YAxisPosition yp) { Add(p, xp, yp, 0); }
/// <summary> /// Draw the plot on the drawing surface /// </summary> /// <param name="g">The GDI+ drawing surface on which to render.</param> /// <param name="bounds">The bounding rectangle on the drawing surface to be considered the plot area.</param> public void Draw(Graphics g, Rectangle bounds) { if (plots_.Count == 0) { return; // TODO: better output in this case. } float scale = (float)DetermineScaleFactor(bounds.Width, bounds.Height); if (xAxis1_ == null) { xAxis1_ = (Axis)xAxis2_.Clone(); xAxis1_.HideTickText = true; xAxis1_.TicksAngle = -Math.PI / 2.0f; } if (xAxis2_ == null) { xAxis2_ = (Axis)xAxis1_.Clone(); xAxis2_.HideTickText = true; xAxis2_.TicksAngle = Math.PI / 2.0f; } if (yAxis1_ == null) { yAxis1_ = (Axis)yAxis2_.Clone(); yAxis1_.HideTickText = true; yAxis1_.TicksAngle = Math.PI / 2.0f; } if (yAxis2_ == null) { yAxis2_ = (Axis)yAxis1_.Clone(); yAxis2_.HideTickText = true; yAxis2_.TicksAngle = -Math.PI / 2.0f; } // TODO: fix this so these not automatically overwritten. xAxis1_.TickScale = scale; xAxis1_.FontScale = scale; yAxis1_.TickScale = scale; yAxis1_.FontScale = scale; xAxis2_.TickScale = scale; xAxis2_.FontScale = scale; yAxis2_.TickScale = scale; yAxis2_.FontScale = scale; // now have axes world info. set physical limits. // first guess axes positions, then find bounding box, then change // to align nicely with side of control. System.Drawing.Rectangle cb = bounds; RectangleF bb; // guess physical x axis (bottom). Put it at the bottom of the plot PhysicalAxis pXAxis1 = new PhysicalAxis(xAxis1_, new Point(cb.Left, cb.Bottom), new Point(cb.Right, cb.Bottom)); int bottomIndent = (int)(padding_); if (!pXAxis1.Axis.Hidden) { // evaluate its bounding box bb = pXAxis1.GetBoundingBox(); // finally determine its indentation from the bottom bottomIndent = (int)(bottomIndent + bb.Bottom - cb.Bottom); } // guess physical y axis (left). Put it at the left side. PhysicalAxis pYAxis1 = new PhysicalAxis(yAxis1_, new Point(cb.Left, cb.Bottom), new Point(cb.Left, cb.Top)); int leftIndent = (int)(padding_); if (!pYAxis1.Axis.Hidden) { // evaluate its bounding box bb = pYAxis1.GetBoundingBox(); // finally determine its indentation from the left leftIndent = (int)(leftIndent - bb.Left + cb.Left); } // guess secondary x axis (top). PhysicalAxis pXAxis2 = new PhysicalAxis(xAxis2_, new Point(cb.Left, cb.Top), new Point(cb.Right, cb.Top)); int topIndent = (int)(padding_); double titleHeight = FontScaler.scaleFont(titleFont_, scale).Height; if (!pXAxis2.Axis.Hidden) { // evaluate its bounding box bb = pXAxis2.GetBoundingBox(); topIndent = (int)(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)((double)titleHeight * 1.3f); } } // guess secondary y axis (right). Put it at the right side. PhysicalAxis pYAxis2 = new PhysicalAxis(yAxis2_, new Point(cb.Right, cb.Bottom), new Point(cb.Right, cb.Top)); int rightIndent = (int)(padding_); if (!pYAxis2.Axis.Hidden) { // evaluate its bounding box bb = pYAxis2.GetBoundingBox(); // finally determine its indentation from the right rightIndent = (int)(rightIndent + bb.Right - cb.Right); } // now determine if legend should change any of these (legend should be fully // visible at all times), and draw legend. Legend legend = null; float lXPos = 0.0f; float lYPos = 0.0f; if (showLegend_) { legend = new Legend(); legend.BorderStyle = LegendBorderStyle; RectangleF legendWidthHeight = legend.GetBoundingBox(0, 0, plots_, scale); // calculate legend position. lYPos = legendOffsetY_; if (legendOffsetXAxis_ == XAxisPosition.Bottom) { lYPos += cb.Bottom - bottomIndent; if (horizontalEdgeLegendPlacement_ == Legend.Placement.Inside) { lYPos -= legendWidthHeight.Height; } } else { lYPos += cb.Top + topIndent; if (horizontalEdgeLegendPlacement_ == Legend.Placement.Outside) { lYPos -= legendWidthHeight.Height; } } lXPos = legendOffsetX_; if (legendOffsetYAxis_ == YAxisPosition.Left) { if (verticalEdgeLegendPlacement_ == Legend.Placement.Outside) { lXPos -= legendWidthHeight.Width; } lXPos += cb.Left + leftIndent; } else { if (verticalEdgeLegendPlacement_ == Legend.Placement.Inside) { lXPos -= legendWidthHeight.Width; } lXPos += cb.Right - rightIndent; } // update axes positions if need to for legend position. if (lXPos < padding_) { int changeAmount = -(int)lXPos + padding_; // only allow axes to move away from bounds. if (changeAmount > 0) { leftIndent += changeAmount; } lXPos += changeAmount; } if (lXPos + legendWidthHeight.Width > bounds.Right - padding_) { int changeAmount = ((int)lXPos - bounds.Right + (int)legendWidthHeight.Width + padding_); // only allow axes to move away from bounds. if (changeAmount > 0) { rightIndent += changeAmount; } lXPos -= changeAmount; } if (lYPos < padding_) { int changeAmount = -(int)lYPos + padding_; // only allow axes to move away from bounds. if (changeAmount > 0) { topIndent += changeAmount; } lYPos += changeAmount; } if (lYPos + legendWidthHeight.Height > bounds.Bottom - padding_) { int changeAmount = ((int)lYPos - bounds.Bottom + (int)legendWidthHeight.Height + padding_); // only allow axes to move away from bounds. if (changeAmount > 0) { bottomIndent += changeAmount; } lYPos -= changeAmount; } } // now we have all the 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); // now we are ready to define the bounding box for the plot area (to use in clipping // operations. plotAreaBoundingBoxCache_ = new Rectangle(cb.Left + leftIndent, cb.Top + topIndent, cb.Width - leftIndent - rightIndent, cb.Height - topIndent - bottomIndent); #if _IWANNASEE_ bb = pXAxis1.GetBoundingBox(); g.DrawRectangle(new Pen(Color.Orange), bb.X, bb.Y, bb.Width, bb.Height); bb = pXAxis2.GetBoundingBox(); g.DrawRectangle(new Pen(Color.Orange), bb.X, bb.Y, bb.Width, bb.Height); bb = pYAxis1.GetBoundingBox(); g.DrawRectangle(new Pen(Color.Orange), bb.X, bb.Y, bb.Width, bb.Height); bb = pYAxis2.GetBoundingBox(); g.DrawRectangle(new Pen(Color.Orange), bb.X, bb.Y, bb.Width, bb.Height); g.DrawRectangle(new Pen(Color.Red, 5.0F), plotAreaBoundingBox_); #endif // Fill in the background. if (plotBackColor_ != null) { g.FillRectangle(new System.Drawing.SolidBrush((Color)plotBackColor_), pYAxis1.PhysicalMin.X, pXAxis2.PhysicalMax.Y, pXAxis1.PhysicalMax.X - pXAxis1.PhysicalMin.X, pYAxis1.PhysicalMin.Y - pYAxis1.PhysicalMax.Y); } // draw title StringFormat drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Center; g.DrawString(title_, FontScaler.scaleFont(titleFont_, scale), titleBrush_, new PointF((pXAxis2.PhysicalMax.X + pXAxis2.PhysicalMin.X) / 2.0f, cb.Top + padding_), drawFormat); // now draw grid. DrawGrid(g, pXAxis1, pYAxis1, pXAxis2, pYAxis2); // now draw axes. pXAxis1.Draw(g); pXAxis2.Draw(g); pYAxis1.Draw(g); pYAxis2.Draw(g); // draw plots. for (int i = 0; i < plots_.Count; ++i) { IPlot plot = (IPlot)plots_[i]; XAxisPosition xap = (XAxisPosition)xAxisPositions_[i]; YAxisPosition yap = (YAxisPosition)yAxisPositions_[i]; PhysicalAxis xAxis; PhysicalAxis yAxis; if (xap == XAxisPosition.Bottom) { xAxis = pXAxis1; } else { xAxis = pXAxis2; } if (yap == YAxisPosition.Left) { yAxis = pYAxis1; } else { yAxis = pYAxis2; } // set the clipping region.. (necessary for zoom) g.Clip = new Region((Rectangle)plotAreaBoundingBoxCache_); // plot.. plot.Draw(g, xAxis, yAxis); // reset it.. g.ResetClip(); // cache the physical axes we used on this draw; pXAxis1Cache_ = pXAxis1; pYAxis1Cache_ = pYAxis1; pXAxis2Cache_ = pXAxis2; pYAxis2Cache_ = pYAxis2; } if (legend != null) { legend.Draw(g, (int)lXPos, (int)lYPos, plots_, scale); } }
/// <summary> /// Constructor /// </summary> /// <param name="a">Aspect Ratio</param> /// <param name="holdFixedX">When adjusting the position of axes, the specified axis will never be moved.</param> /// <param name="holdFixedY">When adjusting the position of axes, the specified axis will never be moved.</param> public AspectRatio(double a, XAxisPosition holdFixedX, YAxisPosition holdFixedY) { a_ = a; holdFixedX_ = holdFixedX; holdFixedY_ = holdFixedY; }
public void LegendAttachTo(XAxisPosition xa, YAxisPosition ya) { legendOffsetXAxis_ = xa; legendOffsetYAxis_ = ya; }
/// <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) { // 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 (AutoScaleTitle) { scaled_font = Utils.ScaleFont(titleFont_, scale); } else { scaled_font = titleFont_; } g.DrawString(title_, scaled_font, 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; 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; 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 (legend_ != null) { legend_.UpdateAxesPositions( pXAxis1, pYAxis1, pXAxis2, pYAxis2, drawables_, scale, 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 (plotBackColor_ != null) { g.FillRectangle( new System.Drawing.SolidBrush((Color)plotBackColor_), (Rectangle)plotAreaBoundingBoxCache_); } else if (plotBackBrush_ != null) { g.FillRectangle( plotBackBrush_.Get((Rectangle)plotAreaBoundingBoxCache_), (Rectangle)plotAreaBoundingBoxCache_); } else if (plotBackImage_ != null) { g.DrawImage( Utils.TiledImage(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 + padding_ - titleExtraOffset; Font scaledFont; if (AutoScaleTitle) { scaledFont = Utils.ScaleFont(titleFont_, scale); } else { scaledFont = titleFont_; } g.DrawString(title_, scaledFont, 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 = 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 > legendZOrder_) { // draw legend. if (!legendDrawn && legend_ != null) { legend_.Draw(g, legendPosition, 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 && legend_ != null) { legend_.Draw(g, legendPosition, drawables_, scale); } // cache the physical axes we used on this draw; pXAxis1Cache_ = pXAxis1; pYAxis1Cache_ = pYAxis1; pXAxis2Cache_ = pXAxis2; 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 }
public void Add(IPlot p, XAxisPosition xp, YAxisPosition yp) { ps_.Add(p, xp, yp); }
/// <summary> /// Constructor, which defines the world pixel length together with /// the x-axis that should be held constant when forcing this /// constraint [the other x-axis only will be moved]. /// </summary> /// <param name="p">The world pixel length</param> /// <param name="holdFixedX">The position of this x-axis will be held constant. The other x-axis will be moved in order to force the constraint.</param> public YPixelWorldLength( double p, XAxisPosition holdFixedX ) { this.pWorldLength_ = p; this.holdFixedX_ = holdFixedX; }
/// <summary> /// Constructor, which defines the world pixel length together with /// the x-axis that should be held constant when forcing this /// constraint [the other x-axis only will be moved]. /// </summary> /// <param name="p">The world pixel length</param> /// <param name="holdFixedX">The position of this x-axis will be held constant. The other x-axis will be moved in order to force the constraint.</param> public YPixelWorldLength(double p, XAxisPosition holdFixedX) { this.pWorldLength_ = p; this.holdFixedX_ = holdFixedX; }