find nearest lines(or pline) from selected point

find nearest lines(or pline) from selected point

iPranavKulkarni
Advocate Advocate
1,260 Views
6 Replies
Message 1 of 7

find nearest lines(or pline) from selected point

iPranavKulkarni
Advocate
Advocate

Hi, I tried to trace boundary from selected point (close boundary with polyline) but I need to find/get nearest lines.
can some one help me with this.

I tried:

Entity pl = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;
//entity is polyline
Extents3d extents = pl.GeometricExtents;
Point3d center = extents.MinPoint + (extents.MaxPoint - extents.MinPoint) / 2.0;

Capture.PNG

Need to find lines from point in all direction

0 Likes
Accepted solutions (1)
1,261 Views
6 Replies
Replies (6)
Message 2 of 7

_gile
Consultant
Consultant

Hi,

Here's a way to get the closest curve to a point.

        public static Curve GetClosestCurve(IEnumerable<Curve> curves, Point3d pt)
        {
            var closest = curves.First();
            var minDist = pt.DistanceTo(closest.GetClosestPointTo(pt, false));
            foreach (var curve in curves.Skip(1))
            {
                double dist = pt.DistanceTo(curve.GetClosestPointTo(pt, false));
                if (dist < minDist)
                {
                    minDist = dist;
                    closest = curve;
                }
            }
            return closest;
        }

 

The same thing with F#:

let getClosestCurve (pt: Point3d) =
    Seq.minBy (fun (c: Curve) -> pt.DistanceTo(c.GetClosestPointTo(pt, false)))


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 7

_gile
Consultant
Consultant

.NET 7 has a MinBy (and MaxBy) extension method but as we're limited to .NET Framework with AutoCAD, we need to build it (the following extension methods are taken from Gile.AutoCAD.Extension library).

 

    public static class LinqExtension
    {
        /// <summary>
        /// Gets the smallest item of the sequence using the default comparer with the 'selector' function returned values.
        /// </summary>
        /// <typeparam name="TSource">Type the items.</typeparam>
        /// <typeparam name="TKey">Type of the returned value of 'selector' function.</typeparam>
        /// <param name="source">Sequence to which the method applies.</param>
        /// <param name="selector">Mapping function from 'TSource' to 'TKey'.</param>
        /// <returns>The smallest item in the sequence.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if 'source' is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown if 'selector' is null.</exception>
        public static TSource MinBy<TSource, TKey>(
            this IEnumerable<TSource> source,
            Func<TSource, TKey> selector)
        {
            return source.MinBy(selector, Comparer<TKey>.Default);
        }

        /// <summary>
        /// Gets the smallest item of the sequence using the 'comparer' with the 'selector' function returned values.
        /// </summary>
        /// <typeparam name="TSource">Type the items.</typeparam>
        /// <typeparam name="TKey">Type of the returned value of 'selector' function.</typeparam>
        /// <param name="source">Sequence to which the method applies.</param>
        /// <param name="selector">Mapping function from 'TSource' to 'TKey'.</param>
        /// <param name="comparer">Comparer used for the type 'TKey'.</param>
        /// <returns>The smallest item in the sequence.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown if 'source' is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown if 'selector' is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown if 'comparer' is null.</exception>
        public static TSource MinBy<TSource, TKey>(
            this IEnumerable<TSource> source,
            Func<TSource, TKey> selector,
            IComparer<TKey> comparer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));
            using (var iterator = source.GetEnumerator())
            {
                if (!iterator.MoveNext())
                    throw new InvalidOperationException("Empty sequence");

                var min = iterator.Current;
                var minKey = selector(min);
                while (iterator.MoveNext())
                {
                    var current = iterator.Current;
                    var currentKey = selector(current);
                    if (comparer.Compare(currentKey, minKey) < 0)
                    {
                        min = current;
                        minKey = currentKey;
                    }
                }
                return min;
            }
        }
    }

 

 

Now the GetClosestCurve can be simply written:

 

public static Curve GetClosestCurve(IEnumerable<Curve> curves, Point3d pt) =>
            curves.MinBy(c => pt.DistanceTo(c.GetClosestPointTo(pt, false)));

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 4 of 7

iPranavKulkarni
Advocate
Advocate

Thanks!
Is this possible with the direction(axis)?

I need to get closest line in X-dir, Y-dir.(left right up and down)

 

0 Likes
Message 5 of 7

_gile
Consultant
Consultant
Accepted solution

This should work (returns null if none curve found on the axis):

        public static Curve GetClosestCurve(IEnumerable<Curve> curves, Point3d point, Vector3d axis)
        {
            using (var xline = new Xline { BasePoint = point, UnitDir = axis })
            {
                var curvesOnAxis = new Dictionary<Curve, Point3d>();
                Curve closestCurve = null;
                double minDist = double.MaxValue;
                foreach (var curve in curves)
                {
                    var points = new Point3dCollection();
                    curve.IntersectWith(xline, Intersect.OnBothOperands, points, IntPtr.Zero, IntPtr.Zero);
                    if (0 < points.Count)
                    {
                        double dist = points.Cast<Point3d>().Select(p => p.DistanceTo(point)).Min();
                        if (dist < minDist)
                        {
                            closestCurve = curve;
                            minDist = dist;
                        }
                    }
                }
                return closestCurve;
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 6 of 7

iPranavKulkarni
Advocate
Advocate

thanks for your support. It worked for me with small changes.

 

0 Likes
Message 7 of 7

iPranavKulkarni
Advocate
Advocate

thanks with your support I can get all the lines and closest line from that.
now I am finding some of lines in all direction.

need to get boundary (trace boundary)

iPranavKulkarni_0-1687415132425.png

 

0 Likes