Я обнаружил проблему в библиотеке ZedGraph ... кто-то, пожалуйста, исправьте меня, если я что-то пропустил, у меня не должно быть
При использовании FilledLineItem он имеет набор верхних и нижних точек.
Когда вызывается «Draw», он вызывается для класса LineItem, который имеет только набор точек.
Итак, я добавил к методу Draw:
DrawPoints(pane, maxX, maxY, curve, curve.LowerPoints, g, source, scaleFactor, minX, minY, isPixelDrawn)
DrawPoints - это метод, который я извлек из метода Draw в Symbol. Он содержит следующее
private void DrawPoints(GraphPane pane, int maxX, int maxY, LineItem curve, IPointList points, Graphics g, Symbol source, float scaleFactor, int minX, int minY, bool[,] isPixelDrawn)
{
double curX;
double curY;
int tmpX;
int tmpY;
double lowVal;
if ( points != null && ( _border.IsVisible || _fill.IsVisible ) )
{
SmoothingMode sModeSave = g.SmoothingMode;
if ( _isAntiAlias )
g.SmoothingMode = SmoothingMode.HighQuality;
// For the sake of speed, go ahead and create a solid brush and a pen
// If it's a gradient fill, it will be created on the fly for each symbol
//SolidBrush brush = new SolidBrush( this.fill.Color );
using ( Pen pen = source._border.GetPen( pane, scaleFactor ) )
using ( GraphicsPath path = MakePath( g, scaleFactor ) )
{
RectangleF rect = path.GetBounds();
using ( Brush brush = source.Fill.MakeBrush( rect ) )
{
ValueHandler valueHandler = new ValueHandler( pane, false );
Scale xScale = curve.GetXAxis( pane ).Scale;
Scale yScale = curve.GetYAxis( pane ).Scale;
bool xIsLog = xScale.IsLog;
bool yIsLog = yScale.IsLog;
bool xIsOrdinal = xScale.IsAnyOrdinal;
double xMin = xScale.Min;
double xMax = xScale.Max;
// Loop over each defined point
for ( int i = 0; i < points.Count; i++ )
{
// Check that this symbol should be shown, if not, then continue to the next symbol
if(!points[i].ShowSymbol)
{
continue;
}
// Get the user scale values for the current point
// use the valueHandler only for stacked types
if ( pane.LineType == LineType.Stack )
{
valueHandler.GetValues( curve, i, out curX, out lowVal, out curY );
}
// otherwise, just access the values directly. Avoiding the valueHandler for
// non-stacked types is an optimization to minimize overhead in case there are
// a large number of points.
else
{
curX = points[i].X;
if ( curve is StickItem )
curY = points[i].Z;
else
curY = points[i].Y;
}
// Any value set to double max is invalid and should be skipped
// This is used for calculated values that are out of range, divide
// by zero, etc.
// Also, any value <= zero on a log scale is invalid
if ( curX != PointPair.Missing &&
curY != PointPair.Missing &&
!System.Double.IsNaN( curX ) &&
!System.Double.IsNaN( curY ) &&
!System.Double.IsInfinity( curX ) &&
!System.Double.IsInfinity( curY ) &&
( curX > 0 || !xIsLog ) &&
( !yIsLog || curY > 0.0 ) &&
( xIsOrdinal || ( curX >= xMin && curX <= xMax ) ) )
{
// Transform the user scale values to pixel locations
tmpX = (int) xScale.Transform( curve.IsOverrideOrdinal, i, curX );
tmpY = (int) yScale.Transform( curve.IsOverrideOrdinal, i, curY );
// Maintain an array of "used" pixel locations to avoid duplicate drawing operations
if ( tmpX >= minX && tmpX <= maxX && tmpY >= minY && tmpY <= maxY ) // guard against the zoom-in case
{
if ( isPixelDrawn[tmpX, tmpY] )
continue;
isPixelDrawn[tmpX, tmpY] = true;
}
// If the fill type for this symbol is a Gradient by value type,
// the make a brush corresponding to the appropriate current value
if ( _fill.IsGradientValueType || _border._gradientFill.IsGradientValueType )
{
using ( Brush tBrush = _fill.MakeBrush( rect, points[i] ) )
using ( Pen tPen = _border.GetPen( pane, scaleFactor, points[i] ) )
this.DrawSymbol( g, tmpX, tmpY, path, tPen, tBrush );
}
else
{
// Otherwise, the brush is already defined
// Draw the symbol at the specified pixel location
this.DrawSymbol( g, tmpX, tmpY, path, pen, brush );
}
}
}
}
}
g.SmoothingMode = sModeSave;
}
}
Итак, мой метод «Draw» теперь выглядит так:
public void Draw( Graphics g, GraphPane pane, LineItem curve, float scaleFactor,
bool isSelected )
{
Symbol source = this;
if ( isSelected )
source = Selection.Symbol;
int tmpX, tmpY;
int minX = (int)pane.Chart.Rect.Left;
int maxX = (int)pane.Chart.Rect.Right;
int minY = (int)pane.Chart.Rect.Top;
int maxY = (int)pane.Chart.Rect.Bottom;
// (Dale-a-b) we'll set an element to true when it has been drawn
bool[,] isPixelDrawn = new bool[maxX + 1, maxY + 1];
double curX, curY, lowVal;
DrawPoints(pane, maxX, maxY, curve, curve.Points, g, source, scaleFactor, minX, minY, isPixelDrawn);
// Need to check if this is a "Filled" line item, if it is, it may have lower points, in which case the lower points need to be output as well
FilledLineItem filledLineItem = curve as FilledLineItem;
if (filledLineItem != null)
{
DrawPoints(pane, maxX, maxY, curve, filledLineItem.LowerPoints, g, source, scaleFactor, minX, minY, isPixelDrawn);
}
}
... после приведения кривой к FilledLineItem (но не до проверки, что это на самом деле FilledLineItem).
Это решило проблему, и я надеюсь, что это поможет всем, у кого может быть такая же проблема.