Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Lisp to draw line between two lines - dividing space equally

48 REPLIES 48
SOLVED
Reply
Message 1 of 49
Anonymous
16187 Views, 48 Replies

Lisp to draw line between two lines - dividing space equally

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

Tags (1)
48 REPLIES 48
Message 2 of 49
Ranjit_Singh2
in reply to: Anonymous


@Anonymous wrote:

Hi all,..................2 polylines /lines ( Parallel or on parallel). I am using.............. I assume you mean parallel or not parallel


If the two lines selected are not parallel what is your criteria to divide the space? use the space between mid point of both entities? And if they are not parallel which one do you want to use to divide the space? Explain with a sketch if possible.
Message 3 of 49
Anonymous
in reply to: Ranjit_Singh2

Hi Ranjith,

 

Sorry for the typo: I actually meant, non parallel.

 

If it is not parallel, the criteria should be drawing a line/s to divide the space between the endpoints of original lines, which already does with the existing lisp, LineBetween - LB to input in the AutoCAD command line to initiate the lisp.. I think the best starting point would be taking that lisp and improve further. I can attach the lisp which I am currently using - with due respect and credit to the original creator.  The limitations which I noticed is it will not work when the UCS is rotated in the model space, the line  created is a LINE not a polyline even though the original lines selected are polylines. The third big limitation is it should have the flexibility to accept a user input just to ask the space should be divided into how many spaces, which right now is dividing it into two- which practically can be used if the number of spaces the user wants are even numbers. 

 

Please let me know if I made myself clear or not.

 

Thanks for your help.

 

Regards,

 

VM

Message 4 of 49
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... 

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


As a start, try first drawing Lines between the ends of the 2 you mean, and using Ladder.lsp, available here, to draw Lines as "rungs" across the new ones [using the Select option, and, when it asks for selection, selecting the Lines you drew across the ends of the ones you want divided between].  Yes, so far it draws, and accepts for selection, only Lines, but you get to say how many, and it works in 3D and across non-parallel Lines.  If that looks like it's close to what you want, it would be easy enough to convert it to work from a selection of two Lines or Polyline line segments that you want the new ones splitting the distance between, and to draw Polylines if that's what you select.

 

[I assume you're talking about individual Polyline segments, not splitting the meandering space between multi-segment Polylines.  If you want the latter, I think there are some routines that you can find by Searching with terms about intermediate contour lines.  Such a routine might do exactly what you want already.]

Kent Cooper, AIA
Message 5 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

Hope you had a good weekend,

 

Sorry for being late in replying. Monday morning....Last week before Christmas....Year end deadlines...

 

So I tried the Ladder.lsp as you suggested. Seems very promising to me in the aspect that it asks for input from the user, but lacking in clarity that it is not necessarily doing an offset of the end points of the selected lines  - meaning the lines created are not consistent for my kind of purpose, when the selecting lines are not equal length/ are non parallel and things likes that. It seems it does not want to select  the line, if I am selecting a polyline. It does not work if the UCS is rotated. The resulting lines will be created somewhere far away, which is same with LINEBETWEEN lisp as well.

 

So if we can some how combine both the codes - it will work - we still need to figure out why it is not selecting the polylines( in the case of (LADDER) and how we can incorporate the UCS rotation 9 In the case of both, LADDER and LINEBETWEEN)

 

I am attaching a sample drawing explaining my objective and the work flow for your review and comment

 

Regards,

VM

Message 6 of 49
john.uhden
in reply to: Anonymous

My %&*!@$ computer failed to send my lengthy response.  I'll try it again, a lot shorter.

 

Are you looking to create an exact "tweener?"  I don't think that can happen unless one of the polylines was created by offsetting the other, in which case the tweener can be created simply by offsetting one of the polylines by a fraction of the original offset distance.  Otherwise, my mind is picturing a pile of toothpicks randomly dropped on the floor like in "The Rainman."

John F. Uhden

Message 7 of 49
Kent1Cooper
in reply to: john.uhden


@john.uhden wrote:

.... 

Are you looking to create an exact "tweener?"  ....


I think they want to do this -- selecting the red vertical lines that have cut-off arrows pointing to them at the ends [Polylines in their drawing, though I see no advantage to that over ordinary Lines] and having the routine draw in the yellow ones [which I did by drawing temporary horizontal Lines between the ends of the red ones, lying along the cyan perimeter, and using Ladder.lsp asking for four divisions].  @Anonymous, is this correct?

 

ConcJoints.PNG

Kent Cooper, AIA
Message 8 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

You got it exactly correct. That is all I want. The other bells and whistles like UCS,  can wait until if someone can figure out the logic to get this done.

 

Thanks a lot guys for your support.

 

Regards,

 

Message 9 of 49
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... we still need to figure out why it is not selecting the polylines( in the case of (LADDER) ....


Nothing to figure out there -- it was written specifically to work with Lines [that is, LINE entities specifically] only, because that was the situation for which it was requested.   What looks like a "line" visually speaking is not always the same as a Line entity [I always capitalize entity types, so the difference between "line" and "Line" is meaningful in my Posts] in AutoCAD, and the difference matters.  It will be easy enough to adjust the code to accept Polylines, as well as for the other things you mention -- I just have to get around to it, but I have it in mind [see your seasonal considerations...].

 

I would ask a question:  Is there some reason that those red [in your sample drawing] "lines" are Polylines, rather than ordinary Lines?  I don't see any advantage to doing them that way, but they use more memory than the equivalent Lines would.  If they are going to be Polylines, can I assume that they will always and only be single-line-segment Polylines?  It could make a difference to how a routine would work with them.

Kent Cooper, AIA
Message 10 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

Sorry guys, I was not aware that polylines take more memory technically. As far as using polylines it is just an office practice. I think I can change that if necessary ( for concrete work ). I think the biggest reason being we do lot of organic designs so to do revisions and adjustments, we are finding polylines are much better. That is why the red lines drawn as polylines. But if we are using LIneBetween lisp, the resulting lines are "Lines". You can see them in the left side of the sample drawing I attached before ( the Green lines). Those are made with LineBetween lisp.

 

Hope this clarifies your query, Kent.

 

Thanks again,

 

VM

Message 11 of 49
Anonymous
in reply to: Anonymous

Oh By the way, take your time, Enjoy the season.

 

VM

Message 12 of 49
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

....  It will be easy enough to adjust the code to accept Polylines, as well as for the other things you mention -- I just have to get around to it....


Try this out [lightly tested].  Note that you can specify the points without having the Lines/Polylines already there, so in your sample drawing, you don't need those red section boundaries already in place -- this can draw them for you.  But when they are already in place, you can choose the Existing-line-selection option.

 

;|
SplitBetween.lsp, to draw Lines between four selected points, or take
selection of two existing Lines or single-line-segment Polylines, and
draw subdividing Lines between and paralleling them or "splaying"
between them if not parallel.  Works in 3D, and in any UCS.
If selecting existing lines, draws subdividing Lines on Layer of second
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, 20 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 blipmode clayer)
    svvals (mapcar 'getvar svnames)
  ); setq
  (mapcar 'setvar svnames '(0 0)); turn off Osnap, command echoing

  (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 "_.line" ptA1 ptA2 "")
      (setq linA (entlast)); [will take points from it later in case in non-World UCS]
      (command "_.line" 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 "_.line"
      (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
Message 13 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

WOW Man! You are a genius!

 

I tried the code out. It works perfect. I tried even with non parallel, different lengths of original lines, and even rotating the UCS. Everything works perfect.

Another thing I noticed is even if the current layer is different from the Lines/ Polylines to be selected,  the created lines are in the sale layer of the selected lines - not in the current layer, which is awesome. This code is so versatile.

 

I will ask my colleagues to check this out and will come back to you if there are any issues/ concerns. If some other people who has more experience than me check this code out it would be great as well.

 

For now I am going to accept this as a solution, and thanks a TON for t your effort and help, during a very busy time schedule.

 

Regards,

 

VM

 

Message 14 of 49
Ranjit_Singh2
in reply to: Anonymous

Here is another version.

(defun c:somefunc  (/ f curlayer curosmode ent exit a b spaces spaces1 testlst vlaobj1 vlaobj2 x y z)
  (while (setq vlaObj1   (vlax-ename->vla-object (setq ent (car (entsel))))
               vlaObj2   (vlax-ename->vla-object (car (entsel)))
               curlayer  (getvar 'clayer)
               curosmode (getvar 'osmode)
               spaces1   (getreal "\nEnter number of spaces: "))
    (cond ((or (minusp spaces1) (< spaces1 1)) "Spaces should be greater than 1")
          (T
           (setvar 'clayer (cdr (assoc 8 (entget ent))))
           (setvar 'osmode 16384)
           (setq spaces  (test spaces1 ())
                 testlst (vl-sort
                           (apply
                             'append
                             (mapcar
                               '(lambda (y)
                                  (mapcar '(lambda (x) (append (append (list (distance x y)) (list x)) (list y)))
                                          (list (vlax-curve-getStartPoint vlaObj1)
                                                (vlax-curve-getEndPoint vlaObj1))))
                               (list (vlax-curve-getStartPoint vlaObj2)
                                     (vlax-curve-getEndPoint vlaObj2))))
                           '(lambda (x y) (< (car x) (car y))))
                 a       (cdar testlst)
                 b       (cdr (apply 'append
                                     (car (mapcar '(lambda (y)
                                                     (mapcar '(lambda (x)
                                                                (if (not (or (equal (cadar testlst) (cadr x) y)
                                                                             (equal (caddar testlst) (caddr x) y)
                                                                             (equal (cadar testlst) (caddr x) y)
                                                                             (equal (caddar testlst) (cadr x) y)))
                                                                  x))
                                                             testlst))
                                                  (list 1e-15))))))
           (command "._undo" "_begin")
           (test2 a b spaces1 spaces)
           (command "._undo" "_end")
           (initget "Yes No")
           (setq f (cond ((getkword "\nFLip lines [Yes/No] <No>: "))
                         ("No")))
           (cond ((wcmatch f "Yes,Y")
                  (command "._undo" 1)
                  (setq z (last a))
                  (setq a (cons (car a) (cdr b)))
                  (setq b (cons (car b) (list z)))
                  (test2 a b spaces1 spaces))
                 (T ())))))
  (setvar 'clayer curlayer)
  (setvar 'osmode curosmode))

(defun test  (x y)
  (cond ((< x 1) y)
        (T (test (fix (- x 1)) (cons (fix x) y)))))

(defun test2  (a b c d)
  (mapcar '(lambda (x y) (command-s "._pline" x y ""))
          (mapcar '(lambda (x) (polar (car a) (angle (car a) (cadr a)) (* (/ (distance (car a) (cadr a)) c) x)))
                  (if (not (zerop (rem c (fix c))))
                    d
                    (cdr (reverse d))))
          (mapcar '(lambda (x) (polar (car b) (angle (car b) (cadr b)) (* (/ (distance (car b) (cadr b)) c) x)))
                  (if (not (zerop (rem c (fix c))))
                    d
                    (cdr (reverse d))))))
Message 15 of 49
Anonymous
in reply to: Ranjit_Singh2

Hi Ranjit,

 

Thanks for the code. I will try it out tomorrow. Middle of a deadline....

 

Will reply soon.

 

Regards,

VM

Message 16 of 49
Anonymous
in reply to: Anonymous

Hi Ranjit,

 

I tried your lisp. I have a question.

 

1. What does the flip lines option do? it makes the created lines go shorter inconsistently ( as far as I notice, I may not be true, since I am not properly following your logic here ). Please explain.

 

Pros:

 

1. all the resulting lines are polylines, irrespective of the original lines - good in my kind of workflow. But in the case of Kent's Lisp (SplitBetween), all the resulting lines were 'Line' not 'Polyline'

 

I guess Kent assured in previous replies that it is not a big deal and he can fix it easily. If not I can select all the 'Lines' and convert it into a 'Polyline' either using a lisp or PEDIT > select MULTIPLE command or MPEDIT command.

 

Cons:

 

1. In my testing, I found it is not working when the lines are drawn after rotating the UCS. but it is working perfectly when Kent's Lisp (SplitBetween) is used.

 

These are my findings as of now,

 

Thanks for the effort Ranjit

 

Regards,

 

VM

 

 

 

.

 

 

Message 17 of 49
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... 

1. all the resulting lines are polylines, irrespective of the original lines - good in my kind of workflow. But in the case of Kent's Lisp (SplitBetween), all the resulting lines were 'Line' not 'Polyline'

 

I guess Kent assured in previous replies that it is not a big deal and he can fix it easily. If not I can select all the 'Lines' and convert it into a 'Polyline' either using a lisp or PEDIT > select MULTIPLE command or MPEDIT command.

....


Yes, it can easily be "fixed" if it's really worth it.  The simple way would be to just add the 'p' into the command names:  (command "_.pline" ... in three places.

 

But then you have to consider that there could sometimes be a current Polyline width other than 0 in effect, in which case those Polyline lines will all have that width, unless you also explicitly build the Width option into the Pline commands and force it to zero, or force it ahead of time with (setvar 'plinewid 0) somewhere before the first Pline command occurs.  And then you have to decide whether, if there is a non-0 width set when you start, you would want it to remain in effect after you're done, for other purposes, and therefore need to save its current value and reset it, including in *error* handling.

 

But unless you want them to have width, I am having a hard time imagining what possible benefit there could be to their being Polylines instead of Lines, which is the main reason I built the code to make Lines.  Can you describe what is "good in my kind of workflow" about their being Polylines instead?

Kent Cooper, AIA
Message 18 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

Thanks for more indepth explanation on coding, really appreciate that.

 

Kent, that requirement is minor, considering the fact that you dealt with 90-95 percent of this work flow issue. Converting the Line to Polyline is very minor and I can do it in one step ( using another lisp or MPEDIT). So it is not necessary to revise the code, after you explained the other factors to be considered if we are changing the resulting Lines to Polylines instead. 

 

Since you asked, about the benefit in my kind of work flow, I like to work with polylines rather than lines since the concrete line work is mostly organic in our design ( Landscape Architecture) so if I want to make the side walk/ concrete pattern/ saw cut lines/ sandblast areas meandering - I want to do it with Polylines rather than Lines. That is the only benefit which as I said is only minor.

 

Kent, thanks again for all the help.

 

You have a Merry Christmas and a very prosperous 2017.

 

Regards,

 

VM

 

 

 

Message 19 of 49
Kent1Cooper
in reply to: Anonymous


@Anonymous wrote:

.... Converting the Line to Polyline is very minor and I can do it in one step ( using another lisp or MPEDIT). So it is not necessary to revise the code, after you explained the other factors to be considered if we are changing the resulting Lines to Polylines instead. 

.... 


Don't bother with that extra step.  You can deal with all of my concerns by adding the 'p' into the command names as described before, and doing this:

 

....
(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, set Polyline width to 0 ....

 

That's one of the nice things about this list-based way of saving and resetting System Variables -- you can just add more into the list, in that one place, without adding any variables, or any additional saving or resetting functions.

 

Make sure you put it in the list as one of the first three variable names [it could be earlier in it than shown above], because those three 0's in the last code line above are going to set that value into the first three variables in the list -- it will stop mapping when either list ends.  The other two variables are changed later [and 0 would be an invalid value for CLAYER anyway].

Kent Cooper, AIA
Message 20 of 49
Anonymous
in reply to: Kent1Cooper

Hi Kent,

 

That was too much for a person know practically nothing about coding/ programing. But I knod of understand the logic/ explanation, if not fully. 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). Sorry Kent, I know it is little bit spoon feeding, but it is a reality that I know nothing about Lisp programing.

 

Regards,

 

VM

 

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report