MarcoW Posted January 15, 2010 Posted January 15, 2010 Hello, This I brew (credit-> with some help from Asmi's website): (defun c:getClosestPoint (/ obj pt1 pt2) ; Make variables local (vl-load-com) ; Loads the extended AutoLISP functions (setq obj (car (entsel)) ; Select an object / curve pt1 (getpoint "\nGrab yourself a point: ") ; As it says... pt2 (vlax-curve-getClosestPointTo obj pt1) ; The actual "determination" of the closest point ); end of setq (command "_.line" pt1 pt2 "") ; draw line between the 2 points (princ) ; clean running ); end of defun (princ) ;clean loading Is it possible to modify this code in a way that I will not have to select the object? I guess there must be a way to "get the closest object to the given point". After the AutoCad needs to find the object itself. When there are many object, I know it is hard to be precise but thats not the point now. All I want to know is if it is possible, and how. By the way, to determine the closest point was much easier as I thought. I hope the answer to my question is too. Thanks for helping me out! Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 Perhaps something along these lines, but I wouldn't want to do it for thousands of objects.... (defun c:test (/ i ss pt ent lst Nrst) (if (and (setq i -1 ss (ssget "_X" '((0 . "*LINE,CIRCLE,ELLIPSE,ARC")))) (setq pt (getpoint "\nSelect a Point: "))) (progn (while (setq ent (ssname ss (setq i (1+ i)))) (setq lst (cons (cons ent (vlax-curve-getClosestPointto ent pt)) lst))) (setq Nrst (car (vl-sort lst (function (lambda (a b) (< (distance (cdr a) pt) (distance (cdr b) pt))))))) (entmakex (list (cons 0 "LINE") (cons 10 pt) (cons 11 (cdr Nrst)))))) (princ)) Quote
MarcoW Posted January 15, 2010 Author Posted January 15, 2010 Hi Lee, That is exactly what I needed to know. Thank you ! But now, for the learning part... I can't make any sense out of it, that is due to my still lacking knowledge. But, I get better all along. Maybe you can explain me a little more, if you can / want. I'd be happy with it. Cheers. Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 Maybe you can explain me a little more, if you can / want.I'd be happy with it.. Sure dude: [b][color=RED]([/color][/b][b][color=BLUE]defun[/color][/b] c:test [b][color=RED]([/color][/b][b][color=BLUE]/[/color][/b] i ss pt ent lst Nrst[b][color=RED])[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]if[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]and[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] i [b][color=#009900]-1[/color][/b] [i][color=#990099];; Initiate Counter[/color][/i] ss [b][color=RED]([/color][/b][b][color=BLUE]ssget[/color][/b] [b][color=#a52a2a]"_X"[/color][/b] [b][color=DARKRED]'[/color][/b][b][color=RED]([/color][/b][b][color=RED]([/color][/b][b][color=#009900]0[/color][/b] . [b][color=#a52a2a]"*LINE,CIRCLE,ELLIPSE,ARC"[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Get A SelectionSet of all CurveObjects to iterate through[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] pt [b][color=RED]([/color][/b][b][color=BLUE]getpoint[/color][/b] [b][color=#a52a2a]"\nSelect a Point: "[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Get Point from User[/color][/i] [b][color=RED])[/color][/b] [i][color=#990099]; end AND[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]progn[/color][/b] [i][color=#990099];; Open Wrapper for 'then' statement[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]while[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] ent [b][color=RED]([/color][/b][b][color=BLUE]ssname[/color][/b] ss [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] i [b][color=RED]([/color][/b][b][color=BLUE]1+[/color][/b] i[b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; While we can get an entity name in the SelectionSet[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] lst [b][color=RED]([/color][/b][b][color=BLUE]cons[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cons[/color][/b] ent [b][color=RED]([/color][/b][b][color=BLUE]vlax-curve-getClosestPointto[/color][/b] ent pt[b][color=RED])[/color][/b][b][color=RED])[/color][/b] lst[b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Make a list of entities and closest Points (in case we need the object also)[/color][/i] [i][color=#990099];; List looks like this:[/color][/i] [i][color=#990099];; ((<Entity name: 7ef038c0> . (-23.3336 30.6639 0.0))[/color][/i] [i][color=#990099];; (<Entity name: 7ef038c8> . (-46.4083 3.42278 0.0)) ...)[/color][/i] [b][color=RED])[/color][/b] [i][color=#990099]; end WHILE[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]setq[/color][/b] Nrst [b][color=RED]([/color][/b][b][color=BLUE]car[/color][/b] [i][color=#990099];; Get the First item of the Sorted List[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]vl-sort[/color][/b] lst [b][color=RED]([/color][/b][b][color=BLUE]function[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]lambda[/color][/b] [b][color=RED]([/color][/b]a b[b][color=RED])[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]<[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]distance[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cdr[/color][/b] a[b][color=RED])[/color][/b] pt[b][color=RED])[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]distance[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cdr[/color][/b] b[b][color=RED])[/color][/b] pt[b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Sort the list by distance from the original selected point[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]entmakex[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]list[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cons[/color][/b] [b][color=#009900]0[/color][/b] [b][color=#a52a2a]"LINE"[/color][/b][b][color=RED])[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cons[/color][/b] [b][color=#009900]10[/color][/b] pt[b][color=RED])[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cons[/color][/b] [b][color=#009900]11[/color][/b] [b][color=RED]([/color][/b][b][color=BLUE]cdr[/color][/b] Nrst[b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Create a line from the user selected point to the nearest point[/color][/i] [b][color=RED]([/color][/b][b][color=BLUE]princ[/color][/b][b][color=RED])[/color][/b][b][color=RED])[/color][/b] [i][color=#990099];; Exit Cleanly[/color][/i] Quote
MarcoW Posted January 15, 2010 Author Posted January 15, 2010 Thank you Lee! I can follow but it is hard for me. ie. two times the "cons" within 1 setq... making a list in a list? And this: (while (setq ent (ssname ss (setq i (1+ i)))) How to read this? First: add "1" to "i" every time the loop comes across Then "do something" (-->ssname ???) with the selection set "ss" And then put the result out of that into the variable "ent". This loops as long as ..? I wish I had more time to spend on this. Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 Marco, Experiment a bit, see what happens when you use two 'cons'. As for the While loop, look into the Visual LISP Editor help files for 'ssname' Lee Quote
MarcoW Posted January 15, 2010 Author Posted January 15, 2010 Yeah you are right, I should have looked there first. (setq ent1 (ssname sset 0)) ; Gets the name of the first entity in sset. Two cons is meaning: putting a new item in the list, as first item? Oughh... it's hard but it is to be learned. Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 When used with two atoms, cons makes a dotted pair, or, when used with an atom/list and another list, it will add the atom/list to the beginning of the list. Quote
devitg Posted January 15, 2010 Posted January 15, 2010 Hi Lee Mac, I wonder about the way you do LISP. Could you explain what is the difference between ENTMAKE and ENMAKEX? Thanks. Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 I tend to use entmakex over entmake, as it returns the entity name of the newly created entity, which can be useful. Quote
devitg Posted January 15, 2010 Posted January 15, 2010 I tend to use entmakex over entmake, as it returns the entity name of the newly created entity, which can be useful. So it is some like the (entmake (list (cons 0 "LINE") (cons 10 pt) (cons 11 (cdr Nrst)))))) (setq line (entlast)) Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 These will give the same result: (setq line (entmakex (list (cons 0 "LINE") (cons 10 p1) (cons 11 p2)))) (entmake (list (cons 0 "LINE") (cons 10 p1) (cons 11 p2))) (setq line (entlast)) Lee Quote
devitg Posted January 15, 2010 Posted January 15, 2010 Thanks Lee. Is not to late for you now? Its 8.30 pm here Quote
Lee Mac Posted January 15, 2010 Posted January 15, 2010 Thanks Lee. Is not to late for you now? Its 8.30 pm here Nah - just occassionally on the forums while watching telly - 23:25 here Quote
MarcoW Posted January 16, 2010 Author Posted January 16, 2010 Lee, I have tried it and allthought there are really more than thousand object in the drawing, it still works. How would one need to approach this if the objects were in an xref? In my first post: obj (car (entsel)) turning into: obj (car (nentsel)) .. is possible, but your code is made in a different way.. You do not use the "entsel" thing... Quote
Lee Mac Posted January 16, 2010 Posted January 16, 2010 The vlax-curve-getClosestPointto only works with Curve Objects, so you would have to add the XRef sub-entities to the selection set. Its a lot easier if you allow the user to select an object. Quote
MarcoW Posted January 18, 2010 Author Posted January 18, 2010 Yes I know but that is the point, I don't want to select the object manually. I am going to try to pick a point an then create a kind of "boundary". Or limits if you like... Only objects within those limits take part then. Tnx for helping me. Quote
MarcoW Posted January 21, 2010 Author Posted January 21, 2010 The vlax-curve-getClosestPointto only works with Curve Objects, so you would have to add the XRef sub-entities to the selection set. Its a lot easier if you allow the user to select an object. Lee, I have tried to find a lisp in wich "xref sub entities" are put so the selection set. Did not find anything I can use or explore, . I did find this code, from CAB, somewhere on the internet: (At first the code worked, I don't know what I am doing wrong with that now, I dont work) (defun c:test (/ pk r lyr) (if (and (setq pk (getpoint "\nPick point to get lines.")) (setq r (getdist pk "\nEnter search distance.")) (setq lyr (getstring t "\nEnter layer name.")) ) (if (setq ss ([color=royalblue]get_lines[/color] r pk lyr)) [color=red] (mapcar '(lambda (x) (print x)) (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss))) ) [/color] (prompt "\nNothing found.") ) ) (princ) ) ;; get lines crossing a rectangle 2*rad with pt as the center ;; only on layer specified (defun get_lines (rad pt lay / ll ur) (setq ll (list (- (car pt) rad) (- (cadr pt) rad)) ur (list (+ (car pt) rad) (+ (cadr pt) rad)) ) (ssget "_C" ur ll ; look at the entire drawing, no user input ;; filter to follow (list '(0 . "LINE") ; get only lines (cons 8 lay) ; layer name (cons 410 (getvar "ctab")) ; current space only ) ) ) As far as I know the return / result of this program is the entities name (in xref) that is closest to the point given. I see that there is a crossing used in the ssget part. The blue part is executing the sub-function, so till that point I get it. Then the red part, that I can't explain. Somehow I am stuck, with everything. Can you help me out again? I will again try to specify my needs: 1. Prompt for user input (getpoint) 2. Get nearest point on "anything" --> also XREF Better to say: it will 99% be something (line / circle etc.) in an Xref. Maybe 1% is not in an Xref... therefore "anything". From there I will try my own way again. The code from CAB is not what must be used but I guess that in this code is a usefull part, the red part. Quote
Lee Mac Posted January 21, 2010 Posted January 21, 2010 The red part just prints the entity names in the selection set, it is nothing to do with the selection process. The actual selection process just uses a crossing selection set, and will not get Xref sub-entities, but just the xRef itself. Quote
Recommended Posts
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.