PackedCoordinateSequence.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 » PackedCoordinateSequence.cs
using System;
using GeoAPI.Geometries;

namespace GisSharpBlog.NetTopologySuite.Geometries{
    /// <summary>
    /// A <c>CoordinateSequence</c> implementation based on a packed arrays.
    /// A <c>CoordinateSequence</c> implementation based on a packed arrays.
    /// </summary>
    public abstract class PackedCoordinateSequence : ICoordinateSequence
    {        
        /// <summary>
        /// A soft reference to the Coordinate[] representation of this sequence.
        /// Makes repeated coordinate array accesses more efficient.
        /// </summary>
        protected WeakReference coordRef;

        /// <summary>
        /// The dimensions of the coordinates hold in the packed array
        /// </summary>
        protected int dimension;

        /// <summary>
        /// Returns the dimension (number of ordinates in each coordinate) for this sequence.
        /// </summary>
        /// <value></value>
        public int Dimension
        {
            get { return dimension; }            
        }

        /// <summary>
        /// Returns the number of coordinates in this sequence.
        /// </summary>
        /// <value></value>
        public abstract int Count { get; }

        /// <summary>
        /// Returns (possibly a copy of) the ith Coordinate in this collection.
        /// Whether or not the Coordinate returned is the actual underlying
        /// Coordinate or merely a copy depends on the implementation.
        /// Note that in the future the semantics of this method may change
        /// to guarantee that the Coordinate returned is always a copy. Callers are
        /// advised not to assume that they can modify a CoordinateSequence by
        /// modifying the Coordinate returned by this method.
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public ICoordinate GetCoordinate(int i) 
        {
            ICoordinate[] arr = GetCachedCoords();
            if(arr != null)
                 return arr[i];
            else return GetCoordinateInternal(i);
        }

        /// <summary>
        /// Returns a copy of the i'th coordinate in this sequence.
        /// This method optimizes the situation where the caller is
        /// going to make a copy anyway - if the implementation
        /// has already created a new Coordinate object, no further copy is needed.
        /// </summary>
        /// <param name="i">The index of the coordinate to retrieve.</param>
        /// <returns>
        /// A copy of the i'th coordinate in the sequence
        /// </returns>
        public ICoordinate GetCoordinateCopy(int i) 
        {
            return GetCoordinateInternal(i);
        }

        /// <summary>
        /// Copies the i'th coordinate in the sequence to the supplied Coordinate.  
        /// Only the first two dimensions are copied.        
        /// </summary>
        /// <param name="i">The index of the coordinate to copy.</param>
        /// <param name="c">A Coordinate to receive the value.</param>
        public void GetCoordinate(int i, ICoordinate c) 
        {
            c.X = GetOrdinate(i, Ordinates.X);
            c.Y = GetOrdinate(i, Ordinates.Y);
        }        

        /// <summary>
        /// Returns (possibly copies of) the Coordinates in this collection.
        /// Whether or not the Coordinates returned are the actual underlying
        /// Coordinates or merely copies depends on the implementation. 
        /// Note that if this implementation does not store its data as an array of Coordinates,
        /// this method will incur a performance penalty because the array needs to
        /// be built from scratch.
        /// </summary>
        /// <returns></returns>
        public ICoordinate[] ToCoordinateArray() 
        {
            ICoordinate[] arr = GetCachedCoords();
            // testing - never cache
            if (arr != null)
                return arr;

            arr = new ICoordinate[Count];
            for (int i = 0; i < arr.Length; i++) 
                arr[i] = GetCoordinateInternal(i);
            
            coordRef = new WeakReference(arr);
            return arr;
        }        

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ICoordinate[] GetCachedCoords() 
        {
            if (coordRef != null) 
            {
                ICoordinate[] arr = (ICoordinate[]) coordRef.Target;
                if (arr != null) 
                    return arr;
                else 
                {            
                    coordRef = null;
                    return null;
                }
            } 
            else return null;            
        }

        /// <summary>
        /// Returns ordinate X (0) of the specified coordinate.
        /// </summary>
        /// <param name="index"></param>
        /// <returns>
        /// The value of the X ordinate in the index'th coordinate.
        /// </returns>
        public double GetX(int index) 
        {
            return GetOrdinate(index, Ordinates.X);
        }

        /// <summary>
        /// Returns ordinate Y (1) of the specified coordinate.
        /// </summary>
        /// <param name="index"></param>
        /// <returns>
        /// The value of the Y ordinate in the index'th coordinate.
        /// </returns>
        public double GetY(int index) 
        {
            return GetOrdinate(index, Ordinates.Y);
        }

        /// <summary>
        /// Returns the ordinate of a coordinate in this sequence.
        /// Ordinate indices 0 and 1 are assumed to be X and Y.
        /// Ordinates indices greater than 1 have user-defined semantics
        /// (for instance, they may contain other dimensions or measure values).
        /// </summary>
        /// <param name="index">The coordinate index in the sequence.</param>
        /// <param name="ordinate">The ordinate index in the coordinate (in range [0, dimension-1]).</param>
        /// <returns></returns>
        public abstract double GetOrdinate(int index, Ordinates ordinate);


        /// <summary>
        /// Sets the first ordinate of a coordinate in this sequence.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        public void SetX(int index, double value) 
        {
            coordRef = null;
            SetOrdinate(index, Ordinates.X, value);
        }

        /// <summary>
        /// Sets the second ordinate of a coordinate in this sequence.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        public void setY(int index, double value) 
        {
            coordRef = null;
            SetOrdinate(index, Ordinates.Y, value);
        }

        /// <summary>
        /// Sets the ordinate of a coordinate in this sequence.
        /// </summary>
        /// <remarks>
        /// Warning: for performance reasons the ordinate index is not checked:
        /// if it is over dimensions you may not get an exception but a meaningless value.
        /// </remarks>        
        /// <param name="index">The coordinate index.</param>
        /// <param name="ordinate">The ordinate index in the coordinate, 0 based, 
        /// smaller than the number of dimensions.</param>
        /// <param name="value">The new ordinate value.</param>
        public abstract void SetOrdinate(int index, Ordinates ordinate, double value);

        /// <summary>
        /// Returns a Coordinate representation of the specified coordinate, by always
        /// building a new Coordinate object.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected abstract ICoordinate GetCoordinateInternal(int index);

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public abstract Object Clone();

        /// <summary>
        /// Expands the given Envelope to include the coordinates in the sequence.
        /// Allows implementing classes to optimize access to coordinate values.
        /// </summary>
        /// <param name="env">The envelope to expand.</param>
        /// <returns>A reference to the expanded envelope.</returns>
        public abstract IEnvelope ExpandEnvelope(IEnvelope env);
    }

    /// <summary>
    /// Packed coordinate sequence implementation based on doubles.
    /// </summary>
    public class PackedDoubleCoordinateSequence : PackedCoordinateSequence 
    {
        /// <summary>
        /// The packed coordinate array
        /// </summary>
        private double[] coords;

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedDoubleCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coords"></param>
        /// <param name="dimensions"></param>
        public PackedDoubleCoordinateSequence(double[] coords, int dimensions) 
        {
            if (dimensions < 2) 
                throw new ArgumentException("Must have at least 2 dimensions");
            
            if (coords.Length % dimensions != 0) 
                throw new ArgumentException("Packed array does not contain " + 
                    "an integral number of coordinates");
      
            this.dimension = dimensions;
            this.coords = coords;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedDoubleCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="dimensions"></param>
        public PackedDoubleCoordinateSequence(float[] coordinates, int dimensions) 
        {
            this.coords = new double[coordinates.Length];
            this.dimension = dimensions;
            for (int i = 0; i < coordinates.Length; i++) 
                this.coords[i] = coordinates[i];
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedDoubleCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="dimension"></param>
        public PackedDoubleCoordinateSequence(ICoordinate[] coordinates, int dimension) 
        {
            if (coordinates == null)
                coordinates = new ICoordinate[0];
            this.dimension = dimension;

            coords = new double[coordinates.Length * this.dimension];
            for (int i = 0; i < coordinates.Length; i++) 
            {
                coords[i * this.dimension] = coordinates[i].X;
                if (this.dimension >= 2)
                    coords[i * this.dimension + 1] = coordinates[i].Y;
                if (this.dimension >= 3)
                    coords[i * this.dimension + 2] = coordinates[i].Z;
            }
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="PackedDoubleCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coordinates"></param>
        public PackedDoubleCoordinateSequence(ICoordinate[] coordinates) : this(coordinates, 3) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedDoubleCoordinateSequence"/> class.
        /// </summary>
        /// <param name="size"></param>
        /// <param name="dimension"></param>
        public PackedDoubleCoordinateSequence(int size, int dimension)
        {
            this.dimension = dimension;
            coords = new double[size * this.dimension];
        }

        /// <summary>
        /// Returns a Coordinate representation of the specified coordinate, by always
        /// building a new Coordinate object.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected override ICoordinate GetCoordinateInternal(int index) 
        {
            double x = coords[index * dimension];
            double y = coords[index * dimension + 1];
            double z = dimension == 2 ? 0.0 : coords[index * dimension + 2];
            return new Coordinate(x, y, z);
        }

        /// <summary>
        /// Returns the number of coordinates in this sequence.
        /// </summary>
        /// <value></value>
        public override int Count 
        {
            get { return coords.Length / dimension; }
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override Object Clone() 
        {
            double[] clone = new double[coords.Length];
            Array.Copy(coords, clone, coords.Length);
            return new PackedDoubleCoordinateSequence(clone, dimension);
        }

        /// <summary>
        /// Returns the ordinate of a coordinate in this sequence.
        /// Ordinate indices 0 and 1 are assumed to be X and Y.
        /// Ordinates indices greater than 1 have user-defined semantics
        /// (for instance, they may contain other dimensions or measure values).
        /// </summary>
        /// <param name="index">The coordinate index in the sequence.</param>
        /// <param name="ordinate">The ordinate index in the coordinate (in range [0, dimension-1]).</param>
        /// <returns></returns>
        public override double GetOrdinate(int index, Ordinates ordinate) 
        {
            return coords[index * dimension + (int) ordinate];
        }

        /// <summary>
        /// Sets the ordinate of a coordinate in this sequence.
        /// </summary>
        /// <param name="index">The coordinate index.</param>
        /// <param name="ordinate">The ordinate index in the coordinate, 0 based,
        /// smaller than the number of dimensions.</param>
        /// <param name="value">The new ordinate value.</param>
        /// <remarks>
        /// Warning: for performance reasons the ordinate index is not checked:
        /// if it is over dimensions you may not get an exception but a meaningless value.
        /// </remarks>
        public override void SetOrdinate(int index, Ordinates ordinate, double value) 
        {
            coordRef = null;
            coords[index * dimension + (int) ordinate] = value;
        }

        /// <summary>
        /// Expands the given Envelope to include the coordinates in the sequence.
        /// Allows implementing classes to optimize access to coordinate values.
        /// </summary>
        /// <param name="env">The envelope to expand.</param>
        /// <returns>A reference to the expanded envelope.</returns>
        public override IEnvelope ExpandEnvelope(IEnvelope env)
        {
            for (int i = 0; i < coords.Length; i += dimension)
                env.ExpandToInclude(coords[i], coords[i + 1]);        
            return env;
        }
    }

    /// <summary>
    /// Packed coordinate sequence implementation based on floats.
    /// </summary>
    public class PackedFloatCoordinateSequence : PackedCoordinateSequence 
    {
        /// <summary>
        /// The packed coordinate array
        /// </summary>
        private float[] coords;

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedFloatCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coords"></param>
        /// <param name="dimensions"></param>
        public PackedFloatCoordinateSequence(float[] coords, int dimensions) 
        {
            if (dimensions < 2) 
                throw new ArgumentException("Must have at least 2 dimensions");      
            
            if (coords.Length % dimensions != 0) 
                throw new ArgumentException("Packed array does not contain " + 
                    "an integral number of coordinates");
      
            this.dimension = dimensions;
            this.coords = coords;
        }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="PackedFloatCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="dimensions"></param>
        public PackedFloatCoordinateSequence(double[] coordinates, int dimensions) 
        {
            this.coords = new float[coordinates.Length];
            this.dimension = dimensions;
            for (int i = 0; i < coordinates.Length; i++) 
                this.coords[i] = (float) coordinates[i];      
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedFloatCoordinateSequence"/> class.
        /// </summary>
        /// <param name="coordinates"></param>
        /// <param name="dimension"></param>
        public PackedFloatCoordinateSequence(ICoordinate[] coordinates, int dimension) 
        {
            if (coordinates == null)
                coordinates = new ICoordinate[0];
            this.dimension = dimension;

            coords = new float[coordinates.Length * this.dimension];
            for (int i = 0; i < coordinates.Length; i++) 
            {
                coords[i * this.dimension] = (float) coordinates[i].X;
                if (this.dimension >= 2)
                    coords[i * this.dimension + 1] = (float) coordinates[i].Y;
                if (this.dimension >= 3)
                coords[i * this.dimension + 2] = (float) coordinates[i].Z;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PackedFloatCoordinateSequence"/> class.
        /// </summary>
        /// <param name="size"></param>
        /// <param name="dimension"></param>
        public PackedFloatCoordinateSequence(int size, int dimension) 
        {
            this.dimension = dimension;
            coords = new float[size * this.dimension];
        }

        /// <summary>
        /// Returns a Coordinate representation of the specified coordinate, by always
        /// building a new Coordinate object.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected override ICoordinate GetCoordinateInternal(int index) 
        {
            double x = coords[index * dimension];
            double y = coords[index * dimension + 1];
            double z = dimension == 2 ? 0.0 : coords[index * dimension + 2];
            return new Coordinate(x, y, z);
        }

        /// <summary>
        /// Returns the number of coordinates in this sequence.
        /// </summary>
        /// <value></value>
        public override int Count
        {
            get { return coords.Length / dimension; }
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override Object Clone() 
        {
            float[] clone = new float[coords.Length];
            Array.Copy(coords, clone, coords.Length);
            return new PackedFloatCoordinateSequence(clone, dimension);
        }

        /// <summary>
        /// Returns the ordinate of a coordinate in this sequence.
        /// Ordinate indices 0 and 1 are assumed to be X and Y.
        /// Ordinates indices greater than 1 have user-defined semantics
        /// (for instance, they may contain other dimensions or measure values).
        /// </summary>
        /// <param name="index">The coordinate index in the sequence.</param>
        /// <param name="ordinate">The ordinate index in the coordinate (in range [0, dimension-1]).</param>
        /// <returns></returns>
        public override double GetOrdinate(int index, Ordinates ordinate) 
        {
            return coords[index * dimension + (int) ordinate];
        }

        /// <summary>
        /// Sets the ordinate of a coordinate in this sequence.
        /// </summary>
        /// <param name="index">The coordinate index.</param>
        /// <param name="ordinate">The ordinate index in the coordinate, 0 based,
        /// smaller than the number of dimensions.</param>
        /// <param name="value">The new ordinate value.</param>
        /// <remarks>
        /// Warning: for performance reasons the ordinate index is not checked:
        /// if it is over dimensions you may not get an exception but a meaningless value.
        /// </remarks>
        public override void SetOrdinate(int index, Ordinates ordinate, double value) 
        {
            coordRef = null;
            coords[index * dimension + (int) ordinate] = (float) value;
        }

        /// <summary>
        /// Expands the given Envelope to include the coordinates in the sequence.
        /// Allows implementing classes to optimize access to coordinate values.
        /// </summary>
        /// <param name="env">The envelope to expand.</param>
        /// <returns>A reference to the expanded envelope.</returns>
        public override IEnvelope ExpandEnvelope(IEnvelope env)
        {
        for (int i = 0; i < coords.Length; i += dimension )
            env.ExpandToInclude(coords[i], coords[i + 1]);      
        return env;
        }
    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.