Ordering blocks based on distance along a polyline

Ordering blocks based on distance along a polyline

Anonymous
Not applicable
920 Views
4 Replies
Message 1 of 5

Ordering blocks based on distance along a polyline

Anonymous
Not applicable

Hello,

 

First, let me provide some context to my problem. I have a number of blocks which are placed along a polyline. What I want to achieve is a command whereby the user selects a number of blocks, and then they are ordered based on their distance from the start of the polyline.

 

Code:

TypedValue[] filterlist = new TypedValue[1];
            filterlist[0] = new TypedValue(0, "INSERT");

            SelectionFilter filter = new SelectionFilter(filterlist);
            PromptSelectionResult psr1 = ed.GetSelection(filter);

            if (psr1.Status != PromptStatus.OK)
                return;

            SelectionSet psrSet = psr1.Value;
           
            ObjectIdCollection obs = new ObjectIdCollection();
            foreach (ObjectId id1 in psrSet.GetObjectIds())
            {
                obs.Add(id1);
            }

This first section allows the user to select some blocks, puts them into a selection set and then creates an ObjectIDCollection to store them.

 

It is at this point that I am not sure how to order them based on distance from start point. I can create a string that tells me the distance to the start point of each block but can't get that final step to actually order them based on this criteria.

 

Any help is appreciated.

 

Cheers

 

Matt

0 Likes
Accepted solutions (1)
921 Views
4 Replies
Replies (4)
Message 2 of 5

_gile
Consultant
Consultant

Hi,

 

You can use the OrderBy() Linq extension method.

It requires a key selector function as argument.

The key selector function could return:

pline.GetDistAtPoint(pline.GetClosestPointTo(blockRef.Position, false));


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 5

Anonymous
Not applicable

Thanks! I'm just struggling to set up the linq function.

 

The code below calls all the blocks into an array (I think):

 

var obj = new BlockReference[obs.Count];
                for (int i = 0; i < obs.Count; i++)
                {
                    obj[i] = tr.GetObject(obs[i], OpenMode.ForRead) as BlockReference;
                }

and then the sorting bit I still can't get to work:

 

var sorted = obj.OrderBy(c.GetDistAtPoint(c.GetClosestPointTo(obj[i].Position, false)));
0 Likes
Message 4 of 5

_gile
Consultant
Consultant
Accepted solution

OrderBy applies to a sequence (IEnumerable) of some Type instances, not to a single instance.

 

Here's a little snippet:

 

IEnumerable<BlockReference> sortedBlocks = psr.Value
    .GetObjectIds() 
    .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead)) // map the ObjectId array into a BlockReference sequence
    .OrderBy(br => pline.GetDistAtPoint(pline.GetClosestPointTo(br.Position, false))); // order the blockReference sequence

sortedBlocks type is : IEnumerable<BlockReference>.

You can iterate it with foreach, convert it to a BlockReference[] with ToArray() method or to a List<BlockRefernce> with Tolist().

 

If you need an ObjectIdColletcion, you can map back the sequence to an ObjectId array:

 

ObjectIdCollection ids = new ObjectIdCollection(sortedBlocks.Select(br => br.ObjectId).ToArray()); 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5

Anonymous
Not applicable

Thanks very much for the code and explanation. Slowly getting the hang of c# and CAD.

 

0 Likes