// Returns true if point lies in the viewing plane, false otherwise protected bool ClipSegment(IAxis x_axis, IAxis y_axis, ref Point a, ref Point b) { long x_min, x_max; x_axis.GetGridClipRegion(out x_min, out x_max); long y_min, y_max; y_axis.GetGridClipRegion(out y_min, out y_max); // Use the Cohen-Sutherland algorithm to clip points // described http://www.cim.mcgill.ca/~langer/557B/Jan16.html int outcode_a, outcode_b; while (true) { outcode_a = Convert.ToInt32(a.Y > y_max) << 3; outcode_a |= Convert.ToInt32(a.Y < y_min) << 2; outcode_a |= Convert.ToInt32(a.X > x_max) << 1; outcode_a |= Convert.ToInt32(a.X < x_min); outcode_b = Convert.ToInt32(b.Y > y_max) << 3; outcode_b |= Convert.ToInt32(b.Y < y_min) << 2; outcode_b |= Convert.ToInt32(b.X > x_max) << 1; outcode_b |= Convert.ToInt32(b.X < x_min); // Trivially accept edge if bitwise OR of outcodes is 0000 if ((outcode_a | outcode_b) == 0) { return(true); } // Trivially reject edge if the bitwise AND of the two outcomes is other than 0000 if ((outcode_a & outcode_b) != 0) { return(false); } // Now, we know that at least one of the points needs to be clipped. Point p = a, o = b; int current_outcode = outcode_a; if (outcode_a == 0) { p = b; o = a; current_outcode = outcode_b; } double m = (b.Y - a.Y) / ((double)b.X - a.X); p.IsClipped = true; // handle vertical lines specially, since // Cohen-Sutherland doesn't specifically // discuss them bool is_vertical = (m == Double.PositiveInfinity); if ((current_outcode & 8) == 8) // Above { p.Y = y_max; p.X = (is_vertical) ? p.X : Convert.ToInt64(((p.Y - o.Y) / m) + o.X); } else if ((current_outcode & 4) == 4) // Below { p.Y = y_min; p.X = (is_vertical) ? p.X : Convert.ToInt64(((p.Y - o.Y) / m) + o.X); } else if ((current_outcode & 2) == 2) // Right { p.X = x_max; p.Y = (is_vertical) ? p.Y : Convert.ToInt64(((p.X - o.X) * m) + o.Y); } else if ((current_outcode & 1) == 1) // Left { p.X = x_min; p.Y = (is_vertical) ? p.Y : Convert.ToInt64(((p.X - o.X) * m) + o.Y); } if (outcode_a != 0) { a = p; } else { b = p; } } }