Jump to content

Recommended Posts

Posted

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.

Posted

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.

Posted

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.

Posted

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.

Posted (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 by pBe
Posted

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.

Posted

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. :thumbsup:

Posted

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 ;)

Posted

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 "")

Posted
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>

:)

Posted

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.

Posted

@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.

Posted

@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 "")

Posted
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?
Posted
Great! But what about 2D points?

 

True, the conditional required is likely to nullify any gains in performance by using this method over mapcar..

Posted

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>

Posted

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>

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...