示例#1
0
 private bool IsInside(Vertex point, int direction)
 {
     switch (direction)
     {
         case BOUND_RIGHT:
             if (point.X <= ClippingRectangle.Right) return true;
             return false;
         case BOUND_LEFT:
             if (point.X >= ClippingRectangle.Left) return true;
             return false;
         case BOUND_TOP:
             if (point.Y >= ClippingRectangle.Top) return true;
             return false;
         case BOUND_BOTTOM:
             if (point.Y <= ClippingRectangle.Bottom) return true;
             return false;
     }
     return false;
 }
示例#2
0
 /// <summary>
 /// Creates a segment from double valued ordinates.
 /// </summary>
 /// <param name="x1"></param>
 /// <param name="y1"></param>
 /// <param name="x2"></param>
 /// <param name="y2"></param>
 public Segment(double x1, double y1, double x2, double y2)
 {
     P1 = new Vertex(x1, y1);
     P2 = new Vertex(x2, y2);
 }
示例#3
0
 /// <summary>
 /// Tests to see if the specified segment contains the point within Epsilon tollerance.
 /// </summary>
 /// <returns></returns>
 public bool IntersectsVertex(Vertex point)
 {
     double x1 = P1.X;
     double y1 = P1.Y;
     double x2 = P2.X;
     double y2 = P2.Y;
     double pX = point.X;
     double pY = point.Y;
     // COllinear
     if (Math.Abs((x2 - x1) * (pY - y1) - (pX - x1) * (y2 - y1)) > Epsilon) return false;
     // In the x is in bounds and it is colinear, it is on the segment
     if (x1 < x2)
     {
         if (x1 <= pX && pX <= x2) return true;
     }
     else
     {
         if (x2 <= pX && pX <= x1) return true;
     }
     return false;
 }
示例#4
0
        /// <summary>
        /// Returns a vertex representing the closest point on this line segment from a given vertex
        /// </summary>
        /// <param name="point">The point we want to be close to</param>
        /// <param name="isInfiniteLine">If true treat the line as infinitly long</param>
        /// <param name="endPointFlag">Outputs 0 if the vertex is on the line segment, 1 if beyond P0, 2 if beyong P1 and -1 if P1=P2</param>
        /// <returns>The point on this segment or infinite line that is closest to the given point</returns>
        public Vertex ClosestPointTo(Vertex point, bool isInfiniteLine, out EndPointInteraction endPointFlag)
        {
            // If the points defining this segment are the same, we treat the segment as a point
            // special handling to avoid 0 in denominator later
            if (P2.X == P1.X && P2.Y == P1.Y)
            {
                endPointFlag = EndPointInteraction.P1equalsP2;
                return P1;
            }

            //http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm

            Vector v = ToVector(); // vector from p1 to p2 in the segment
            v.Z = 0;
            Vector w = new Vector(P1.ToCoordinate(), point.ToCoordinate()); // vector from p1 to Point
            w.Z = 0;
            double c1 = w.Dot(v); // the dot product represents the projection onto the line

            if (c1 < 0)
            {
                endPointFlag = EndPointInteraction.PastP1;
                if (!isInfiniteLine) // The closest point on the segment to Point is p1
                    return P1;
            }

            double c2 = v.Dot(v);

            if (c2 <= c1)
            {
                endPointFlag = EndPointInteraction.PastP2;
                if (!isInfiniteLine) // The closest point on the segment to Point is p2
                    return P2;
            }

            // The closest point on the segment is perpendicular to the point,
            // but somewhere on the segment between P1 and P2
            endPointFlag = EndPointInteraction.OnLine;
            double b = c1 / c2;
            v = v.Multiply(b);
            Vertex pb = new Vertex(P1.X + v.X, P1.Y + v.Y);
            return pb;
        }
示例#5
0
 /// <summary>
 /// Returns a vertex representing the closest point on this line segment from a given vertex
 /// </summary>
 /// <param name="point">The point we want to be close to</param>
 /// <returns>The point on this segment that is closest to the given point</returns>
 public Vertex ClosestPointTo(Vertex point)
 {
     EndPointInteraction endPointFlag;
     return ClosestPointTo(point, false, out endPointFlag);
 }
示例#6
0
 /// <summary>
 /// Creates a point shape from a vertex
 /// </summary>
 /// <param name="coord"></param>
 public Shape(Vertex coord)
 {
     _shapeRange = new ShapeRange(FeatureType.Point);
     _vertices = new double[2];
     _vertices[0] = coord.X;
     _vertices[1] = coord.Y;
     const int offset = 0;
     PartRange part = new PartRange(_vertices, 0, offset, FeatureType.Point);
     part.NumVertices = 1;
     _shapeRange.Parts.Add(part);
     _shapeRange.Extent = new Extent(coord.X, coord.Y, coord.X, coord.Y);
 }
示例#7
0
 /// <summary>
 /// Tests the intersection with a vertex
 /// </summary>
 /// <param name="vert"></param>
 /// <returns></returns>
 public bool Intersects(Vertex vert)
 {
     return Intersects(new Shape(vert).Range);
 }
示例#8
0
 private List<Vertex> ClipDirection(IEnumerable<Vertex> points, int direction)
 {
     bool previousInside = true;
     var result = new List<Vertex>();
     var previous = new Vertex();
     bool isFirst = true;
     foreach (var point in points)
     {
         bool inside = IsInside(point, direction);
         if (previousInside && inside)
         {
             // both points are inside, so simply add the current point
             result.Add(point);
             previous = point;
         }
         if (previousInside && inside == false)
         {
             if (isFirst == false)
             {
                 // crossing the boundary going out, so insert the intersection instead
                 result.Add(BoundIntersection(previous, point, direction));
             }
             previous = point;
         }
         if (previousInside == false && inside)
         {
             // crossing the boundary going in, so insert the intersection AND the new point
             result.Add(BoundIntersection(previous, point, direction));
             result.Add(point);
             previous = point;
         }
         if (previousInside == false && inside == false)
         {
             previous = point;
         }
         isFirst = false;
         previousInside = inside;
     }
     // be sure to close the polygon if it is not closed
     if (result.Count > 0)
     {
         if (result[0].X != result[result.Count - 1].X ||
             result[0].Y != result[result.Count - 1].Y)
         {
             result.Add(result[0]);
         }
     }
     return result;
 }
示例#9
0
 /// <summary>
 /// Creates a new "point" shape that has only the one point.
 /// </summary>
 /// <param name="v"></param>
 public ShapeRange(Vertex v)
 {
     FeatureType = FeatureType.Point;
     Parts = new List<PartRange>();
     _numParts = -1;
     double[] coords = new double[2];
     coords[0] = v.X;
     coords[1] = v.Y;
     PartRange prt = new PartRange(coords, 0, 0, FeatureType.Point);
     prt.NumVertices = 1;
     Extent = new Extent(v.X, v.Y, v.X, v.Y);
     Parts.Add(prt);
 }
示例#10
0
 private Coordinate GetCoordinate(Vertex vertex, int index)
 {
     var c = new Coordinate(vertex.X, vertex.Y);
     if (M != null && M.Length > 0) c.M = M[index];
     if (Z != null && Z.Length > 0) c.Z = Z[index];
     return c;
 }
示例#11
0
 /// <summary>
 /// Creates a point shape from a vertex
 /// </summary>
 /// <param name="coord"></param>
 public Shape(Vertex coord)
 {
     _shapeRange = new ShapeRange(FeatureType.Point);
     _vertices = new [] { coord.X, coord.Y };
     _shapeRange.Parts.Add(new PartRange(_vertices, 0, 0, FeatureType.Point) {NumVertices = 1});
     _shapeRange.Extent = new Extent(coord.X, coord.Y, coord.X, coord.Y);
 }
示例#12
0
 /// <summary>
 /// Tests to see if the point is inside or on the boundary of this extent.
 /// </summary>
 /// <param name="vert"></param>
 /// <returns></returns>
 public bool Intersects(Vertex vert)
 {
     if (vert.X < MinX)
     {
         return false;
     }
     if (vert.X > MaxX)
     {
         return false;
     }
     if (vert.Y < MinY)
     {
         return false;
     }
     return !(vert.Y > MaxY);
 }
示例#13
0
 /// <summary>
 /// Reads double precision X and Y values that are interwoven
 /// </summary>
 /// <param name="count"></param>
 /// <returns></returns>
 public Vertex[] ReadVertices(int count)
 {
     int len = count * 16;
     byte[] rawBytes = new byte[len];
     Read(rawBytes, 0, len);
     Vertex[] result = new Vertex[count];
     Buffer.BlockCopy(rawBytes, 0, result, 0, len);
     return result;
 }
示例#14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool Equals(Vertex other)
 {
     return other.X == X && other.Y == Y;
 }
示例#15
0
 /// <summary>
 /// Creates a new instance of Segment
 /// </summary>
 public Segment(Vertex p1, Vertex p2)
 {
     P1 = p1;
     P2 = p2;
 }
示例#16
0
 /// <summary>
 /// Gets the first vertex from the first part.
 /// </summary>
 /// <returns></returns>
 public Vertex First()
 {
     double[] verts = Parts[0].Vertices;
     Vertex result = new Vertex(verts[StartIndex], verts[StartIndex + 1]);
     return result;
 }
示例#17
0
 /// <summary>
 /// Calculates the shortest distance to this line segment from the specified MapWinGIS.Point
 /// </summary>
 /// <param name="point">A MapWinGIS.Point specifing the location to find the distance to the line</param>
 /// <returns>A double value that is the shortest distance from the given Point to this line segment</returns>
 public double DistanceTo(Coordinate point)
 {
     Vertex p = new Vertex(point.X, point.Y);
     Vertex pt = ClosestPointTo(p);
     Vector dist = new Vector(new Coordinate(pt.X, pt.Y), point);
     return dist.Length2D;
 }
示例#18
0
 private Vertex BoundIntersection(Vertex start, Vertex end, int direction)
 {
     double x, y;
     switch (direction)
     {
         case BOUND_RIGHT:
             x = ClippingRectangle.Right;
             y = start.Y + (end.Y - start.Y) * (ClippingRectangle.Right - start.X) / (end.X - start.X);
             break;
         case BOUND_LEFT:
             x = ClippingRectangle.Left;
             y = start.Y + (end.Y - start.Y) * (ClippingRectangle.Left - start.X) / (end.X - start.X);
             break;
         case BOUND_TOP:
             y = ClippingRectangle.Top;
             x = start.X + (end.X - start.X) * (ClippingRectangle.Top - start.Y) / (end.Y - start.Y);
             break;
         case BOUND_BOTTOM:
             y = ClippingRectangle.Bottom;
             x = start.X + (end.X - start.X) * (ClippingRectangle.Bottom - start.Y) / (end.Y - start.Y);
             break;
         default:
             x = y = 0;
             break;
     }
     return new Vertex(x, y);
 }