Author Topic: How to Fix the serrated edge of polyline with "DrawJig"?  (Read 3193 times)

0 Members and 1 Guest are viewing this topic.

cjw

  • Guest
How to Fix the serrated edge of polyline with "DrawJig"?
« on: July 23, 2011, 10:19:32 AM »
AutoCAD2008, the polyline drawing with the serrated edge.
But i used the lisp, which with the function "grread". Lisp work smooth.

Here is my C# code:
Code: [Select]
using System;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Colors;
namespace CsMgd1
{
        /// <summary>
        /// 绘制板负筋
        /// </summary>
        public class MyClass : DrawJig
        {
            private Polyline entGangJin;
            private Point2d startPt, endPt;
            [CommandMethod("tt")]
            public void BanFuJin()
            {
                CreateLayer("REIN", 1);
                Database db = HostApplicationServices.WorkingDatabase;
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage("\n画板负筋 作者:carrot1983 2011年7月23日");
                bool flag = true;
                while (flag)
                {
                    PromptPointOptions pointOpt = new PromptPointOptions("\n指定第一点<退出>: ");
                    pointOpt.AllowNone = true; //允许空输入
                    PromptPointResult pointRes = ed.GetPoint(pointOpt);
                    if (pointRes.Status != PromptStatus.OK)
                    {
                        flag = false;
                    }
                    else
                    {
                        // 取得起点
                        startPt = new Point2d(pointRes.Value.X, pointRes.Value.Y);
                        // 创建多段线
                        Point2d[] pt = new Point2d[4];
                        pt[0] = startPt;
                        pt[1] = startPt;
                        pt[2] = startPt;
                        pt[3] = startPt;
                        Point2dCollection pts = new Point2dCollection(pt);
                        int n = pts.Count;
                        entGangJin = new Polyline();
                        for (int i = 0; i < n; i++)
                            entGangJin.AddVertexAt(i, pts[i], 0, 100 * 0.3, 100 * 0.3);
                        entGangJin.Layer = "REIN";
                        // 提交事务处理
                        using (Transaction trans = db.TransactionManager.StartTransaction())
                        {
                            BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                            BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                            // 开始拖拽.
                            PromptResult resJig = ed.Drag(this);
                            if (resJig.Status == PromptStatus.OK)
                            {
                                btr.AppendEntity(entGangJin);
                                trans.AddNewlyCreatedDBObject(entGangJin, true);
                                trans.Commit();
                            }
                        }
                    }
                }
            }
            protected override bool WorldDraw(Autodesk.AutoCAD.GraphicsInterface.WorldDraw draw)
            {
                draw.Geometry.Draw(entGangJin);
                return true;
            }
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                Database db = HostApplicationServices.WorkingDatabase;
                JigPromptPointOptions optJigPoint = new JigPromptPointOptions("\n指定第二点:");
                optJigPoint.Cursor = CursorType.Crosshair;
                optJigPoint.BasePoint = new Point3d(startPt.X, startPt.Y, 0.0);
                optJigPoint.UseBasePoint = true;
                //
                // 用AcquirePoint函数得到用户输入的点.
                PromptPointResult resJigPoint = prompts.AcquirePoint(optJigPoint);
                Point2d curPt = new Point2d(resJigPoint.Value.X, resJigPoint.Value.Y);
                if (curPt != endPt)
                {
                    // 重新设置多段线参数--------------------------------------------
                    // 线的起点 startPt 终点 curPt
                    Point2d pt1, pt2, pt3, pt4;
                    double ang = startPt.GetVectorTo(curPt).Angle;
                    pt1 = PolarPoint(startPt, (ang - Math.PI * 0.5), 100 * 2);
                    pt2 = startPt;
                    pt3 = curPt;
                    pt4 = PolarPoint(curPt, (ang - Math.PI * 0.5), 100 * 2);
                    entGangJin.SetPointAt(0, pt1);
                    entGangJin.SetPointAt(1, pt2);
                    entGangJin.SetPointAt(2, pt3);
                    entGangJin.SetPointAt(3, pt4);

                    // 保存当前点
                    endPt = curPt;
                    return SamplerStatus.OK;
                }
                else
                    return SamplerStatus.NoChange;
            }

            // 创建图层
            public static void CreateLayer(string layerName, short colorIndex)
            {
                Database db = HostApplicationServices.WorkingDatabase;
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForWrite);
                    ObjectId layerId;
                    if (lt.Has(layerName) == false)
                    {
                        LayerTableRecord ltr = new LayerTableRecord();
                        //图层名
                        ltr.Name = layerName;
                        //颜色
                        Color layerColor = Color.FromColorIndex(ColorMethod.ByColor, colorIndex);
                        ltr.Color = layerColor;
                        //图层打印
                        ltr.IsPlottable = true;
                        //线型
                        LinetypeTable tt = (LinetypeTable)trans.GetObject(db.LinetypeTableId, OpenMode.ForRead);
                        LinetypeTableRecord ttr;
                        try
                        {
                            db.LoadLineTypeFile("Continuous", "acadiso.lin");
                        }
                        catch
                        {
                            // 此处无需操作.
                        }
                        ttr = (LinetypeTableRecord)trans.GetObject(tt["Continuous"], OpenMode.ForRead);
                        ltr.LinetypeObjectId = ttr.ObjectId;
                        layerId = lt.Add(ltr);
                        trans.AddNewlyCreatedDBObject(ltr, true);
                        db.Clayer = layerId;
                    }
                    trans.Commit();
                }
            }
            // 获取与给定点指定角度和距离的点.
            public static Point2d PolarPoint(Point2d basePt, double angle, double distance)
            {
                double[] pt = new double[2];
                pt[0] = basePt[0] + distance * Math.Cos(angle);
                pt[1] = basePt[1] + distance * Math.Sin(angle);
                Point2d point = new Point2d(pt[0], pt[1]);
                return point;
            }
            // 将图形对象加入到模型空间的函数.
            public static ObjectId AppendEntity(Entity ent)
            {
                Database db = HostApplicationServices.WorkingDatabase;
                ObjectId entId;
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    entId = btr.AppendEntity(ent);
                    trans.AddNewlyCreatedDBObject(ent, true);
                    trans.Commit();
                }
                return entId;
            }
        }
}



cjw

  • Guest
Re: How to Fix the serrated edge of polyline with "DrawJig"?
« Reply #1 on: July 23, 2011, 10:20:35 AM »
Here is my Lisp code.

Thanks for your any reply.

Code: [Select]
(defun C:tt (/                   A                 ANG               B
             ENTMAKE-LAYER-NAME&COLOR         ENTMAKE-REIN  GET-PLINE-PT_LST
             GRR           MODE                 OBJ_PLINE     PT1
             PT2           PT3                 PT_LST               TIME
             VLA-UPDATE-PLINE                 X
            )

  (setq        ENTMAKE-REIN
         (lambda (PTS)
           (if (entmake
                 (append
                   (list (cons 0 "LWPOLYLINE")
                         (cons 100 "AcDbEntity")
                         (cons 100 "AcDbPolyline")
                         (cons 8 "REIN")
                         (cons 43 (* 0.3 100))
                         (cons 70 0)
                         (cons 90 (length PTS))
                   )
                   (mapcar '(lambda (X) (cons 10 X))
                           PTS
                   )
                 )
               )
             (entlast)
           )
         )
  )

  (setq        ENTMAKE-LAYER-NAME&COLOR
         (lambda (NAME COLOR)
           (if (not (tblsearch "LAYER" NAME))
             (entmake
               (list
                 (cons 0 "LAYER")
                 (cons 100 "AcDbSymbolTableRecord")
                 (cons 100 "AcDbLayerTableRecord")
                 (cons 2 NAME)
                 (cons 62 COLOR)
                 (cons 6 "Continuous")
                 (cons 70 0)
               )
             )
           )
         )
  )

  (setq        VLA-UPDATE-PLINE
         (lambda (OBJ_PLINE I PT / VLA_PT)
           (vl-load-com)
           (setq VLA_PT        (vlax-make-safearray
                          vlax-vbdouble
                          '(0 . 1)
                        )
           )
           (vlax-safearray-fill
             VLA_PT
             (list (car PT) (cadr PT))
           )
           (vla-put-coordinate OBJ_PLINE I VLA_PT)
           (vla-update OBJ_PLINE)
         )
  )

  (defun *ERROR* (MSG)
    (if        (not
          (member MSG
                  '("console break"
                    "Function cancelled"
                    "quit / exit abort"
                    ""
                   )
          )
        )
      (princ (strcat "\n[注意]: " MSG))
    )
    (redraw)
    (vla-endundomark
      (vla-get-activedocument
        (vlax-get-acad-object)
      )
    )
    (princ)
  )

  (setq        GET-PLINE-PT_LST
         (lambda (PT1 PT2 / A ANG B PT0 PT3 PT_TXT)
           (setq ANG (angle PT1 PT2))
           (if (and (> ANG (* 0.5 pi))
                    (<= ANG (* 1.5 pi))
               )
             (setq ANG (- ANG pi))
           )
           (setq PT0 (polar PT1 (- ANG (* 0.5 pi)) (* 100 1.5)))
           (setq PT3 (polar PT2 (- ANG (* 0.5 pi)) (* 100 1.5)))
           (setq PT_TXT        (polar (mapcar
                                 '(lambda (A B) (* (+ A B) 0.5))
                                 PT1
                                 PT2
                               )
                               (+ ANG (* 0.5 pi))
                               (* 100 0.5)
                        )
           )
           (list PT0 PT1 PT2 PT3 PT_TXT ANG)
         )
  )

  (princ "\n画板负筋 作者:carrot1983 2009年11月14日")

  ;;指定起点:
  (while (setq PT1 (getpoint "\n指定起点: "))
    (progn
      (setq OBJ_PLINE (vlax-ename->vla-object
                        (ENTMAKE-REIN (list PT1 PT1 PT1 PT1))
                      )
      )

      (princ "\n指定下一点: ")
      ;;动态绘制
      (progn
        (setq TIME t)
        (setq MODE (getvar "ORTHOMODE"))
        (while TIME
          (setq GRR (grread t 12 0))
          (redraw)
          ;;按F8的时候
          (cond
            ((= (cadr GRR) 15)
             (cond ((= MODE 1) (setvar "ORTHOMODE" (setq MODE 0)))
                   ((= MODE 0) (setvar "ORTHOMODE" (setq MODE 1)))
             )
            )
            ;;移动鼠标的时候
            ((= (car GRR) 5)
             (progn
               (setq PT2 (cadr GRR))
               (if (= (getvar "ORTHOMODE") 1)
                 (if (>        (abs (- (car PT1) (car PT2)))
                        (abs (- (cadr PT1) (cadr PT2)))
                     )
                   (setq PT3 (list (car PT2) (cadr PT1) (caddr PT2)))
                   (setq PT3 (list (car PT1) (cadr PT2) (caddr PT2)))
                 )
                 (setq PT3 PT2)
               )
               (setq PT2 PT3)
               (setq PT_LST (GET-PLINE-PT_LST PT1 PT2))
               (setq ANG (last PT_LST))
               (VLA-UPDATE-PLINE OBJ_PLINE 0 (nth 0 PT_LST))
               (VLA-UPDATE-PLINE OBJ_PLINE 1 (nth 1 PT_LST))
               (VLA-UPDATE-PLINE OBJ_PLINE 2 (nth 2 PT_LST))
               (VLA-UPDATE-PLINE OBJ_PLINE 3 (nth 3 PT_LST))
             )
            )
            ;;指点的时候
            ((= (car GRR) 3)
             (setq TIME NIL)
            )
            ((= (car GRR) 25)
             (setq TIME NIL)
             (vla-erase OBJ_PLINE)
            )
            ((= (car GRR) 2)
             t
            )
            (t
             (setq TIME NIL)
            )
          )
        )
      )
    )
  )
  (princ)
)


kaefer

  • Guest
Re: How to Fix the serrated edge of polyline with "DrawJig"?
« Reply #2 on: July 26, 2011, 07:23:05 PM »
But i used the lisp, which with the function "grread". Lisp work smooth.

Is it the sometimes awfully ragged appearance which bothers you? Sorry, can't fix that.

In contrast, transient entities work half smooth. You could still see some redrawing going on, not as bad as with the Jig. Transients combined with Editor.PointMonitor are very similar to your GRREAD loop.

Here is my F# code:
Code: [Select]
type acApp = Autodesk.AutoCAD.ApplicationServices.Application
type acGiTm =  Autodesk.AutoCAD.GraphicsInterface.TransientManager
type acGiTdm =  Autodesk.AutoCAD.GraphicsInterface.TransientDrawingMode

let pi = System.Math.PI
let p2d (p: Point3d) = new Point2d(p.X, p.Y)
let polarVec angle distance =
    new Vector2d(distance * cos angle, distance * sin angle)

[<CommandMethod "drawThingy">]
let drawThingyCommand() =
    let db = HostApplicationServices.WorkingDatabase
    let ed = acApp.DocumentManager.MdiActiveDocument.Editor

    let curvp = acApp.GetSystemVariable "CVPORT" |> unbox<int16> |> int
    let vps = new IntegerCollection[| curvp |]
    let ppr = ed.GetPoint "Start point"
    if ppr.Status = PromptStatus.OK then
       
        let startp = p2d ppr.Value
        let lastp = ref startp
   
        use pl = new Polyline()
        pl.SetDatabaseDefaults()
        for i in 0 .. 3 do
            pl.AddVertexAt(i, startp, 0., 30., 30.)
        acGiTm.CurrentTransientManager.AddTransient(
            pl, acGiTdm.DirectShortTerm, 128, vps )
        |> ignore

        let pointMonitor =
            ed.PointMonitor
            |> Observable.subscribe
                (fun e ->
                    let endp = p2d e.Context.ComputedPoint
                    let ang = (startp.GetVectorTo endp).Angle - pi / 2.
                    let ang = if ang >= 0. && ang < pi then ang - pi else ang
                    pl.SetPointAt(0, startp + polarVec ang 200.)
                    pl.SetPointAt(1, startp)
                    pl.SetPointAt(2, endp)
                    pl.SetPointAt(3, endp + polarVec ang 200.)
                    acGiTm.CurrentTransientManager.UpdateTransient(pl, vps) )

        let ppr1 =
            new PromptPointOptions("End point", AllowNone = true)
            |> ed.GetPoint
        pointMonitor.Dispose()
        acGiTm.CurrentTransientManager.EraseTransient(pl, vps) |> ignore

        if ppr1.Status = PromptStatus.OK then
            use tr = db.TransactionManager.StartTransaction()
            let btr =
                tr.GetObject(
                    db.CurrentSpaceId, OpenMode.ForWrite ) :?> BlockTableRecord
            btr.AppendEntity pl |> ignore
            tr.AddNewlyCreatedDBObject(pl, true)
            tr.Commit()

By the way, both your DrawJig and your lisp function aren't conforming to the user interface guideline, that any command should be cancellable when it waits for user input. It is therefore advisible to check the Status of JigPrompts.AcquirePoint and to pass SamplerStatus.Cancel accordingly.

Cheers
« Last Edit: July 26, 2011, 07:28:39 PM by kaefer »

cjw

  • Guest
Re: How to Fix the serrated edge of polyline with "DrawJig"?
« Reply #3 on: July 27, 2011, 11:27:54 AM »
But i used the lisp, which with the function "grread". Lisp work smooth.

Is it the sometimes awfully ragged appearance which bothers you? Sorry, can't fix that.

In contrast, transient entities work half smooth. You could still see some redrawing going on, not as bad as with the Jig. Transients combined with Editor.PointMonitor are very similar to your GRREAD loop.

Here is my F# code:
Code: [Select]
type acApp = Autodesk.AutoCAD.ApplicationServices.Application
type acGiTm =  Autodesk.AutoCAD.GraphicsInterface.TransientManager
type acGiTdm =  Autodesk.AutoCAD.GraphicsInterface.TransientDrawingMode

let pi = System.Math.PI
let p2d (p: Point3d) = new Point2d(p.X, p.Y)
let polarVec angle distance =
    new Vector2d(distance * cos angle, distance * sin angle)

[<CommandMethod "drawThingy">]
let drawThingyCommand() =
    let db = HostApplicationServices.WorkingDatabase
    let ed = acApp.DocumentManager.MdiActiveDocument.Editor

    let curvp = acApp.GetSystemVariable "CVPORT" |> unbox<int16> |> int
    let vps = new IntegerCollection[| curvp |]
    let ppr = ed.GetPoint "Start point"
    if ppr.Status = PromptStatus.OK then
       
        let startp = p2d ppr.Value
        let lastp = ref startp
   
        use pl = new Polyline()
        pl.SetDatabaseDefaults()
        for i in 0 .. 3 do
            pl.AddVertexAt(i, startp, 0., 30., 30.)
        acGiTm.CurrentTransientManager.AddTransient(
            pl, acGiTdm.DirectShortTerm, 128, vps )
        |> ignore

        let pointMonitor =
            ed.PointMonitor
            |> Observable.subscribe
                (fun e ->
                    let endp = p2d e.Context.ComputedPoint
                    let ang = (startp.GetVectorTo endp).Angle - pi / 2.
                    let ang = if ang >= 0. && ang < pi then ang - pi else ang
                    pl.SetPointAt(0, startp + polarVec ang 200.)
                    pl.SetPointAt(1, startp)
                    pl.SetPointAt(2, endp)
                    pl.SetPointAt(3, endp + polarVec ang 200.)
                    acGiTm.CurrentTransientManager.UpdateTransient(pl, vps) )

        let ppr1 =
            new PromptPointOptions("End point", AllowNone = true)
            |> ed.GetPoint
        pointMonitor.Dispose()
        acGiTm.CurrentTransientManager.EraseTransient(pl, vps) |> ignore

        if ppr1.Status = PromptStatus.OK then
            use tr = db.TransactionManager.StartTransaction()
            let btr =
                tr.GetObject(
                    db.CurrentSpaceId, OpenMode.ForWrite ) :?> BlockTableRecord
            btr.AppendEntity pl |> ignore
            tr.AddNewlyCreatedDBObject(pl, true)
            tr.Commit()

By the way, both your DrawJig and your lisp function aren't conforming to the user interface guideline, that any command should be cancellable when it waits for user input. It is therefore advisible to check the Status of JigPrompts.AcquirePoint and to pass SamplerStatus.Cancel accordingly.

Cheers

kaefer
Thank you. thanks for your suggestion.
My friend QJchen told me that AutoCAD2012 may be better.

kaefer

  • Guest
Re: How to Fix the serrated edge of polyline with "DrawJig"?
« Reply #4 on: July 27, 2011, 01:21:42 PM »
My friend QJchen told me that AutoCAD2012 may be better.

What kind of product improvement regarding Jig display might have happened between 18.1 and 18.2?