Author Topic: Add vertex  (Read 832 times)

0 Members and 1 Guest are viewing this topic.

Offline (gile)

  • C#
  • *
  • Posts: 87
  • Karma: +8/-0
  • Gender: Male
    • prefered language: F
    • Prog expertise: Good
    • View Profile
Add vertex
« on: November 21, 2010, 10:43:47 PM »
Hi,

The AVX command allows to add vertices to a polyline.
The `Jig' allows a dynamic preview of the new segment(s).
The command works whatever the polyline construction plane (`dynamic UCS' behavior while the polyline plane is different from the current UCS).
A DVX command allows to remove vertices

It deals with osnaps...


It deals with non constant widthes...


It deals with arc segments and with start and end points.


Code: [Select]
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace PolylineEdit
{
    public class AddVertex
    {
        Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor;
        Database db = HostApplicationServices.WorkingDatabase;

        class VertexJig : EntityJig
        {
            Polyline m_pline;
            Point3d m_point;
            int m_index;
            Vector3d m_vector;
            double m_bulge;
            double m_sWidth;
            double m_eWidth;

            public VertexJig(Polyline pline, Point3d point, int index, Vector3d vector, double bulge, double sWidth, double eWidth)
                : base(pline)
            {
                m_pline = pline;
                m_point = point;
                m_index = index;
                m_vector = vector;
                m_bulge = bulge;
                m_sWidth = sWidth;
                m_eWidth = eWidth;
            }

            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                JigPromptPointOptions jppo = new JigPromptPointOptions("\nSpecify the new vertex: ");
                jppo.UserInputControls = (UserInputControls.Accept3dCoordinates);
                PromptPointResult ppr = prompts.AcquirePoint(jppo);
                if (ppr.Status == PromptStatus.OK)
                {
                    if (ppr.Value.IsEqualTo(m_point))
                        return SamplerStatus.NoChange;
                    else
                    {
                        m_point = ppr.Value;
                        return SamplerStatus.OK;
                    }
                }
                return SamplerStatus.Cancel;
            }

            protected override bool Update()
            {
                if (m_pline.NumberOfVertices == 3)
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    double length = m_pline.GetDistanceAtParameter(2);
                    double dist1 = m_pline.GetDistanceAtParameter(1);
                    double dist2 = length - dist1;
                    double width = m_sWidth < m_eWidth ?
                        ((dist1 * (m_eWidth - m_sWidth)) / length) + m_sWidth :
                        ((dist2 * (m_sWidth - m_eWidth)) / length) + m_eWidth;
                    double angle = Math.Atan(m_bulge);
                    m_pline.SetPointAt(m_index, pt);
                    m_pline.SetEndWidthAt(0, width);
                    m_pline.SetStartWidthAt(1, width);
                    m_pline.SetBulgeAt(0, Math.Tan(angle * (dist1 / length)));
                    m_pline.SetBulgeAt(1, Math.Tan(angle * (dist2 / length)));
                }
                else if (m_index == 0)
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    m_pline.SetPointAt(m_index, pt);
                    if (m_bulge != 0.0)
                    {
                        Vector3d vec = m_point.GetVectorTo(m_pline.GetPoint3dAt(1));
                        double ang = vec.GetAngleTo(m_vector, m_pline.Normal);
                        double bulge = Math.Tan(ang / 2.0);
                        m_pline.SetBulgeAt(0, bulge);
                    }
                }
                else
                {
                    Point3d transPt = m_point.TransformBy(Matrix3d.WorldToPlane(m_pline.Normal));
                    Point2d pt = new Point2d(transPt.X, transPt.Y);
                    m_pline.SetPointAt(m_index, pt);
                    if (m_bulge != 0.0)
                    {
                        Vector3d vec = m_pline.GetPoint3dAt(0).GetVectorTo(m_point);
                        double ang = m_vector.GetAngleTo(vec, m_pline.Normal);
                        double bulge = Math.Tan(ang / 2.0);
                        m_pline.SetBulgeAt(0, bulge);
                    }
                }
                return true;
            }

            public Point3d GetPoint()
            {
                return m_point;
            }
        }

        [CommandMethod("AVX")]
        public void Avx()
        {
            PromptEntityOptions peo = new PromptEntityOptions("\nSelect a segment where to add a vertex: ");
            peo.SetRejectMessage("\nIncorrect entity");
            peo.AllowNone = false;
            peo.AllowObjectOnLockedLayer = false;
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status == PromptStatus.OK)
            {
                Matrix3d UCS = ed.CurrentUserCoordinateSystem;
                ObjectId objId = per.ObjectId;
                try
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        Polyline pline = tr.GetObject(objId, OpenMode.ForRead, false) as Polyline;
                        if (pline != null)
                        {
                            Point3d pickPt = pickPointOnPline(pline, per.PickedPoint);
                            double param = pline.GetParameterAtPoint(pickPt);
                            int index = (int)param;

                            Matrix3d OCS = Matrix3d.PlaneToWorld(pline.Normal);
                            Point3d transPt = pickPt.TransformBy(OCS);

                            if (!OCS.CoordinateSystem3d.Zaxis.IsEqualTo(UCS.CoordinateSystem3d.Zaxis))
                            {
                                ed.CurrentUserCoordinateSystem = plineUCS(pline, index);
                            }

                            Int16 aperture = (Int16)acadApp.GetSystemVariable("APERTURE");
                            double viewsize = (double)acadApp.GetSystemVariable("VIEWSIZE");
                            Point2d screensize = (Point2d)acadApp.GetSystemVariable("SCREENSIZE");
                            double tol = 2 * aperture * viewsize / screensize.Y;
                            Tolerance tolerance = new Tolerance(tol, tol);

                            int endParam = pline.Closed == true ? pline.NumberOfVertices : pline.NumberOfVertices - 1;
                            Vector3d vec;

                            using (Polyline ghost = new Polyline())
                            {
                                ghost.ColorIndex = 7;

                                if ((pline.Closed == false) && pickPt.IsEqualTo(pline.GetPoint3dAt(0), tolerance))
                                {
                                    vec = pline.GetFirstDerivative(0);
                                    double bulge = pline.GetBulgeAt(0);
                                    double width = pline.GetStartWidthAt(0);
                                    Point2d p0 = new Point2d(transPt.X, transPt.Y);
                                    Point2d p1 = pline.GetPoint2dAt(0);

                                    ghost.AddVertexAt(0, p0, bulge, width, width);
                                    ghost.AddVertexAt(1, p1, bulge, width, width);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 0, vec, bulge, width, width);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.AddVertexAt(index, ghost.GetPoint2dAt(0), ghost.GetBulgeAt(0), width, width);
                                    }
                                }
                                else if ((pline.Closed == false) && pickPt.IsEqualTo(pline.GetPoint3dAt(endParam), tolerance))
                                {
                                    vec = pline.GetFirstDerivative(endParam);
                                    double bulge = pline.GetBulgeAt(index);
                                    double width = pline.GetEndWidthAt(endParam);
                                    Point2d p0 = pline.GetPoint2dAt(endParam);
                                    Point2d p1 = new Point2d(transPt.X, transPt.Y);

                                    ghost.AddVertexAt(0, p0, bulge, width, width);
                                    ghost.AddVertexAt(1, p1, bulge, width, width);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 1, vec, bulge, width, width);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.AddVertexAt(endParam + 1, ghost.GetPoint2dAt(1), ghost.GetBulgeAt(0), width, width);
                                        pline.SetBulgeAt(endParam, ghost.GetBulgeAt(0));
                                    }
                                }

                                else
                                {
                                    double bulge = pline.GetBulgeAt(index);
                                    double sWidth = pline.GetStartWidthAt(index);
                                    double eWidth = pline.GetEndWidthAt(index);
                                    Point2d p0 = pline.GetPoint2dAt(index);
                                    Point2d p1 = new Point2d(transPt.X, transPt.Y);
                                    Point2d p2;
                                    if (pline.Closed == false)
                                        p2 = pline.GetPoint2dAt(index + 1);
                                    else
                                    {
                                        try { p2 = pline.GetPoint2dAt(index + 1); }
                                        catch { p2 = pline.GetPoint2dAt(0); }
                                    }

                                    ghost.AddVertexAt(0, p0, bulge, sWidth, 0.0);
                                    ghost.AddVertexAt(1, p1, bulge, 0.0, eWidth);
                                    ghost.AddVertexAt(2, p2, 0.0, 0.0, 0.0);
                                    ghost.Normal = pline.Normal;
                                    ghost.Elevation = pline.Elevation;

                                    VertexJig jig = new VertexJig(ghost, pickPt, 1, vec, bulge, sWidth, eWidth);

                                    PromptResult res = ed.Drag(jig);
                                    if (res.Status == PromptStatus.OK)
                                    {
                                        pline.UpgradeOpen();
                                        pline.SetEndWidthAt(index, ghost.GetStartWidthAt(1));
                                        pline.AddVertexAt(index + 1, ghost.GetPoint2dAt(1), ghost.GetBulgeAt(1), ghost.GetStartWidthAt(1), eWidth);
                                        pline.SetBulgeAt(index, ghost.GetBulgeAt(0));
                                    }
                                }
                            }
                            ed.CurrentUserCoordinateSystem = UCS;
                        }
                        tr.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    ed.CurrentUserCoordinateSystem = UCS;
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }

        [CommandMethod("DVX")]
        public void Dvx()
        {
            PromptEntityOptions peo = new PromptEntityOptions("\nSelact the vertex to remove: ");
            peo.SetRejectMessage("\nIncorrect entity");
            peo.AllowNone = false;
            peo.AllowObjectOnLockedLayer = false;
            peo.AddAllowedClass(typeof(Polyline), true);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status == PromptStatus.OK)
            {
                ObjectId objId = per.ObjectId;
                try
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        Polyline pline = tr.GetObject(objId, OpenMode.ForWrite, false) as Polyline;
                        if (pline != null)
                        {
                            if (pline.NumberOfVertices > 2)
                            {
                                Point3d pickPt = pickPointOnPline(pline, per.PickedPoint);
                                double param = pline.GetParameterAtPoint(pickPt);
                                int index = (int)param;
                                if ((param - Math.Truncate(param)) > 0.5)
                                    index += 1;
                                pline.RemoveVertexAt(index);
                            }
                            else
                                ed.WriteMessage("\nOnly two vertices left");
                        }
                        tr.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    ed.WriteMessage("Error: " + ex.Message);
                }
            }
        }

        private Point3d pickPointOnPline(Polyline pl, Point3d pt)
        {
            pt = pt.TransformBy(ed.CurrentUserCoordinateSystem);
            Vector3d vdir = ed.GetCurrentView().ViewDirection;
            pt = pt.Project(pl.GetPlane(), vdir);
            return pl.GetClosestPointTo(pt, false);
        }

        private Matrix3d plineUCS(Polyline pline, int param)
        {
            Point3d origin = pline.GetPoint3dAt(param);
            Vector3d xDir = origin.GetVectorTo(pline.GetPoint3dAt(param + 1)).GetNormal();
            Vector3d zDir = pline.Normal;
            Vector3d yDir = zDir.CrossProduct(xDir).GetNormal();
            return new Matrix3d(new double[16]{
                xDir.X, yDir.X, zDir.X, origin.X,
                xDir.Y, yDir.Y, zDir.Y, origin.Y,
                xDir.Z, yDir.Z, zDir.Z, origin.Z,
                0, 0, 0, 1});
        }
    }
}

target audience:{advanced}