Jump to content

Recommended Posts

Posted

Good evening all

 

Having a bit of trouble with using the activeX aCselectionsetWindowPolygon selection set creation method

 

The problem arises initially with the legacy

  (ssget "WP" plist) 

method which subject ot failure if the document is zoomed to the extent that all point in the point list are visible.

The activeX method is impervious to zoom issue as it uses the document object methods more akin to that of ObjectARX

 

the below code is as close as I have managed

 

  (vla-select  sset acselectionsetwindowpolygon (vla-get-coordinates ent) nil filter_code filter_value)

;ERROR  -  Automation Error. Invalid argument Mode in Select

Any thoughts?

 

EDIT:

 

The reason this providing an issue is the method in which it is called

 vlr-object-reactor ...  :vlr-modified

which doesn't allow either of the following workarounds

 

 (setq zfactor (ggetvar "ZOOMFACTOR"))
 (setvar "ZOOMFACTOR" 1)
 ...
 (setvar "ZOOMFACTOR zfactor)
;ERROR - Something along the lines of setvar has been rejected by AutoCAD

;----------

(command"zoom""o" ent"")
;ERROR - Invalid Autocad function call

cheers,

Ollie

  • Replies 24
  • Created
  • Last Reply

Top Posters In This Topic

  • Lee Mac

    9

  • ollie

    7

  • wizman

    6

  • gile

    2

Top Posters In This Topic

Posted Images

Posted

command functions are not to be used with reactors, try vla-selectbypolygon, be aware also that pointslist argument is An array of 3D WCS coordinates specifying the selection fence.

Posted

Here's a sample:

 

 

 

;;
;;  Sample Function for Selection Set:
;;  Pick a Polygon then creates a selection set
;;  of entites in layer "0" within the Boundary.
;;  Returns Vla-objects within the set
;;  
(vl-load-com)
;;
(setq acadDocument (vla-get-ActiveDocument (vlax-get-acad-object)))
(setq mSpace (vla-get-ModelSpace acadDocument))
(setq SSetName "MySSet")
(setq SSets (vla-get-SelectionSets acadDocument))
(if (vl-catch-all-error-p
     (vl-catch-all-apply
       'vla-add
       (list SSets
             SSetName
       )
     )
   )
 (vla-clear (vla-Item SSets SSetName))
)
(setq SSet (vla-Item SSets SSetName))
;;
;;  Pick Polygon
;;  
(setq mylist (vlax-safearray->list
              (vlax-variant-value
                (vla-get-coordinates
                  (vlax-ename->vla-object (car (entsel)))
                )
              )
            )
)
;;
;;
(defun groupby2 (lst / grp) ;WIZ_03JAN10
 (while (< 1 (length lst))
   (Setq grp (cons (list
                     (car lst)
                     (cadr lst)
                   )
                   grp
             )
   )
   (setq lst (cddr lst))
 )
 (vl-remove 'nil (reverse (cons lst grp)))
)
;;
;;
(setq mylist (groupby2 mylist))
;;
;;
(setq mylist (mapcar (function (lambda (x)
                                (append x '(0.))
                              )
                    )
                    mylist
            )
)
;;
;;
(setq mylist (apply 'append mylist))
;;
;;
(defun list->safearray (lst datatype)
 (vlax-safearray-fill
   (vlax-make-safearray
     (eval datatype)
     (cons 0
           (1-
             (length lst)
           )
     )
   )
   lst
 )
)
;;
;;
(setq myarray (list->safearray mylist 'vlax-vbdouble))
;;
;;


;;create a single element array for the DXF Code
(setq filter_code (vlax-make-safearray vlax-vbinteger '(0 . 0)))

;;create a single element array for the value
(setq filter_value (vlax-make-safearray vlax-vbvariant '(0 . 0)))

;;DXF Code for layers
(vlax-safearray-fill filter_code '()

;;the filter value
(vlax-safearray-fill filter_value '("0")); << LAYER VALUE
;;
;;
(vla-SelectByPolygon
 sset
 acselectionsetwindowpolygon
 myarray
 filter_code
 filter_value
)
;;
;;
;;(vlax-dump-Object sset t)
;;
;;
(setq counter 0)
(repeat (vla-get-count sset)
 (princ "\n")  
 (princ(vla-item sset counter))
 (setq counter (1+ counter))
)
;;
;; WIZ_03JAN10

Posted

Thanks gentlemen

 

The issue I was having as it turned out was using

vla-select ...
;rather than 
vla-selectbypolygon

Thanks for the insight Wizman. I spent hours last night trying to find the invalid method that I was attempting to use on the internet.

 

Sadly the vla selection set seemingly has the same issue as the legacy ssget method. the attribute block is still only found when all point passed to either selection set methods are visible

 

With that said I think I will try a reverse to this approach whereupon I will check all of the relevant INSERT's insertion points to see if they are contained in the polyline

 

Cheers,

Ollie

Posted
With that said I think I will try a reverse to this approach whereupon I will check all of the relevant INSERT's insertion points to see if they are contained in the polyline

 

I was just about to recommend that approach... :)

 

Although, it may be a difficult approach if you are dealing with an irregular polygon - LISP doesn't have in inherent "insidep" function... :geek:

 

But yeah, something like:

 

(vlax-for lay (vla-get-layouts (vla-get-ActiveDocument (vlax-get-acad-object))))
 (vlax-for obj (vla-get-Block lay)
   (if (eq "AcDbBlockReference" (vla-get-Objectname obj))
     (setq pt (vlax-get obj 'InsertionPoint)) ...

Posted

You're welcome Ollie, you may want to try also doing a (vla-zoom.. to make it visible on screen..

Posted
You're welcome Ollie, you may want to try also doing a (vla-zoom.. to make it visible on screen..

 

Nice thought, sadly the function doesn't exist. I've been trhough the document object model relentlessly trying to find a method of zooming through vla- without even a glimpse of hope

Posted
Nice thought, sadly the function doesn't exist. I've been trhough the document object model relentlessly trying to find a method of zooming through vla- without even a glimpse of hope

 

vla-ZoomExtents

vla-ZoomCenter

vla-ZoomAll..

 

There are tons...

Posted
vla-ZoomExtents

vla-ZoomCenter

vla-ZoomAll..

 

There are tons...

 

Hehe I forgot about the aprops. Essentially took Wizman/s comment as a literal statement.

 

Once again gentlemen I cannot thank you's enough. the following is the psuedo solution

 

 (vla-zoomextents (vlax-get-acad-object))
 (vla-selectbypolygon sset acselectionsetwindowpolygon plist filter_code    filter_value)
 (vla-zoomprevious (vlax-get-acad-object))

 

Once I have tidied the rest of the code up I will post the result

 

Cheers,

Ollie

Posted

zoom to polygon...'-)

 

 

(defun c:zoom2polygon (/ pl)
   (setq pl (vlax-ename->vla-object (car (entsel))))
   (setq pl (vlax-get pl 'Coordinates))
   ;;
   ;;
   (defun groupby2 (lst / grp)         ;WIZ_03JAN10
       (while (< 1 (length lst))
           (Setq grp (cons (list
                               (car lst)
                               (cadr lst)
                           ) ;_ list
                           grp
                     ) ;_ cons
           ) ;_ Setq
           (setq lst (cddr lst))
       ) ;_ while
       (vl-remove 'nil (reverse (cons lst grp)))
   ) ;_ defun
   ;;
   ;;
   (setq pl (groupby2 pl))
   (setq pl (maxminpnt pl))
   (setq pl (mapcar 'vlax-3d-point pl))
   ;;
   ;;
   (vla-ZoomWindow (vlax-get-acad-object) (car pl) (cadr pl))
) ;_ defun
;;
;; WIZ_03JAN10

Posted

This is a reasonably tidy version

 

Simply load and enter capture into the command line to add the reactors

 

Admittedly I will be changing the selection set method to (ssget) at some point but, so as the initial question on this thread was not in vain the vla- method has be retained for now

 

Thanks to Wizman and Lee Mac for collaborating with me on this one. Hehe I had a dream '(yester)day, your help has made it happen

 

EDIT: The initial 'capture' function originally used a file read function to create a list of the global variables, however, it seemed impractical to post that version due to file format , appropriate list selection etc. For the purpose of demonstration it uses the globals.

 

EDIT++: I feel kind of bad about the poor comments but proper documentation can jump until tomorrow

 

(vl-load-com)

;GLOBAL VARIABLES--------------------;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Layer containing the Polylines and attributes
(setq GIAReactorLayer "SAMPLE")
;Attribute block containing the Attribute definition
(setq GIAReactorAttBlock "ATTBLOCK")
;Attribute containing the Gross internal area
(setq GIAReactorAttribute "ATTDEF")

;END OF GLOBAL VARIABLE DECLERATIONS-;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;------------------------------------------------;
;CAPTURE                     ;
; check for polylines on the Reactor layer     ;
; add reactor to all applicable polylines     ;
;                         ;
; Alert user when there are no valid polylines   ;
; in the activedocument                 ;

(defun c:capture( / sset)
 (setq sset (ssget "X" (list(cons 8  GIAReactorLayer)'(0 . "LWPOLYLINE"))))
 (if( = nil sset)
   (progn
     (alert (strcat "No " GIAReactorLayer " polyline(s) detected" ))
     (exit)
   )
 )
 (setq cntr -1)
 (while(< (setq cntr (1+ cntr)) (sslength sset))
   (addGIAReactor (ssname sset cntr))
 )
)

;-----------------------------------------------;
;addGIAReactor                    ;
; Add the OBJECT-CLOSED reactor passed entity    ;

(defun addGIAReactor (Ent )
 (vlr-object-reactor (list (vlax-ename->vla-object ent)) "GIA Reactor" '((:vlr-objectclosed .  UpdateGIA)))
)

;-----------------------------------------------;
;updateGIA                    ;
; Find the attribute block that resides inside  ;
; the modified polyline and update the GIA      ;
; attribute                    ;
;                        ;
; Princ new value to the console        ;
;                        ;
; Inform user via console that the attribute    ;
; was not found in the located attribute    ;
; suggest spell checking the attribute name    ;
(defun updateGIA( ent reactor params / sset ent)
 (vla-zoomextents (vlax-get-acad-object))
 (setq sset (createvlasset (getpointlist ent)))
 (vla-zoomprevious (vlax-get-acad-object))
 (if(>  (vla-get-count sset) 0)
   (progn
     (if(= (vla-get-hasattributes (setq attblock(vla-item sset 0))) :vlax-true)
   (progn
     (foreach c (vlax-safearray->list(vlax-variant-value(vla-getattributes attblock)))
       (if(= (strcase (vla-get-tagstring c) ) (strcase GIAReactorAttribute) )
         (progn
           (vla-put-textstring c (rtos(/ (vla-get-area ent) 1000000) 2 2))
       (princ (strcat "\nNew gross internal area: " (vla-get-textstring c) "m²"))
         )
       )
     )
   )
     )
   )
 )
)
(defun getPointList (ent)
 (setq ls (vlax-safearray->list(vlax-variant-value(vla-get-coordinates ent))))
 (setq ls (groupby2 ls))
 (setq ls (mapcar (function (lambda(x)(append x '(0.0)))) ls))
 (setq ls (apply 'append ls))
 (setq ls
   (vlax-safearray-fill
     (vlax-make-safearray
       vlax-vbdouble
       (cons 0 (1-(length ls)))
     )
     ls
   )
 )
 ls
)

(defun groupby2 (lst / grp) ;WIZ_03JAN10
 (while (< 1 (length lst))
   (Setq grp (cons (list
                     (car lst)
                     (cadr lst)
                   )
                   grp
             )
   )
   (setq lst (cddr lst))
 )
 (vl-remove 'nil (reverse (cons lst grp)))
)


(defun createVlaSset( plist  / Adoc ssets sset filter_value filter_code)
 (setq Adoc (vla-get-activedocument(vlax-get-acad-object)))
 (setq ssets (vla-get-selectionsets Adoc))
 (setq cntr -1)
 (while(< (setq cntr (1+ cntr)) (vla-get-count ssets))
   (if(eq (vla-get-name (vla-item ssets cntr)) "sset")
     (vla-delete(vla-item ssets cntr))
   )
 )
 (setq sset (vla-add ssets "sset"))
 (setq filter_code (vlax-make-safearray vlax-vbinteger '(0 . 0)))
 (vlax-safearray-fill filter_code '(2))
 (setq filter_value (vlax-make-safearray vlax-vbvariant '(0 . 0)))
 (vlax-safearray-fill filter_value (list GIAReactorAttBlock))
 (vla-selectbypolygon sset acselectionsetwindowpolygon   plist filter_code filter_value)
 sset
)

sample.dwg

Posted

I would recommend that you change the "capture" function to something like this:

 

(defun c:capture ( / sset i ent ObjLst)
 (if (setq i -1 sset (ssget "X" (list (cons 8  GIAReactorLayer) '(0 . "LWPOLYLINE"))))
   
   (if (not *ObjReac*) ;; *ObjReac* Global
     (progn
     
       (while (setq ent (ssname ss (setq i (1+ i))))
         (setq ObjLst (cons (vlax-ename->vla-object ent) ObjLst)))

       (setq *ObjReac* (vlr-object-reactor Objlst "GIA Reactor" '((:vlr-objectclosed .  UpdateGIA)))))

     (princ "\n** Reactor already Running **"))

   (princ "\n** No LWPolylines Found **"))
 
 (princ))

As, currently, you are creating a new reactor for every individual object that you find... not such a good idea...

 

Also, I would recommend adding a function to remove the reactor if the user so wishes :) For example, see post #6 of this.

 

Hope this helps,

 

Lee

Posted

good one ollie, thanks for sharing, i'll study it. you may find a way to suppress the error prompt when the boundary is erased or even more good excercise to make it persistent.

Posted
good one ollie, thanks for sharing, i'll study it. you may find a way to suppress the error prompt when the boundary is erased or even more good excercise to make it persistent.

 

No problem, I also intend to make this more robust. I wrote it in a the usual ideal envirnment without considering errors, exceptions etc.

 

Lee Mac, for some reason I never considered the Object list in the reactor declerations. Once again I have been shunned by the almaganation of OOP and procedural languages

 

Ollie

Posted
No problem, I also intend to make this more robust. I wrote it in a the usual ideal envirnment without considering errors, exceptions etc.

 

Lee Mac, for some reason I never considered the Object list in the reactor declerations. Once again I have been shunned by the almaganation of OOP and procedural languages

 

Ollie

 

Not a problem, we are all learning :)

Posted
As, currently, you are creating a new reactor for every individual object that you find... not such a good idea...

IMO, it's easier to manage individual object reactors than a single one with the objects stored in the 'owners' argument of the reactor, for example if the objet is erased.

 

even more good excercise to make it persistent

Always IMO, I avoid using persistent reactors because this way the reactor is linked to the object (IOW to the file) rather than to the routine.

When opening back the file, if the reactor is fired while the callback routine isn't loaded, an error will occur.

I'd rather store the object handles in a dictionary while saving the file (with a DWG retactor callback) and re-build them while the routine is loaded.

 

An example in the attached file and more explainations in this thread (have to register).

Rectangle_1.08.lsp

Posted

thanks gile, i'll learn from your code.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...