Author Topic: -={Challenge}=- Math: Area, Scale, Points  (Read 2587 times)

0 Members and 1 Guest are viewing this topic.

Grrr1337

  • Swamp Rat
  • Posts: 812
-={Challenge}=- Math: Area, Scale, Points
« on: January 30, 2021, 12:50:02 PM »
Hey guys,
Haven't been posting for a while, hopefully you're doin alright in 2021.  :thinking:

Given a point list (closed one) -
 
Code: [Select]
((19.1947 9.72373) (24.7985 9.19778) (28.0063 11.2198) (30.008 9.06602) (30.4813 4.20126)
  (26.3245 6.77841) (23.8251 2.83379) (21.0363 4.8061) (17.2611 5.1875) (14.3538 10.5915)) ; example given list

which could be represend by a closed LWpolyline with straight segments
(although we don't actually have any ACAD geometry to work with, but rather whatever closed shape).

The questions are:

• How we could get the area via math?
Code: [Select]
(getPointListArea <PointList>); returns the area
• On a given base-point / say the shape's centroid or points-bbox centroid or '(0 0 0) / whatever-point
  and on a given area as an input,
  How we could translate these points in order to match the original shape and the desired area? (math)
  /sounds like offset, but its actually scale/
Code: [Select]
(SetPointListArea <PointList> <BasePoint> <DesiredArea>); returns the translated PointList coordinates
Like imagine this LWpolyline with the certain area, where its scaled by reference by its area so it results for instance 10% larger or smaller.
But like I said we don't deal with such, its just math. (although for testing result purposes its allowed to entmake a lwpoly)

BTW I don't expect much answers so I consider it as a challenge.
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #1 on: January 30, 2021, 04:29:54 PM »
Hi,

I do not have so much time to play, but here's a way to solve the first task.

Code - Auto/Visual Lisp: [Select]
  1. ;; triangleArea
  2. ;; Returns the algebraic (signed) area of the triangle defined by three 2d points
  3. ;; the area is negative if points are clockwise
  4. (defun triangleArea (p1 p2 p3)
  5.   (/ (- (* (- (car p2) (car p1))
  6.            (- (cadr p3) (cadr p1))
  7.         )
  8.         (* (- (car p3) (car p1))
  9.            (- (cadr p2) (cadr p1))
  10.         )
  11.      )
  12.      2.0
  13.   )
  14. )
  15.  
  16. ;; polygonArea
  17. ;; Returns the algebraic (signed) area of the polygon defined by a list of points
  18. ;; the area is negative if points are clockwise
  19. (defun polygonArea (pts / loop)
  20.   (defun loop (pt area pts)
  21.     (if (cdr pts)
  22.       (loop pt (+ area (triangleArea pt (car pts) (cadr pts))) (cdr pts))
  23.       area
  24.     )
  25.   )
  26.   (loop (car pts) 0 (cdr pts))
  27. )

(defun getPointListArea (pointList) (abs polygonArea))
« Last Edit: January 30, 2021, 04:40:03 PM by gile »
Speaking English as a French Frog

BIGAL

  • Swamp Rat
  • Posts: 1417
  • 40 + years of using Autocad
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #2 on: January 30, 2021, 06:49:57 PM »
There is a mathematical formula for the area of points, using just points.

Maybe https://www.mathopenref.com/coordpolygonarea.html
A man who never made a mistake never made anything

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #3 on: January 30, 2021, 08:54:01 PM »
Code: [Select]
(defun vk_GetSignedArea (CoordsList)
  (/ (apply '+
    (mapcar (function (lambda (p1 p2) (* (+ (car p1) (car p2)) (- (cadr p1) (cadr p2)))))
    CoordsList
    (cons (last CoordsList) CoordsList)
    )
     )
     2.0
  )
)
(defun vk_GetArea (CoordsList) (abs (vk_GetSignedArea CoordsList)))
(defun vk_ScaleCoordsList (lst p0 s)
  (mapcar (function (lambda (p) (polar p0 (angle p0 p) (* (distance p0 p) s)))) lst)
)
(defun vk_ScaleCoordsListArea (lst p0 a /)
  (vk_ScaleCoordsList lst p0 (sqrt (/ a (vk_GetArea lst))))
)

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #4 on: January 31, 2021, 04:34:12 AM »
Hi,

I do not have so much time to play, but here's a way to solve the first task.

Code - Auto/Visual Lisp: [Select]
  1. ;; triangleArea
  2.  
  3. ;; polygonArea
  4.  


Hi, Gile
I remember such function existed somewhere on the internet, but forgot who the author was.
As a math dummy I'm impressed of your solution..

Back at the time when I was attending geodesy class in my university, we were taught of finding the area of any shape via floodfill algorithm:
• define MxN square-grid ontop of the shape,
• sum the area of all the squares inside the shape
• the squares which are intersecting the boundary of
  the shape were forming trapezoid or triangle region from the inner side, so their total area is added-up aswell

But I think that your approach is faster and more accurate.


There is a mathematical formula for the area of points, using just points.

Maybe https://www.mathopenref.com/coordpolygonarea.html

Thanks BIGAL,
trouble is that I suck at translating math algorithms as program languages,
and I've used my first question to be the base for my second one - which is the real challenge.


Code: [Select]
(defun vk_GetSignedArea (CoordsList)
  ; ...
)
(defun vk_GetArea (CoordsList)
  ; ...
)
(defun vk_ScaleCoordsList (lst p0 s)
  ; ...
)
(defun vk_ScaleCoordsListArea (lst p0 a /)
  ; ...
)

Holy s... VovKa,
You've won the challenge!

Performed a basic testing by incrementing an area, and checking if the pointlist's centroid is retained -
Everything works correctly.  :-)

Code - Auto/Visual Lisp: [Select]
  1. (test) ; test function
  2. ;| sample print-return (which is correct):
  3. (181.798 95.1695) 15179.3 15179.3)
  4. (181.798 95.1695) 15679.3 15679.3)
  5. (181.798 95.1695) 16179.3 16179.3)
  6. (181.798 95.1695) 16679.3 16679.3)
  7. (181.798 95.1695) 17179.3 17179.3)
  8. |;
  9. (defun test ( / pL pc ar i e npL )
  10.   (setq pL (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget (car (entsel "\nPick a LWpoly:"))))))
  11.   (setq pc (PolyCentroid pL))
  12.   (setq ar (vk_GetArea pL))
  13.   (setq i 500) ; area increment
  14.   (repeat 5
  15.       (setq e (LWPoly (setq npL (vk_ScaleCoordsListArea pL pc (setq ar (+ ar i)))) 1))
  16.     )
  17.     (print (list (PolyCentroid npL) (vk_GetArea npL) (vlax-curve-getArea e))) ; check that the base-point is retained and the area matches
  18.   )
  19. ); defun
  20.  
  21.  
  22. (defun LWPoly (lst cls)
  23.     (append
  24.       (list
  25.         (cons 0 "LWPOLYLINE")
  26.         (cons 100 "AcDbEntity")
  27.         (cons 100 "AcDbPolyline")
  28.         (cons 90 (length lst))
  29.         (cons 70 cls)
  30.       )
  31.       (mapcar (function (lambda (p) (cons 10 p))) lst)
  32.     )
  33.   )
  34. )
  35.  
  36.  
  37. (defun PolyCentroid ( l ) ; Lee Mac (modified it a bit)
  38.  
  39.   (
  40.     (lambda ( a )
  41.       (if (not (equal 0.0 a 1e-8))
  42.        
  43.         (mapcar '/
  44.           (apply 'mapcar
  45.             (cons '+
  46.               (mapcar
  47.                 (function
  48.                   (lambda ( a b )
  49.                     (
  50.                       (lambda ( m )
  51.                         (mapcar
  52.                           (function
  53.                             (lambda ( c d ) (* (+ c d) m))
  54.                           )
  55.                           a b
  56.                         )
  57.                       )
  58.                       (- (* (car a) (cadr b)) (* (car b) (cadr a)))
  59.                     )
  60.                   )
  61.                 )
  62.                 l (cons (last l) l)
  63.               )
  64.             )
  65.           )
  66.           (list a a)
  67.         )
  68.        
  69.       )
  70.     )
  71.     (* 3.0
  72.       (apply '+
  73.         (mapcar
  74.           (function
  75.             (lambda ( a b )
  76.               (- (* (car a) (cadr b)) (* (car b) (cadr a)))
  77.             )
  78.           )
  79.           l (cons (last l) l)
  80.         )
  81.       )
  82.     )
  83.   )
  84. )




(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #5 on: January 31, 2021, 04:18:13 PM »
You've won the challenge!
being the only participant is cool :)

Grrr1337

  • Swamp Rat
  • Posts: 812
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #6 on: January 31, 2021, 05:16:10 PM »
You've won the challenge!
being the only participant is cool :)

I'm not used to post challenges quite often, but isn't the criteria for a winner to be:
• first one who did it
• no flaws in the returns/algorithm
• don't think that your subs can be shortened or simplified more than that

Still this thread is open for alternative solutions or suggestions, like I know that LM is able to scale a point list using matrix transformations -
Code: [Select]
(LM:ScaleByMatrix (Vertices e) (trans p 1 0) s) (cdr (assoc 70 (entget e)))
 :wink:
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)
vevo.bg

BIGAL

  • Swamp Rat
  • Posts: 1417
  • 40 + years of using Autocad
Re: -={Challenge}=- Math: Area, Scale, Points
« Reply #7 on: January 31, 2021, 06:27:25 PM »
Challenge accepted. Compare pline area from properties.

Code: [Select]
; https://www.mathopenref.com/coordpolygonarea.html

; (x1y2-y1x2)+(x2y3-x3y2)+...all / 2

(defun c:parea ( / ent x lst)
(setq ent (entsel "\npick pline "))

(setq lst (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget (car ent)))))
(setq lst (reverse lst))
(setq lst (cons (last lst) lst))

(setq x 0 tot 0.0)

(repeat (- (length lst) 1)
  (setq xy (- (* (car (nth x lst))(cadr (nth (+ x 1) lst))) (* (car (nth (+ x 1) lst))(cadr (nth x lst)))))
  (setq tot (+ tot xy))
  (setq x (+ x 1))
)

(setq tot (abs (/ tot 2.0)))

(alert (strcat "Area is " (rtos tot 2 3)))

(princ)
)
A man who never made a mistake never made anything