感谢您的回复克里,您的建议听起来不错。
我把它分成了2个函数
- [CommandMethod("ChangeInsertionpoint")]
- 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
,这是大多数情况下第一次工作,但第二次它抛出一个摆动器。此外,如果你剪辑一个块引用,然后旋转它,它会出错,所以复合矩阵需要退后一步。一开始,我认为我必须相对于新的插入点移动剪辑,但我没有。 |