adolfken 发表于 2013-4-15 11:17:25

动态插入箭头

平常因为工作的关系经常要插入一些箭头,根据鼠标的位置变化方向和变化.之前有人写过这个功能,我就按照样例仿写了一下,可能因为水平的关系算法有些复杂,还希望大家轻拍,麻烦各位大侠帮忙把算法优化一下,刚写完没有完全测试可能有点小问题.

(defun c:tt ()
   (vl-load-com)
   (setq acad (vlax-get-acad-object))
   (setq acaddocument (vla-get-activedocument acad))
   (setq mspace (vla-get-modelspace acaddocument))
   (setq h (getreal "\n请输入偏移距离"))
(setq endata (entsel "\n请选择一条线"))
   (setq ename (car endata))
   (setq p0 (cadr endata))
   (setq obj (vlax-ename->vla-object ename))
   (setq l1 (car (vlax-safearray->list (vlax-variant-value (vla-offset obj h)))))         ;偏移曲线1
   (setq l2 (car (vlax-safearray->list (vlax-variant-value (vla-offset obj (* -1 h))))))    ;偏移曲线2
   (setq p1 (vlax-curve-getclosestpointto l1 p0 t))      ;插入点1
   (setq p2 (vlax-curve-getclosestpointto l2 p0 t))      ;插入点2
   (vla-delete l1)    ;删除曲线1
   (vla-delete l2)    ;删除曲线2
   (setq ang1 (angle p2 p1));插入点1 点2角度
   (setq ang2 (- ang1 (/ pi 2)));计算直线角度或者曲线的切线角度
   (setq obj (vla-insertblock mspace (vlax-3d-point p2) "11005" 1 1 1 ang2)) ;插入块名为11005的图块
   (setq loop t)
(while loop
    (setq code (grread t 8))
    (cond
   ((= (car code) 5)
    (setq ang3 (- (angle p0 (cadr code)) ang2))   ;光标所在点与单选点的角度减去直线的或者曲线切线的角度
    (if (< ang3 0)
      (setq ang3 (+ ang3 (* 2 pi))))
   (cond
      ((and (> ang3 0 ) (< ang3(/ pi 2)))
         (vla-put-Rotation obj ang2)
         (vla-put-insertionpoint obj (vlax-3d-point p1))
         )
      ((and (> ang3 (/ pi 2)) (< ang3 pi))
         (vla-put-Rotation obj (- ang2 pi))
         (vla-put-insertionpoint obj (vlax-3d-point p1))
         )
      ((and (> ang3 pi) (< ang3(* 3 (/ pi 2))))
         (vla-put-Rotation obj (- ang2 pi))
         (vla-put-insertionpoint obj (vlax-3d-point p2))
         )
      ((and (> ang3 (* 3 (/ pi 2))) (< ang3(* 2 pi)))
         (vla-put-Rotation obj ang2)
         (vla-put-insertionpoint obj (vlax-3d-point p2))
         )            
       )
    )
   ((= code '(25 37)) (vla-delete obj))
   (T (setq loop nil))
   )
   )
)


xxxx223 发表于 2020-1-10 13:32:51

根据自己使用改了下,在图形中第一次使用时,输入名字,自动创建一个800*400的箭头块,或者选择已有块

xyp1964 发表于 2013-4-15 14:09:50

;; 曲线动态插入箭头

adolfken 发表于 2013-4-15 16:44:40

本帖最后由 adolfken 于 2013-4-15 18:39 编辑

在院长和wowan两位大侠的指导下我按照正常切线方向的计算写了代码,非常感谢两位. (defun c:tt ()
          (vl-load-com)
          (setq acad (vlax-get-acad-object))
          (setq acaddocument (vla-get-activedocument acad))
          (setq mspace (vla-get-modelspace acaddocument))
          (setq h (getreal "\n请输入偏移距离"))
      (setq endata (entsel "\n请选择一条线"))
          (setq p0 (cadr endata))
      (setq l1 (vlax-ename->vla-object (car endata)))
          (setq p1 (vlax-curve-getclosestpointto l1 p0 t))
          (setq ang1 (angle p1 (mapcar '+ p1 (vlax-curve-getfirstderiv l1 (vlax-curve-getparamatpoint l1 p1)))))
      (setq p2 (polar p1 (+ ang1 (/ pi 2)) h))
          (setq p3 (polar p1 (- ang1 (/ pi 2)) h))
          (setq obj (vla-insertblock mspace (vlax-3d-point p2) "11005" 1 1 1 ang1))
          (setq loop t)
      (while loop
                  (setq code (grread t 8))
                  (cond
                        ((= (car code) 5)
                         (setq ang2 (- (angle p1 (cadr code)) ang1))
                         (if (< ang2 0)
                           (setq ang2 (+ ang2 (* 2 pi))))
                        (cond
                           ((and (> ang2 0 ) (< ang2 (/ pi 2)))               
                              (vla-put-Rotation obj ang1)               
                              (vla-put-insertionpoint obj (vlax-3d-point p2))
                              )
                           ((and (> ang2 (/ pi 2) ) (< ang2 pi))               
                              (vla-put-Rotation obj (- ang1 pi))               
                              (vla-put-insertionpoint obj (vlax-3d-point p2))
                              )
                           ((and (> ang2 pi ) (< ang2(* 3 (/ pi 2))))               
                              (vla-put-Rotation obj (- ang1 pi))               
                              (vla-put-insertionpoint obj (vlax-3d-point p3))
                              )
                           ((and (> ang2 (* 3 (/ pi 2))) (< ang2(* pi 2)))               
                              (vla-put-Rotation obj ang1)               
                              (vla-put-insertionpoint obj (vlax-3d-point p3))
                              )
                            )
                         )
                        ((= (car code) 25) (setq loop nil) (vla-delete obj))
                        (T (setq loop nil))
                        )
          )
)

lzg8877 发表于 2013-4-19 06:35:45

这个好是好 工作关系用不上 感谢热心人

yaya-54 发表于 2013-5-10 11:00:02

出现错误:
请选择一条线; 错误: Automation 错误。 文件处理器错误
另外最好距离可以点选。

朽木大师 发表于 2013-5-10 11:27:42

yaya-54 发表于 2013-5-10 11:00 static/image/common/back.gif
出现错误:
请选择一条线; 错误: Automation 错误。 文件处理器错误
另外最好距离可以点选。

同样的错误
同样的建议

朽木大师 发表于 2013-5-10 11:35:45

看明白了,原来是要先自己画个箭头做个块

夺天工 发表于 2018-12-16 22:36:20

错误: Automation 错误。 文件处理器错误

j15tty 发表于 2020-1-10 14:38:04

本帖最后由 j15tty 于 2020-1-10 14:44 编辑

C:\Users\Administrator\Desktop\GIF动画录制工具20200110141850.gif public class 坡度标注Jig : DrawJig
    {
      public Autodesk.AutoCAD.DatabaseServices.Polyline m_pl;
      private Point3d m_pt, m_insertPt;
      public static DBText m_text = new DBText();
      private Curve m_c;
      public static double m_bl = 1;
      public static double m_jj = 3;
      public static double m_h = 3;
      private Database m_db;
      public 坡度标注Jig(Autodesk.AutoCAD.DatabaseServices.Polyline pl, DBText text, Curve c, Point3d pt, Database db, double bl, double jj, double h)
      {
            m_pl = pl;
            m_pt = pt;
            m_text = text;
            m_c = c;
            m_db = db;
            m_bl = bl;
            m_jj = jj;
            m_h = h;
      }
      protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
      {
            Point3d p1 = m_c.GetClosestPointTo(m_insertPt, false);
            Vector3d vecCz = m_insertPt - p1;//鼠标点到曲线的垂足点的向量
            Vector3d vec = m_insertPt - m_pt;//得到鼠标与曲线上点取点的向量
            Vector3d vec1 = m_c.GetFirstDerivative(m_pt);//曲线点切向量
            double angFx = vec.GetAngleTo(Vector3d.XAxis, -Vector3d.ZAxis);//鼠标点与曲线上点取点向量与X轴的夹角;
            double angQx = vec1.GetAngleTo(Vector3d.XAxis, -Vector3d.ZAxis);
            double ang = vec.GetAngleTo(vec1);
            Point3d insertPt, pt1, pt2, pt3;
            bool flag = IsLeftOfCurve(m_c, m_insertPt);
            if (flag == true)
            {
                insertPt = m_pt.polarPoint(angQx + Math.PI / 2, m_jj);
                if (ang < Math.PI / 2)
                {
                  pt1 = insertPt.polarPoint(angQx + Math.PI, m_bl * 5);
                  pt2 = pt1.polarPoint(angQx, m_bl * 10);
                  pt3 = pt2.polarPoint(angQx, m_bl * 3.5);
                  m_text.Position = insertPt.polarPoint(angQx + Math.PI / 2, m_bl * 0.5 + m_text.Height / 2);
                  m_text.Rotation = angQx;
                  m_text.Height = m_h;
                  m_text.HorizontalMode = TextHorizontalMode.TextMid;
                  m_text.VerticalMode = TextVerticalMode.TextBottom;
                  m_text.AlignmentPoint = m_text.Position;
                  m_text.AdjustAlignment(m_db);
                }
                else
                {
                  pt1 = insertPt.polarPoint(angQx, m_bl * 5);
                  pt2 = pt1.polarPoint(angQx + Math.PI, m_bl * 10);
                  pt3 = pt2.polarPoint(angQx + Math.PI, m_bl * 3.5);
                  m_text.Position = insertPt.polarPoint(angQx + Math.PI / 2, m_bl * 0.5 + m_text.Height / 2);
                  m_text.Rotation = angQx;
                  m_text.Height = m_h;
                  m_text.HorizontalMode = TextHorizontalMode.TextMid;
                  m_text.VerticalMode = TextVerticalMode.TextBottom;
                  m_text.AlignmentPoint = m_text.Position;
                  m_text.AdjustAlignment(m_db);
                }

            }
            else
            {
                insertPt = m_pt.polarPoint(angQx - Math.PI / 2, m_jj);
                if (ang < Math.PI / 2)
                {
                  pt1 = insertPt.polarPoint(angQx + Math.PI, m_bl * 5);
                  pt2 = pt1.polarPoint(angQx, m_bl * 10);
                  pt3 = pt2.polarPoint(angQx, m_bl * 3.5);
                  m_text.Position = insertPt.polarPoint(angQx - Math.PI / 2, m_bl * 0.5 + m_text.Height / 2);
                  m_text.Rotation = angQx + Math.PI;
                  m_text.Height = m_h;
                  m_text.HorizontalMode = TextHorizontalMode.TextMid;
                  m_text.VerticalMode = TextVerticalMode.TextBottom;
                  m_text.AlignmentPoint = m_text.Position;
                  m_text.AdjustAlignment(m_db);
                }
                else
                {
                  pt1 = insertPt.polarPoint(angQx, m_bl * 5);
                  pt2 = pt1.polarPoint(angQx + Math.PI, m_bl * 10);
                  pt3 = pt2.polarPoint(angQx + Math.PI, m_bl * 3.5);
                  m_text.Position = insertPt.polarPoint(angQx - Math.PI / 2, m_bl * 0.5 + m_text.Height / 2);
                  m_text.Rotation = angQx + Math.PI;
                  m_text.Height = m_h;
                  m_text.HorizontalMode = TextHorizontalMode.TextMid;
                  m_text.VerticalMode = TextVerticalMode.TextBottom;
                  m_text.AlignmentPoint = m_text.Position;
                  m_text.AdjustAlignment(m_db);
                }
            }
            m_pl.Normal = Vector3d.ZAxis;
            m_pl.Elevation = 0.0;
            m_pl.SetPointAt(0, new Point2d(pt1.X, pt1.Y));
            m_pl.SetPointAt(1, new Point2d(pt2.X, pt2.Y));
            m_pl.SetPointAt(2, new Point2d(pt3.X, pt3.Y));
            m_pl.SetStartWidthAt(0, 0);
            m_pl.SetEndWidthAt(0, 0);
            m_pl.SetStartWidthAt(1, m_bl);
            m_pl.SetEndWidthAt(1, 0);
            m_pl.SetStartWidthAt(2, 0);
            m_pl.SetEndWidthAt(2, 0);
            draw.Geometry.Draw(m_pl);
            draw.Geometry.Draw(m_text);
            return true;
      }

      protected override SamplerStatus Sampler(JigPrompts prompts)
      {
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
            Matrix3d mat = ed.CurrentUserCoordinateSystem;
            JigPromptPointOptions optInsertPt = new JigPromptPointOptions("\n请选择方向或[比例增(A)/比例减(S)/间距增(D)/间距减(F)/坡度设置(Q)]");
            optInsertPt.UserInputControls = (UserInputControls.Accept3dCoordinates |
                                             UserInputControls.NullResponseAccepted |
                                             UserInputControls.NoNegativeResponseAccepted |
                                             UserInputControls.GovernedByOrthoMode);
            optInsertPt.Keywords.Add("A");
            optInsertPt.Keywords.Add("S");
            optInsertPt.Keywords.Add("D");
            optInsertPt.Keywords.Add("F");
            optInsertPt.Keywords.Add("Q");
            optInsertPt.AppendKeywordsToMessage = false;
            //m_pt = m_pt.TransformBy(mat);
            PromptPointResult resJigInsertPt = prompts.AcquirePoint(optInsertPt);
            if (resJigInsertPt.Status == PromptStatus.Cancel)
                return SamplerStatus.Cancel;
            if (resJigInsertPt.Status == PromptStatus.Keyword)
            {
                switch (resJigInsertPt.StringResult)
                {
                  case "A":
                        {
                            m_bl = m_bl * 2;
                            m_h = m_h * 2;
                            break;
                        }
                  case "S":
                        {
                            m_bl = m_bl * 0.5;
                            m_h = m_h * 0.5;
                            break;
                        }
                  case "D":
                        {
                            m_jj = m_jj * 1.1;
                            break;
                        }
                  case "F":
                        {
                            m_jj = m_jj * 0.9;
                            break;
                        }
                  case "Q":
                        {

                            PromptStringOptions opt = new PromptStringOptions("\n请输入坡度");
                            PromptResult res = ed.GetString(opt);
                            if (res.Status != PromptStatus.OK)
                              break;
                            else
                            {
                              try
                              {
                                    double value = Convert.ToDouble(res.StringResult);
                                    if (value >= 10)
                                    {
                                        if (MyEntity.IsInteger(res.StringResult))
                                        {
                                          m_text.TextString = (value / 10).ToString("0") + "%";
                                        }
                                        else
                                        {
                                          m_text.TextString = (value / 10).ToString("0.####") + "%";
                                        }
                                    }
                                    else
                                        m_text.TextString = res.StringResult + "‰";
                              }
                              catch (System.Exception ex)
                              {
                                    ed.WriteMessage(ex.Message);
                                    m_text.TextString = "3" + "‰";
                              }
                            }
                            break;
                        }
                }

            }
            if (m_insertPt != resJigInsertPt.Value)
            {

                m_insertPt = resJigInsertPt.Value;

                return SamplerStatus.OK;
            }
            else
            {

                return SamplerStatus.NoChange;
            }

      }
页: [1]
查看完整版本: 动态插入箭头