Author Topic: xData or lData  (Read 6347 times)

0 Members and 1 Guest are viewing this topic.

Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
xData or lData
« on: July 05, 2009, 08:22:42 AM »
I am currently working on the LISP as shown below - it will "pair" a block with a Polyline, and record the number of block instances and polyline width and height in the attributes of the block.

I have used xData to store the handles of both the Block and polyline, but is there any advantage in using lData over xData? What are the differences between the two?

Also, I have studied Andrea's DLeader LISP and based my reactor on it - using a command reactor and reacting to grip transformations. But I think it would be better to use an Object Reactor, as this accounts for more modifications - but I can't see how I can use one, as you need a list of VLA-Objects to monitor, so I think I would have to keep removing and re-building the reactor upon every use of the program. If anyone knows another way to achieve this goal, help would be appreciated.

Code: [Select]
(defun c:blkUpd (/ ins wid hgt blk bEnt bObj
                   pEnt pObj MiP MaP win num )
  (vl-load-com)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name

  (if
    (and
      (setq bEnt
        (car (entsel "\nSelect Block: ")))
      (eq "AcDbBlockReference"
          (vla-get-ObjectName
            (setq bObj
              (vlax-ename->vla-object bEnt))))
      (eq (vla-get-HasAttributes bObj) :vlax-true)
      (eq (strcase blk) (strcase (vla-get-Name bObj)))
      (setq pEnt
        (car (entsel "\nSelect Polyline: ")))
      (wcmatch
        (cdr (assoc 0 (entget pEnt))) "*POLYLINE"))
    (progn
      (vla-getBoundingBox
        (setq pObj
          (vlax-ename->vla-object pEnt)) 'MiP 'MaP)
      (mapcar
        (function
          (lambda (Obj)
            (putxdat Obj "LMACUPD"
              (vl-prin1-to-string
                (list
                  (vla-get-Handle pObj)
                    (vla-get-Handle bObj)))))) (list pObj bObj))
      (setq win (mapcar 'vlax-safearray->list (list MiP MaP))
            num (sslength
                  (ssget "_X"
                    (list
                      (cons 0 "INSERT")
                        (cons 2 (vla-get-Name bObj))
                          (cons 66 1)))))            
      (foreach Att (vlax-safearray->list
                     (vlax-variant-value
                       (vla-getAttributes bObj)))
        (cond
          ((eq ins (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos num 2 0)))
          ((eq Wid (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (caadr win) (caar win)) 2 2)))
          ((eq Hgt (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (cadadr win) (cadar win)) 2 2))))))
    (princ "\n<< Incorrect Selection >>"))
  (princ))

(defun BlkUpdr (Reac Args / ins wid hgt blk ss xtyp xval hand
                            pObj MiP MaP bObj win num)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name
  
  (if (vl-position
        (car Args)
          '("GRIP_STRETCH"
            "GRIP_MOVE"
            "GRIP_SCALE"
            "GRIP_ROTATE"))
    (if (setq ss (cadr (ssgetfirst)))
      (progn
        (vla-getXdata
          (vlax-ename->vla-object
            (ssname ss 0)) "LMACUPD" 'xtyp 'xval)
        (if (and xtyp xval)
          (progn
            (setq hand
              (mapcar 'handent
                (read
                  (vlax-variant-value
                    (cadr
                      (vlax-safearray->list xval))))))
            (vla-getBoundingBox
              (setq pObj
                (vlax-ename->vla-object (car hand))) 'MiP 'MaP)
            (setq bObj (vlax-ename->vla-object (cadr hand))
                  win (mapcar 'vlax-safearray->list (list MiP MaP))
                  num (sslength
                        (ssget "_X"
                          (list
                            (cons 0 "INSERT")
                              (cons 2 (vla-get-Name bObj))
                                (cons 66 1)))))
            (foreach Att (vlax-safearray->list
                           (vlax-variant-value
                             (vla-getAttributes bObj)))
              (cond
                ((eq ins (vla-get-TagString Att))
                 (vla-put-TextString Att
                   (rtos num 2 0)))
                ((eq Wid (vla-get-TagString Att))
                 (vla-put-TextString Att
                   (rtos
                     (- (caadr win) (caar win)) 2 2)))
                ((eq Hgt (vla-get-TagString Att))
                 (vla-put-TextString Att
                   (rtos
                     (- (cadadr win) (cadar win)) 2 2)))))))))))          

(defun putxdat (Obj App Data / ent type1 valeur)

  (setq xtype
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbInteger '(0 . 1)) '(1001 1000))))

  (setq xval
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbVariant '(0 . 1)) (list App Data))))

  (vla-setXData Obj xtype xval))

(if *lmac-Block*
  (vlr-remove *lmac-Block*)
  (setq *lmac-Block* nil))
(setq *lmac-Block*
  (vlr-command-Reactor nil
    (list
      (cons :vlr-CommandEnded 'BlkUpdr))))


CAB

  • Global Moderator
  • Seagull
  • Posts: 10362
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

gile

  • Water Moccasin
  • Posts: 2224
  • Marseille, France
Re: xData or lData
« Reply #2 on: July 05, 2009, 08:55:29 AM »
Hi,

While you are using object reactors, you can store datas in the reactor data too.

About xdatas and ldatas, I read sometimes ldatas have a very bad reputation, but I keep on using them beacause it's much more easy and concise.
AFAIK their bad reputation is due to 2 things :
- They don't support AutoCAD release upgrades. By my side, I never had this kind of problem. Perhaps it was a problem with the first Visual LISP releases (2000 to 2002) which was quite instable.
- The other thing is that ldatas can only be read by LISP (xdatas, xrecords, dictionaries are accessible with every language). So for using with Visual LISP reactors, I do use ldatas instead of xdatas or standard dictionaries, as here where some datas (the rectangle coordinates) are stored in the object reactor data and some others (all rectangle handles) are strored in a document ldata.
Speaking English as a French Frog


Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
Re: xData or lData
« Reply #4 on: July 05, 2009, 09:40:03 AM »
While you are using object reactors, you can store datas in the reactor data too.

I am quite inexperienced with reactors, but I shall certainly look into this  :-)

About xdatas and ldatas, I read sometimes ldatas have a very bad reputation, but I keep on using them beacause it's much more easy and concise.
AFAIK their bad reputation is due to 2 things :
- They don't support AutoCAD release upgrades. By my side, I never had this kind of problem. Perhaps it was a problem with the first Visual LISP releases (2000 to 2002) which was quite instable.
- The other thing is that ldatas can only be read by LISP (xdatas, xrecords, dictionaries are accessible with every language). So for using with Visual LISP reactors, I do use ldatas instead of xdatas or standard dictionaries, as here where some datas (the rectangle coordinates) are stored in the object reactor data and some others (all rectangle handles) are strored in a document ldata.

Thanks for the information - from your pointers, I think I shall stick to using xData - but this is very interesting indeed.

Lee

Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
Re: xData or lData
« Reply #5 on: July 05, 2009, 10:08:38 AM »
Ok, I have attempted to use an Object Reactor - but I have never used one before, and I get ADS rejected... then AutoCAD crashes pretty bad.   :-( :-(

Code: [Select]
(defun c:blkUpd (/ ins wid hgt blk bEnt bObj
                   pEnt pObj MiP MaP win num )
  (vl-load-com)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name

  (if
    (and
      (setq bEnt
        (car (entsel "\nSelect Block: ")))
      (eq "AcDbBlockReference"
          (vla-get-ObjectName
            (setq bObj
              (vlax-ename->vla-object bEnt))))
      (eq (vla-get-HasAttributes bObj) :vlax-true)
      (eq (strcase blk) (strcase (vla-get-Name bObj)))
      (setq pEnt
        (car (entsel "\nSelect Polyline: ")))
      (wcmatch
        (cdr (assoc 0 (entget pEnt))) "*POLYLINE"))
    (progn
      (vla-getBoundingBox
        (setq pObj
          (vlax-ename->vla-object pEnt)) 'MiP 'MaP)
      (mapcar
        (function
          (lambda (Obj)
            (putxdat Obj "LMACUPD"
              (vl-prin1-to-string
                (list
                  (vla-get-Handle pObj)
                    (vla-get-Handle bObj)))))) (list pObj bObj))
      (mapcar
        (function
          (lambda (Obj)
            (vlr-owner-add *lmac-block* Obj))) (list pObj bObj))
      (setq win (mapcar 'vlax-safearray->list (list MiP MaP))
            num (sslength
                  (ssget "_X"
                    (list
                      (cons 0 "INSERT")
                        (cons 2 (vla-get-Name bObj))
                          (cons 66 1)))))           
      (foreach Att (vlax-safearray->list
                     (vlax-variant-value
                       (vla-getAttributes bObj)))
        (cond
          ((eq ins (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos num 2 0)))
          ((eq Wid (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (caadr win) (caar win)) 2 2)))
          ((eq Hgt (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (cadadr win) (cadar win)) 2 2))))))
    (princ "\n<< Incorrect Selection >>"))
  (princ))

(defun c:BlkUpdshow (/ gr ent xtyp xval Objlst)
  (while
    (and
      (setq gr (grread t 13 2))
      (eq 5 (car gr)))
    (if (setq ent (car (nentselp (cadr gr))))
      (progn
        (vla-getXdata
          (vlax-ename->vla-object ent) "LMACUPD" 'xtyp 'xval)
        (if (and xtyp xval)
          (mapcar
            (function
              (lambda (x)
                (redraw x 3)))
            (setq Objlst
              (mapcar 'handent
                (read
                  (vlax-variant-value
                    (cadr
                      (vlax-safearray->list xval)))))))))
          (if Objlst
            (mapcar
              (function
                (lambda (x)
                  (redraw x 4))) Objlst))))
  (princ))
           

(defun BlkUpdr (Obj Reac Args / ins wid hgt blk ss xtyp xval hand
                                pObj MiP MaP bObj win num)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name

 
  (vla-getXdata Obj "LMACUPD" 'xtyp 'xval)
  (if (and xtyp xval)
    (progn
      (setq hand
        (mapcar 'handent
          (read
            (vlax-variant-value
              (cadr
                (vlax-safearray->list xval))))))
      (vla-getBoundingBox
        (setq pObj
          (vlax-ename->vla-object (car hand))) 'MiP 'MaP)
      (setq bObj (vlax-ename->vla-object (cadr hand))
            win (mapcar 'vlax-safearray->list (list MiP MaP))
            num (sslength
                  (ssget "_X"
                    (list
                      (cons 0 "INSERT")
                        (cons 2 (vla-get-Name bObj))
                          (cons 66 1)))))
      (foreach Att (vlax-safearray->list
                     (vlax-variant-value
                       (vla-getAttributes bObj)))
        (cond
          ((eq ins (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos num 2 0)))
          ((eq Wid (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (caadr win) (caar win)) 2 2)))
          ((eq Hgt (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (cadadr win) (cadar win)) 2 2))))))))
 

(defun putxdat (Obj App Data / ent type1 valeur)

  (setq xtype
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbInteger '(0 . 1)) '(1001 1000))))

  (setq xval
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbVariant '(0 . 1)) (list App Data))))

  (vla-setXData Obj xtype xval))

(if *lmac-Block*
  (vlr-remove *lmac-Block*)
  (setq *lmac-Block* nil))
(setq *lmac-Block*
  (vlr-object-Reactor '() nil
    (list
      (cons :vlr-modified 'BlkUpdr)
      (cons :vlr-copied 'BlkUpdr))))


Any pointer on this would be great  8-)

Jeff_M

  • King Gator
  • Posts: 3942
  • C3D user & customizer
Re: xData or lData
« Reply #6 on: July 05, 2009, 11:20:47 AM »
Lee, I haven't worked much with lisp reactors so I don't have an answer for you. I do, however see what is happening. First off, it does not crash my Acad2010. The block correctly updates with the data. If I modify the pline using the Pedit command or Properties palette, no errors are created. The only time I get the ADS error is when grip editing. This indicates to me that the reactor is firing with every mouse move instead of the completion of the command, but since the grip is still moving it cannot get the required data from the pline.

I've quickly looked and don't see a way to avoid this...although I'm pretty sure there must be.

Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
Re: xData or lData
« Reply #7 on: July 05, 2009, 12:03:04 PM »
I've tried to improve it by Adding the highlighted lines to avoid multiple calls, but it still crashes with an "INTERNAL ERROR" when I grip-move the block  :-(

Code: [Select]
(defun c:blkUpd (/ ins wid hgt blk bEnt bObj
                   pEnt pObj MiP MaP win num )
  (vl-load-com)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name

  (if
    (and
      (setq bEnt
        (car (entsel "\nSelect Block: ")))
      (eq "AcDbBlockReference"
          (vla-get-ObjectName
            (setq bObj
              (vlax-ename->vla-object bEnt))))
      (eq (vla-get-HasAttributes bObj) :vlax-true)
      (eq (strcase blk) (strcase (vla-get-Name bObj)))
      (setq pEnt
        (car (entsel "\nSelect Polyline: ")))
      (wcmatch
        (cdr (assoc 0 (entget pEnt))) "*POLYLINE"))
    (progn
      (vla-getBoundingBox
        (setq pObj
          (vlax-ename->vla-object pEnt)) 'MiP 'MaP)
      (mapcar
        (function
          (lambda (Obj)
            (putxdat Obj "LMACUPD"
              (vl-prin1-to-string
                (list
                  (vla-get-Handle pObj)
                    (vla-get-Handle bObj)))))) (list pObj bObj))
      (mapcar
        (function
          (lambda (Obj)
            (vlr-owner-add *lmac-block* Obj))) (list pObj bObj))
      (setq win (mapcar 'vlax-safearray->list (list MiP MaP))
            num (sslength
                  (ssget "_X"
                    (list
                      (cons 0 "INSERT")
                        (cons 2 (vla-get-Name bObj))
                          (cons 66 1)))))           
      (foreach Att (vlax-safearray->list
                     (vlax-variant-value
                       (vla-getAttributes bObj)))
        (cond
          ((eq ins (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos num 2 0)))
          ((eq Wid (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (caadr win) (caar win)) 2 2)))
          ((eq Hgt (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (cadadr win) (cadar win)) 2 2))))))
    (princ "\n<< Incorrect Selection >>"))
  (princ))

(defun c:BlkUpdshow (/ gr ent xtyp xval Objlst)
  (while
    (and
      (setq gr (grread t 13 2))
      (eq 5 (car gr)))
    (if (setq ent (car (nentselp (cadr gr))))
      (progn
        (vla-getXdata
          (vlax-ename->vla-object ent) "LMACUPD" 'xtyp 'xval)
        (if (and xtyp xval)
          (mapcar
            (function
              (lambda (x)
                (redraw x 3)))
            (setq Objlst
              (mapcar 'handent
                (read
                  (vlax-variant-value
                    (cadr
                      (vlax-safearray->list xval)))))))))
          (if Objlst
            (mapcar
              (function
                (lambda (x)
                  (redraw x 4))) Objlst))))
  (princ))
           

(defun BlkUpdr (Obj Reac Args / ins wid hgt blk ss xtyp xval hand
                                pObj MiP MaP bObj win num)

  (setq ins "INSTANCES")   ;; << Instances Tag
  (setq Wid "WIDTH")       ;; << Width Tag
  (setq Hgt "HEIGHT")      ;; << Height Tag
  (setq blk "TESTER")      ;; << Block Name

[color=red]
  (if (not Args)
    (progn[/color]
  (vla-getXdata Obj "LMACUPD" 'xtyp 'xval)
  (if (and xtyp xval)
    (progn
      (setq hand
        (mapcar 'handent
          (read
            (vlax-variant-value
              (cadr
                (vlax-safearray->list xval))))))
      (vla-getBoundingBox
        (setq pObj
          (vlax-ename->vla-object (car hand))) 'MiP 'MaP)
      (setq bObj (vlax-ename->vla-object (cadr hand))
            win (mapcar 'vlax-safearray->list (list MiP MaP))
            num (sslength
                  (ssget "_X"
                    (list
                      (cons 0 "INSERT")
                        (cons 2 (vla-get-Name bObj))
                          (cons 66 1)))))
      (foreach Att (vlax-safearray->list
                     (vlax-variant-value
                       (vla-getAttributes bObj)))
        (cond
          ((eq ins (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos num 2 0)))
          ((eq Wid (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (caadr win) (caar win)) 2 2)))
          ((eq Hgt (vla-get-TagString Att))
           (vla-put-TextString Att
             (rtos
               (- (cadadr win) (cadar win)) 2 2))))))))))
 

(defun putxdat (Obj App Data / ent type1 valeur)

  (setq xtype
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbInteger '(0 . 1)) '(1001 1000))))

  (setq xval
    (vlax-make-variant
      (vlax-safearray-fill
        (vlax-make-safearray
          vlax-vbVariant '(0 . 1)) (list App Data))))

  (vla-setXData Obj xtype xval))

(if *lmac-Block*
  (vlr-remove *lmac-Block*)
  (setq *lmac-Block* nil))
(setq *lmac-Block*
  (vlr-object-Reactor '() nil
    (list
      (cons :vlr-modified 'BlkUpdr)
      (cons :vlr-copied 'BlkUpdr))))



gile

  • Water Moccasin
  • Posts: 2224
  • Marseille, France
Re: xData or lData
« Reply #8 on: July 05, 2009, 12:18:59 PM »
Hi,

I think you'd rather use one object reactor for each object because while an object reactor is fired the application can't edit its owner (it's opened).
This way will also allow you to avoid using xdata and use the reactor data.
Speaking English as a French Frog

CAB

  • Global Moderator
  • Seagull
  • Posts: 10362
I've reached the age where the happy hour is a nap. (°Ώ°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
Re: xData or lData
« Reply #10 on: July 05, 2009, 04:12:10 PM »

gile

  • Water Moccasin
  • Posts: 2224
  • Marseille, France
Re: xData or lData
« Reply #11 on: July 05, 2009, 05:44:45 PM »
Hi,

I posted new releases of "TotalArea" and "TotalPerim" here.

They seems to be quite closed to your example: a block reference is linked to one or more objets and displays in an attributes the sum of these objects areas (or perimeters).
Each linked object as its own object reactor.
The block handle is stored in the object reactor data.
The list of objects handles is stored in a ldata linked to the block reference (can be replace by an xdata).
Rather than using persistents reactor, the reactors are built while the file is loaded.
« Last Edit: July 06, 2009, 05:23:20 AM by gile »
Speaking English as a French Frog

Lee Mac

  • Seagull
  • Posts: 12254
  • London, England
Re: xData or lData
« Reply #12 on: July 05, 2009, 06:42:26 PM »
Many thanks Gile, I'll be sure to take a look et je dissιquerai votre code  :-P

[Did French A-Level, bit rusty...]