Author Topic: Region/centroid coordinates  (Read 5280 times)

0 Members and 1 Guest are viewing this topic.

csgoh

  • Newt
  • Posts: 176
Region/centroid coordinates
« on: March 28, 2006, 10:11:10 AM »
I am writing a function to return the centroid coordinates but am stuck when it returns nil all the time?
Help is much appreciated to correct this function. The object is a closed lwpolyline or 3dpolyline.
Thanks
Code: [Select]
;;
;; Function Calculate Centroid Coords
;; USAGE
;; Argument
;; obj  - <vla-object>
;; Returns
;; <List of Centroid coordinates> or nil
;;
(defun wg:CentroidCrd( obj / region_array centroid_pt )
  (if (not (vl-catch-all-error-p
        (setq Region_array
      (vl-catch-all-apply
             'vla-addregion (list obj)
       ))))
     (progn
      (setq centroid_pt
    (vlax-get (setq region (vlax-safearray-get-element
                      (vlax-variant-value Region_array) 0)
                    )
   'centroid))
;; erase the auxiliar region object
      (vla-delete region)
     );progn
    );if
    centroid_pt
);wg:CentroidCrd


LE

  • Guest
Re: Region/centroid coordinates
« Reply #1 on: March 28, 2006, 10:14:27 AM »
See if this routine can do what you want:

Code: [Select]
;; by http://www.geometricad.com

(vl-load-com)

(defun draw_point  (pt col / d)
  (setq d (* (getvar "viewsize") 0.015))
  (grdraw
    (trans (polar pt (* 0.25 pi) d) 0 1)
    (trans (polar pt (* 1.25 pi) d) 0 1)
    col
    (- col))
  (grdraw
    (trans (polar pt (* 0.75 pi) d) 0 1)
    (trans (polar pt (* 1.75 pi) d) 0 1)
    col
    (- col)))

(defun gb_getcentroid  (obj / array new_array centroid_pt base)
  (setq array (vlax-make-safearray vlax-vbObject '(0 . 0)))
  (vlax-safearray-put-element array 0 obj)
  (setq new_array
(vlax-invoke-method
   (vla-objectidtoobject
     (setq base (vla-get-database obj))
     (vla-get-ownerid obj))
   'AddRegion
   array))
  (vlax-release-object base)
  (setq centroid_pt
(vlax-get
   (setq region (vlax-safearray-get-element
  (vlax-variant-value new_array)
  0))
   'centroid))
  (vla-delete region)
  centroid_pt)

(if (not (vl-bb-ref 'gb_loaded))
  (progn
    (vl-bb-set 'gb_loaded t)
    (setq model (vla-get-modelspace
  (setq doc (vla-get-activedocument
      (setq acad_obj (vlax-get-acad-object))))))
    (if (not (vl-catch-all-error-p
       (setq vla_circle
      (vl-catch-all-apply
'vla-addcircle
(list model
      (vlax-3d-point (list 0.0 0.0 0.0))
      1.0)))))
      (progn
(gb_getcentroid vla_circle)
(vla-delete vla_circle)))
    (setq model nil
  doc nil
  acad_obj
   nil
  vla_circle nil)))

(defun C:SHOWCENTROID  (/ ename obj)
  (if (and (setq ename (car (entsel "\nSelect a polyline: ")))
   (wcmatch (cdadr (entget ename)) "*POLYLINE")
   (setq obj (vlax-ename->vla-object ename))
   (= (vla-get-closed obj) :vlax-true))
    (draw_point (gb_getcentroid obj) 7))
  (princ))

(princ)

Jürg Menzi

  • Swamp Rat
  • Posts: 599
  • Oberegg, Switzerland
Re: Region/centroid coordinates
« Reply #2 on: March 28, 2006, 10:39:22 AM »
Visit my homepage -> Free Stuff and search for 'VxGetMassProps'
A computer's human touch is its unscrupulousness!
MENZI ENGINEERING GmbH
Current A2k16... A2k24 - Start R2.18

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Region/centroid coordinates
« Reply #3 on: March 28, 2006, 01:31:31 PM »
csgoh,
In response to "Why doesn't mine work", you should get in the habit of making things work WITHOUT a (vl-catch-all-apply) in the function. Once it works on a test object, THEN go back and add your error traps.

In this case, the catch-all was catching the error of not specifying an Object to which the the region was to be added. Since it was caught, you never saw that it was happening.

Here is your code, modified to how I would do it.
Code: [Select]
;;
;; Function Calculate Centroid Coords
;; USAGE
;; Argument
;; obj  - <vla-object>
;; Returns
;; <List of Centroid coordinates> or nil
;;
(defun wg:CentroidCrd ( obj / region_array centroid_pt )
  (if (not (vl-catch-all-error-p
        (setq Region_array
      (vl-catch-all-apply
             '(lambda ()
(vlax-invoke
  (vla-get-modelspace
    (vla-get-document obj))
  'addregion
  (list obj)
  ))))
)
   )
     (progn
      (setq centroid_pt
     (vlax-get (setq region (car Region_array))
       'centroid))
;; erase the auxiliar region object
      (vla-delete region)
     );progn
    );if
    centroid_pt
);wg:CentroidCrd

csgoh

  • Newt
  • Posts: 176
Re: Region/centroid coordinates
« Reply #4 on: March 29, 2006, 12:38:20 AM »
Thanks Jeff.
Like you said, I added an error trap after the routine works. I am just confused on how to use vl-catch-all-apply. I have seen many codes using this but I am still confused as to when to use it in the proper place. Anyway, thanks. I still could not comprehend why you added a lambda function after vl-catch-all-apply, when the help section states (vl-catch-all-apply 'function list). Anyway thanks for the advice. And many thanks to LE and Jurg.

csgoh

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Region/centroid coordinates
« Reply #5 on: March 29, 2006, 01:43:33 AM »
Thanks Jeff.
I still could not comprehend why you added a lambda function after vl-catch-all-apply, when the help section states (vl-catch-all-apply 'function list).
csgoh
OK, look at it this way.....
'(lambda ()...) is defining a function.
(vl-catch-all-apply) expects a function.
So by using (lambda) I am allowing my code to be placed into the catch-all in a manner that looks like it would without the (catch-all) and means I only need to add the "(vla-catch-all-apply '(lambda ()" just prior to my working test code and the add "))" after that working code to close the two added functions. . If I just used 'vla-addregion (or, I would prefer to use 'vlax-invoke) then it would need to be re-written to be followed by a complete list of the needed arguments.

This snip is identical (or should be, but it's late and I'm not testing it.....) to what I posted earlier, but without the (lambda):
Code: [Select]
......
(if (not (vl-catch-all-error-p
        (setq Region_array
          (vl-catch-all-apply
             'vlax-invoke
           (list (vla-get-modelspace
                    (vla-get-document obj))
                  'addregion
                  (list obj)
             )
          )))
    )
.......
So you see, there is more than one way to use the (vl-catch-all-apply)
« Last Edit: March 29, 2006, 01:47:41 AM by Jeff_M »

csgoh

  • Newt
  • Posts: 176
Re: Region/centroid coordinates
« Reply #6 on: March 29, 2006, 05:56:02 AM »
Thanks for your explanation.
However if I replace your code;
Quote
     (setq centroid_pt
        (vlax-get (setq region (car Region_array))
             'centroid))


with
Quote
      (setq   centroid_pt
       (vlax-get (setq region (vlax-safearray-get-element
                            (vlax-variant-value Region_array) 0)
                    )
         'centroid))


the function fails. Why is that? The second code is also the same as the one provided by LE. I am getting more confused. Shouldn't the two codes provide the same thing.
Thanks.

Jeff_M

  • King Gator
  • Posts: 4096
  • C3D user & customizer
Re: Region/centroid coordinates
« Reply #7 on: March 29, 2006, 12:30:51 PM »
:-) Nope, that's the beauty  :lmao: of VLisp & ActiveX.....
(vla-get-XXXX obj) & (vlax-get-property obj 'xxxx) will always return a Variant or safearray, depending on the data being returned.
(vlax-get obj 'xxx) will USUALLY return a standard list which is why I use this. No converting from variants/safearrays. However, I did say "usuaully" because, for whatever reason (known only to the programmers at Adesk) SOME methods and properties do not support this method. One that I can think of is the "getboundingbox" method.

Examine the values of the 2 variables we set by the 2 different ways of getting the 'centroid property:
Code: [Select]
_$ (setq cent1 (vlax-get obj 'centroid))
(18.3049 9.76847)
_$ (setq cent2 (vla-get-centroid obj))
#<variant 8197 ...>
_$ (vlax-variant-value cent2)
#<safearray...>
_$ (vlax-safearray->list (vlax-variant-value cent2))
(18.3049 9.76847)
which one do you think is easier to work with? Now examine the variables returned by the 2 methods of creating the Region:
First the 2 functions...
Code: [Select]
(setq Region_array1
       (vlax-invoke
(vla-get-modelspace
   (vla-get-document obj))
'addregion
(list obj)
))
;;;;;;;
  (setq array (vlax-make-safearray vlax-vbObject '(0 . 0)))
  (vlax-safearray-put-element array 0 obj)
(setq Region_array2
       (vla-addregion
(vla-get-modelspace
   (vla-get-document obj))
array))
and the results:
Code: [Select]
_$

(#<VLA-OBJECT IAcadRegion 04c99484>)
_$

#<variant 8201 ...>
now can you see why I used the (car) vs. the (vlax-safearray-get-element....)?