Hello!
In case of very irregular 2D shapes where Centroid is a point outside a polyline, what is the alternative.
I would like to find an alternative middle point inside the polyline.
Any suggestions?
Thanks in advance + regards,
Lzucco
Solved! Go to Solution.
Solved by _gile. Go to Solution.
For what purpose? I imagine it could vary a lot depending on what you want to do with/from/to/about the alternate location, and the particular shape of the Polyline. Maybe the (vlax-curve-getClosestPointTo) function, giving it the actual centroid to find the closest point on the Polyline to? Of course, that will always be on the edge of the Polyline, not "inside" it, if that distinction matters to you.
It is indeed an absolutely ambiguous description and very difficult to define once we can find innumerous irregular polygons shapes in a city map that are the representation of plots of land.
What I'm trying to find is a equidistant middle point inside the polyline that not touch the borders.
Attached an example. The irregular shape with has the Centroid outside the polyline is colored.
I found a routine I wrote more than 10 years ago. it uses a dichotomic search for the max offset distance according to a fuzz.
(defun MostInnerPoint (obj fuzz / 2d-coord->pt-lst 3d-coord->pt-lst dich-sub len tmp) (vl-load-com) (defun 2d-coord->pt-lst (lst) (if lst (cons (list (car lst) (cadr lst)) (2d-coord->pt-lst (cddr lst)) ) ) ) (defun 3d-coord->pt-lst (lst) (if lst (cons (list (car lst) (cadr lst) (caddr lst)) (3d-coord->pt-lst (cdddr lst)) ) ) ) (defun dich-sub (inf sup / of new pts) (if (equal inf sup fuzz) (progn (setq of (vlax-invoke obj 'Offset inf) pts (if (= (vla-get-ObjectName (car of)) "AcDbPolyline") (2d-coord->pt-lst (vlax-get (car of) 'Coordinates)) (3d-coord->pt-lst (vlax-get (car of) 'ControlPoints)) ) ) (mapcar 'vla-delete of) (mapcar (function (lambda (x) (/ x (length pts)) ) ) (apply 'mapcar (cons '+ pts)) ) ) (progn (setq new (/ (+ inf sup) 2.0) of (vl-catch-all-apply 'vlax-invoke (list obj 'Offset new) ) ) (if (vl-catch-all-error-p of) (dich-sub inf new) (progn (mapcar 'vla-delete of) (dich-sub new sup) ) ) ) ) ) (if (and (member (vla-get-ObjectName obj) '("AcDbPolyline" "AcDbSpline") ) (vlax-curve-isClosed obj) (or (= (vla-get-ObjectName obj) "AcDbPolyline") (vlax-curve-isPlanar obj) ) (setq tmp (vl-catch-all-apply 'vlax-invoke (list obj 'Offset fuzz))) (setq len (vlax-curve-getDistAtParam obj (vlax-curve-getEndParam obj)) tmp (car tmp) ) (if (< len (vlax-curve-getDistAtParam tmp (vlax-curve-getEndParam tmp)) ) (setq len (/ len (* -2 pi))) (setq len (/ len (* 2 pi))) ) (not (vla-delete tmp)) ) (dich-sub 0.0 len) ) ) (defun c:test (/ ent) (and (setq ent (car (entsel))) (entmake (list '(0 . "POINT") '(62 . 3) (cons 10 (MostInnerPoint (vlax-ename->vla-object ent) 0.01) ) ) ) ) (princ) )
I absolutely don't remember. Dividing by 2 seems to work the same.
(setq len (/ len 2.))
;[...]
(dich-sub 0.0 len)