qjchen 发表于 2012-1-3 09:39:58

[飞马系列] 块内图元全部原地拷贝或者部分移位拷贝

本帖最后由 qjchen 于 2013-10-20 19:31 编辑

前天

Cabinsummer提出了 http://bbs.mjtd.com/thread-91567-1-1.html

块内图元的拷贝问题,由于不是很熟悉lisp的块内操作,又想学习一下.Net的编法,于是借鉴了Kean的代码,

http://through-the-interface.typepad.com/through_the_interface/2010/06/changing-the-layer-of-an-entity-in-an-autocad-block-using-net.html
但为了历遍里面的实体和拷贝部分实体,就学习了一些.Net的Matrix函数和历遍
图片如下,代码如下,我的.Net水平挺低的,代码没有怎么优化,各位见笑了:)

不过对于不等比例的块,此程序是会报错的,可能得用.explode了。

DLL是可以netload的,命令是cnl

http://qjchen.mjtd.com/wp-content/uploads/2012/01/copyinsideblock.gif


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
namespace form1
{
    public class KeanCopyFromBlock
    {
      
      static public void ChangeNestedLayer()
      {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Transaction tr = doc.TransactionManager.StartTransaction();
            // 选择是所有块内实体原地拷贝还是选择部分块内实体拖动拷贝
            PromptKeywordOptions pko = new PromptKeywordOptions("\n是 1.选择所有块内实体原地拷贝 2.选择部分块内实体拖动拷贝: ", "1, 2");
            PromptResult pr = ed.GetKeywords(pko);
            if (pr.Status != PromptStatus.OK)
            {
                ed.WriteMessage("\n*Canceled*\n");
                return;
            }
            using (tr)
            {
                // Loop until cancelled or completed
                PromptEntityOptions peo = new PromptEntityOptions("\n请选择一个块:");
                peo.SetRejectMessage("\n必须是一个块:");
                peo.AddAllowedClass(typeof(BlockReference), true);
                PromptEntityResult per = ed.GetEntity(peo);
                if (per.Status != PromptStatus.OK) return;
                BlockReference br = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;
                switch (pr.StringResult)
                {
                  case "1":
                        BlockTableRecord btr = tr.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
                        foreach (ObjectId id in btr)
                        {
                            Entity Ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
                            if (Ent != null)
                            {
                              Entity tempEnt = qSubEntityClone(Ent, ed, db, doc, br);
                            }
                        }
                        break;
                  case "2":
                        PromptNestedEntityResult rs;
                        // Collection of our selected entities
                        ObjectIdCollection ids = new ObjectIdCollection();
                        rs = ed.GetNestedEntity("\n请选择需要拷贝的该块内的实体: ");
                        if (rs.Status == PromptStatus.OK)
                        {
                            ids.Add(rs.ObjectId);
                            HighlightSubEntity(doc, rs);
                        }
                        //while (rs.Status == PromptStatus.OK);
                        if (ids.Count > 0)
                        {
                            for (int i = 0; i < ids.Count; i++)
                            {
                              Entity Ent = tr.GetObject(ids, OpenMode.ForWrite) as Entity;
                              if (Ent != null)
                              {
                                    Entity tempEnt = qSubEntityClone(Ent, ed, db, doc, br);
                                    PromptPointResult bpResult, dpResult;
                                    PromptPointOptions bpProps = new PromptPointOptions("\n拷贝起点:");
                                    bpProps.AllowNone = true;
                                    bpProps.UseBasePoint = false;
                                    bpResult = ed.GetPoint(bpProps);
                                    if (bpResult.Status != PromptStatus.OK)
                                        throw new System.Exception("\n用户取消.");
                                    PromptPointOptions dpProps = new PromptPointOptions("\n拷贝终点:");
                                    dpProps.AllowNone = true;
                                    dpProps.UseBasePoint = true;
                                    dpProps.BasePoint = bpResult.Value;
                                    dpResult = ed.GetPoint(dpProps);
                                    if (dpResult.Status != PromptStatus.OK)
                                        throw new System.Exception("\n用户取消.");
                                    Point3d pa = bpResult.Value;
                                    Point3d pb = dpResult.Value;
                                    qCopy(tempEnt, pa, pb);
                              }
                            }
                        }
                        break;
                  default
                        :
                        break;
                }
                tr.Commit();
                // Regen clears highlighting and reflects the new layer
                ed.Regen();
            }
      }
      static private Entity qSubEntityClone(Entity Ent, Editor ed, Database db, Document doc, BlockReference br)
      {
            Transaction tr = doc.TransactionManager.StartTransaction();
            BlockTableRecord CurSpace = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
            LayerTable LayTbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
            LinetypeTable LtTbl = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;
            Dictionary<ObjectId, Handle> Dict = new Dictionary<ObjectId, Handle>();
            object Obj = Ent.Clone();
            Entity tempEnt = Obj as Entity;
            if (tempEnt == null) return null;
            using (tr)
            {
                LayerTableRecord ltr = tr.GetObject(Ent.LayerId, OpenMode.ForRead) as LayerTableRecord;
                tempEnt.LayerId = Ent.LayerId;
                tempEnt.Color = Ent.EntityColor.ColorMethod == Autodesk.AutoCAD.Colors.ColorMethod.ByLayer ? ltr.Color : Ent.Color;
                tempEnt.LinetypeId = Ent.Linetype == "ByLayer" ? ltr.LinetypeObjectId : Ent.LinetypeId;
                tempEnt.TransformBy(br.BlockTransform);
                CurSpace.AppendEntity(tempEnt);
                tr.AddNewlyCreatedDBObject(tempEnt, true);
                //Dict.Add(tempEnt.ObjectId, ids.Handle);
                //下面这段是对块内块的,暂时我就不考虑了
                if (tempEnt is BlockReference)
                {
                  BlockReference tempBlkRef = tempEnt as BlockReference;
                  foreach (ObjectId attId in tempBlkRef.AttributeCollection)
                  {
                        Ent = tr.GetObject(attId, OpenMode.ForWrite) as Entity;
                        Ent.Color = tempEnt.Color;
                        //Ent.LayerId = tempLayId;
                        Ent.Linetype = "Continuous";
                        //Dict.Add(attId, attId.Handle);
                  }
                }
                tr.Commit();
            }
            return tempEnt;
      }
      private static void HighlightSubEntity(
          Document doc, PromptNestedEntityResult rs
      )
      {
            // Extract relevant information from the prompt object
            ObjectId selId = rs.ObjectId;
            ObjectId[] objIds = rs.GetContainers();
            int len = objIds.Length;
            // Reverse the "containers" list
            ObjectId[] revIds = new ObjectId;
            for (int i = 0; i < len; i++)
            {
                ObjectId id =
                  (ObjectId)objIds.GetValue(len - i - 1);
                revIds.SetValue(id, i);
            }
            // Now add the selected entity to the end
            revIds.SetValue(selId, len);
            // Retrieve the sub-entity path for this entity
            SubentityId subEnt =
            new SubentityId(SubentityType.Null, 0);
            FullSubentityPath path = new FullSubentityPath(revIds, subEnt);
            // Open the outermost container, relying on the open
            // transaction...
            ObjectId id2 = (ObjectId)revIds.GetValue(0);
            Entity ent = id2.GetObject(OpenMode.ForRead) as Entity;
            // ... and highlight the nested entity
            if (ent != null)
                ent.Highlight(path, false);
      }
      private static void qCopy(Entity ent, Point3d p1, Point3d p2)
      {
            Vector3d vec = p2 - p1;
            Matrix3d mt = Matrix3d.Displacement(vec);
            ent.TransformBy(mt);
      }
    }
}



此代码+dll


vlisp2012 发表于 2012-1-4 20:07:59

支持一下!!!

myjping 发表于 2012-1-5 16:45:54

这个其实不用那么麻烦的,取得对象,复制对角,缩放,旋转;如果对象是固定类型的比如圆,多义线什么的更方便了,取得点就可以了

chpmould 发表于 2012-1-7 14:32:31

支持一下...

江湖远人 发表于 2012-1-8 11:21:31

学习一下,这方面知识太少了

xiaxiang 发表于 2012-1-10 19:26:33

qjchen 兄,在06下执行命令cnl报错,是版本的问题吗

qjchen 发表于 2012-1-10 21:24:25

xiaxiang 发表于 2012-1-10 19:26 static/image/common/back.gif
qjchen 兄,在06下执行命令cnl报错,是版本的问题吗

哦,.NET的一般2007之后比较好

chlh_jd 发表于 2012-1-27 13:42:59

全部拷贝或许没有必要的,一个炸开命令就全部都有了;不过部分复制还是很有必要的,支持!
之前写了个单选的:
http://bbs.mjtd.com/thread-86165-1-1.html

sageman 发表于 2013-3-29 08:26:10

非常实用,谢谢!

NJZX05 发表于 2013-10-18 12:53:51

受益不小!
页: [1]
查看完整版本: [飞马系列] 块内图元全部原地拷贝或者部分移位拷贝