PrecisionModel.cs :  » GIS » DeepEarth » GisSharpBlog » NetTopologySuite » Geometries » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GIS » DeepEarth 
DeepEarth » GisSharpBlog » NetTopologySuite » Geometries » PrecisionModel.cs
using System;
using GeoAPI.Geometries;

namespace GisSharpBlog.NetTopologySuite.Geometries{        
    /// <summary> 
    /// Specifies the precision model of the <c>Coordinate</c>s in a <c>Geometry</c>.
    /// In other words, specifies the grid of allowable
    /// points for all <c>Geometry</c>s.
    /// The <c>makePrecise</c> method allows rounding a coordinate to
    /// a "precise" value; that is, one whose
    /// precision is known exactly.
    /// Coordinates are assumed to be precise in geometries.
    /// That is, the coordinates are assumed to be rounded to the
    /// precision model given for the point.
    /// NTS input routines automatically round coordinates to the precision model
    /// before creating Geometries.
    /// All internal operations
    /// assume that coordinates are rounded to the precision model.
    /// Constructive methods (such as bool operations) always round computed
    /// coordinates to the appropriate precision model.
    /// Currently three types of precision model are supported:
    /// <para>
    /// Floating: represents full double precision floating point.
    /// This is the default precision model used in NTS
    /// FloatingSingle: represents single precision floating point.
    /// Fixed: represents a model with a fixed number of decimal places.
    /// </para>
    /// A Fixed Precision Model is specified by a scale factor.
    /// The scale factor specifies the grid which numbers are rounded to.
    /// Input coordinates are mapped to fixed coordinates according to the following
    /// equations:
    ///  jtsPt.x = round( (inputPt.x * scale ) / scale
    ///  jtsPt.y = round( (inputPt.y * scale ) / scale
    /// Coordinates are represented internally as double-precision values.
    /// Since .NET uses the IEEE-394 floating point standard, this
    /// provides 53 bits of precision. (Thus the maximum precisely representable
    /// integer is 9,007,199,254,740,992).
    /// NTS methods currently do not handle inputs with different precision models.
  /// </summary>
#if !SILVERLIGHT
  [Serializable]
#endif
  public class PrecisionModel : IPrecisionModel
    {
        private const int FloatingPrecisionDigits = 16;
        private const int FloatingSinglePrecisionDigits = 6;
        private const int FixedPrecisionDigits = 1;

        /// <summary>  
        /// The maximum precise value representable in a double. Since IEE754
        /// double-precision numbers allow 53 bits of mantissa, the value is equal to
        /// 2^53 - 1.  This provides <i>almost</i> 16 decimal digits of precision.
        /// </summary>
        public const double MaximumPreciseValue = 9007199254740992.0;

        /// <summary>
        /// The type of PrecisionModel this represents.
        /// </summary>
        private PrecisionModels modelType;

        /// <summary> 
        /// The scale factor which determines the number of decimal places in fixed precision.
        /// </summary>
        private double scale;

        /// <summary> 
        /// Creates a <c>PrecisionModel</c> with a default precision
        /// of Floating.
        /// </summary>
        public PrecisionModel() 
        {
            // default is floating precision
            modelType = PrecisionModels.Floating;
        }

        /// <summary>
        /// Creates a <c>PrecisionModel</c> that specifies
        /// an explicit precision model type.
        /// If the model type is Fixed the scale factor will default to 1.
        /// </summary>
        /// <param name="modelType">
        /// The type of the precision model.
        /// </param>
        public PrecisionModel(PrecisionModels modelType)
        {
            this.modelType = modelType;

            if (modelType == PrecisionModels.Fixed)
                Scale = 1.0;            
        }

        /// <summary>  
        /// Creates a <c>PrecisionModel</c> that specifies Fixed precision.
        /// Fixed-precision coordinates are represented as precise internal coordinates,
        /// which are rounded to the grid defined by the scale factor.        
        /// </summary>
        /// <param name="scale">
        /// Amount by which to multiply a coordinate after subtracting
        /// the offset, to obtain a precise coordinate
        /// </param>
        /// <param name="offsetX">Not used.</param>
        /// <param name="offsetY">Not used.</param>
        [Obsolete("Offsets are no longer supported, since internal representation is rounded floating point")]
        public PrecisionModel(double scale, double offsetX, double offsetY) 
        {
            modelType = PrecisionModels.Fixed;
            Scale = scale;
        }

        /// <summary>  
        /// Creates a <c>PrecisionModel</c> that specifies Fixed precision.
        /// Fixed-precision coordinates are represented as precise internal coordinates,
        /// which are rounded to the grid defined by the scale factor.
        /// </summary>
        /// <param name="scale">
        /// Amount by which to multiply a coordinate after subtracting
        /// the offset, to obtain a precise coordinate.
        /// </param>  
        public PrecisionModel(double scale) 
        {
            modelType = PrecisionModels.Fixed;
            Scale = scale;
        }

        /// <summary> 
        /// Copy constructor to create a new <c>PrecisionModel</c>
        /// from an existing one.
        /// </summary>
        /// <param name="pm"></param>
        public PrecisionModel(PrecisionModel pm) 
        {
            modelType = pm.modelType;
            scale = pm.scale;
        }

        /// <summary>
        /// Return HashCode.
        /// </summary>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }


        /// <summary> 
        /// Tests whether the precision model supports floating point.
        /// </summary>
        /// <returns><c>true</c> if the precision model supports floating point.</returns>
        public bool IsFloating
        {
            get
            {
                return modelType == PrecisionModels.Floating || modelType == PrecisionModels.FloatingSingle;
            }
        }

        /// <summary>
        /// Returns the maximum number of significant digits provided by this
        /// precision model.
        /// Intended for use by routines which need to print out precise values.
        /// </summary>
        /// <returns>
        /// The maximum number of decimal places provided by this precision model.
        /// </returns>
        public int MaximumSignificantDigits
        {
            get
            {
                switch (modelType)
                {
                    case PrecisionModels.Floating:
                        return FloatingPrecisionDigits;
                    case PrecisionModels.FloatingSingle:
                        return FloatingSinglePrecisionDigits;
                    case PrecisionModels.Fixed:
                        return FixedPrecisionDigits + (int)Math.Ceiling(Math.Log(Scale) / Math.Log(10));
                    default:
                        throw new ArgumentOutOfRangeException(modelType.ToString());
                }
            }
      }

        /// <summary>
        /// Returns the multiplying factor used to obtain a precise coordinate.
        /// This method is private because PrecisionModel is intended to
        /// be an immutable (value) type.
        /// </summary>
        /// <returns>    
        /// the amount by which to multiply a coordinate after subtracting
        /// the offset.
        /// </returns>
        public double Scale
        {
            get { return scale; }
            set { this.scale = Math.Abs(value); }
        }

        /// <summary> 
        /// Gets the type of this PrecisionModel.
        /// </summary>
        /// <returns></returns>
        public PrecisionModels GetPrecisionModelType()
        {                        
            return modelType;
        }

        /// <summary> 
        /// Gets the type of this PrecisionModel.
        /// </summary>
        /// <returns></returns>
        public PrecisionModels PrecisionModelType
        {
            get { return modelType; }            
        }

        /// <summary> 
        /// Returns the x-offset used to obtain a precise coordinate.
        /// </summary>
        /// <returns>
        /// The amount by which to subtract the x-coordinate before
        /// multiplying by the scale.
        /// </returns>
        [Obsolete("Offsets are no longer used")]
        public double OffsetX
        {
            get { return 0; }
        }

        /// <summary> 
        /// Returns the y-offset used to obtain a precise coordinate.
        /// </summary>
        /// <returns> 
        /// The amount by which to subtract the y-coordinate before
        /// multiplying by the scale
        /// </returns>
        [Obsolete("Offsets are no longer used")]
        public double OffsetY
        {
            get { return 0; }
        }

        /// <summary>  
        /// Sets <c>internal</c> to the precise representation of <c>external</c>.
        /// </summary>
        /// <param name="cexternal">The original coordinate.</param>
        /// <param name="cinternal">
        /// The coordinate whose values will be changed to the
        /// precise representation of <c>external</c>.
        /// </param>        
        [Obsolete("Use MakePrecise instead")]
        public void ToInternal(ICoordinate cexternal, ICoordinate cinternal) 
        {
            if (IsFloating) 
            {
                cinternal.X = cexternal.X;
                cinternal.Y = cexternal.Y;
            }
            else 
            {
                cinternal.X = MakePrecise(cexternal.X);
                cinternal.Y = MakePrecise(cexternal.Y);
            }
            cinternal.Z = cexternal.Z;
        }

        /// <summary>  
        /// Returns the precise representation of <c>external</c>.
        /// </summary>
        /// <param name="cexternal">The original coordinate.</param>
        /// <returns>
        /// The coordinate whose values will be changed to the precise
        /// representation of <c>external</c>
        /// </returns>
        [Obsolete("Use MakePrecise instead")]
        public ICoordinate ToInternal(ICoordinate cexternal) 
        {
            ICoordinate cinternal = new Coordinate(cexternal);
            MakePrecise( cinternal);
            return cinternal;
        }

        /// <summary>
        /// Returns the external representation of <c>internal</c>.
        /// </summary>
        /// <param name="cinternal">The original coordinate.</param>
        /// <returns>
        /// The coordinate whose values will be changed to the
        /// external representation of <c>internal</c>.
        /// </returns>
        [Obsolete("No longer needed, since internal representation is same as external representation")]
        public ICoordinate ToExternal(ICoordinate cinternal) 
        {
            ICoordinate cexternal = new Coordinate(cinternal);
            return cexternal;
        }

        /// <summary>  
        /// Sets <c>external</c> to the external representation of <c>internal</c>.
        /// </summary>
        /// <param name="cinternal">The original coordinate.</param>
        /// <param name="cexternal">
        /// The coordinate whose values will be changed to the
        /// external representation of <c>internal</c>.
        /// </param>
        [Obsolete("No longer needed, since internal representation is same as external representation")]
        public void ToExternal(ICoordinate cinternal, ICoordinate cexternal) 
        {
            cexternal.X = cinternal.X;
            cexternal.Y = cinternal.Y;
        }

        /// <summary> 
        /// Rounds a numeric value to the PrecisionModel grid.
        /// Symmetric Arithmetic Rounding is used, to provide
        /// uniform rounding behaviour no matter where the number is
        /// on the number line.
        /// </summary>
        /// <param name="val"></param>
        public double MakePrecise(double val) 
        {
            if (modelType == PrecisionModels.FloatingSingle)
            {                
              float floatSingleVal = (float) val;
              return (double)floatSingleVal;
            }            
            if (modelType == PrecisionModels.Fixed) 
              // return Math.Round(val * scale) / scale;          // Diego Guidi say's: i use the Java Round algorithm (used in JTS 1.6)
                                                                    // Java Rint method, used in JTS 1.5, was consistend with .NET Round algorithm
                return Math.Floor(((val * scale) + 0.5d)) / scale;
            return val;     // modelType == FLOATING - no rounding necessary
        }

        /// <summary> 
        /// Rounds a Coordinate to the PrecisionModel grid.
        /// </summary>
        /// <param name="coord"></param>
        public void MakePrecise(ICoordinate coord)
        {
            // optimization for full precision
            if (modelType == PrecisionModels.Floating) 
                return;

            coord.X = MakePrecise(coord.X);
            coord.Y = MakePrecise(coord.Y);
            //MD says it's OK that we're not makePrecise'ing the z [Jon Aquino]
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString() 
        {
            string description = "UNKNOWN";
            if (modelType == PrecisionModels.Floating)
              description = "Floating";            
            else if (modelType == PrecisionModels.FloatingSingle)
              description = "Floating-Single";            
            else if (modelType == PrecisionModels.Fixed) 
              description = "Fixed (Scale=" + Scale + ")";            
            return description;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public override bool Equals(object other) 
        {
            if (other == null)
                return false;

            if (!(other is IPrecisionModel))
                return false;            

            return Equals((IPrecisionModel) other);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="otherPrecisionModel"></param>
        /// <returns></returns>
        public bool Equals(IPrecisionModel otherPrecisionModel)
        {
            return  modelType == otherPrecisionModel.PrecisionModelType &&
                    scale == otherPrecisionModel.Scale;
        }        
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        public static bool operator ==(PrecisionModel obj1, PrecisionModel obj2)
        {
            return Equals(obj1, obj2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        public static bool operator !=(PrecisionModel obj1, PrecisionModel obj2)
        {
            return !(obj1 == obj2);
        }       

        /// <summary> 
        /// Compares this <c>PrecisionModel</c> object with the specified object for order.
        /// A PrecisionModel is greater than another if it provides greater precision.
        /// The comparison is based on the value returned by the
        /// {getMaximumSignificantDigits) method.
        /// This comparison is not strictly accurate when comparing floating precision models
        /// to fixed models; however, it is correct when both models are either floating or fixed.
        /// </summary>
        /// <param name="o">
        /// The <c>PrecisionModel</c> with which this <c>PrecisionModel</c>
        /// is being compared.
        /// </param>
        /// <returns>
        /// A negative integer, zero, or a positive integer as this <c>PrecisionModel</c>
        /// is less than, equal to, or greater than the specified <c>PrecisionModel</c>.
        /// </returns>
        public int CompareTo(object o) 
        {
            return CompareTo((IPrecisionModel) o);   
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int CompareTo(IPrecisionModel other)
        {
            int sigDigits = MaximumSignificantDigits;
            int otherSigDigits = other.MaximumSignificantDigits;
            return (sigDigits).CompareTo(otherSigDigits);
        }
    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.