[飞马系列] 块内图元全部原地拷贝或者部分移位拷贝
本帖最后由 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
支持一下!!! 这个其实不用那么麻烦的,取得对象,复制对角,缩放,旋转;如果对象是固定类型的比如圆,多义线什么的更方便了,取得点就可以了
支持一下... 学习一下,这方面知识太少了 qjchen 兄,在06下执行命令cnl报错,是版本的问题吗 xiaxiang 发表于 2012-1-10 19:26 static/image/common/back.gif
qjchen 兄,在06下执行命令cnl报错,是版本的问题吗
哦,.NET的一般2007之后比较好 全部拷贝或许没有必要的,一个炸开命令就全部都有了;不过部分复制还是很有必要的,支持!
之前写了个单选的:
http://bbs.mjtd.com/thread-86165-1-1.html
非常实用,谢谢! 受益不小!
页:
[1]