1228 lines
42 KiB
C#
1228 lines
42 KiB
C#
//============================================================================
|
|
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
|
|
//Copyright ?2004 John Champion
|
|
//
|
|
//This library is free software; you can redistribute it and/or
|
|
//modify it under the terms of the GNU Lesser General Public
|
|
//License as published by the Free Software Foundation; either
|
|
//version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
//This library is distributed in the hope that it will be useful,
|
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
//Lesser General Public License for more details.
|
|
//
|
|
//You should have received a copy of the GNU Lesser General Public
|
|
//License along with this library; if not, write to the Free Software
|
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//=============================================================================
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Collections;
|
|
using System.Runtime.Serialization;
|
|
using System.Security.Permissions;
|
|
|
|
#if ( !DOTNET1 ) // Is this a .Net 2 compilation?
|
|
using System.Collections.Generic;
|
|
#endif
|
|
|
|
namespace DrawGraph
|
|
{
|
|
|
|
/// <summary>
|
|
/// This class contains the data and methods for an individual curve within
|
|
/// a graph pane. It carries the settings for the curve including the
|
|
/// key and item names, colors, symbols and sizes, linetypes, etc.
|
|
/// </summary>
|
|
///
|
|
/// <author> John Champion
|
|
/// modified by Jerry Vos </author>
|
|
/// <version> $Revision: 3.40 $ $Date: 2007/04/16 00:03:01 $ </version>
|
|
[Serializable]
|
|
abstract public class CurveItem : ISerializable, ICloneable
|
|
{
|
|
|
|
#region Fields
|
|
|
|
/// <summary>
|
|
/// protected field that stores a <see cref="Label" /> instance for this
|
|
/// <see cref="CurveItem"/>, which is used for the <see cref="Legend" />
|
|
/// label. Use the public
|
|
/// property <see cref="Label"/> to access this value.
|
|
/// </summary>
|
|
internal Label _label;
|
|
|
|
/// <summary>
|
|
/// protected field that stores the boolean value that determines whether this
|
|
/// <see cref="CurveItem"/> is on the bottom X axis or the top X axis (X2).
|
|
/// Use the public property <see cref="IsX2Axis"/> to access this value.
|
|
/// </summary>
|
|
protected bool _isX2Axis;
|
|
/// <summary>
|
|
/// protected field that stores the boolean value that determines whether this
|
|
/// <see cref="CurveItem"/> is on the left Y axis or the right Y axis (Y2).
|
|
/// Use the public property <see cref="IsY2Axis"/> to access this value.
|
|
/// </summary>
|
|
protected bool _isY2Axis;
|
|
|
|
/// <summary>
|
|
/// protected field that stores the index number of the Y Axis to which this
|
|
/// <see cref="CurveItem" /> belongs. Use the public property <see cref="YAxisIndex" />
|
|
/// to access this value.
|
|
/// </summary>
|
|
protected int _yAxisIndex;
|
|
|
|
/// <summary>
|
|
/// protected field that stores the boolean value that determines whether this
|
|
/// <see cref="CurveItem"/> is visible on the graph.
|
|
/// Use the public property <see cref="IsVisible"/> to access this value.
|
|
/// Note that this value turns the curve display on or off, but it does not
|
|
/// affect the display of the legend entry. To hide the legend entry, you
|
|
/// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
|
|
/// </summary>
|
|
protected bool _isVisible;
|
|
|
|
// Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Protected field that stores the boolean value that determines whether this
|
|
/// <see cref="CurveItem"/> is selected on the graph.
|
|
/// Use the public property <see cref="IsSelected"/> to access this value.
|
|
/// Note that this value changes the curve display color, but it does not
|
|
/// affect the display of the legend entry. To hide the legend entry, you
|
|
/// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
|
|
/// </summary>
|
|
protected bool _isSelected;
|
|
|
|
// Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Protected field that stores the boolean value that determines whether this
|
|
/// <see cref="CurveItem"/> can be selected in the graph.
|
|
/// </summary>
|
|
protected bool _isSelectable;
|
|
|
|
/// <summary>
|
|
/// protected field that stores a boolean value which allows you to override the normal
|
|
/// ordinal axis behavior. Use the public property <see cref="IsOverrideOrdinal"/> to
|
|
/// access this value.
|
|
/// </summary>
|
|
protected bool _isOverrideOrdinal;
|
|
|
|
/// <summary>
|
|
/// The <see cref="IPointList"/> of value sets that
|
|
/// represent this <see cref="CurveItem"/>.
|
|
/// The size of this list determines the number of points that are
|
|
/// plotted. Note that values defined as
|
|
/// System.Double.MaxValue are considered "missing" values
|
|
/// (see <see cref="PointPairBase.Missing"/>),
|
|
/// and are not plotted. The curve will have a break at these points
|
|
/// to indicate the values are missing.
|
|
/// </summary>
|
|
protected IPointList _points;
|
|
|
|
/// <summary>
|
|
/// A tag object for use by the user. This can be used to store additional
|
|
/// information associated with the <see cref="CurveItem"/>. ZedGraph does
|
|
/// not use this value for any purpose.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that, if you are going to Serialize ZedGraph data, then any type
|
|
/// that you store in <see cref="Tag"/> must be a serializable type (or
|
|
/// it will cause an exception).
|
|
/// </remarks>
|
|
public object Tag;
|
|
|
|
/// <summary>
|
|
/// Protected field that stores the hyperlink information for this object.
|
|
/// </summary>
|
|
internal Link _link;
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
/// <summary>
|
|
/// <see cref="CurveItem"/> constructor the pre-specifies the curve label, the
|
|
/// x and y data values as a <see cref="IPointList"/>, the curve
|
|
/// type (Bar or Line/Symbol), the <see cref="Color"/>, and the
|
|
/// <see cref="SymbolType"/>. Other properties of the curve are
|
|
/// defaulted to the values in the <see cref="GraphPane.Default"/> class.
|
|
/// </summary>
|
|
/// <param name="label">A string label (legend entry) for this curve</param>
|
|
/// <param name="x">An array of double precision values that define
|
|
/// the independent (X axis) values for this curve</param>
|
|
/// <param name="y">An array of double precision values that define
|
|
/// the dependent (Y axis) values for this curve</param>
|
|
public CurveItem( string label, double[] x, double[] y ) :
|
|
this( label, new PointPairList( x, y ) )
|
|
{
|
|
}
|
|
/*
|
|
public CurveItem( string _label, int y ) : this( _label, new IPointList( ) )
|
|
{
|
|
}
|
|
*/
|
|
/// <summary>
|
|
/// <see cref="CurveItem"/> constructor the pre-specifies the curve label, the
|
|
/// x and y data values as a <see cref="IPointList"/>, the curve
|
|
/// type (Bar or Line/Symbol), the <see cref="Color"/>, and the
|
|
/// <see cref="SymbolType"/>. Other properties of the curve are
|
|
/// defaulted to the values in the <see cref="GraphPane.Default"/> class.
|
|
/// </summary>
|
|
/// <param name="label">A string label (legend entry) for this curve</param>
|
|
/// <param name="points">A <see cref="IPointList"/> of double precision value pairs that define
|
|
/// the X and Y values for this curve</param>
|
|
public CurveItem( string label, IPointList points )
|
|
{
|
|
Init( label );
|
|
|
|
if ( points == null )
|
|
_points = new PointPairList();
|
|
else
|
|
//this.points = (IPointList) _points.Clone();
|
|
_points = points;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal initialization routine thats sets some initial values to defaults.
|
|
/// </summary>
|
|
/// <param name="label">A string label (legend entry) for this curve</param>
|
|
private void Init( string label )
|
|
{
|
|
_label = new Label( label, null );
|
|
_isY2Axis = false;
|
|
_isX2Axis = false;
|
|
_isVisible = true;
|
|
_isOverrideOrdinal = false;
|
|
this.Tag = null;
|
|
_yAxisIndex = 0;
|
|
_link = new Link();
|
|
}
|
|
|
|
/// <summary>
|
|
/// <see cref="CurveItem"/> constructor that specifies the label of the CurveItem.
|
|
/// This is the same as <c>CurveItem(label, null, null)</c>.
|
|
/// <seealso cref="CurveItem( string, double[], double[] )"/>
|
|
/// </summary>
|
|
/// <param name="label">A string label (legend entry) for this curve</param>
|
|
public CurveItem( string label ): this( label, null )
|
|
{
|
|
}
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
public CurveItem( )
|
|
{
|
|
Init( null );
|
|
}
|
|
/// <summary>
|
|
/// The Copy Constructor
|
|
/// </summary>
|
|
/// <param name="rhs">The CurveItem object from which to copy</param>
|
|
public CurveItem( CurveItem rhs )
|
|
{
|
|
_label = rhs._label.Clone();
|
|
_isY2Axis = rhs.IsY2Axis;
|
|
_isX2Axis = rhs.IsX2Axis;
|
|
_isVisible = rhs.IsVisible;
|
|
_isOverrideOrdinal = rhs._isOverrideOrdinal;
|
|
_yAxisIndex = rhs._yAxisIndex;
|
|
|
|
if ( rhs.Tag is ICloneable )
|
|
this.Tag = ((ICloneable) rhs.Tag).Clone();
|
|
else
|
|
this.Tag = rhs.Tag;
|
|
|
|
_points = (IPointList) rhs.Points.Clone();
|
|
|
|
_link = rhs._link.Clone();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
|
|
/// calling the typed version of Clone.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Note that this method must be called with an explicit cast to ICloneable, and
|
|
/// that it is inherently virtual. For example:
|
|
/// <code>
|
|
/// ParentClass foo = new ChildClass();
|
|
/// ChildClass bar = (ChildClass) ((ICloneable)foo).Clone();
|
|
/// </code>
|
|
/// Assume that ChildClass is inherited from ParentClass. Even though foo is declared with
|
|
/// ParentClass, it is actually an instance of ChildClass. Calling the ICloneable implementation
|
|
/// of Clone() on foo actually calls ChildClass.Clone() as if it were a virtual function.
|
|
/// </remarks>
|
|
/// <returns>A deep copy of this object</returns>
|
|
object ICloneable.Clone()
|
|
{
|
|
throw new NotImplementedException( "Can't clone an abstract base type -- child types must implement ICloneable" );
|
|
//return new PaneBase( this );
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Serialization
|
|
/// <summary>
|
|
/// Current schema value that defines the version of the serialized file
|
|
/// </summary>
|
|
public const int schema = 11;
|
|
|
|
/// <summary>
|
|
/// Constructor for deserializing objects
|
|
/// </summary>
|
|
/// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data
|
|
/// </param>
|
|
/// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data
|
|
/// </param>
|
|
protected CurveItem( SerializationInfo info, StreamingContext context )
|
|
{
|
|
// The schema value is just a file version parameter. You can use it to make future versions
|
|
// backwards compatible as new member variables are added to classes
|
|
int sch = info.GetInt32( "schema" );
|
|
|
|
_label = (Label) info.GetValue( "label", typeof(Label) );
|
|
_isY2Axis = info.GetBoolean( "isY2Axis" );
|
|
if ( sch >= 11 )
|
|
_isX2Axis = info.GetBoolean( "isX2Axis" );
|
|
else
|
|
_isX2Axis = false;
|
|
|
|
_isVisible = info.GetBoolean( "isVisible" );
|
|
|
|
_isOverrideOrdinal = info.GetBoolean( "isOverrideOrdinal" );
|
|
|
|
// Data Points are always stored as a PointPairList, regardless of the
|
|
// actual original type (which could be anything that supports IPointList).
|
|
_points = (PointPairList) info.GetValue( "points", typeof(PointPairList) );
|
|
|
|
Tag = info.GetValue( "Tag", typeof(object) );
|
|
|
|
_yAxisIndex = info.GetInt32( "yAxisIndex" );
|
|
|
|
_link = (Link) info.GetValue( "link", typeof(Link) );
|
|
|
|
}
|
|
/// <summary>
|
|
/// Populates a <see cref="SerializationInfo"/> instance with the data needed to serialize the target object
|
|
/// </summary>
|
|
/// <param name="info">A <see cref="SerializationInfo"/> instance that defines the serialized data</param>
|
|
/// <param name="context">A <see cref="StreamingContext"/> instance that contains the serialized data</param>
|
|
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
|
|
public virtual void GetObjectData( SerializationInfo info, StreamingContext context )
|
|
{
|
|
info.AddValue( "schema", schema );
|
|
info.AddValue( "label", _label );
|
|
info.AddValue( "isY2Axis", _isY2Axis );
|
|
info.AddValue( "isX2Axis", _isX2Axis );
|
|
info.AddValue( "isVisible", _isVisible );
|
|
info.AddValue( "isOverrideOrdinal", _isOverrideOrdinal );
|
|
|
|
// if points is already a PointPairList, use it
|
|
// otherwise, create a new PointPairList so it can be serialized
|
|
PointPairList list;
|
|
if ( _points is PointPairList )
|
|
list = _points as PointPairList;
|
|
else
|
|
list = new PointPairList( _points );
|
|
|
|
info.AddValue( "points", list );
|
|
info.AddValue( "Tag", Tag );
|
|
info.AddValue( "yAxisIndex", _yAxisIndex );
|
|
|
|
info.AddValue( "link", _link );
|
|
}
|
|
#endregion
|
|
|
|
#region Properties
|
|
/// <summary>
|
|
/// A <see cref="Label" /> instance that represents the <see cref="ZedGraph.Legend"/>
|
|
/// entry for the this <see cref="CurveItem"/> object
|
|
/// </summary>
|
|
public Label Label
|
|
{
|
|
get { return _label; }
|
|
set { _label = value;}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The <see cref="Line"/>/<see cref="Symbol"/>/<see cref="Bar"/>
|
|
/// color (FillColor for the Bar). This is a common access to
|
|
/// <see cref="ZedGraph.LineBase.Color">Line.Color</see>,
|
|
/// <see cref="ZedGraph.LineBase.Color">Border.Color</see>, and
|
|
/// <see cref="ZedGraph.Fill.Color">Fill.Color</see> properties for this curve.
|
|
/// </summary>
|
|
public Color Color
|
|
{
|
|
get
|
|
{
|
|
if ( this is BarItem )
|
|
return ((BarItem) this).Bar.Fill.Color;
|
|
else if ( this is LineItem && ((LineItem) this).Line.IsVisible )
|
|
return ((LineItem) this).Line.Color;
|
|
else if ( this is LineItem )
|
|
return ((LineItem) this).Symbol.Border.Color;
|
|
else if ( this is ErrorBarItem )
|
|
return ((ErrorBarItem) this).Bar.Color;
|
|
else if ( this is HiLowBarItem )
|
|
return ((HiLowBarItem) this).Bar.Fill.Color;
|
|
else
|
|
return Color.Empty;
|
|
}
|
|
set
|
|
{
|
|
if ( this is BarItem )
|
|
{
|
|
((BarItem) this).Bar.Fill.Color = value;
|
|
}
|
|
else if ( this is LineItem )
|
|
{
|
|
((LineItem) this).Line.Color = value;
|
|
((LineItem) this).Symbol.Border.Color = value;
|
|
((LineItem) this).Symbol.Fill.Color = value;
|
|
}
|
|
else if ( this is ErrorBarItem )
|
|
((ErrorBarItem) this).Bar.Color = value;
|
|
else if ( this is HiLowBarItem )
|
|
((HiLowBarItem) this).Bar.Fill.Color = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/> is visible on the graph.
|
|
/// Note that this value turns the curve display on or off, but it does not
|
|
/// affect the display of the legend entry. To hide the legend entry, you
|
|
/// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
|
|
/// </summary>
|
|
public bool IsVisible
|
|
{
|
|
get { return _isVisible; }
|
|
set { _isVisible = value; }
|
|
}
|
|
|
|
// Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/> is selected on the graph.
|
|
/// Note that this value changes the curve displayed color, but it does not
|
|
/// affect the display of the legend entry. To hide the legend entry, you
|
|
/// have to set <see cref="ZedGraph.Label.IsVisible"/> to false.
|
|
/// </summary>
|
|
public bool IsSelected
|
|
{
|
|
get { return _isSelected; }
|
|
set
|
|
{
|
|
_isSelected = value;
|
|
|
|
/*
|
|
if ( this is BarItem )
|
|
{
|
|
( (BarItem)this ).Bar.Fill.UseInactiveColor = !value;
|
|
}
|
|
else if ( this is LineItem )
|
|
{
|
|
( (LineItem)this ).Line.Fill.UseInactiveColor = !value;
|
|
( (LineItem)this ).Symbol.Fill.UseInactiveColor = !value;
|
|
( (LineItem)this ).Symbol.Fill.UseInactiveColor = !value;
|
|
}
|
|
else if ( this is HiLowBarItem )
|
|
( (HiLowBarItem)this ).Bar.Fill.UseInactiveColor = !value;
|
|
else if ( this is PieItem )
|
|
( (PieItem)this ).Fill.UseInactiveColor = !value;
|
|
*/
|
|
}
|
|
}
|
|
|
|
// Revision: JCarpenter 10/06
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/> can be selected in the graph.
|
|
/// </summary>
|
|
public bool IsSelectable
|
|
{
|
|
get { return _isSelectable; }
|
|
set { _isSelectable = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value which allows you to override the normal
|
|
/// ordinal axis behavior.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Normally for an ordinal axis type, the actual data values corresponding to the ordinal
|
|
/// axis will be ignored (essentially they are replaced by ordinal values, e.g., 1, 2, 3, etc).
|
|
/// If IsOverrideOrdinal is true, then the user data values will be used (even if they don't
|
|
/// make sense). Fractional values are allowed, such that a value of 1.5 is between the first and
|
|
/// second ordinal position, etc.
|
|
/// </remarks>
|
|
/// <seealso cref="AxisType.Ordinal"/>
|
|
/// <seealso cref="AxisType.Text"/>
|
|
public bool IsOverrideOrdinal
|
|
{
|
|
get { return _isOverrideOrdinal; }
|
|
set { _isOverrideOrdinal = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value that determines which X axis this <see cref="CurveItem"/>
|
|
/// is assigned to.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The
|
|
/// <see cref="ZedGraph.XAxis"/> is on the bottom side of the graph and the
|
|
/// <see cref="ZedGraph.X2Axis"/> is on the top side. Assignment to an axis
|
|
/// determines the scale that is used to draw the curve on the graph.
|
|
/// </remarks>
|
|
/// <value>true to assign the curve to the <see cref="ZedGraph.X2Axis"/>,
|
|
/// false to assign the curve to the <see cref="ZedGraph.XAxis"/></value>
|
|
public bool IsX2Axis
|
|
{
|
|
get { return _isX2Axis; }
|
|
set { _isX2Axis = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value that determines which Y axis this <see cref="CurveItem"/>
|
|
/// is assigned to.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The
|
|
/// <see cref="ZedGraph.YAxis"/> is on the left side of the graph and the
|
|
/// <see cref="ZedGraph.Y2Axis"/> is on the right side. Assignment to an axis
|
|
/// determines the scale that is used to draw the curve on the graph. Note that
|
|
/// this value is used in combination with the <see cref="YAxisIndex" /> to determine
|
|
/// which of the Y Axes (if there are multiples) this curve belongs to.
|
|
/// </remarks>
|
|
/// <value>true to assign the curve to the <see cref="ZedGraph.Y2Axis"/>,
|
|
/// false to assign the curve to the <see cref="ZedGraph.YAxis"/></value>
|
|
public bool IsY2Axis
|
|
{
|
|
get { return _isY2Axis; }
|
|
set { _isY2Axis = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the index number of the Y Axis to which this
|
|
/// <see cref="CurveItem" /> belongs.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This value is essentially an index number into the <see cref="GraphPane.YAxisList" />
|
|
/// or <see cref="GraphPane.Y2AxisList" />, depending on the setting of
|
|
/// <see cref="IsY2Axis" />.
|
|
/// </remarks>
|
|
public int YAxisIndex
|
|
{
|
|
get { return _yAxisIndex; }
|
|
set { _yAxisIndex = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/>
|
|
/// is a <see cref="BarItem"/>. This does not include <see cref="HiLowBarItem"/>'s
|
|
/// or <see cref="ErrorBarItem"/>'s.
|
|
/// </summary>
|
|
/// <value>true for a bar chart, or false for a line or pie graph</value>
|
|
public bool IsBar
|
|
{
|
|
get { return this is BarItem; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/>
|
|
/// is a <see cref="PieItem"/>.
|
|
/// </summary>
|
|
/// <value>true for a pie chart, or false for a line or bar graph</value>
|
|
public bool IsPie
|
|
{
|
|
get { return this is PieItem; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines whether this <see cref="CurveItem"/>
|
|
/// is a <see cref="LineItem"/>.
|
|
/// </summary>
|
|
/// <value>true for a line chart, or false for a bar type</value>
|
|
public bool IsLine
|
|
{
|
|
get { return this is LineItem; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a flag indicating if the Z data range should be included in the axis scaling calculations.
|
|
/// </summary>
|
|
/// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
|
|
/// </param>
|
|
/// <value>true if the Z data are included, false otherwise</value>
|
|
abstract internal bool IsZIncluded( GraphPane pane );
|
|
|
|
/// <summary>
|
|
/// Gets a flag indicating if the X axis is the independent axis for this <see cref="CurveItem" />
|
|
/// </summary>
|
|
/// <param name="pane">The parent <see cref="GraphPane" /> of this <see cref="CurveItem" />.
|
|
/// </param>
|
|
/// <value>true if the X axis is independent, false otherwise</value>
|
|
abstract internal bool IsXIndependent( GraphPane pane );
|
|
|
|
/// <summary>
|
|
/// Readonly property that gives the number of points that define this
|
|
/// <see cref="CurveItem"/> object, which is the number of points in the
|
|
/// <see cref="Points"/> data collection.
|
|
/// </summary>
|
|
public int NPts
|
|
{
|
|
get
|
|
{
|
|
if ( _points == null )
|
|
return 0;
|
|
else
|
|
return _points.Count;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The <see cref="IPointList"/> of X,Y point sets that represent this
|
|
/// <see cref="CurveItem"/>.
|
|
/// </summary>
|
|
public IPointList Points
|
|
{
|
|
get { return _points; }
|
|
set { _points = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// An accessor for the <see cref="PointPair"/> datum for this <see cref="CurveItem"/>.
|
|
/// Index is the ordinal reference (zero based) of the point.
|
|
/// </summary>
|
|
public PointPair this[int index]
|
|
{
|
|
get
|
|
{
|
|
if ( _points == null )
|
|
return new PointPair( PointPair.Missing, PointPair.Missing );
|
|
else
|
|
return ( _points )[index];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the hyperlink information for this <see cref="CurveItem" />.
|
|
/// </summary>
|
|
// /// <seealso cref="ZedGraph.Web.IsImageMap" />
|
|
public Link Link
|
|
{
|
|
get { return _link; }
|
|
set { _link = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Rendering Methods
|
|
/// <summary>
|
|
/// Do all rendering associated with this <see cref="CurveItem"/> to the specified
|
|
/// <see cref="Graphics"/> device. This method is normally only
|
|
/// called by the Draw method of the parent <see cref="ZedGraph.CurveList"/>
|
|
/// 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="ZedGraph.GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="pos">The ordinal position of the current <see cref="Bar"/>
|
|
/// curve.</param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="ZedGraph.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>
|
|
abstract public void Draw( Graphics g, GraphPane pane, int pos, float scaleFactor );
|
|
|
|
/// <summary>
|
|
/// Draw a legend key entry for this <see cref="CurveItem"/> at the specified location.
|
|
/// This abstract base method passes through to <see cref="BarItem.DrawLegendKey"/> or
|
|
/// <see cref="LineItem.DrawLegendKey"/> to do the rendering.
|
|
/// </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="ZedGraph.GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <param name="rect">The <see cref="RectangleF"/> struct that specifies the
|
|
/// location for the legend key</param>
|
|
/// <param name="scaleFactor">
|
|
/// The scaling factor to be used for rendering objects. This is calculated and
|
|
/// passed down by the parent <see cref="ZedGraph.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>
|
|
abstract public void DrawLegendKey( Graphics g, GraphPane pane, RectangleF rect, float scaleFactor );
|
|
|
|
#endregion
|
|
|
|
#region Utility Methods
|
|
|
|
/// <summary>
|
|
/// Add a single x,y coordinate point to the end of the points collection for this curve.
|
|
/// </summary>
|
|
/// <param name="x">The X coordinate value</param>
|
|
/// <param name="y">The Y coordinate value</param>
|
|
public void AddPoint( double x, double y )
|
|
{
|
|
this.AddPoint( new PointPair( x, y ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add a <see cref="PointPair"/> object to the end of the points collection for this curve.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method will only work if the <see cref="IPointList" /> instance reference
|
|
/// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
|
|
/// Otherwise, it does nothing.
|
|
/// </remarks>
|
|
/// <param name="point">A reference to the <see cref="PointPair"/> object to
|
|
/// be added</param>
|
|
public void AddPoint( PointPair point )
|
|
{
|
|
if ( _points == null )
|
|
this.Points = new PointPairList();
|
|
|
|
if ( _points is IPointListEdit )
|
|
( _points as IPointListEdit ).Add( point );
|
|
else
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the points from this <see cref="CurveItem"/>. This is the same
|
|
/// as <c>CurveItem.Points.Clear()</c>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method will only work if the <see cref="IPointList" /> instance reference
|
|
/// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
|
|
/// Otherwise, it does nothing.
|
|
/// </remarks>
|
|
public void Clear()
|
|
{
|
|
if ( _points is IPointListEdit )
|
|
(_points as IPointListEdit).Clear();
|
|
else
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a single point from this <see cref="CurveItem" />.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method will only work if the <see cref="IPointList" /> instance reference
|
|
/// at <see cref="Points" /> supports the <see cref="IPointListEdit" /> interface.
|
|
/// Otherwise, it does nothing.
|
|
/// </remarks>
|
|
/// <param name="index">The ordinal position of the point to be removed.</param>
|
|
public void RemovePoint( int index )
|
|
{
|
|
if ( _points is IPointListEdit )
|
|
(_points as IPointListEdit).RemoveAt( index );
|
|
else
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the X Axis instance (either <see cref="XAxis" /> or <see cref="X2Axis" />) to
|
|
/// which this <see cref="CurveItem" /> belongs.
|
|
/// </summary>
|
|
/// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
|
|
/// <returns>Either a <see cref="XAxis" /> or <see cref="X2Axis" /> to which this
|
|
/// <see cref="CurveItem" /> belongs.
|
|
/// </returns>
|
|
public Axis GetXAxis( GraphPane pane )
|
|
{
|
|
if ( _isX2Axis )
|
|
return pane.X2Axis;
|
|
else
|
|
return pane.XAxis;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the Y Axis instance (either <see cref="YAxis" /> or <see cref="Y2Axis" />) to
|
|
/// which this <see cref="CurveItem" /> belongs.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method safely retrieves a Y Axis instance from either the <see cref="GraphPane.YAxisList" />
|
|
/// or the <see cref="GraphPane.Y2AxisList" /> using the values of <see cref="YAxisIndex" /> and
|
|
/// <see cref="IsY2Axis" />. If the value of <see cref="YAxisIndex" /> is out of bounds, the
|
|
/// default <see cref="YAxis" /> or <see cref="Y2Axis" /> is used.
|
|
/// </remarks>
|
|
/// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
|
|
/// <returns>Either a <see cref="YAxis" /> or <see cref="Y2Axis" /> to which this
|
|
/// <see cref="CurveItem" /> belongs.
|
|
/// </returns>
|
|
public Axis GetYAxis( GraphPane pane )
|
|
{
|
|
if ( _isY2Axis )
|
|
{
|
|
if ( _yAxisIndex < pane.Y2AxisList.Count )
|
|
return pane.Y2AxisList[_yAxisIndex];
|
|
else
|
|
return pane.Y2AxisList[0];
|
|
}
|
|
else
|
|
{
|
|
if ( _yAxisIndex < pane.YAxisList.Count )
|
|
return pane.YAxisList[_yAxisIndex];
|
|
else
|
|
return pane.YAxisList[0];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the index of the Y Axis in the <see cref="YAxis" /> or <see cref="Y2Axis" /> list to
|
|
/// which this <see cref="CurveItem" /> belongs.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method safely retrieves a Y Axis index into either the <see cref="GraphPane.YAxisList" />
|
|
/// or the <see cref="GraphPane.Y2AxisList" /> using the values of <see cref="YAxisIndex" /> and
|
|
/// <see cref="IsY2Axis" />. If the value of <see cref="YAxisIndex" /> is out of bounds, the
|
|
/// default <see cref="YAxis" /> or <see cref="Y2Axis" /> is used, which is index zero.
|
|
/// </remarks>
|
|
/// <param name="pane">The <see cref="GraphPane" /> object to which this curve belongs.</param>
|
|
/// <returns>An integer value indicating which index position in the list applies to this
|
|
/// <see cref="CurveItem" />
|
|
/// </returns>
|
|
public int GetYAxisIndex( GraphPane pane )
|
|
{
|
|
if ( _yAxisIndex >= 0 &&
|
|
_yAxisIndex < ( _isY2Axis ? pane.Y2AxisList.Count : pane.YAxisList.Count ) )
|
|
return _yAxisIndex;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads some pseudo unique colors/symbols into this CurveItem. This
|
|
/// is the same as <c>MakeUnique(ColorSymbolRotator.StaticInstance)</c>.
|
|
/// <seealso cref="ColorSymbolRotator.StaticInstance"/>
|
|
/// <seealso cref="ColorSymbolRotator"/>
|
|
/// <seealso cref="MakeUnique(ColorSymbolRotator)"/>
|
|
/// </summary>
|
|
public void MakeUnique()
|
|
{
|
|
this.MakeUnique( ColorSymbolRotator.StaticInstance );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads some pseudo unique colors/symbols into this CurveItem. This
|
|
/// is mainly useful for differentiating a set of new CurveItems without
|
|
/// having to pick your own colors/symbols.
|
|
/// <seealso cref="MakeUnique(ColorSymbolRotator)"/>
|
|
/// </summary>
|
|
/// <param name="rotator">
|
|
/// The <see cref="ColorSymbolRotator"/> that is used to pick the color
|
|
/// and symbol for this method call.
|
|
/// </param>
|
|
virtual public void MakeUnique( ColorSymbolRotator rotator )
|
|
{
|
|
this.Color = rotator.NextColor;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Go through the list of <see cref="PointPair"/> data values for this <see cref="CurveItem"/>
|
|
/// and determine the minimum and maximum values in the data.
|
|
/// </summary>
|
|
/// <param name="xMin">The minimum X value in the range of data</param>
|
|
/// <param name="xMax">The maximum X value in the range of data</param>
|
|
/// <param name="yMin">The minimum Y value in the range of data</param>
|
|
/// <param name="yMax">The maximum Y value in the range of data</param>
|
|
/// <param name="ignoreInitial">ignoreInitial is a boolean value that
|
|
/// affects the data range that is considered for the automatic scale
|
|
/// ranging (see <see cref="GraphPane.IsIgnoreInitial"/>). If true, then initial
|
|
/// data points where the Y value is zero are not included when
|
|
/// automatically determining the scale <see cref="Scale.Min"/>,
|
|
/// <see cref="Scale.Max"/>, and <see cref="Scale.MajorStep"/> size. All data after
|
|
/// the first non-zero Y value are included.
|
|
/// </param>
|
|
/// <param name="isBoundedRanges">
|
|
/// Determines if the auto-scaled axis ranges will subset the
|
|
/// data points based on any manually set scale range values.
|
|
/// </param>
|
|
/// <param name="pane">
|
|
/// A reference to the <see cref="GraphPane"/> object that is the parent or
|
|
/// owner of this object.
|
|
/// </param>
|
|
/// <seealso cref="GraphPane.IsBoundedRanges"/>
|
|
virtual public void GetRange( out double xMin, out double xMax,
|
|
out double yMin, out double yMax,
|
|
bool ignoreInitial,
|
|
bool isBoundedRanges,
|
|
GraphPane pane )
|
|
{
|
|
// The lower and upper bounds of allowable data for the X values. These
|
|
// values allow you to subset the data values. If the X range is bounded, then
|
|
// the resulting range for Y will reflect the Y values for the points within the X
|
|
// bounds.
|
|
double xLBound = double.MinValue;
|
|
double xUBound = double.MaxValue;
|
|
double yLBound = double.MinValue;
|
|
double yUBound = double.MaxValue;
|
|
|
|
// initialize the values to outrageous ones to start
|
|
xMin = yMin = Double.MaxValue;
|
|
xMax = yMax = Double.MinValue;
|
|
|
|
Axis yAxis = this.GetYAxis( pane );
|
|
Axis xAxis = this.GetXAxis( pane );
|
|
if ( yAxis == null || xAxis == null )
|
|
return;
|
|
|
|
if ( isBoundedRanges )
|
|
{
|
|
xLBound = xAxis._scale._lBound;
|
|
xUBound = xAxis._scale._uBound;
|
|
yLBound = yAxis._scale._lBound;
|
|
yUBound = yAxis._scale._uBound;
|
|
}
|
|
|
|
|
|
bool isZIncluded = this.IsZIncluded( pane );
|
|
bool isXIndependent = this.IsXIndependent( pane );
|
|
bool isXLog = xAxis.Scale.IsLog;
|
|
bool isYLog = yAxis.Scale.IsLog;
|
|
|
|
// Loop over each point in the arrays
|
|
//foreach ( PointPair point in this.Points )
|
|
for ( int i=0; i<this.Points.Count; i++ )
|
|
{
|
|
PointPair point = this.Points[i];
|
|
|
|
double curX = point.X;
|
|
double curY = point.Y;
|
|
double curZ = point.Z;
|
|
|
|
bool outOfBounds = curX < xLBound || curX > xUBound ||
|
|
curY < yLBound || curY > yUBound ||
|
|
( isZIncluded && isXIndependent && ( curZ < yLBound || curZ > yUBound ) ) ||
|
|
( isZIncluded && !isXIndependent && ( curZ < xLBound || curZ > xUBound ) ) ||
|
|
( curX <= 0 && isXLog ) || ( curY <= 0 && isYLog );
|
|
|
|
// ignoreInitial becomes false at the first non-zero
|
|
// Y value
|
|
if ( ignoreInitial && curY != 0 &&
|
|
curY != PointPair.Missing )
|
|
ignoreInitial = false;
|
|
|
|
if ( !ignoreInitial &&
|
|
!outOfBounds &&
|
|
curX != PointPair.Missing &&
|
|
curY != PointPair.Missing )
|
|
{
|
|
if ( curX < xMin )
|
|
xMin = curX;
|
|
if ( curX > xMax )
|
|
xMax = curX;
|
|
if ( curY < yMin )
|
|
yMin = curY;
|
|
if ( curY > yMax )
|
|
yMax = curY;
|
|
|
|
if ( isZIncluded && isXIndependent && curZ != PointPair.Missing )
|
|
{
|
|
if ( curZ < yMin )
|
|
yMin = curZ;
|
|
if ( curZ > yMax )
|
|
yMax = curZ;
|
|
}
|
|
else if ( isZIncluded && curZ != PointPair.Missing )
|
|
{
|
|
if ( curZ < xMin )
|
|
xMin = curZ;
|
|
if ( curZ > xMax )
|
|
xMax = curZ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Returns a reference to the <see cref="Axis"/> object that is the "base"
|
|
/// (independent axis) from which the values are drawn. </summary>
|
|
/// <remarks>
|
|
/// This property is determined by the value of <see cref="BarSettings.Base"/> for
|
|
/// <see cref="BarItem"/>, <see cref="ErrorBarItem"/>, and <see cref="HiLowBarItem"/>
|
|
/// types. It is always the X axis for regular <see cref="LineItem"/> types.
|
|
/// Note that the <see cref="BarSettings.Base" /> setting can override the
|
|
/// <see cref="IsY2Axis" /> and <see cref="YAxisIndex" /> settings for bar types
|
|
/// (this is because all the bars that are clustered together must share the
|
|
/// same base axis).
|
|
/// </remarks>
|
|
/// <seealso cref="BarBase"/>
|
|
/// <seealso cref="ValueAxis"/>
|
|
public virtual Axis BaseAxis( GraphPane pane )
|
|
{
|
|
BarBase barBase;
|
|
|
|
if ( this is BarItem || this is ErrorBarItem || this is HiLowBarItem )
|
|
barBase = pane._barSettings.Base;
|
|
else
|
|
barBase = _isX2Axis ? BarBase.X2 : BarBase.X;
|
|
|
|
if ( barBase == BarBase.X )
|
|
return pane.XAxis;
|
|
else if ( barBase == BarBase.X2 )
|
|
return pane.X2Axis;
|
|
else if ( barBase == BarBase.Y )
|
|
return pane.YAxis;
|
|
else
|
|
return pane.Y2Axis;
|
|
|
|
}
|
|
/// <summary>Returns a reference to the <see cref="Axis"/> object that is the "value"
|
|
/// (dependent axis) from which the points are drawn. </summary>
|
|
/// <remarks>
|
|
/// This property is determined by the value of <see cref="BarSettings.Base"/> for
|
|
/// <see cref="BarItem"/>, <see cref="ErrorBarItem"/>, and <see cref="HiLowBarItem"/>
|
|
/// types. It is always the Y axis for regular <see cref="LineItem"/> types.
|
|
/// </remarks>
|
|
/// <seealso cref="BarBase"/>
|
|
/// <seealso cref="BaseAxis"/>
|
|
public virtual Axis ValueAxis( GraphPane pane )
|
|
{
|
|
BarBase barBase;
|
|
|
|
if ( this is BarItem || this is ErrorBarItem || this is HiLowBarItem )
|
|
barBase = pane._barSettings.Base;
|
|
else
|
|
barBase = BarBase.X;
|
|
|
|
if ( barBase == BarBase.X || barBase == BarBase.X2 )
|
|
{
|
|
return GetYAxis( pane );
|
|
}
|
|
else
|
|
return GetXAxis( pane );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate the width of each bar, depending on the actual bar type
|
|
/// </summary>
|
|
/// <returns>The width for an individual bar, in pixel units</returns>
|
|
public float GetBarWidth( GraphPane pane )
|
|
{
|
|
// Total axis width =
|
|
// npts * ( nbars * ( bar + bargap ) - bargap + clustgap )
|
|
// cg * bar = cluster gap
|
|
// npts = max number of points in any curve
|
|
// nbars = total number of curves that are of type IsBar
|
|
// bar = bar width
|
|
// bg * bar = bar gap
|
|
// therefore:
|
|
// totwidth = npts * ( nbars * (bar + bg*bar) - bg*bar + cg*bar )
|
|
// totwidth = bar * ( npts * ( nbars * ( 1 + bg ) - bg + cg ) )
|
|
// solve for bar
|
|
|
|
float barWidth;
|
|
|
|
if ( this is ErrorBarItem )
|
|
barWidth = (float) ( ((ErrorBarItem)this).Bar.Symbol.Size *
|
|
pane.CalcScaleFactor() );
|
|
else if ( this is HiLowBarItem )
|
|
// barWidth = (float) ( ((HiLowBarItem)this).Bar.GetBarWidth( pane,
|
|
// ((HiLowBarItem)this).BaseAxis(pane), pane.CalcScaleFactor() ) );
|
|
barWidth = (float) ( ((HiLowBarItem)this).Bar.Size *
|
|
pane.CalcScaleFactor() );
|
|
else // BarItem or LineItem
|
|
{
|
|
// For stacked bar types, the bar width will be based on a single bar
|
|
float numBars = 1.0F;
|
|
if ( pane._barSettings.Type == BarType.Cluster || pane._barSettings.Type == BarType.ClusterHiLow )
|
|
numBars = pane.CurveList.NumBars;
|
|
|
|
float denom = numBars * ( 1.0F + pane._barSettings.MinBarGap ) -
|
|
pane._barSettings.MinBarGap + pane._barSettings.MinClusterGap;
|
|
if ( denom <= 0 )
|
|
denom = 1;
|
|
barWidth = pane.BarSettings.GetClusterWidth() / denom;
|
|
}
|
|
|
|
if ( barWidth <= 0 )
|
|
return 1;
|
|
|
|
return barWidth;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determine the coords for the rectangle associated with a specified point for
|
|
/// this <see cref="CurveItem" />
|
|
/// </summary>
|
|
/// <param name="pane">The <see cref="GraphPane" /> to which this curve belongs</param>
|
|
/// <param name="i">The index of the point of interest</param>
|
|
/// <param name="coords">A list of coordinates that represents the "rect" for
|
|
/// this point (used in an html AREA tag)</param>
|
|
/// <returns>true if it's a valid point, false otherwise</returns>
|
|
abstract public bool GetCoords( GraphPane pane, int i, out string coords );
|
|
|
|
#endregion
|
|
|
|
#region Inner classes
|
|
|
|
#if ( DOTNET1 ) // Is this a .Net 1.1 compilation?
|
|
|
|
/// <summary>
|
|
/// Compares <see cref="CurveItem"/>'s based on the point value at the specified
|
|
/// index and for the specified axis.
|
|
/// <seealso cref="System.Collections.ArrayList.Sort()"/>
|
|
/// </summary>
|
|
public class Comparer : IComparer
|
|
{
|
|
private int index;
|
|
private SortType sortType;
|
|
|
|
/// <summary>
|
|
/// Constructor for Comparer.
|
|
/// </summary>
|
|
/// <param name="type">The axis type on which to sort.</param>
|
|
/// <param name="index">The index number of the point on which to sort</param>
|
|
public Comparer( SortType type, int index )
|
|
{
|
|
this.sortType = type;
|
|
this.index = index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares two <see cref="CurveItem"/>s using the previously specified index value
|
|
/// and axis. Sorts in descending order.
|
|
/// </summary>
|
|
/// <param name="l">Curve to the left.</param>
|
|
/// <param name="r">Curve to the right.</param>
|
|
/// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
|
|
public int Compare( object l, object r )
|
|
{
|
|
CurveItem cl = (CurveItem) l;
|
|
CurveItem cr = (CurveItem) r;
|
|
|
|
if (cl == null && cr == null )
|
|
return 0;
|
|
else if (cl == null && cr != null )
|
|
return -1;
|
|
else if (cl != null && cr == null)
|
|
return 1;
|
|
|
|
if ( cr != null && cr.NPts <= index )
|
|
cr = null;
|
|
if ( cl != null && cl.NPts <= index )
|
|
cl = null;
|
|
|
|
double lVal, rVal;
|
|
|
|
if ( sortType == SortType.XValues )
|
|
{
|
|
lVal = ( l != null ) ? System.Math.Abs( cl[index].X ) : PointPair.Missing;
|
|
rVal = ( r != null ) ? System.Math.Abs( cr[index].X ) : PointPair.Missing;
|
|
}
|
|
else
|
|
{
|
|
lVal = ( l != null ) ? System.Math.Abs( cl[index].Y ) : PointPair.Missing;
|
|
rVal = ( r != null ) ? System.Math.Abs( cr[index].Y ) : PointPair.Missing;
|
|
}
|
|
|
|
if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
|
|
cl = null;
|
|
if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
|
|
cr = null;
|
|
|
|
if ( ( cl == null && cr == null) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
|
|
return 0;
|
|
else if ( cl == null && cr != null )
|
|
return -1;
|
|
else if ( cl != null && r == null )
|
|
return 1;
|
|
else
|
|
return rVal < lVal ? -1 : 1;
|
|
}
|
|
}
|
|
|
|
#else // Otherwise, it's .Net 2.0 so use generics
|
|
|
|
/// <summary>
|
|
/// Compares <see cref="CurveItem"/>'s based on the point value at the specified
|
|
/// index and for the specified axis.
|
|
/// <seealso cref="System.Collections.ArrayList.Sort()"/>
|
|
/// </summary>
|
|
public class Comparer : IComparer<CurveItem>
|
|
{
|
|
private int index;
|
|
private SortType sortType;
|
|
|
|
/// <summary>
|
|
/// Constructor for Comparer.
|
|
/// </summary>
|
|
/// <param name="type">The axis type on which to sort.</param>
|
|
/// <param name="index">The index number of the point on which to sort</param>
|
|
public Comparer( SortType type, int index )
|
|
{
|
|
this.sortType = type;
|
|
this.index = index;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Compares two <see cref="CurveItem"/>s using the previously specified index value
|
|
/// and axis. Sorts in descending order.
|
|
/// </summary>
|
|
/// <param name="l">Curve to the left.</param>
|
|
/// <param name="r">Curve to the right.</param>
|
|
/// <returns>-1, 0, or 1 depending on l.X's relation to r.X</returns>
|
|
public int Compare( CurveItem l, CurveItem r )
|
|
{
|
|
if (l == null && r == null )
|
|
return 0;
|
|
else if (l == null && r != null )
|
|
return -1;
|
|
else if (l != null && r == null)
|
|
return 1;
|
|
|
|
if ( r != null && r.NPts <= index )
|
|
r = null;
|
|
if ( l != null && l.NPts <= index )
|
|
l = null;
|
|
|
|
double lVal, rVal;
|
|
|
|
if ( sortType == SortType.XValues )
|
|
{
|
|
lVal = ( l != null ) ? System.Math.Abs( l[index].X ) : PointPair.Missing;
|
|
rVal = ( r != null ) ? System.Math.Abs( r[index].X ) : PointPair.Missing;
|
|
}
|
|
else
|
|
{
|
|
lVal = ( l != null ) ? System.Math.Abs( l[index].Y ) : PointPair.Missing;
|
|
rVal = ( r != null ) ? System.Math.Abs( r[index].Y ) : PointPair.Missing;
|
|
}
|
|
|
|
if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
|
|
l = null;
|
|
if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
|
|
r = null;
|
|
|
|
if ( (l == null && r == null) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
|
|
return 0;
|
|
else if (l == null && r != null )
|
|
return -1;
|
|
else if (l != null && r == null)
|
|
return 1;
|
|
else
|
|
return rVal < lVal ? -1 : 1;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|