ollie Posted January 2, 2010 Posted January 2, 2010 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 Quote
wizman Posted January 3, 2010 Posted January 3, 2010 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. Quote
wizman Posted January 3, 2010 Posted January 3, 2010 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 Quote
ollie Posted January 3, 2010 Author Posted January 3, 2010 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 Quote
Lee Mac Posted January 3, 2010 Posted January 3, 2010 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... 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)) ... Quote
wizman Posted January 3, 2010 Posted January 3, 2010 You're welcome Ollie, you may want to try also doing a (vla-zoom.. to make it visible on screen.. Quote
ollie Posted January 3, 2010 Author Posted January 3, 2010 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 Quote
Lee Mac Posted January 3, 2010 Posted January 3, 2010 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... Quote
Lee Mac Posted January 3, 2010 Posted January 3, 2010 Use CTRL+SPACE or CTRL+SHIFT+SPACE to complete the word: Quote
ollie Posted January 3, 2010 Author Posted January 3, 2010 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 Quote
wizman Posted January 3, 2010 Posted January 3, 2010 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 Quote
ollie Posted January 3, 2010 Author Posted January 3, 2010 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 Quote
Lee Mac Posted January 3, 2010 Posted January 3, 2010 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 Quote
wizman Posted January 4, 2010 Posted January 4, 2010 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. Quote
ollie Posted January 4, 2010 Author Posted January 4, 2010 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 Quote
Lee Mac Posted January 4, 2010 Posted January 4, 2010 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 Quote
gile Posted January 4, 2010 Posted January 4, 2010 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 Quote
Recommended Posts
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.