/// <summary> /// Clip a linestring. /// </summary> /// <param name="linestring">Linestrings that should be clipped.</param> /// <param name="xmin">The minimum x of the clip rect.</param> /// <param name="ymin">The minimum y of the clip rect.</param> /// <param name="xmax">The maximum x of the clip rect.</param> /// <param name="ymax">The maximum y of the clip rect.</param> /// <returns> List of clipped linestrings.</returns> public static List <List <double[]> > ClipLinestring(List <double[]> linestring, double xmin, double ymin, double xmax, double ymax) { List <List <double[]> > returnLinestrings = new List <List <double[]> >(); List <double[]> returnLinestring = new List <double[]>(); int numLines = linestring.Count - 1; LineClipStatus prevClipStatus = LineClipStatus.Outside; for (int lineNum = 0; lineNum < numLines; lineNum++) { double[] p0 = linestring[lineNum]; double[] p1 = linestring[lineNum + 1]; double x0 = p0[X]; double y0 = p0[Y]; double x1 = p1[X]; double y1 = p1[Y]; LineClipStatus clipStatus = ClipLine(ref x0, ref y0, ref x1, ref y1, xmin, ymin, xmax, ymax); // See if we need to add no points, last point, or both points if (clipStatus != LineClipStatus.Outside) { if (prevClipStatus == LineClipStatus.Outside || (prevClipStatus & LineClipStatus.ClippedLast) == LineClipStatus.ClippedLast) { // Add both returnLinestring.Add(new[] { x0, y0 }); } returnLinestring.Add(new[] { x1, y1 }); } if ((clipStatus & LineClipStatus.ClippedLast) == LineClipStatus.ClippedLast) { returnLinestrings.Add(returnLinestring); returnLinestring = new List <double[]>(); prevClipStatus = LineClipStatus.Outside; } else { prevClipStatus = clipStatus; } } if (returnLinestring.Count > 1) { returnLinestrings.Add(returnLinestring); } return(returnLinestrings); }
/// <summary> /// Clip a line segment. Coordinates are modified in place. /// </summary> /// <param name="x1">The x value of the lines start point.</param> /// <param name="y1">The y value of the lines start point.</param> /// <param name="x2">The x value of the lines end point.</param> /// <param name="y2">The y value of the lines end point.</param> /// <param name="xmin">The minimum x of the clip rect.</param> /// <param name="ymin">The minimum y of the clip rect.</param> /// <param name="xmax">The maximum x of the clip rect.</param> /// <param name="ymax">The maximum y of the clip rect.</param> /// <returns> Clip status indicating how the line was clipped.</returns> public static LineClipStatus ClipLine(ref double x1, ref double y1, ref double x2, ref double y2, double xmin, double ymin, double xmax, double ymax) { // Outcodes for P0, P1, and whatever point lies outside the clip rectangle int hhh = 0; bool done = false; LineClipStatus returnValue = LineClipStatus.Unknown; // compute outcodes int outcode0 = ComputeOutCode(x1, y1, xmin, ymin, xmax, ymax); int outcode1 = ComputeOutCode(x2, y2, xmin, ymin, xmax, ymax); do { if ((outcode0 | outcode1) == 0) { if (returnValue == LineClipStatus.Unknown) { returnValue = LineClipStatus.Inside; } done = true; } else if ((outcode0 & outcode1) > 0) { returnValue = LineClipStatus.Outside; done = true; } else { // failed both tests, so calculate the line segment to clip // from an outside point to an intersection with clip edge double x = 0, y = 0; // At least one endpoint is outside the clip rectangle; pick it. int outcodeOut; if (outcode0 != 0) { outcodeOut = outcode0; returnValue |= LineClipStatus.ClippedFirst; } else { outcodeOut = outcode1; returnValue |= LineClipStatus.ClippedLast; } // Now find the intersection point; // use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0) if ((outcodeOut & Top) > 0) { x = x1 + ((x2 - x1) * (ymax - y1) / (y2 - y1)); y = ymax; } else if ((outcodeOut & Bottom) > 0) { x = x1 + ((x2 - x1) * (ymin - y1) / (y2 - y1)); y = ymin; } else if ((outcodeOut & Right) > 0) { y = y1 + ((y2 - y1) * (xmax - x1) / (x2 - x1)); x = xmax; } else if ((outcodeOut & Left) > 0) { y = y1 + ((y2 - y1) * (xmin - x1) / (x2 - x1)); x = xmin; } // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x1 = x; y1 = y; outcode0 = ComputeOutCode(x1, y1, xmin, ymin, xmax, ymax); } else { x2 = x; y2 = y; outcode1 = ComputeOutCode(x2, y2, xmin, ymin, xmax, ymax); } } hhh++; }while (done != true && hhh < 5000); return(returnValue); }