Lisp to draw line between two lines - dividing space equally

Lisp to draw line between two lines - dividing space equally

Anonymous
Not applicable
19,890 Views
48 Replies
Message 1 of 49

Lisp to draw line between two lines - dividing space equally

Anonymous
Not applicable

Hi all,

 

 

First of all, Thanks for the effort and time you spend for this AutoCAD community.

 

Can some body let me know if there is a lisp program to draw lines, exactly dividing ( the user should be able to input the number of spaces he/she wants between the lines) the space between 2 polylines /lines ( Parallel or on parallel). I am using the lisp LineBetween currently, but it has its own limitations, like it will not work when the UCS is rotated, the midway line created  is a LINE rather than a polyline  even if the original lines selected are polylines, etc.

 

Purpose:

 

I basically use this  to make concrete scoring while doing storefront concrete, where I have to tell the general contractor where to give construction joints/ control joints. Depending upon the structural stoop and building wall projections, I have to decide whether I have to divide the space equally in 2, 3, 4 parts, etc.

 

Any help in this regard is highly appreciated.

 

Regards,

 

VM

0 Likes
Accepted solutions (1)
19,891 Views
48 Replies
Replies (48)
Message 21 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... I am afraid  I have to get your help to include this in the lisp ( if "I" do it - the lisp is going to do 'WONDERS' - lol). ....


Try this [untested this time]:

;|
SplitBetween.lsp, to draw Polylines between four selected points, or take
selection of two existing Lines or single-line-segment Polylines, and
draw subdividing Polylines between and paralleling them or "splaying"
between them if not parallel.  Works in 3D, and in any UCS.
If selecting existing lines, draws subdividing Polylines on Layer of 2nd
selected line; if picking four points, draws on current Layer.
Accounts for lines drawn in opposite directions, by reading second line
the other way; if lines are not co-planar, decides that on the basis of
2D view in current Coordinate System.
Kent Cooper, last edited 21 December 2016
|;

(defun C:SLB ; = Split Lines Between
  (/ *error* var ev doc svnames svvals ptA1 ptA2 ptB1
    ptB2 linA linB edata parts partno delta1 delta2 inc1 inc2)

  (defun *error* (errmsg)
    (if (wcmatch errmsg "Function cancelled,quit / exit abort,console break")
      (princ (strcat "\nError: " errmsg))
    ); if
    (mapcar 'setvar svnames svvals); reset
    (vla-endundomark doc)
    (princ)
  ); defun -- *error*

  (defun var (ltr); build variable name
    (read (strcat "lin" ltr))
  ); defun -- var

  (defun ev (ltr); get contents of variable name
    (eval (var ltr))
  ); defun -- ev

  (vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object))))
  (setq ; System Variable saving/resetting without separate variables for each:
    svnames '(osmode cmdecho plinewid blipmode clayer)
    svvals (mapcar 'getvar svnames)
  ); setq
  (mapcar 'setvar svnames '(0 0 0)); turn off Osnap, command echoing, Pline width to 0

  (initget 1 "Existing")
  (setq ptA1 (getpoint "First Line's start point [or select Existing lines]: "))
  (if (listp ptA1); if User picked a point
    (progn ; then
      (initget 1)
      (setq ptA2 (getpoint ptA1 "First Line's end point: "))
      (initget 1)
      (setq ptB1 (getpoint "Second Line's start point: "))
      (initget 1)
      (setq ptB2 (getpoint ptB1 "Second Line's end point: "))
      (command "_.pline" ptA1 ptA2 "")
      (setq linA (entlast)); [will take points from it later in case in non-World UCS]
      (command "_.pline" ptB1 ptB2 "")
      (setq linB (entlast))
    ); progn
    (progn ; else [if User typed E]
      (foreach ind '("A" "B")
        (while
          (not
            (and
              (set (var ind) (car (entsel (strcat "\nSelect line " ind ": ")))); linA or linB
              (setq edata (entget (ev ind)))
              (wcmatch (setq etype (cdr (assoc 0 edata))) "LINE,*POLYLINE")
              (if (= etype "LINE") T (= (vlax-curve-getEndParam (ev ind)) 1)); single segment
              (cond ; not arc segment
                ((= (cdr (assoc 100 (reverse edata))) "AcDb3dPolyline"))
                ((= etype "LWPOLYLINE") (= (cdr (assoc 42 edata)) 0.0))
                ((= etype "POLYLINE") (= (cdr (assoc 42 (entget (entnext (ev ind))))) 0.0))
                (T) ; for Line
              ); if
            ); and
          ); not
          (prompt "\nNothing selected, or not a Line or single-line-segment Polyline.")
        ); while
        (redraw (ev ind) 3); highlight
      ); foreach
      (setvar 'clayer (cdr (assoc 8 edata)))
    ); progn -- else
  ); if [pick point vs. select Existing lines]

  (setq
    ptA1 (vlax-curve-getStartPoint linA)
    ptA2 (vlax-curve-getEndPoint linA)
    ptB1 (vlax-curve-getStartPoint linB)
    ptB2 (vlax-curve-getEndPoint linB)
  ); setq
  (if
    (inters ; if it would make 'butterfly' lines in 2D view,
      (list (car ptA1) (cadr ptA1) 0)
      (list (car ptB1) (cadr ptB1) 0)
      (list (car ptA2) (cadr ptA2) 0)
      (list (car ptB2) (cadr ptB2) 0)
    ); inters
    (setq ptB1 ptB2 ptB2 (vlax-curve-getStartPoint linB)); reverse direction for line B
  ); if

  (initget 7); no Enter, no zero, no negative
  (setq
    parts (getint "\nDivide intervening space into how many equal segments? ")
    partno 1
    delta1 (mapcar '- ptB1 ptA1)
    delta2 (mapcar '- ptB2 ptA2)
    inc1 (mapcar '/ delta1 (list parts parts parts))
    inc2 (mapcar '/ delta2 (list parts parts parts))
  ); setq

  (redraw linA 4) (redraw linB 4); un-highlight
  (setvar 'blipmode 0)
  (setq partno 1)
  (while (< partno parts)
    (command "_.pline"
      (trans (mapcar '+ ptA1 (mapcar '* inc1 (list partno partno partno))) 0 1)
      (trans (mapcar '+ ptA2 (mapcar '* inc2 (list partno partno partno))) 0 1)
      ""
    ); command
    (setq partno (1+ partno))
  ); while
  (mapcar 'setvar svnames svvals); reset
  (vla-endundomark doc)
  (princ)
); defun
(prompt "Type SLB to Split Lines Between lines defined by 4 points or selected.")
Kent Cooper, AIA
0 Likes
Message 22 of 49

Anonymous
Not applicable

Hi Kent,

 

Lightly tested and it works good. Is there a possibility to get the resulting lines fall on the current layer? if it is not lot of work. Right now it is falling in the layer of the last line selected. If it is lot of work, I do not want to trouble you.

 

Regards,

 

VM

0 Likes
Message 23 of 49

Ranjit_Singh
Advisor
Advisor

You are right it does not consider UCS changes. Also, the flip option was only added in case the lines are to be interpolated between diagonally opposite points. Not that you would ever need it for score lines. I also added division on real numbers, say 2.6  spaces, for instance, again not very useful for your purpose but I was just having a little too much fun writing this program.

0 Likes
Message 24 of 49

Anonymous
Not applicable

Ha ha, Thanks Ranjit.

 

You have a good feature there, including the real numbers for division.

And thanks for the clarification on the option to Flip Lines.

 

Regards,

 

VM

0 Likes
Message 25 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... Is there a possibility to get the resulting lines fall on the current layer? if it is not lot of work. ....


Here ya go -- I just removed clayer from the svnames list, and the (setvar 'clayer ...  line that was taking it to the Layer of a selected object [and the comment about that in the top notes].

 

I wish they hadn't removed the Spoiler capability, so these would take up so much vertical space on the webpage [I guess I could put it into a file and attach that], but here we go....

 

;|
SplitBetween.lsp, to draw Polylines between four selected points, or take
selection of two existing Lines or single-line-segment Polylines, and
draw subdividing Polylines between and paralleling them, or "splaying"
between them if not parallel.  Works in 2D or 3D, and in any UCS.
Draws on current Layer.
Accounts for lines drawn in opposite directions, by reading second line
the other way; if lines are not co-planar, decides whether to do so on
the basis of 2D view in current Coordinate System. Kent Cooper, last edited 21 December 2016 |; (defun C:SLB ; = Split Lines Between (/ *error* var ev doc svnames svvals ptA1 ptA2 ptB1 ptB2 linA linB edata parts partno delta1 delta2 inc1 inc2) (defun *error* (errmsg) (if (wcmatch errmsg "Function cancelled,quit / exit abort,console break") (princ (strcat "\nError: " errmsg)) ); if (mapcar 'setvar svnames svvals); reset (vla-endundomark doc) (princ) ); defun -- *error* (defun var (ltr); build variable name (read (strcat "lin" ltr)) ); defun -- var (defun ev (ltr); get contents of variable name (eval (var ltr)) ); defun -- ev (vla-startundomark (setq doc (vla-get-activedocument (vlax-get-acad-object)))) (setq ; System Variable saving/resetting without separate variables for each: svnames '(osmode cmdecho plinewid blipmode) svvals (mapcar 'getvar svnames) ); setq (mapcar 'setvar svnames '(0 0 0)); turn off Osnap, command echoing, Pline width to 0 (initget 1 "Existing") (setq ptA1 (getpoint "First Line's start point [or select Existing lines]: ")) (if (listp ptA1); if User picked a point (progn ; then (initget 1) (setq ptA2 (getpoint ptA1 "First Line's end point: ")) (initget 1) (setq ptB1 (getpoint "Second Line's start point: ")) (initget 1) (setq ptB2 (getpoint ptB1 "Second Line's end point: ")) (command "_.pline" ptA1 ptA2 "") (setq linA (entlast)); [will take points from it later in case in non-World UCS] (command "_.pline" ptB1 ptB2 "") (setq linB (entlast)) ); progn (progn ; else [if User typed E] (foreach ind '("A" "B") (while (not (and (set (var ind) (car (entsel (strcat "\nSelect line " ind ": ")))); linA or linB (setq edata (entget (ev ind))) (wcmatch (setq etype (cdr (assoc 0 edata))) "LINE,*POLYLINE") (if (= etype "LINE") T (= (vlax-curve-getEndParam (ev ind)) 1)); single segment (cond ; not arc segment ((= (cdr (assoc 100 (reverse edata))) "AcDb3dPolyline")) ((= etype "LWPOLYLINE") (= (cdr (assoc 42 edata)) 0.0)) ((= etype "POLYLINE") (= (cdr (assoc 42 (entget (entnext (ev ind))))) 0.0)) (T) ; for Line ); if ); and ); not (prompt "\nNothing selected, or not a Line or single-line-segment Polyline.") ); while (redraw (ev ind) 3); highlight ); foreach ); progn -- else ); if [pick point vs. select Existing lines] (setq ptA1 (vlax-curve-getStartPoint linA) ptA2 (vlax-curve-getEndPoint linA) ptB1 (vlax-curve-getStartPoint linB) ptB2 (vlax-curve-getEndPoint linB) ); setq (if (inters ; if it would make 'butterfly' lines in 2D view, (list (car ptA1) (cadr ptA1) 0) (list (car ptB1) (cadr ptB1) 0) (list (car ptA2) (cadr ptA2) 0) (list (car ptB2) (cadr ptB2) 0) ); inters (setq ptB1 ptB2 ptB2 (vlax-curve-getStartPoint linB)); reverse direction for line B ); if (initget 7); no Enter, no zero, no negative (setq parts (getint "\nDivide intervening space into how many equal segments? ") partno 1 delta1 (mapcar '- ptB1 ptA1) delta2 (mapcar '- ptB2 ptA2) inc1 (mapcar '/ delta1 (list parts parts parts)) inc2 (mapcar '/ delta2 (list parts parts parts)) ); setq (redraw linA 4) (redraw linB 4); un-highlight (setvar 'blipmode 0) (setq partno 1) (while (< partno parts) (command "_.pline" (trans (mapcar '+ ptA1 (mapcar '* inc1 (list partno partno partno))) 0 1) (trans (mapcar '+ ptA2 (mapcar '* inc2 (list partno partno partno))) 0 1) "" ); command (setq partno (1+ partno)) ); while (mapcar 'setvar svnames svvals); reset (vla-endundomark doc) (princ) ); defun (prompt "Type SLB to Split Lines Between lines defined by 4 points or selected.")
Kent Cooper, AIA
0 Likes
Message 26 of 49

Anonymous
Not applicable

Hi Kent,

 

Amazing!!! all working fine and the way exactly I wanted. Thank you for this wonderful effort and the desired outcome. Will check it out more during holidays and let you know the feedback. I am planning to give it to few of my colleagues for testing (with due credit to you, of course). Hopefully I can give you more real life feedback in new year.

 

Thanks for making our life a lot easier...

 

Once again merry Christmas and Happy New Year 2017.

 

Regards,

 

VM

0 Likes
Message 27 of 49

Anonymous
Not applicable

Hi, Kent

 

Thanks for your efforts. I just tried with your code, but i have an issue of undefined "vla-endundomark"
I can't find the solution of the issue anywhere. Would you help to solve it?

I'm using autocad 2015

 

Thanks again.

0 Likes
Message 28 of 49

braudpat
Mentor
Mentor
Hello

Please add the following instruction at the beginning of the routine:
(vl-load-com)

Regards, Patrice
Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 29 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

... i have an issue of undefined "vla-endundomark".....


Welcome to these Forums!

 

And thanks to @braudpat for supplying the answer.  I have things that do that (vl-load-com) thing for me whenever I open AutoCAD, so routines that use (vl...) functions always work for me even if I forget to include that in them.  I try to remember when posting things here, but don't always....

Kent Cooper, AIA
0 Likes
Message 30 of 49

john.uhden
Mentor
Mentor

I was hoping to see it draw a somewhat concentric/parallel polyline between two wavy contours, but that would be a trick and a half.  IMHO it's not even worth trying, unless one used a gazillion vertices.  Better to just do it by eye.  What power is a gazillion anyway?

John F. Uhden

0 Likes
Message 31 of 49

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

I was hoping to see it draw a somewhat concentric/parallel polyline between two wavy contours, but that would be a trick and a half. ....


There are things out there along those [sp]lines, such as SplineAverage.lsp, on this thread.  In that case, it does require the Splines in question [as many as you want] to have the same number of fit points, but there are definitely limitations [read the whole thread].  And using a gazillion vertices [or as many as you feel the need for to get the accuracy you need] is the idea behind PathAverage.lsp, here, which is limited to averaging two paths, though they can be of a variety of entity types, even different from each other.

Kent Cooper, AIA
0 Likes
Message 32 of 49

Anonymous
Not applicable

This Lisp is great. Is it possible to change it / adjust it so that I can switch object snap on and off in the middle of the comand? At the moment it is a little problematic. (Disclaimer: I know nothing about LISP-Programming, I just like using them when the Autocad commands don't exist...)

 

Cheers,

 

Jack 

0 Likes
Message 33 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

This Lisp is great. Is it possible to change it / adjust it so that I can switch object snap on and off in the middle of the comand? ....


Good idea.  Updated version attached, with turning off of Osnap moved to after  selections of points or objects, before drawing of new Lines.

 

It's the one that draws Lines, but you can adjust it to draw Polylines instead, and to deal with width if necessary, as instructed in earlier Posts.

Kent Cooper, AIA
Message 34 of 49

Anonymous
Not applicable

Hi,

 

I am looking for exactly that kind of tool. I use AutoCAD 2014 for 2D drawings using lines and polylines. When I enter "SLB" after loading the code nothing happens.

 

I also found this: http://people.fsv.cvut.cz/www/chourpav/Lisp/Chapter%206.htm

But when I enter the first point on the parallel line (pt3) then ACAD returns "nil". It also turns off all Osnap modes while leaving Osnap on.

 

Hope you can help me out.

0 Likes
Message 35 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... When I enter "SLB" after loading the code nothing happens. ....


 

It works for me, in Acad2004 and 2016.  You don't get a prompt sequence like this?

 

Command: SLB
First Line's start point [or select Existing lines]: E
Select line A: {did so}
Select line B: {did so}
Divide intervening space into how many equal segments? 4

 

[It would be different if I picked a point first.]  No message(s) or anything?

Kent Cooper, AIA
0 Likes
Message 36 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

I also found this: http://people.fsv.cvut.cz/www/chourpav/Lisp/Chapter%206.htm

But when I enter the first point on the parallel line (pt3) then ACAD returns "nil". It also turns off all Osnap modes while leaving Osnap on.

....


 

Apart from the nil return, does it do the Breaking and draw the Lines across?  The last thing in that routine is a (command) function, and that always returns nil, so if it performs the rest, you can ignore the nil return.  This is why you see:

 

  (princ)

 

before the final closing right parenthesis in many routines -- it makes them "exit quietly," suppressing that nil return.

 

The Osnap thing is easily fixed -- you'll find countless examples of routines in these Forums that save its value first, do their thing, and restore that value.  That can be added if the code otherwise does what you want.

Kent Cooper, AIA
0 Likes
Message 37 of 49

Anonymous
Not applicable

Thank you for your quick answer.

Yes, nothing happens when I enter "SLB", no prompts.

 

With the other routine I can enter 3 points ( 2 on one line and the third perpendicular to the first one on the parallel line), then the dynamic input line next to the cursor flickers and returns "nil".

 

Of course I can first trim the walls and then copy windows and doors into the opening. My apm isn't something to brag about, so it might work faster if the lines from the walls could "adjust" to the placed windows.

0 Likes
Message 38 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

... I can enter 3 points ..., then the dynamic input line next to the cursor flickers and returns "nil".

....


 

Stab-in-the-dark here -- might it have something to do with dynamic input and routines written before it existed?  Try turning it off [F12] and running the commands again.

Kent Cooper, AIA
0 Likes
Message 39 of 49

john.uhden
Mentor
Mentor

I sort of think this exercise was all a waste of time.  You're not designing a nuclear reactor, but just a concrete construction joint.  Jusr  eyeball where the additional joints should go.  The contractor is just going to put them where he feels like anyway, if he adds them at all.

John F. Uhden

Message 40 of 49

barry2104
Collaborator
Collaborator

is it possible to extend this Lisp to be able to pick two curved polylines (e.g. two S-curves which run alongside eachother but not necessarily parallel to one another, but start and finish around the same chainage) and get the curved "midline" as a (polyline or likely rather spline) Output?

Or is that geometrically/lisply impossible?

Even if it was to spit out something that had a say 20-segment (straight segmented) polyline Output instead of a new Doublecurve/S-Curve, that would help me too (but less than perfect).

 

Here an example - i have two Magenta S-Curves (polylines) and Need to generate the yellow midline, be it as a spline or multisegmented polyline (here drawn by Hand as a rough multisegmented polyline)

Unbenannt.JPG

Running AutoCAD Architecture 2020, in German
0 Likes