7.动态绘制(Jig)

愿你出走半生,归来仍是少年! 

环境:.NET FrameWork4.5、ObjectArx 2016 64bit、Entity Framework 6. 

目录

1. 来源       

2. Jig类

2.1 EntityJig类        

2.2 DrawJig类        

2.2.1 MoveBlockSingleAttributeJig(DrawJig实现类) 

2.2.2 ToolMoveFlag(业务实现类)  


1. 来源       

        在CAD数据编辑时,实体的位置移动是时常需要遇见的操作。通过的方式是选中实体后再选择新的位置,然后将实体直接挪过去,虽然这样达到了移动实体的目的,但是交互效果过于糟糕。举个例子,在内业人员进行标注文本的位置挪动时,直接通过点选的方式进行文本的位置变更会导致在变更完成前内业人员无法确定变更后的效果,是否盖压严重、重叠等等问题。 由于带来的需求是需要实现配合鼠标移动的实体动态绘制效果。例如动态绘制一个矩形,而不是让用户去点击矩形的四个顶点;移动实体的时候,在选中实体后生成一根跟随鼠标的虚线,标识出新的位置等等。

2. Jig类

        在CAD中提供了Autodesk.AutoCAD.EditorInput.Jig类。在CAD的二次开发中,使用JIG技术可实现操作的动态性、交互,在交互中可在鼠标移动的同时实现拖动、牵引等效果表达,达到所见即所得的交互效果。

        Jig内部逻辑在停止前会不断进行循环,每次循环总体上分为四步

  •         获取用户拖动、移动的鼠标
  •         将其解释为距离、角度或点
  •         使用该值更新实体的数据
  •         调用实体的WorldDraw方法在屏幕上重绘它

        Jig类作为一个抽象类,拥有两个派生类:Autodesk.AutoCAD.EditorInput.DrawJig

Autodesk.AutoCAD.EditorInput.EntityJig

2.1 EntityJig类        

         针对单个实体提供拖拽的效果实现和最终的更新。

2.2 DrawJig类        

         无特定的实体,可针对的实体相对宽松,自由度更高。此处以移动块参考中的属性实体为例,先看效果如下:

2.2.1 MoveBlockSingleAttributeJig(DrawJig实现类) 

        该类继承于DrawJig类,通过Sampler方法实现目标点的确定,通过WorldDraw方法实现绘制。

  /// <summary>
    /// 移动块的指定属性
    /// </summary>
    public class MoveBlockSingleAttributeJig : DrawJig
    {
        //要挪到的目标点
        private Point3d selectedPt;

        //属性
        private AttributeReference attrRef;

        //字宽
        private double textWidth = 0;

        private BlockReference br = null;


        #region 结果

        /// <summary>
        ///属性的位置
        /// </summary>
        private Point3d selfAttributePosition;

        public Point3d AttributePosition { get { return selfAttributePosition; } }

        /// <summary>
        /// 牵引线
        /// </summary>
        private Autodesk.AutoCAD.DatabaseServices.Polyline selfDraftLine;

        public Autodesk.AutoCAD.DatabaseServices.Polyline DraftLine { get { return selfDraftLine; } }

        #endregion



        public MoveBlockSingleAttributeJig(BlockReference blockReference,AttributeReference attribute)
        {
            attrRef = attribute;

            double textHeight = attrRef.Height;

            //0.72是赵总根据经验推出的比例
            textWidth = attrRef.WidthFactor * textHeight * attrRef.TextString.GetByteLength() * 0.72;

            br = blockReference;
             
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {

            PromptPointResult ppr = prompts.AcquirePoint("请选择属性的新位置!");

            if (ppr.Status != PromptStatus.OK)
            {
                return SamplerStatus.Cancel;
            }

            selectedPt = ppr.Value;

            return SamplerStatus.OK;
        }

        protected override bool WorldDraw(WorldDraw draw)
        {

            Autodesk.AutoCAD.DatabaseServices.Polyline pl = new Autodesk.AutoCAD.DatabaseServices.Polyline();

            pl.AddVertexAt(0, new Point2d(br.Position.X, br.Position.Y), 0, 0, 0);
            pl.AddVertexAt(1, new Point2d(selectedPt.X, selectedPt.Y), 0, 0, 0);

            var cloneAttr = (AttributeReference)attrRef.Clone();

            if (selectedPt.X >= attrRef.Position.X)
            {
                cloneAttr.Position = new Point3d(selectedPt.X, selectedPt.Y + 0.4, 0);

                pl.AddVertexAt(2, new Point2d(selectedPt.X + textWidth, selectedPt.Y), 0, 0, 0);

            }
            else
            {
                cloneAttr.Position = new Point3d(selectedPt.X - textWidth, selectedPt.Y + 0.4, 0);

                pl.AddVertexAt(2, new Point2d(cloneAttr.Position.X, selectedPt.Y), 0, 0, 0);
            }


            pl.Linetype = "DASHED2";

            selfDraftLine = (Autodesk.AutoCAD.DatabaseServices.Polyline)pl.Clone();
            selfAttributePosition = cloneAttr.Position;

            draw.Geometry.Draw(pl);
            draw.Geometry.Draw(cloneAttr);

            return true;
        }


    }

2.2.2 ToolMoveFlag(业务实现类)  

        该类调用动态绘制,结合业务实现功能需求。通过SelectBlockReferenceByPointer方法选择指定图层中的引用指定块定义的块参考实体,并在回调中获取块中的第一个属性进行位置动效操作。针对操作完成后将属性的位置进行更新以及添加牵引线。

  [CommandMethod("MF")]
        public override void Command()
        {
            FileInfo absSymbolFile = new FileInfo(ModuleConfig.CadConfig.Symbol.AbsPointSymbol);


            SelectionHelper.SelectBlockReferenceByPointer(new BlockReferenceSelectOptions()
            {
                BlockDefindName = absSymbolFile.Name.Replace(absSymbolFile.Extension, ""),
                LayerName = ModuleConfig.CadConfig.Layers.AbsoluteLayers.AbsoluteRelationLayer.Name
            },
            (doc,db,editor,trans, entity) =>
            {
                BlockReference br = entity as BlockReference;

                AttributeReference attrRef=null;

                var enumerator = br.AttributeCollection.GetEnumerator();
             
                while (enumerator.MoveNext())
                {
                    var tempId = (ObjectId)enumerator.Current;

                    AttributeReference tempAttr = (AttributeReference)trans.GetObject(tempId, OpenMode.ForRead, false, true);

                    attrRef = tempAttr;

                    break;
                }

                doc.LoadLineType("DASHED2");

                MoveBlockSingleAttributeJig moveJig = new MoveBlockSingleAttributeJig(br,attrRef);

                PromptResult pr = editor.Drag(moveJig);

                if (pr.Status == PromptStatus.OK)
                {
                    //更新属性
                    attrRef.UpgradeOpen();
                    attrRef.Position = moveJig.AttributePosition;

                    //添加牵引线 
                    BlockTable blockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                    BlockTableRecord  btr = trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                    moveJig.DraftLine.Linetype = "Continuous";
                    moveJig.DraftLine.Layer = ModuleConfig.CadConfig.Layers.AbsoluteLayers.AbsoluteFlagLineLayer.Name;

                    btr.AppendEntity(moveJig.DraftLine);
                    trans.AddNewlyCreatedDBObject(moveJig.DraftLine, true);

                    moveJig.DraftLine.Dispose();
                    
                    
                }

                
            });
           

             

        }

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在ObjectARX中,实现连续绘制直线的Jig需要完成以下几个步骤: 1. 定义一个派生自AcEdJig的类,例如MyLineJig。在该类中,需要定义一些成员变量,例如起点、终点等。 2. 重载MyLineJig类中的drag()函数。在该函数中,需要根据用户的鼠标操作更新当前终点的位置,并将终点位置限制在某些范围内(例如限制在一个矩形区域内)。 3. 重载MyLineJig类中的update()函数。在该函数中,需要使用AcGiWorldDraw对象绘制当前的直线,并在绘制过程中使用AcGiSubEntityTraits对象设置直线的属性。 4. 在AutoCAD命令的实现函数中,创建MyLineJig对象,并使用AcEdJig::drag()函数启动Jig。在Jig完成后,从MyLineJig对象中获取最终的起点和终点位置,并使用AcDbLine对象创建直线实体。 以下是一个简单的示例代码: ``` class MyLineJig : public AcEdJig { public: MyLineJig() : m_startPt(AcGePoint3d::kOrigin), m_endPt(AcGePoint3d::kOrigin) {} virtual ~MyLineJig() {} virtual DragStatus sampler() override { // 获取用户当前的鼠标位置 AcGePoint3d curPt; if (acedGetPoint(nullptr, _T("终点:"), asDblArray(m_endPt)) != RTNORM) return DragStatus::kCancel; // 根据鼠标位置更新当前终点 if (curPt != m_endPt) { m_endPt = curPt; return DragStatus::kUpdate; } else { return DragStatus::kNoChange; } } virtual Adesk::Boolean update() override { // 绘制当前的直线 AcGiWorldDraw* pWorldDraw = acgiWorldDraw(); if (pWorldDraw) { AcGePoint3d pts[2] = { m_startPt, m_endPt }; pWorldDraw->geometry().polyline(2, pts); } return Adesk::kTrue; } public: AcGePoint3d m_startPt; AcGePoint3d m_endPt; }; void testDrawLine() { MyLineJig lineJig; if (acedGetPoint(asDblArray(lineJig.m_startPt), _T("起点:"), nullptr) == RTNORM) { lineJig.doIt(); // 启动Jig AcDbLine* pLine = new AcDbLine(lineJig.m_startPt, lineJig.m_endPt); acdbHostApplicationServices()->workingDatabase()->addAcDbEntity(pLine); } } ``` 上述代码中,MyLineJig类重载了drag()和update()函数,通过获取用户的鼠标位置更新当前终点,并使用AcGiWorldDraw对象在AutoCAD中绘制直线。在AutoCAD命令的实现函数中,创建MyLineJig对象并启动Jig,最终创建AcDbLine对象作为直线实体。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就是那个帕吉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值