//============================================================================
//PointPair Class
//Copyright ?2004 Jerry Vos
//
//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.Runtime.Serialization;
using System.Security.Permissions;
using System.Collections;
using IComparer = System.Collections.IComparer;
#if ( !DOTNET1 ) // Is this a .Net 2 compilation?
using System.Collections.Generic;
#endif
namespace DrawGraph
{
///
/// A simple point represented by an (X,Y,Z) group of double values.
///
///
/// Jerry Vos modified by John Champion
/// $Revision: 3.24 $ $Date: 2007/03/17 18:43:44 $
[Serializable]
public class PointPair : PointPairBase, ISerializable
{
#region Member variables
///
/// This PointPair's Z coordinate. Also used for the lower value (dependent axis)
/// for and charts.
///
public double Z;
///
/// A tag object for use by the user. This can be used to store additional
/// information associated with the . ZedGraph never
/// modifies this value, but if it is a type, it
/// may be displayed in a
/// within the object.
///
///
/// Note that, if you are going to Serialize ZedGraph data, then any type
/// that you store in must be a serializable type (or
/// it will cause an exception).
///
public object Tag;
#endregion
#region Constructors
///
/// Default Constructor
///
public PointPair() : this( 0, 0, 0, null )
{
}
///
/// Creates a point pair with the specified X and Y.
///
/// This pair's x coordinate.
/// This pair's y coordinate.
public PointPair( double x, double y )
: this ( x, y, 0, null )
{
}
///
/// Creates a point pair with the specified X, Y, and
/// label ().
///
/// This pair's x coordinate.
/// This pair's y coordinate.
/// This pair's string label ()
public PointPair( double x, double y, string label )
: this( x, y, 0, label as object )
{
}
///
/// Creates a point pair with the specified X, Y, and base value.
///
/// This pair's x coordinate.
/// This pair's y coordinate.
/// This pair's z or lower dependent coordinate.
public PointPair( double x, double y, double z )
: this( x, y, z, null )
{
}
///
/// Creates a point pair with the specified X, Y, base value, and
/// string label ().
///
/// This pair's x coordinate.
/// This pair's y coordinate.
/// This pair's z or lower dependent coordinate.
/// This pair's string label ()
public PointPair( double x, double y, double z, string label )
: this( x, y, z, label as object )
{
}
///
/// Creates a point pair with the specified X, Y, base value, and
/// ().
///
/// This pair's x coordinate.
/// This pair's y coordinate.
/// This pair's z or lower dependent coordinate.
/// This pair's property
public PointPair( double x, double y, double z, object tag )
: base( x, y )
{
this.Z = z;
this.Tag = tag;
}
///
/// Creates a point pair from the specified struct.
///
/// The struct from which to get the
/// new values.
public PointPair( PointF pt ) : this( pt.X, pt.Y, 0, null )
{
}
///
/// The PointPair copy constructor.
///
/// The basis for the copy.
public PointPair( PointPair rhs ) : base( rhs )
{
this.Z = rhs.Z;
if ( rhs.Tag is ICloneable )
this.Tag = ((ICloneable) rhs.Tag).Clone();
else
this.Tag = rhs.Tag;
}
#endregion
#region Serialization
///
/// Current schema value that defines the version of the serialized file
///
public const int schema2 = 11;
///
/// Constructor for deserializing objects
///
/// A instance that defines the serialized data
///
/// A instance that contains the serialized data
///
protected PointPair( SerializationInfo info, StreamingContext context )
: base( info, 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( "schema2" );
Z = info.GetDouble( "Z" );
Tag = info.GetValue( "Tag", typeof(object) );
}
///
/// Populates a instance with the data needed to serialize the target object
///
/// A instance that defines the serialized data
/// A instance that contains the serialized data
[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]
public override void GetObjectData( SerializationInfo info, StreamingContext context )
{
base.GetObjectData( info, context );
info.AddValue( "schema2", schema2 );
info.AddValue( "Z", Z );
info.AddValue( "Tag", Tag );
}
#endregion
#region Properties
///
/// Readonly value that determines if either the X, Y, or Z
/// coordinate in this PointPair is an invalid (not plotable) value.
/// It is considered invalid if it is missing (equal to System.Double.Max),
/// Infinity, or NaN.
///
/// true if any value is invalid
public bool IsInvalid3D
{
get { return this.X == PointPair.Missing ||
this.Y == PointPair.Missing ||
this.Z == PointPair.Missing ||
Double.IsInfinity( this.X ) ||
Double.IsInfinity( this.Y ) ||
Double.IsInfinity( this.Z ) ||
Double.IsNaN( this.X ) ||
Double.IsNaN( this.Y ) ||
Double.IsNaN( this.Z );
}
}
///
/// The "low" value for this point (lower dependent-axis value).
/// This is really just an alias for .
///
/// The lower dependent value for this .
public double LowValue
{
get { return this.Z; }
set { this.Z = value; }
}
///
/// The ColorValue property is just an alias for the
/// property.
///
///
/// For other types, such as the , the
/// can be mapped to a unique value. This is used with the
/// option.
///
virtual public double ColorValue
{
get { return Z; }
set { Z = value; }
}
#endregion
#region Inner classes
#if ( DOTNET1 ) // Is this a .Net 1.1 compilation?
///
/// Compares points based on their y values. Is setup to be used in an
/// ascending order sort.
///
///
public class PointPairComparerY : IComparer
{
///
/// Compares two s.
///
/// Point to the left.
/// Point to the right.
/// -1, 0, or 1 depending on l.Y's relation to r.Y
public int Compare( object l, object r )
{
PointPair pl = (PointPair) l;
PointPair pr = (PointPair) r;
if (pl == null && pr == null)
{
return 0;
}
else if (pl == null && pr != null)
{
return -1;
}
else if (pl != null && pr == null)
{
return 1;
}
double lY = pl.Y;
double rY = pr.Y;
if (System.Math.Abs(lY - rY) < .000000001)
return 0;
return lY < rY ? -1 : 1;
}
}
///
/// Compares points based on their x values. Is setup to be used in an
/// ascending order sort.
///
///
public class PointPairComparer : IComparer
{
private SortType sortType;
///
/// Constructor for PointPairComparer.
///
/// The axis type on which to sort.
public PointPairComparer( SortType type )
{
this.sortType = type;
}
///
/// Compares two s.
///
/// Point to the left.
/// Point to the right.
/// -1, 0, or 1 depending on l.X's relation to r.X
public int Compare( object l, object r )
{
PointPair pl = (PointPair) l;
PointPair pr = (PointPair) r;
if ( pl == null && pr == null )
return 0;
else if ( pl == null && pr != null )
return -1;
else if ( pl != null && pr == null )
return 1;
double lVal, rVal;
if ( sortType == SortType.XValues )
{
lVal = pl.X;
rVal = pr.X;
}
else
{
lVal = pl.Y;
rVal = pr.Y;
}
if ( lVal == PointPair.Missing || Double.IsInfinity( lVal ) || Double.IsNaN( lVal ) )
pl = null;
if ( rVal == PointPair.Missing || Double.IsInfinity( rVal ) || Double.IsNaN( rVal ) )
pr = null;
if ( ( pl == null && pr == null ) || ( System.Math.Abs( lVal - rVal ) < 1e-10 ) )
return 0;
else if ( pl == null && pr != null )
return -1;
else if ( pl != null && pr == null )
return 1;
else
return lVal < rVal ? -1 : 1;
}
}
#else // Otherwise, it's .Net 2.0, so use generics
///
/// Compares points based on their y values. Is setup to be used in an
/// ascending order sort.
///
///
public class PointPairComparerY : IComparer
{
///
/// Compares two s.
///
/// Point to the left.
/// Point to the right.
/// -1, 0, or 1 depending on l.Y's relation to r.Y
public int Compare( PointPair l, PointPair r )
{
if ( l == null && r == null )
{
return 0;
}
else if ( l == null && r != null )
{
return -1;
}
else if ( l != null && r == null )
{
return 1;
}
double lY = l.Y;
double rY = r.Y;
if ( System.Math.Abs( lY - rY ) < .000000001 )
return 0;
return lY < rY ? -1 : 1;
}
}
///
/// Compares points based on their x values. Is setup to be used in an
/// ascending order sort.
///
///
public class PointPairComparer : IComparer
{
private SortType sortType;
///
/// Constructor for PointPairComparer.
///
/// The axis type on which to sort.
public PointPairComparer( SortType type )
{
this.sortType = type;
}
///
/// Compares two s.
///
/// Point to the left.
/// Point to the right.
/// -1, 0, or 1 depending on l.X's relation to r.X
public int Compare( PointPair l, PointPair r )
{
if ( l == null && r == null )
return 0;
else if ( l == null && r != null )
return -1;
else if ( l != null && r == null )
return 1;
double lVal, rVal;
if ( sortType == SortType.XValues )
{
lVal = l.X;
rVal = r.X;
}
else
{
lVal = l.Y;
rVal = r.Y;
}
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 lVal < rVal ? -1 : 1;
}
}
#endif
#endregion
#region Methods
///
/// Compare two objects for equality. To be equal, X, Y, and Z
/// must be exactly the same between the two objects.
///
/// The object to be compared with.
/// true if the objects are equal, false otherwise
public override bool Equals( object obj )
{
PointPair rhs = obj as PointPair;
return this.X == rhs.X && this.Y == rhs.Y && this.Z == rhs.Z;
}
///
/// Return the HashCode from the base class.
///
///
public override int GetHashCode()
{
return base.GetHashCode();
}
///
/// Format this PointPair value using the default format. Example: "( 12.345, -16.876 )".
/// The two double values are formatted with the "g" format type.
///
/// true to show the third "Z" or low dependent value coordinate
/// A string representation of the PointPair
virtual public string ToString( bool isShowZ )
{
return this.ToString( PointPair.DefaultFormat, isShowZ );
}
///
/// Format this PointPair value using a general format string.
/// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
/// If
/// is true, then the third "Z" coordinate is also shown.
///
/// A format string that will be used to format each of
/// the two double type values (see ).
/// A string representation of the PointPair
/// true to show the third "Z" or low dependent value coordinate
virtual public string ToString( string format, bool isShowZ )
{
return "( " + this.X.ToString( format ) +
", " + this.Y.ToString( format ) +
( isShowZ ? ( ", " + this.Z.ToString( format ) ) : "" )
+ " )";
}
///
/// Format this PointPair value using different general format strings for the X, Y, and Z values.
/// Example: a format string of "e2" would give "( 1.23e+001, -1.69e+001 )".
///
/// A format string that will be used to format the X
/// double type value (see ).
/// A format string that will be used to format the Y
/// double type value (see ).
/// A format string that will be used to format the Z
/// double type value (see ).
/// A string representation of the PointPair
public string ToString( string formatX, string formatY, string formatZ )
{
return "( " + this.X.ToString( formatX ) +
", " + this.Y.ToString( formatY ) +
", " + this.Z.ToString( formatZ ) +
" )";
}
#endregion
}
}