X剪辑和块插入点
Kean在这里有一个很好的xclip工作示例http://through-the-interface.typepad.com/through_the_interface/2010/11/adding-a-2d-spatial-filter-to-perform-a-simple-xclip-on-an-external-reference-in-autocad-using-net.html然而,这对我没有帮助,因为我正在尝试更新现有的剪辑信息
下面是一个工作函数,用于更改块的插入,在获得xclipped blockref之前,该函数工作正常
如果在XCLIPFRAME设置为2或1且图形中有剪裁的blockref的情况下运行以下代码,您将看到剪辑移动到LALALand中的某个位置
代码只是复制现有剪辑信息,然后以某种愚蠢的形式将其恢复。有人知道它在做什么吗
public static void NewInsertionPoint()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
//Get the blockreference
PromptEntityOptions peo = new PromptEntityOptions("Pick a blockreference to change the insertion point:");
peo.SetRejectMessage("Must be a blockreference:");
peo.AddAllowedClass (typeof(BlockReference),true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
//New insertion point
PromptPointResult ppo=ed.GetPoint("Pick the new insertion point:");
if (ppo.Status != PromptStatus.OK) return;
Matrix3d ucs=ed.CurrentUserCoordinateSystem;
Point3d insPt = ppo.Value.TransformBy(ucs),newPt;
bool hasAtts=false;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference br = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;
ObjectId blockId=br.BlockTableRecord;
BlockTableRecord btr = tr.GetObject(blockId, OpenMode.ForWrite) as BlockTableRecord;
Plane plane=new Plane(ucs.CoordinateSystem3d.Origin,ucs.CoordinateSystem3d.Zaxis);
//Transform inspt back to the blockdef
Matrix3d blockmatrix = br.BlockTransform;
insPt= insPt.TransformBy(blockmatrix.Inverse());
//Util.AddEnt.Point(insPt, 2);
Vector3d v=btr.Origin-insPt;
Matrix3d move=Matrix3d.Displacement(v);
Matrix2d disp = Matrix2d.Displacement(insPt.Convert2d(plane)-btr.Origin.Convert2d(plane));
//Move the ents in the block
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.TransformBy(move);
ent.DowngradeOpen();
if(ent.GetType()==typeof(AttributeDefinition))
hasAtts=true;
}
ObjectIdCollection ids = btr.GetBlockReferenceIds(false, true);
//Move the BlockReferences
foreach (ObjectId brefId in ids)
{
bool btrans = false;
BlockReference b = tr.GetObject(brefId, OpenMode.ForWrite) as BlockReference;
if (b.BlockTableRecord == blockId)
{
newPt = insPt.TransformBy(b.BlockTransform);
b.TransformBy(Matrix3d.Displacement(newPt - b.Position));
btrans = true;
}
else
{
BlockTableRecord nestedBref = tr.GetObject(b.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;
foreach (ObjectId id in nestedBref)
{
if (id == brefId)
{
newPt = insPt.TransformBy(b.BlockTransform);
b.TransformBy(Matrix3d.Displacement(newPt - b.Position));
btrans = true;
break;
}
}
}
if (btrans)
{
ObjectId id = b.ExtensionDictionary;
if (id == ObjectId.Null) continue;
DBDictionary dic = tr.GetObject(id, OpenMode.ForWrite) as DBDictionary;
const string spatialName = "SPATIAL";
DBDictionary FilterDic = tr.GetObject(dic.GetAt("ACAD_FILTER"), OpenMode.ForWrite) as DBDictionary;
if (!FilterDic.Contains(spatialName)) continue;
SpatialFilter sf = tr.GetObject(FilterDic.GetAt(spatialName), OpenMode.ForWrite) as SpatialFilter;
SpatialFilterDefinition def = sf.Definition;
Point2dCollection pts = new Point2dCollection();
foreach (Point2d pt in def.GetPoints())
{
//pts.Add(pt.TransformBy(disp));
pts.Add(pt);
}
SpatialFilterDefinition NewDef = new SpatialFilterDefinition
(def.GetPoints(), def.Normal, def.Elevation, def.FrontClip, def.BackClip, def.Enabled);
//SpatialFilterDefinition NewDef = new SpatialFilterDefinition
// (pts, def.Normal, def.Elevation, def.FrontClip, def.BackClip, def.Enabled);
SpatialFilter NewSf = new SpatialFilter();
NewSf.Definition = NewDef;
FilterDic.Remove(spatialName);
FilterDic.SetAt(spatialName, NewSf);
tr.AddNewlyCreatedDBObject(NewSf, true);
}
}
if (hasAtts)
Blocks.blocks.UpdateAtts(blockId, db);
tr.Commit();
}
} // end NewInsertionPoint
**** Hidden Message ***** 再近一点,您必须减去块引用位置。
foreach (Point2d pt in def.GetPoints())
{
pts.地址(pt);
}
变
为 Vector3d v3 = br。Position.GetAsVector();
foreach (Point2d pt in def.GetPoints())
{
Point3d p = new Point3d(pt.X,pt.是的,防守海拔);
p = p -v3;
分。Add(p.Convert2d(plane));
}
但是,如果您复制剪辑的块引用,则会导致所有剪辑和块引用都转到剪辑的 forst 实例 追踪布莱斯看起来是个大问题。
...希望我有时间玩
可能值得尝试调整斯蒂芬普雷斯顿或基恩的兴趣... 感谢您的回复克里,您的建议听起来不错。
我把它分成了2个函数
public static void NewInsertionPoint()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptEntityOptions peo = new PromptEntityOptions("Pick a blockreference to change the insertion point:");
peo.SetRejectMessage("Must be a blockreference:");
peo.AddAllowedClass (typeof(BlockReference),true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
PromptPointResult ppo=ed.GetPoint("Pick the new insertion point:");
if (ppo.Status != PromptStatus.OK) return;
Matrix3d ucs=ed.CurrentUserCoordinateSystem;
Point3d insPt = ppo.Value.TransformBy(ucs),newPt;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference br = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;
ObjectId blockId=br.BlockTableRecord;
BlockTableRecord btr = tr.GetObject(blockId, OpenMode.ForWrite) as BlockTableRecord;
Matrix3d blockmatrix = br.BlockTransform;
insPt= insPt.TransformBy(blockmatrix.Inverse());
Vector3d v=btr.Origin-insPt;
Matrix3d move=Matrix3d.Displacement(v);
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.TransformBy(move);
ent.DowngradeOpen();
}
ObjectIdCollection ids = btr.GetBlockReferenceIds(false, true);
foreach (ObjectId brefId in ids)
{
BlockReference b = tr.GetObject(brefId, OpenMode.ForWrite) as BlockReference;
newPt = insPt.TransformBy(b.BlockTransform);
if (b.BlockTableRecord == blockId)
{
b.TransformBy(Matrix3d.Displacement(newPt - b.Position));
}
else
{
BlockTableRecord nestedBref = tr.GetObject(b.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;
foreach (ObjectId id in nestedBref)
{
if (id == brefId)
{
b.TransformBy(Matrix3d.Displacement(newPt - b.Position));
break;
}
}
}
UpdateClip(db, b, v);
}
tr.Commit();
}
ed.Regen();
} // end NewInsertionPoint
public static void UpdateClip(Database db,BlockReference br,Vector3d v)
{
const string spatialName = "SPATIAL";
ObjectId ExId = br.ExtensionDictionary;
if (ExId == ObjectId.Null) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
DBDictionary dic = tr.GetObject(ExId, OpenMode.ForWrite) as DBDictionary;
if (!dic.Contains("ACAD_FILTER")) return;
DBDictionary clipDic = tr.GetObject(dic.GetAt("ACAD_FILTER"), OpenMode.ForWrite) as DBDictionary;
if (!clipDic.Contains(spatialName)) return;
SpatialFilter sf = tr.GetObject(clipDic.GetAt(spatialName), OpenMode.ForWrite) as SpatialFilter;
SpatialFilterDefinition def = sf.Definition;
Plane plane=new Plane(new Point3d(0,0,def.Elevation),def.Normal);
Matrix3d m = br.BlockTransform;
Matrix3d disp=Matrix3d.Displacement(v.Negate());
Point2dCollection pts = new Point2dCollection();
foreach (Point2d pt in def.GetPoints())
{
Point3d p = new Point3d(pt.X, pt.Y,def.Elevation);
p = p.TransformBy(m.Inverse());
pts.Add(p.Convert2d(plane));
}
SpatialFilterDefinition def2=new SpatialFilterDefinition(
pts,def.Normal,def.Elevation,def.FrontClip,def.BackClip,def.Enabled);
clipDic.Remove(spatialName);
SpatialFilter sf2 = new SpatialFilter();
sf2.Definition = def2;
SpatialFilterVolume sfv=sf.GetVolume();
clipDic.SetAt(spatialName, sf2);
tr.AddNewlyCreatedDBObject(sf2,true);
tr.Commit();
}
} // end UpdateClip
,这是大多数情况下第一次工作,但第二次它抛出一个摆动器。此外,如果你剪辑一个块引用,然后旋转它,它会出错,所以复合矩阵需要退后一步。一开始,我认为我必须相对于新的插入点移动剪辑,但我没有。 我在2015年用VS2012 express和crash再次尝试了这一点,事实上,运行Kean的代码也会崩溃。我希望有人能在2015年尝试基恩代码 http://through-the-interface.typepad.com/through_the_interface/2010/11/adding-a-2d-spatial-filter-to-perform-a-simple-xclip-on-an-external-reference-in-autocad-using-net.html
以防万一其他人对剪辑感兴趣。这崩溃为我 ACAD 2015 机械使用香草. 基恩说他在2015年尝试过,它没有崩溃,所以我有点迷茫。希望别人可以试一试 我可以让 Kean 和此示例 http://adndevblog.typepad.com/autocad/2013/01/spatial-filter-xclip-command-command-in-c.html 将剪辑添加到外部参照。
但是,如果它不会反转,并且如果使用握把编辑剪辑,它就会崩溃。 谢谢你的努力,杰夫,我想我会放弃的。如果我单步执行代码,它不会崩溃,但我也不能编辑剪辑,有时我可以删除剪辑,但不能重新剪辑。
较新的代码看起来需要用较新的cad版本更新,所以我可能也会跳过这一步。
可惜,否则更改插入点代码真的很方便。 这似乎工作正常。
它不允许剪辑与blockref在不同的平面上。
在保存关闭并重新打开之前,不会显示剪辑夹点。
public static void NewInsertionPoint()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
//Get the blockreference
PromptEntityOptions peo = new PromptEntityOptions("\nPick a blockreference to change the insertion point:");
peo.SetRejectMessage("Must be a blockreference:");
peo.AddAllowedClass (typeof(BlockReference),true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
//New insertion point
PromptPointResult ppo=ed.GetPoint("\nPick the new insertion point:");
if (ppo.Status != PromptStatus.OK) return;
Matrix3d ucs=ed.CurrentUserCoordinateSystem;
Point3d insPt = ppo.Value.TransformBy(ucs),newPt=Point3d.Origin;
bool hasAtts=false;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
//Get the blockref
BlockReference br = tr.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference;
ObjectId blockId=br.BlockTableRecord;
//get it's blockdef
BlockTableRecord btr = tr.GetObject(blockId, OpenMode.ForWrite) as BlockTableRecord;
//Transform inspt back to the blockdef
Matrix3d blockmatrix = br.BlockTransform;
insPt= insPt.TransformBy(blockmatrix.Inverse());
Matrix3d move = Matrix3d.Displacement(btr.Origin - insPt);
//Move the ents in the block
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
ent.TransformBy(move);
if(ent.GetType()==typeof(AttributeDefinition))
hasAtts=true;
}
ObjectIdCollection ids = btr.GetBlockReferenceIds(false, true);
//Move the BlockReferences
Matrix3d mBref = new Matrix3d();
foreach (ObjectId brefId in ids)
{
bool btrans = false;
BlockReference b = tr.GetObject(brefId, OpenMode.ForWrite) as BlockReference;
Point3d bposition = b.Position;
if (b.BlockTableRecord == blockId)//has to unless nested
{
newPt = insPt.TransformBy(b.BlockTransform);
mBref=Matrix3d.Displacement(newPt - b.Position);
b.TransformBy(mBref);
btrans = true;
}
else
{
BlockTableRecord nestedBref = tr.GetObject(b.BlockTableRecord, OpenMode.ForWrite) as BlockTableRecord;
foreach (ObjectId id in nestedBref)
{
if (id == brefId)
{
newPt = insPt.TransformBy(b.BlockTransform);
b.TransformBy(mBref);
btrans = true;
break;
}
}
}
if (btrans)
{
ObjectId id = b.ExtensionDictionary;
if (id == ObjectId.Null) continue;
DBDictionary dic = tr.GetObject(id, OpenMode.ForWrite) as DBDictionary;
const string spatialName = "SPATIAL";
if (!dic.Contains("ACAD_FILTER")) continue;
DBDictionary FilterDic = tr.GetObject(dic.GetAt("ACAD_FILTER"), OpenMode.ForWrite) as DBDictionary;
if (!FilterDic.Contains(spatialName)) continue;
SpatialFilter sf = tr.GetObject(FilterDic.GetAt(spatialName), OpenMode.ForWrite) as SpatialFilter;
SpatialFilterDefinition def = sf.Definition;
Point2dCollection pts = new Point2dCollection();
Matrix3d m = sf.OriginalInverseBlockTransform;
// Matrix3d w= sf.ClipSpaceToWorldCoordinateSystemTransform;
//need this for clips on a different plane than the blockref
CoordinateSystem3d cs = m.CoordinateSystem3d;
Plane plane = new Plane(cs.Origin, cs.Zaxis);
Matrix2d disp = Matrix2d.Displacement(newPt.Convert2d(plane) - b.Position.Convert2d(plane));
foreach (Point2d pt in def.GetPoints())
{
Point3d l = new Point3d(plane, pt);
l = l.TransformBy(move);
l = l.TransformBy(m);
pts.Add(l.Convert2d(plane));
}
pts.TrimToSize();
SpatialFilterDefinition NewDef = new SpatialFilterDefinition
(pts,Vector3d.ZAxis,0, def.FrontClip, def.BackClip, true);
SpatialFilter NewSf = new SpatialFilter();
NewSf.Definition = NewDef;
FilterDic.Remove(spatialName);//REMOVE the old filter
FilterDic.SetAt(spatialName, NewSf);
tr.AddNewlyCreatedDBObject(NewSf, true);
}
if (hasAtts)
Blocks.blocks.UpdateAtts(blockId, db);
}
tr.Commit();
}
ed.Regen();
} // end NewInsertionPoint
页:
[1]