//============================================================================ //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 } }