Ok so I tweaked my code after reading the 2 posts you mentioned but the clip is still falling in the wrong place for both 2d and 3d block references? I added the "DrawClipBoundary" method which successfully places an outline around the intended Xclip boundary. Can you spot where I'm going wrong? Its driving me potty.
Also I wrote an additional function to read existing XCLIP information which returned some interesting results, it appears the clip retains the coordainate system values at the time of creation?
[CommandMethod("XCLIPALL")]
public static void XRefClipAll()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
const string filterDictName = "ACAD_FILTER";
const string spatialName = "SPATIAL";
var peo = new PromptEntityOptions("\nSelect a block: ");
peo.SetRejectMessage("\nMust be a block reference.");
peo.AddAllowedClass(typeof (BlockReference), true);
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
var ppo = new PromptPointOptions("\nSelect rect clip 1st corner: ");
var ppr1 = ed.GetPoint(ppo);
if (ppr1.Status != PromptStatus.OK)
return;
var pco = new PromptCornerOptions( "\nSelect rect clip 2nd corner: ", ppr1.Value)
{
UseDashedLine = true
};
var ppr2 = ed.GetCorner(pco);
if (ppr2.Status != PromptStatus.OK)
return;
var bref = (BlockReference) tr.GetObject(per.ObjectId, OpenMode.ForRead);
var bottomLeftCorner = ppr1.Value.TransformBy(bref.BlockTransform.Inverse());
var upperRightCorner = ppr2.Value.TransformBy(bref.BlockTransform.Inverse());
var pts = new Point2dCollection(2)
{
new Point2d(bottomLeftCorner.X, bottomLeftCorner.Y),
new Point2d(upperRightCorner.X, upperRightCorner.Y),
};
Vector3d normal;
double elev;
if (db.TileMode)
{
normal = db.Ucsxdir.CrossProduct(db.Ucsydir);
elev = db.Elevation;
}
else
{
normal = db.Pucsxdir.CrossProduct(db.Pucsydir);
elev = db.Pelevation;
}
normal.GetNormal();
// Create spatial filter
var sfd = new SpatialFilterDefinition(
pts,
normal, elev,
double.PositiveInfinity,
double.NegativeInfinity,
true);
// Show Intend xclip boundary
DrawClipBoundary(pts, bref, normal, elev);
var sf = new SpatialFilter {Definition = sfd};
// Create extension dictionary if doesn't exist
if (br.ExtensionDictionary == ObjectId.Null)
{
br.UpgradeOpen();
br.CreateExtensionDictionary();
br.DowngradeOpen();
}
// Add spatial filter to extension dictionary
var xDict = (DBDictionary) tr.GetObject(br.ExtensionDictionary, OpenMode.ForWrite);
if (xDict.Contains(filterDictName))
{
var filterDict =
(DBDictionary) tr.GetObject(xDict.GetAt(filterDictName), OpenMode.ForWrite);
if (filterDict.Contains(spatialName))
filterDict.Remove(spatialName);
filterDict.SetAt(spatialName, sf);
}
else
{
var fDict = new DBDictionary();
xDict.SetAt(filterDictName, fDict);
tr.AddNewlyCreatedDBObject(fDict, true);
fDict.SetAt(spatialName, sf);
}
tr.AddNewlyCreatedDBObject(sf, true);
tr.Commit();
}
ed.Regen();
}
-------------------------------------
READ FUNCTION
-------------------------------------
[CommandMethod("XCLIPREAD")]
public static void XRefClipRead()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
const string filterDictName = "ACAD_FILTER";
const string spatialName = "SPATIAL";
var peo = new PromptEntityOptions("\nSelect MVF block: ");
peo.SetRejectMessage("\nMust be a block reference.");
peo.AddAllowedClass(typeof (BlockReference), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
var br = (BlockReference) tr.GetObject(per.ObjectId, OpenMode.ForRead);
if (br.ExtensionDictionary == ObjectId.Null) return;
var xDict = (DBDictionary)tr.GetObject(br.ExtensionDictionary, OpenMode.ForWrite);
if (xDict.Contains(filterDictName))
{
var filterDict = (DBDictionary) tr.GetObject(xDict.GetAt(filterDictName), OpenMode.ForRead);
if(!filterDict.Contains(spatialName)) return;
var sf = tr.GetObject(filterDict.GetAt(spatialName), OpenMode.ForRead) as SpatialFilter;
SpatialFilterDefinition def = sf.Definition;
foreach (Point2d pt in def.GetPoints())
{
ed.WriteMessage("\nPoints: " + pt);
}
ed.WriteMessage("\nNormal: " + def.Normal);
ed.WriteMessage("\nElevation: " + def.Elevation);
ed.WriteMessage("\nFront clip: " + def.FrontClip);
ed.WriteMessage("\nBack clip: " + def.BackClip);
}
}
}