make osnap focus on desired geometrical center

make osnap focus on desired geometrical center

bart.tuytten
Contributor Contributor
627 Views
8 Replies
Message 1 of 9

make osnap focus on desired geometrical center

bart.tuytten
Contributor
Contributor

Hello,

 

basically i run a routine now looping a selection set of polylines adding

a text at each geometrical center.

 

This is the issue I encounter.

In case the Startpoint of the i-th polyline is closer to

the geometrical center of an adjacent polyline, the text will of course appear inside the wrong polyline.

I was thinking of defining a new point based on the bounding box of the i-th polyline.

 

Yet up till now I'm not able to solve this programming quest myself.

Does someone have a suggestion on how to make this work?

 

Thank you.

 

(while (< i j)
(setq pl_i_name (ssname ss i))

(setq pl_cen (osnap (vlax-curve-getStartPoint pl_i_name) "gcen"))
(setq i (1+ i))
)

0 Likes
Accepted solutions (2)
628 Views
8 Replies
Replies (8)
Message 2 of 9

Kent1Cooper
Consultant
Consultant
Accepted solution

With the DELOBJ System Variable set to 0 so the Polyline remains, perhaps something like this:

 

....

  (command "_.region" pl_i_name "")
  (setq pl_cen (vlax-get (vlax-ename->vla-object (entlast)) "Centroid"))
  (entdel (entlast)); remove the Region

....

Kent Cooper, AIA
0 Likes
Message 3 of 9

_gile
Consultant
Consultant
Accepted solution

Hi,

The following routine computes the centroid of a polyline.

 

;; ALGEB-AREA
;; Returns tha algebraic area of the triangle defined by 3  2d points
;; the area is negative if points are clockwise

(defun algeb-area (p1 p2 p3)
  (/ (-	(* (- (car p2) (car p1))
	   (- (cadr p3) (cadr p1))
	)
	(* (- (car p3) (car p1))
	   (- (cadr p2) (cadr p1))
	)
     )
     2.0
  )
)

;; TRIANGLE-CENTROID
;; Returns the centroid of a triangle defined by 3 points

(defun triangle-centroid (p1 p2 p3)
  (mapcar '(lambda (x1 x2 x3)
	     (/ (+ x1 x2 x3) 3.0)
	   )
	  p1
	  p2
	  p3
  )
)

;; POLYARC-CENTROID
;; Returns a list which first item is the centroid of a 'polyarc'
;; and the second its algeraic area
;;
;; Arguments
;; bu : polyarc bulge
;; p1 : start point
;; p2 : end point

(defun polyarc-centroid	(bu p1 p2 / ang rad cen area dist cg)
  (setq	ang  (* 2 (atan bu))
	rad  (/	(distance p1 p2)
		(* 2 (sin ang))
	     )
	cen  (polar p1
		    (+ (angle p1 p2) (- (/ pi 2) ang))
		    rad
	     )
	area (/ (* rad rad (- (* 2 ang) (sin (* 2 ang)))) 2.0)
	dist (/ (expt (distance p1 p2) 3) (* 12 area))
	cg   (polar cen
		    (- (angle p1 p2) (/ pi 2))
		    dist
	     )
  )
  (list cg area)
)

;; PLINE-CENTROID
;; Returns the WCS coordinates of a lwpolyline centroid
;;
;; Argument
;; pl : the lwpolyline ename

(defun pline-centroid (pl / elst lst tot cen p0 area cen)
  (setq elst (entget pl))
  (while (setq elst (member (assoc 10 elst) elst))
    (setq lst  (cons (cons (cdar elst) (cdr (assoc 42 elst))) lst)
	  elst (cdr elst)
    )
  )
  (setq	lst (reverse lst)
	tot 0.0
	cen '(0.0 0.0)
	p0  (caar lst)
  )
  (if (/= 0 (cdar lst))
    (setq p-c (polyarc-centroid (cdar lst) p0 (caadr lst))
	  cen (mapcar '(lambda (x) (* x (cadr p-c))) (car p-c))
	  tot (cadr p-c)
    )
  )
  (setq lst (cdr lst))
  (if (equal (car (last lst)) p0 1e-9)
    (setq lst (reverse (cdr (reverse lst))))
  )
  (while (cadr lst)
    (setq area (algeb-area p0 (caar lst) (caadr lst))
	  cen  (mapcar '(lambda (x1 x2) (+ x1 (* x2 area)))
		       cen
		       (triangle-centroid p0 (caar lst) (caadr lst))
	       )
	  tot  (+ area tot)
    )
    (if	(/= 0 (cdar lst))
      (setq p-c	(polyarc-centroid (cdar lst) (caar lst) (caadr lst))
	    cen	(mapcar	'(lambda (x1 x2) (+ x1 (* x2 (cadr p-c))))
			cen
			(car p-c)
		)
	    tot	(+ tot (cadr p-c))
      )
    )
    (setq lst (cdr lst))
  )
  (if (/= 0 (cdar lst))
    (setq p-c (polyarc-centroid (cdar lst) (caar lst) p0)
	  cen (mapcar '(lambda (x1 x2) (+ x1 (* x2 (cadr p-c))))
		      cen
		      (car p-c)
	      )
	  tot (+ tot (cadr p-c))
    )
  )
  (trans (list (/ (car cen) tot)
	       (/ (cadr cen) tot)
	       (cdr (assoc 38 (entget pl)))
	 )
	 pl
	 0
  )
)

Using:

(while (< i j)
  (setq pl_i_name (ssname ss i))
  (setq pl_cen (pline-centroid pl-i-name))
  (setq i (1+ i))
)

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 4 of 9

bart.tuytten
Contributor
Contributor

Hello,

 

I integrated the code you suggested adapting the 'Delobj' to 0, though I got some error:

 

Command: Error: ActiveX Server returned the error: unknown name: "Centroid"

I could not find out what was leading to this result.

 

In the meanwhile I also tried _gile 's code and that one ended up in satisfying result.


I want to express my appreciation for your quick analysis and response.

 

Regards, Bart Tuytten

0 Likes
Message 5 of 9

bart.tuytten
Contributor
Contributor

Hello Gilles,

 

your code solved my issue.

Thanks a lot for your input and quik response.

 

Regards, Bart Tuytten

 

For completeness and for other users of the forum:

'pl-i-name' >> 'pl_i_name'

 

 

0 Likes
Message 6 of 9

CodeDing
Advisor
Advisor

@bart.tuytten ,

 

Well, my answer is obviously not as sophisticated as @_gile 's.. 😅 But my take uses the (command "_.DRAWORDER ...) method to solve the Geometric Center dilemma. 

(defun c:TEST ( / ss)
  (if (setq ss (ssget '((0 . "LWPOLYLINE"))))
    (repeat (setq cnt (sslength ss))
      (setq e (ssname ss (setq cnt (1- cnt))))
      (if (not (zerop (getpropertyvalue e "Closed")))
        (Text
          (GCen e)
          (* 0.05 (eHeight e))
          "Geometric-Center"
        );text
      );if
    );repeat
  );if
  (prompt "\nTEST Complete.")
  (princ)
);defun


(defun Text (pt hgt str)
  (entmakex (list (cons 0 "TEXT") (cons 10 pt) (cons 11 pt) (cons 40 hgt) (cons 1 str) (cons 72 1) (cons 73 2)))
)

(defun GCen (e / )
  (command "_.DRAWORDER" e "" "_f")
  (osnap (vlax-curve-getstartpoint e) "gcen")
)

(defun PolyPoints (e / return cnt)
  (repeat (setq cnt (fix (getpropertyvalue e "EndParam")))
    (setq return
      (cons
        (list (getpropertyvalue e "Vertices" (setq cnt (1- cnt)) "Position/X")
              (getpropertyvalue e "Vertices" cnt "Position/Y"))
        return
      );cons
    );setq
  );repeat
)

(defun corners (points) ; <-- compliments of dbroad
  (list
    (apply 'mapcar (cons 'min points))
    (apply 'mapcar (cons 'max points)))
)

(defun eHeight (e / cnr)
  (setq cnr (corners (PolyPoints e)))
  (- (cadadr cnr) (cadar cnr))
)

 

Best,

~DD

0 Likes
Message 7 of 9

Kent1Cooper
Consultant
Consultant

@bart.tuytten wrote:

....

I integrated the code you suggested adapting the 'Delobj' to 0, though I got some error:

 

Command: Error: ActiveX Server returned the error: unknown name: "Centroid"

....


It returns a point list for me.  Without seeing the overall context, I couldn't say what it might be, except if a Polyline was not closed [not even visually], so it couldn't make a Region from it, but then Geometric-Center Osnap wouldn't work on it, either.

Kent Cooper, AIA
0 Likes
Message 8 of 9

bart.tuytten
Contributor
Contributor

Hello,

 

it took some time for me to test your code.

Unfortunately this code leads to the same issue.

The 'Geometric-Center' text appears in an adjacent polyline,

I assume when the adjacent geometric center is more near.

 

Yet I appreciate your input very much.

Thank you for considering my question and sending your post.

 

Regards, Bart Tuytten

0 Likes
Message 9 of 9

bart.tuytten
Contributor
Contributor

Hello,

 

this evening I tested the method through region once again.

And now it seems to run.

The 'unknown name: "Centroid"' does not appear anymore.

Unfortunately I can't indicate what was going wrong earlier.

 

I will indicate your input as a solution, as it might help other lisp fanatics.

 

Thanks again for your reply,

Bart Tuytten

0 Likes