Author Topic: in ucs how to get BlockReference's GeometricExtents  (Read 312 times)

0 Members and 1 Guest are viewing this topic.

Tutulisper

  • Mosquito
  • Posts: 8
in ucs how to get BlockReference's GeometricExtents
« on: February 26, 2020, 11:01:16 AM »
in ucs how to get BlockReference's  real GeometricExtents

gile

  • Water Moccasin
  • Posts: 2251
  • Marseille, France
Re: in ucs how to get BlockReference's GeometricExtents
« Reply #1 on: February 26, 2020, 01:15:29 PM »
Hi,

GeometricExtents are always about WCS.
If you want the extents about the current UCS, you have to transform the BlockReference from UCS to WCS, get the extents and transform back the block reference and its extents to UCS.

Code - C#: [Select]
  1.         [CommandMethod("UCSBBOX")]
  2.         public static void GetExtentsAboutUcs()
  3.         {
  4.             var doc = Application.DocumentManager.MdiActiveDocument;
  5.             var db = doc.Database;
  6.             var ed = doc.Editor;
  7.             var peo = new PromptEntityOptions("\nSelect block reference: ");
  8.             peo.SetRejectMessage("\nSelected object is not a block reference.");
  9.             peo.AddAllowedClass(typeof(BlockReference), true);
  10.             var per = ed.GetEntity(peo);
  11.             if (per.Status != PromptStatus.OK)
  12.                 return;
  13.             var ucs = ed.CurrentUserCoordinateSystem;
  14.             using (var tr = db.TransactionManager.StartTransaction())
  15.             {
  16.                 var br = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForWrite);
  17.                 br.TransformBy(ucs.Inverse());
  18.                 var exts = br.GeometricExtents;
  19.                 using (var pline = new Polyline())
  20.                 {
  21.                     pline.AddVertexAt(0, new Point2d(exts.MinPoint.X, exts.MinPoint.Y), 0.0, 0.0, 0.0);
  22.                     pline.AddVertexAt(1, new Point2d(exts.MaxPoint.X, exts.MinPoint.Y), 0.0, 0.0, 0.0);
  23.                     pline.AddVertexAt(2, new Point2d(exts.MaxPoint.X, exts.MaxPoint.Y), 0.0, 0.0, 0.0);
  24.                     pline.AddVertexAt(3, new Point2d(exts.MinPoint.X, exts.MaxPoint.Y), 0.0, 0.0, 0.0);
  25.                     pline.Closed = true;
  26.                     pline.SetDatabaseDefaults();
  27.                     var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  28.                     btr.AppendEntity(pline);
  29.                     tr.AddNewlyCreatedDBObject(pline, true);
  30.                     pline.TransformBy(ucs);
  31.                 }
  32.                 br.TransformBy(ucs);
  33.                 tr.Commit();
  34.             }
  35.         }
Speaking English as a French Frog

Tutulisper

  • Mosquito
  • Posts: 8
Re: in ucs how to get BlockReference's GeometricExtents
« Reply #2 on: February 26, 2020, 10:03:50 PM »
thanks ,if i want get "Polyline" or "Line" in the BlockReference
how can i transform the Coordinate system。
Code - C#: [Select]
  1.  [LispFunction("Blkbox")]
  2.          public static ResultBuffer Blkbox(ResultBuffer rb)
  3.          {
  4.              Document curDoc = Application.DocumentManager.MdiActiveDocument;
  5.              Database db = HostApplicationServices.WorkingDatabase;
  6.              Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  7.  
  8.              if (rb == null) return null;
  9.              TypedValue[] tvValues = rb.AsArray();
  10.  
  11.              using (Transaction trans = db.TransactionManager.StartTransaction())
  12.              {
  13.  
  14.                  ResultBuffer result = new ResultBuffer();
  15.                  BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
  16.                  Entity ent = (Entity)trans.GetObject((ObjectId)tvValues[0].Value, OpenMode.ForRead);
  17.                  if (ent != null && ent.GetType() == typeof(BlockReference))
  18.                  {
  19.                      BlockReference br = (BlockReference)trans.GetObject((ObjectId)tvValues[0].Value, OpenMode.ForRead);
  20.                      string blkname = br.Name;
  21.                      ed.WriteMessage("\nBlock Name: (" + blkname + ").");
  22.                      ObjectId blockRecordId = bt[blkname];
  23.                      BlockTableRecord blockRecord = (BlockTableRecord)blockRecordId.GetObject(OpenMode.ForRead);
  24.                      Extents3d tmpExtents3D = new Extents3d();
  25.                      int num = 0;
  26.                      foreach (ObjectId entID in blockRecord)
  27.                      {
  28.                          Entity entity = (Entity)trans.GetObject(entID, OpenMode.ForRead);
  29.                          // string str = entity.GetType().Name;
  30.                         // get  "Polyline" or "Line"
  31.                          if (entity.GetType().Name == "Polyline" || entity.GetType().Name == "Line")
  32.                          {
  33.                              Extents3d tmp = entity.GeometricExtents;
  34.                              tmpExtents3D.AddExtents(tmp);
  35.                              num = num + 1;
  36.                          }
  37.                      }
  38.                      if (num > 0)
  39.                      {
  40.                          Point3d maxpt = tmpExtents3D.MaxPoint;
  41.                          Point3d minpt = tmpExtents3D.MinPoint;
  42.                          // Translate the OCS to WCS
  43.                          Matrix3d mt = br.BlockTransform;
  44.                          Point3d ptmax = maxpt.TransformBy(mt);
  45.                          Point3d ptmin = minpt.TransformBy(mt);
  46.                          result.Add(new TypedValue((int)LispDataType.Point3d, ptmax));
  47.                          result.Add(new TypedValue((int)LispDataType.Point3d, ptmin));
  48.                      }
  49.                      else
  50.                      {
  51.                          return null;
  52.  
  53.                      }
  54.  
  55.                  }
  56.  
  57.                  trans.Commit();
  58.                  return result;
  59.              }
  60.  
  61.          }
  62.  
« Last Edit: February 26, 2020, 10:15:22 PM by Tutulisper »

gile

  • Water Moccasin
  • Posts: 2251
  • Marseille, France
Re: in ucs how to get BlockReference's GeometricExtents
« Reply #3 on: February 27, 2020, 02:17:32 AM »
I'm not sure to understand what you try to achieve but here's an example to get the UCS coordinates of  the extents about UCS of lines and polylines contained in the block reference.

Code - C#: [Select]
  1.         [LispFunction("Blkbox")]
  2.         public static ResultBuffer Blkbox(ResultBuffer rb)
  3.         {
  4.             // validation of the LISP argument
  5.             if (rb == null) return null;
  6.             TypedValue[] tvValues = rb.AsArray();
  7.             if (1 < tvValues.Length) return null;
  8.             if (tvValues[0].TypeCode != (int)LispDataType.ObjectId) return null;
  9.             ObjectId id = (ObjectId)tvValues[0].Value;
  10.             if (id.ObjectClass.DxfName != "INSERT") return null;
  11.  
  12.             Document curDoc = Application.DocumentManager.MdiActiveDocument;
  13.             Database db = HostApplicationServices.WorkingDatabase;
  14.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  15.             Matrix3d ucs2wcs = ed.CurrentUserCoordinateSystem;
  16.             Matrix3d wcs2ucs = ucs2wcs.Inverse();
  17.  
  18.             using (Transaction trans = db.TransactionManager.StartTransaction())
  19.             {
  20.                 ResultBuffer result = new ResultBuffer();
  21.                 BlockReference br = (BlockReference)trans.GetObject(id, OpenMode.ForRead);
  22.                 string blkname = br.Name;
  23.                 ed.WriteMessage("\nBlock Name: (" + blkname + ").");
  24.  
  25.                 using (DBObjectCollection entitySet = new DBObjectCollection())
  26.                 {
  27.                     br.Explode(entitySet);
  28.                     Extents3d tmpExtents3D = new Extents3d();
  29.                     int num = 0;
  30.                     foreach (Entity entity in entitySet)
  31.                     {
  32.                         // get  "Polyline" or "Line"
  33.                         if (entity is Polyline || entity is Line)
  34.                         {
  35.                             entity.TransformBy(wcs2ucs);
  36.                             tmpExtents3D.AddExtents(entity.GeometricExtents);
  37.                             num++;
  38.                         }
  39.                         entity.Dispose();
  40.                     }
  41.                     if (0 < num)
  42.                     {
  43.                         result.Add(new TypedValue((int)LispDataType.Point3d, tmpExtents3D.MinPoint));
  44.                         result.Add(new TypedValue((int)LispDataType.Point3d, tmpExtents3D.MaxPoint));
  45.                     }
  46.                 }
  47.                 trans.Commit();
  48.                 return result;
  49.             }
  50.         }

To test the result:
Code - Auto/Visual Lisp: [Select]
  1. (setq bbox (blkbox (car (entsel))))
  2. (command "_.rectang" "_non" (car bbox) "_non" (cadr bbox))

But all this can be done directly with LISP, here's an example:
Code - Auto/Visual Lisp: [Select]
  1. ;; gc:TMatrixFromTo
  2. ;; Returns the (4x4) transformation matrix from a coordinate system to another one
  3. ;; (same arguments type as 'trans')
  4. ;;
  5. ;; Arguments
  6. ;; from : source coordinate system (integer, vector or ename)
  7. ;; to : destination coordinate system (integer, vector or ename)
  8. (defun gc:TMatrixFromTo (from to)
  9.   (append
  10.     (mapcar
  11.       (function
  12.         (lambda (v o)
  13.           (append (trans v from to T) (list o))
  14.         )
  15.       )
  16.       '((1. 0. 0.) (0. 1. 0.) (0. 0. 1.))
  17.       (trans '(0. 0. 0.) to from)
  18.     )
  19.     '((0. 0. 0. 1.))
  20.   )
  21. )
  22.  
  23. ;; gc:UcsBoundingBox
  24. ;; Returns the UCS coordinates of the entity extents (bounding box)
  25. ;; about the current UCS
  26. ;;
  27. ;; Arguments
  28. ;; obj: an entity (ENAME or VLA-OBJCET)
  29. ;; _OutputMinPtSym: a quoted symbol (output)
  30. ;; _OutputMaxPtSym: a quoted symbol (output)
  31.  
  32. (defun gc:UcsBoundingBox (obj _OutputMinPtSym _OutputMaxPtSym)
  33.   (and (= (type obj) 'ENAME)
  34.        (setq obj (vlax-ename->vla-object obj))
  35.   )
  36.   (vla-TransformBy obj (vlax-tmatrix (gc:TMatrixFromTo 1 0)))
  37.   (vla-GetBoundingBox obj _OutputMinPtSym _OutputMaxPtSym)
  38.   (vla-TransformBy obj (vlax-tmatrix (gc:TMatrixFromTo 0 1)))
  39.   (set _OutputMinPtSym (vlax-safearray->list (eval _OutputMinPtSym)))
  40.   (set _OutputMaxPtSym  (vlax-safearray->list (eval _OutputMaxPtSym)))
  41. )

using:
Code - Auto/Visual Lisp: [Select]
  1. (gc:UcsBoundingBox (car (entsel)) 'minPt 'maxPt)
  2. (command "_.rectang" "_non" minPt "_non" maxPt)
Speaking English as a French Frog

Tutulisper

  • Mosquito
  • Posts: 8
Re: in ucs how to get BlockReference's GeometricExtents
« Reply #4 on: February 27, 2020, 03:04:23 AM »
thank you!
your code is very nice and Solved the problem
for some BlockReference it can not get the "GetBoundingBox" so it's only to go inside the BlockReference to get it.
« Last Edit: February 27, 2020, 11:38:10 AM by Tutulisper »