Joining parallel lines with single line

Joining parallel lines with single line

Anonymous
Not applicable
7,230 Views
20 Replies
Message 1 of 21

Joining parallel lines with single line

Anonymous
Not applicable

Hello everyone,

Very new to AutoCad & lisp coding so please forgive my ignorance.

Am looking to join two (regular) parallel lines, end point to end point, with a single perpendicular line. Ideally it would be great if I could just window select the two lines I wanted connected but would settle for manually selecting the two end points.

I know much has been said & done about achieving this with polylines etc but I need my lines to remain as just regular lines.

I did find a lisp routine that came close but it joined the parallel lines with lines at both ends: thus creating a rectangle. Other routines have placed multiple lines between the two parallels creating a train track kind of look.

Again, I apologise as the above mentioned lisps may be quite easy to modify so that only one line is added but that is currently above my pay grade!

Hopefully my request has made sense & someone clever can solve my issue.

Thank-you everyone.

Brad

0 Likes
Accepted solutions (2)
7,231 Views
20 Replies
Replies (20)
Message 2 of 21

ВeekeeCZ
Consultant
Consultant

Better post a sample dwg.

Would both line in the same direction? Or not necessary?

0 Likes
Message 3 of 21

3wood
Advisor
Advisor
Accepted solution

I had an old one written in 1999. 

You can try the code below:

;;;
;;; Joinends.lsp
;;;
;;; By 3wood, April 1999

(defun c:jdd(/ ss1 pt0 i lin0 pt1 pt2 b1 pt_s1 b2 pt_s2a dst0 pt_s2) 
  (while (= ss1 nil)
    (prompt"\nSelect lines to be connected:")
    (setq ss1(ssget '((0 . "line"))))
  )
  (setq pt0(getpoint"\nSelect a point to determine which ends will be connected: "))
  (setq i 0)
  (repeat (sslength ss1)
    (setq lin0 (entget(ssname ss1 i)))
    (setq pt1 (cdr(assoc 10 lin0)))
    (setq pt2 (cdr(assoc 11 lin0)))
    (if (<(distance pt1 pt0)(distance pt2 pt0))
        (setq b1(append b1 (list pt1)))
        (setq b1(append b1 (list pt2)))
    )
    (setq i (1+ i))
  )
  (while (>=(length b1) 2)
    (setq pt_s1 (car b1))
    (setq b2 (cdr b1))
    (foreach pt_s2a b2 
      (if (= dst0 nil)
          (setq pt_s2 pt_s2a
                dst0(distance pt_s1 pt_s2a)
          )
          (if (<(distance pt_s1 pt_s2a) dst0)             
              (setq pt_s2 pt_s2a
                    dst0 (distance pt_s1 pt_s2a)
              )
          )
      )
    )
    (setq dst0 nil)
    (setq b1(append(cdr(member pt_s2 b2))(cdr(member pt_s2 (reverse b2)))))
    (setq lin0(subst(cons 10 pt_s1)(assoc 10 lin0)lin0))
    (setq lin0(subst(cons 11 pt_s2)(assoc 11 lin0)lin0))
    (entmake lin0)
  )
  (princ)
)
0 Likes
Message 4 of 21

Anonymous
Not applicable

Nailed it '3Wood'!

 

Manually drawing a line between these gaps was only a few mouse/keyboard clicks but do this 30-40 times per drawing and work on 10-12 documents per day...starts to add up.

 

Your solution works magnificently and has answered my request perfectly.

Can't thank you enough mate.

 

Brad

0 Likes
Message 5 of 21

Kent1Cooper
Consultant
Consultant
Accepted solution

For a broader-scope solution, try CapEnd.lsp with its CE command, available >here<.  The Line "capping" is the default, but it can also close such ends with an Arc, a circular-pipe cut-end symbol, or a cut line.  It can be used on any  object types with linearity that have ends [Lines, Arcs, partial Ellipses, open-ended Polylines and Splines, even Rays], and it verifies that the things selected line up and aim in the same direction at the selected ends.  You do need to select each object, anywhere closer to the end you want capped.  See more at the image in the link, and comments in the file.

Kent Cooper, AIA
0 Likes
Message 6 of 21

Anonymous
Not applicable

Hi Kent1Cooper,

 

Thankyou so very much for that.  Works beautifully and is now a tool in my custom AutoCad palette.

You're a legend!

0 Likes
Message 7 of 21

MaccyDee
Enthusiast
Enthusiast

bit of a stretch but do you know of anyway to make this LSP or another LSP be able to close multiple pairs of lines at once?

 

attached a .dwg of what i mean, i want to cap off every open section so it becomes one entity/ closed poly line, it needs to be hatched after this so needs to be closed (easy enough to do with select and close if all the lines are there)

0 Likes
Message 8 of 21

Sea-Haven
Mentor
Mentor

Try this just drag 1st point - 2nd point over the 2 lines near the missing end.

(defun c:endcap ( / pt1 pt2 pt3 pt4 pt5 pt6 ss d1 d2)
(while (setq pt1 (getpoint "\nPick point 1 Enter to exit"))
  (setq pt2 (getpoint pt1 "\nPick point 2"))
  (setq ss (ssget "F" (list pt1 pt2)(list (cons 0 "*LINE"))))
  (if (= (sslength ss) 2)
  (progn
    (setq ent1 (vlax-ename->vla-object (ssname ss 0)) ent2 (vlax-ename->vla-object (ssname ss 1)))
	(setvar 'clayer (vla-get-layer ent1))
    (setq pt3 (vlax-curve-getstartpoint ent1) pt4 (vlax-curve-getendpoint ent1))
    (setq d1 (distance pt1 pt3) d2 (distance pt1 pt4))
    (if (> d1 d2)
     (setq temp pt3 pt3 pt4 pt4 temp)
    )
    (setq pt5 (vlax-curve-getstartpoint ent2) pt6 (vlax-curve-getendpoint ent2))
    (setq d1 (distance pt1 pt5) d2 (distance pt1 pt6))
    (if (> d1 d2)
      (setq temp pt6 pt6 pt5 pt5 temp)
    )
    (command "line" pt3 pt5 "")
  )
  )
)
(princ)
)
(c:endcap)
0 Likes
Message 9 of 21

Kent1Cooper
Consultant
Consultant

@Sea-Haven wrote:

Try this just drag 1st point - 2nd point over the 2 lines near the missing end.


[That's in answer to the original post from over 2 years ago, not to the latest reviving Message, since it does only one end-capping at a time.]

 

Apart from setting the current Layer to that of one of the Lines [what if they're on different Layers?] and not setting it back, I don't see any advantage to that over just having ENDpoint Osnap on [which I virtually always do anyway] and just using the plain old LINE command.  You're going to need to pick twice near the desired ends, so just Osnap to them.

 

It can also be thrown off by geometric relationships.  With the white being the existing Lines, and the dashed green being the drag-across line, this red result works as expected:

Kent1Cooper_0-1650974467553.png

but in these kinds of situations it "sees" the wrong ends:

Kent1Cooper_1-1650974501949.png  

Kent1Cooper_2-1650974917899.png

BUT it has the advantage over mine that it will at least do angled closures and connect ends of non-parallel Lines [if you need to do those] -- mine checks that the ends are parallel and line up in such a way that in the Line-closure option the result is perpendicular, because of its other closure options that don't make sense otherwise.

Kent Cooper, AIA
0 Likes
Message 10 of 21

Kent1Cooper
Consultant
Consultant

@MaccyDee wrote:

.... do you know of anyway to make this LSP or another LSP be able to close multiple pairs of lines at once? ....


That would be challenging.  I assume you would want to select all of that stuff in a big window or something.  So a routine would need to figure out which open ends are close to which other open ends -- probably by storing all ends of all non-closed Polylines [or Lines, if you might use those sometimes], eliminating any that have an end of another object at the same place, and doing distance comparisons.  It may be possible, but I can't work on that right now.

Kent Cooper, AIA
0 Likes
Message 11 of 21

Sea-Haven
Mentor
Mentor

Yes Kent after posting realized it should be a auto thing and look for open ends, it could be done as a find every end and have a look does it have another line at that end point if so skip, else look further for another parallel line say check angle. The only issue I see is the width of the offsets varies in the sample. Need to put thinking cap on. Problems with pline corner maybe.

 

What may be better is go back a step when draw 2 lines cap then. 

0 Likes
Message 12 of 21

Kent1Cooper
Consultant
Consultant

And would they always be lined-up-and-parallel at their ends [the kind of relationships that CapEnd.lsp accepts], or might you sometimes have situations like these to close [red being the closure Lines]?

Kent1Cooper_0-1651060346844.png

 

Kent Cooper, AIA
0 Likes
Message 13 of 21

Charlie.ford7Z4SW
Explorer
Explorer

Hi Kent1Cooper

 

I was wondering if there was anyway of incorporating that Lisp into the code below. basically what this lisp does is create offsets from layers and then you select an internal area to make a boundary. The problem I am having now is shown here https://www.cadtutor.net/forum/topic/76307-delete-a-previous-action-in-the-lisp-command/#comment-603...

 

 

(defun c:APV (/ ss1 Lastent TargEnt TargLayer undo obj ss of en pt ent) 
 		(setq SS1 (ssadd))
 		(setq LastEnt (entlast))
		(while (setq TargEnt (car (entsel "\nSelect object on layer to select: "))) 
  		(setq TargLayer (assoc 8 (entget TargEnt)))
  		(sssetfirst nil (ssget "_X" (list TargLayer)))
   		(defun *error* (msg)
   		(or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
      		(princ (strcat "\n** Error: " msg " **")))
   		(princ)
  		)

	(if (and (ssget '((0 . "ARC,CIRCLE,ELLIPSE,*LINE")))
          (setq of (getdist "\nSpecify Offset Distance: ")))
   (progn
     (setq undo
       (not
         (vla-StartUndomark
           (setq doc
             (vla-get-ActiveDocument
               (vlax-get-acad-object)
             )
           )
         )
       )
     )
     
     (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc))
       (mapcar
         (function
           (lambda ( o )
             (vl-catch-all-apply
               (function vla-offset) (list obj o)
             )
           )
         )
         (list of (- of))
       )
     )
     (vla-delete ss)
	(setq undo (vla-EndUndoMark doc))
   )
 )
)
(if (setq en (entnext LastEnt))  ;adds all offsets to SS1
      (while en
        (ssadd en SS1)
        (setq en (entnext en))))

	 (while (setq pt (getpoint "\nPick internal point: "))
   (command "_.-boundary" "_a" "_i" "_n" "" "" "_non" pt "")
) 
  (foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex SS1)))
    (entdel ent) 
)                
(princ)
)

 

 Let me know if there is a way of putting a couple lines in this command to sort that problem

Many thanks for this code you've sent already it is very useful 

0 Likes
Message 14 of 21

Kent1Cooper
Consultant
Consultant

@Charlie.ford7Z4SW wrote:

....

 Let me know if there is a way of putting a couple lines in this command to sort that problem

.... 


More than a "couple," but if Line cappings of open ends will do, this [add the blue stuff] seems to work in quickie testing:

....

        (list of (- of))
      )
      (if (not (vlax-curve-isClosed obj))
        (progn ; then
          (setq OffsetResult2 (entlast))
          (entdel OffsetResult2); temporarily, in order to:
          (setq OffsetResult1 (entlast))
          (entdel OffsetResult2); bring back in
          (command
            "_.line" "_non" (vlax-curve-getStartPoint OffsetResult1) "_non" (vlax-curve-getStartPoint OffsetResult2) ""
            "_.line" "_non" (vlax-curve-getEndPoint OffsetResult1) "_non" (vlax-curve-getEndPoint OffsetResult2) ""
          ); command
        ); progn
      ); if
      )
      (vla-delete ss)

....

Kent1Cooper_0-1669666910565.png

Kent Cooper, AIA
0 Likes
Message 15 of 21

Kent1Cooper
Consultant
Consultant

Or, if Arc [really Circle] closures are preferred, try this:

....

      (list of (- of))
      )
      (if (not (vlax-curve-isClosed obj))
        (progn ; then
          (setq OffsetResult2 (entlast))
          (command
            "_.circle" "_non" (vlax-curve-getStartPoint obj) "_non" (vlax-curve-getStartPoint OffsetResult2) ""
            "_.circle" "_non" (vlax-curve-getEndPoint obj) "_non" (vlax-curve-getEndPoint OffsetResult2) ""
          ); command
        ); progn
      ); if
      )
      (vla-delete ss)

....

Kent1Cooper_0-1669666698658.png

 

Kent Cooper, AIA
0 Likes
Message 16 of 21

Charlie.ford7Z4SW
Explorer
Explorer

Brilliant thank you @Kent1Cooper that has done the trick!! cheers

0 Likes
Message 17 of 21

nathanERDLX
Enthusiast
Enthusiast
Hey Kent,

could be on my side but the 'download tip' button isn't functional anymore on Cadanalyst, are your lisp commands available on other sites?
0 Likes
Message 18 of 21

Kent1Cooper
Consultant
Consultant

@nathanERDLX wrote:
....
could be on my side but the 'download tip' button isn't functional anymore on Cadanalyst, ....

I just recently pointed that out to the people at Cadalyst, and they replied that they're working on fixing it.  In the meantime, here's that one.

Kent Cooper, AIA
Message 19 of 21

martin_spurnyQ7KE9
Explorer
Explorer

Hi there!

I was interested in using this LISP you edited, but its not working for me, I dont know why. The result of Charlie's code with your's edit looks like this for me. Dunno whats wrong? It puts only "ends" of offsets to new layer. Or maybe I am using it wrong. I though it create offset of all lines in layer and then create "cap" on ends?

EDIT: (I am using AC LT 2024)

 

error_lisp.png

 

0 Likes
Message 20 of 21

MaccyDee
Enthusiast
Enthusiast

Wow, I suck at replying, sorry!

 

For my use case the ends are going to be parallel, but I could see how having non parallel lines could be handy also.

 

Just an idea for how to work out which lines to join to which, could you do something like;

Join all lines already touching, I.e join command, then set them all to counter clockwise, delete coincident/colinear points (they occasionally pop up when I connect these objects)  then however the lisp actually works, analyse each point like how you do with the vertex skip button, get the coords for every first and last point of each line, save those to a list and then cap the ends that are closest (normal cap end function) 

 

So;

line 1, vertex 1 will be parallel or nearest to line 4 vertex 7

Line 1, vertex 6 will be near line 8, vertex 2

 

If that makes sense

0 Likes