public override bool Equals(Object obj) { // Check for null values and compare run-time types. if (obj == null || GetType() != obj.GetType()) { return(false); } LineSegment2D l = (LineSegment2D)obj; return(Start == l.Start && End == l.End); }
/** * Returns 1 if inside, 0 if intersecting and -1 outside. */ public LineRelation DescribeRelation(LineSegment2D line) { //int x1, int y1, int x2, int y2, float xmax = X + Width; float ymax = Y + Height; float u1 = 0.0f; float u2 = 1.0f; float deltaX = (line.End.X - line.Start.X); float deltaY = (line.End.Y - line.Start.Y); /* * left edge, right edge, bottom edge and top edge checking */ float[] pPart = { -deltaX, deltaX, -deltaY, deltaY }; float[] qPart = { line.Start.X - X, xmax - line.Start.X, line.Start.Y - Y, ymax - line.Start.Y }; for (int i = 0; i < 4; i++) { float p = pPart[i]; float q = qPart[i]; if (p == 0 && q < 0) { return(LineRelation.LINE_OUTSIDE); } float r = q / p; if (p < 0) { u1 = Math.Max(u1, r); } else if (p > 0) { u2 = Math.Min(u2, r); } if (u1 > u2) { return(LineRelation.LINE_OUTSIDE); } } if (u2 < 1 || u1 < 1) { return(LineRelation.LINE_INTERSECTS); } else { return(LineRelation.LINE_INSIDE); } }
public float DistanceSquared(LineSegment2D line) { //snap the 4 corners to the line and form delta Vector2D d1 = line.SnapDelta(TopLeft); Vector2D d2 = line.SnapDelta(TopRight); Vector2D d3 = line.SnapDelta(BottomLeft); Vector2D d4 = line.SnapDelta(BottomRight); float xLower = Math.Min(Math.Min(d1.X, d2.X), Math.Min(d3.X, d4.X)); float xUpper = Math.Max(Math.Max(d1.X, d2.X), Math.Max(d3.X, d4.X)); float dX = (xUpper * xLower < 0) ? 0 : Math.Min(Math.Abs(xLower), Math.Abs(xUpper)); //if not all on the same side distance along X axis is 0 float yLower = Math.Min(Math.Min(d1.Y, d2.Y), Math.Min(d3.Y, d4.Y)); float yUpper = Math.Max(Math.Max(d1.Y, d2.Y), Math.Max(d3.Y, d4.Y)); float dY = (yUpper * yLower < 0) ? 0 : Math.Min(Math.Abs(yLower), Math.Abs(yUpper)); //if not all on the same side distance along Y axis is 0 return(dX * dX + dY * dY); }
public float DistanceSquared(LineSegment2D other) { //see IsIntersecting... Vector2D v = StartToEnd; Vector2D ov = other.StartToEnd; Vector2D s = Start - other.Start; float denom = v.Cross(ov); if (denom == 0) //lines are parallel { float d = Direction.OrthogonalizedClockwise().Dot(s); return(d * d); } float a = CgMath.Saturate(ov.Cross(s) / denom); float b = CgMath.Saturate(v.Cross(s) / denom); return(Math.Min(other.DistanceSquared(Sample(a)), this.DistanceSquared(other.Sample(b)))); }
public bool Overlaps(LineSegment2D line) { //same aproach as distance to line segment but simplified //snap the 4 corners to the line and form delta Vector2D d1 = line.SnapDelta(TopLeft); Vector2D d2 = line.SnapDelta(TopRight); Vector2D d3 = line.SnapDelta(BottomLeft); Vector2D d4 = line.SnapDelta(BottomRight); if (CgMath.Sign(d1.X, d2.X, d3.X, d4.X) == 0)//mixed signs { return(true); } if (CgMath.Sign(d1.Y, d2.Y, d3.Y, d4.Y) == 0)//mixed signs { return(true); } return(false); }
/** * Get information on how the two lines interact. */ public Relation GetRelation(LineSegment2D other, float tolerance = 0) { //see IsIntersecting... Vector2D v = StartToEnd; Vector2D ov = other.StartToEnd; Vector2D s = Start - other.Start; float denom = v.Cross(ov); float a = ov.Cross(s) / denom; float b = v.Cross(s) / denom; Relation result = Relation.NoConnection; if (Math.Abs(a - 1) < tolerance && (b >= 0 && b <= 1)) //touching - a is 1 and b in range { result = result | Relation.EndConnects; } if (Math.Abs(a) < tolerance && (b >= 0 && b <= 1)) //touching - a is 0 and b in range { result = result | Relation.StartConnects; } if (Math.Abs(b) < tolerance && (a >= 0 && a <= 1)) //touching - b is 1 and a in range { result = result | Relation.OtherStartConnects; } if (Math.Abs(b - 1) < tolerance && (a >= 0 && a <= 1)) //touching - b is 0 and a in range { result = result | Relation.OtherEndConnects; } if (a > tolerance && (a - 1) < tolerance && b > tolerance && (b - 1) < tolerance) { result = result | Relation.Intersection; } return(result); }
/** * Constrains a linesegment to fit in the rectangle. Uses Liang Barsky Algorithm. * Returns reference to the passed input argument after clipping or null if no portion of the line is within the rectangle. */ public LineSegment2D Clip(LineSegment2D line) { //int x1, int y1, int x2, int y2, Vector2D max = BottomRight; Vector2D start = line.Start; Vector2D delta = line.StartToEnd; float u1 = 0.0f; float u2 = 1.0f; if (delta.X == 0 && (start.X < X || start.X > max.X)) { return(LineSegment2D.Void); } if (delta.Y == 0 && (start.Y < Y || start.Y > max.Y)) { return(LineSegment2D.Void); } //ugly but optimized //left float r = (start.X - X) / (-delta.X); if (delta.X > 0) { u1 = Math.Max(u1, r); } else if (delta.X < 0) { u2 = Math.Min(u2, r); } if (u1 > u2) { return(LineSegment2D.Void); } //right r = (max.X - start.X) / delta.X; if (delta.X < 0) { u1 = Math.Max(u1, r); } else if (delta.X > 0) { u2 = Math.Min(u2, r); } if (u1 > u2) { return(LineSegment2D.Void); } //top r = (start.Y - Y) / -delta.Y; if (delta.Y > 0) { u1 = Math.Max(u1, r); } else if (delta.Y < 0) { u2 = Math.Min(u2, r); } if (u1 > u2) { return(LineSegment2D.Void); } //bottom r = (max.Y - start.Y) / delta.Y; if (delta.Y < 0) { u1 = Math.Max(u1, r); } else if (delta.Y > 0) { u2 = Math.Min(u2, r); } if (u1 > u2) { return(LineSegment2D.Void); } //clip if (u2 < 1) { line.End = start + u2 * delta; } if (u1 > 0) { line.Start = start + u1 * delta; } return(line); }
public float Distance(LineSegment2D line) { return((float)Math.Sqrt(DistanceSquared(line))); }
/** * Returns a new vector v at the position where the lines would intersect. Segment boundaries are not considered. */ public Vector2D Intersect(LineSegment2D other) { return(Start + StartToEnd * GetIntersectionRatio(other)); }
/** * Compare this line segment to another and return true if the lines are parallel. */ public bool IsParallel(LineSegment2D other, float tolerance = 0) { return(Math.Abs(StartToEnd.Cross(other.StartToEnd)) <= tolerance); }