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; }
/// <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); }
/// <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; }
/// <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; }
/// <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); }
/// <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); }
/// <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); }
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; }
/// <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); }
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; }
/// <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); }
/// <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); }
/// <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; }
/// <summary> /// /// </summary> /// <param name="other"></param> /// <returns></returns> public bool Equals(Vertex other) { return other.X == X && other.Y == Y; }
/// <summary> /// Creates a new instance of Segment /// </summary> public Segment(Vertex p1, Vertex p2) { P1 = p1; P2 = p2; }
/// <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; }
/// <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; }
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); }