The class encapsulates 2D line segment and provides some tool methods related to lines.

The class provides some methods which are related to line segments: distance to point, finding intersection point, etc.

A line segment may be converted to a Line.

Sample usage:

// create a segment LineSegment segment = new LineSegment( new Point( 0, 0 ), new Point( 3, 4 ) ); // get segment's length float length = segment.Length; // get intersection point with a line Point? intersection = segment.GetIntersectionWith( new Line( new Point( -3, 8 ), new Point( 0, 4 ) ) );
예제 #1
0
        public void DistanceToPointTest( float x, float y, float x1, float y1, float x2, float y2, float expectedDistance )
        {
            Point pt = new Point( x, y );
            Point pt1 = new Point( x1, y1 );
            Point pt2 = new Point( x2, y2 );
            LineSegment segment = new LineSegment( pt1, pt2 );

            Assert.AreEqual( expectedDistance, segment.DistanceToPoint( pt ) );
        }
예제 #2
0
        public void IntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2, float ix, float iy, IntersectionType type )
        {
            LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) );
            LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) );
            Point expectedIntersection = new Point( ix, iy );

            Assert.DoesNotThrow( ( ) =>
            {
                Point? segSeg = segA.GetIntersectionWith( segB );
                Point? segLine = segA.GetIntersectionWith( (Line) segB );
                Point? lineSeg = ( (Line) segA ).GetIntersectionWith( segB );

                if ( type == IntersectionType.AllFour )
                {
                    Assert.AreEqual( expectedIntersection, segSeg );
                }
                else
                {
                    Assert.AreEqual( null, segSeg );
                }

                if ( ( type == IntersectionType.AllFour ) || ( type == IntersectionType.SegmentA ) )
                {
                    Assert.AreEqual( expectedIntersection, segLine );
                }
                else
                {
                    Assert.AreEqual( null, segLine );
                }

                if ( ( type == IntersectionType.AllFour ) || ( type == IntersectionType.SegmentB ) )
                {
                    Assert.AreEqual( expectedIntersection, lineSeg );
                }
                else
                {
                    Assert.AreEqual( null, lineSeg );
                }
            } );

            Point? lineLine = ( (Line) segA ).GetIntersectionWith( (Line) segB );

            if ( type != IntersectionType.None )
            {
                Assert.AreEqual( expectedIntersection, lineLine );
            }
            else
            {
                Assert.AreEqual( null, lineLine );
            }
        }
예제 #3
0
        public void CommonIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2, float ix, float iy )
        {
            LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) );
            LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) );
            Point expectedIntersection = new Point( ix, iy );

            // are we really collinear?
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segA ).GetIntersectionWith( (Line) segB ) );

            Assert.Throws<InvalidOperationException>( ( ) => segA.GetIntersectionWith( (Line) segB ) );
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segA ).GetIntersectionWith( segB ) );
            Assert.Throws<InvalidOperationException>( ( ) => segB.GetIntersectionWith( (Line) segA ) );
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segB ).GetIntersectionWith( segA ) );
            Assert.AreEqual( expectedIntersection, segB.GetIntersectionWith( segA ) );
            Assert.AreEqual( expectedIntersection, segA.GetIntersectionWith( segB ) );
        }
예제 #4
0
        public void OverlappingSegmentIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2 )
        {
            LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) );
            LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) );

            // are we really collinear?
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segA ).GetIntersectionWith( (Line) segB ) );

            Assert.Throws<InvalidOperationException>( ( ) => segA.GetIntersectionWith( (Line) segB ) );
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segA ).GetIntersectionWith( segB ) );
            Assert.Throws<InvalidOperationException>( ( ) => segB.GetIntersectionWith( (Line) segA ) );
            Assert.Throws<InvalidOperationException>( ( ) => ( (Line) segB ).GetIntersectionWith( segA ) );
            Assert.Throws<InvalidOperationException>( ( ) => segB.GetIntersectionWith( segA ) );
            Assert.Throws<InvalidOperationException>( ( ) => segA.GetIntersectionWith( segB ) );
        }
예제 #5
0
        public void LengthTest( float sx, float sy, float ex, float ey, float expectedResult )
        {
            LineSegment segment = new LineSegment( new Point( sx, sy ), new Point( ex, ey ) );

            Assert.AreEqual( expectedResult, segment.Length );
        }
예제 #6
0
        public void ParallelIntersectionPointTest( float ax1, float ay1, float ax2, float ay2, float bx1, float by1, float bx2, float by2 )
        {
            LineSegment segA = new LineSegment( new Point( ax1, ay1 ), new Point( ax2, ay2 ) );
            LineSegment segB = new LineSegment( new Point( bx1, by1 ), new Point( bx2, by2 ) );

            // are we really parallel?
            Assert.AreEqual( null, ( (Line) segA ).GetIntersectionWith( (Line) segB ) );

            Assert.AreEqual( null, segA.GetIntersectionWith( (Line) segB ) );
            Assert.AreEqual( null, ( (Line) segA ).GetIntersectionWith( segB ) );
            Assert.AreEqual( null, segB.GetIntersectionWith( (Line) segA ) );
            Assert.AreEqual( null, ( (Line) segB ).GetIntersectionWith( segA ) );
            Assert.AreEqual( null, segB.GetIntersectionWith( segA ) );
            Assert.AreEqual( null, segA.GetIntersectionWith( segB ) );
        }
예제 #7
0
        /// <summary>
        /// Finds, provided it exists, the intersection point with the specified <see cref="LineSegment"/>.
        /// </summary>
        /// 
        /// <param name="other"><see cref="LineSegment"/> to find intersection with.</param>
        /// 
        /// <returns>Returns intersection point with the specified <see cref="LineSegment"/>, or <see langword="null"/>, if
        /// the two segments do not intersect.</returns>
        /// 
        /// <remarks><para>If the two segments do not intersect, the method returns <see langword="null"/>. If the two
        /// segments share multiple points, this throws an <see cref="InvalidOperationException"/>.
        /// </para></remarks>
        /// 
        /// <exception cref="InvalidOperationException">Thrown if the segments overlap - if they have
        /// multiple points in common.</exception>
        /// 
        public Point? GetIntersectionWith(LineSegment other)
        {
            Point? result = null;

            if ((line.Slope == other.line.Slope) || (line.IsVertical && other.line.IsVertical))
            {
                if (line.Intercept == other.line.Intercept)
                {
                    // Collinear segments. Inspect and handle.
                    // Consider this segment AB and other as CD. (start/end in both cases)
                    // There are three cases:
                    // 0 shared points: C and D both project onto the same ray of AB
                    // 1 shared point: One of A or B equals one of C or D, and the other of C/D 
                    //      projects on the correct ray.
                    // Many shared points.

                    ProjectionLocation projC = LocateProjection(other.start), projD = LocateProjection(other.end);

                    if ((projC != ProjectionLocation.SegmentAB) && (projC == projD))
                    {
                        // no shared points
                        result = null;
                    }
                    else if (((start == other.start) && (projD == ProjectionLocation.RayA)) ||
                              ((start == other.end) && (projC == ProjectionLocation.RayA)))
                    {
                        // shared start point
                        result = start;
                    }
                    else if (((end == other.start) && (projD == ProjectionLocation.RayB)) ||
                              ((end == other.end) && (projC == ProjectionLocation.RayB)))
                    {
                        // shared end point
                        result = end;
                    }
                    else
                    {
                        // overlapping
                        throw new InvalidOperationException("Overlapping segments do not have a single intersection point.");
                    }
                }
            }
            else
            {
                result = GetIntersectionWith(other.line);

                if ((result.HasValue) && (other.LocateProjection(result.Value) != ProjectionLocation.SegmentAB))
                {
                    // the intersection is on the extended line of this segment
                    result = null;
                }
            }

            return result;
        }
예제 #8
0
 /// <summary>
 /// Finds, provided it exists, the intersection point with the specified <see cref="LineSegment"/>.
 /// </summary>
 /// 
 /// <param name="other"><see cref="LineSegment"/> to find intersection with.</param>
 /// 
 /// <returns>Returns intersection point with the specified <see cref="LineSegment"/>, or <see langword="null"/>,
 /// if this line does not intersect with the segment.</returns>
 /// 
 /// <remarks><para>If the line and segment do not intersect, the method returns <see langword="null"/>.
 /// If the line and segment share multiple points, the method throws an <see cref="InvalidOperationException"/>.
 /// </para></remarks>
 /// 
 /// <exception cref="InvalidOperationException">Thrown if <paramref name="other"/> is a portion
 /// of this line.</exception>
 /// 
 public Point? GetIntersectionWith(LineSegment other)
 {
     return other.GetIntersectionWith(this);
 }
예제 #9
0
        /// <summary>
        ///   Process the filter on the specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image data.</param>
        ///
        protected override unsafe void ProcessFilter(UnmanagedImage image)
        {
            // get border point which is still in the line

            IntPoint a = new IntPoint(0, 0);
            IntPoint b = new IntPoint(0, image.Height);
            IntPoint c = new IntPoint(image.Width, 0);
            IntPoint d = new IntPoint(image.Width, image.Height);

            LineSegment top = new LineSegment(a, c);
            LineSegment left = new LineSegment(a, b);
            LineSegment right = new LineSegment(c, d);
            LineSegment bottom = new LineSegment(b, d);

            Accord.Point?[] points = new Accord.Point?[4];
            points[0] = line.GetIntersectionWith(bottom);
            points[1] = line.GetIntersectionWith(left);
            points[2] = line.GetIntersectionWith(right);
            points[3] = line.GetIntersectionWith(top);

            IntPoint? p1 = null;
            IntPoint? p2 = null;
            foreach (var p in points)
            {
                if (p == null)
                    continue;

                if (p1 == null)
                {
                    p1 = p.Value.Round();
                    continue;
                }

                p2 = p.Value.Round();
                break;
            }

            IntPoint start = new IntPoint(image.Width - p1.Value.X, p1.Value.Y);
            IntPoint end = new IntPoint(image.Width - p2.Value.X, p2.Value.Y);

            Drawing.Line(image, start, end, markerColor);
        }