Author Topic: How can I know if the shapes are the same?  (Read 9053 times)

0 Members and 1 Guest are viewing this topic.

litss

  • Guest
How can I know if the shapes are the same?
« on: February 16, 2009, 09:08:13 AM »
I wish I could find a way to group shapes(closed pline) that are the same. But it is hard for me. Any one have a good idea? Thx!

Attached is a fig. If I select all the shapes by "ssget", I want a way to find out the "1" and "2", which are the same shapes.



CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How can I know if the shapes are the same?
« Reply #1 on: February 16, 2009, 10:13:57 AM »
There are lots of common items that can be compared but absolute conformation may be complex.

This is what I would check.
Both are LWPolylines
Both are closed or open
They have the same length & area
They have the same number of segments
May not need this one but check that the segment lengths are the same

That should be a good test.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #2 on: February 16, 2009, 10:29:34 AM »
There are lots of common items that can be compared but absolute conformation may be complex.

This is what I would check.
Both are LWPolylines
Both are closed or open
They have the same length & area
They have the same number of segments
May not need this one but check that the segment lengths are the same

That should be a good test.

That's scary...this is what I was starting to write. :-D

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How can I know if the shapes are the same?
« Reply #3 on: February 16, 2009, 10:59:42 AM »
You are just being LOGICAL.  :lmao:
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

litss

  • Guest
Re: How can I know if the shapes are the same?
« Reply #4 on: February 16, 2009, 11:15:59 AM »
Quote
Both are LWPolylines
Both are closed or open
They have the same length & area
They have the same number of segments
May not need this one but check that the segment lengths are the same

It's for sure: Both are LWPolylines & Both are closed
And I can do comparison of length & area. But it's not enough. There are hundreds of plines in my draft, length & area are all close to each other.
:( the problem is how to check each segment length? starting from which leg of the plines?  it might be a huge comparison. quite hard for me...

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How can I know if the shapes are the same?
« Reply #5 on: February 16, 2009, 11:51:22 AM »
Look into these functions. They will get you what you need.
Code: [Select]
(vlax-curve-getarea curve-obj)
(vlax-curve-getclosestpointto curve-obj givenPnt [extend])
(vlax-curve-getclosestpointtoprojection curve-obj givenPnt normal [extend])
(vlax-curve-getdistatparam curve-obj param)
(vlax-curve-getdistatpoint curve-obj point)
(vlax-curve-getendparam curve-obj)
(vlax-curve-getendpoint curve-obj)
(vlax-curve-getfirstderiv curve-obj param)
(vlax-curve-getparamatdist curve-obj dist)
(vlax-curve-getparamatpoint curve-obj point)
(vlax-curve-getpointatdist curve-obj dist)
(vlax-curve-getpointatparam curve-obj param)
(vlax-curve-getsecondderiv curve-obj param)
(vlax-curve-getstartparam curve-obj)
(vlax-curve-getstartpoint curve-obj)
(vlax-curve-isClosed ent) ; true if Closed
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Spike Wilbury

  • Guest

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: How can I know if the shapes are the same?
« Reply #7 on: February 16, 2009, 04:56:39 PM »
That is a very good link. Thanks 8-)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Spike Wilbury

  • Guest
Re: How can I know if the shapes are the same?
« Reply #8 on: February 16, 2009, 05:09:24 PM »
That is a very good link. Thanks 8-)

Yes... Alan,

That's one of my old url kept for quite a while.... :)




ps> using a default name - me

SomeCallMeDave

  • Guest
Re: How can I know if the shapes are the same?
« Reply #9 on: February 16, 2009, 05:15:05 PM »
I haven't done a rigorous proof (have done no proof at all really), but it would seem to me that the sum of the distances from the centroid to each vertex would be a unique value for each shape and would be independent of the rotation of the shape.

And it would be a quick calculation:
  for each shape:
          calc the centroid
          build a vertex list (just an (assoc 10) list since the OP said all shapes are LwPoly)
          then sum the distances ->     (apply '+ (mapcar '(lambda (x) (distance x centroid)) vertlist))

Build a list containing each value, find the matches, use the index of the list to pull the entities from the selection set.

Almost writes itself  :)


         
         

ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #10 on: February 16, 2009, 05:33:53 PM »
Give this a try....seems to work OK for me  :-)  **will not work if you reverse the vertexes  fixed.

Code: [Select]
(defun c:similar_polylines (/ d lst n n2 obj out ss)
  (setq n -1)
  (if (setq ss (ssget '((0 . "LWPOLYLINE"))))
    (progn (repeat (sslength ss)
             (setq obj (vlax-ename->vla-object (ssname ss (setq n (1+ n))))
                   n2  0.0
                   d   nil
             )
             ;;get distances between vertexes  **accuracy is 5 decimal places
             (repeat (fix (vlax-curve-getendparam obj))
               (setq d (cons (rtos (distance (vlax-curve-getpointatparam obj n2)
                                             (vlax-curve-getpointatparam obj (setq n2 (1+ n2)))
                                   )
                                   2
                                   5
                             )
                             d
                       )
               )
             )
             ;;put all the information into the list to check
             (setq lst (cons (list obj
                                   (rtos (vla-get-area obj) 2 5)
                                   (vla-get-closed obj)
                                   (rtos (vla-get-length obj) 2 5)
                                   (vlax-curve-getendparam obj)
                                   (vl-sort d '>)
                             )
                             lst
                       )
             )
           )
           ;;iterate the list checking for more than one occurence of the first element properties
           (foreach pl lst
             (if (> (length (vl-remove-if-not '(lambda (x) (equal x (cdr pl)))
                                              (mapcar 'cdr lst)
                            )
                    )
                    1
                 )
               (setq out (cons (car pl) out))
             )
           )
    )
  )
  ;;(foreach x out (vla-put-color x 3))
  ;;quick check
  out
)
(c:similar_polylines)


« Last Edit: February 16, 2009, 06:17:57 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

litss

  • Guest
Re: How can I know if the shapes are the same?
« Reply #11 on: February 17, 2009, 01:48:38 AM »
Thx all of u guys! helped me a lot..

to:  David Blackmon
I like ur way "the sum of the distances from the centroid". I'll try it tonight :)

to: ronjonp
ur routine runs perfectly. And I made some modification so that it could group each kind of shapes as a list. Hope you don't mind. I am poor at programing, so it might not look as clean as urs :). here's it:

Code: [Select]
(defun c:similar_polylines (/ d lst n n2 obj out ss)
  (setq n -1)
  (if (setq ss (ssget '((0 . "LWPOLYLINE"))))
    (progn
      (repeat (sslength ss)
        (setq obj (vlax-ename->vla-object (ssname ss (setq n (1+ n))))
              n2 0.0
              d nil
        )             ;;get distances between vertexes  **accuracy is 5 decimal places
        (repeat (fix (vlax-curve-getendparam obj))
          (setq d (cons (rtos (distance (vlax-curve-getpointatparam obj n2)
                                        (vlax-curve-getpointatparam obj (setq n2 (1+ n2)))
                              ) 2 5
                        ) d
                  )
          )
        )             ;;put all the information into the list to check
        (setq lst (cons (list obj (rtos (vla-get-area obj) 2 5) (vla-get-closed obj) (rtos
                                                                                           (vla-get-length obj)
                                                                                           2 5
                                                                                     )
                              (vlax-curve-getendparam obj) (vl-sort d '>)
                        ) lst
                  )
        )
      )           ;;iterate the list checking for more than one occurence of the first element properties
   ;;;------------------modified------------------------------------------------
      (setq out '())
      (while (> (length lst) 0)
        (setq pl (car lst))
        (setq lst0 (vl-remove-if-not '(lambda (x)
                                        (equal (cdr x) (cdr pl))
                                      ) lst
                   )
        )
        (setq out (cons lst0 out))
        (setq n 0)
        (repeat (length lst0)
          (setq pl (nth n lst0))
          (setq lst (vl-remove-if '(lambda (x)
                                     (equal (cdr x) (cdr pl))
                                   ) lst
                    )
          )
          (setq n (1+ n))
        );repeat
      );while
    )
  )
  (setq n 3)
  (foreach x out
    (setq n (1+ n))
    (foreach y x
      (vla-put-color (car y) n)
    )
  )  ;;quick check
  ;;;------------------modified------------------------------------------------
)
(c:similar_polylines)

ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #12 on: February 17, 2009, 10:18:12 AM »
Glad it worked for you :)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #13 on: February 17, 2009, 10:41:11 AM »
Here is how I would group the objects as sublists.
Code: [Select]
(defun c:similar_polylines (/ d lst n n2 obj out ss sub)
  (setq n -1)
  (if (setq ss (ssget '((0 . "LWPOLYLINE"))))
    (progn (repeat (sslength ss)
             (setq obj (vlax-ename->vla-object (ssname ss (setq n (1+ n))))
                   n2  0.0
                   d   nil
             )
             ;;get distances between vertexes  **accuracy is 5 decimal places
             (repeat (fix (vlax-curve-getendparam obj))
               (setq
                 d (cons (rtos (distance (vlax-curve-getpointatparam obj n2)
                                         (vlax-curve-getpointatparam obj (setq n2 (1+ n2)))
                               )
                               2
                               5
                         )
                         d
                   )
               )
             )
             ;;put all the information into the list to check
             (setq lst (cons (list obj
                                   (rtos (vla-get-area obj) 2 5)
                                   (vla-get-closed obj)
                                   (rtos (vla-get-length obj) 2 5)
                                   (vlax-curve-getendparam obj)
                                   (vl-sort d '>)
                             )
                             lst
                       )
             )
           )
           ;;iterate the list checking for more than one occurence of the first element properties
           (foreach pl lst
             (if (> (length
                      (setq sub (vl-remove-if-not '(lambda (x) (equal (cdr x) (cdr pl)))
                                                  lst
                                )
                      )
                    )
                    1
                 )
               (progn (setq out (cons (mapcar 'car sub) out))
                      (setq lst (vl-remove-if '(lambda (x) (member x sub)) lst))
               )
             )
           )
    )
  )
  (setq n 0)
  (foreach pl out
    (setq n (1+ n))
    (mapcar '(lambda (x) (vla-put-color x n)) pl)
  )
  out
)
(c:similar_polylines)

Here is one using David's centroid\vertex distance method...same results as the one above  :-)

Code: [Select]
(defun c:similar_polylines (/ e lst m n out pts ss sub sum x)
  (setq n -1)
  (if (setq ss (ssget '((0 . "LWPOLYLINE"))))
    (progn (repeat (sslength ss)
             (setq e (ssname ss (setq n (1+ n))))
             (setq pts (mapcar 'cdr
                               (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget e))
                       )
                   m   (list (/ (apply '+ (mapcar 'car pts)) (length pts))
                             (/ (apply '+ (mapcar 'cadr pts)) (length pts))
                       )
                   ;;same 5 decimal precision
                   sum (apply '+
                              (mapcar 'atof
                                      (mapcar '(lambda (x) (rtos (distance m x) 2 5)) pts)
                              )
                       )
                   lst (cons (list e sum) lst)
             )
           )
           (foreach pl lst
             (if (> (length
                      (setq sub (vl-remove-if-not '(lambda (x) (equal (cdr x) (cdr pl)))
                                                  lst
                                )
                      )
                    )
                    1
                 )
               (progn (setq out (cons (mapcar 'car sub) out))
                      (setq lst (vl-remove-if '(lambda (x) (member x sub)) lst))
               )
             )
           )
    )
  )
  (setq n 0)
  (foreach pl out
    (setq n (1+ n))
    (mapcar '(lambda (x) (vla-put-color (vlax-ename->vla-object x) n))
            pl
    )
  )
  out
)
(c:similar_polylines)
« Last Edit: February 17, 2009, 11:44:52 AM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

SomeCallMeDave

  • Guest
Re: How can I know if the shapes are the same?
« Reply #14 on: February 17, 2009, 01:51:11 PM »
Very nice Ron.

I like your method of calculating the centroid.  Much more concise than mine.

ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #15 on: February 17, 2009, 01:56:46 PM »
Very nice Ron.

I like your method of calculating the centroid.  Much more concise than mine.

Thanks David :) I like this solution as well for averaging the point list
Code: [Select]
(mapcar '(lambda (x) (/ x (length points))) (apply 'mapcar (cons '+ points))) I grabbed it from somewhere off the swamp....perhaps MP's or Giles code?

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

litss

  • Guest
Re: How can I know if the shapes are the same?
« Reply #16 on: February 18, 2009, 08:27:05 AM »
wow, ronjonp, u r fast :)

Quote
Here is how I would group the objects as sublists.
ur way is better. I still have some problems in applying the "mapcar" and "lambda". hard to understand...need to do more homework

Quote
Here is one using David's centroid\vertex distance method...
My way of calculating the centroid is much more complicated and much slower than urs. Do we get the same centroid by these two methods? Here's mine.
Code: [Select]
  (defun centroid (ENT /)
    (command "_REGION" ENT "")
    (setq p1 (vlax-safearray->list (vlax-variant-value
                                                       (vla-get-centroid
                                                                         (vlax-ename->vla-object
                                                                                                 (ENTLAST)
                                                                         )
                                                       )
                                   )
             )
    )
    (entdel (entlast))
    p1
  ) 




ronjonp

  • Needs a day job
  • Posts: 7529
Re: How can I know if the shapes are the same?
« Reply #17 on: February 18, 2009, 09:48:06 AM »
wow, ronjonp, u r fast :)

Quote
Here is how I would group the objects as sublists.
ur way is better. I still have some problems in applying the "mapcar" and "lambda". hard to understand...need to do more homework

Quote
Here is one using David's centroid\vertex distance method...
My way of calculating the centroid is much more complicated and much slower than urs. Do we get the same centroid by these two methods? Here's mine.
....

From my tests they return different results depending on the shape (square\rectangle same) other polygons different. My guess is the centroid function uses more points along the boundary.

You can shorten your routine above by using "vlax-get" since it will return the point and not a variant.

Code: [Select]
(defun centroid (ent /)
  (command "_REGION" ent "")
  (setq p1 (vlax-get (vlax-ename->vla-object (entlast)) 'centroid))
)

Enjoy :)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC