Bill Tillman Posted April 9, 2012 Posted April 9, 2012 My LISP program creates many lines doing it's work. I'm at an area where two of the lines which get drawn need to be connected my a single line which goes from the midpoint of one to the midpoint of the other. (command "._LINE" pt1 pt2 "") (setq l1 (entlast)) (command "._LINE" pt3 pt4 "") (setq l2 (entlast)) (command "._LINE "mid" l1 "mid" l2" "") This of course does not work. In searching I don't seem to come up with any information on how to select the midpoint of a line using LISP. Quote
Bill Tillman Posted April 9, 2012 Author Posted April 9, 2012 As is usual with this process...I no sooner clicked the post button when I thought of a novel approach on this. By using the entget to grab the endpoints of the two lines and then a little arithmetic to calculate the middle points, I resolved this one. Quote
BIGAL Posted April 10, 2012 Posted April 10, 2012 Just a suggestion (setq l1 (entlast)) replace above with a defun (midptline) this would call entlast and work out pt (seqt L1 mpt) You could make it a global defun ->acad.lsp and call it from any routine then. Whilst the suggestions posted here are almost all single solutions using a library of common defuns makes life a lot easier if you are going to write lots of routines particuarly ones like this. Remove hard coding of layer names it can be done. Quote
irneb Posted April 10, 2012 Posted April 10, 2012 There's various ways of doing this, yet seeing as you've got the 4 points in your code, perhaps something like this: (defun midpoint (pt1 pt2 / ) (mapcar '(lambda (a b) (/ (+ a b) 2.)) pt1 pt2)) Then simply call it thus: (command "._LINE" "_None" (midpoint pt1 pt2) "_None" (midpoint pt3 pt4) "") If you need even the midpoint of an arc or polyline, then perhaps look into the vlax-curve-* functions. Quote
pBe Posted April 10, 2012 Posted April 10, 2012 (edited) ;;;MidPoint Between 2 Point Using CAL ;;;ARG -> 2 Points ;;;RET -> PointList ;;; comment removed [pBe retarded mode ] (if (not (member "geomcal.arx" (arx))) (arxload "geomcal") ) (defun midpt (p1 p2)(cal "(p1+p2)/2")) Edited April 10, 2012 by pBe Quote
irneb Posted April 10, 2012 Posted April 10, 2012 While that's fine (and a good sample of how to get a cal call in lisp), here's an issue showing that it's not always better to use ARX. (if (not (member "geomcal.arx" (arx))) (arxload "geomcal") ) (defun midpt (p1 p2)(cal "(p1+p2)/2")) (defun midp1 (pt1 pt2 /) (mapcar (function (lambda (a b) (/ (+ a b) 2.))) pt1 pt2)) (defun midp2 (pt1 pt2 /) (mapcar '/ (mapcar '+ pt1 pt2) '(2. 2. 2.))) While all 3 give the same result, the ARX is actually a LOT slower than the normal direct lisp idea. Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP1 PT1 PT2).....1202 / 4.65 <fastest> (MIDP2 PT1 PT2).....1357 / 4.11 (MIDPT PT1 PT2).....5584 / 1.00 <slowest> That's because of the overhead while converting to and fro between lispstringarx. Quote
pBe Posted April 10, 2012 Posted April 10, 2012 Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP1 PT1 PT2).....1202 / 4.65 (MIDP2 PT1 PT2).....1357 / 4.11 (MIDPT PT1 PT2).....5584 / 1.00 [/code] Geez, Now, THAT is SLOW. like turtle slow....like snail slow... like The three-toed sloth slow... like pBe typing skills slow..... Point taken Irneb. Quote
irneb Posted April 10, 2012 Posted April 10, 2012 Don't get me wrong. It's not that it's a bad idea, in some instances the speed doesn't count (say you get the midpoint between 2 picked points, then the speed is nullified due to the time taken for the user to click the 2 points). Not to mention, that's a difference of 5 seconds across 32k points - so in practise I don't think anyone would even notice! Your post does show an alternative, and it actually shows a lot more Quote
godofcad Posted April 10, 2012 Posted April 10, 2012 I think it vl help to u ....... Try this (setq pt1 (getpoint)) (setq pt2 (getpoint)) (command "line" pt1 pt2 "") (setq L1(entget(entlast))) (setq mid_pt1(polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2))) (setq pt3(getpoint)) (setq pt4(getpoint)) (command "line" pt3 pt4 "") (setq l2(entget(entlast))) (setq mid_pt2(polar pt3 (angle pt3 pt4) (/ (distance pt3 pt4) 2))) (command "line" mid_pt1 mid_pt2 "") Quote
Lee Mac Posted April 10, 2012 Posted April 10, 2012 Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP1 PT1 PT2).....1202 / 4.65 <fastest> (MIDP2 PT1 PT2).....1357 / 4.11 (MIDPT PT1 PT2).....5584 / 1.00 <slowest> (defun midp3 ( pt1 pt2 / ) (list (/ (+ (car pt1) (car pt2)) 2.0) (/ (+ (cadr pt1) (cadr pt2)) 2.0) (/ (+ (caddr pt1) (caddr pt2)) 2.0) ) ) Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP3 P1 P2)......1045 / 10.21 <fastest> (MIDP1 P1 P2)......1185 / 9 (MIDP2 P1 P2)......1248 / 8.55 (MIDPT P1 P2).....10670 / 1 <slowest> Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP3 P1 P2).....1029 / 1.2 <fastest> (MIDP1 P1 P2).....1201 / 1.03 (MIDP2 P1 P2).....1232 / 1 <slowest> Quote
Comatosis Posted April 10, 2012 Posted April 10, 2012 It would probably be even slower than everything suggested so far, but autoCAD (at least 2010) already has a snap option called "Mid Between 2 Points" (_m2p) that you can select in the shift+right-click menu (whatever that's called, heh). I have no idea if it's accessible through AutoLISP or if it would help clean up the code/reduce resource consumption at all, but eh, figured I might as well throw that out there just in case, lol. Quote
MSasu Posted April 11, 2012 Posted April 11, 2012 @Bill Tillman: For sure, you already received a bunch of good solutions to your issue. I will try to comment a little on your first approach. If you want to use the OSNAP modes to locate the points, then you should either match the action on prompter (that it, supply points for selection, not entity names) or use the OSNAP AutoLISP function. (command "_LINE" "_MID" pt1 "_MID" pt3 "") or (command "_LINE" (osnap pt1 "_MID") (osnap pt3 "_MID") "") However, this isn’t a recommended solution since it may be affected by the zoom level, how crowded is the drawing in that area and the size of pickbox, and also if entities are visible on the screen or not - there is the risk to have other item selected or no selection at all. Quote
MSasu Posted April 11, 2012 Posted April 11, 2012 @Comatosis: M2P or MTP is listed by AutoCAD as a command modifier; it may be used in AutoLISP codes too. (command "_LINE" "_M2P" pt1 pt2 "_M2P" pt3 pt4 "") Quote
irneb Posted April 11, 2012 Posted April 11, 2012 Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s): (MIDP3 P1 P2).....1029 / 1.2 <fastest> (MIDP1 P1 P2).....1201 / 1.03 (MIDP2 P1 P2).....1232 / 1 <slowest> Great! But what about 2D points? Quote
Lee Mac Posted April 11, 2012 Posted April 11, 2012 Great! But what about 2D points? True, the conditional required is likely to nullify any gains in performance by using this method over mapcar.. Quote
irneb Posted April 11, 2012 Posted April 11, 2012 Not too bad: (defun midp4 (pt1 pt2 / z1 z2) (append (list (/ (+ (car pt1) (car pt2)) 2.0) (/ (+ (cadr pt1) (cadr pt2)) 2.0)) (if (and (setq z1 (caddr pt1)) (setq z2 (caddr pt2))) (list (/ (+ z1 z2) 2.0))))) Benchmarking ...................Elapsed milliseconds / relative speed for 65536 iteration(s): (MIDP3 PT1 PT2).....1794 / 1.54 <fastest> (MIDP4 PT1 PT2).....1903 / 1.45 (MIDP1 PT1 PT2).....2371 / 1.16 (MIDP2 PT1 PT2).....2762 / 1 <slowest> Quote
irneb Posted April 11, 2012 Posted April 11, 2012 Actually, godofcad's idea is even speedier: (defun midp5 (pt1 pt2 /) (polar pt1 (angle pt1 pt2) (/ (distance pt1 pt2) 2.))) Benchmarking ...................Elapsed milliseconds / relative speed for 65536 iteration(s): (MIDP5 PT1 PT2).....1826 / 1.09 <fastest> (MIDP3 PT1 PT2).....1888 / 1.06 (MIDP4 PT1 PT2).....1996 / 1 <slowest> 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.