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 DoublePoint( 0, 0 ), new DoublePoint( 3, 4 ) ); // get segment's length double length = segment.Length; // get intersection point with a line DoublePoint? intersection = segment.GetIntersectionWith( new Line( new DoublePoint( -3, 8 ), new DoublePoint( 0, 4 ) ) );
Beispiel #1
0
			public AForge.Point NormalEnd { get; set; }		// (needed in drawing, avoid calculating twice)

			public Component(AForge.Point centr, double alignmnt, List<IntPoint> outln, 
							 LineSegment lngst, AForge.Point Nstart, AForge.Point Nend)
			{
				Center = centr;
				Alignment = alignmnt;
				Outline = outln;
				Longest = lngst;
				NormalStart = Nstart;
				NormalEnd = Nend;
			}
Beispiel #2
0
        // ==========================================================================================================
        // Components:
        // ==========================================================================================================
        private List<Shapes.Component> FindComponentsFunct(Bitmap bitmap)
        {
            // Locating objects
            BlobCounter blobCounter = new BlobCounter();
            blobCounter.FilterBlobs = true;
            blobCounter.MinHeight = 8;
            blobCounter.MinWidth = 8;
            blobCounter.ProcessImage(bitmap);
            Blob[] blobs = blobCounter.GetObjectsInformation();

            // create convex hull searching algorithm
            GrahamConvexHull hullFinder = new GrahamConvexHull();
            ClosePointsMergingOptimizer optimizer1 = new ClosePointsMergingOptimizer();
            FlatAnglesOptimizer optimizer2 = new FlatAnglesOptimizer();

            List<Shapes.Component> Components = new List<Shapes.Component>();

            // process each blob
            foreach (Blob blob in blobs)
            {
                List<IntPoint> leftPoints, rightPoints, edgePoints = new List<IntPoint>();
                if ((blob.Rectangle.Height > 400) && (blob.Rectangle.Width > 600))
                {
                    break;	// The whole image could be a blob, discard that
                }
                // get blob's edge points
                blobCounter.GetBlobsLeftAndRightEdges(blob,
                    out leftPoints, out rightPoints);

                edgePoints.AddRange(leftPoints);
                edgePoints.AddRange(rightPoints);

                // blob's convex hull
                List<IntPoint> Outline = hullFinder.FindHull(edgePoints);
                optimizer1.MaxDistanceToMerge = 4;
                optimizer2.MaxAngleToKeep = 170F;
                Outline = optimizer2.OptimizeShape(Outline);
                Outline = optimizer1.OptimizeShape(Outline);

                // find Longest line segment
                float dist = 0;
                LineSegment Longest = new LineSegment(Outline[0], Outline[1]);
                LineSegment line;
                dist = Longest.Length;
                int LongestInd = 0;
                for (int i = 1; i < Outline.Count; i++)
                {
                    if (i != Outline.Count - 1)
                    {
                        line = new LineSegment(Outline[i], Outline[i + 1]);
                    }
                    else
                    {
                        // last iteration
                        if (Outline[i] == Outline[0])
                        {
                            break;
                        }
                        line = new LineSegment(Outline[i], Outline[0]);
                    }
                    if (line.Length > dist)
                    {
                        Longest = line;
                        dist = line.Length;
                        LongestInd = i;
                    }
                }
                // Get the center point of it
                AForge.Point LongestCenter = new AForge.Point();
                LongestCenter.X = (float)Math.Round((Longest.End.X - Longest.Start.X) / 2.0 + Longest.Start.X);
                LongestCenter.Y = (float)Math.Round((Longest.End.Y - Longest.Start.Y) / 2.0 + Longest.Start.Y);
                AForge.Point NormalStart = new AForge.Point();
                AForge.Point NormalEnd = new AForge.Point();
                // Find normal:
                // start= longest.start rotated +90deg relative to center
                // end= longest.end rotated -90deg and relative to center
                // If you rotate point (px, py) around point (ox, oy) by angle theta you'll get:
                // p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
                // p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
                // cos90 = 0, sin90= 1 =>
                // p'x= -(py-oy) + ox= oy-py+ox, p'y= (px-ox)+ oy
                NormalStart.X = LongestCenter.Y - Longest.Start.Y + LongestCenter.X;
                NormalStart.Y = (Longest.Start.X - LongestCenter.X) + LongestCenter.Y;
                // cos-90=0, sin-90= -1 =>
                // p'x= (py-oy) + ox
                // p'y= -(px-ox)+oy= ox-px+oy
                NormalEnd.X = (Longest.Start.Y - LongestCenter.Y) + LongestCenter.X;
                NormalEnd.Y = LongestCenter.X - Longest.Start.X + LongestCenter.Y;
                // Make line out of the points
                Line Normal = Line.FromPoints(NormalStart, NormalEnd);

                // Find the furthest intersection to the normal (skip the Longest)
                AForge.Point InterSection = new AForge.Point();
                AForge.Point Furthest = new AForge.Point();
                bool FurhtestAssinged = false;
                LineSegment seg;
                dist = 0;
                for (int i = 0; i < Outline.Count; i++)
                {
                    if (i == LongestInd)
                    {
                        continue;
                    }
                    if (i != Outline.Count - 1)
                    {
                        seg = new LineSegment(Outline[i], Outline[i + 1]);
                    }
                    else
                    {
                        // last iteration
                        if (Outline[i] == Outline[0])
                        {
                            break;
                        }
                        seg = new LineSegment(Outline[i], Outline[0]);
                    }
                    if (seg.GetIntersectionWith(Normal) == null)
                    {
                        continue;
                    }
                    InterSection = (AForge.Point)seg.GetIntersectionWith(Normal);
                    if (InterSection.DistanceTo(LongestCenter) > dist)
                    {
                        Furthest = InterSection;
                        FurhtestAssinged = true;
                        dist = InterSection.DistanceTo(LongestCenter);
                    }
                }
                // Check, if there is a edge point that is close to the normal even further
                AForge.Point fPoint = new AForge.Point();
                for (int i = 0; i < Outline.Count; i++)
                {
                    fPoint.X = Outline[i].X;
                    fPoint.Y = Outline[i].Y;
                    if (Normal.DistanceToPoint(fPoint) < 1.5)
                    {
                        if (fPoint.DistanceTo(LongestCenter) > dist)
                        {
                            Furthest = fPoint;
                            FurhtestAssinged = true;
                            dist = fPoint.DistanceTo(LongestCenter);
                        }
                    }
                }
                AForge.Point ComponentCenter = new AForge.Point();
                if (FurhtestAssinged)
                {
                    // Find the midpoint of LongestCenter and Furthest: This is the centerpoint of component
                    ComponentCenter.X = (float)Math.Round((LongestCenter.X - Furthest.X) / 2.0 + Furthest.X);
                    ComponentCenter.Y = (float)Math.Round((LongestCenter.Y - Furthest.Y) / 2.0 + Furthest.Y);
                    // Alignment is the angle of longest
                    double Alignment;
                    if (Math.Abs(Longest.End.X - Longest.Start.X) < 0.001)
                    {
                        Alignment = 0;
                    }
                    else
                    {
                        Alignment = Math.Atan((Longest.End.Y - Longest.Start.Y) / (Longest.End.X - Longest.Start.X));
                        Alignment = Alignment * 180.0 / Math.PI; // in deg.
                    }
                    Components.Add(new Shapes.Component(ComponentCenter, Alignment, Outline, Longest, NormalStart, NormalEnd));
                }
            }
            return Components;
        }
Beispiel #3
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 );
 }
Beispiel #4
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);

            AForge.Point?[] points = new AForge.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);
        }
Beispiel #5
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 DoublePoint? GetIntersectionWith( LineSegment other )
        {
            DoublePoint? 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;
        }
Beispiel #6
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));
 }
Beispiel #7
0
 public Component(Point centr, double alignmnt, List<IntPoint> outln,
                  LineSegment lngst, Point Nstart, Point Nend)
     : base(centr.X, centr.Y)
 {
     Alignment = alignmnt;
     Outline = outln;
     Longest = lngst;
     NormalStart = Nstart;
     NormalEnd = Nend;
 }