how to get geometric extents of a nested block reference?

how to get geometric extents of a nested block reference?

a.kouchakzadeh
Advocate Advocate
597 Views
6 Replies
Message 1 of 7

how to get geometric extents of a nested block reference?

a.kouchakzadeh
Advocate
Advocate

Hi and wish every one a peaceful year.

 

Im confused with blkRef.BlockTransform concept.

 

I have a block reference which is nested.

I use GetNestedEntity to select a nested entity but Im only interested in the block references. so I would use the GetContainer method.

 

but Im not getting the right geometric extents.

what am I doing wrong?

using (Transaction tr = db.TransactionManager.StartTransaction())
{
    var pner = ed.GetNestedEntity("\nSelect block - possibly nested");
    if (pner.Status != PromptStatus.OK)
        return;
    var objIds = pner.GetContainers().ToList();
    if (objIds is null)
        return;
    if (objIds.Count == 0)
        return;

    var child = tr.GetObject(objIds[0], OpenMode.ForRead) as BlockReference;
    var parent = tr.GetObject(objIds[objIds.Count-1], OpenMode.ForRead) as BlockReference;

    var pl = StandardColumnCreator(child, parent.BlockTransform);
    var md = tr.GetObject(db.CurrentSpaceId,OpenMode.ForWrite) as BlockTableRecord;
    md.AppendEntity(pl);
    tr.AddNewlyCreatedDBObject(pl, true);
    tr.Commit();
}

 

private static Polyline StandardColumnCreator(Entity rawEntity, Matrix3d? transform = null)
{
    var extents = rawEntity.GeometricExtents;
    var point1 = extents.MinPoint;
    var point2 = extents.MaxPoint;
    if (transform.HasValue)
    {
        point1 = point1.TransformBy(transform.Value);
        point2 = point2.TransformBy(transform.Value);
    }
    var minPoint = new Point2d(
        point1.X < point2.X ? point1.X : point2.X, point1.Y < point2.Y ? point1.Y : point2.Y);
    var maxPoint = new Point2d(
        point1.X > point2.X ? point1.X : point2.X, point1.Y > point2.Y ? point1.Y : point2.Y);

    var rectanglePolyline = new Polyline();
    rectanglePolyline.AddVertexAt(0, minPoint, 0, 0, 0);
    rectanglePolyline.AddVertexAt(1, new Point2d(maxPoint.X, minPoint.Y), 0, 0, 0);
    rectanglePolyline.AddVertexAt(2, maxPoint, 0, 0, 0);
    rectanglePolyline.AddVertexAt(3, new Point2d(minPoint.X, maxPoint.Y), 0, 0, 0);
    rectanglePolyline.Closed = true;
    return rectanglePolyline;
}
0 Likes
Accepted solutions (1)
598 Views
6 Replies
Replies (6)
Message 2 of 7

ActivistInvestor
Mentor
Mentor

It would be easier to draw the polyline in the same coordinate system as the nested insertion, and then transform it to the current UCS using the BlockTransform of the owning or parent BlockReference.

 

public static class NestedExtentsExample
{
   [CommandMethod("STDCOL")]
   public static void CommandMethod()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      var ed = doc.Editor;
      using(Transaction tr = db.TransactionManager.StartTransaction())
      {
         var pner = ed.GetNestedEntity("\nSelect block - possibly nested");
         if(pner.Status != PromptStatus.OK)
            return;
         var objIds = pner.GetContainers();
         if(objIds is null || objIds.Length == 0)
            return;
         BlockReference parent = null;
         if(objIds.Length > 1)
            parent = tr.GetObject(objIds[1], OpenMode.ForRead) as BlockReference;
         var blkref = tr.GetObject(objIds[0], OpenMode.ForRead) as BlockReference;
         var pl = StandardColumnCreator(blkref, parent);
         var btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
         btr.AppendEntity(pl);
         tr.AddNewlyCreatedDBObject(pl, true);
         tr.Commit();
      }
   }

   static Polyline PolylineFromExtents(Extents3d ext)
   {
      var min = ext.MinPoint;
      var max = ext.MaxPoint;
      var p2 = new Point3d(max.X, min.Y, 0.0);
      var p4 = new Point3d(min.X, max.Y, 0.0);
      var pline = (Polyline)
         Curve.CreateFromGeCurve(
            new CompositeCurve3d(
               new LineSegment3d[]{
                  new LineSegment3d(min, p2),
                  new LineSegment3d(p2, max),
                  new LineSegment3d(max, p4) }));
      pline.Closed = true;
      return pline;
   }

   static Polyline StandardColumnCreator(Entity rawEntity, BlockReference parent = null)
   {
      var blockref = rawEntity as BlockReference;
      if(parent is not null && blockref is not null)
         return PolylineFromExtents(blockref.GeometryExtentsBestFit(parent.BlockTransform));
      Extents3d extents;
      if(blockref is not null)
         extents = blockref.GeometryExtentsBestFit();
      else
         extents = rawEntity.GeometricExtents;
      var pline = PolylineFromExtents(extents);
      if(parent is not null)
         pline.TransformBy(parent.BlockTransform);
      return pline;
   }
}

 

 

0 Likes
Message 3 of 7

a.kouchakzadeh
Advocate
Advocate

Thanks for the reply

I have 3 blocks "c1" nested in "c2" and "c2" nested in "c3";

when I select c1 , the bounding box polyline is drawn in the area I have marked in the picture.

which is the bounding box of "c1" IF inserted on (0,0,0) with scale factor 1. 

I'm confused with blocktransform because I thought its suppose to give me the point of the block reference.

how can I get the actual bounding box of the nested "c1" ?

 

Capture.JPG

0 Likes
Message 4 of 7

ActivistInvestor
Mentor
Mentor

I'm assuming you ran the test code I posted above. That code should create the bounding polyline of the most-deeply-nested block reference whose definition contains the nested entity that was selected.

 

If you're not getting that result, please post the drawing you cited above where the result was not what you expected, and I will have a look at it.

0 Likes
Message 5 of 7

ActivistInvestor
Mentor
Mentor
Accepted solution

The example above doesn't deal with deeply-nested insertions, which requires a slightly-different approach.

 

This one should work with insertions nested to any depth:

 

 

public static class NestedExtentsExample
{
   [CommandMethod("STDCOL")]
   public static void CommandMethod()
   {
      Document doc = Application.DocumentManager.MdiActiveDocument;
      Database db = doc.Database;
      var ed = doc.Editor;
      using(Transaction tr = db.TransactionManager.StartTransaction())
      {
         var pner = ed.GetNestedEntity("\nSelect block - possibly nested");
         if(pner.Status != PromptStatus.OK)
            return;
         var objIds = pner.GetContainers();
         if(objIds is null || objIds.Length == 0)
            return;
         var pl = StandardColumnCreator(tr, objIds[0], pner.Transform);
         var btr = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
         btr.AppendEntity(pl);
         tr.AddNewlyCreatedDBObject(pl, true);
         tr.Commit();
      }
   }

   static Polyline PolylineFromExtents(Extents3d ext)
   {
      var min = ext.MinPoint;
      var max = ext.MaxPoint;
      var p2 = new Point3d(max.X, min.Y, 0.0);
      var p4 = new Point3d(min.X, max.Y, 0.0);
      var pline = (Polyline)
         Curve.CreateFromGeCurve(
            new CompositeCurve3d(
               new LineSegment3d[]{
                  new LineSegment3d(min, p2),
                  new LineSegment3d(p2, max),
                  new LineSegment3d(max, p4) }));
      pline.Closed = true;
      return pline;
   }

   private static Polyline StandardColumnCreator(Transaction tr, ObjectId blockrefId, Matrix3d xform)
   {
      if(blockrefId.IsNull)
         throw new ArgumentException(nameof(blockrefId));
      var blkref = (BlockReference)tr.GetObject(blockrefId, OpenMode.ForRead);
      var btr = (BlockTableRecord) tr.GetObject(blkref.BlockTableRecord, OpenMode.ForRead);
      Extents3d extents = new Extents3d();
      extents.AddBlockExtents(btr);
      Polyline pline = PolylineFromExtents(extents);
      pline.TransformBy(xform);
      return pline;
   }

}

 

0 Likes
Message 6 of 7

a.kouchakzadeh
Advocate
Advocate

prefect. that did the trick.

can you explain what does AddBlockExtents(btr) do?

0 Likes
Message 7 of 7

ActivistInvestor
Mentor
Mentor

It adds the extents of all entities in the block. 

0 Likes