LineSegment.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 » LineSegment.cs
using System;
using System.Text;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Algorithm;

namespace GisSharpBlog.NetTopologySuite.Geometries{
    /// <summary> 
    /// Represents a line segment defined by two <c>Coordinate</c>s.
    /// Provides methods to compute various geometric properties
    /// and relationships of line segments.
    /// This class is designed to be easily mutable (to the extent of
    /// having its contained points public).
    /// This supports a common pattern of reusing a single LineSegment
    /// object as a way of computing segment properties on the
    /// segments defined by arrays or lists of <c>Coordinate</c>s.
    /// </summary>    
#if !SILVERLIGHT
  [Serializable]
#endif
    public class LineSegment: IComparable
    {
        private ICoordinate p0 = null, p1 = null;

        /// <summary>
        /// 
        /// </summary>
        public ICoordinate P1
        {
            get { return p1; }
            set { p1 = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public ICoordinate P0
        {
            get { return p0; }
            set { p0 = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        public LineSegment(ICoordinate p0, ICoordinate p1) 
        {
            this.p0 = p0;
            this.p1 = p1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ls"></param>
        public LineSegment(LineSegment ls) : this(ls.p0, ls.p1) { }

        /// <summary>
        /// 
        /// </summary>
        public LineSegment() : this(new Coordinate(), new Coordinate()) { }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public ICoordinate GetCoordinate(int i)
        {
            if (i == 0) return P0;
            return P1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ls"></param>
        public void SetCoordinates(LineSegment ls)
        {
            SetCoordinates(ls.P0, ls.P1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        public void SetCoordinates(ICoordinate p0, ICoordinate p1)
        {
            this.P0.X = p0.X;
            this.P0.Y = p0.Y;
            this.P1.X = p1.X;
            this.P1.Y = p1.Y;
        }

        /// <summary>
        /// Computes the length of the line segment.
        /// </summary>
        /// <returns>The length of the line segment.</returns>
        public double Length
        {
            get
            {
                return P0.Distance(P1);
            }
        }

        /// <summary> 
        /// Tests whether the segment is horizontal.
        /// </summary>
        /// <returns><c>true</c> if the segment is horizontal.</returns>
        public bool IsHorizontal
        {
            get
            {
                return P0.Y == P1.Y;
            }
        }

        /// <summary>
        /// Tests whether the segment is vertical.
        /// </summary>
        /// <returns><c>true</c> if the segment is vertical.</returns>
        public bool IsVertical
        {
            get
            {
                return P0.X == P1.X;
            }
        }

        /// <summary> 
        /// Determines the orientation of a LineSegment relative to this segment.
        /// The concept of orientation is specified as follows:
        /// Given two line segments A and L,
        /// A is to the left of a segment L if A lies wholly in the
        /// closed half-plane lying to the left of L
        /// A is to the right of a segment L if A lies wholly in the
        /// closed half-plane lying to the right of L
        /// otherwise, A has indeterminate orientation relative to L. This
        /// happens if A is collinear with L or if A crosses the line determined by L.
        /// </summary>
        /// <param name="seg">The <c>LineSegment</c> to compare.</param>
        /// <returns>
        /// 1 if <c>seg</c> is to the left of this segment,        
        /// -1 if <c>seg</c> is to the right of this segment,
        /// 0 if <c>seg</c> has indeterminate orientation relative to this segment.
        /// </returns>
        public int OrientationIndex(LineSegment seg)
        {
            int orient0 = CGAlgorithms.OrientationIndex(P0, P1, seg.P0);
            int orient1 = CGAlgorithms.OrientationIndex(P0, P1, seg.P1);
            // this handles the case where the points are Curve or collinear
            if (orient0 >= 0 && orient1 >= 0)
                return Math.Max(orient0, orient1);
            // this handles the case where the points are R or collinear
            if (orient0 <= 0 && orient1 <= 0)
                return Math.Max(orient0, orient1);
            // points lie on opposite sides ==> indeterminate orientation
            return 0;
        }

        /// <summary> 
        /// Reverses the direction of the line segment.
        /// </summary>
        public void Reverse()
        {
            ICoordinate temp = P0;
            P0 = P1;
            P1 = temp;
        }

        /// <summary> 
        /// Puts the line segment into a normalized form.
        /// This is useful for using line segments in maps and indexes when
        /// topological equality rather than exact equality is desired.
        /// </summary>
        public void Normalize()
        {
            if (P1.CompareTo(P0) < 0) 
                Reverse();
        }

        /// <returns> 
        /// The angle this segment makes with the x-axis (in radians).
        /// </returns>
        public double Angle
        {
            get
            {
               return Math.Atan2(P1.Y - P0.Y, P1.X - P0.X);
            }
        }

        /// <summary> 
        /// Computes the distance between this line segment and another one.
        /// </summary>
        /// <param name="ls"></param>
        /// <returns></returns>
        public double Distance(LineSegment ls)
        {
            return CGAlgorithms.DistanceLineLine(P0, P1, ls.P0, ls.P1);
        }

        /// <summary> 
        /// Computes the distance between this line segment and a point.
        /// </summary>
        public double Distance(ICoordinate p)
        {
            return CGAlgorithms.DistancePointLine(p, P0, P1);
        }

        /// <summary> 
        /// Computes the perpendicular distance between the (infinite) line defined
        /// by this line segment and a point.
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public double DistancePerpendicular(ICoordinate p)
        {
            return CGAlgorithms.DistancePointLinePerpendicular(p, P0, P1);
        }

        /// <summary>
        /// Compute the projection factor for the projection of the point p
        /// onto this <c>LineSegment</c>. The projection factor is the constant k
        /// by which the vector for this segment must be multiplied to
        /// equal the vector for the projection of p.
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public double ProjectionFactor(ICoordinate p)
        {
            if (p.Equals(P0)) return 0.0;
            if (p.Equals(P1)) return 1.0;

            // Otherwise, use comp.graphics.algorithms Frequently Asked Questions method
            /*                 AC dot AB
                        r = ------------
                              ||AB||^2
                        r has the following meaning:
                        r=0 Point = A
                        r=1 Point = B
                        r<0 Point is on the backward extension of AB
                        r>1 Point is on the forward extension of AB
                        0<r<1 Point is interior to AB
            */
            double dx = P1.X - P0.X;
            double dy = P1.Y - P0.Y;
            double len2 = dx * dx + dy * dy;
            double r = ((p.X - P0.X) * dx + (p.Y - P0.Y) * dy) / len2;
            return r;
        }

        /// <summary> 
        /// Compute the projection of a point onto the line determined
        /// by this line segment.
        /// Note that the projected point
        /// may lie outside the line segment.  If this is the case,
        /// the projection factor will lie outside the range [0.0, 1.0].
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public ICoordinate Project(ICoordinate p)
        {
            if (p.Equals(P0) || p.Equals(P1)) 
                return new Coordinate(p);

            double r = ProjectionFactor(p);
            ICoordinate coord = new Coordinate();
            coord.X = P0.X + r * (P1.X - P0.X);
            coord.Y = P0.Y + r * (P1.Y - P0.Y);
            return coord;
        }

        /// <summary> 
        /// Project a line segment onto this line segment and return the resulting
        /// line segment.  The returned line segment will be a subset of
        /// the target line line segment.  This subset may be null, if
        /// the segments are oriented in such a way that there is no projection.
        /// Note that the returned line may have zero length (i.e. the same endpoints).
        /// This can happen for instance if the lines are perpendicular to one another.
        /// </summary>
        /// <param name="seg">The line segment to project.</param>
        /// <returns>The projected line segment, or <c>null</c> if there is no overlap.</returns>
        public LineSegment Project(LineSegment seg)
        {
            double pf0 = ProjectionFactor(seg.P0);
            double pf1 = ProjectionFactor(seg.P1);
            // check if segment projects at all
            if (pf0 >= 1.0 && pf1 >= 1.0) return null;
            if (pf0 <= 0.0 && pf1 <= 0.0) return null;

            ICoordinate newp0 = Project(seg.P0);
            if (pf0 < 0.0) newp0 = P0;
            if (pf0 > 1.0) newp0 = P1;

            ICoordinate newp1 = Project(seg.P1);
            if (pf1 < 0.0) newp1 = P0;
            if (pf1 > 1.0) newp1 = P1;

            return new LineSegment(newp0, newp1);
        }

        /// <summary> 
        /// Computes the closest point on this line segment to another point.
        /// </summary>
        /// <param name="p">The point to find the closest point to.</param>
        /// <returns>
        /// A Coordinate which is the closest point on the line segment to the point p.
        /// </returns>
        public ICoordinate ClosestPoint(ICoordinate p)
        {
            double factor = ProjectionFactor(p);
            if (factor > 0 && factor < 1) 
                return Project(p);
            double dist0 = P0.Distance(p);
            double dist1 = P1.Distance(p);
            if (dist0 < dist1)
                return P0;
            else return P1;
        }

        /// <summary>
        /// Computes the closest points on a line segment.
        /// </summary>
        /// <param name="line"></param>
        /// <returns>
        /// A pair of Coordinates which are the closest points on the line segments.
        /// </returns>
        public ICoordinate[] ClosestPoints(LineSegment line)
        {
            // test for intersection
            ICoordinate intPt = Intersection(line);
            if (intPt != null)
                return new ICoordinate[] { intPt, intPt };            

            /*
            *  if no intersection closest pair contains at least one endpoint.
            * Test each endpoint in turn.
            */
            ICoordinate[] closestPt = new ICoordinate[2];
            double minDistance = Double.MaxValue;
            double dist;

            ICoordinate close00 = ClosestPoint(line.P0);
            minDistance = close00.Distance(line.P0);
            closestPt[0] = close00;
            closestPt[1] = line.P0;

            ICoordinate close01 = ClosestPoint(line.P1);
            dist = close01.Distance(line.P1);
            if (dist < minDistance) 
            {
                minDistance = dist;
                closestPt[0] = close01;
                closestPt[1] = line.P1;
            }

            ICoordinate close10 = line.ClosestPoint(P0);
            dist = close10.Distance(P0);
            if (dist < minDistance) 
            {
                minDistance = dist;
                closestPt[0] = P0;
                closestPt[1] = close10;
            }

            ICoordinate close11 = line.ClosestPoint(P1);
            dist = close11.Distance(P1);
            if (dist < minDistance) 
            {
                minDistance = dist;
                closestPt[0] = P1;
                closestPt[1] = close11;
            }

            return closestPt;
        }

        /// <summary>
        /// Computes an intersection point between two segments, if there is one.
        /// There may be 0, 1 or many intersection points between two segments.
        /// If there are 0, null is returned. If there is 1 or more, a single one
        /// is returned (chosen at the discretion of the algorithm).  If
        /// more information is required about the details of the intersection,
        /// the {RobustLineIntersector} class should be used.
        /// </summary>
        /// <param name="line"></param>
        /// <returns> An intersection point, or <c>null</c> if there is none.</returns>
        public ICoordinate Intersection(LineSegment line)
        {
            LineIntersector li = new RobustLineIntersector();
            li.ComputeIntersection(P0, P1, line.P0, line.P1);
            if (li.HasIntersection)
            return li.GetIntersection(0);
            return null;
        }

        /// <summary>  
        /// Returns <c>true</c> if <c>o</c> has the same values for its points.
        /// </summary>
        /// <param name="o">A <c>LineSegment</c> with which to do the comparison.</param>
        /// <returns>
        /// <c>true</c> if <c>o</c> is a <c>LineSegment</c>
        /// with the same values for the x and y ordinates.
        /// </returns>
        public override bool Equals(object o) 
        {
            if (o == null)
                return false;
            if (!(o is LineSegment)) 
                return false;            
            LineSegment other = (LineSegment) o;
            return p0.Equals(other.p0) && p1.Equals(other.p1);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        public static bool operator ==(LineSegment obj1, LineSegment obj2)
        {
            return Equals(obj1, obj2);
        }

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

        /// <summary>
        /// Compares this object with the specified object for order.
        /// Uses the standard lexicographic ordering for the points in the LineSegment.
        /// </summary>
        /// <param name="o">
        /// The <c>LineSegment</c> with which this <c>LineSegment</c>
        /// is being compared.
        /// </param>
        /// <returns>
        /// A negative integer, zero, or a positive integer as this <c>LineSegment</c>
        /// is less than, equal to, or greater than the specified <c>LineSegment</c>.
        /// </returns>
        public int CompareTo(object o) 
        {
            LineSegment other = (LineSegment) o;
            int comp0 = P0.CompareTo(other.P0);
            if (comp0 != 0) return comp0;
            return P1.CompareTo(other.P1);
        }

        /// <summary>
        /// Returns <c>true</c> if <c>other</c> is
        /// topologically equal to this LineSegment (e.g. irrespective
        /// of orientation).
        /// </summary>
        /// <param name="other">
        /// A <c>LineSegment</c> with which to do the comparison.
        /// </param>
        /// <returns>
        /// <c>true</c> if <c>other</c> is a <c>LineSegment</c>
        /// with the same values for the x and y ordinates.
        /// </returns>
        public bool EqualsTopologically(LineSegment other)
        {
            return
                P0.Equals(other.P0) && P1.Equals(other.P1) || 
                P0.Equals(other.P1) && P1.Equals(other.P0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("LINESTRING( ");
            sb.Append(P0.X).Append(" ");
            sb.Append(P0.Y).Append(", ");
            sb.Append(P1.X).Append(" ");
            sb.Append(P1.Y).Append(")");
            return sb.ToString();
        }

        /// <summary>
        /// Return HashCode.
        /// </summary>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.