I have a solution:
[CommandMethod( "testClip", CommandFlags.Modal )]
public void testClip() // This method can have any name
{
try
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
const string filterDictName = "ACAD_FILTER";
const string spatialName = "SPATIAL";
//Wybrać blok
PromptEntityOptions peo = new PromptEntityOptions( "\nWskaż blok: " );
peo.AllowNone = true;
PromptEntityResult per = null;
do
{
per = ed.GetEntity( peo );
if( per.Status == PromptStatus.OK )
{
using( Transaction tr = db.TransactionManager.StartTransaction() )
{
BlockTableRecord curSpc = tr.GetObject( db.CurrentSpaceId, OpenMode.ForWrite ) as BlockTableRecord;
Entity ent = tr.GetObject( per.ObjectId, OpenMode.ForRead ) as Entity;
if( ent.GetType() == typeof( BlockReference ) )
{
//Jest blok. Wyłuskać obwiednię.
BlockReference blRef = ent as BlockReference;
if( blRef.ExtensionDictionary != ObjectId.Null )
{
DBDictionary extdict = tr.GetObject( blRef.ExtensionDictionary, OpenMode.ForRead ) as DBDictionary;
if( extdict.Contains( filterDictName ) )
{
DBDictionary fDict = tr.GetObject( extdict.GetAt( filterDictName ), OpenMode.ForRead ) as DBDictionary;
if( fDict.Contains( spatialName ) )
{
SpatialFilter sf = tr.GetObject( fDict.GetAt( spatialName ), OpenMode.ForRead ) as SpatialFilter;
SpatialFilterDefinition sfd = sf.Definition;
var pts = sfd.GetPoints();
Matrix3d matBloku = sf.ClipSpaceToWorldCoordinateSystemTransform.PreMultiplyBy( sf.OriginalInverseBlockTransform ).PreMultiplyBy( blRef.BlockTransform );
Matrix3d invMat = sf.OriginalInverseBlockTransform;
//Jeśli są dwa punkty, to jest tylko prostokąt. Jeśli więcej, to wielobok.
Polyline pln = new Polyline();
if( pts.Count == 2 )
{
Point2d pts0 = pts[0];
Point2d pts1 = pts[1];
Point2d p0 = RKGeometryczne.punkt3Dna2D( new Point3d( pts0.X, pts0.Y, 0 ).TransformBy( matBloku ) );
Point2d p1 = RKGeometryczne.punkt3Dna2D( new Point3d( pts1.X, pts0.Y, 0 ).TransformBy( matBloku ) );
Point2d p2 = RKGeometryczne.punkt3Dna2D( new Point3d( pts1.X, pts1.Y, 0 ).TransformBy( matBloku ) );
Point2d p3 = RKGeometryczne.punkt3Dna2D( new Point3d( pts0.X, pts1.Y, 0 ).TransformBy( matBloku ) );
pln.AddVertexAt( pln.NumberOfVertices, p0, 0, 0, 0 );
pln.AddVertexAt( pln.NumberOfVertices, p1, 0, 0, 0 );
pln.AddVertexAt( pln.NumberOfVertices, p2, 0, 0, 0 );
pln.AddVertexAt( pln.NumberOfVertices, p3, 0, 0, 0 );
} //if( pts.Count == 2 )
else
{
for( int i = 0; i < pts.Count; i++ )
{
Point2d p = RKGeometryczne.punkt3Dna2D( new Point3d( pts[i].X, pts[i].Y, 0 ).TransformBy( matBloku ) );
pln.AddVertexAt( pln.NumberOfVertices, p, 0, 0, 0 );
} //for( int i = 0; i < pts.Count; i++ )
} //else if( pts.Count == 2 )
pln.ColorIndex = 1;
pln.Closed = true;
curSpc.AppendEntity( pln );
tr.AddNewlyCreatedDBObject( pln, true );
//foreach( var pt in pts )
//{
// ed.WriteMessage( "\nBoundary point at {0}", pt );
//}
} //if( fDict.Contains( spatialName ) )
} //if( extdict.Contains( filterDictName ) )
} //if( blRef.ExtensionDictionary != ObjectId.Null )
} //if( ent.GetType() == typeof( BlockReference ) )
tr.Commit();
} //using( Transaction tr = db.TransactionManager.StartTransaction() )
} //if( per.Status == PromptStatus.OK )
} while( per.Status == PromptStatus.OK );
}
catch( System.Exception ex )
{
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( ex.ToString() );
}
}
Most important:
BlockReference blRef = ent as BlockReference;
...
SpatialFilter sf = tr.GetObject( fDict.GetAt( spatialName ), OpenMode.ForRead ) as SpatialFilter;
SpatialFilterDefinition sfd = sf.Definition;
var pts = sfd.GetPoints();
Matrix3d matBloku = sf.ClipSpaceToWorldCoordinateSystemTransform.PreMultiplyBy( sf.OriginalInverseBlockTransform ).PreMultiplyBy( blRef.BlockTransform );
...
Point2d p = RKGeometryczne.punkt3Dna2D( new Point3d( pts[i].X, pts[i].Y, 0 ).TransformBy( matBloku ) );
pln.AddVertexAt( pln.NumberOfVertices, p, 0, 0, 0 );