Getting (subentity) vertex points of swept solid

Getting (subentity) vertex points of swept solid

Anonymous
Not applicable
3,348 Views
13 Replies
Message 1 of 14

Getting (subentity) vertex points of swept solid

Anonymous
Not applicable

I am trying to find the vertex points of a swept polyline. So i have a solid that was created by sweeping a circle along a 3D polyline. It looks like that (and i would like to get the coordinates of those vertex points):
Untitled.png

 

Googling the whole of Friday last week i think i have to play around with the subentity part. I found out how to change the color of the subentity edges for instance, but couldn't for Christs sake not find out how to access the geometric

 

This is what i tried out so far, but as i noted right at the bottom i am kinda lost there. (or am i completely on the wrong path with subentity)

(long story short, I want to get the coordinates of the vertices of the 3D solid that was swept from a 3dpolyline by using a circle)

 

    [CommandMethod("SubEntExample")]
    public void SubEntExample()
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;

        PromptEntityOptions peo = new PromptEntityOptions("\nSelect a 3D solid: ");
        peo.SetRejectMessage("\nInvalid selection...");
        peo.AddAllowedClass(typeof(Solid3d), true);

        PromptEntityResult per = ed.GetEntity(peo);

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

        using (Transaction Tx = db.TransactionManager.StartTransaction())
        {
            Solid3d solid = Tx.GetObject(per.ObjectId, OpenMode.ForWrite) as Solid3d;

            ObjectId[] ids = new ObjectId[] { per.ObjectId };

            FullSubentityPath path = new FullSubentityPath(ids, new SubentityId(SubentityType.Null, IntPtr.Zero));

            List<SubentityId> subEntIds = new List<SubentityId>();

            using (Autodesk.AutoCAD.BoundaryRepresentation.Brep brep =
                new Autodesk.AutoCAD.BoundaryRepresentation.Brep(path))
            {                    
                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Edge edge in brep.Edges)
                {
                    subEntIds.Add(edge.SubentityPath.SubentId);
                }                    
            }

            foreach (SubentityId subentId in subEntIds)
            {

                *** here i am lost ***

            }
            Tx.Commit();
        }
    }

 

0 Likes
Accepted solutions (2)
3,349 Views
13 Replies
Replies (13)
Message 2 of 14

Alexander.Rivilis
Mentor
Mentor

Try to use GetGripPoints method to get vertexes. But if history of Solid3d is cleared I think there is no method to get vertexes of 3dpolyline.

 

P.S.: Correct forum for AutoCAD .NET API questions >>>here<<<  This forum is only for ObjectARX (C++) questions.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 3 of 14

Anonymous
Not applicable

oh, sorry for posting it in the wrong forum.

 

cheers for the answer, i will dig into that

0 Likes
Message 4 of 14

Alexander.Rivilis
Mentor
Mentor

If you find another solution, then share it with all.

You can also getting all Faces/Edges/Vertexes of this Solid3d (with help of BREP .NET API), but I am not sure that you can identify vertexes of 3dpolyline among all other vertexes of Solid3d.

Also you can read:

http://adndevblog.typepad.com/autocad/2015/09/finding-axis-end-points-of-a-cylindrical-3d-solid.html

http://adndevblog.typepad.com/autocad/2012/08/retrieving-native-curve-geometry-using-brep-api.html

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 5 of 14

Anonymous
Not applicable

as you already warned me the getgrippoints wont differ between the grippoints, so i would get all of them and not just the ones of the polyline

 

i've fallen over the GetObjectSnapPoints method now but for some reason with the samplecode i wrote it wont fill the point collection (snappoints) at all

does anyone have a clue what i am doing wrong there:

 

        [CommandMethod("testcentersnap")]
        public void testcentersnap()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            
            
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                PromptEntityResult selectionRes = ed.GetEntity("Select Entity ");

                if (selectionRes.Status == PromptStatus.OK)
                {
                    try
                    {
                        ObjectId objId = selectionRes.ObjectId;
                        Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForRead);

                        Point3d tempPoint = new Point3d();
                        Matrix3d mat = Matrix3d.Identity;
                        Point3dCollection snapPts = new Point3dCollection();
                        IntegerCollection geomIds = new IntegerCollection(1);

                        ent.GetObjectSnapPoints(ObjectSnapModes.ModeCenter, 1, tempPoint, tempPoint, mat, snapPts, geomIds);                        

                        foreach (Point3d singlePoint3D in snapPts)
                        {
                            ed.WriteMessage("X: " + singlePoint3D.X.ToString() + "\n" +
                                            "Y: " + singlePoint3D.Y.ToString() + "\n" +
                                            "Z: " + singlePoint3D.Z.ToString() + "\n");
                        }                        
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception ex)
                    {
                        ed.WriteMessage(ex.Message);
                        tr.Abort();
                    }
                }
            }
        }
0 Likes
Message 6 of 14

Alexander.Rivilis
Mentor
Mentor
GetObjectSnapPoints can not help you.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 7 of 14

Anonymous
Not applicable
Accepted solution

it indeed did not help hehe 🙂

 

in my case all the swept solids were created by sweeping a circle around the path

So for my situation the following solution does the job. 

 

I can ignore the 5 first grip points as they will always be the grip points of the sweep element (a circle)

i then stay left with the grip points of the sweep path

i further then check if the grips are the middle grips or not, in case they are i remove them from my list where i store all the grips

 

here is the code i ended up for now (that is by far not an optimized solution, but it does its job for now, if anyone has better solutions/ideas just keep them comin:) 😞

        /// <summary>
        /// gets the middle of two points
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static Point3d GetMiddlePoint(Point3d p1, Point3d p2)
        {
            LineSegment3d temporaryLine = new LineSegment3d(p1, p2);
            return temporaryLine.MidPoint;
        }

        /// <summary>
        /// checks if the point is a middle point of the previous and following point
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="testingPoint"></param>
        /// <returns></returns>
        public static bool IsMidPointOfVertices(Point3d p1, Point3d p2, Point3d testingPoint)
        {
            if (GetMiddlePoint(p1, p2) == testingPoint)
                return true;

            return false;
        }

        /// <summary>
        /// Label all the vertex points in a swept 3d solid
        /// only works if the sweep element is a circle
        /// </summary>
        [CommandMethod("GripPoint")]
        static public void GripPoint()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                try
                {
                    // Prompt for selection of a solid to be traversed
                    PromptEntityOptions prEntOpt = new PromptEntityOptions("\nSelect a 3D solid:");
                    prEntOpt.SetRejectMessage("\nMust be a 3D solid.");
                    prEntOpt.AddAllowedClass(typeof(Solid3d), true);
                    PromptEntityResult prEntRes = ed.GetEntity(prEntOpt);

                    ObjectId[] objIds = { prEntRes.ObjectId };
                    Solid3d en = (Solid3d)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);

                    // declaring needed variables for GetGripPoints() method
                    GripDataCollection gripsTotalAmount = new GripDataCollection();
                    double curViewUnitSize = 0;
                    int gripSize = 0;
                    Vector3d curViewDir = doc.Editor.GetCurrentView().ViewDirection;
                    GetGripPointsFlags bitFlags = GetGripPointsFlags.GripPointsOnly;
                    en.GetGripPoints(gripsTotalAmount, curViewUnitSize, gripSize, curViewDir, bitFlags);

                    // if we have more than 8 vertices than we have a proper polyline (5 alone for the sweepcircle)
                    // so only if we have more than 8 we swap it into our list (from 5 till end of grips)
                    if (gripsTotalAmount.Count > 7)
                    {
                        List<GripData> polyLineGrips = new List<GripData>();

                        for (int counter = 5; counter < gripsTotalAmount.Count; counter++)
                            polyLineGrips.Add(gripsTotalAmount[counter]);


                        // loop through all polyline grips and see if we have middlepoint grips
                        // if we do, we remove them from the list
                        // starting from maxcount and going down so RemoveAt wont change the order
                        int whileCounter = polyLineGrips.Count - 2;
                        while (whileCounter > 0)
                        {
                            // check if current point is middlepoint and remove it fromt he list
                            // if that is the case
                            if (IsMidPointOfVertices(polyLineGrips[whileCounter - 1].GripPoint,
                                                      polyLineGrips[whileCounter + 1].GripPoint,
                                                      polyLineGrips[whileCounter].GripPoint))
                            {
                                polyLineGrips.RemoveAt(whileCounter);
                            }
                            whileCounter--;
                        }
                        

                        // temporary for loop to showcase labelling (testing purpose only)
                        for (int counter = 0; counter < polyLineGrips.Count; counter++)
                        {
                            // Open the Block table record Model space for write
                            BlockTable acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                            BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                            // Create a single-line text object
                            DBText acText = new DBText();
                            acText.SetDatabaseDefaults();
                            acText.Position = polyLineGrips[counter].GripPoint;
                            acText.Height = 0.05;
                            acText.TextString = Convert.ToString(counter + 1);

                            // Add the new object to the block table record and the transaction
                            acBlkTblRec.AppendEntity(acText);
                            tr.AddNewlyCreatedDBObject(acText, true);
                        }
                    }

                    tr.Commit();
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("\nException during traversal: {0}", ex.Message);
                }
            }
        }

 

0 Likes
Message 8 of 14

Alexander.Rivilis
Mentor
Mentor

If history was cleared (command BREP) then you code do not return appropriate vertexes:

 

2016-11-02_17-21-29.png

 

 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 9 of 14

Anonymous
Not applicable

yeah thats what i found out aswell, luckily its for a very specific task and i know for sure that the history wont be cleared for where we use it.

 

I am sadly aware that it is not a perfect (actually far away from that) or beautiful suoltion.

BUT it is a solution that does its job for now 🙂

0 Likes
Message 10 of 14

Alexander.Rivilis
Mentor
Mentor
Accepted solution

Try this code. Maybe this is a better solution:

 

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.BoundaryRepresentation;

// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(GetSweepAxis.MyCommands))]

namespace GetSweepAxis
{

  public class MyCommands
  {

    [CommandMethod("FindCylinderAxis")]
    public void FindCylinderAxis()
    {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
      PromptEntityOptions peo = new PromptEntityOptions("Pick a 3DSOLID: ");
      peo.SetRejectMessage("\nA 3d solid must be selected.");
      peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Solid3d), true);
      PromptEntityResult per = ed.GetEntity(peo);
      if (per.Status != PromptStatus.OK)
        return;

      using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
      {
        Solid3d sld = tr.GetObject(per.ObjectId, OpenMode.ForRead, false) as Solid3d;
        Point3d axisPt1 = Point3d.Origin;
        Point3d axisPt2 = Point3d.Origin;
        Point3dCollection pts = new Point3dCollection();
        if (GetCylinderAxis(sld, ref  pts))
        {
          for (int i = 0; i < pts.Count; i++)
          {
            ed.WriteMessage("\nPt[{0}] = {1}", i, pts[i]);
          }
        }
        else
        {
          ed.WriteMessage("\nNot a sweeped solid");
        }
        tr.Commit();
      }
    }

    private bool GetCylinderAxis(Solid3d solid, ref Point3dCollection pts)
    {
      using (Brep brep = new Brep(solid))
      {
        BrepEdgeCollection edges = brep.Edges;
        foreach (Edge edge in edges)
        {
          Curve3d curv = ((ExternalCurve3d)edge.Curve).NativeCurve;
          if (curv is CircularArc3d)
          {
            CircularArc3d circle = curv as CircularArc3d;
            if (!pts.Contains(circle.Center)) pts.Add(circle.Center);
          }
          else if (curv is EllipticalArc3d)
          {
            EllipticalArc3d circle = curv as EllipticalArc3d;
            if (!pts.Contains(circle.Center)) pts.Add(circle.Center);
          }
        }
      }
      return (pts.Count > 1) ? true : false;
    }
  }
}

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 11 of 14

Anonymous
Not applicable

that is obviously a way better solution, thanks a lot

 

so frustrating how i keep searching and searching and in the end the solution i come up with is so much worse than what you just typed in a few seconds 🙂

thanks for the help, much appreciated!

Message 12 of 14

Alexander.Rivilis
Mentor
Mentor

This solution I also did not immediately found. It is base on this topic: http://adndevblog.typepad.com/autocad/2015/09/finding-axis-end-points-of-a-cylindrical-3d-solid.html

But in your case not CircularArc3d but also EllipticalArc3d curve may appeared.

 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 13 of 14

Abhay.KaranjikarQRNDZ
Contributor
Contributor

Thanks for sharing the code. However not sure how to use in civil3D 2022. Need further guidance

0 Likes