Get the Vector3d value from Polyine3d

Get the Vector3d value from Polyine3d

waseefur.rahman
Advocate Advocate
1,564 Views
4 Replies
Message 1 of 5

Get the Vector3d value from Polyine3d

waseefur.rahman
Advocate
Advocate

Hi,

I am having a entity as Polyline, from that I was able to get the normal value

Dim Obj As Entity


Dim Objpts As Vector3d = Obj.Normal

 


Incase if the entity is Polyline3d

how to get the normal value for that?

i am getting the error as Normal is not a member of Polyline3d,
Could any suggest how to get Vector3d value for Polyline3d.

Thanks

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

_gile
Consultant
Consultant

Hi,

 

The Normal property of some entities refers to the normal of the entity plane (i.e. the unit vector perpendicular to the plane).

2D entities as Polyline, Circle, Arc, Text, and so on lie on a (single) plane so the Normal property of these entities refers the the normal vector of their plane.

Typically a Polyline3d is not planar (a planar Polyline3d should be replaced by aPolyline2d or a Polyline), so there's no plane to define a normal vector.

 

You should be more explicit about what you're trying to do so that it may be possible to find a work around.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 5

waseefur.rahman
Advocate
Advocate

Hi Gile,

Many Thanks for your brief description.

One more thing please, Is there any way to Convert Polyline3d to Polyline.

0 Likes
Message 4 of 5

_gile
Consultant
Consultant

waseefur.rahman a écrit :


One more thing please, Is there any way to Convert Polyline3d to Polyline.


Yes, this may be quite easy using the Curve.GetOthoProjectedCurve() or Curve.GetProjectedCurve() method but it requires to already know the Polyline plane (its normal and elevation).

 

What have you so far? Why do you need the Normal vector for? How are drawn your 3d polylines?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 5

_gile
Consultant
Consultant
Accepted solution

The following Polyline3d.ToPolyline() extension method returns a new instance of Polyline if the Polyline3d is planar.

 

    public static class ExtensionMethods
    {
        /// <summary>
        /// Gets the vertices of a polyline 3d.
        /// </summary>
        /// <param name="pline3d">The instance this method applies to.</param>
        /// <returns>The collection of vertices positions (SimpleVertex or FitVertex).</returns>
        public static Point3dCollection GetVertices(this Polyline3d pline3d)
        {
            if (pline3d == null)
                throw new ArgumentNullException(nameof(pline3d));

            var points = new Point3dCollection();
            using (var tr = pline3d.Database.TransactionManager.StartOpenCloseTransaction())
            {
                foreach (ObjectId id in pline3d)
                {
                    var vx = (PolylineVertex3d)tr.GetObject(id, OpenMode.ForRead);
                    if (vx.VertexType != Vertex3dType.ControlVertex)
                        points.Add(vx.Position);
                }
                tr.Commit();
            }
            return points;
        }

        /// <summary>
        /// Evaluates if the points lies on a single plane.
        /// </summary>
        /// <param name="points">The instance this method applies to.</param>
        /// <param name="normal">Normal of the plane.</param>
        /// <returns></returns>
        public static bool IsPlanar(this Point3dCollection points, out Vector3d normal)
        {
            if (points == null)
                throw new ArgumentNullException(nameof(points));

            normal = new Vector3d();
            if (points.Count < 3)
                return false;
            var v = points[0].GetVectorTo(points[1]);
            var u = new Vector3d();
            bool found = false;
            for (int i = 2; i < points.Count; i++)
            {
                u = points[0].GetVectorTo(points[i]);
                if (!u.IsParallelTo(v))
                {
                    found = true;
                    break;
                }
            }
            if (!found)
                return false;
            normal = v.CrossProduct(u).GetNormal();
            var plane = new Plane(points[0], normal);
            double d = Tolerance.Global.EqualPoint;
            return points.Cast<Point3d>().All(p => Math.Abs(plane.GetSignedDistanceTo(p)) <= d);
        }

        /// <summary>
        /// Gets a Polyline from the Polyline3d. 
        /// An exception is thrown if the Polyline3d vertices do not define a single plane.
        /// </summary>
        /// <param name="pline3d">The instance this method applies to.</param>
        /// <returns>A new Polyline instance.</returns>
        public static Polyline ToPolyline(this Polyline3d pline3d)
        {
            if (pline3d == null)
                throw new ArgumentNullException(nameof(pline3d));

            Vector3d normal;
            var points = pline3d.GetVertices();
            if (!points.IsPlanar(out normal))
                throw new InvalidOperationException("The Polyline3d does not define a single plane.");
            var plane = new Plane(Point3d.Origin, normal);
            var pline = new Polyline(points.Count);
            for (int i = 0; i < points.Count; i++)
            {
                pline.AddVertexAt(i, points[i].Convert2d(plane), 0.0, 0.0, 0.0);
            }
            pline.Normal = normal;
            pline.Elevation = points[0].TransformBy(Matrix3d.WorldToPlane(plane)).Z;
            pline.Closed = pline3d.Closed;
            return pline;
        }
    }

Testing example:

 

        [CommandMethod("TEST")]
        public void Polyline3dToPolyline()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var peo = new PromptEntityOptions("\nSelect a 3D polyline: ");
            peo.SetRejectMessage("\nSelected object is not a 3D polyline.");
            peo.AddAllowedClass(typeof(Polyline3d), true);
            var per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var pl3d = (Polyline3d)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
                var space = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                try
                {
                    var pline = pl3d.ToPolyline();
                    pline.SetDatabaseDefaults();
                    space.AppendEntity(pline);
                    tr.AddNewlyCreatedDBObject(pline, true);
                    pl3d.Erase();
                }
                catch (System.Exception ex)
                {
                    Application.ShowAlertDialog(ex.Message);
                }
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes