Author Topic: Algorithm: 4 point boundary, the area is the smallest.  (Read 2014 times)

0 Members and 1 Guest are viewing this topic.

ssdd

  • Newt
  • Posts: 35
Algorithm: 4 point boundary, the area is the smallest.
« on: May 21, 2018, 09:27:57 AM »
Algorithm: 4 point boundary, the area is the smallest.

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: Algorithm: 4 point boundary, the area is the smallest.
« Reply #1 on: May 21, 2018, 12:43:08 PM »
Find minimum enclosing triangle by approximation points of reference curve :

Approximation points (I've modified Lee's sub) :
Code: [Select]
(defun c:curve2pts ( / MR:ent->pts c acc pts )

  (vl-load-com)

  ;; Entity to Point List  -  M.R.
  ;; Returns a list of points describing or approximating the supplied entity, else nil if the entity is not supported.
  ;; ent - [ent] Entity name to be described by point list (POINT/LINE/ARC/CIRCLE/LWPOLYLINE/POLYLINE/ELLIPSE/SPLINE)
  ;; acc - [num] Positive number determining the point density for non-linear objects

  (defun MR:ent->pts ( ent acc / der di1 di2 enx inc lst par fds fdm )
      (setq enx (entget ent))
      (cond
          (   (= "POINT" (cdr (assoc 0 enx)))
              (list (cdr (assoc 10 enx)))
          )
          (   (= "LINE" (cdr (assoc 0 enx)))
              (list (cdr (assoc 10 enx)) (cdr (assoc 11 enx)))
          )
          (   (wcmatch (cdr (assoc 0 enx)) "ARC,CIRCLE")
              (setq di1 0.0
                    di2 (vlax-curve-getdistatparam ent (vlax-curve-getendparam ent))
                    inc (/ di2 acc)
                    di2 (- di2 1e-8)
              )
              (while (< di1 di2)
                  (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                        di1 (+ di1 inc)
                  )
              )
              (reverse (if (vlax-curve-isclosed ent) lst (cons (vlax-curve-getendpoint ent) lst)))
          )
          (   (and (wcmatch (cdr (assoc 0 enx)) "*POLYLINE") (zerop (logand 80 (cdr (assoc 70 enx)))))
              (setq par 0)
              (repeat (fix (+ 1.0 1e-8 (vlax-curve-getendparam ent)))
                  (cond
                      (   (not (setq der (vlax-curve-getsecondderiv ent par))))
                      (   (equal der '(0.0 0.0 0.0) 1e-8)
                          (if (/= par (vlax-curve-getendparam ent))
                              (setq lst (cons (vlax-curve-getpointatparam ent par) lst))
                          )
                      )
                      (   (not (equal der '(0.0 0.0 0.0) 1e-8))
                          (if (/= par (vlax-curve-getendparam ent))
                              (progn
                                  (setq di1 (vlax-curve-getdistatparam ent par)
                                        di2 (vlax-curve-getdistatparam ent (1+ par))
                                  )
                                  (setq inc (/ (- di2 di1) acc)
                                        di2 (- di2 1e-8)
                                  )
                                  (while (< di1 di2)
                                      (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                                            di1 (+ di1 inc)
                                      )
                                  )
                              )
                          )
                      )
                  )
                  (setq par (1+ par))
              )
              (reverse (if (vlax-curve-isclosed ent) lst (cons (vlax-curve-getendpoint ent) lst)))
          )
          (   (= "ELLIPSE" (cdr (assoc 0 enx)))
              (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent))
                    di2 (vlax-curve-getdistatparam ent (vlax-curve-getendparam   ent))
                    inc (/ (- di2 di1) acc)
                    di2 (- di2 1e-8)
              )
              (while (< di1 di2)
                  (setq fds (cons (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))) fds)
                        di1 (+ di1 (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))))
                  )
              )
              (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent)))
              (setq fdm (apply 'max fds))
              (while (< di1 di2)
                  (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                        di1 (+ di1 (* (/ (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))) fdm) inc))
                  )
              )
              (reverse (if (vlax-curve-isclosed ent) lst (cons (vlax-curve-getendpoint ent) lst)))
          )
          (   (= "SPLINE" (cdr (assoc 0 enx)))
              (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent))
                    di2 (vlax-curve-getdistatparam ent (vlax-curve-getendparam   ent))
                    inc (/ (- di2 di1) acc)
                    di2 (- di2 1e-8)
              )
              (while (< di1 di2)
                  (setq fds (cons (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))) fds)
                        di1 (+ di1 (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))))
                  )
              )
              (setq di1 (vlax-curve-getdistatparam ent (vlax-curve-getstartparam ent)))
              (setq fdm (apply 'max fds))
              (while (< di1 di2)
                  (setq lst (cons (vlax-curve-getpointatdist ent di1) lst)
                        di1 (+ di1 (* (/ (distance '(0.0 0.0 0.0) (vlax-curve-getfirstderiv ent (vlax-curve-getparamatdist ent di1))) fdm) inc))
                  )
              )
              (reverse (if (vlax-curve-isclosed ent) lst (cons (vlax-curve-getendpoint ent) lst)))
          )
      )
  )

  (while (or (not (setq c (car (entsel "\nPick curve entity...")))) (if c (vl-catch-all-error-p (vl-catch-all-apply 'vlax-curve-getstartpoint (list c)))))
    (prompt "\nMissed or picked wrong entity type...")
  )
  (initget 6)
  (setq acc (getreal "\nSpecify number of point density <35> : "))
  (if (null acc)
    (setq acc 35.0)
  )
  (setq pts (MR:ent->pts c acc))
  (foreach p pts
    (entmake (list '(0 . "POINT") (cons 10 p)))
  )
  (princ)
)

Minimum and maximum enclosing triangle - convex hull :
http://www.theswamp.org/index.php?topic=50176.msg553387#msg553387

When you find smallest triangle, cut the biggest apex area sub triangle with convex hull edge so the final result is 4 pt shape with smallest area...
« Last Edit: May 22, 2018, 11:00:33 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: Algorithm: 4 point boundary, the area is the smallest.
« Reply #2 on: May 22, 2018, 09:15:23 AM »
This mod of my posted link worked for me... Very limited testings...

Code - Auto/Visual Lisp: [Select]
  1. (defun c:minencquadpol-rndpts ( / *error* car-sort unit mid LM:ConvexHull LM:Clockwise-p MR:triangarea ac ti pdm pds f ss i p pl lil pp1 pp2 pp3 ar trl ll ur qual pp11 pp12 pp21 pp22 pp31 pp32 pp4 tr qua )
  2.  
  3.  
  4.   (defun *error* ( msg )
  5.     (if f (vl-cmdf "_.UCS" "_P"))
  6.     (if pdm (setvar 'pdmode pdm))
  7.     (if pds (setvar 'pdsize pds))
  8.     (if msg (prompt msg))
  9.     (princ)
  10.   )
  11.  
  12.   (defun car-sort ( l f / removenth r k )
  13.  
  14.     (defun removenth ( l n / k )
  15.       (setq k -1)
  16.       (vl-remove-if '(lambda ( x ) (= (setq k (1+ k)) n)) l)
  17.     )
  18.  
  19.     (setq k -1)
  20.     (vl-some '(lambda ( a ) (setq k (1+ k)) (if (vl-every '(lambda ( x ) (apply f (list a x))) (removenth l k)) (setq r a))) l)
  21.     r
  22.   )
  23.  
  24.   (defun unit ( v / d )
  25.     (if (not (equal (setq d (distance '(0.0 0.0 0.0) v)) 0.0 1e-8))
  26.       (mapcar '(lambda ( x ) (/ x d)) v)
  27.     )
  28.   )
  29.  
  30.   (defun mid ( p1 p2 )
  31.     (mapcar '(lambda ( a b ) (/ (+ a b) 2.0)) p1 p2)
  32.   )
  33.  
  34.   ;; Convex Hull  -  Lee Mac
  35.   ;; Implements the Graham Scan Algorithm to return the Convex Hull of a list of points.
  36.  
  37.   (defun LM:ConvexHull ( lst / ch p0 )
  38.       (cond
  39.           (   (< (length lst) 4) lst)
  40.           (   (setq p0 (car lst))
  41.               (foreach p1 (cdr lst)
  42.                   (if (or (< (cadr p1) (cadr p0))
  43.                           (and (= (cadr p1) (cadr p0)) (< (car p1) (car p0)))
  44.                       )
  45.                       (setq p0 p1)
  46.                   )
  47.               )
  48.               (setq lst (vl-remove p0 lst))
  49.               (setq lst (append (list p0) lst))
  50.               (setq lst
  51.                   (vl-sort lst
  52.                       (function
  53.                           (lambda ( a b / c d )
  54.                               (if (or (equal (setq c (angle p0 a)) (setq d (angle p0 b)) 1e-8) (and (or (equal c 0.0 1e-8) (equal c (* 2 pi) 1e-8)) (or (equal d 0.0 1e-8) (equal d (* 2 pi) 1e-8))))
  55.                                   (< (distance (list (car p0) (cadr p0)) a) (distance (list (car p0) (cadr p0)) b))
  56.                                   (< c d)
  57.                               )
  58.                           )
  59.                       )
  60.                   )
  61.               )
  62.               (setq ch (list (cadr lst) (car lst)))
  63.               (foreach pt (cddr lst)
  64.                   (setq ch (cons pt ch))
  65.                   (while (and (caddr ch) (LM:Clockwise-p (caddr ch) (cadr ch) pt))
  66.                       (setq ch (cons pt (cddr ch)))
  67.                   )
  68.               )
  69.               (reverse ch)
  70.           )
  71.       )
  72.   )
  73.  
  74.   ;; Clockwise-p  -  Lee Mac
  75.   ;; Returns T if p1,p2,p3 are clockwise oriented or collinear
  76.  
  77.   (defun LM:Clockwise-p ( p1 p2 p3 )
  78.       (<  (-  (* (- (car  p2) (car  p1)) (- (cadr p3) (cadr p1)))
  79.               (* (- (cadr p2) (cadr p1)) (- (car  p3) (car  p1)))
  80.           )
  81.           1e-8
  82.       )
  83.   )
  84.  
  85.   ;; triangarea - Marko R.
  86.   ;; Returns area of triangle defined with p1,p2,p3 in 3d space
  87.  
  88.   (defun MR:triangarea ( p1 p2 p3 / v12 v13 v1 v21 v23 v2 c cz r ar )
  89.     (setq v12 (unit (mapcar '- p2 p1)))
  90.     (setq v13 (unit (mapcar '- p3 p1)))
  91.     (setq v1 (unit (mid v12 v13)))
  92.     (setq v21 (mapcar '- v12))
  93.     (setq v23 (unit (mapcar '- p3 p2)))
  94.     (setq v2 (unit (mid v21 v23)))
  95.     (setq c (inters p1 (mapcar '+ p1 v1) p2 (mapcar '+ p2 v2) nil))
  96.     (setq cz (trans c 0 v12))
  97.     (setq r (distance (mapcar '+ '(0.0 0.0) (trans p1 0 v12)) cz))
  98.     (setq ar (* r 0.5 (+ (distance p1 p2) (distance p2 p3) (distance p3 p1))))
  99.     ar
  100.   )
  101.  
  102.   (setq pdm (getvar 'pdmode))
  103.   (setvar 'pdmode 0)
  104.   (setq pds (getvar 'pdsize))
  105.   (setvar 'pdsize -1.5)
  106.   (if (eq (getvar 'worlducs) 0)
  107.     (progn
  108.       (vl-cmdf "_.UCS" "_W")
  109.       (setq f t)
  110.     )
  111.   )
  112.   (prompt "\nSelect RND more than 3 points in WCS plane...")
  113.   (while (or (not (setq ss (ssget '((0 . "POINT"))))) (not (and (equal (caddr (car (acet-geom-ss-extents-accurate ss))) 0.0 1e-6) (equal (caddr (cadr (acet-geom-ss-extents-accurate ss))) 0.0 1e-6))) (and ss (< (sslength ss) 3)))
  114.     (prompt "\nEmpty sel. set or some of selected points don't lie in WCS plane or selected less than 3 points... Please select RND points in WCS plane again...")
  115.   )
  116.   (setq ti (car (_vl-times)))
  117.   (repeat (setq i (sslength ss))
  118.     (setq p (cdr (assoc 10 (entget (ssname ss (setq i (1- i)))))))
  119.     (setq pl (cons p pl))
  120.   )
  121.   (setq pl (LM:ConvexHull pl))
  122.   (setq lil (mapcar '(lambda ( p1 p2 ) (list p1 p2)) pl (cdr (reverse (cons (car pl) (reverse pl))))))
  123.   (if (> (length pl) 3)
  124.     (foreach l1 lil
  125.       (foreach l2 (vl-remove l1 lil)
  126.         (foreach l3 (vl-remove l2 (vl-remove l1 lil))
  127.           (setq pp1 (inters (car l1) (cadr l1) (car l2) (cadr l2) nil))
  128.           (setq pp2 (inters (car l2) (cadr l2) (car l3) (cadr l3) nil))
  129.           (setq pp3 (inters (car l3) (cadr l3) (car l1) (cadr l1) nil))
  130.           (if (and pp1 pp2 pp3)
  131.             (progn
  132.               (setq ll (list (apply 'min (mapcar 'car (list pp1 pp2 pp3))) (apply 'min (mapcar 'cadr (list pp1 pp2 pp3)))))
  133.               (setq ur (list (apply 'max (mapcar 'car (list pp1 pp2 pp3))) (apply 'max (mapcar 'cadr (list pp1 pp2 pp3)))))
  134.               (setq ar (MR:triangarea pp1 pp2 pp3))
  135.               (vla-zoomwindow ac (vlax-3d-point ll) (vlax-3d-point ur))
  136.               (if (and (ssget "_CP" (list pp1 pp2 pp3) '((0 . "POINT"))) (eq (sslength ss) (sslength (ssget "_CP" (list pp1 pp2 pp3) '((0 . "POINT"))))))
  137.                 (setq trl (cons (list ar pp1 pp2 pp3) trl))
  138.               )
  139.             )
  140.           )
  141.         )
  142.       )
  143.     )
  144.     (progn
  145.       (setq pp1 (car pl) pp2 (cadr pl) pp3 (caddr pl))
  146.       (setq trl (cons (list (MR:triangarea pp1 pp2 pp3) pp1 pp2 pp3) trl))
  147.     )
  148.   )
  149.   (if (> (length trl) 1)
  150.     (setq tr (car-sort trl '(lambda ( a b ) (<= (car a) (car b)))))
  151.     (setq tr (car trl))
  152.   )
  153.   (setq pp1 (cadr tr) pp2 (caddr tr) pp3 (cadddr tr))
  154.   (foreach li lil
  155.     (if (and (setq pp11 (inters (car li) (cadr li) pp1 pp2 nil)) (setq pp12 (inters (car li) (cadr li) pp1 pp3 nil)) (not (equal pp11 pp12 1e-8)) (not (equal pp11 pp2 1e-8)) (not (equal pp11 pp3 1e-8)) (not (equal pp12 pp2 1e-8)) (not (equal pp12 pp3 1e-8)))
  156.       (progn
  157.         (setq ll (list (apply 'min (mapcar 'car (list pp11 pp2 pp3 pp12))) (apply 'min (mapcar 'cadr (list pp11 pp2 pp3 pp12)))))
  158.         (setq ur (list (apply 'max (mapcar 'car (list pp11 pp2 pp3 pp12))) (apply 'max (mapcar 'cadr (list pp11 pp2 pp3 pp12)))))
  159.         (vla-zoomwindow ac (vlax-3d-point ll) (vlax-3d-point ur))
  160.         (if (and (ssget "_CP" (list pp11 pp2 pp3 pp12) '((0 . "POINT"))) (eq (sslength ss) (sslength (ssget "_CP" (list pp11 pp2 pp3 pp12) '((0 . "POINT"))))))
  161.           (setq qual (cons (list (+ (MR:triangarea pp11 pp2 pp3) (MR:triangarea pp3 pp11 pp12)) pp11 pp2 pp3 pp12) qual))
  162.         )
  163.       )
  164.     )
  165.     (if (and (setq pp31 (inters (car li) (cadr li) pp2 pp3 nil)) (setq pp32 (inters (car li) (cadr li) pp1 pp3 nil)) (not (equal pp31 pp32 1e-8)) (not (equal pp31 pp2 1e-8)) (not (equal pp31 pp1 1e-8)) (not (equal pp32 pp2 1e-8)) (not (equal pp32 pp1 1e-8)))
  166.       (progn
  167.         (setq ll (list (apply 'min (mapcar 'car (list pp1 pp2 pp31 pp32))) (apply 'min (mapcar 'cadr (list pp1 pp2 pp31 pp32)))))
  168.         (setq ur (list (apply 'max (mapcar 'car (list pp1 pp2 pp31 pp32))) (apply 'max (mapcar 'cadr (list pp1 pp2 pp31 pp32)))))
  169.         (vla-zoomwindow ac (vlax-3d-point ll) (vlax-3d-point ur))
  170.         (if (and (ssget "_CP" (list pp1 pp2 pp31 pp32) '((0 . "POINT"))) (eq (sslength ss) (sslength (ssget "_CP" (list pp1 pp2 pp31 pp32) '((0 . "POINT"))))))
  171.           (setq qual (cons (list (+ (MR:triangarea pp1 pp2 pp31) (MR:triangarea pp1 pp31 pp32)) pp1 pp2 pp31 pp32) qual))
  172.         )
  173.       )
  174.     )
  175.     (if (and (setq pp21 (inters (car li) (cadr li) pp1 pp2 nil)) (setq pp22 (inters (car li) (cadr li) pp2 pp3 nil)) (not (equal pp21 pp22 1e-8)) (not (equal pp21 pp1 1e-8)) (not (equal pp21 pp3 1e-8)) (not (equal pp22 pp1 1e-8)) (not (equal pp22 pp3 1e-8)))
  176.       (progn
  177.         (setq ll (list (apply 'min (mapcar 'car (list pp1 pp21 pp22 pp3))) (apply 'min (mapcar 'cadr (list pp1 pp21 pp22 pp3)))))
  178.         (setq ur (list (apply 'max (mapcar 'car (list pp1 pp21 pp22 pp3))) (apply 'max (mapcar 'cadr (list pp1 pp21 pp22 pp3)))))
  179.         (vla-zoomwindow ac (vlax-3d-point ll) (vlax-3d-point ur))
  180.         (if (and (ssget "_CP" (list pp1 pp21 pp22 pp3) '((0 . "POINT"))) (eq (sslength ss) (sslength (ssget "_CP" (list pp1 pp21 pp22 pp3) '((0 . "POINT"))))))
  181.           (setq qual (cons (list (+ (MR:triangarea pp1 pp21 pp22) (MR:triangarea pp1 pp22 pp3)) pp1 pp21 pp22 pp3) qual))
  182.         )
  183.       )
  184.     )
  185.   )
  186.   (if (> (length qual) 1)
  187.     (setq qua (car-sort qual '(lambda ( a b ) (<= (car a) (car b)))))
  188.     (setq qua (car qual))
  189.   )
  190.   (setq pp1 (nth 1 qua) pp2 (nth 2 qua) pp3 (nth 3 qua) pp4 (nth 4 qua))
  191.     (list
  192.       '(0 . "LWPOLYLINE")
  193.       '(100 . "AcDbEntity")
  194.       '(100 . "AcDbPolyline")
  195.       '(90 . 4)
  196.       (cons 70 (if (eq 1 (getvar 'plinegen)) 129 1))
  197.       '(62 . 3)
  198.       '(38 . 0.0)
  199.       (cons 10 pp1)
  200.       (cons 10 pp2)
  201.       (cons 10 pp3)
  202.       (cons 10 pp4)
  203.       '(210 0.0 0.0 1.0)
  204.     )
  205.   )
  206.   (prompt (strcat "\nArea of quad is : " (rtos (caar qual) 2 50)))
  207.   (prompt (strcat "\nElapsed time : " (rtos (/ (- (car (_vl-times)) ti) 1000.0) 2 50) " seconds..."))
  208.   (vl-cmdf "_.ZOOM" "_OB" (entlast) "")
  209.   (*error* nil)
  210. )
  211.  

HTH., M.R.
« Last Edit: June 19, 2019, 12:50:34 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ssdd

  • Newt
  • Posts: 35
Re: Algorithm: 4 point boundary, the area is the smallest.
« Reply #3 on: May 28, 2018, 12:08:47 PM »
Thanks Ribarm