TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: highflyingbird on July 22, 2012, 01:56:09 PM

Title: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 22, 2012, 01:56:09 PM
Is there an simple algorithm for calculating maximum inscribed circle into a convex polygon (even a curve)?
It's  also called MIC problem.
See  here (http://en.wikipedia.org/wiki/Roundness_(object)).

I wrote a routine,but it's very slow and it's  wrong sometimes.
I will post my lisp code later.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 23, 2012, 01:56:02 AM
I'm sorry. It is challenging and I can not spend as much time to solve it.

On the solution of this problem have to spend two days. On the qualitative solution - Week...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 23, 2012, 02:03:55 AM
I was faced with similar challenges.
At various times I used the three algorithms
1. analysis of the geometry of the bounding segments (perpendicular, the centers of arcs, etc).
2. approximation of the internal space of the pixels and finding the greatest area filled with pixels.
3. method of inflating the bubble.

was the most efficient region filling in squares, and further analysis of the internal squares as pixels, as points.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 23, 2012, 06:19:27 AM
I was faced with similar challenges.
At various times I used the three algorithms
1. analysis of the geometry of the bounding segments (perpendicular, the centers of arcs, etc).
2. approximation of the internal space of the pixels and finding the greatest area filled with pixels.
3. method of inflating the bubble.

was the most efficient region filling in squares, and further analysis of the internal squares as pixels, as points.
ElpanovEvgeniy,thank you!
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 23, 2012, 10:57:42 AM
ElpanovEvgeniy,thank you!

thanks for that I will not participate in the contest...
Do I understand correctly?  :-D :-D :-D
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 23, 2012, 11:37:30 AM
ElpanovEvgeniy,thank you!

thanks for that I will not participate in the contest...
Do I understand correctly?  :-D :-D :-D

No, my thanks for your good idea indeed,sometimes your idea helped me a lot.
maybe it's really  hard problem,but some genius  will solve it.who knows? :lmao:
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on July 23, 2012, 06:16:27 PM
You can approximate?  :-)

Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; Gian Paolo Cattaneo

(defun C:TesT (/ POLY POLY_vl Dx Dy Lp List_vert_poly list_p_int P_center dist step1 step2)
    (prompt "\nSelect Polyline: ")
    (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
        (progn
            (setq i 1 timer (date2sec))
            (setq step1 60) ;--> grid_1
            (setq step2 20) ;--> grid_2
            (setq POLY_vl (vlax-ename->vla-object POLY))
            (setq list_vert_poly (LM:LWPoly->List POLY))
            (grid_1)   
            (Point_int)
            (grid+)
            (Point_center)
            (repeat 3
                (grid_2)
                (Point_center)
            )
            (entmake
                (list
                    (cons 0 "CIRCLE")
                    (cons 8 (getvar "clayer"))
                    (cons 10 P_center)
                    (cons 40 dist)
                )
            )
            (setq endtimer (date2sec))
            (princ (strcat "time = "(rtos (- endtimer timer) 2 3) " seconds")) 
            (princ)
        )
    )
)


;; LWPolyline to Point List  -  Lee Mac
;; Returns a list of points describing the supplied LWPolyline
(defun LM:LWPoly->List ( ent / der di1 di2 inc lst par rad )
    (setq par 0)
    (repeat (cdr (assoc 90 (entget ent)))
        (if (setq der (vlax-curve-getsecondderiv ent par))
            (if (equal der '(0.0 0.0 0.0) 1e-8)
                (setq lst (cons (vlax-curve-getpointatparam ent par) lst))
                (if
                    (setq rad (distance '(0.0 0.0) (vlax-curve-getfirstderiv ent par))
                          di1 (vlax-curve-getdistatparam ent par)
                          di2 (vlax-curve-getdistatparam ent (1+ par))
                    )
                    (progn
                        (setq inc (/ (- di2 di1) (1+ (fix (* 25 (/ (- di2 di1) rad (+ pi pi)))))))
                        (while (< di1 di2)
                            (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                                  di1 (+ di1 inc)
                            )
                        )
                    )
                )
            )
        )
        (setq par (1+ par))
    )
    lst
)

; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
; Returns a grid of points within the BoundingBox of the selected poly
(defun grid_1 (/ P1_ P2_ n P> )
    (vla-getboundingbox POLY_vl 'p1 'p2)
    (setq P1_ (vlax-safearray->list p1))
    (setq P2_ (vlax-safearray->list p2))
    (setq P1_ (list (car P1_) (cadr P1_)))
    (setq P2_ (list (car P2_) (cadr P2_)))
    (setq Dx (/ (- (car P2_) (car P1_)) step1))
    (setq Dy (/ (- (cadr P2_) (cadr P1_)) step1))
    (setq n 0)
    (setq P> P1_)
    (setq Lp (list P1_))
    (repeat (* (1+ step1) step1)
        (setq P> (list (+ (car P>) Dx) (cadr P>)))
        (setq Lp (cons P> Lp))
        (setq n (1+ n))
        (if (= n step1)
            (progn
                (setq n 0)
                (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
                (setq P> P1_)
                (setq Lp (cons P> Lp))
            )
        )
    )
    (setq Lp (cdr Lp))
)


; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
; Returns a grid of points around the center point (provisional)
(defun grid_2 (/ P1_  P> n)
    (setq list_p_int nil)
    (setq P1_ (list (- (car P_center) (* Dx 2)) (- (cadr P_center) (* Dy 2))))
    (setq Dx (/ (* 4 Dx) step2))
    (setq Dy (/ (* 4 Dy) step2))
    (setq n 0)
    (setq P> P1_)
    (setq list_p_int (list P1_))
    (repeat (* (1+ step2) step2)
        (setq P> (list (+ (car P>) Dx) (cadr P>)))
        (setq list_p_int (cons P> list_p_int))
        (setq n (1+ n))
        (if (= n step2)
            (progn
                (setq n 0)
                (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
                (setq P> P1_)
                (setq list_p_int (cons P> list_p_int))
            )
        )
    )
)
   

; restituisce la lista dei punti interni ad un poligono
; dati:  - lista coordinate dei punti -> Lp
;        - lista coordinate vertici poligono -> list_vert_poly
; Returns the list of points inside the polyline
(defun Point_int (/ P_distant n Pr cont attr p# Pa Pa_ Pb )
    (setq P_distant (list (car (getvar "extmax")) (* 2 (cadr (getvar "extmax")))))   
    (setq list_p_int nil)
    (foreach Pr Lp
        (setq cont -1)
        (setq attr 0)
        (setq p# nil)
        (setq Pa (nth (setq cont (1+ cont)) list_vert_poly))
        (setq Pa_ Pa)
        (repeat (length list_vert_poly)
            (setq Pb (nth (setq cont (1+ cont)) list_vert_poly))
            (if (= cont (length list_vert_poly)) (setq Pb Pa_))
            (setq P# (inters Pa Pb Pr P_distant))
            (if (/= P# nil) (setq attr (1+ attr)))
            (setq Pa Pb)
        )
        (if (> (rem attr 2) 0) (setq list_p_int (cons Pr list_p_int)))    
    )
)


; Infittisce la griglia inserendo altri punti
; nel centro delle diagonali tra i punti interni
; Insert points (interior) to increase the density of the grid
(defun grid+ (/ G+)
    (setq G+
        (mapcar '(lambda ( x ) (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))) list_p_int)
    )
    (setq list_p_int (append G+ list_p_int))
)


; Da una lista di punti restituisce quello pił lontano da un oggetto
; dati:  - lista dei punti -> list_p_int
;        - oggetto -> POLY_vl
; Returns the farthest point from the polyline
(defun Point_center (/ Pa n Pvic)
    (setq Dist 0.0000001)
    (setq P_center nil)
    (foreach Pa list_p_int
(setq Pvic (vlax-curve-getClosestPointTo POLY_vl Pa))
        (if (> (distance Pa Pvic) Dist)
            (progn
                (setq P_center Pa)
                (setq Dist (distance Pa Pvic))
            )
        )
    )
)


(defun date2sec ()
  (setq s (getvar "DATE"))
  (setq seconds (* 86400.0 (- s (fix s))))
)

(vl-load-com)
(princ)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 23, 2012, 09:29:57 PM
You can approximate?  :-)

Code: [Select]
...

Wonderful!!GP!thank you so much.
I will take some time to study your code.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 24, 2012, 02:30:31 AM
You can approximate?  :-)

good implementation of my algorithm!  :-)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 24, 2012, 02:42:10 AM
I'll talk about more than performance of the algorithm - a lot of simple calculations...

1. create a matrix of pixels inside the contour.
2. take a round brush (mathematics) and fill points inside
3. find the most shaded area - there must be a center.

example of the brush:
Code: [Select]
    1 2 1
  2 3 4 3 2
1 3 4 5 4 3 1
2 4 5 6 5 4 2
1 3 4 5 4 3 1
  2 3 4 3 2
    1 2 1
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 24, 2012, 02:50:24 AM
example of the brush:

if the area of maximizing the numbers are very large, you can re-paint only to this area or use a larger brush at once, for large polyline.

just the algorithm is very good for finding the middle line - skilet for any shape, such as a tree.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 24, 2012, 07:15:41 AM
You can approximate?  :-)

Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; Gian Paolo Cattaneo

(defun C:TesT (/ POLY POLY_vl Dx Dy Lp List_vert_poly list_p_int P_center dist step1 step2)
    (prompt "\nSelect Polyline: ")
    (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
        (progn
            (setq i 1 timer (date2sec))
            (setq step1 60) ;--> grid_1
            (setq step2 20) ;--> grid_2
            (setq POLY_vl (vlax-ename->vla-object POLY))
            (setq list_vert_poly (LM:LWPoly->List POLY))
            (grid_1)   
            (Point_int)
            (grid+)
            (Point_center)
            (repeat 3
                (grid_2)
                (Point_center)
            )
            (entmake
                (list
                    (cons 0 "CIRCLE")
                    (cons 8 (getvar "clayer"))
                    (cons 10 P_center)
                    (cons 40 dist)
                )
            )
            (setq endtimer (date2sec))
            (princ (strcat "time = "(rtos (- endtimer timer) 2 3) " seconds")) 
            (princ)
        )
    )
)


;; LWPolyline to Point List  -  Lee Mac
;; Returns a list of points describing the supplied LWPolyline
(defun LM:LWPoly->List ( ent / der di1 di2 inc lst par rad )
    (setq par 0)
    (repeat (cdr (assoc 90 (entget ent)))
        (if (setq der (vlax-curve-getsecondderiv ent par))
            (if (equal der '(0.0 0.0 0.0) 1e-8)
                (setq lst (cons (vlax-curve-getpointatparam ent par) lst))
                (if
                    (setq rad (distance '(0.0 0.0) (vlax-curve-getfirstderiv ent par))
                          di1 (vlax-curve-getdistatparam ent par)
                          di2 (vlax-curve-getdistatparam ent (1+ par))
                    )
                    (progn
                        (setq inc (/ (- di2 di1) (1+ (fix (* 25 (/ (- di2 di1) rad (+ pi pi)))))))
                        (while (< di1 di2)
                            (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                                  di1 (+ di1 inc)
                            )
                        )
                    )
                )
            )
        )
        (setq par (1+ par))
    )
    lst
)

; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
; Returns a grid of points within the BoundingBox of the selected poly
(defun grid_1 (/ P1_ P2_ n P> )
    (vla-getboundingbox POLY_vl 'p1 'p2)
    (setq P1_ (vlax-safearray->list p1))
    (setq P2_ (vlax-safearray->list p2))
    (setq P1_ (list (car P1_) (cadr P1_)))
    (setq P2_ (list (car P2_) (cadr P2_)))
    (setq Dx (/ (- (car P2_) (car P1_)) step1))
    (setq Dy (/ (- (cadr P2_) (cadr P1_)) step1))
    (setq n 0)
    (setq P> P1_)
    (setq Lp (list P1_))
    (repeat (* (1+ step1) step1)
        (setq P> (list (+ (car P>) Dx) (cadr P>)))
        (setq Lp (cons P> Lp))
        (setq n (1+ n))
        (if (= n step1)
            (progn
                (setq n 0)
                (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
                (setq P> P1_)
                (setq Lp (cons P> Lp))
            )
        )
    )
    (setq Lp (cdr Lp))
)


; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
; Returns a grid of points around the center point (provisional)
(defun grid_2 (/ P1_  P> n)
    (setq list_p_int nil)
    (setq P1_ (list (- (car P_center) (* Dx 2)) (- (cadr P_center) (* Dy 2))))
    (setq Dx (/ (* 4 Dx) step2))
    (setq Dy (/ (* 4 Dy) step2))
    (setq n 0)
    (setq P> P1_)
    (setq list_p_int (list P1_))
    (repeat (* (1+ step2) step2)
        (setq P> (list (+ (car P>) Dx) (cadr P>)))
        (setq list_p_int (cons P> list_p_int))
        (setq n (1+ n))
        (if (= n step2)
            (progn
                (setq n 0)
                (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
                (setq P> P1_)
                (setq list_p_int (cons P> list_p_int))
            )
        )
    )
)
   

; restituisce la lista dei punti interni ad un poligono
; dati:  - lista coordinate dei punti -> Lp
;        - lista coordinate vertici poligono -> list_vert_poly
; Returns the list of points inside the polyline
(defun Point_int (/ P_distant n Pr cont attr p# Pa Pa_ Pb )
    (setq P_distant (list (car (getvar "extmax")) (* 2 (cadr (getvar "extmax")))))   
    (setq list_p_int nil)
    (foreach Pr Lp
        (setq cont -1)
        (setq attr 0)
        (setq p# nil)
        (setq Pa (nth (setq cont (1+ cont)) list_vert_poly))
        (setq Pa_ Pa)
        (repeat (length list_vert_poly)
            (setq Pb (nth (setq cont (1+ cont)) list_vert_poly))
            (if (= cont (length list_vert_poly)) (setq Pb Pa_))
            (setq P# (inters Pa Pb Pr P_distant))
            (if (/= P# nil) (setq attr (1+ attr)))
            (setq Pa Pb)
        )
        (if (> (rem attr 2) 0) (setq list_p_int (cons Pr list_p_int)))    
    )
)


; Infittisce la griglia inserendo altri punti
; nel centro delle diagonali tra i punti interni
; Insert points (interior) to increase the density of the grid
(defun grid+ (/ G+)
    (setq G+
        (mapcar '(lambda ( x ) (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))) list_p_int)
    )
    (setq list_p_int (append G+ list_p_int))
)


; Da una lista di punti restituisce quello pił lontano da un oggetto
; dati:  - lista dei punti -> list_p_int
;        - oggetto -> POLY_vl
; Returns the farthest point from the polyline
(defun Point_center (/ Pa n Pvic)
    (setq Dist 0.0000001)
    (setq P_center nil)
    (foreach Pa list_p_int
(setq Pvic (vlax-curve-getClosestPointTo POLY_vl Pa))
        (if (> (distance Pa Pvic) Dist)
            (progn
                (setq P_center Pa)
                (setq Dist (distance Pa Pvic))
            )
        )
    )
)


(defun date2sec ()
  (setq s (getvar "DATE"))
  (setq seconds (* 86400.0 (- s (fix s))))
)

(vl-load-com)
(princ)
Great routine !
May need higher accuracy ?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 24, 2012, 07:32:19 AM
...
Great routine !
May need higher accuracy ?

replace
Code: [Select]
(repeat 3
  (grid_2)
  (Point_center)
)
for
Code: [Select]
(repeat 8
  (grid_2)
  (Point_center)
)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on July 24, 2012, 02:26:22 PM
Thanks to all.  :-)
This was the request in my thread here (http://www.cadtutor.net/forum/showthread.php?63874-Maximum-circle-inscribed-in-a-closed-polyline):

I try to explain how it works:

(grid_1)
Calculation of the grid points within the getboundingbox of poly,
Subdivision = (step1 x step1)
Increase the value of step1 for greater certainty of outcome
I think step1 = 60 a good relationship time/accuracy

(Point_int)
Calculation of internal points on the polyline

(grid+)
Increase the density of the grid points (only internal).

(Point_center)
Calculation of the farthest point from the polyline
   
(grid_2)
Calculation of a new (dense) grid of points around the center provisionally calculated


The result is approximated.
Perhaps for the exact solution:
1.Construct the Voronoi Diagram of the edges in P. This can be done with, for example, Fortunes algorithm;
2.For Voronoi nodes (points equidistant to three or more edges) inside P;
3.Find the node with the maximum distance to edges in P. This node is the centre of the maximum inscribed circle.


http://stackoverflow.com/questions/4279478/maximum-circle-inside-a-non-convex-polygon
Voronoi Diagram (http://en.wikipedia.org/wiki/Voronoi_diagram)
Fortunes algorithm (http://en.wikipedia.org/wiki/Fortune%27s_algorithm)

Ciao

Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 25, 2012, 02:12:35 AM
replace
Code: [Select]
(repeat 3
  (grid_2)
  (Point_center)
)
for
Code: [Select]
(repeat 8
  (grid_2)
  (Point_center)
)
Thanks ElpanovEvgeniy.
I've test 'repeat 8 ... , it take the same result .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 25, 2012, 02:18:16 AM
When set step1=100 step2=40 , It get right .
Code: [Select]
...
(progn
            (setq i 1 t1 (getvar "MilliSecs"))
            (setq step1 100) ;--> grid_1
            (setq step2 40) ;--> grid_2
            (setq POLY_vl (vlax-ename->vla-object POLY))
            (setq list_vert_poly (LM:LWPoly->List POLY))
            (grid_1)   
            (Point_int)
            (grid+)
            (Point_center)
            (repeat 2
                (grid_2)
                (Point_center)
            )
            (entmake
                (list
                    (cons 0 "CIRCLE")                   
                    (cons 10 P_center)
                    (cons 40 dist)
                )
            )
            (setq t2 (getvar "MilliSecs"))
            (princ (strcat "time = "(rtos (- t2 t1) 2 0) " MilliSecs")) 
            (princ)
        )
...
Perhaps , When the grid division is not small enough in step1 ,  ALL close to the max-dia zone from step1 must be calculated in step2  ?
Code: [Select]
    1 2 1
  2 3 4 3 2
1 3 4 5 4 3 1
2 4 5 6 5 4 2
1 3 4 5 4 3 1
  2 3 4 3 2
    1 2 1   1 2 1
          2 3 4 3 2
        1 3 4 5 4 3 1
          2 3 4 3 1
            1 2 1
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 25, 2012, 03:07:14 AM

Code: [Select]
    1 2 1
  2 3 4 3 2
1 3 4 5 4 3 1
2 4 5 6 5 4 2
1 3 4 5 4 3 1
  2 3 4 3 2
    1 2 1   1 2 1
          2 3 4 3 2
        1 3 4 5 4 3 1
          2 3 4 3 1
            1 2 1

Use a round brush, I tried to explain to another algorithm!
Now I will prepare an explanation ...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 25, 2012, 03:53:16 AM
matrix take shape and fill it with a brush matrix
then add up the numbers and find the position of the greatest number.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 25, 2012, 06:01:37 AM
Thanks  ElpanovEvgeniy's very good idea , thanks GP's code!
Quote from: lee mac
Here we have:
 
1) It is obvious that circle is inside of the boundary.
 2) Circle must touch the boundary in at least 2 places.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 25, 2012, 06:24:36 AM
This is not just an idea - it really works the algorithm used in one of my projects. Allows you to find more space in the lwpolyline and find the skeleton of the contour. The skeleton - the middle line long or branching areas.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on July 25, 2012, 04:37:32 PM
Perhaps , When the grid division is not small enough in step1 ,  ALL close to the max-dia zone from step1 must be calculated in step2  ?

Is very important to the value of (step1)
If there are areas of similar size could potentially contain the maximum circle, it is appropriate to increase this value, to the detriment of the time required.
Increasing the value of (repeat N (grid_2) (Point_center)) is then refined the position of point searched.

(grid_1) ---> subdivision = step1 x step1

(grid_2) ---> subdivision = step2 x step2
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 26, 2012, 02:19:37 AM
...
GP,Very good explanation,a lot of thanks.

ElpanovEvgeniy, Yes,your algorithm is amazing.
My oalgorithm can get a very accurate answer,but sometimes it doesn't work,and takes a lot of  time.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 26, 2012, 03:11:04 AM

ElpanovEvgeniy, Yes,your algorithm is amazing.
My oalgorithm can get a very accurate answer,but sometimes it doesn't work,and takes a lot of  time.

I was told algorithm, more than 10 years ago.
He told me a very old wise man.
Ordered to make a shape out of plywood.
Sprinkle dry sand on plywood.
The top of the sand - the largest center of the inscribed circle.
Ridges of - the contour of the skeleton.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 26, 2012, 03:49:15 AM
I was told algorithm, more than 10 years ago.
He told me a very old wise man.
Ordered to make a shape out of plywood.
Sprinkle dry sand on plywood.
The top of the sand - the largest center of the inscribed circle.
Ridges of - the contour of the skeleton.

Yes,like this: maybe it's called sand-heap analogy.

let me think of here. (http://www.theswamp.org/index.php?topic=41837.0)
they have some kind of relationship.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 26, 2012, 04:09:14 AM
in solving the problem, you can use the exact values ​​in the matrix of the brush.
Then, examining the amount received for each cell in the figure, we can find the actual slope and location of the analyzed edges and center.
But to my task, it was necessary to obtain high speed and the approximate location of the center. Integers have helped increase the speed for large matrices.

a good picture!
perfectly illustrates the algorithm.
So, I created a 3D surface to visualize the results. Z - the amount for each cell
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Stefan on July 26, 2012, 06:49:33 AM
My version
Code: [Select]
;max circle inside polyline
;Stefan M. 26.07.2012
(defun C:TEST ( / space e l m c o r p offtype)
  (setq space (vlax-get (vla-get-ActiveDocument (vlax-get-acad-object)) (if (= (getvar 'cvport) 1) 'PaperSpace 'ModelSpace)))
  (setq offtype (getvar 'offsetgaptype))
  (setvar 'offsetgaptype 1)
  (if (setq e (ssget ":E:S:L" '((0 . "LWPOLYLINE"))))
     (progn
(setq e (vlax-ename->vla-object (ssname e 0))
      l (list (vla-copy e))
      m 0.0
)
(while l
   (foreach x l
      (if
(setq c (cond ((and
                                  (= (vlax-curve-GetEndParam x) 2.0)
                                  (or
                                    (vl-some 'zerop (mapcar '(lambda (a) (vla-getbulge x a)) '(0 1)))
                                    (<=
                                      (distance
                                        (vlax-curve-GetPointAtParam x 0.5)
                                        (vlax-curve-GetPointAtParam x 1.5)
                                        )
                                      (distance
                                        (vlax-curve-GetPointAtParam x 0.0)
                                        (vlax-curve-GetPointAtParam x 1.0)
                                        )
                                      )
                                    )
                                  )
(mapcar '(lambda (a b) (* 0.5 (+ a b)))
(vlax-curve-GetPointAtParam x 0.5)
(vlax-curve-GetPointAtParam x 1.5)
)
       )
       ((and
   (= (vlax-curve-GetEndParam x) 3.0)
                                   (vlax-curve-IsClosed x)
   (vl-every 'zerop (mapcar '(lambda (a) (vla-getbulge x a)) '(0 1 2)))
)
(incircle x)
       )
                               ((and
   (= (vlax-curve-GetEndParam x) 4.0)
                                   (equal '(0. 0. 0.) (mapcar '+ (vlax-curve-GetFirstDeriv x 0.5) (vlax-curve-GetFirstDeriv x 2.5)) 1e-8)
   (equal '(0. 0. 0.) (mapcar '+ (vlax-curve-GetFirstDeriv x 1.5) (vlax-curve-GetFirstDeriv x 3.5)) 1e-8)
)
                                (median x)
                                )
       ((< (vla-get-area x) 1e-7) (median x))
)
)
(if
    (equal (setq r (distance c (vlax-curve-GetClosestPointTo e c))) m 1e-8)
    (setq p (cons (list c r) p))
    (if (> r m) (setq p (list (list c r)) m r))
)
(setq o (append (offset_in x) o))
      )
      (vla-delete x)
   )
   (setq l o o nil)
)
(foreach x p (vla-put-Color (vla-AddCircle space (vlax-3D-point (car x)) (cadr x)) acRed))
     )
  )
  (setvar 'offsetgaptype offtype)
  (princ)
)

(defun incircle (e / a b c p pt)
  (setq a (vlax-curve-GetDistAtParam e 1)
        b (- (vlax-curve-GetDistAtParam e 2) a)
        c (- (setq p (vlax-curve-GetDistAtParam e 3)) a b)
        pt (mapcar 'vlax-curve-GetPointAtParam (list e e e) '(2 3 1))
        )
  (mapcar
    '(lambda (x) (/ (apply '+ (mapcar '* (list a b c) x)) p))
    (list
      (mapcar 'car pt)
      (mapcar 'cadr pt)
      )
    )
  )

(defun median (e / i l n)
  (repeat
    (setq n (fix (setq i (vlax-curve-GetEndParam e))))
    (setq l (cons (vlax-curve-GetPointAtParam e (setq n (1- n))) l))
    )
  (mapcar
    '(lambda (x) (/ (apply '+ x) i))
    (list
      (mapcar 'car l)
      (mapcar 'cadr l)
      )
    )
  )

(defun offset_in (e / i)
   (setq i (/ (vla-get-Area e) (vla-get-Length e) 10.0))
   (apply
      'append
      (mapcar
         (function
            (lambda (x / o)
               (if
                  (not (vl-catch-all-error-p (setq o (vl-catch-all-apply 'vlax-invoke (list e 'Offset x)))))
                    (vl-remove-if
                       '(lambda (a)
                           (and
                              (or
                                 (> (vla-get-Area a) (vla-get-Area e))
                                 (> (vla-get-Length a) (vla-get-Length e))
                              )
                              (not (vla-delete a))
                           )
                        )
                       o
                    )
               )
            )
         )
         (list i (- i))
      )
   )
)

EDIT: fixed some bugs
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: DEVITG on July 26, 2012, 11:56:31 PM

For the 2 solution , amazing , outstanding

Thanks for such beatifull works.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on July 27, 2012, 03:34:05 AM
Stefan,
great code!  :kewl:
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: highflyingbird on July 27, 2012, 04:22:59 AM
Stefan,Excellent!! 8-)
Both of you are geniuses!
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Stefan on July 27, 2012, 05:17:25 AM
Thank you guys!
It is working in most situations, but I found some when is giving a wrong result (see image 1)
Beside, there is an issue about what is "inside" and "outside" of a pline. (see img2)

P.S. How to embed an image into a post?  :oops:
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 27, 2012, 01:56:21 PM
Perhaps , When the grid division is not small enough in step1 ,  ALL close to the max-dia zone from step1 must be calculated in step2  ?

Is very important to the value of (step1)
If there are areas of similar size could potentially contain the maximum circle, it is appropriate to increase this value, to the detriment of the time required.
Increasing the value of (repeat N (grid_2) (Point_center)) is then refined the position of point searched.

(grid_1) ---> subdivision = step1 x step1

(grid_2) ---> subdivision = step2 x step2
Wonderful explanation, GP, Thank you very much.

Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 27, 2012, 02:34:24 PM
Stefan,Excellent!! 8-)
Both of you are geniuses!
1+

I guess, AutoCAD has its own regulations on the offset curve .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 27, 2012, 02:41:23 PM
matrix take shape and fill it with a brush matrix
then add up the numbers and find the position of the greatest number.
Excellent algorithm !
Look forward to further implementation .

Does it has been used in the AutoCAD Core Applications ?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 27, 2012, 11:34:22 PM
matrix take shape and fill it with a brush matrix
then add up the numbers and find the position of the greatest number.
Excellent algorithm !
Look forward to further implementation .

Does it has been used in the ?

Yes, I have used this algorithm in one of the commercial programs. I can not publish the code here, and details of use. But I have shown the way!

I do not work in the autodesk, though, I am now a member of the ADN.
I think that these algorithms are not used in AutoCAD Core Applications, but can not be sure...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 28, 2012, 02:34:16 AM
Yes, I have used this algorithm in one of the commercial programs. I can not publish the code here, and details of use. But I have shown the way!
Depth explanation of the grid method , Thanks again .
I think that these algorithms are not used in AutoCAD Core Applications, but can not be sure...
In some old acad versions , I miss seen that boundary can be created by two method , one is Filling Method , another is Ray Method .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 28, 2012, 03:04:00 AM
"Ray Method" is a method for determining the inside or the outside.
In their programs, I use another method to determine the inside or the outside. It does not require checking the intersection and running quickly.

need to check the direction of a polyline, the angle between the direction of the polyline and the first derivative. If 0 < A < pi and polyline counter-clockwise, the point is inside. If the nearest point on the polyline gets on top, should be repeated to a neighboring segment. further

PS. ray method sometimes gives an error - if the beam passes through the tangent to the path and not falling into one point of intersection gives the...
therefore, I developed another method that works fast enough...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 29, 2012, 02:47:33 PM
"Ray Method" is a method for determining the inside or the outside.
In their programs, I use another method to determine the inside or the outside. It does not require checking the intersection and running quickly.

need to check the direction of a polyline, the angle between the direction of the polyline and the first derivative. If 0 < A < pi and polyline counter-clockwise, the point is inside. If the nearest point on the polyline gets on top, should be repeated to a neighboring segment. further

PS. ray method sometimes gives an error - if the beam passes through the tangent to the path and not falling into one point of intersection gives the...
therefore, I developed another method that works fast enough...
Thanks ElpanovEvgeniy .
Agree with you , but I have not understood that how to determine which point's and how many point's First derivative in the Curve ?
For polygon ,  one by one ; For Polyline (contained arcs) or other type curve ?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Faster on July 29, 2012, 10:29:31 PM
According to ElpanovEvgeniy's algorithm,I wrote the following codes:
Code - Auto/Visual Lisp: [Select]
  1. (defun PtInPOLY-P  (POLY PT / CP PL PARAM DEV A)
  2.   (defun LM:ListClockwise-p ( lst )
  3.     (minusp
  4.         (apply '+
  5.             (mapcar
  6.                 (function
  7.                     (lambda ( a b )
  8.                         (- (* (car b) (cadr a)) (* (car a) (cadr b)))
  9.                     )
  10.                 )
  11.                 lst (cons (last lst) lst)
  12.             )
  13.         )
  14.     )
  15. )
  16.  
  17.  
  18.   (cond
  19.     ((equal pt
  20.             (setq cp (vlax-curve-getclosestpointto poly pt))
  21.             1e-8))
  22.     (t
  23.      (setq pl
  24.             (mapcar
  25.               'cdr
  26.               (vl-remove-if-not
  27.                 '(lambda (x) (= 10 (car x)))
  28.                 (entget poly)
  29.                 )
  30.               )
  31.            )
  32.      (setq param (vlax-curve-getparamatpoint poly cp))
  33.      (if (not (setq dev (vlax-curve-getFirstDeriv poly param)))
  34.        (if (not (setq dev (vlax-curve-getFirstDeriv
  35.                             poly
  36.                             (setq param (+ 1e-8 param)))))
  37.          (setq dev (vlax-curve-getFirstDeriv
  38.                      poly
  39.                      (setq param (- param 1e-8 1e-8))))
  40.          )
  41.        )
  42.      (setq cp (vlax-curve-getpointatparam poly param))
  43.      (setq a (- (angle cp pt) (angle '(0 0 0) dev)))
  44.      (if (MINUSP a)
  45.        (setq a (+ a pi pi)))
  46.      (if (LM:ListClockwise-p pl)
  47.        (> a pi)
  48.        (< a pi)
  49.        )
  50.      )
  51.     )
  52.   )
  53.  
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 29, 2012, 11:44:16 PM
good code
It does not take into account details.
1. As I said, if the closest point falls on the top, you need to jointly consider both segments.
2. check the direction of a polyline, written by Lee does not work with polylines having arc segments.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 29, 2012, 11:53:25 PM
 Direction and Reverse lwpolyline  (http://www.theswamp.org/index.php?topic=12220.msg151275#msg151275)
 :-)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Faster on July 30, 2012, 02:41:24 AM
good code
It does not take into account details.
1. As I said, if the closest point falls on the top, you need to jointly consider both segments.
2. check the direction of a polyline, written by Lee does not work with polylines having arc segments.
Thank you  ElpanovEvgeniy!
This is improved version:
I wondered why the function "LM:ListClockwise-p " does not work with polylines having arc segments.
Code - Auto/Visual Lisp: [Select]
  1. (defun PtInPOLY-P  (POLY PT        /       CP      LW
  2.                                    MINP    MAXP    MINX    MINY
  3.                                    MAXX    MAXY    X       Y
  4.                                    LST     CLOCKWISEP      ENDPARAM
  5.                                    CURVELENGTH     PARAM   DIST
  6.                                    D1      D2      DEV     A)
  7.   (cond
  8.     ((equal pt
  9.             (setq cp (vlax-curve-getclosestpointto poly pt))
  10.             1e-8))
  11.     ((progn
  12.        (vla-GetBoundingBox
  13.          (setq lw (vlax-ename->vla-object POLY))
  14.          'MinP
  15.          'MaxP)
  16.        (setq MinP (vlax-safearray->list MinP))
  17.        (setq MaxP (vlax-safearray->list MaxP))
  18.        (setq minx (car MinP)
  19.              miny (cadr MinP)
  20.              maxx (car MaxP)
  21.              maxy (cadr MaxP)
  22.              x    (car pt)
  23.              y    (cadr pt)
  24.              )
  25.        (or (< x minx)
  26.            (> x maxx)
  27.            (< y miny)
  28.            (> y maxy)
  29.            )
  30.        )
  31.      NIL
  32.      )
  33.     (t
  34.      (setq
  35.        lst (mapcar
  36.              (function
  37.                (lambda (x)
  38.                  (vlax-curve-getParamAtPoint
  39.                    lw
  40.                    (vlax-curve-getClosestPointTo lw x)
  41.                    )
  42.                  )
  43.                )
  44.              (list minp
  45.                    (list minx maxy)
  46.                    MaxP
  47.                    (list maxx miny)
  48.                    )
  49.              )
  50.        )
  51.      (setq ClockwiseP
  52.             (if (or
  53.                   (<= (car lst) (cadr lst) (caddr lst) (cadddr lst))
  54.                   (<= (cadr lst) (caddr lst) (cadddr lst) (car lst))
  55.                   (<= (caddr lst) (cadddr lst) (car lst) (cadr lst))
  56.                   (<= (cadddr lst) (car lst) (cadr lst) (caddr lst))
  57.                   ) ;_  or
  58.               t
  59.               ) ;_  if
  60.            )
  61.      (setq endparam    (vlax-curve-getendparam poly)
  62.            curvelength (vlax-curve-getDistAtParam poly endparam)
  63.            )
  64.      (setq param (vlax-curve-getparamatpoint poly cp)
  65.            dist  (vlax-curve-getDistAtParam poly param)
  66.            )
  67.      (if (equal param (fix param) 1e-8)
  68.        (progn
  69.          (setq d1 (- dist 1e-8))
  70.          (if (minusp d1)
  71.            (setq d1 (+ curvelength d1))
  72.            )
  73.          (setq d2 (+ dist 1e-8))
  74.          (if (> d2 curvelength)
  75.            (setq d2 (- d2 curvelength)))
  76.          (if (< (distance pt (vlax-curve-getpointatdist poly d1))
  77.                 (distance pt (vlax-curve-getpointatdist poly d2))
  78.                 )
  79.            (setq param (vlax-curve-getparamatdist poly d1))
  80.            (setq param (vlax-curve-getparamatdist poly d2))
  81.            )
  82.          )
  83.        )
  84.      (setq dev (vlax-curve-getFirstDeriv poly param)
  85.            cp  (vlax-curve-getpointatparam poly param)
  86.            )
  87.      ;|(setq a (- (angle cp pt) (angle '(0 0 0) dev)))
  88.      (if (MINUSP a)
  89.        (setq a (+ a pi pi)))
  90.      (if ClockwiseP
  91.        (> a pi)
  92.        (< a pi)
  93.        )|;
  94.   ;;Another alternative judge method
  95.        (=       ClockwiseP
  96.         (
  97.          (lambda (p1 p2 p3)
  98.            (<
  99.              (* (- (car p2) (car p1)) (- (cadr p3) (cadr p1)))
  100.              (* (- (cadr p2) (cadr p1)) (- (car p3) (car p1)))
  101.              )
  102.            )
  103.           pt
  104.           cp
  105.           (mapcar '+ cp dev)
  106.           )
  107.         )
  108.      )
  109.     )
  110.   )
  111.  
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 30, 2012, 03:49:55 AM
I wondered why the function "LM:ListClockwise-p " does not work with polylines having arc segments.

which direction this lwpolyline?

The code Lee will give the wrong direction...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Faster on July 30, 2012, 04:09:42 AM
I wondered why the function "LM:ListClockwise-p " does not work with polylines having arc segments.

which direction this lwpolyline?

The code Lee will give the wrong direction...
I see, thank you very much.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on July 30, 2012, 11:41:17 AM
This is improved version:
I wondered why the function "LM:ListClockwise-p " does not work with polylines having arc segments.
Hi Faster , good codes.
Test not ok for Self-intersecting curves , I post the test dwg .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Faster on July 30, 2012, 08:45:59 PM
This is improved version:
I wondered why the function "LM:ListClockwise-p " does not work with polylines having arc segments.
Hi Faster , good codes.
Test not ok for Self-intersecting curves , I post the test dwg .
I think ElpanovEvgeniy's  algorithm for Self-intersecting curves may be invalid!
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ElpanovEvgeniy on July 31, 2012, 12:07:01 AM
I think ElpanovEvgeniy's  algorithm for Self-intersecting curves may be invalid!

Yes!  :-)
I developed an algorithm for use in production.
You can not make the part that has self-intersection...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: VVA on July 31, 2012, 04:07:49 AM
I have long been using the algorithm proposed by Eugene. Thank him again.   :lol: On the topic of all polylinienrichtungen counterclockwise (http://www.cadtutor.net/forum/showthread.php?59671-all-polylinienrichtungen-counterclockwise&p=405007&viewfull=1#post405007) Irneb offered another option for the Self-intersecting curves
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: irneb on July 31, 2012, 11:16:38 AM
That code of mine still doesn't work on the PL as per Evgeniy's example in post #42. And it's debatable on which direction you "say" a self-intersecting polyline is. All my code does is to sum the changes in angles between vectors - then testing if the sum is positive / negative. So a very large vector has the same weighting as a very small one. I think this is where the issue might be resolved.

As I understand it, a "true" reflection of self-intersecting polylines might be derived by generating the intersection areas, calculating their directions and weighting by their areas.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: irneb on July 31, 2012, 11:38:45 AM
Perhaps using a similar approach to my original, but splitting the polyline into equal parts instead of simply by vectors:
Code - Auto/Visual Lisp: [Select]
  1. (defun pl-ccw-p  (obj / angle@par EndPar grain par delta aT a1 a2)
  2.   (defun angle@par (par) (angle '(0.0 0.0 0.0) (vlax-curve-getFirstDeriv obj par)))
  3.   (setq grain 1000
  4.         delta (/ (setq EndPar (vlax-curve-getEndParam obj)) grain)
  5.         par   0.0
  6.         a1    (angle@par par)
  7.         aT 0.0)
  8.   (repeat grain
  9.     (setq a2 (angle@par (min EndPar (setq par (+ par delta))))
  10.           a  (- a2 a1))
  11.     (if (> (abs a) pi)
  12.       (setq a (* (if (< a 0.0)
  13.                    -1.0
  14.                    1.0)
  15.                  (- (abs a) (* pi 2)))))
  16.     (setq aT (+ aT a)
  17.           a1 a2))
  18.   (>= aT 0.0))
Though it's still not working for the self-intersecting PL as per Faster's post #45.  ::)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: CAB on July 31, 2012, 03:41:14 PM
When a pline crosses over itself how do you define direction?
And does you definition have exceptions?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Faster on August 01, 2012, 12:36:17 AM
We should define the direction of self-intersecting PL   each loop!
We cannot say the self-intersecting PL is clockwise or counter-clockwise.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: irneb on August 01, 2012, 04:02:41 AM
Exactly! If you want to define a direction for a self-crossing polyline as a whole, all I can think of is to use each loop's area as a weighting. E.g. see attached: If using this definition the left PL would be CCW and the right CW.

But it's a moot point. As Faster's said, the more important idea is figuring out the direction of each loop. Thus you have to somehow split the polyline into it's component loops, then calculate each one's direction individually (which you'd have to do in any case to figure the area weighted version as I'm suggesting).
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: Lee Mac on August 01, 2012, 04:31:11 AM
Why not use the winding number (http://en.wikipedia.org/wiki/Winding_number) of th curve to determine the overall direction?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: irneb on August 01, 2012, 06:25:21 AM
I suppose that's a good idea, but it's extremely dependent on the selection of a centroid point. E.g. following this:
Code - Auto/Visual Lisp: [Select]
  1. (defun pl-ccw-p1 (obj / len grain delta dist pts cent a1 a2 a wind)
  2.         grain 1000.
  3.         delta (/ len grain)
  4.         dist 0.
  5.         pts (list (vlax-curve-getPointAtDist obj dist))
  6.         cent (car pts))
  7.   (while (<= (setq dist (+ dist delta)) len)
  8.     (setq pts (cons (vlax-curve-getPointAtDist obj dist) pts)
  9.           cent (mapcar '+ cent (car pts))))
  10.   (setq cent (mapcar '(lambda (n) (/ n grain)) cent)
  11.         wind 0.
  12.         pts (reverse pts)
  13.         a1 (angle cent (car pts)))
  14.   (foreach pt (cdr pts)
  15.     (setq a2 (angle cent pt)
  16.           a (- a2 a1))
  17.     (if (> (abs a) pi)
  18.       (setq a (* (if (< a 0.0)
  19.                    -1.0
  20.                    1.0)
  21.                  (- (abs a) (* pi 2)))))
  22.     (setq wind (+ wind a)
  23.           a1 a2))
  24.   (>= wind 0.))
It returns CW for the left poly in my previous post, but CCW for the right one. Exactly the opposite of what I'd expect.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 01, 2012, 11:59:52 AM
Why not use the winding number (http://en.wikipedia.org/wiki/Winding_number) of th curve to determine the overall direction?
Hi Lee Mac , I try to use the method you suggest .
It can determine CW or CCW easily ,
but I don't know how to use the counts-number to determine the point is in or out for self-intersecting curves , Even get the wrong counts-number for star-polygon.
following is poor codes .
Code: [Select]
(defun c:test (/ en pt l num)
  (setq en (car (entsel "\n Select a curve :")))
  (setq l (get_closed_curve_pts en))
  (while (setq pt (getpoint "\nSelect a point :"))
    (if (equal (vlax-curve-getclosestpointto en pt) pt 1e-6)
      ;_point at curve
      (princ "\Point at the curve .")
      (progn
    (setq num (get-widding-number l pt))
   (princ (strcat "\n Counts" (rtos num 2 1)))
    ;_this often wrong result ...
    (setq num (fix num));_?
    ;_how to use counts number ?
    (cond ((< -1 num 1)
   (alert "OUT ")
  )
  ((< num 0)
   (if (= (rem num 2) 0);_does this is correct ?
     (alert "Curve clockwise , \n\r Point OUT")
     (alert "Curve clockwise , \n\r Point IN")
   )
  )
  (t
   (if (= (rem num 2) 0);_does this is correct ?
     (alert "Curve counter-clockwise , \n\r Point OUT")
     (alert "Curve counter-clockwise , \n\r Point IN")
   )
  )
    )   
  )))
  (princ)
)
;;get points of a closed curve
(defun get_closed_curve_pts (en / ent et)
  (setq
    ent (entget en)
    et (cdr (assoc 0 ent))
  )
  (cond
    ((= et "LWPOLYLINE")
     ((lambda (/ a b vetex bu p1 p2 l r ang an1 N)
(while (setq ent (member (assoc 10 ent) ent))
  (setq b     (cons (cdar ent) b)
ent   (member (assoc 42 ent) ent)
b     (cons (cdar ent) b)
ent   (cdr ent)
vetex (cons b vetex)
b     nil
  )
)
(while vetex
  (setq a     (car vetex)
vetex (cdr vetex)
bu    (car a)
p1    (cadr a)
  )
  (if l
    (setq p2 (car l))
    (setq p2 (cadr (last vetex))
  l  (cons p2 l)
    )
  )
  (if (equal bu 0 1e-6)
    (setq l (cons p1 l))
    (progn
      (setq ang (* 2 (atan bu))
    r (/ (distance p1 p2)
   (* 2 (sin ang))
)
    c (polar p1
       (+ (angle p1 p2) (- (/ pi 2) ang))
       r
)
    r (abs r)
    ang (abs (* ang 2.0))
    N (abs (fix (/ ang 0.0174532925199433)))
      )
      (if (= N 0)
(setq l (cons p1 l))
(progn
  (setq an1 (/ ang N)
ang (angle c p2)
  )
  (if (not (minusp bu))
    (setq an1 (- an1))
  )
  (repeat (1- N)
    (setq ang (+ ang an1))
    (setq l (cons (polar c ang r) l))
  )
  (setq l (cons p1 l))
)
      )
    )
  )
)
l
      )
     )
    )
    ((= et "CIRCLE")
     ((lambda (c R / sa ptl)
(setq sa 0.0)
(repeat 180
  (setq ptl (cons (polar c sa R) ptl)
sa  (+ sa 0.0174532925199433)
  )
)
(setq ptl (reverse ptl))
(append
  ptl
  (mapcar (function
    (lambda (p)
      (mapcar (function +) c (mapcar (function -) c p))
    )
  )
  ptl
  )
)
      )
       (dxf 10 ent)
       (dxf 40 ent)
     )
    )
    ((= et "SPLINE")
     ((lambda (/ r l _oce)
(setq _oce (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(if (vl-catch-all-apply
      (function vl-cmdf)
      (list "_PEDIT"
    (vlax-vla-object->ename
      (vla-copy (vlax-ename->vla-object en))
    )
    ""
    10
    ""
      )
    )
  (progn
    (setq l (ss-assoc 10 (entget (setq r (entlast)))))
    (if (vlax-curve-isClosed r)
      (setq l (append l (list (car l))))
    )
    (entdel r)
  )
)
(setvar "CMDECHO" _oce)
l
      )
     )
    )
    ((= et "ELLIPSE")
     ((lambda (/ e l _os)
(setq _os (getvar "OSMODE"))
(setvar "OSMODE" 0)
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object en) 0.1)
)
(setq e (entlast))
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object (entlast)) -0.1)
)
(entdel e)
(setq e (entlast))
(setq l (ss-assoc 10 (entget e)))
(entdel e)
(setvar "OSMODE" _os)
l
      )
     )
    )
  )
)
;;
(defun get-widding-number (l pt / ang p1 p2)
  (if (equal (car l) (last l) 1e-6)
    nil
    (setq l (append l (list (car l))))
  )
  (setq ang 0.0)
  (while (cadr l)
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
    )
    (if (equal p1 p2)
      (setq an1 0.0)
    (setq an1
   ((lambda (/  a  b c d e f g)    
    (setq b (distance p1 pt)
  c (distance p2 pt)
  a (distance p1 p2)
  d (- (* (- (car p1) (car pt)) (- (cadr p2) (cadr pt)))
       (* (- (car p2) (car pt)) (- (cadr p1) (cadr pt)))
    )
  e  (+ (* b b) (* c c) (* -1 a a))
  f (acos (/ e 2. b c))
  g (/ d (abs d)))
    (if (< e 0) (* g (- pi f))(* g f))) 
)
    ))
    (setq ang (+ ang an1))
  )
  (/ ang 2. pi)
)
;;------------------
(defun dxf (co el)
  (cdr (assoc co el))
  )
;;
(defun acos (a)
  (if (and (= (numberp a) T)
   (<= (abs a) 1.0)
      )
    (if (= a 0.0)
      (* pi 0.5)
      (atan (/ (sqrt (- 1 (* a a)))
       a
    )
      )
    )   
  )
)
;;
(defun ss-assoc (a lst / b res)
  (while (setq b (assoc a lst))
    (setq lst  (cdr (member b lst))
  res (cons (cdr b) res)
    ))(reverse res))
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 01, 2012, 02:04:06 PM
correct counts-number's error caused by the decimal precision and non-positive error in solving the angle by Law of cosines .
Now it run well .
Code: [Select]
(defun c:test (/ en pt l num)
  (setq en (car (entsel "\n Select a curve :")))
  (setq l (get_closed_curve_pts en))
  (while (setq pt (getpoint "\nSelect a point :"))
    (if (equal (vlax-curve-getclosestpointto en pt) pt 1e-6)
 ;_point at curve
      (princ "\Point at the curve .")
      (progn
(setq num (get-widding-number l pt))
(princ (strcat "\n Counts" (rtos num 2 1)))
 ;_this often wrong result , because of decimal precision ; Now correct .
(if (equal (fix num) num 1e-4)
  (setq num (fix num))
  (if (and (> num 0) (equal (1+ (fix num)) num 1e-4))
    (setq num (1+ (fix num)))
    (if (and (< num 0) (equal (1- (fix num)) num 1e-4))
      (setq num (1- (fix num)))
      (setq num (fix num)))))
 ;_how to use counts number ?
(cond ((< -1 num 1)
       (alert "OUT ")
      )
      ((< num 0)
       (if (= (rem num 2) 0) ;_does this is correct ?
(alert "Curve clockwise , \n\r Point OUT")
(alert "Curve clockwise , \n\r Point IN")
       )
      )
      (t
       (if (= (rem num 2) 0) ;_does this is correct ?
(alert "Curve counter-clockwise , \n\r Point OUT")
(alert "Curve counter-clockwise , \n\r Point IN")
       )
      )
)
      )
    )
  )
  (princ)
)
;;get points of a closed curve
(defun get_closed_curve_pts (en / ent et)
  (setq
    ent (entget en)
    et (cdr (assoc 0 ent))
  )
  (cond
    ((= et "LWPOLYLINE")
     ((lambda (/ a b vetex bu p1 p2 l r ang an1 N)
(while (setq ent (member (assoc 10 ent) ent))
  (setq b     (cons (cdar ent) b)
ent   (member (assoc 42 ent) ent)
b     (cons (cdar ent) b)
ent   (cdr ent)
vetex (cons b vetex)
b     nil
  )
)
(while vetex
  (setq a     (car vetex)
vetex (cdr vetex)
bu    (car a)
p1    (cadr a)
  )
  (if l
    (setq p2 (car l))
    (setq p2 (cadr (last vetex))
  l  (cons p2 l)
    )
  )
  (if (equal bu 0 1e-6)
    (setq l (cons p1 l))
    (progn
      (setq ang (* 2 (atan bu))
    r (/ (distance p1 p2)
   (* 2 (sin ang))
)
    c (polar p1
       (+ (angle p1 p2) (- (/ pi 2) ang))
       r
)
    r (abs r)
    ang (abs (* ang 2.0))
    N (abs (fix (/ ang 0.0174532925199433)))
      )
      (if (= N 0)
(setq l (cons p1 l))
(progn
  (setq an1 (/ ang N)
ang (angle c p2)
  )
  (if (not (minusp bu))
    (setq an1 (- an1))
  )
  (repeat (1- N)
    (setq ang (+ ang an1))
    (setq l (cons (polar c ang r) l))
  )
  (setq l (cons p1 l))
)
      )
    )
  )
)
l
      )
     )
    )
    ((= et "CIRCLE")
     ((lambda (c R / sa ptl)
(setq sa 0.0)
(repeat 180
  (setq ptl (cons (polar c sa R) ptl)
sa  (+ sa 0.0174532925199433)
  )
)
(setq ptl (reverse ptl))
(append
  ptl
  (mapcar (function
    (lambda (p)
      (mapcar (function +) c (mapcar (function -) c p))
    )
  )
  ptl
  )
)
      )
       (dxf 10 ent)
       (dxf 40 ent)
     )
    )
    ((= et "SPLINE")
     ((lambda (/ r l _oce)
(setq _oce (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(if (vl-catch-all-apply
      (function vl-cmdf)
      (list "_PEDIT"
    (vlax-vla-object->ename
      (vla-copy (vlax-ename->vla-object en))
    )
    ""
    10
    ""
      )
    )
  (progn
    (setq l (ss-assoc 10 (entget (setq r (entlast)))))
    (if (vlax-curve-isClosed r)
      (setq l (append l (list (car l))))
    )
    (entdel r)
  )
)
(setvar "CMDECHO" _oce)
l
      )
     )
    )
    ((= et "ELLIPSE")
     ((lambda (/ e l _os)
(setq _os (getvar "OSMODE"))
(setvar "OSMODE" 0)
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object en) 0.1)
)
(setq e (entlast))
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object (entlast)) -0.1)
)
(entdel e)
(setq e (entlast))
(setq l (ss-assoc 10 (entget e)))
(entdel e)
(setvar "OSMODE" _os)
l
      )
     )
    )
  )
)
;;
(defun get-widding-number (l pt / ang p1 p2)
  (if (equal (car l) (last l) 1e-6)
    nil
    (setq l (append l (list (car l))))
  )
  (setq ang 0.0)
  (while (cadr l)
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
    )
    (if (equal p1 p2)
      (setq an1 0.0)
      (setq an1
     ((lambda (/ a b c d e f g)
(setq b (distance p1 pt)
      c (distance p2 pt)
      a (distance p1 p2)
      d (- (* (- (car p1) (car pt)) (- (cadr p2) (cadr pt)))
   (* (- (car p2) (car pt)) (- (cadr p1) (cadr pt)))
)
      e (+ (* b b) (* c c) (* -1 a a))
      f (abs (acos (/ e 2. b c)));_here must be Positive
      g (/ d (abs d))
)
(if (< e 0)
  (* g (- pi f))
  (* g f)
)
      )
     )
      )
    )
    (setq ang (+ ang an1))
  )
  (/ ang 2. pi)
)

;;------------------
(defun dxf (co el)
  (cdr (assoc co el))
  )
;;
(defun acos (a)
  (if (and (= (numberp a) T)
   (<= (abs a) 1.0)
      )
    (if (= a 0.0)
      (* pi 0.5)
      (atan (/ (sqrt (- 1 (* a a)))
       a
    )
      )
    )   
  )
)
;;
(defun ss-assoc (a lst / b res)
  (while (setq b (assoc a lst))
    (setq lst  (cdr (member b lst))
  res (cons (cdr b) res)
    ))(reverse res))
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 01, 2012, 02:41:06 PM
For function unit .
Code: [Select]
;;; SS:ClosedCurve:Pinp&CW?
;;; function ---- Get Given Point position with a closed curve ,
;;;               and determin Curve is Clokwise ?
;;; Curve    ---- A closed curve , Curve-type must be "LWPOLYLINE" "CIRCLE" "ELLIPSE" "SPLINE" ;
;;; pt       ---- a given point (in wcs)
;;; return a list (point_postion_num Clokwise_boolean)
;;;         point_postion_num  ----  -1  pt out of curve
;;;                            ----   0  pt at curve
;;;                            ----   1  pt in curve
;;;         Clokwise_boolean   ----  NIL Counter-Clockwise
;;;                            ----  T  Clokwise
;;; by GSLS(SS) 2012-8-2
(defun SS:ClosedCurve:Pinp&CW? (curve pt / p l n r)
  (if (vlax-curve-isclosed curve)
    (progn
      (setq l (get_closed_curve_pts curve))
      (if (equal (setq p (vlax-curve-getclosestpointto en pt))
pt
1e-6
  )
(progn
  (setq n (get-widding-number
    l
    (polar p
   (- (angle (list 0 0 0)
     (vlax-curve-getfirstderiv
       en
       (vlax-curve-getparamatpoint
en
p
       )
     )
      )
      (* 0.5 pi)
   )
                                  0.1
    )    
  )
  )
  (if (< n 0)
    (list 0 T)
    (list 0 NIL)
  )
)
(progn
  (setq n (get-widding-number l pt))
  (if (< n 0)
    (setq r (list T))
    (setq r (list NIL))
  )
  (if (equal (fix n) n 1e-4)
    (setq n (fix n))
    (if (and (> n 0) (equal (1+ (fix n)) n 1e-4))
      (setq n (1+ (fix n)))
      (if (and (< n 0) (equal (1- (fix n)) n 1e-4))
(setq n (1- (fix n)))
(setq n (fix n))
      )
    )
  )
  (if (= (rem n 2) 0)
    (cons -1 r)
    (cons 1 r)
  )
)
      )
    )
  )
)
;;;---------------------
;;
(defun ss-assoc (a lst / b res)
  (while (setq b (assoc a lst))
    (setq lst  (cdr (member b lst))
  res (cons (cdr b) res)
    ))(reverse res))
;;
(defun acos (a)
  (if (and (= (numberp a) T)
   (<= (abs a) 1.0)
      )
    (if (= a 0.0)
      (* pi 0.5)
      (atan (/ (sqrt (- 1 (* a a)))
       a
    )
      )
    )   
  )
)
;; get point set of a closed curve by order
;; this function you improve by yourself acordding your need .
(defun get_closed_curve_pts (en / ent et)
  ;;by GSLS(SS)
  (setq
    ent (entget en)
    et (cdr (assoc 0 ent))
  )
  (cond
    ((= et "LWPOLYLINE")
     ((lambda (/ a b vetex bu p1 p2 l r ang an1 N)
(while (setq ent (member (assoc 10 ent) ent))
  (setq b     (cons (cdar ent) b)
ent   (member (assoc 42 ent) ent)
b     (cons (cdar ent) b)
ent   (cdr ent)
vetex (cons b vetex)
b     nil
  )
)
(while vetex
  (setq a     (car vetex)
vetex (cdr vetex)
bu    (car a)
p1    (cadr a)
  )
  (if l
    (setq p2 (car l))
    (setq p2 (cadr (last vetex))
  l  (cons p2 l)
    )
  )
  (if (equal bu 0 1e-6)
    (setq l (cons p1 l))
    (progn
      (setq ang (* 2 (atan bu))
    r (/ (distance p1 p2)
   (* 2 (sin ang))
)
    c (polar p1
       (+ (angle p1 p2) (- (/ pi 2) ang))
       r
)
    r (abs r)
    ang (abs (* ang 2.0))
    N (abs (fix (/ ang 0.0174532925199433)))
      )
      (if (= N 0)
(setq l (cons p1 l))
(progn
  (setq an1 (/ ang N)
ang (angle c p2)
  )
  (if (not (minusp bu))
    (setq an1 (- an1))
  )
  (repeat (1- N)
    (setq ang (+ ang an1))
    (setq l (cons (polar c ang r) l))
  )
  (setq l (cons p1 l))
)
      )
    )
  )
)
l
      )
     )
    )
    ((= et "CIRCLE")
     ((lambda (c R / sa ptl)
(setq sa 0.0)
(repeat 180
  (setq ptl (cons (polar c sa R) ptl)
sa  (+ sa 0.0174532925199433)
  )
)
(setq ptl (reverse ptl))
(append
  ptl
  (mapcar (function
    (lambda (p)
      (mapcar (function +) c (mapcar (function -) c p))
    )
  )
  ptl
  )
)
      )
       (cdr (assoc 10 ent))
       (cdr (assoc 40 ent))
     )
    )
    ((= et "SPLINE")
     ((lambda (/ r l _oce)
(setq _oce (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(if (vl-catch-all-apply
      (function vl-cmdf)
      (list "_PEDIT"
    (vlax-vla-object->ename
      (vla-copy (vlax-ename->vla-object en))
    )
    ""
    10
    ""
      )
    )
  (progn
    (setq l (ss-assoc 10 (entget (setq r (entlast)))))
    (if (vlax-curve-isClosed r)
      (setq l (append l (list (car l))))
    )
    (entdel r)
  )
)
(setvar "CMDECHO" _oce)
l
      )
     )
    )
    ((= et "ELLIPSE")
     ((lambda (/ e l _os)
(setq _os (getvar "OSMODE"))
(setvar "OSMODE" 0)
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object en) 0.1)
)
(setq e (entlast))
(vl-catch-all-apply
  (function vla-offset)
  (list (vlax-ename->vla-object (entlast)) -0.1)
)
(entdel e)
(setq e (entlast))
(setq l (ss-assoc 10 (entget e)))
(entdel e)
(setvar "OSMODE" _os)
l
      )
     )
    )
  )
)
;;
;; This method suggest by Lee Mac from http://en.wikipedia.org/wiki/Winding_number
;; function : get widding number
;; l  ---- point set of a Closed Curve
;; pt ---- a given point to determin position with the Closed Curve
;; return a widding number
;; by GSLS(SS) 2012-08-02
(defun get-widding-number (l pt / ang p1 p2)
  (if (equal (car l) (last l) 1e-6)
    nil
    (setq l (append l (list (car l))))
  )
  (setq ang 0.0)
  (while (cadr l)
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
    )
    (if (equal p1 p2)
      (setq an1 0.0)
      (setq an1
     ((lambda (/ a b c d e f g)
(setq b (distance p1 pt)
      c (distance p2 pt)
      a (distance p1 p2)
      d (- (* (- (car p1) (car pt)) (- (cadr p2) (cadr pt)))
   (* (- (car p2) (car pt)) (- (cadr p1) (cadr pt)))
)
      e (+ (* b b) (* c c) (* -1 a a))
      f (abs (acos (/ e 2. b c)));_here must be Positive
      g (/ d (abs d))
)
(if (< e 0)
  (* g (- pi f))
  (* g f)
)
      )
     )
      )
    )
    (setq ang (+ ang an1))
  )
  (/ ang 2. pi)
)
Test function
Code: [Select]
(defun c:test (/ en pt n)
  (setq en (car (entsel "\n Select a Closed Curve :")))
  (while (setq pt (getpoint "\nSelect a point :"))
    (setq n (SS:ClosedCurve:Pinp&CW? en pt))
    (cond ((and (< (car n) 0) (cadr n))
   (alert "Out , CW")
  )
  ((and (< (car n) 0) (not (cadr n)))
   (alert "Out , CCW")
  )
  ((and (= (car n) 0) (cadr n))
   (alert "At , CW")
  )
  ((and (= (car n) 0) (not (cadr n)))
   (alert "At , CCW")
  )
  ((and (> (car n) 0) (cadr n))
   (alert "In , CW")
  )
  ((and (> (car n) 0) (not (cadr n)))
   (alert "In , CCW")
  )
    )
  )
  (princ)
)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 01, 2012, 03:09:01 PM
The Clockwise case of a closed curve , seem like Associating with the point position ?
Just like the right shape on the up post , is it correct ?
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 02, 2012, 07:34:21 AM
Acordding GP's method and codes , and determine pt-in-curve by the method Lee Mac suggest .
It can supports self-intersection , butthe problem that it ps. not correct result yet be there , unless the setp1 is enough great .
The codes get-widding-number seems so poor, Need your improving .( I guess this method used in AutoCAD interface , but didn't know how get it )
Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; Gian Paolo Cattaneo

(defun C:TesT (/ POLY    POLY_vl   Dx        Dy
       Lp List_vert_poly      list_p_int
       P_center dist    step1     step2     t1
       t2
      )
  (prompt "\nSelect Polyline: ")
  (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
    (progn
      (setq i  1
    t1 (getvar "MilliSecs")
      )
      (setq step1 40) ;--> grid_1
      (setq step2 20) ;--> grid_2
      (setq list_vert_poly (LWPoly->List POLY 10))
      (grid_1)
      (Point_int)
      (grid+)
      (Point_center)
      (repeat 2
(grid_2)
(Point_center)
      )
      (entmake
(list
  (cons 0 "CIRCLE")
  (cons 10 P_center)
  (cons 40 dist)
)
      )
      (setq t2 (getvar "MilliSecs"))
      (princ (strcat "time = " (rtos (- t2 t1) 2 0) " MilliSecs"))
      (princ)
    )
  )
)

;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
;; Returns a grid of points within the BoundingBox of the selected poly
(defun grid_1 (/   p1 p2 X1 Y1 l1)
  (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  (setq p1 (vlax-safearray->list p1)
p2 (vlax-safearray->list p2)
p1 (list (car p1) (cadr p1))
p2 (list (car p2) (cadr p2))
  )
  (setq Dx (/ (- (car p2) (car p1)) step1))
  (setq Dy (/ (- (cadr p2) (cadr p1)) step1)) 
  (setq Lp (list p1)
X1 (car p1)
Y1 (cadr p1)
  )
  (repeat step1
    (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  )
  (setq Lp (list Lp))
  (repeat step1
    (setq  Lp (cons (mapcar (function (lambda (x)
       (list (car x) (+ (cadr x) Dy))
     )
   )
   (car lp)
   )  Lp)
    )
  )
  (setq Lp (apply (function append) Lp))
)


;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
;; Returns a grid of points around the center point (provisional)
(defun grid_2 (/ P1_ P> n)
  (setq list_p_int nil)
  (setq P1_ (list (- (car P_center) (* Dx 2))
  (- (cadr P_center) (* Dy 2))
    )
  )
  (setq Dx (/ (* 4 Dx) step2))
  (setq Dy (/ (* 4 Dy) step2))
  (setq n 0)
  (setq P> P1_)
  (setq list_p_int (list P1_))
  (repeat (* (1+ step2) step2)
    (setq P> (list (+ (car P>) Dx) (cadr P>)))
    (setq list_p_int (cons P> list_p_int))
    (setq n (1+ n))
    (if (= n step2)
      (progn
(setq n 0)
(setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
(setq P> P1_)
(setq list_p_int (cons P> list_p_int))
      )
    )
  )
)


;; restituisce la lista dei punti interni ad un poligono
;; dati:  - lista coordinate dei punti -> Lp
;;        - lista coordinate vertici poligono -> list_vert_poly
;; Returns the list of points inside the polyline
(defun Point_int (/ n Pr cont attr p# Pa Pa_ Pb)
  (setq list_p_int nil)
  (foreach Pr Lp
    (if (> (Point-in-ClosedCurve-p list_vert_poly Pr) 0)
      (setq list_p_int (cons Pr list_p_int))
    )
  )
)
;; Infittisce la griglia inserendo altri punti
;; nel centro delle diagonali tra i punti interni
;; Insert points (interior) to increase the density of the grid
(defun grid+ (/ G+)
  (setq G+
(mapcar '(lambda (x)
    (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  )
list_p_int
)
  )
  (setq list_p_int (append G+ list_p_int))
)


;; Da una lista di punti restituisce quello pił lontano da un oggetto
;; dati:  - lista dei punti -> list_p_int
;;        - oggetto -> POLY_vl
;; Returns the farthest point from the polyline
(defun Point_center (/ Pa n Pvic)
  (setq Dist 1e-7)
  (setq P_center nil)
  (foreach Pa list_p_int
    (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
    (if (> (distance Pa Pvic) Dist)
      (progn
(setq P_center Pa)
(setq Dist (distance Pa Pvic))
      )
    )
  )
)
;;
(defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  ;;Acc --- 0 ~ 99
  (setq ent (entget en))
  (while (setq ent (member (assoc 10 ent) ent))
    (setq b (cons (cdar ent) b)
  ent (member (assoc 42 ent) ent)
  b (cons (cdar ent) b)
  ent (cdr ent)
  vetex (cons b vetex)
  b nil
    )
  )
  (while vetex
    (setq a (car vetex)
  vetex (cdr vetex)
  bu (car a)
  p1 (cadr a)
    )
    (if l
      (setq p2 (car l))
      (setq p2 (cadr (last vetex))
    l  (cons p2 l)
      )
    )
    (if (equal bu 0 1e-6)
      (setq l (cons p1 l))
      (progn
(setq ang (* 2 (atan bu))
      r   (/ (distance p1 p2)
     (* 2 (sin ang))
  )
      c   (polar p1
(+ (angle p1 p2) (- (/ pi 2) ang))
r
  )
      r   (abs r)
      ang (abs (* ang 2.0))
      N   (abs (fix (/ ang 0.0174532925199433)))
      N   (min N (1+ Acc))
)
(if (= N 0)
  (setq l (cons p1 l))
  (progn
    (setq an1 (/ ang N)
  ang (angle c p2)
    )
    (if (not (minusp bu))
      (setq an1 (- an1))
    )
    (repeat (1- N)
      (setq ang (+ ang an1))
      (setq l (cons (polar c ang r) l))
    )
    (setq l (cons p1 l))
  )
)
      )
    )
  )
  l
)
;;
;; This method suggest by Lee Mac from http://en.wikipedia.org/wiki/Winding_number
;; function : determin the point position with the closed curve by widding-number method
;; l  ---- point set of a Closed Curve , First item must same as Last item .
;; pt ---- a given point to determin position with the Closed Curve
;;; return a num
;;;           ----  -1  pt out of curve
;;;           ----   0  pt at curve
;;;           ----   1  pt in curve
;; by GSLS(SS) 2012-08-02
(defun Point-in-ClosedCurve-p (l pt / ang p1 p2 n r at)
  (setq ang 0.0
at  nil
  )
  (while (and (cadr l) (not at))
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
    )
    (if (equal p1 p2 1e-6)
      (setq an1 0.0)
      (setq an1
     ((lambda (/ a b c d e f g)
(setq b (distance p1 pt)
      c (distance p2 pt)
      a (distance p1 p2)
      d (- (* (- (car p1) (car pt)) (- (cadr p2) (cadr pt)))
   (* (- (car p2) (car pt)) (- (cadr p1) (cadr pt)))
)
)
(if (and (equal d 0.0 1e-4) (setq at T))
  pi
  (progn
    (setq
      e (+ (* b b) (* c c) (* -1 a a))
      f (abs ((lambda (x)
(cond ((equal x 0.0 1e-6)(* pi 0.5))
      ((equal x 1.0 1e-6)0.0)
      ((atan (/ (sqrt (- 1 (* x x)))
x
     )
       ))
))
       (/ e 2. b c)
     )
)
      g (if (> d 0)  1  -1)
    )
    (if (< e 0)
      (* g (- pi f))
      (* g f)
    )
  )
)
      )
     )
      )
    )
    (setq ang (+ ang an1))
  )
  ;;deal widding number 
  (if at
    0
    (progn
      (setq n (/ ang 2. pi))
      (if (equal (fix n) n 1e-4)
(setq n (fix n))
(if (and (> n 0) (equal (1+ (fix n)) n 1e-4))
  (setq n (1+ (fix n)))
  (if (and (< n 0) (equal (1- (fix n)) n 1e-4))
    (setq n (1- (fix n)))
    (setq n (fix n))
  )
)
      )
      (if (= (rem n 2) 0)
-1
1
      )
    )
  )
)
;|
(defun c:t1 ( / en l n)
  (setq en (car (entsel))
l (LWPoly->List en 10))
  (while (setq pt (getpoint ))
    (setq n (Point-in-ClosedCurve-p l pt))
   (cond ((> n 0)
     (alert "IN"))
((= n 0)
     (alert "AT"))
(t
  (alert "OUT")))))
  |;
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on August 02, 2012, 10:58:57 AM
Acordding GP's method and codes , and determine pt-in-curve by the method Lee Mac suggest .
It can supports self-intersection , butthe problem that it ps. not correct result yet be there , unless the setp1 is enough great .
The codes get-widding-number seems so poor, Need your improving .( I guess this method used in AutoCAD interface , but didn't know how get it )
Code: [Select]
.................
.................
;; Returns the list of points inside the polyline
(defun Point_int (/ n Pr cont attr p# Pa Pa_ Pb)
  (setq list_p_int nil)
  (foreach Pr Lp
    (if (> (Point-in-ClosedCurve-p list_vert_poly Pr) 0)
      (setq list_p_int (cons Pr list_p_int))
    )
  )
)
...................
...................

The points inside are not calculated correctly.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 03, 2012, 03:15:12 AM
The points inside are not calculated correctly.
Thank you for test , I'll check it .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 03, 2012, 05:26:23 AM
The points inside are not calculated correctly.
Change the widding number's rounding accuracy 1e-4 into 1e-3 or 1e-2 will correct this problem .
Code: [Select]
;;
;; This method suggest by Lee Mac from http://en.wikipedia.org/wiki/Winding_number
;; function : determin the point position with the closed curve by widding-number method
;; l  ---- point set of a Closed Curve , First item must same as Last item .
;; pt ---- a given point to determin position with the Closed Curve
;; return a num
;;           ----  -1  pt out of curve
;;           ----   0  pt at curve
;;           ----   1  pt in curve
;; by GSLS(SS) 2012-08-02
;; Edited : Change widding number's Acc 1e-4 into 1e-2 ,
;;          for checking point in or out it's a integer
(defun Point-in-ClosedCurve-p (l pt / ang p1 p2 n r at)
  (setq ang 0.0
at  nil
  )
  (while (and (cadr l) (not at))
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
    )
    (if (equal p1 p2 1e-6)
      (setq an1 0.0)
      (setq an1
     ((lambda (/ a b c d e f g)
(setq b (distance p1 pt)
      c (distance p2 pt)
      a (distance p1 p2)
      d (- (* (- (car p1) (car pt)) (- (cadr p2) (cadr pt)))
   (* (- (car p2) (car pt)) (- (cadr p1) (cadr pt)))
)
)
(if (and (equal d 0.0 1e-4) (setq at T))
  pi
  (progn
    (setq
      e (+ (* b b) (* c c) (* -1 a a))
      f (abs ((lambda (x)
(cond ((equal x 0.0 1e-6)(* pi 0.5))
      ((equal x 1.0 1e-6)0.0)
      ((atan (/ (sqrt (- 1 (* x x)))
x
     )
       ))
))
       (/ e 2. b c)
     )
)
      g (if (> d 0)  1  -1)
    )
    (if (< e 0)
      (* g (- pi f))
      (* g f)
    )
  )
)
      )
     )
      )
    )
    (setq ang (+ ang an1))
  )
  ;;deal widding number 
  (if at
    0
    (progn
      (setq n (/ ang 2. pi))
      (if (and (> n 0) (equal (1+ (fix n)) n 1e-2))
;_Change Acc 1e-4 to 1e-2 for correct 2012-8-3
  (setq n (1+ (fix n)))
  (if (and (< n 0) (equal (1- (fix n)) n 1e-2))
    ;_Change Acc 1e-4 to 1e-2 for correct 2012-8-3
    (setq n (1- (fix n)))
    (setq n (fix n))
  )
)
      (if (= (rem n 2) 0)
-1
1
      )
    )
  )
)

change test function for check Point_inter result .
Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; Gian Paolo Cattaneo

(defun C:TesT (/ POLY    POLY_vl   Dx        Dy
       Lp List_vert_poly      list_p_int
       P_center dist    step1     step2     t1
       t2
      )
  (prompt "\nSelect Polyline: ")
  (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
    (progn
      (setq i  1
    t1 (getvar "MilliSecs")
      )
      (setq step1 40) ;--> grid_1
      (setq step2 20) ;--> grid_2
      (setq list_vert_poly (LWPoly->List POLY 99))
      (grid_1)     
      (Point_int)     
      (foreach a list_p_int
(entmake (list (cons 0 "POINT")
       (cons 10 a))
)
)
      (grid+)
      (Point_center)
      (repeat 2
(grid_2)
(Point_center)
      )
      (entmake
(list
  (cons 0 "CIRCLE")
  (cons 10 P_center)
  (cons 40 dist)
)
      )
      (setq t2 (getvar "MilliSecs"))
      (princ (strcat "time = " (rtos (- t2 t1) 2 0) " MilliSecs"))
      (princ)
    )
  )
)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 05, 2012, 08:03:12 AM
New version for Point-in-ClosedCurve , it run quickest .
Code: [Select]
(defun Point-in-ClosedCurve-p (l pt / ang p1 p2 n r at)
  (setq ang 0.0)
  (while (and (cadr l) (not at))
    (setq p1 (car l)
  p2 (cadr l)
  l  (cdr l)
  an1 (- (angle pt p2) (angle pt p1))
    )   
    (if (< an1 (- pi))
      (setq an1 (+ an1 pi pi))
      (if (> an1 pi)
(setq an1 (- an1 pi pi))
      )
    )
    (if (equal (abs an1) pi 1e-14)
      (setq at T)
    )
    (setq ang (+ ang an1))
  )
  ;;deal widding number 
  (if at
    0
    (progn
      (setq n (/ ang 2. pi))
      (if (and (> n 0) (equal (1+ (fix n)) n 1e-2))
 ;_Change Acc 1e-4 to 1e-2 for correct 2012-8-3
(setq n (1+ (fix n)))
(if (and (< n 0) (equal (1- (fix n)) n 1e-2))
 ;_Change Acc 1e-4 to 1e-2 for correct 2012-8-3
  (setq n (1- (fix n)))
  (setq n (fix n))
)
      )
      (if (= (rem n 2) 0)
-1
1
      )
    )
  )
)

Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 05, 2012, 11:20:23 AM
Use GP's method :
Some change will improve the speed and accuracy .
1. To suit for any complex tubular closed curve ,  Use the ratio of circumference and area to optimize the number of grids in  the step 1 ;
Code: [Select]
(setq area (vlax-curve-getArea poly)
         len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly)))
(setq step1 (max 10 (fix (/ len 0.4 (sqrt area)))));_--> grid_1     
2.  Force step2 into 10 , because  10 equal grid is enough to make the radius improve the accuracy of a rating
3.  change the 'Grid_2' routine's area
Code: [Select]
;;old grid_2 area
+ + + + +
+ + + + +
+ + o + +
+ + + + +
+ + + + +
;;new grid_2 area
+ + +
+ o +
+ + +
4. Use radius accuracy to control the loop , 'While' method replace  'Repeat' method .
  In most cases, will improve the speed .
5.  Limits the number of the while loop, to adapt to the rectangle .

Codes Following
Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; writed by Gian Paolo Cattaneo
;;; edited by GSLS(SS) 2012-8-5

(defun C:TesT (/ POLY    POLY_vl   Dx        Dy
       Lp List_vert_poly      list_p_int
       P_center dist    step1     step2     t1
       t2  R0  area len i
      )
  (gc)
  (prompt "\nSelect Polyline: ")
  (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
    (progn
      (setq i  1
    t1 (getvar "MilliSecs")
      )
      (setq area (vlax-curve-getArea poly)
    len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly)))
      (setq step1 (max 10 (fix (/ len 0.4 (sqrt area)))));_--> grid_1     
      (setq step2 10);_--> grid_2
      (setq list_vert_poly (LWPoly->List POLY 10))     
      (grid_1)
      (Point_int)     
      (grid+)
      (Point_center)
      (setq i 0)
      (while (and (> (- Dist R0) 1e-8)(< i 10))
(grid_2)
(Point_center)
(setq i (1+ i))
      )
      (entmake
(list
  (cons 0 "CIRCLE")
  (cons 10 P_center)
  (cons 40 dist)
)
      )
      (setq t2 (getvar "MilliSecs"))
      (princ (strcat "time = " (rtos (- t2 t1) 2 0) " MilliSecs"))
      (princ)
    )
  )
)

;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
;; Returns a grid of points within the BoundingBox of the selected poly
(defun grid_1 (/ p1 p2 X1 Y1 l1)
  (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  (setq p1 (vlax-safearray->list p1)
p2 (vlax-safearray->list p2)
p1 (list (car p1) (cadr p1))
p2 (list (car p2) (cadr p2))
  )
  (setq Dx (/ (- (car p2) (car p1)) step1))
  (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  (setq Lp (list p1)
X1 (car p1)
Y1 (cadr p1)
  )
  (repeat step1
    (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  )
  (setq Lp (list Lp))
  (repeat step1
    (setq Lp (cons (mapcar (function (lambda (x)
       (list (car x) (+ (cadr x) Dy))
     )
   )
   (car lp)
   )
   Lp
     )
    )
  )
  (setq Lp (apply (function append) Lp))
)
;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
;; Returns a grid of points around the center point (provisional)
(defun grid_2 (/ X1 Y1 P1)
  (setq list_p_int nil
X1    (- (car P_center) Dx)
Y1    (- (cadr P_center) Dy)
P1    (list X1 Y1)
Dx    (/ (* 2 Dx) step2)
Dy    (/ (* 2 Dy) step2)
  )
  (setq list_p_int (list P1))
  (repeat step2
    (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  )
  (setq list_p_int (list list_p_int))
  (repeat step2
    (setq list_p_int
   (cons (mapcar (function (lambda (x)
     (list (car x) (+ (cadr x) Dy))
   )
)
(car list_p_int)
)
list_p_int
   )
    )
  )
  (setq list_p_int (apply (function append) list_p_int))
)
;; restituisce la lista dei punti interni ad un poligono
;; dati:  - lista coordinate dei punti -> Lp
;;        - lista coordinate vertici poligono -> list_vert_poly
;; Returns the list of points inside the polyline
(defun Point_int (/ n Pr cont attr p# Pa Pa_ Pb)
  (setq list_p_int nil)
  (foreach Pr Lp
    (if (> (Point-in-ClosedCurve-p list_vert_poly Pr) 0)
      (setq list_p_int (cons Pr list_p_int))
    )
  )
)
;; Infittisce la griglia inserendo altri punti
;; nel centro delle diagonali tra i punti interni
;; Insert points (interior) to increase the density of the grid
(defun grid+ (/ G+)
  (setq G+
(mapcar '(lambda (x)
    (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  )
list_p_int
)
  )
  (setq list_p_int (append G+ list_p_int))
)
;; Da una lista di punti restituisce quello pił lontano da un oggetto
;; dati:  - lista dei punti -> list_p_int
;;        - oggetto -> POLY_vl
;; Returns the farthest point from the polyline
(defun Point_center (/ Pa Pvic)   
  (foreach Pa list_p_int
    (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
    (if (> (distance Pa Pvic) Dist)
      (setq P_center Pa
      R0 Dist
      Dist (distance Pa Pvic))
    )
  )
)
;;
(defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  ;;Acc --- 0 ~ 99
  (setq ent (entget en))
  (while (setq ent (member (assoc 10 ent) ent))
    (setq b (cons (cdar ent) b)
  ent (member (assoc 42 ent) ent)
  b (cons (cdar ent) b)
  ent (cdr ent)
  vetex (cons b vetex)
  b nil
    )
  )
  (while vetex
    (setq a (car vetex)
  vetex (cdr vetex)
  bu (car a)
  p1 (cadr a)
    )
    (if l
      (setq p2 (car l))
      (setq p2 (cadr (last vetex))
    l  (cons p2 l)
      )
    )
    (if (equal bu 0 1e-6)
      (setq l (cons p1 l))
      (progn
(setq ang (* 2 (atan bu))
      r   (/ (distance p1 p2)
     (* 2 (sin ang))
  )
      c   (polar p1
(+ (angle p1 p2) (- (/ pi 2) ang))
r
  )
      r   (abs r)
      ang (abs (* ang 2.0))
      N   (abs (fix (/ ang 0.0174532925199433)))
      N   (min N (1+ Acc))
)
(if (= N 0)
  (setq l (cons p1 l))
  (progn
    (setq an1 (/ ang N)
  ang (angle c p2)
    )
    (if (not (minusp bu))
      (setq an1 (- an1))
    )
    (repeat (1- N)
      (setq ang (+ ang an1)
    l (cons (polar c ang r) l)
      )
    )
    (setq l (cons p1 l))
  )
)
      )
    )
  )
  l
)
;;
;; This method suggest by Lee Mac from http://en.wikipedia.org/wiki/Winding_number
;; function : determin the point position with the closed curve by widding-number method
;; l  ---- point set of a Closed Curve , First item must same as Last item .
;; pt ---- a given point to determin position with the Closed Curve
;; return a num
;;           ----  -1  pt out of curve
;;           ----   0  pt at curve
;;           ----   1  pt in curve
;; by GSLS(SS) 2012-08-02
;; Edited : Change widding number's Acc 1e-4 into 1e-2 ,
;;          for checking point in or out it's a integer
;; Edited 2012-8-5
;;         Improved vector angle calculation , only use angle function .
;;         
(defun Point-in-ClosedCurve-p (l pt / ang p1 p2 n r at)
  (setq ang 0.0)
  (while (and (cadr l) (not at))
    (setq p1  (car l)
  p2  (cadr l)
  l   (cdr l)
  an1 (- (angle pt p2) (angle pt p1))
    )
    (if (< an1 (- pi))
      (setq an1 (+ an1 pi pi))
      (if (> an1 pi)
(setq an1 (- an1 pi pi))
      )
    )
    (if (equal (abs an1) pi 1e-14);_If it's just used to solve the maximum radius of the circle,
                                 ;_here's  precision 1e-14 can be set lower , such as 1e-1 ,
                                 ;_this will exclude the point of the curve edge .
                                 ;_but for ultra-narrow four-point rectangle will generate an error .
      (setq at T)
    )
    (setq ang (+ ang an1))
  )
  ;;deal widding number 
  (if at
    0
    (progn
      (setq n (/ ang 2. pi))
      (if (and (> n 0) (equal (1+ (fix n)) n 1e-2))
(setq n (1+ (fix n)))
(if (and (< n 0) (equal (1- (fix n)) n 1e-2))
  (setq n (1- (fix n)))
  (setq n (fix n))
)
      )
      (if (= (rem n 2) 0)
-1
1
      )
    )
  )
)
Any suggestions are welcome .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 05, 2012, 01:42:01 PM
improve the routine for determining point in curve , Saving most of his time .
the (grid+) step can be omitted .
Code: [Select]
;;; maximum circle inscribed in a closed polyline
;;; writed by Gian Paolo Cattaneo
;;; edited by GSLS(SS) 2012-8-5

(defun C:TesT (/ POLY POLY_vl  Dx    Dy     Lp
       List_vert_poly list_p_int    P_center dist
       step1 step2 t1   t2 t3  t4    R0     area
       len i
      )
  (gc)
  (prompt "\nSelect Polyline: ")
  (if (setq POLY (ssname (ssget ":S" '((0 . "LWPOLYLINE"))) 0))
    (progn
      (setq i 1)
      (setq area (vlax-curve-getArea poly)
    len (vlax-curve-getDistAtParam
   poly
   (vlax-curve-getEndParam poly)
)
      )
      (setq step1 (max 10 (fix (/ len 0.4 (sqrt area))))) ;_--> grid_1     
      (setq step2 10) ;_--> grid_2
      (setq list_vert_poly (LWPoly->List POLY 10))     
      (grid_1)
      (setq t1 (getvar "MilliSecs"))
      (Point_int)
      (setq t2 (getvar "MilliSecs"))
      ;|
      (foreach a list_p_int
(entmake (list (cons 0 "POINT")
       (cons 10 a)
       (cons 62 3))))|;
      ;_(grid+)
      (Point_center)
      (setq t3 (getvar "MilliSecs"))
      (setq i 0)
      (while (and (> (- Dist R0) 1e-8) (< i 10))
(grid_2)
(Point_center)
(setq i (1+ i))
      )
      (setq t4 (getvar "MilliSecs"))
      (entmake
(list
  (cons 0 "CIRCLE")
  (cons 10 P_center)
  (cons 40 dist)
)
      )
      (princ
(strcat "\ntime1 = " (rtos (- t2 t1) 2 0) " MilliSecs")
      )
      (princ
(strcat "\ntime2 = " (rtos (- t3 t2) 2 0) " MilliSecs")
      )
      (princ
(strcat "\ntime3 = " (rtos (- t4 t3) 2 0) " MilliSecs")
      )
      (princ)
    )
  )
)

;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
;; Returns a grid of points within the BoundingBox of the selected poly
(defun grid_1 (/ p1 p2 X1 Y1 l1)
  (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  (setq p1 (vlax-safearray->list p1)
p2 (vlax-safearray->list p2)
p1 (list (car p1) (cadr p1))
p2 (list (car p2) (cadr p2))
  )
  (setq Dx (/ (- (car p2) (car p1)) step1))
  (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  (setq Lp (list p1)
X1 (car p1)
Y1 (cadr p1)
  )
  (repeat step1
    (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  )
  (setq Lp (list Lp))
  (repeat step1
    (setq Lp (cons (mapcar (function (lambda (x)
       (list (car x) (+ (cadr x) Dy))
     )
   )
   (car lp)
   )
   Lp
     )
    )
  )
  (setq Lp (apply (function append) Lp))
)
;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
;; Returns a grid of points around the center point (provisional)
(defun grid_2 (/ X1 Y1 P1)
  (setq list_p_int nil
X1    (- (car P_center) Dx)
Y1    (- (cadr P_center) Dy)
P1    (list X1 Y1)
Dx    (/ (* 2 Dx) step2)
Dy    (/ (* 2 Dy) step2)
  )
  (setq list_p_int (list P1))
  (repeat step2
    (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  )
  (setq list_p_int (list list_p_int))
  (repeat step2
    (setq list_p_int
   (cons (mapcar (function (lambda (x)
     (list (car x) (+ (cadr x) Dy))
   )
)
(car list_p_int)
)
list_p_int
   )
    )
  )
  (setq list_p_int (apply (function append) list_p_int))
)
;; restituisce la lista dei punti interni ad un poligono
;; dati:  - lista coordinate dei punti -> Lp
;;        - lista coordinate vertici poligono -> list_vert_poly
;; Returns the list of points inside the polyline
(defun Point_int ()
  (setq list_p_int
(vl-remove-if-not
   (function
     (lambda (pt)
       ;_determine point in curve , use widding number
       (equal
PI
(abs
   (apply
     (function +)
     (mapcar (function (lambda (x y / a)
(rem (- (angle pt x) (angle pt y)) PI)
       )
     )
     list_vert_poly
     (cdr list_vert_poly)
     )
   )
)
1e-8
       )
     )
   )
   Lp
)
  )
)
;; Infittisce la griglia inserendo altri punti
;; nel centro delle diagonali tra i punti interni
;; Insert points (interior) to increase the density of the grid
(defun grid+ (/ G+)
  (setq G+
(mapcar '(lambda (x)
    (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  )
list_p_int
)
  )
  (setq list_p_int (append G+ list_p_int))
)
;; Da una lista di punti restituisce quello pił lontano da un oggetto
;; dati:  - lista dei punti -> list_p_int
;;        - oggetto -> POLY_vl
;; Returns the farthest point from the polyline
(defun Point_center (/ Pa Pvic)
  (foreach Pa list_p_int
    (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
    (if (> (distance Pa Pvic) Dist)
      (setq P_center Pa
    R0      Dist
    Dist     (distance Pa Pvic)
      )
    )
  )
)
;;
(defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  ;;Acc --- 0 ~ 99
  (setq ent (entget en))
  (while (setq ent (member (assoc 10 ent) ent))
    (setq b (cons (cdar ent) b)
  ent (member (assoc 42 ent) ent)
  b (cons (cdar ent) b)
  ent (cdr ent)
  vetex (cons b vetex)
  b nil
    )
  )
  (while vetex
    (setq a (car vetex)
  vetex (cdr vetex)
  bu (car a)
  p1 (cadr a)
    )
    (if l
      (setq p2 (car l))
      (setq p2 (cadr (last vetex))
    l  (cons p2 l)
      )
    )
    (if (equal bu 0 1e-6)
      (setq l (cons p1 l))
      (progn
(setq ang (* 2 (atan bu))
      r   (/ (distance p1 p2)
     (* 2 (sin ang))
  )
      c   (polar p1
(+ (angle p1 p2) (- (/ pi 2) ang))
r
  )
      r   (abs r)
      ang (abs (* ang 2.0))
      N   (abs (fix (/ ang 0.0174532925199433)))
      N   (min N (1+ Acc))
)
(if (= N 0)
  (setq l (cons p1 l))
  (progn
    (setq an1 (/ ang N)
  ang (angle c p2)
    )
    (if (not (minusp bu))
      (setq an1 (- an1))
    )
    (repeat (1- N)
      (setq ang (+ ang an1)
    l (cons (polar c ang r) l)
      )
    )
    (setq l (cons p1 l))
  )
)
      )
    )
  )
  l
)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: GP on August 05, 2012, 03:39:31 PM
fixed a bug:

;;; writed by Gian Paolo Cattaneo GSLS(SS)

:-)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on August 06, 2012, 07:44:44 AM
fixed a bug:

;;; writed by Gian Paolo Cattaneo GSLS(SS)

:-)
I just state fact , you are always so humble  :-)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 03, 2014, 04:40:36 AM
I've decided to revive this topic... Thanks to GSLS(SS) and Gian P., I've written this extension... It should create maximum inscribed circles and also in 3D... Please, test the code - I've had many small fine tunings until I finally settled to this version... If circle with current color is drawn than in most cases the result is exact circle - if circle is yellow, then it's not precise...

HTH, M.R. (Hope I saved some time for those that code...)

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ipls ( / *error* 2d-lw-pt GetIntersections GroupByNum interse1e2 MaximumInscribedCircle_p LWPoly->List grid_1 grid_2 Point_int grid+ Point_center adoc area len ape polys poly pl x e n i lst p dist ci ptse1e2 pts1 pts2 pts3 ptsints plpts ptl )
  2.  
  3.  
  4.   (defun *error* ( msg )
  5.     (if ape (setvar 'aperture ape))
  6.     (vla-endundomark adoc)
  7.     (if msg (prompt msg))
  8.     (princ)
  9.   )
  10.  
  11.   (defun 2d-lw-pt ( lst )
  12.     (if lst
  13.       (cons (list (car lst) (cadr lst)) (2d-lw-pt (cddr lst)))
  14.     ) ;_  if
  15.   )
  16.  
  17.   (defun GetIntersections ( obj1 obj2 )
  18.     (GroupByNum (vlax-invoke obj1 'IntersectWith obj2 acExtendNone) 3)
  19.   )
  20.  
  21.   (defun GroupByNum ( l n / r)
  22.     (if l
  23.       (cons
  24.         (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r))
  25.         (GroupByNum l n)
  26.       )
  27.     )
  28.   )
  29.  
  30.   (defun interse1e2 ( e1 e2 / lst )
  31.     (if (and e1 e2)
  32.       (setq lst (GetIntersections (vlax-ename->vla-object e1) (vlax-ename->vla-object e2)))
  33.     )
  34.     lst
  35.   )
  36.  
  37. ;****************************************************************************
  38. ;  Ritorna il centro del massimo cerchio inscritto in una polilinea          
  39. ;  Returns the center point of the maximum inscribed circle in a polyline    
  40. ;                    Author: Gian Paolo Cattaneo
  41. ;  edited by GSLS(SS) 2012-8-5
  42. ;****************************************************************************                            
  43.   (defun MaximumInscribedCircle_p ( poly / list_vert_poly step1 step2 i r0 P_center )
  44.  
  45.       (setq step1 (max 10 (fix (/ len 0.4 (sqrt area))))) ;_--> grid_1      
  46.       (setq step2 10) ;_--> grid_2
  47.       (setq list_vert_poly (LWPoly->List POLY 10))      
  48.       (grid_1)
  49.       (Point_int)
  50.       (Point_center)
  51.       (setq i 0)
  52.       (while (and (> (- Dist R0) 1e-8) (< i 10))
  53.         (grid_2)
  54.         (Point_center)
  55.         (setq i (1+ i))
  56.       )
  57.       P_center
  58.   )
  59.  
  60. ;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
  61. ;; Returns a grid of points within the BoundingBox of the selected poly
  62.   (defun grid_1 (/ p1 p2 X1 Y1 l1)
  63.     (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  64.     (setq       p1 (vlax-safearray->list p1)
  65.           p2 (vlax-safearray->list p2)
  66.           p1 (list (car p1) (cadr p1))
  67.           p2 (list (car p2) (cadr p2))
  68.     )
  69.     (setq Dx (/ (- (car p2) (car p1)) step1))
  70.     (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  71.     (setq       Lp (list p1)
  72.           X1 (car p1)
  73.           Y1 (cadr p1)
  74.     )
  75.     (repeat step1
  76.       (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  77.     )
  78.     (setq Lp (list Lp))
  79.     (repeat step1
  80.       (setq Lp (cons (mapcar (function (lambda (x)
  81.                  (list (car x) (+ (cadr x) Dy))
  82.                )
  83.            )
  84.            (car lp)
  85.          )
  86.          Lp
  87.          )
  88.       )
  89.     )
  90.     (setq Lp (apply (function append) Lp))
  91.   )
  92. ;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
  93. ;; Returns a grid of points around the center point (provisional)
  94.   (defun grid_2 (/ X1 Y1 P1)
  95.     (setq       list_p_int nil
  96.           X1       (- (car P_center) Dx)
  97.           Y1       (- (cadr P_center) Dy)
  98.           P1       (list X1 Y1)
  99.           Dx       (/ (* 2 Dx) step2)
  100.           Dy       (/ (* 2 Dy) step2)
  101.     )
  102.     (setq list_p_int (list P1))
  103.     (repeat step2
  104.       (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  105.     )
  106.     (setq list_p_int (list list_p_int))
  107.     (repeat step2
  108.       (setq list_p_int
  109.        (cons (mapcar (function (lambda (x)
  110.                (list (car x) (+ (cadr x) Dy))
  111.              )
  112.          )
  113.          (car list_p_int)
  114.        )
  115.        list_p_int
  116.        )
  117.       )
  118.     )
  119.     (setq list_p_int (apply (function append) list_p_int))
  120.   )
  121. ;; restituisce la lista dei punti interni ad un poligono
  122. ;; dati:  - lista coordinate dei punti -> Lp
  123. ;;        - lista coordinate vertici poligono -> list_vert_poly
  124. ;; Returns the list of points inside the polyline
  125.   (defun Point_int ()
  126.     (setq       list_p_int
  127.      (vl-remove-if-not
  128.        (function
  129.          (lambda (pt)
  130.            ;_determine point in curve , use widding number
  131.            (equal
  132.              PI
  133.              (abs
  134.                (apply
  135.                  (function +)
  136.                  (mapcar (function (lambda (x y / a)
  137.                    (rem (- (angle pt x) (angle pt y)) PI)
  138.                        )
  139.                    )
  140.                    list_vert_poly
  141.                    (cdr list_vert_poly)
  142.                  )
  143.                )
  144.              )
  145.              1e-8
  146.            )
  147.          )
  148.        )
  149.        Lp
  150.      )
  151.     )
  152.   )
  153. ;; Infittisce la griglia inserendo altri punti
  154. ;; nel centro delle diagonali tra i punti interni
  155. ;; Insert points (interior) to increase the density of the grid
  156.   (defun grid+ (/ G+)
  157.     (setq       G+
  158.      (mapcar '(lambda (x)
  159.           (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  160.         )
  161.        list_p_int
  162.      )
  163.     )
  164.     (setq list_p_int (append G+ list_p_int))
  165.   )
  166. ;; Da una lista di punti restituisce quello pił lontano da un oggetto
  167. ;; dati:  - lista dei punti -> list_p_int
  168. ;;        - oggetto -> POLY_vl
  169. ;; Returns the farthest point from the polyline
  170.   (defun Point_center (/ Pa Pvic)
  171.     (setq Dist 1e-6)
  172.     (foreach Pa list_p_int
  173.       (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
  174.       (if       (> (distance Pa Pvic) Dist)
  175.         (setq P_center Pa
  176.               R0             Dist
  177.               Dist     (distance Pa Pvic)
  178.         )
  179.       )
  180.     )
  181.   )
  182. ;;
  183.   (defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  184.     ;;Acc --- 0 ~ 99
  185.     (setq ent (entget en))
  186.     (while (setq ent (member (assoc 10 ent) ent))
  187.       (setq b   (cons (cdar ent) b)
  188.             ent (member (assoc 42 ent) ent)
  189.             b   (cons (cdar ent) b)
  190.             ent (cdr ent)
  191.             vetex       (cons b vetex)
  192.             b   nil
  193.       )
  194.     )
  195.     (while vetex
  196.       (setq a   (car vetex)
  197.             vetex       (cdr vetex)
  198.             bu  (car a)
  199.             p1  (cadr a)
  200.       )
  201.       (if       l
  202.         (setq p2 (car l))
  203.         (setq p2 (cadr (last vetex))
  204.               l  (cons p2 l)
  205.         )
  206.       )
  207.       (if       (equal bu 0 1e-6)
  208.         (setq l (cons p1 l))
  209.         (progn
  210.           (setq ang (* 2 (atan bu))
  211.                 r         (/ (distance p1 p2)
  212.                        (* 2 (sin ang))
  213.                     )
  214.                 c         (polar p1
  215.                        (+ (angle p1 p2) (- (/ pi 2) ang))
  216.                     r
  217.                     )
  218.                 r         (abs r)
  219.                 ang (abs (* ang 2.0))
  220.                 N         (abs (fix (/ ang 0.0174532925199433)))
  221.                 N         (min N (1+ Acc))
  222.           )
  223.           (if (= N 0)
  224.             (setq l (cons p1 l))
  225.             (progn
  226.               (setq an1 (/ ang N)
  227.               ang (angle c p2)
  228.               )
  229.               (if       (not (minusp bu))
  230.                 (setq an1 (- an1))
  231.               )
  232.               (repeat (1- N)
  233.                 (setq ang       (+ ang an1)
  234.                 l       (cons (polar c ang r) l)
  235.                 )
  236.               )
  237.               (setq l (cons p1 l))
  238.             )
  239.           )
  240.         )
  241.       )
  242.     )
  243.     l
  244.   )
  245.  
  246.   (setq ape (getvar 'aperture))
  247.   (setvar 'aperture 10)
  248.   (command "_.ucs" "_W")
  249.   (if
  250.     (and
  251.       (princ "\nSelect a Closed LWPolylines")
  252.       (setq polys (ssget '((0 . "LWPOLYLINE")(-4 . "&=")(70 . 1))))
  253.     )
  254.     (progn
  255.       (setq i -1)
  256.       (while (setq poly (ssname polys (setq i (1+ i))))
  257.         (setq area (vlax-curve-getArea poly)
  258.               len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly))
  259.         )
  260.         (setq x (vla-copy (vlax-ename->vla-object poly)))
  261.         (setq n (vla-get-normal x))
  262.         (setq e (vla-get-elevation x))
  263.         (vla-put-normal x (vlax-3d-point 0. 0. 1.))
  264.         (vla-update x)
  265.         (setq p (MaximumInscribedCircle_p (vlax-vla-object->ename x)))
  266.         (setq p (list (car p) (cadr p)))
  267.         (setq pl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 38 e) (assoc 10 (entget (vlax-vla-object->ename x))) (cons 10 p) '(210 0.0 0.0 1.0))))
  268.         (vla-put-normal (vlax-ename->vla-object pl) n)
  269.         (vla-update (vlax-ename->vla-object pl))
  270.         (setq p (trans (vlax-curve-getendpoint pl) 0 poly))
  271.         (setq ci (entmakex (list '(0 . "CIRCLE") '(100 . "AcDbEntity") '(100 . "AcDbCircle") (cons 10 p) (cons 40 (+ dist 1e-3)) '(62 . 2) (assoc 210 (entget poly)))))
  272.         (entdel pl)
  273.         (entdel (vlax-vla-object->ename x))
  274.         (setq ptse1e2 (vl-catch-all-apply 'interse1e2 (list poly ci)))
  275.         (command "_.ucs" "_ZA" '(0.0 0.0 0.0) (trans (cdr (assoc 210 (entget poly))) 0 1 t))
  276.         (setq pts1 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptse1e2) (cadr ptse1e2)))
  277.         (setq pts2 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (caddr ptse1e2) (cadddr ptse1e2)))
  278.         (setq pts3 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car (reverse ptse1e2)) (cadr (reverse ptse1e2))))
  279.         (setq ptse1e2 (list pts1 pts2 pts3))
  280.         (setq ptsints ptse1e2)
  281.         (setq plpts (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget poly))))
  282.         (setq plpts (mapcar '(lambda ( x ) (list (car x) (cadr x) e)) plpts))
  283.         (setq plpts (mapcar '(lambda ( x ) (trans x poly 0)) plpts))
  284.         (foreach pt ptsints
  285.           (mapcar '(lambda ( x ) (if (equal pt x (/ len 40.0 (sqrt area))) (setq ptl (cons pt ptl)))) plpts)
  286.         )
  287.         (foreach pt ptl
  288.           (setq ptsints (vl-remove-if '(lambda ( x ) (equal x pt (/ len 16.0 (sqrt area)))) ptsints))
  289.         )
  290.         (if (>= (length ptl) 3)
  291.             (progn
  292.             (entdel ci)
  293.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_end" (trans (caddr ptl) 0 1))
  294.             )
  295.         )
  296.         (if (and (= (length ptl) 2) (= (length ptsints) 0))
  297.             (progn
  298.             (entdel ci)
  299.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1))
  300.             )
  301.         )
  302.         (if (and (= (length ptl) 2) (= (length ptsints) 1))
  303.             (progn
  304.             (entdel ci)
  305.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  306.             )
  307.         )
  308.         (if (and (= (length ptl) 1) (= (length ptsints) 1))
  309.             (progn
  310.             (entdel ci)
  311.             (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  312.             )
  313.         )
  314.         (if (and (= (length ptl) 1) (= (length ptsints) 2))
  315.             (progn
  316.             (entdel ci)
  317.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  318.             )
  319.         )
  320.         (if (and (null ptl) (>= (length ptsints) 3))
  321.             (progn
  322.             (entdel ci)
  323.             (vl-cmdf "_.circle" "3P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (caddr ptsints)) 0 1))
  324.             )
  325.         )
  326.         (if (and (null ptl) (= (length ptsints) 2))
  327.             (progn
  328.             (entdel ci)
  329.             (vl-cmdf "_.circle" "2P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  330.             )
  331.         )
  332.         (command "_.ucs" "_P")
  333.         (setq ptl nil)
  334.       )
  335.       (command "_.ucs" "_P")
  336.     )
  337.   )
  338.   (*error* nil)
  339. )
  340.  

Regards, and many thanks to GP & GSLS(SS)...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 03, 2014, 05:05:46 AM
In fact I've already founded example LWPOLYLINE where it fails... See attachment - so center point is wrong - algorithm by GSLS(SS) needs to be improved...
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 03, 2014, 07:32:42 AM
I've implemented both algorithms and GP's and GSLS(SS)'s into single one... Posted LWPOLYLINE was solved, but I suppose both algorithms have their lacks in finding center point... So if GSLS(SS)'s fails then GP's is processed and if it also fails, then probably manual approach is desirable... Please inform me for any failures with this final version...

M.R.

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ipls ( / *error* 2d-lw-pt GetIntersections GroupByNum interse1e2 MaximumInscribedCircle_p LWPoly->List grid_1 grid_2 Point_int grid+ Point_center MaximumInscribedCircle_p_GP Vert_poly_GP grid_1_GP grid_2_GP inside_p_GP grid+_GP center_p_GP adoc area len ape polys poly pl x e n i lst p dist ci ptse1e2 pts1 pts2 pts3 ptsints plpts ptl )
  2.  
  3.  
  4.   (defun *error* ( msg )
  5.     (if ape (setvar 'aperture ape))
  6.     (vla-endundomark adoc)
  7.     (if msg (prompt msg))
  8.     (princ)
  9.   )
  10.  
  11.   (defun 2d-lw-pt ( lst )
  12.     (if lst
  13.       (cons (list (car lst) (cadr lst)) (2d-lw-pt (cddr lst)))
  14.     ) ;_  if
  15.   )
  16.  
  17.   (defun GetIntersections ( obj1 obj2 )
  18.     (GroupByNum (vlax-invoke obj1 'IntersectWith obj2 acExtendNone) 3)
  19.   )
  20.  
  21.   (defun GroupByNum ( l n / r)
  22.     (if l
  23.       (cons
  24.         (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r))
  25.         (GroupByNum l n)
  26.       )
  27.     )
  28.   )
  29.  
  30.   (defun interse1e2 ( e1 e2 / lst )
  31.     (if (and e1 e2)
  32.       (setq lst (GetIntersections (vlax-ename->vla-object e1) (vlax-ename->vla-object e2)))
  33.     )
  34.     lst
  35.   )
  36.  
  37. ;****************************************************************************
  38. ;  Ritorna il centro del massimo cerchio inscritto in una polilinea          
  39. ;  Returns the center point of the maximum inscribed circle in a polyline    
  40. ;                    Author: Gian Paolo Cattaneo                            
  41.   (defun MaximumInscribedCircle_p_GP
  42.          ( obj gr1 gr2 rep_gr2 / POLY POLY_vl Dx Dy Lp ;List_vert_poly
  43.                                  list_p_int P_center step1 step2 pc pc_d)
  44.  
  45.       (setq step1 gr1) ;--> grid_1
  46.       (setq step2 gr2) ;--> grid_2
  47.       (setq POLY_vl obj)
  48.       (setq list_vert_poly (Vert_poly_GP))
  49.       (grid_1_GP)  
  50.       (inside_p_GP)
  51.       (grid+_GP)
  52.       (center_p_GP)
  53.       (repeat rep_gr2
  54.           (grid_2_GP)
  55.           (center_p_GP)
  56.       )
  57.       (setq dist pc_d);distanza dal poligono
  58.       pc
  59.   )
  60.  
  61. ; restituisce la lista dei vertici di una polilinea
  62. ; Returns a list of polyline vertices
  63.   (defun Vert_poly_GP (/ n_par pt Lv ) ;elev)
  64.       (setq n_par (fix (vlax-curve-getendparam POLY_vl)))
  65.       (repeat n_par
  66.           (setq pt (vlax-curve-getpointatparam POLY_vl (setq n_par (1- n_par))))
  67.           (setq Lv (cons pt Lv))
  68.           (if (= 1 (length Lv)) (setq elev (last pt)))
  69.           (if (/= (last pt) elev)
  70.               (progn
  71.                   (alert
  72.                       (strcat
  73.                           "Invalid Object Selected."
  74.                           "\nThe z coordinate must be the same for all vertices."
  75.                       )
  76.                   )
  77.                   (exit)
  78.               )
  79.           )
  80.       )
  81.       Lv
  82.   )
  83.  
  84. ; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
  85. ; Returns a grid of points inside the BoundingBox of the selected poly
  86.   (defun grid_1_GP (/ P1_ P2_ n P> )
  87.       (vla-getboundingbox POLY_vl 'p1 'p2)
  88.       (setq P1_ (vlax-safearray->list p1))
  89.       (setq P2_ (vlax-safearray->list p2))
  90.       (setq P1_ (list (car P1_) (cadr P1_)))
  91.       (setq P2_ (list (car P2_) (cadr P2_)))
  92.       (setq Dx (/ (- (car P2_) (car P1_)) step1))
  93.       (setq Dy (/ (- (cadr P2_) (cadr P1_)) step1))
  94.       (setq n 0)
  95.       (setq P> P1_)
  96.       (setq Lp (list P1_))
  97.       (repeat (* (1+ step1) step1)
  98.           (setq P> (list (+ (car P>) Dx) (cadr P>)))
  99.           (setq Lp (cons P> Lp))
  100.           (setq n (1+ n))
  101.           (if (= n step1)
  102.               (progn
  103.                   (setq n 0)
  104.                   (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
  105.                   (setq P> P1_)
  106.                   (setq Lp (cons P> Lp))
  107.               )
  108.           )
  109.       )
  110.       (setq Lp (cdr Lp))
  111.   )
  112.  
  113. ; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
  114. ; Returns a grid of points around the center point (provisional)
  115.   (defun grid_2_GP (/ P1_ P> n)
  116.       (setq list_p_int nil)
  117.       (setq P1_ (list (- (car P_center) Dx) (- (cadr P_center) Dy)))
  118.       (setq Dx (/ (* 2 Dx) step2))
  119.       (setq Dy (/ (* 2 Dy) step2))
  120.       (setq n 0)
  121.       (setq P> P1_)
  122.       (setq list_p_int (list P1_))  
  123.       (repeat (* (1+ step2) step2)
  124.           (setq P> (list (+ (car P>) Dx) (cadr P>)))
  125.           (setq list_p_int (cons P> list_p_int))
  126.           (setq n (1+ n))
  127.           (if (= n step2)
  128.               (progn
  129.                   (setq n 0)
  130.                   (setq P1_ (list (car P1_) (+ (cadr P1_) Dy)))
  131.                   (setq P> P1_)
  132.                   (setq list_p_int (cons P> list_p_int))
  133.               )
  134.           )
  135.       )
  136.   )
  137.  
  138. ; restituisce la lista dei punti interni ad un poligono
  139. ; dati:  - lista coordinate dei punti -> Lp
  140. ;        - lista coordinate vertici poligono -> list_vert_poly
  141. ; Returns the list of points inside the polyline
  142.   (defun inside_p_GP (/ remote_p n Pr cont attr p# Pa Pa_ Pb)
  143.       (setq remote_p (list (car (getvar "extmax")) (* 1.1 (cadr (getvar "extmax")))))    
  144.       (setq list_p_int nil)
  145.       (foreach Pr Lp   
  146.           (setq cont -1)
  147.           (setq attr 0)
  148.           (setq p# nil)
  149.           (setq Pa (nth (setq cont (1+ cont)) list_vert_poly))
  150.           (setq Pa_ Pa)
  151.           (repeat (length list_vert_poly)
  152.               (setq Pb (nth (setq cont (1+ cont)) list_vert_poly))
  153.               (if (= cont (length list_vert_poly)) (setq Pb Pa_))
  154.               (setq P# (inters Pa Pb Pr remote_p))
  155.               (if (/= P# nil) (setq attr (1+ attr)))
  156.               (setq Pa Pb)
  157.           )
  158.           (if (> (rem attr 2) 0) (setq list_p_int (cons Pr list_p_int)))             
  159.       )
  160.   )
  161.  
  162. ; Infittisce la griglia inserendo altri punti
  163. ; nel centro delle diagonali tra i punti interni
  164. ; Increases the grid density
  165.   (defun grid+_GP (/ G+)
  166.       (setq G+
  167.           (mapcar '(lambda ( x ) (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))) list_p_int)
  168.       )
  169.       (setq list_p_int (append G+ list_p_int))
  170.   )
  171.  
  172. ; Da una lista di punti restituisce quello pił lontano da un oggetto
  173. ; dati:  - lista dei punti -> list_p_int
  174. ;        - oggetto -> POLY_vl
  175. ; Returns the farthest point from the polyline
  176.   (defun center_p_GP (/ Pa n Pvic Dist)
  177.       (setq Dist 1e-6)
  178.       (setq P_center nil)
  179.       (foreach Pa list_p_int
  180.       (setq Pvic (vlax-curve-getClosestPointTo POLY_vl Pa))
  181.           (if (> (distance Pa Pvic) Dist)
  182.               (progn
  183.                   (setq P_center Pa)
  184.                   (setq Dist (distance Pa Pvic))
  185.               )
  186.           )
  187.       )
  188.       (setq pc P_center) ;punto centro cerchio
  189.       (setq pc_d Dist)   ;distanza dal poligono
  190.   )
  191.  
  192. ;****************************************************************************  
  193.  
  194. ;****************************************************************************
  195. ;  Ritorna il centro del massimo cerchio inscritto in una polilinea          
  196. ;  Returns the center point of the maximum inscribed circle in a polyline    
  197. ;                    Author: Gian Paolo Cattaneo
  198. ;  edited by GSLS(SS) 2012-8-5
  199. ;****************************************************************************                            
  200.   (defun MaximumInscribedCircle_p ( poly / list_vert_poly step1 step2 i r0 P_center )
  201.  
  202.       (setq step1 (max 10 (fix (/ len 0.4 (sqrt area))))) ;_--> grid_1      
  203.       (setq step2 10) ;_--> grid_2
  204.       (setq list_vert_poly (LWPoly->List POLY 10))      
  205.       (grid_1)
  206.       (Point_int)
  207.       (Point_center)
  208.       (setq i 0)
  209.       (while (and (> (- Dist R0) 1e-8) (< i 10))
  210.         (grid_2)
  211.         (Point_center)
  212.         (setq i (1+ i))
  213.       )
  214.       P_center
  215.   )
  216.  
  217. ;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
  218. ;; Returns a grid of points within the BoundingBox of the selected poly
  219.   (defun grid_1 (/ p1 p2 X1 Y1 l1)
  220.     (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  221.     (setq       p1 (vlax-safearray->list p1)
  222.           p2 (vlax-safearray->list p2)
  223.           p1 (list (car p1) (cadr p1))
  224.           p2 (list (car p2) (cadr p2))
  225.     )
  226.     (setq Dx (/ (- (car p2) (car p1)) step1))
  227.     (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  228.     (setq       Lp (list p1)
  229.           X1 (car p1)
  230.           Y1 (cadr p1)
  231.     )
  232.     (repeat step1
  233.       (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  234.     )
  235.     (setq Lp (list Lp))
  236.     (repeat step1
  237.       (setq Lp (cons (mapcar (function (lambda (x)
  238.                  (list (car x) (+ (cadr x) Dy))
  239.                )
  240.            )
  241.            (car lp)
  242.          )
  243.          Lp
  244.          )
  245.       )
  246.     )
  247.     (setq Lp (apply (function append) Lp))
  248.   )
  249. ;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
  250. ;; Returns a grid of points around the center point (provisional)
  251.   (defun grid_2 (/ X1 Y1 P1)
  252.     (setq       list_p_int nil
  253.           X1       (- (car P_center) Dx)
  254.           Y1       (- (cadr P_center) Dy)
  255.           P1       (list X1 Y1)
  256.           Dx       (/ (* 2 Dx) step2)
  257.           Dy       (/ (* 2 Dy) step2)
  258.     )
  259.     (setq list_p_int (list P1))
  260.     (repeat step2
  261.       (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  262.     )
  263.     (setq list_p_int (list list_p_int))
  264.     (repeat step2
  265.       (setq list_p_int
  266.        (cons (mapcar (function (lambda (x)
  267.                (list (car x) (+ (cadr x) Dy))
  268.              )
  269.          )
  270.          (car list_p_int)
  271.        )
  272.        list_p_int
  273.        )
  274.       )
  275.     )
  276.     (setq list_p_int (apply (function append) list_p_int))
  277.   )
  278. ;; restituisce la lista dei punti interni ad un poligono
  279. ;; dati:  - lista coordinate dei punti -> Lp
  280. ;;        - lista coordinate vertici poligono -> list_vert_poly
  281. ;; Returns the list of points inside the polyline
  282.   (defun Point_int ()
  283.     (setq       list_p_int
  284.      (vl-remove-if-not
  285.        (function
  286.          (lambda (pt)
  287.            ;_determine point in curve , use widding number
  288.            (equal
  289.              PI
  290.              (abs
  291.                (apply
  292.                  (function +)
  293.                  (mapcar (function (lambda (x y / a)
  294.                    (rem (- (angle pt x) (angle pt y)) PI)
  295.                        )
  296.                    )
  297.                    list_vert_poly
  298.                    (cdr list_vert_poly)
  299.                  )
  300.                )
  301.              )
  302.              1e-8
  303.            )
  304.          )
  305.        )
  306.        Lp
  307.      )
  308.     )
  309.   )
  310. ;; Infittisce la griglia inserendo altri punti
  311. ;; nel centro delle diagonali tra i punti interni
  312. ;; Insert points (interior) to increase the density of the grid
  313.   (defun grid+ (/ G+)
  314.     (setq       G+
  315.      (mapcar '(lambda (x)
  316.           (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  317.         )
  318.        list_p_int
  319.      )
  320.     )
  321.     (setq list_p_int (append G+ list_p_int))
  322.   )
  323. ;; Da una lista di punti restituisce quello pił lontano da un oggetto
  324. ;; dati:  - lista dei punti -> list_p_int
  325. ;;        - oggetto -> POLY_vl
  326. ;; Returns the farthest point from the polyline
  327.   (defun Point_center (/ Pa Pvic)
  328.     (setq Dist 1e-6)
  329.     (foreach Pa list_p_int
  330.       (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
  331.       (if       (> (distance Pa Pvic) Dist)
  332.         (setq P_center Pa
  333.               R0             Dist
  334.               Dist     (distance Pa Pvic)
  335.         )
  336.       )
  337.     )
  338.   )
  339. ;;
  340.   (defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  341.     ;;Acc --- 0 ~ 99
  342.     (setq ent (entget en))
  343.     (while (setq ent (member (assoc 10 ent) ent))
  344.       (setq b   (cons (cdar ent) b)
  345.             ent (member (assoc 42 ent) ent)
  346.             b   (cons (cdar ent) b)
  347.             ent (cdr ent)
  348.             vetex       (cons b vetex)
  349.             b   nil
  350.       )
  351.     )
  352.     (while vetex
  353.       (setq a   (car vetex)
  354.             vetex       (cdr vetex)
  355.             bu  (car a)
  356.             p1  (cadr a)
  357.       )
  358.       (if       l
  359.         (setq p2 (car l))
  360.         (setq p2 (cadr (last vetex))
  361.               l  (cons p2 l)
  362.         )
  363.       )
  364.       (if       (equal bu 0 1e-6)
  365.         (setq l (cons p1 l))
  366.         (progn
  367.           (setq ang (* 2 (atan bu))
  368.                 r         (/ (distance p1 p2)
  369.                        (* 2 (sin ang))
  370.                     )
  371.                 c         (polar p1
  372.                        (+ (angle p1 p2) (- (/ pi 2) ang))
  373.                     r
  374.                     )
  375.                 r         (abs r)
  376.                 ang (abs (* ang 2.0))
  377.                 N         (abs (fix (/ ang 0.0174532925199433)))
  378.                 N         (min N (1+ Acc))
  379.           )
  380.           (if (= N 0)
  381.             (setq l (cons p1 l))
  382.             (progn
  383.               (setq an1 (/ ang N)
  384.               ang (angle c p2)
  385.               )
  386.               (if       (not (minusp bu))
  387.                 (setq an1 (- an1))
  388.               )
  389.               (repeat (1- N)
  390.                 (setq ang       (+ ang an1)
  391.                 l       (cons (polar c ang r) l)
  392.                 )
  393.               )
  394.               (setq l (cons p1 l))
  395.             )
  396.           )
  397.         )
  398.       )
  399.     )
  400.     l
  401.   )
  402.  
  403.   (setq ape (getvar 'aperture))
  404.   (setvar 'aperture 10)
  405.   (command "_.ucs" "_W")
  406.   (if
  407.     (and
  408.       (princ "\nSelect a Closed LWPolylines")
  409.       (setq polys (ssget '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1))))
  410.     )
  411.     (progn
  412.       (setq i -1)
  413.       (while (setq poly (ssname polys (setq i (1+ i))))
  414.         (setq area (vlax-curve-getArea poly)
  415.               len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly))
  416.         )
  417.         (setq x (vla-copy (vlax-ename->vla-object poly)))
  418.         (setq n (vla-get-normal x))
  419.         (setq e (vla-get-elevation x))
  420.         (vla-put-normal x (vlax-3d-point 0. 0. 1.))
  421.         (vla-update x)
  422.         (setq p (MaximumInscribedCircle_p (vlax-vla-object->ename x)))
  423.         (setq p (list (car p) (cadr p)))
  424.         (setq pl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 38 e) (assoc 10 (entget (vlax-vla-object->ename x))) (cons 10 p) '(210 0.0 0.0 1.0))))
  425.         (vla-put-normal (vlax-ename->vla-object pl) n)
  426.         (vla-update (vlax-ename->vla-object pl))
  427.         (setq p (trans (vlax-curve-getendpoint pl) 0 poly))
  428.         (setq ci (entmakex (list '(0 . "CIRCLE") '(100 . "AcDbEntity") '(100 . "AcDbCircle") (cons 10 p) (cons 40 (+ dist 1e-2)) '(62 . 2) (assoc 210 (entget poly)))))
  429.         (entdel pl)
  430.         (setq ptse1e2 (vl-catch-all-apply 'interse1e2 (list poly ci)))
  431.         (if (/= (length ptse1e2) 6)
  432.           (progn
  433.             (entdel ci)
  434.             (setq p (MaximumInscribedCircle_p_GP x 250 25 5))
  435.             (setq p (list (car p) (cadr p)))
  436.             (setq pl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 38 e) (assoc 10 (entget (vlax-vla-object->ename x))) (cons 10 p) '(210 0.0 0.0 1.0))))
  437.             (vla-put-normal (vlax-ename->vla-object pl) n)
  438.             (vla-update (vlax-ename->vla-object pl))
  439.             (setq p (trans (vlax-curve-getendpoint pl) 0 poly))
  440.             (setq ci (entmakex (list '(0 . "CIRCLE") '(100 . "AcDbEntity") '(100 . "AcDbCircle") (cons 10 p) (cons 40 (+ dist 1e-2)) '(62 . 2) (assoc 210 (entget poly)))))
  441.             (entdel pl)
  442.             (setq ptse1e2 (vl-catch-all-apply 'interse1e2 (list poly ci)))
  443.           )
  444.         )
  445.         (entdel (vlax-vla-object->ename x))
  446.         (command "_.ucs" "_ZA" '(0.0 0.0 0.0) (trans (cdr (assoc 210 (entget poly))) 0 1 t))
  447.         (setq pts1 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptse1e2) (cadr ptse1e2)))
  448.         (setq pts2 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (caddr ptse1e2) (cadddr ptse1e2)))
  449.         (setq pts3 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car (reverse ptse1e2)) (cadr (reverse ptse1e2))))
  450.         (setq ptse1e2 (list pts1 pts2 pts3))
  451.         (setq ptsints ptse1e2)
  452.         (setq plpts (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget poly))))
  453.         (setq plpts (mapcar '(lambda ( x ) (list (car x) (cadr x) e)) plpts))
  454.         (setq plpts (mapcar '(lambda ( x ) (trans x poly 0)) plpts))
  455.         (foreach pt ptsints
  456.           (mapcar '(lambda ( x ) (if (equal pt x (/ len 40.0 (sqrt area))) (setq ptl (cons pt ptl)))) plpts)
  457.         )
  458.         (foreach pt ptl
  459.           (setq ptsints (vl-remove-if '(lambda ( x ) (equal x pt (/ len 16.0 (sqrt area)))) ptsints))
  460.         )
  461.         (if (>= (length ptl) 3)
  462.             (progn
  463.             (entdel ci)
  464.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_end" (trans (caddr ptl) 0 1))
  465.             )
  466.         )
  467.         (if (and (= (length ptl) 2) (= (length ptsints) 0))
  468.             (progn
  469.             (entdel ci)
  470.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1))
  471.             )
  472.         )
  473.         (if (and (= (length ptl) 2) (= (length ptsints) 1))
  474.             (progn
  475.             (entdel ci)
  476.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  477.             )
  478.         )
  479.         (if (and (= (length ptl) 1) (= (length ptsints) 1))
  480.             (progn
  481.             (entdel ci)
  482.             (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  483.             )
  484.         )
  485.         (if (and (= (length ptl) 1) (= (length ptsints) 2))
  486.             (progn
  487.             (entdel ci)
  488.             (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  489.             )
  490.         )
  491.         (if (and (null ptl) (>= (length ptsints) 3))
  492.             (progn
  493.             (entdel ci)
  494.             (vl-cmdf "_.circle" "3P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (caddr ptsints)) 0 1))
  495.             )
  496.         )
  497.         (if (and (null ptl) (= (length ptsints) 2))
  498.             (progn
  499.             (entdel ci)
  500.             (vl-cmdf "_.circle" "2P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  501.             )
  502.         )
  503.         (command "_.ucs" "_P")
  504.         (setq ptl nil)
  505.       )
  506.       (command "_.ucs" "_P")
  507.     )
  508.   )
  509.   (*error* nil)
  510. )
  511.  
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: chlh_jd on May 03, 2014, 11:40:38 AM
Ribarm , you are always welcome .
Even now , I have not use this program before writting .
I'll test yours , after some time later .
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 05, 2014, 08:18:59 AM
I've done some modifications again... Now I've shortened complete code to only GSLS(SS) variant... It should be fast if found 6 intersections with polyline and little larger circle... If not then it will proceed to process little slower - higher precision search with the same sub-functions, but with larger arguments supplied... Have checked for various cases with various lwpolylines and had no problems... My posted DWG was solved, and in situation where GP's variant searched wrong, now GSLS(SS) code was correct... This was lwpolyline Evgeniy posted as picture showing the problem - how would you determine direction of polyline (large arc above trimmed rectangle)... So here is my I hope last final version...

[EDIT : I've put slower search algorithm into comments - commented out complete paragraph - it should work now fast enough...]

[EDIT : I've removed slower search algorithm and put grid1=50 and grid2=50 - it should be fast enough...]

Also made small modifications to sub-functions... Evgeniy's example lwpolyline is still with some approximately solution...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ipls ( / *error* GetIntersections GroupByNum interse1e2 MaximumInscribedCircle_p LWPoly->List grid_1 grid_2 Point_int grid+ Point_center adoc area len osm ape polys poly pl x e n i lst p dist ci ptse1e2 pts1 pts2 pts3 ptsints plpts ptl )
  2.  
  3.  
  4.   (defun *error* ( msg )
  5.     (if osm (setvar 'osmode osm))
  6.     (if ape (setvar 'aperture ape))
  7.     (vla-endundomark adoc)
  8.     (if msg (prompt msg))
  9.     (princ)
  10.   )
  11.  
  12.   (defun GetIntersections ( obj1 obj2 )
  13.     (GroupByNum (vlax-invoke obj1 'IntersectWith obj2 acExtendNone) 3)
  14.   )
  15.  
  16.   (defun GroupByNum ( l n / r)
  17.     (if l
  18.       (cons
  19.         (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r))
  20.         (GroupByNum l n)
  21.       )
  22.     )
  23.   )
  24.  
  25.   (defun interse1e2 ( e1 e2 / lst )
  26.     (if (and e1 e2)
  27.       (setq lst (GetIntersections (vlax-ename->vla-object e1) (vlax-ename->vla-object e2)))
  28.     )
  29.     lst
  30.   )
  31.  
  32. ;****************************************************************************
  33. ;  Ritorna il centro del massimo cerchio inscritto in una polilinea          
  34. ;  Returns the center point of the maximum inscribed circle in a polyline    
  35. ;                    Author: Gian Paolo Cattaneo
  36. ;  edited by GSLS(SS) 2012-8-5
  37. ;****************************************************************************                            
  38.   (defun MaximumInscribedCircle_p ( poly step1 step2 / list_vert_poly step1 step2 r0 P_center )
  39.  
  40.       (setq step1 step1) ;_--> grid_1
  41.       (setq step2 step2) ;_--> grid_2
  42.       (setq list_vert_poly (LWPoly->List POLY 10))      
  43.       (grid_1)
  44.       (Point_int)
  45.       (Point_center)
  46.       (while (> (- Dist R0) 1e-12)
  47.         (grid_2)
  48.         (Point_center)
  49.       )
  50.       P_center
  51.   )
  52.  
  53. ;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
  54. ;; Returns a grid of points within the BoundingBox of the selected poly
  55.   (defun grid_1 (/ p1 p2 X1 Y1 l1)
  56.     (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  57.     (setq p1 (vlax-safearray->list p1)
  58.           p2 (vlax-safearray->list p2)
  59.           p1 (list (car p1) (cadr p1))
  60.           p2 (list (car p2) (cadr p2))
  61.     )
  62.     (setq Dx (/ (- (car p2) (car p1)) step1))
  63.     (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  64.     (setq Lp (list p1)
  65.           X1 (car p1)
  66.           Y1 (cadr p1)
  67.     )
  68.     (repeat step1
  69.       (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  70.     )
  71.     (setq Lp (list Lp))
  72.     (repeat step1
  73.       (setq Lp (cons (mapcar (function (lambda (x)
  74.                           (list (car x) (+ (cadr x) Dy))
  75.                           )
  76.                         )
  77.                         (car lp)
  78.                       )
  79.                       Lp
  80.                )
  81.       )
  82.     )
  83.     (setq Lp (apply (function append) Lp))
  84.   )
  85. ;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
  86. ;; Returns a grid of points around the center point (provisional)
  87.   (defun grid_2 (/ X1 Y1 P1)
  88.     (setq list_p_int nil
  89.           X1       (- (car P_center) (* 1.0 Dx))
  90.           Y1       (- (cadr P_center) (* 1.0 Dy))
  91.           P1       (list X1 Y1)
  92.           Dx       (/ (* 2.0 Dx) step2)
  93.           Dy       (/ (* 2.0 Dy) step2)
  94.     )
  95.     (setq list_p_int (list P1))
  96.     (repeat step2
  97.       (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  98.     )
  99.     (setq list_p_int (list list_p_int))
  100.     (repeat step2
  101.       (setq list_p_int
  102.         (cons (mapcar (function (lambda (x)
  103.                 (list (car x) (+ (cadr x) Dy))
  104.                   )
  105.                 )
  106.                 (car list_p_int)
  107.               )
  108.               list_p_int
  109.         )
  110.       )
  111.     )
  112.     (setq list_p_int (apply (function append) list_p_int))
  113.   )
  114. ;; restituisce la lista dei punti interni ad un poligono
  115. ;; dati:  - lista coordinate dei punti -> Lp
  116. ;;        - lista coordinate vertici poligono -> list_vert_poly
  117. ;; Returns the list of points inside the polyline
  118.   (defun Point_int ()
  119.     (setq list_p_int
  120.       (vl-remove-if-not
  121.         (function
  122.           (lambda ( pt )
  123.             ;_determine point in curve , use widding number
  124.             (equal
  125.               PI
  126.               (abs
  127.                 (apply
  128.                   (function +)
  129.                   (mapcar (function (lambda ( x y )
  130.                     (rem (- (angle pt x) (angle pt y)) PI)
  131.                         )
  132.                     )
  133.                     list_vert_poly
  134.                     (cdr list_vert_poly)
  135.                   )
  136.                 )
  137.               )
  138.               1e-8
  139.             )
  140.           )
  141.         )
  142.         Lp
  143.       )
  144.     )
  145.   )
  146.   ;|
  147. ;; Infittisce la griglia inserendo altri punti
  148. ;; nel centro delle diagonali tra i punti interni
  149. ;; Insert points (interior) to increase the density of the grid
  150.   (defun grid+ (/ G+)
  151.     (setq G+
  152.      (mapcar '(lambda (x)
  153.           (list (+ (car x) (/ Dx 2)) (+ (cadr x) (/ Dy 2)))
  154.         )
  155.        list_p_int
  156.      )
  157.     )
  158.     (setq list_p_int (append G+ list_p_int))
  159.   )
  160.   |;
  161. ;; Da una lista di punti restituisce quello pił lontano da un oggetto
  162. ;; dati:  - lista dei punti -> list_p_int
  163. ;;        - oggetto -> POLY_vl
  164. ;; Returns the farthest point from the polyline
  165.   (defun Point_center (/ Pa Pvic)
  166.     (if (null Dist) (setq Dist 1e-6))
  167.     (foreach Pa list_p_int
  168.       (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
  169.       (if (> (distance Pa Pvic) Dist)
  170.         (setq P_center Pa
  171.               R0       Dist
  172.               Dist     (distance Pa Pvic)
  173.         )
  174.       )
  175.     )
  176.   )
  177. ;;
  178.   (defun LWPoly->List (en acc / a b vetex bu p1 p2 l r ang an1 N)
  179.     ;;Acc --- 0 ~ 99
  180.     (setq ent (entget en))
  181.     (while (setq ent (member (assoc 10 ent) ent))
  182.       (setq b   (cons (cdar ent) b)
  183.             ent (member (assoc 42 ent) ent)
  184.             b   (cons (cdar ent) b)
  185.             ent (cdr ent)
  186.             vetex       (cons b vetex)
  187.             b   nil
  188.       )
  189.     )
  190.     (while vetex
  191.       (setq a   (car vetex)
  192.             vetex       (cdr vetex)
  193.             bu  (car a)
  194.             p1  (cadr a)
  195.       )
  196.       (if l
  197.         (setq p2 (car l))
  198.         (setq p2 (cadr (last vetex))
  199.               l  (cons p2 l)
  200.         )
  201.       )
  202.       (if (equal bu 0 1e-6)
  203.         (setq l (cons p1 l))
  204.         (progn
  205.           (setq ang (* 2 (atan bu))
  206.                 r (/ (distance p1 p2)
  207.                      (* 2 (sin ang))
  208.                   )
  209.                 c (polar p1
  210.                     (+ (angle p1 p2) (- (/ pi 2) ang))
  211.                     r
  212.                   )
  213.                 r (abs r)
  214.                 ang (abs (* ang 2.0))
  215.                 N   (abs (fix (/ ang 0.0174532925199433)))
  216.                 N   (min N (1+ Acc))
  217.           )
  218.           (if (= N 0)
  219.             (setq l (cons p1 l))
  220.             (progn
  221.               (setq an1 (/ ang N)
  222.                     ang (angle c p2)
  223.               )
  224.               (if (not (minusp bu))
  225.                 (setq an1 (- an1))
  226.               )
  227.               (repeat (1- N)
  228.                 (setq ang (+ ang an1)
  229.                       l (cons (polar c ang r) l)
  230.                 )
  231.               )
  232.               (setq l (cons p1 l))
  233.             )
  234.           )
  235.         )
  236.       )
  237.     )
  238.     l
  239.   )
  240. ;****************************************************************************
  241. ;****************************************************************************
  242.   (setq osm (getvar 'osmode))
  243.   (setq ape (getvar 'aperture))
  244.   (setvar 'osmode 0)
  245.   (setvar 'aperture 25)
  246.   (command "_.ucs" "_W")
  247.   (if
  248.     (and
  249.       (princ "\nSelect closed lwpolyline(s)")
  250.       (setq polys (ssget '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1))))
  251.     )
  252.     (progn
  253.       (setq i -1)
  254.       (while (setq poly (ssname polys (setq i (1+ i))))
  255.         (setq area (vlax-curve-getArea poly)
  256.               len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly))
  257.         )
  258.         (setq x (vla-copy (vlax-ename->vla-object poly)))
  259.         (setq n (vla-get-normal x))
  260.         (setq e (vla-get-elevation x))
  261.         (vla-put-normal x (vlax-3d-point 0.0 0.0 1.0))
  262.         (vla-update x)
  263.         (setq p (MaximumInscribedCircle_p (vlax-vla-object->ename x) 50 50))
  264.         (setq p (list (car p) (cadr p)))
  265.         (setq pl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 38 e) (assoc 10 (entget (vlax-vla-object->ename x))) (cons 10 p) '(210 0.0 0.0 1.0))))
  266.         (vla-put-normal (vlax-ename->vla-object pl) n)
  267.         (vla-update (vlax-ename->vla-object pl))
  268.         (setq p (trans (vlax-curve-getendpoint pl) 0 poly))
  269.         (setq ci (entmakex (list '(0 . "CIRCLE") '(100 . "AcDbEntity") '(100 . "AcDbCircle") (cons 10 p) (cons 40 (+ dist 5e-5)) '(62 . 2) (assoc 210 (entget poly)))))
  270.         (entdel pl)
  271.         (setq ptse1e2 (vl-catch-all-apply 'interse1e2 (list poly ci)))
  272.         (entdel (vlax-vla-object->ename x))
  273.         (command "_.ucs" "_ZA" '(0.0 0.0 0.0) (trans (cdr (assoc 210 (entget poly))) 0 1 t))
  274.         (if (= (length ptse1e2) 6)
  275.           (progn
  276.             (setq pts1 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptse1e2) (cadr ptse1e2)))
  277.             (setq pts2 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (caddr ptse1e2) (cadddr ptse1e2)))
  278.             (setq pts3 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car (reverse ptse1e2)) (cadr (reverse ptse1e2))))
  279.             (setq ptse1e2 (list pts1 pts2 pts3))
  280.             (setq ptsints ptse1e2)
  281.           )
  282.           (setq ptsints ptse1e2)
  283.         )
  284.         (setq plpts (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget poly))))
  285.         (setq plpts (mapcar '(lambda ( x ) (list (car x) (cadr x) e)) plpts))
  286.         (setq plpts (mapcar '(lambda ( x ) (trans x poly 0)) plpts))
  287.         (foreach pt ptsints
  288.           (mapcar '(lambda ( x ) (if (equal pt x (/ len 40.0 (sqrt area))) (setq ptl (cons pt ptl)))) plpts)
  289.         )
  290.         (foreach pt ptl
  291.           (setq ptsints (vl-remove-if '(lambda ( x ) (equal x pt (/ len 16.0 (sqrt area)))) ptsints))
  292.         )
  293.         (setq ptl (acet-list-remove-duplicates ptl 1.0))
  294.         (setq ptsints (acet-list-remove-duplicates ptsints 1.0))
  295.         (if (>= (length ptl) 3)
  296.             (progn
  297.               (entdel ci)
  298.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_end" (trans (caddr ptl) 0 1))
  299.             )
  300.         )
  301.         (if (and (= (length ptl) 2) (= (length ptsints) 0))
  302.             (progn
  303.               (entdel ci)
  304.               (if (equal (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptl) (cadr ptl)) p 1e-4)
  305.                 (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1))
  306.                 (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getpointatparam poly (+ (min (vlax-curve-getparamatpoint poly (car ptl)) (vlax-curve-getparamatpoint poly (cadr ptl))) (/ (abs (- (vlax-curve-getparamatpoint poly (car ptl)) (vlax-curve-getparamatpoint poly (cadr ptl)))) 2.0))) 0 1))
  307.               )
  308.             )
  309.         )
  310.         (if (and (= (length ptl) 2) (= (length ptsints) 1))
  311.             (progn
  312.               (entdel ci)
  313.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  314.             )
  315.         )
  316.         (if (and (= (length ptl) 1) (= (length ptsints) 1))
  317.             (progn
  318.               (entdel ci)
  319.               (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  320.             )
  321.         )
  322.         (if (and (= (length ptl) 1) (= (length ptsints) 2))
  323.             (progn
  324.               (entdel ci)
  325.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  326.             )
  327.         )
  328.         (if (and (null ptl) (>= (length ptsints) 3))
  329.             (progn
  330.               (entdel ci)
  331.               (vl-cmdf "_.circle" "3P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (caddr ptsints)) 0 1))
  332.             )
  333.         )
  334.         (if (and (null ptl) (= (length ptsints) 2))
  335.             (progn
  336.               (entdel ci)
  337.               (vl-cmdf "_.circle" (trans p poly 1) (trans (vlax-curve-getclosestpointto poly (trans p poly 0)) 0 1))
  338.             )
  339.         )
  340.         (command "_.ucs" "_P")
  341.         (setq ptl nil dist nil)
  342.       )
  343.       (command "_.ucs" "_P")
  344.     )
  345.   )
  346.   (*error* nil)
  347. )
  348.  

Regards, M.R.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 05, 2014, 03:18:16 PM
I have updated my version of Lee Mac's Smallest Circumscribed Circle (Minimum Enclosing Circle)...

You can download from this link :
http://www.cadtutor.net/forum/showthread.php?63541-Smallest-Circumscribing-Circle/page5&p=#49

M.R.
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 06, 2014, 05:52:47 AM
I have updated and optimized my last posted code... HTH, M.R.

Regards...
 :-)
Title: Re: =={challenge}==Find the maximum inscribed circle
Post by: ribarm on May 25, 2014, 04:52:50 AM
I was absent for a while, and I decided to post GP's variant which I thought it was better - I use this code now...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:ipls ( / *error* GetIntersections GroupByNum interse1e2 MaximumInscribedCircle_p LM:LWPoly->List grid_1 grid_2 inside_p Point_center adoc area len osm ape polys poly pl x e n i lst p dist ci ptse1e2 pts1 pts2 pts3 ptsints plpts ptl )
  2.  
  3.  
  4.   (defun *error* ( msg )
  5.     (if osm (setvar 'osmode osm))
  6.     (if ape (setvar 'aperture ape))
  7.     (vla-endundomark adoc)
  8.     (if msg (prompt msg))
  9.     (princ)
  10.   )
  11.  
  12.   (defun GetIntersections ( obj1 obj2 )
  13.     (GroupByNum (vlax-invoke obj1 'IntersectWith obj2 acExtendNone) 3)
  14.   )
  15.  
  16.   (defun GroupByNum ( l n / r)
  17.     (if l
  18.       (cons
  19.         (reverse (repeat n (setq r (cons (car l) r) l (cdr l)) r))
  20.         (GroupByNum l n)
  21.       )
  22.     )
  23.   )
  24.  
  25.   (defun interse1e2 ( e1 e2 / lst )
  26.     (if (and e1 e2)
  27.       (setq lst (GetIntersections (vlax-ename->vla-object e1) (vlax-ename->vla-object e2)))
  28.     )
  29.     lst
  30.   )
  31.  
  32. ;****************************************************************************
  33. ;  Ritorna il centro del massimo cerchio inscritto in una polilinea          
  34. ;  Returns the center point of the maximum inscribed circle in a polyline    
  35. ;                    Author: Gian Paolo Cattaneo
  36. ;****************************************************************************
  37.   (defun MaximumInscribedCircle_p ( poly step1 step2 / list_vert_poly step1 step2 all_ins r0 P_center )
  38.  
  39.       (setq step1 step1) ;_--> grid_1
  40.       (setq step2 step2) ;_--> grid_2
  41.       (setq list_vert_poly (LM:LWPoly->List POLY 25))      
  42.       (grid_1)
  43.       (inside_p)
  44.       (Point_center)
  45.       (while (> (- Dist R0) 4e-13)
  46.         (grid_2)
  47.         (inside_p)
  48.         (Point_center)
  49.       )
  50.       P_center
  51.   )
  52.  
  53. ;; Restituisce una griglia di punti all'interno del getboundingbox della poly selezionata
  54. ;; Returns a grid of points within the BoundingBox of the selected poly
  55.   (defun grid_1 ( / p1 p2 X1 Y1 l1 )
  56.     (vla-getboundingbox (vlax-ename->vla-object POLY) 'p1 'p2)
  57.     (setq p1 (vlax-safearray->list p1)
  58.           p2 (vlax-safearray->list p2)
  59.           p1 (list (car p1) (cadr p1))
  60.           p2 (list (car p2) (cadr p2))
  61.     )
  62.     (setq Dx (/ (- (car p2) (car p1)) step1))
  63.     (setq Dy (/ (- (cadr p2) (cadr p1)) step1))
  64.     (setq Lp (list p1)
  65.           X1 (car p1)
  66.           Y1 (cadr p1)
  67.     )
  68.     (repeat step1
  69.       (setq Lp (cons (list (setq X1 (+ X1 Dx)) Y1) Lp))
  70.     )
  71.     (setq Lp (list Lp))
  72.     (repeat step1
  73.       (setq Lp (cons (mapcar (function (lambda (x)
  74.                           (list (car x) (+ (cadr x) Dy))
  75.                           )
  76.                         )
  77.                         (car lp)
  78.                       )
  79.                       Lp
  80.                )
  81.       )
  82.     )
  83.     (setq Lp (apply (function append) Lp))
  84.   )
  85. ;; Restituisce una griglia di punti intorno al punto centrale (provvisorio)
  86. ;; Returns a grid of points around the center point (provisional)
  87.   (defun grid_2 ( / X1 Y1 P1 )
  88.     (setq list_p_int nil
  89.           X1       (- (car P_center) (* 1.0 Dx (/ step1 4.0)))
  90.           Y1       (- (cadr P_center) (* 1.0 Dy (/ step1 4.0)))
  91.           P1       (list X1 Y1)
  92.           Dx       (/ (* 2.0 Dx (/ step1 4.0)) step2)
  93.           Dy       (/ (* 2.0 Dy (/ step1 4.0)) step2)
  94.     )
  95.     (setq list_p_int (list P1))
  96.     (repeat step2
  97.       (setq list_p_int (cons (list (setq X1 (+ X1 Dx)) Y1) list_p_int))
  98.     )
  99.     (setq list_p_int (list list_p_int))
  100.     (repeat step2
  101.       (setq list_p_int
  102.         (cons (mapcar (function (lambda (x)
  103.                 (list (car x) (+ (cadr x) Dy))
  104.                   )
  105.                 )
  106.                 (car list_p_int)
  107.               )
  108.               list_p_int
  109.         )
  110.       )
  111.     )
  112.     (setq list_p_int (apply (function append) list_p_int))
  113.     (setq step1 step2)
  114.   )
  115. ; restituisce la lista dei punti interni ad un poligono
  116. ; dati:  - lista coordinate dei punti -> Lp
  117. ;        - lista coordinate vertici poligono -> list_vert_poly
  118. ; Returns the list of points inside the polyline
  119.   (defun inside_p ( / remote_p n Pr cont attr p# Pa Pa_ Pb )
  120.       (setq remote_p (list (* 1.1 (car (getvar "extmax"))) (* 1.1 (cadr (getvar "extmax")))))
  121.       (if (not all_ins)
  122.           (progn
  123.               (setq list_p_int nil)
  124.               (foreach Pr Lp   
  125.                   (setq cont -1)
  126.                   (setq attr 0)
  127.                   (setq p# nil)
  128.                   (setq Pa (nth (setq cont (1+ cont)) list_vert_poly))
  129.                   (setq Pa_ Pa)
  130.                   (repeat (length list_vert_poly)
  131.                       (setq Pb (nth (setq cont (1+ cont)) list_vert_poly))
  132.                       (if (= cont (length list_vert_poly)) (setq Pb Pa_))
  133.                       (setq P# (inters Pa Pb Pr remote_p))
  134.                       (if (/= P# nil) (setq attr (1+ attr)))
  135.                       (setq Pa Pb)
  136.                   )
  137.                   (if (> (rem attr 2) 0) (setq list_p_int (cons Pr list_p_int)))             
  138.               )
  139.               (setq list_p_int (reverse list_p_int))
  140.               (if (vl-every '(lambda ( a b ) (equal a b 1e-8)) Lp list_p_int)
  141.                   (setq all_ins t)
  142.                   (setq all_ins nil)
  143.               )
  144.               (setq Lp list_p_int)
  145.           )
  146.       )
  147.   )
  148. ;; Da una lista di punti restituisce quello pił lontano da un oggetto
  149. ;; dati:  - lista dei punti -> list_p_int
  150. ;;        - oggetto -> POLY_vl
  151. ;; Returns the farthest point from the polyline
  152.   (defun Point_center ( / Pa Pvic )
  153.     (if (null Dist) (setq Dist 1e-6))
  154.     (foreach Pa list_p_int
  155.       (setq Pvic (vlax-curve-getClosestPointTo Poly Pa))
  156.       (if (> (distance Pa Pvic) Dist)
  157.         (setq P_center Pa
  158.               R0       Dist
  159.               Dist     (distance Pa Pvic)
  160.         )
  161.       )
  162.     )
  163.   )
  164. ;; LWPolyline to Point List  -  Lee Mac
  165. ;; Returns a list of points describing the supplied LWPolyline with each segment derived
  166.   (defun LM:LWPoly->List ( ent n / der di1 di2 inc lst par )
  167.       (vl-load-com)
  168.       (setq par 0)
  169.       (repeat (cdr (assoc 90 (entget ent)))
  170.           (if
  171.               (setq di1 (vlax-curve-getdistatparam ent par)
  172.                     di2 (vlax-curve-getdistatparam ent (1+ par))
  173.               )
  174.               (progn
  175.                   (setq inc (/ (- di2 di1) n))
  176.                   (while (< di1 di2)
  177.                       (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
  178.                             di1 (+ di1 inc)
  179.                       )
  180.                   )
  181.                   (if (eq (vlax-curve-isclosed ent) nil)
  182.                       (progn
  183.                           (if (equal (vlax-curve-getpointatdist ent di1) (vlax-curve-getendpoint ent) 1e-8)
  184.                               (setq lst (cons (vlax-curve-getendpoint ent) lst))
  185.                           )
  186.                       )
  187.                   )
  188.               )
  189.           )
  190.           (setq par (1+ par))
  191.       )
  192.       (reverse lst)
  193.   )
  194. ;****************************************************************************
  195. ;****************************************************************************
  196.   (setq osm (getvar 'osmode))
  197.   (setq ape (getvar 'aperture))
  198.   (setvar 'osmode 0)
  199.   (setvar 'aperture 25)
  200.   (command "_.ucs" "_W")
  201.   (if
  202.     (and
  203.       (princ "\nSelect closed lwpolyline(s)")
  204.       (setq polys (ssget '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1))))
  205.     )
  206.     (progn
  207.       (setq i -1)
  208.       (while (setq poly (ssname polys (setq i (1+ i))))
  209.         (setq area (vlax-curve-getArea poly)
  210.               len (vlax-curve-getDistAtParam poly (vlax-curve-getEndParam poly))
  211.         )
  212.         (setq x (vla-copy (vlax-ename->vla-object poly)))
  213.         (setq n (vla-get-normal x))
  214.         (setq e (vla-get-elevation x))
  215.         (vla-put-normal x (vlax-3d-point 0.0 0.0 1.0))
  216.         (vla-update x)
  217.         (setq p (MaximumInscribedCircle_p (vlax-vla-object->ename x) 48 32))
  218.         (setq p (list (car p) (cadr p)))
  219.         (setq pl (entmakex (list '(0 . "LWPOLYLINE") '(100 . "AcDbEntity") '(100 . "AcDbPolyline") '(90 . 2) '(70 . 0) (cons 38 e) (assoc 10 (entget (vlax-vla-object->ename x))) (cons 10 p) '(210 0.0 0.0 1.0))))
  220.         (vla-put-normal (vlax-ename->vla-object pl) n)
  221.         (vla-update (vlax-ename->vla-object pl))
  222.         (setq p (trans (vlax-curve-getendpoint pl) 0 poly))
  223.         (setq ci (entmakex (list '(0 . "CIRCLE") '(100 . "AcDbEntity") '(100 . "AcDbCircle") (cons 10 p) (cons 40 (+ dist 1e-5)) '(62 . 2) (assoc 210 (entget poly)))))
  224.         (entdel pl)
  225.         (setq ptse1e2 (vl-catch-all-apply 'interse1e2 (list poly ci)))
  226.         (entdel (vlax-vla-object->ename x))
  227.         (command "_.ucs" "_ZA" '(0.0 0.0 0.0) (trans (cdr (assoc 210 (entget poly))) 0 1 t))
  228.         (if (= (length ptse1e2) 6)
  229.           (progn
  230.             (setq pts1 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptse1e2) (cadr ptse1e2)))
  231.             (setq pts2 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (caddr ptse1e2) (cadddr ptse1e2)))
  232.             (setq pts3 (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car (reverse ptse1e2)) (cadr (reverse ptse1e2))))
  233.             (setq ptse1e2 (list pts1 pts2 pts3))
  234.             (setq ptsints ptse1e2)
  235.           )
  236.           (setq ptsints ptse1e2)
  237.         )
  238.         (setq plpts (mapcar 'cdr (vl-remove-if-not '(lambda ( x ) (= (car x) 10)) (entget poly))))
  239.         (setq plpts (mapcar '(lambda ( x ) (list (car x) (cadr x) e)) plpts))
  240.         (setq plpts (mapcar '(lambda ( x ) (trans x poly 0)) plpts))
  241.         (foreach pt ptsints
  242.           (mapcar '(lambda ( x ) (if (equal pt x (/ len 40.0 (sqrt area))) (setq ptl (cons pt ptl)))) plpts)
  243.         )
  244.         (foreach pt ptl
  245.           (setq ptsints (vl-remove-if '(lambda ( x ) (equal x pt (/ len 16.0 (sqrt area)))) ptsints))
  246.         )
  247.         (setq ptl (acet-list-remove-duplicates ptl 1.0))
  248.         (setq ptsints (acet-list-remove-duplicates ptsints 1.0))
  249.         (if (>= (length ptl) 3)
  250.             (progn
  251.               (entdel ci)
  252.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_end" (trans (caddr ptl) 0 1))
  253.             )
  254.         )
  255.         (if (and (= (length ptl) 2) (= (length ptsints) 0))
  256.             (progn
  257.               (entdel ci)
  258.               (if (equal (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) (car ptl) (cadr ptl)) p 1e-4)
  259.                 (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1))
  260.                 (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getpointatparam poly (+ (min (vlax-curve-getparamatpoint poly (car ptl)) (vlax-curve-getparamatpoint poly (cadr ptl))) (/ (abs (- (vlax-curve-getparamatpoint poly (car ptl)) (vlax-curve-getparamatpoint poly (cadr ptl)))) 2.0))) 0 1))
  261.               )
  262.             )
  263.         )
  264.         (if (and (= (length ptl) 2) (= (length ptsints) 1))
  265.             (progn
  266.               (entdel ci)
  267.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_end" (trans (cadr ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  268.             )
  269.         )
  270.         (if (and (= (length ptl) 1) (= (length ptsints) 1))
  271.             (progn
  272.               (entdel ci)
  273.               (vl-cmdf "_.circle" "2P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1))
  274.             )
  275.         )
  276.         (if (and (= (length ptl) 1) (= (length ptsints) 2))
  277.             (progn
  278.               (entdel ci)
  279.               (vl-cmdf "_.circle" "3P" "_end" (trans (car ptl) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1))
  280.             )
  281.         )
  282.         (if (and (null ptl) (>= (length ptsints) 3))
  283.             (progn
  284.               (entdel ci)
  285.               (vl-cmdf "_.circle" "3P" "_tan" (trans (vlax-curve-getclosestpointto poly (car ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (cadr ptsints)) 0 1) "_tan" (trans (vlax-curve-getclosestpointto poly (caddr ptsints)) 0 1))
  286.             )
  287.         )
  288.         (if (and (null ptl) (= (length ptsints) 2))
  289.             (progn
  290.               (entdel ci)
  291.               (vl-cmdf "_.circle" (trans p poly 1) (trans (vlax-curve-getclosestpointto poly (trans p poly 0)) 0 1))
  292.             )
  293.         )
  294.         (command "_.ucs" "_P")
  295.         (setq ptl nil dist nil)
  296.       )
  297.       (command "_.ucs" "_P")
  298.     )
  299.   )
  300.   (*error* nil)
  301. )
  302.