TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: mailmaverick on April 03, 2017, 05:06:54 AM

Title: Min Bounding Box of INSERT
Post by: mailmaverick on April 03, 2017, 05:06:54 AM
Hi All,

I am using Minimum Bounding Box function as given at : http://lee-mac.com/minboundingbox.html
for constructing Minimum Bounding Box of a text Attribute within a Block.

First Image : My Block.
Second Image : The Bounding Box which I get.
Third Image : The Bounding Box which I want.

AutoCAD Drawing is also attached.
Title: Re: Min Bounding Box of INSERT
Post by: ribarm on April 03, 2017, 11:18:15 AM
See can this be of some help :
https://www.theswamp.org/index.php?topic=50205.0
Title: Re: Min Bounding Box of INSERT
Post by: mailmaverick on April 05, 2017, 02:24:02 AM
Dear Marko

It also gives the same result as Lee's code but not as per requirement.
Title: Re: Min Bounding Box of INSERT
Post by: ChrisCarlson on April 05, 2017, 08:07:39 AM
How would you want to accomplish this? It's certainly doable, I would figure out how to get the height of the attribute first, then apply an offset factor perpendicular to the orientation (your text is 3.3071mm tall but the bounding box appears to be slightly larger), find the intersections, and lastly create the box.
Title: Re: Min Bounding Box of INSERT
Post by: ronjonp on April 05, 2017, 09:28:31 AM
Dear Marko

It also gives the same result as Lee's code but not as per requirement.
I believe it's because you have a dynamic rotation parameter & the actual rotation of the block is 0.
Title: Re: Min Bounding Box of INSERT
Post by: mailmaverick on April 05, 2017, 12:32:55 PM
Dear Marko

It also gives the same result as Lee's code but not as per requirement.
I believe it's because you have a dynamic rotation parameter & the actual rotation of the block is 0.

Dear Marko

If I Change the Dynamic Rotation Parameter to 0 and give the rotation value to the Rotation of the block, it works fine.
Now my other problem, I want the bounding box of the text part only which is much smaller than the line. Sorry for my mistake in my original question, I want bounding Box of only the text part, without the line.
Title: Re: Min Bounding Box of INSERT
Post by: maratovich on April 05, 2017, 01:33:51 PM
mailmaverick
Done

Due diligence:
kdub: Zip file containing .EXE file removed. 2017-04-06
Title: Re: Min Bounding Box of INSERT
Post by: ronjonp on April 05, 2017, 01:46:50 PM
@mailmaverick .. I'd be careful if I were you...
Title: Re: Min Bounding Box of INSERT
Post by: maratovich on April 05, 2017, 01:57:15 PM
@mailmaverick .. I'd be careful if I were you...
Here too ?
Title: Re: Min Bounding Box of INSERT
Post by: ronjonp on April 05, 2017, 01:59:48 PM
@mailmaverick .. I'd be careful if I were you...
Here too ?
It's just me .. new member + 1 post + exe = wary Ron.
Title: Re: Min Bounding Box of INSERT
Post by: ChrisCarlson on April 05, 2017, 02:07:09 PM
mailmaverick
Done

Post the source?
Title: Re: Min Bounding Box of INSERT
Post by: maratovich on April 05, 2017, 02:09:19 PM
 :-)
Created on VB6, analogue of the VBA therefore = exe
Main thing is that the author could solve problem.
Waiting for author's reply to  topic.

Code: [Select]
Private Sub CommandStart_Click()
On Error Resume Next
'-------------------+
Dim I As Long
Dim ii As Long
Dim VseBloki
Dim ImiaBloka As String
Dim ObiektiDlaVibora
Dim NovyBlok
Dim VstavitBlok
Dim VibranieObiekti
Dim VibranyiObiekti() As Object
Dim minExt As Variant
Dim maxExt As Variant
Dim BlokModel As Object
Dim Vsegotext As Long
Dim NameObject As String
Dim MassivDannih
Dim MassivDannih2
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant
Dim TochkaVstavkiBloka(0 To 2) As Double
Dim BX As Double
Dim BY As Double
Dim BZ As Double
Dim oBlk 'As IAcadBlockReference2
Dim oProps As Variant
Dim oDblkProp
Dim vPick As Variant
Dim points(0 To 7) As Double
Dim plineObj 'As AcadPolyline
Dim VstavitBlokRotation As Double
Dim VstavitBlokZerkalo As Double
Dim point1(0 To 2) As Double
Dim CoordPoint As Variant
Dim mirrorObj
'----------------------------------------------------------------------------------+
'----------------------------------------------------------------------------------+
'проверка открыт ли CAD
StartCAD 'запуск или подключение к каду
If CADPodklusen <> True Then Exit Sub
'----------------------------------------------------------------------------------+
'----------------------------------------------------------------------------------+
'создаем блок
Set ObiektiDlaVibora = ThisDrawing.SelectionSets
For Each VibranieObiekti In ObiektiDlaVibora
If VibranieObiekti.Name = "VremeniiNabor" Then
'набор объектов
ThisDrawing.SelectionSets.Item("VremeniiNabor").Delete
Exit For
End If
Next
'определить новый набор объектов
Set VibranieObiekti = ThisDrawing.SelectionSets.Add("VremeniiNabor")
'выбрать на экране объекты
'----------------------------------------------------------------------------------+
'Перейти в Кад
DoEvents
DoEvents
AppActivate acad.Caption 'активировать кад
DoEvents
DoEvents
'----------------------------------------------------------------------------------+
FilterType(0) = 0
FilterData(0) = "INSERT"
VibranieObiekti.SelectOnScreen FilterType, FilterData
If Err Then Err.Clear:  Exit Sub
If VibranieObiekti.Count - 1 = -1 Then
MsgBox "Selection empty !", vbExclamation
Exit Sub
End If
'----------------------------------------------------------------------------------+
'----------------------------------------------------------------------------------+
Dim oBlockRef 'As AcadBlockReference
For Each BlokModel In VibranieObiekti ' перебор объектов в наборе
   NameObject = BlokModel.ObjectName
   If NameObject = "AcDbBlockReference" Then
      Dim Block
      Set Block = BlokModel
      ImiaBloka = BlokModel.Effectivename
      'вставить блок в модель
      Set VstavitBlok = ThisDrawing.ModelSpace.InsertBlock(Block.insertionPoint, ImiaBloka, Block.XScaleFactor, Block.YScaleFactor, Block.ZScaleFactor, 0)
      '----------------------------------------------------------------------------------+
      oProps = VstavitBlok.GetDynamicBlockProperties
      For I = 0 To UBound(oProps)
          Set oDblkProp = oProps(I)
          If oDblkProp.PropertyName = "Angle" Then
              VstavitBlokRotation = oDblkProp.Value '= Atn(1) '45 degree angle
          End If
      Next
      '----------------------------------------------------------------------------------+
      VstavitBlok.GetBoundingBox minExt, maxExt
      points(0) = minExt(0)
      points(1) = minExt(1)
      points(2) = maxExt(0)
      points(3) = minExt(1)
      points(4) = maxExt(0)
      points(5) = maxExt(1)
      points(6) = minExt(0)
      points(7) = maxExt(1)
      Set plineObj = ThisDrawing.ModelSpace.AddLightWeightPolyline(points)
      plineObj.Closed = True
      '----------------------------------------------------------------------------------+
      oProps = Block.GetDynamicBlockProperties
      For I = 0 To UBound(oProps)
          Set oDblkProp = oProps(I)
          If oDblkProp.PropertyName = "Angle" Then
              plineObj.Rotate Block.insertionPoint, oDblkProp.Value - VstavitBlokRotation
          End If
          If oDblkProp.PropertyName = "Flip state" Then
              VstavitBlokZerkalo = oDblkProp.Value
          End If
      Next
      '----------------------------------------------------------------------------------+
      If VstavitBlokZerkalo = 1 Then
         CoordPoint = Block.insertionPoint
         point1(0) = CoordPoint(0): point1(1) = CoordPoint(1) + 1: point1(2) = CoordPoint(2)
         Set mirrorObj = plineObj.Mirror(Block.insertionPoint, point1) 'Определите зеркальную ось
         plineObj.erase
      End If
      VstavitBlok.erase
   End If
Next
'----------------------------------------------------------------------------------+
'----------------------------------------------------------------------------------+
'указать точку вставки блока
'Перейти в Кад
DoEvents
DoEvents
AppActivate acad.Caption 'активировать кад
DoEvents
DoEvents
'----------------------------------------------------------------------------------+
MsgBox "Ok!", vbSystemModal + vbInformation
'----------------------------------------------------------------------------------+
End Sub
Title: Re: Min Bounding Box of INSERT
Post by: CAB on April 05, 2017, 07:31:33 PM
The point is it is irresponsible to run an EXE file from an unknown source on your computer.
Who knows what malicious software could be installed.
You would be a fool to run it at work.

WARNING - RUN EXE FILES AT YOUR OWN RISK!
Title: Re: Min Bounding Box of INSERT
Post by: MP on April 05, 2017, 11:14:13 PM
I'm surprised the attachments remain intact. Due diligence is far more important than worrying about stepping on new toes.
Title: Re: Min Bounding Box of INSERT
Post by: Refri on April 06, 2017, 12:04:22 AM
Why deleted?
If you are afraid of a black cat in a black room - install an antivirus. (I will reveal the secret - there is no cat in the room)
Where can I get the file to check the result?
Title: Re: Min Bounding Box of INSERT
Post by: kdub_nz on April 06, 2017, 12:22:32 AM
Refri,

Thanks for your comments.
Perhaps you could send a Personal Message to the supplier and give him your email address.

Generally we are wary of executable and compiled files being distributed here.
The Swamp is primarily a resource for peer support and as such we prefer code postings are source code ( or source snippets).

Unfortunately the potential dangers in VB6 EXE files or compiled lisp files is not discoverable by a virus scan.

Personally I find teaching/helping users code (and find solutions) for themselves  more rewarding for everyone  than turning the site into a dumping ground for anonymous unsecured programs.

Regards,
Kerry
Title: Re: Min Bounding Box of INSERT
Post by: mailmaverick on April 06, 2017, 12:42:39 AM
Hi

Maratovich's solution seems OK but I need the LISP code, not VB6.
Also, I need bounding box of only the Text Part "JJ-1" and not the entire block.
Thanks.
Title: Re: Min Bounding Box of INSERT
Post by: ronjonp on April 06, 2017, 09:13:34 AM
Hi
...
Also, I need bounding box of only the Text Part "JJ-1" and not the entire block.
...
You should revise your example picture in the first post "Third Image : The Bounding Box which I want"  .. the current one shows the desired result as the entire block bounding box.
Title: Re: Min Bounding Box of INSERT
Post by: ChrisCarlson on April 06, 2017, 10:04:01 AM
Hi

Maratovich's solution seems OK but I need the LISP code, not VB6.
Also, I need bounding box of only the Text Part "JJ-1" and not the entire block.
Thanks.

Couldn't that just be summed up to

Code - Auto/Visual Lisp: [Select]

and

Code - Auto/Visual Lisp: [Select]
  1. vlax-safeArray->list
Title: Re: Min Bounding Box of INSERT
Post by: maratovich on April 06, 2017, 11:37:09 AM
 :whistling:
Title: Re: Min Bounding Box of INSERT
Post by: mailmaverick on April 06, 2017, 11:38:03 AM
Master_Shake,

Since the text attribute is within a Block (which is not exploded), we cannot use vla-getBoundingBox function on it.
It gives following error :- "Automation Error. Null extents".
Title: Re: Min Bounding Box of INSERT
Post by: MP on April 06, 2017, 12:14:24 PM
Master_Shake,

Since the text attribute is within a Block (which is not exploded), we cannot use vla-getBoundingBox function on it.
It gives following error :- "Automation Error. Null extents".

Not true. My guess is you're encountering an attribute with no textstring assigned. You merely need to trap the attempt to get said bounding box and branch accordingly.

Code: [Select]
(defun _GetBoundingBox ( object / a b )
    (vl-catch-all-apply 'vlax-invoke-method (list object 'GetBoundingBox 'a 'b))
    (if a (mapcar 'vlax-safearray->list (list a b)))
)

(if (setq bb (_GetBoundingBox obj))
    (then)
    (else)
)
Title: Re: Min Bounding Box of INSERT
Post by: Lee Mac on April 06, 2017, 12:36:00 PM
Since you're only looking for the bounding box of the attribute reference, here is a Vanilla solution to consider:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:test ( / ent enx idx sel )
  2.     (if (setq sel (ssget '((0 . "INSERT") (66 . 1))))
  3.         (repeat (setq idx (sslength sel))
  4.             (setq ent (entnext (ssname sel (setq idx (1- idx))))
  5.                   enx (entget ent)
  6.             )
  7.             (while (= "ATTRIB" (cdr (assoc 0 enx)))
  8.                 (entmake
  9.                     (append
  10.                        '(
  11.                             (000 . "LWPOLYLINE")
  12.                             (100 . "AcDbEntity")
  13.                             (100 . "AcDbPolyline")
  14.                             (090 . 4)
  15.                             (070 . 1)
  16.                         )
  17.                         (list (cons 38 (cadddr (assoc 10 enx))))
  18.                         (mapcar '(lambda ( p ) (cons 10 p)) (LM:textbox ent))
  19.                         (list (assoc 210 enx))
  20.                     )
  21.                 )
  22.                 (setq ent (entnext ent)
  23.                       enx (entget  ent)
  24.                 )
  25.             )
  26.         )
  27.     )
  28.     (princ)
  29. )
  30.  
  31. ;; Text Box  -  Lee Mac
  32. ;; A wrapper for the textbox function to return the bounding box of a Text or Attrib (in OCS)
  33.  
  34. (defun LM:textbox ( ent / ins mat rot )
  35.     (setq ent (entget ent)
  36.           ins (cdr (assoc 10 ent))
  37.           rot (cdr (assoc 50 ent))
  38.           mat (list
  39.                   (list (cos rot) (sin (- rot)) 0.0)
  40.                   (list (sin rot) (cos rot)     0.0)
  41.                  '(0.0 0.0 1.0)
  42.               )
  43.     )
  44.     (mapcar '(lambda ( x ) (mapcar '+ (mxv mat x) ins)) (LM:points->boundingbox (textbox ent)))
  45. )
  46.  
  47. ;; Points to Bounding Box  -  Lee Mac
  48. ;; Returns the rectangular extents of a supplied point list
  49.  
  50. (defun LM:points->boundingbox ( lst )
  51.     (   (lambda ( l )
  52.             (mapcar '(lambda ( a ) (mapcar '(lambda ( b ) ((eval b) l)) a))
  53.                '(
  54.                     (caar   cadar)
  55.                     (caadr  cadar)
  56.                     (caadr cadadr)
  57.                     (caar  cadadr)
  58.                 )
  59.             )
  60.         )
  61.         (mapcar '(lambda ( f ) (apply 'mapcar (cons f lst))) '(min max))
  62.     )
  63. )
  64.  
  65. ;; Matrix x Vector  -  Vladimir Nesterovsky
  66. ;; Args: m - nxn matrix, v - vector in R^n
  67.  
  68. (defun mxv ( m v )
  69.     (mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)
  70. )
  71.  
Title: Re: Min Bounding Box of INSERT
Post by: ronjonp on April 06, 2017, 12:39:22 PM
Very nice Lee  8)
Title: Re: Min Bounding Box of INSERT
Post by: Lee Mac on April 06, 2017, 12:41:38 PM
Thanks Ron  :-)
Title: Re: Min Bounding Box of INSERT
Post by: mailmaverick on April 06, 2017, 01:18:22 PM
Once again Lee Mac to the rescue. Your code works perfect.
Thanks a lot Lee.
Title: Re: Min Bounding Box of INSERT
Post by: Grrr1337 on April 06, 2017, 02:36:25 PM
I like your subfunctions Lee,
Although for LM:points->boundingbox wouldnt a more adequate function naming be LM:points->4ptboundingbox ?
Title: Re: Min Bounding Box of INSERT
Post by: Lee Mac on April 06, 2017, 04:54:37 PM
Once again Lee Mac to the rescue. Your code works perfect.
Thanks a lot Lee.

You're welcome mailmaverick, I'm glad it helps.

I like your subfunctions Lee,
Although for LM:points->boundingbox wouldnt a more adequate function naming be LM:points->4ptboundingbox ?

Thanks Grrr1337; the boundingbox is rectangular hence 4 points is implied.  :-)