Jump to content

Recommended Posts

Posted

Hi guys

 

I am looking for a routine which helps to select AutoCAD points near line whitin user defined certain distance.

I've tried to write it by myself but I am completely newbie in AutoLISP. Anyway I will share my toughts about it.

 

As I said the user defines the distance from the line, so probably the routine should use the start and end point of the line and add/substract this distance so you get 4 pairs of coordinates and then use these coordinates to define the selection window.I hope it make sense.

 

It will be much apreciated if you give me some hints, thank you in advance.

  • Replies 30
  • Created
  • Last Reply

Top Posters In This Topic

  • guigonse

    8

  • Lee Mac

    5

  • hristev

    5

  • hanhphuc

    4

Posted (edited)

my $0.02

[url="http://www.lee-mac.com/ssget.html"]ssget[/url]
[color="blue"]getpoint 
entget
polar[/color]


(defun c:test ( / d en ob ls xy o1 o2)
 
(defun xy (l)
(if ([color="red"]cadr[/color] l) 
 (cons (list (car l)(cadr l))(xy (cddr l)))))
 
(and 
    (setq d (getdist "\nDistance from line.."))
    (setq en(car(entsel "\nSelect polyline ")))
    (wcmatch (cdr (assoc 0 (entget en))) "LWPOLYLINE")

(setq ob '("o1" "o2")
     ls (mapcar ''((a b)
                   (xy
                    (vlax-get
                    (set (read a) (car (vlax-invoke (vlax-ename->vla-object en) 'Offset b)))
                     'coordinates
                     )
                    )
                   )
                ob (list d (- d))
                )
     )

 (mapcar ''((x)(vla-delete (eval(read x)))) ob)
 (sssetfirst nil (ssget "_WP"  (append (car ls)(reverse (cadr ls))) '((0 . "POINT"))))

    ); and
 )

Edited by hanhphuc
xy function - cddr to cdar
Posted

Thank you very much of both of you!

 

@Tharwat that is exactly what I need. But I haven't been clear enough with my explanation though - the points Z values are not 0. So can you make it to ignore the Z values of the points and take in acount only X Y values and still select them.

 

I appreciate your help :)

Posted

Thank you very much of both of you!

 

@Tharwat that is exactly what I need. But I haven't been clear enough with my explanation though - the points Z values are not 0. So can you make it to ignore the Z values of the points and take in acount only X Y values and still select them.

 

I appreciate your help :)

Posted

Hi,

Try this program and be sure to have the selected line / polyline completely visible in the screen.

 

(defun c:Test ( / dis sel obj l r str end top dwn int sad ssc ent pnt)
 ;; Tharwat - Date: 01.Sep.2017	;;
 (if (and (setq dis (getdist "\nSpecify distance between line and points : "))
          (princ "\nSelect Line/Polyline :")
          (setq sel (ssget "_+.:S:E" '((0 . "LINE,LWPOLYLINE"))))
          (setq obj (ssname sel 0))
          )
   (progn
     (vla-GetBoundingBox (vlax-ename->vla-object obj) 'l 'r)
     (setq str (vlax-safearray->list r)
           end (vlax-safearray->list l)
           top (mapcar '(lambda (c d) (+ d c)) (list dis dis 0.) str)
           dwn (mapcar '(lambda (c d) (- d c)) (list dis dis 0.) end)
           int -1 sad (ssadd)
           )
     (if (setq ssc (ssget "_C" top dwn '((0 . "POINT"))))
       (while (setq ent (ssname ssc (setq int (1+ int))))
         (setq pnt (cdr (assoc 10 (entget ent))))
         (if (<= (distance (vlax-curve-getclosestpointto obj pnt) pnt) dis)
           (ssadd ent sad))
         )
       )
     )
   )
 (sssetfirst nil sad)
 (princ)
 ) (vl-load-com) 

Posted

Thank you very much of both of you!

 

@Tharwat that is exactly what I need. But I haven't been clear enough with my explanation though - the points Z values are not 0. So can you make it to ignore the Z values of the points and take in acount only X Y values and still select them.

 

I appreciate your help :)

Posted
Hi,

Try this program and be sure to have the selected line / polyline completely visible in the screen.

 

(defun c:Test ( / dis sel obj l r str end top dwn int [color="red"]sad[/color] ssc ent pnt)
 ;; Tharwat - Date: 01.Sep.2017	;;

 

;) why sad? i'm happy you still active here, fast & nice code anyway :thumbsup:

Posted

(defun xy (l)
(if [color="blue"](cddr l) [/color]
 (cons (list (car l)(cadr l))(xy (cddr l)))))

 

Hi,

I think there is no need to check for the second list of coordinates since this would come up with the last coordinates missing. ;)

 

;) why sad?

It is just a bad habit of using this name of variable with that function and nothing else. :)

i'm happy you still active here, fast & nice code anyway :thumbsup:

Thank you, its too kind of you to say that. :)

Posted
Hi,

I think there is no need to check for the second list of coordinates since this would come up with the last coordinates missing. ;)

 

 

Thank you Tharwat you are correct,

It was rough written but my ignorant for x,y parity :ouch:

as always good catch :thumbsup:

Posted
Thank you Tharwat you are correct,

It was rough written but my ignorant for x,y parity :ouch:

as always good catch :thumbsup:

 

No problem.

(if l ... is enough.

 

Have a nice weekend. :)

Posted

Here's another way to solve it, without reliance on object visibility:

([color=BLUE]defun[/color] c:ptnearline ( [color=BLUE]/[/color] dis ent enx idx llp lst pnt pte sel tmp urp )
   ([color=BLUE]initget[/color] 4)
   ([color=BLUE]if[/color] 
       ([color=BLUE]and[/color] ([color=BLUE]setq[/color] dis ([color=BLUE]getdist[/color] [color=MAROON]"\nSpecify proximity: "[/color]))
           ([color=BLUE]progn[/color]
               ([color=BLUE]while[/color]
                   ([color=BLUE]not[/color]
                       ([color=BLUE]progn[/color] ([color=BLUE]setvar[/color] 'errno 0) ([color=BLUE]setq[/color] ent ([color=BLUE]car[/color] ([color=BLUE]entsel[/color] [color=MAROON]"\nSelect line or polyline: "[/color])))
                           ([color=BLUE]cond[/color]
                               (   ([color=BLUE]=[/color] 7 ([color=BLUE]getvar[/color] 'errno))
                                   ([color=BLUE]prompt[/color] [color=MAROON]"\nMissed, try again."[/color])
                               )
                               (   ([color=BLUE]null[/color] ent))
                               (   ([color=BLUE]=[/color] [color=MAROON]"LINE"[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 0 ([color=BLUE]setq[/color] enx ([color=BLUE]entget[/color] ent)))))
                                   ([color=BLUE]setq[/color] llp ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 10 enx))
                                         urp ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 11 enx))
                                         tmp ([color=BLUE]mapcar[/color] '[color=BLUE]max[/color] llp urp)
                                         llp ([color=BLUE]mapcar[/color] '[color=BLUE]min[/color] llp urp)
                                         urp tmp
                                   )
                               )
                               (   ([color=BLUE]=[/color] [color=MAROON]"LWPOLYLINE"[/color] ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 0 enx)))
                                   ([color=BLUE]setq[/color] lst ([color=BLUE]mapcar[/color] '[color=BLUE]cdr[/color] ([color=BLUE]vl-remove-if-not[/color] '([color=BLUE]lambda[/color] ( x ) ([color=BLUE]=[/color] 10 ([color=BLUE]car[/color] x))) enx))
                                         llp ([color=BLUE]apply[/color] '[color=BLUE]mapcar[/color] ([color=BLUE]cons[/color] '[color=BLUE]min[/color] lst))
                                         urp ([color=BLUE]apply[/color] '[color=BLUE]mapcar[/color] ([color=BLUE]cons[/color] '[color=BLUE]max[/color] lst))
                                   )
                               )
                               (   ([color=BLUE]prompt[/color] [color=MAROON]"\nPlease select a line or polyline."[/color]))
                           )
                       )
                   )
               )
               ent
           )
           ([color=BLUE]setq[/color] sel
               ([color=BLUE]ssget[/color] [color=MAROON]"_X"[/color]
                   ([color=BLUE]list[/color]
                      '(000 . [color=MAROON]"POINT"[/color])
                      '(-04 . [color=MAROON]">=,>="[/color])
                       ([color=BLUE]cons[/color] 10 ([color=BLUE]mapcar[/color] '[color=BLUE]-[/color] llp ([color=BLUE]list[/color] dis dis)))
                      '(-04 . [color=MAROON]"<=,<="[/color])
                       ([color=BLUE]cons[/color] 10 ([color=BLUE]mapcar[/color] '[color=BLUE]+[/color] urp ([color=BLUE]list[/color] dis dis)))
                       ([color=BLUE]if[/color] ([color=BLUE]=[/color] 1 ([color=BLUE]getvar[/color] 'cvport))
                           ([color=BLUE]cons[/color] 410 ([color=BLUE]getvar[/color] 'ctab))
                          '(410 . [color=MAROON]"Model"[/color])
                       )
                   )
               )
           )
       )
       ([color=BLUE]repeat[/color] ([color=BLUE]setq[/color] idx ([color=BLUE]sslength[/color] sel))
           ([color=BLUE]setq[/color] pte ([color=BLUE]ssname[/color] sel ([color=BLUE]setq[/color] idx ([color=BLUE]1-[/color] idx)))
                 pnt ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 10 ([color=BLUE]entget[/color] pte)))
           )
           ([color=BLUE]if[/color] ([color=BLUE]<[/color] dis ([color=BLUE]distance[/color] pnt ([color=BLUE]vlax-curve-getclosestpointto[/color] ent pnt)))
               ([color=BLUE]ssdel[/color] pte sel)
           )
       )
   )
   ([color=BLUE]sssetfirst[/color] [color=BLUE]nil[/color] sel)
   ([color=BLUE]princ[/color])
)
([color=BLUE]vl-load-com[/color]) ([color=BLUE]princ[/color])

Posted

@hanhphuc, @Tharwat and @Lee Mac, you guys are true legends. As I tried the routines of all of you I realized my explanation was not fully correct. I missed the part that my points' Z value is not 0 and the routine needs to take in account only X and Y. Obviously the routine of @hanhphuc work in that scenario and the other two don't but I am grateful to all tree of you that you spend time on this. Cheers :notworthy:

Posted
        ([color=BLUE]repeat[/color] ([color=BLUE]setq[/color] idx ([color=BLUE]sslength[/color] sel))             ([color=BLUE]setq[/color] pte ([color=BLUE]ssname[/color] sel ([color=BLUE]setq[/color] idx ([color=BLUE]1-[/color] idx)))                   pnt ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 10 ([color=BLUE]entget[/color] pte)))             )             ([color=BLUE]if[/color] ([color=BLUE]<[/color] dis ([color=BLUE]distance[/color] pnt ([color=BLUE]vlax-curve-getclosestpointto[/color] ent pnt)))                 ([color=BLUE]ssdel[/color] pte sel)             )         )

[\QUOTE]

IMO you could forget about pre-selecting POINTS and make Lee Mac's distance check for ALL POINT entities, isn't it? :?

Posted

Arghh!! Missed copy/pasting part of the code... Apologies... :oops:

Posted

       ([color=BLUE]repeat[/color] ([color=BLUE]setq[/color] idx([color=BLUE]sslength[/color][color=red][b][color=red] [b](setq sel[/b][/color] (ssget "X" '((0 . "POINT"))))[/b][/color]))
           ([color=BLUE]setq[/color] pte ([color=BLUE]ssname[/color] sel ([color=BLUE]setq[/color] idx ([color=BLUE]1-[/color] idx)))
                 pnt ([color=BLUE]cdr[/color] ([color=BLUE]assoc[/color] 10 ([color=BLUE]entget[/color] pte)))
           )
           ([color=BLUE]if[/color] ([color=BLUE]<[/color] dis ([color=BLUE]distance[/color] pnt ([color=BLUE]vlax-curve-getclosestpointto[/color] ent pnt)))
               ([color=BLUE]ssdel[/color] pte sel)
           )
       )

 

That's the part of the code i was referring, with small changes in red...

By the way, there's an option for editing my own messages? This will shorten threads, I think...

Posted
IMO you could forget about pre-selecting POINTS and make Lee Mac's distance check for ALL POINT entities, isn't it? :?

 

This is hugely inefficient for large point sets. Using an ssget filter to vastly reduce the initial point set based on coordinate values greatly reduces the number of relatively inefficient calls to vlax-curve-getclosestpointto & distance. Code concision does not necessary equal efficiency.

Posted
This is hugely inefficient for large point sets. Using an ssget filter to vastly reduce the initial point set based on coordinate values greatly reduces the number of relatively inefficient calls to vlax-curve-getclosestpointto & distance. Code concision does not necessary equal efficiency.

 

You're right, probably... :unsure:

But if the whole points group in the rectangle which diagonal is the selection line, then you will end selecting the major part of them despite your coding effort! :facepalm:

What about a "Windows Polygon selection? Would be easy to generate it with (polar ..) generated points from the reference segment, and the selection would be the answer itself...

And frankly speaking, forgetting 3d scanned cloud points, do you really think there would be a loose of performance perception on processing part or the whole of points in the major part of drawings? :D

;; p1 = start point of reference segment
;; p2 = end point of reference segment
;; dist = distance of selection

 (setq a (angle p1 p2)
       ss (ssget "_CW"
               (list
                 (polar p1 a dist)
                 (polar p1 a (- dist))
                 (polar p2 a dist)
                 (polar p2 a (- dist)) )
              '((0 . "POINT"))
        )
   )

I'm just checking strategies...

Posted
This is hugely inefficient for large point sets. Using an ssget filter to vastly reduce the initial point set based on coordinate values greatly reduces the number of relatively inefficient calls to vlax-curve-getclosestpointto & distance. Code concision does not necessary equal efficiency.

 

As a quick demonstration of this difference in efficiency, the following are timings for point sets of varying size:

 

100,000 Random Points

Prefiltered point set:  0.312 seconds
Processing all points:  1.154 seconds

500,000 Random Points

Prefiltered point set:  0.749 seconds
Processing all points:  5.756 seconds

1,000,000 Random Points

Prefiltered point set:  1.232 seconds
Processing all points: 10.389 seconds

Posted

You have wrote both routines and a third to generate random points and evaluated them!! You are my hero!! :o

Questions: how do you make "solid" time measurements with Lisp? And with Visual Lisp?

Referring to the problem, being efficiency a key point, wouldn't be better to optimize (ssget ..) to make the exact selection with a "Window Poligon" option?

Something like

;; p1 = straight segment origin
;; p2 = straight segment end
;; d = max distance to straight segment
(setq a (+ (angle p1 p2) (/ pi 2))
     ss (ssget "_CW"
           (list
             (polar p1 a d)
             (polar p1 a (- d))
             (polar p2 a d)
             (polar p2 a (- d)) )
          '((0 . "POINT")) ) )

This way, selection is the solution, isn't it? But only with straight segments, of course... :roll:

Posted

@guigonse:

In principle you are right, although your window points are not in the correct order.

 

But please note this:

 

  1. Your code assumes a 2D drawing.
  2. The window selection has to be on-screen. Lee has already referred to this.
  3. The end and start point of the line are expressed in the WCS whereas the "CW" points are expressed in the current UCS.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...