Author Topic: Object Reactor and vla-getBoundingBox issue  (Read 2395 times)

0 Members and 1 Guest are viewing this topic.

Red Nova

  • Newt
  • Posts: 69
Object Reactor and vla-getBoundingBox issue
« on: April 23, 2017, 11:45:18 PM »
I am using dynamic block with attribute to tag some other dynamic blocks.
Since content of the attribute might vary, the box surrounding the attribute must follow attribute's boundary.
Width of the box is controlled with a linear parameter inside the dynamic block.
I am trying to create a reactor that will automatically change linear parameter of the dynamic block whenever attribute is modified.
In fact I already created that reactor. I am using vla-getBoundingBox to get width of the attribute, and everything is OK until block has no rotation.
As you know, whenever block is rotated vla-getBoundingBox will return block's boundary in World coordinates, which will lead to a wrong result for me.
I know a few tricks that helped me before.
For example, when I am inserting a new block with some rotation I can rotate it to 0 deg. value, run vla-getBoundingBox, and then rotate the block back on it's place. I use vlax-put function for that. However, it appears that vlax-put does not work when I try to use it in my object reactor...
I tried couple functions as alternatives to vla-getBoundingBox that should return Bounding Box in any UCS, but again none of them worked in my reactor.
Can anybody tell me how to make vlax-put work in my reactor or is there any other way to solve the issue? Are reactors limiting functions that we can use?

Following lines in my "UpdateTagField" reactor are now commented, so the rest of the code can work. However, that means that reactor will apply wrong bounding box size to any block that has rotation properties different from 0. Please remove comments if you try to test it.

;(setq rot (vlax-get-property (nth 0 objlist) 'Rotation))
;(vlax-put (nth 1 objlist) 'Rotation 0)
(vla-getBoundingBox (nth 1 objlist) 'a 'b)
;(vlax-put (nth 1 objlist) 'Rotation rot)

Full code and an dwg file with blocks are attached.
I would appreciate your advises.



Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Object Reactor and vla-getBoundingBox issue
« Reply #1 on: April 24, 2017, 07:59:21 AM »
You can use the functions demonstrated here to obtain the width of the attribute reference.

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Object Reactor and vla-getBoundingBox issue
« Reply #2 on: April 24, 2017, 09:20:46 AM »

BTW,
If the text content is empty, i.e.: "", the boundingbox arguments will be null.
Code: [Select]
(and
  (setq e (car (entsel "\nSelect text: ")))
  (setq o (vlax-ename->vla-object e))
  (vla-put-TextString o "")
  (progn
    (vla-GetBoundingBox o 'll 'ur)
    (print ll) (print ur)
  )
)


Also got me thinking is it possible to modify the object from the callback function.
I tried this, but it fails:

Code - Auto/Visual Lisp: [Select]
  1. (defun OwnerTest:CB ( ownr rtr args )
  2.   ; Ok, heres the logic:
  3.   ; - The callback function wants to modify the object
  4.   ; - But if the object is modified it will trigger the ":vlr-modified" event, so it will run the callback function again
  5.   ; So, first remove the object from the list, modify it and reinclude it:
  6.   (vlr-owner-remove rtr ownr)
  7.   (vla-put-Layer ownr "0") ; setting values for the owner fails
  8.   ; (princ (strcat "\n" (vla-get-Layer ownr))) ; obtaining values from the owner works
  9.   (vlr-owner-add rtr ownr)
  10.   (princ)
  11. ); defun OwnerTest:CB
  12.  
  13.  
  14. (defun C:test ( / SS i Lowners rtr )
  15.   (cond
  16.     ( (setq SS (ssget "_:L-I"))
  17.       (repeat (setq i (sslength SS)) (setq Lowners (cons (vlax-ename->vla-object (ssname SS (setq i (1- i)))) Lowners)) )
  18.       (foreach rtr (cdar (vlr-reactors :VLR-Object-Reactor)) (if (= "OwnerTest" (vlr-data rtr)) (vlr-remove rtr)) ) ; Run once on startup
  19.       (VLR-Object-Reactor Lowners "OwnerTest" '((:vlr-modified . OwnerTest:CB)))
  20.     ); SS
  21.   ); cond
  22.   (princ)
  23. ); defun
  24.  

I think that my question is related to the problem (not trying to steal the thread).
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Red Nova

  • Newt
  • Posts: 69
Re: Object Reactor and vla-getBoundingBox issue
« Reply #3 on: April 24, 2017, 09:35:40 AM »
Thank you, Lee Mac. It works fine.  :-)
And for sure that's more professional than rotating the block like I did.
I wonder though why I could not use vlax-put in the reactor callback. It's the first time I tried a reactor and looks like they are picky...

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: Object Reactor and vla-getBoundingBox issue
« Reply #4 on: April 24, 2017, 10:36:52 AM »
Quote from: Lee Mac;418622
You can't modify the owner of the object reactor within the object reactor callback function for which that object is an owner. This would cause an infinite callback loop since the modification would fire the reactor, evaluating the callback function, triggering the reactor...

However, there is a workaround if you want to modify the owner of an object reactor within its own callback function: disable the object reactor within the object reactor callback function and create a command reactor triggered by the commandended event. Then, within the callback function of the command reactor, modify the owner and re-enable the object reactor, then remove the command reactor. This is the method I use to retain the position of the centerlines in this program.

Solution to my previous question:

Code - Auto/Visual Lisp: [Select]
  1. (defun OwnerTest:CB ( ownr rtr args )
  2.   (setq *Notifiers* (cons ownr *Notifiers*)) ; store to pass this list to the (EditorOwnerTest:CB), using list if multiple objects are modified at once
  3.   (vlr-owner-remove rtr ownr) ; remove the objects (from watching) (this is temporarily)
  4.   (princ (strcat "\n" (vla-get-Layer ownr))) ; display that this callback function is working
  5.   (princ)
  6. ); defun OwnerTest:CB
  7.  
  8. (defun EditorOwnerTest:CB ( rtr args )
  9.   (cond
  10.     (*Notifiers* ; check if theres list to process
  11.       (mapcar (function (lambda(x) (and (vlax-write-enabled-p x) (vla-put-Layer x "0")))) *Notifiers*) ; apply changes
  12.       (mapcar (function (lambda (x) (vlr-owner-add *Ortr* x))) *Notifiers*) ; reinclude the objects
  13.       (setq *Notifiers* nil) ; set the list to nil - so it won't stack, and to avoid redundant modifications
  14.     ); *Notifiers*
  15.   ); cond
  16.   (princ)
  17. ); defun EditorOwnerTest:CB
  18.  
  19.  
  20. (defun C:test ( / SS i Lowners rtr )
  21.   (cond
  22.     ( (setq SS (ssget "_:L-I"))
  23.       (repeat (setq i (sslength SS)) (setq Lowners (cons (vlax-ename->vla-object (ssname SS (setq i (1- i)))) Lowners)) )
  24.       (foreach rtr (cdar (vlr-reactors :VLR-Object-Reactor)) (if (= "OwnerTest" (vlr-data rtr)) (vlr-remove rtr)) )
  25.       (setq *Ortr* (VLR-Object-Reactor Lowners "OwnerTest" '((:vlr-modified . OwnerTest:CB)))) ; globalise it for the (EditorOwnerTest:CB)
  26.       (foreach rtr (cdar (vlr-reactors :VLR-Editor-Reactor)) (if (= "EditorOwnerTest" (vlr-data rtr)) (vlr-remove rtr)) )  
  27.       (VLR-Editor-Reactor "EditorOwnerTest" '((:vlr-commandEnded . EditorOwnerTest:CB)(:vlr-lispEnded . EditorOwnerTest:CB)))
  28.     ); SS
  29.   ); cond
  30.   (princ)
  31. ); defun C:test
  32.  



(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

Red Nova

  • Newt
  • Posts: 69
Re: Object Reactor and vla-getBoundingBox issue
« Reply #5 on: April 24, 2017, 11:16:47 AM »
Quote
You can't modify the owner of the object reactor within the object reactor callback function for which that object is an owner. This would cause an infinite callback loop since the modification would fire the reactor, evaluating the callback function, triggering the reactor...

That answers my question. Thanks  :-)