Select lines and faces

Select lines and faces

Anonymous
Not applicable
3,210 Views
8 Replies
Message 1 of 9

Select lines and faces

Anonymous
Not applicable

Hi

 

I want to create the following two functions, but I can't find a good way to do it. I have read old blog posts about selecting nearest face using BREP and selecting solid sub-entities without getting the functionality I want. The functions i would like to create are as follows:

 

1. Select lines. The user should be able to select a selection set of any type of line or edge. It could be a 3d polyline, 3d polyline inside a block, solid edge, solid edge inside a block, surface edge etc. I want to use this to calculate the total length of of all the selected lines/edges.

 

2. Select faces. The user should be able to select a selection set of any face. It could be a region, surface, face of solid, face of solid inside a block etc. This will be an improved version of the selection when holding ctrl down and selecting faces. I want to use this to calculate the sum of all the face areas. 

 

How can I create these functions?

0 Likes
3,211 Views
8 Replies
Replies (8)
Message 2 of 9

_gile
Consultant
Consultant

Hi,

 

Here's a little example for "lines". As is, it works with polylines, 3d polylines, surfaces, 3d solids and same entities contained in uniformly scales block references. You should be able to adapt it to suit your needs.

 

        [CommandMethod("TEST")]
        public void Test()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var filter = new SelectionFilter(new[]
            {
                new TypedValue(-4, "<or"),
                new TypedValue(0, "INSERT,LWPOLYLINE,3DSOLID,*SURFACE"),
                new TypedValue(-4, "<and"),
                new TypedValue(0, "POLYLINE"),
                new TypedValue(-4, "&"),
                new TypedValue(70, 8),
                new TypedValue(-4, "and>"),
                new TypedValue(-4, "or>")
            });
            var psr = ed.GetSelection(filter);
            if (psr.Status == PromptStatus.OK)
            {
                using (var tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    double length = psr.Value
                        .Cast<SelectedObject>()
                        .Select(so => (Entity)tr.GetObject(so.ObjectId, OpenMode.ForRead))
                        .Sum(ent => GetEdgeLength(ent));
                    ed.WriteMessage($"\nTotal edges length: {length}");
                    tr.Commit();
                }
            }
        }
        
        private double GetEdgeLength(Entity entity)
        {
            if (entity is Polyline3d || entity is Polyline)
            {
                var curve = (Curve)entity;
                return curve.GetDistanceAtParameter(curve.EndParam);
            }
            if (entity is Solid3d || entity is AcDb.Surface)
            {
                using (var brep = new Brep(entity))
                {
                    return brep.Edges.Sum(edge => edge.GetPerimeterLength());
                }
            }
            if (entity is BlockReference)
            {
                var br = (BlockReference)entity;
                if (br.ScaleFactors.IsProportional())
                {
                    var length = 0.0;
                    using (var entities = new DBObjectCollection())
                    {
                        br.Explode(entities);
                        foreach (Entity ent in entities)
                        {
                            length += GetEdgeLength(ent);
                            ent.Dispose();
                        }
                    }
                    return length;
                }
            }
            return 0.0;
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 9

ActivistInvestor
Mentor
Mentor

@Anonymous wrote:

Hi

 

I want to create the following two functions, but I can't find a good way to do it. I have read old blog posts about selecting nearest face using BREP and selecting solid sub-entities without getting the functionality I want. The functions i would like to create are as follows:

 

1. Select lines. The user should be able to select a selection set of any type of line or edge. It could be a 3d polyline, 3d polyline inside a block, solid edge, solid edge inside a block, surface edge etc. I want to use this to calculate the total length of of all the selected lines/edges.

 

2. Select faces. The user should be able to select a selection set of any face. It could be a region, surface, face of solid, face of solid inside a block etc. This will be an improved version of the selection when holding ctrl down and selecting faces. I want to use this to calculate the sum of all the face areas. 

 

How can I create these functions?


Can you clarify if you want to select only some, but not all edges of a solid or surface?  I'm not sure there's an easy way to select only certain edges of a solid/surface, while also allowing selection of simple entities like lines, polylines (including those nested in block references).

 

 

0 Likes
Message 4 of 9

Anonymous
Not applicable

I would like the line-picker to select only some edges in a solid, or two edges from two different solids. I want it to be totally generic in picking a selection set of any lines/edges. And similar for the face-picker.

 

If you do a selection holding the ctrl key down you are able to select edges or faces on a solid. If you then iterate the current selection set you will see the selected edges or faces. (See attached images.)

 

var psr = ed.GetSelection();
            if (psr.Status == PromptStatus.OK)
            {
                using (var tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    for (int i = 0; i < psr.Value.Count; i++)
                    {
                        Entity ent = (Entity)tr.GetObject(psr.Value[i].ObjectId, OpenMode.ForRead);
                        ed.WriteMessage("\nSelected type: " + ent.GetType().ToString());

                        var subs = psr.Value[i].GetSubentities();
                        if (subs != null)
                        {
                            for (int j = 0; j < subs.Length; j++)
                            {
                                var subtype = subs[i].FullSubentityPath.SubentId.Type;
                                ed.WriteMessage("\n  Subtype: " + subtype.ToString());
                            }
                        }
                    }
                    tr.Abort();
                }
            }

 

But it should be possible setting up the filter as well. Would it be posssible to use something like the code shown below. (I have not got it to work.)

 

new TypedValue((int)DxfCode.Subclass, "AcBrFace")
0 Likes
Message 5 of 9

ActivistInvestor
Mentor
Mentor

@Anonymous wrote:

I would like the line-picker to select only some edges in a solid, or two edges from two different solids. I want it to be totally generic in picking a selection set of any lines/edges. And similar for the face-picker.

 

If you do a selection holding the ctrl key down you are able to select edges or faces on a solid. If you then iterate the current selection set you will see the selected edges or faces. (See attached images.)

 

var psr = ed.GetSelection();
            if (psr.Status == PromptStatus.OK)
            {
                using (var tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    for (int i = 0; i < psr.Value.Count; i++)
                    {
                        Entity ent = (Entity)tr.GetObject(psr.Value[i].ObjectId, OpenMode.ForRead);
                        ed.WriteMessage("\nSelected type: " + ent.GetType().ToString());

                        var subs = psr.Value[i].GetSubentities();
                        if (subs != null)
                        {
                            for (int j = 0; j < subs.Length; j++)
                            {
                                var subtype = subs[i].FullSubentityPath.SubentId.Type;
                                ed.WriteMessage("\n  Subtype: " + subtype.ToString());
                            }
                        }
                    }
                    tr.Abort();
                }
            }

 

But it should be possible setting up the filter as well. Would it be posssible to use something like the code shown below. (I have not got it to work.)

 

new TypedValue((int)DxfCode.Subclass, "AcBrFace")

The selection filter only recognizes entity types (objects with managed wrappers that derived from AcDbEntity), but not API types like AcBrFace. 

 

You can select selected edges on a single entity or several, but I'm not sure you can also include other types of 'lines' like Line, Polyline, and so forth.

0 Likes
Message 6 of 9

SEANT61
Advisor
Advisor

I've experimented with a process that offers a little, at least, of what you're hoping to do.  I haven't had a chance to go back and look at this code yet (perhaps later today), but see the attachment in this thread (See Mark's posting towards end of thread):

 

http://www.theswamp.org/index.php?topic=25614.0

 

This screencast shows it in action:

 

 


************************************************************
May your cursor always snap to the location intended.
Message 7 of 9

SEANT61
Advisor
Advisor

I should point out that you may need to register at theswamp.org to view that thread.  Fortunately, membership at theswamp is well worth the effort.


************************************************************
May your cursor always snap to the location intended.
Message 8 of 9

SEANT61
Advisor
Advisor

An updated solution, for more modern versions of AutoCAD, has been attached to post #16 of that thread at theswamp.org.


************************************************************
May your cursor always snap to the location intended.
Message 9 of 9

Anonymous
Not applicable

Hi, Sean

 

Thanks alot for the example. You've done a good job with this functionality. As you say it doesn't do everything I was looking for, but it is the closest so far. Lots of kudos going your way.

 

- Fredrik

0 Likes