Lisp routine for special divide command

Lisp routine for special divide command

Mark.E.Brinkman
Explorer Explorer
3,620 Views
22 Replies
Message 1 of 23

Lisp routine for special divide command

Mark.E.Brinkman
Explorer
Explorer

Need a lisp routine that would evenly divide a line into => 9', break the line, and would apply points at the ends of each segment. If the (=>9') max length could be adjustable that would be even better. Ddevideoing this manually is time-consuming.

 

Thank you in advance!

 

 

0 Likes
3,621 Views
22 Replies
Replies (22)
Message 2 of 23

Kent1Cooper
Consultant
Consultant

You may be able to use SubDivide.lsp with its SD command, >here<.  See the comments at the top, particularly about adding the Point objects.  HOWEVER, it doesn't do a fixed segment length, but either a quantity of segments you specify or a maximum segment length you specify [it calculates the minimum number of segments so each will not exceed the maximum length].  Either way, all resulting segments will be the same length as each other.  If you want a fixed segment length such as 9', you will usually end up with a very-different-length segment left over at the end -- if that's appropriate, the routine can be adjusted easily to work that way.

Kent Cooper, AIA
0 Likes
Message 3 of 23

john.uhden
Mentor
Mentor

@Mark.E.Brinkman 

As @Kent1Cooper pointed out, his solution is a special DIVIDE command, but dividing doesn't provide for specific distances as does the MEASURE command.  And the MEASURE command leaves the entire remainder at the end.  Maybe you would prefer to split the remainder evenly between the start and the end.

For example, a 40 unit line cut into 9 unit lengths could make 4 segments with one 2 unit segment at each end.    --|---------|---------|---------|---------|--  (40/9 = 4 rem 4)

OR, maybe if the remainder is small, you want to add 1/2 of it to the the first and last segments.  You would get to enter the maximum remainder.  I am implying that maybe you want a tolerance so that there is no waste.  We don't want you throwing away little pieces of platinum bars.

You said you wanted to break the line at each point AND place an AutoCAD Point object at each break?  Might the lines also be polylines and maybe with arced segments as well?  It could make a difference as to the method to be used in the code, not that it would affect you or the results.

And I might as well ask now... do you want to process not just one line at a time but perhaps a selection of lines?  Might you want a filter to select lines of only certain layers or colors or linetypes or thicknesses or elevations or widths (polylines) or ltscales or lengths or combinations thereof?  Or inside or outside some boundary?  Maybe different filters for each day of the week or for each username or for whether the day of the year is odd or even or whether it's morning or afternoon or night?  I'm not sure if we can filter based on the outside temperature or time 'til high tide (if you're in a coastal area).  We certainly can't filter for any SSN without invading your privacy.

John F. Uhden

Message 4 of 23

calderg1000
Mentor
Mentor

Regards @Mark.E.Brinkman 

If you don't mind having some waste at the beginning or end of the line, here's something quick

 

 

 

 

(defun c:d9 (/ s p1 p2 sp pt)
  (setvar 'pdmode 3)
  (setvar 'pdsize 0.2)
  (if
    (setq s (car (entsel "\nSelect Line Object:")))
     (progn
       (vl-cmdf "_measure" s 9)
       (vla-getboundingbox (vlax-ename->vla-object s) 'p1 'p2)
       (setq p1 (vlax-safearray->list p1)
             p2 (vlax-safearray->list p2)
       )
       (setq sp (ssget "_c" p1 p2 '((0 . "point"))))
       (repeat (setq i (sslength sp))
         (setq
           pt (cdr (assoc 10 (entget (setq np (ssname sp (setq i (1- i)))))))
         )
         (vl-cmdf "_breakatpoint" s "near" pt)
         (setq s (entlast))
       )
     )
  )
)

 

 

 

 

 


Carlos Calderon G
EESignature
>Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

0 Likes
Message 5 of 23

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

.... the MEASURE command leaves the entire remainder at the end.  Maybe you would prefer to split the remainder evenly between the start and the end.

.....


That is one of the options in the MEA+ command, part of DivideMeasurePlus.lsp, >here<.  It doesn't break the path object into pieces, but a version could be made to do so [or a version of SubDivide.lsp could be made with fixed-length pieces and the option to use that kind of break-location positioning].

EDIT:  In such a case, there's another possible option.  Should the evenly-divided remainder pieces be minimal in length, using the largest available number of specified-length pieces?  [That's what MEA+ does.]  Or should it use one fewer specified-length pieces, so that the evenly-divided remainder pieces are closer to the specified length?

In other words, if [for example] your specified length is 10, and an object is 36 units long, should it divide it into pieces of lengths:
3 10 10 10 3

or

8 10 10 8

?

Kent Cooper, AIA
Message 6 of 23

john.uhden
Mentor
Mentor

Hey, Cal,

I like the approach.  And I didn't know there was a "BREAKPOINT" command.  Thanks!

The only thing different I would have done is to get the last entity before the MEASURE and then get each point by entnexting and consing to a list.  Ya never know if there might be other points within that boundingbox that would screw up the breaks.

John F. Uhden

0 Likes
Message 7 of 23

Mark.E.Brinkman
Explorer
Explorer

Maybe you would prefer to split the remainder evenly between the start and the end. (Yes, that would be the intent, but the 40'/5 segments (need to keep the segments @ 9' or less) and equally spaced. this would work out to 8'. No remainder). 

For example, a 40 unit line cut into 9 unit lengths could make 4 segments with one 2 unit segment at each end.    --|---------|---------|---------|---------|--  (40/9 = 4 rem 4)

OR, maybe if the remainder is small, you want to add 1/2 of it to the first and last segments.  You would get to enter the maximum remainder.  I am implying that maybe you want a tolerance so that there is no waste. (Correct, no waste)  We don't want you throwing away little pieces of platinum bars.

You said you wanted to break the line at each point AND place an AutoCAD Point object at each break? (Yes, eventually I will work in a part number for each piece and the side the part number is on will determine the finish side). Might the lines also be polylines and maybe with arced segments as well? (Yes, this will apply to arcs also) It could make a difference as to the method to be used in the code, not that it would affect you or the results.

And I might as well ask now... do you want to process not just one line at a time but perhaps a selection of lines? (Yes) Might you want a filter to select lines of only certain layers or colors or linetypes or thicknesses or elevations or widths (polylines) or ltscales or lengths or combinations thereof? (Yes)  Or inside or outside some boundary? (Yes)  Maybe different filters for each day of the week or for each username or for whether the day of the year is odd or even or whether it's morning or afternoon or night?  I'm not sure if we can filter based on the outside temperature or time 'til high tide (if you're in a coastal area).  We certainly can't filter for any SSN without invading your privacy. Sounds like you may have run across this before, 

0 Likes
Message 8 of 23

Kent1Cooper
Consultant
Consultant

@Mark.E.Brinkman wrote:

Maybe you would prefer to split the remainder evenly between the start and the end. (Yes, that would be the intent, but the 40'/5 segments (need to keep the segments @ 9' or less) and equally spaced. this would work out to 8'. No remainder). 

....


Subdivide.lsp [see Message 2] will do exactly that, with the Maximum-segment-length option.  Get into the code and follow the directions for adding the Point objects at the subdivision points, and set a PDMODE System Variable value you like, to see them.

Kent Cooper, AIA
0 Likes
Message 9 of 23

john.uhden
Mentor
Mentor

@Mark.E.Brinkman 

So the 9' isn't sacred?  It's actually 9' or less?

40/5 = 8 is okay?

Is 39/5 = 7.8 okay?

Is 37/5 = 7.4 okay?

  BUT

39/4 = 9.75 is NOT okay?

 

So I gather it would be the longest length <= 9' (with no waste), right?

 

What we have run into before is a lot of "By the way, can you make that work on blah blah blah."

John F. Uhden

0 Likes
Message 10 of 23

Mark.E.Brinkman
Explorer
Explorer

So the 9' isn't sacred?  It's actually 9' or less?

40/5 = 8 is okay? (Correct)

Is 39/5 = 7.8 okay? (Correct)

Is 37/5 = 7.4 okay? (Correct)

  BUT

39/4 = 9.75 is NOT okay? (Not OK)

 

So I gather it would be the longest length <= 9' (with no waste), right? (Yes)

 

What we have run into before is a lot of "By the way, can you make that work on blah blah blah."

0 Likes
Message 11 of 23

Kent1Cooper
Consultant
Consultant

@Mark.E.Brinkman wrote:

So the 9' isn't sacred?  It's actually 9' or less?

40/5 = 8 is okay? (Correct)

Is 39/5 = 7.8 okay? (Correct)

Is 37/5 = 7.4 okay? (Correct)

  BUT

39/4 = 9.75 is NOT okay? (Not OK)

 

So I gather it would be the longest length <= 9' (with no waste), right? (Yes)

....


Further confirmation -- that's exactly what SubDivide.lsp under its Maximum option is designed to do.

Kent Cooper, AIA
0 Likes
Message 12 of 23

john.uhden
Mentor
Mentor

@Mark.E.Brinkman 

Picking up on what @calderg1000 did,

Please try the following (no I haven't made the effort to select multiple curves inside a polyline boundary).

 

(defun c:d9+ (/ *error* vars vals e start end n d dd p plist)
  (gc)
  (vl-load-com)
  (defun *error* (error)
     (mapcar 'setvar vars vals)
     (vla-endundomark *doc*)
     (cond
       (not error)
       ((wcmatch (strcase error) "*CANCEL*,*QUIT*")
         (vl-exit-with-error "\r                                              ")
       )
       (1 (vl-exit-with-error (strcat "\r*ERROR*: " error)))
     )
     (princ)
  )
  ;;------------------------------------------
  ;; Intitialze drawing and program variables:
  ;;
  (setq *acad* (vlax-get-acad-object))
  (setq *doc* (vlax-get *acad* 'ActiveDocument))
  (vla-endundomark *doc*)
  (vla-startundomark *doc*)
  (setq vars '("cmdecho" "pdmode" "pdsize"))
  (setq vals (mapcar 'getvar vars))
  (mapcar 'setvar vars '(0 3 0.4))
  (if
    (setq e (car (entsel "\nSelect Line/Curve Object:")))
     (progn
       (setq start (vlax-curve-getdistatpoint e (vlax-curve-getstartpoint e)))
       (setq end (vlax-curve-getdistatpoint e (vlax-curve-getendpoint e)))
       (setq n (fix (/ (- end start) 9)))
       (if (> (/ (- end start) n) 9)(setq n (1+ n)))
       (setq dd (/ (- end start) n))
       (setq d start)
       (while (not (equal (setq d (+ d dd)) end 0.01))
         (setq p (vlax-curve-getpointatdist e d))
         (setq plist (cons p plist))
         (entmakex (list '(0 . "POINT")(cons 10 p)))
       )
       (foreach p (reverse plist)
         (vl-cmdf "_.break" e p "@")
         (setq e (entlast))
       )
     )
  )
  (princ (strcat "\nDivided " (rtos (- end start)) " long curve into (" (itoa n) ") " (rtos dd) " long pieces.\n"))
  (*error* nil)
)

 

John F. Uhden

0 Likes
Message 13 of 23

Mark.E.Brinkman
Explorer
Explorer

Freaking awesome! I changed the length to 108 and it works perfectly for 9' on lines and arcs. I will try to add to the lisp by adding the select option for multiple lines and figuring out how to apply to circles and ellipses.

 

Thank you!

 

0 Likes
Message 14 of 23

john.uhden
Mentor
Mentor

This is just slightly better because a while loop let's you keep picking.

BUT, forget about circles and closed ellipses because...

"Cannot break a closed, periodic curve at only one point."

(defun c:d9+ (/ *error* vars vals e start end n d dd p plist)
  (gc)
  (vl-load-com)
  (defun *error* (error)
     (mapcar 'setvar vars vals)
     (vla-endundomark *doc*)
     (cond
       (not error)
       ((wcmatch (strcase error) "*CANCEL*,*QUIT*")
         (vl-exit-with-error "\r                                              ")
       )
       (1 (vl-exit-with-error (strcat "\r*ERROR*: " error)))
     )
     (princ)
  )
  ;;------------------------------------------
  ;; Intitialze drawing and program variables:
  ;;
  (setq *acad* (vlax-get-acad-object))
  (setq *doc* (vlax-get *acad* 'ActiveDocument))
  (vla-endundomark *doc*)
  (vla-startundomark *doc*)
  (setq vars '("cmdecho" "pdmode" "pdsize"))
  (setq vals (mapcar 'getvar vars))
  (mapcar 'setvar vars '(0 3 0.4))
  (while (setq e (car (entsel "\nSelect Line/Curve Object:")))
    (setq plist nil)
    (setq start (vlax-curve-getdistatpoint e (vlax-curve-getstartpoint e)))
    (setq end (vlax-curve-getdistatpoint e (vlax-curve-getendpoint e)))
    (setq n (fix (/ (- end start) 9)))
    (if (> (/ (- end start) n) 9)(setq n (1+ n)))
    (setq dd (/ (- end start) n))
    (setq d start)
    (while (not (equal (setq d (+ d dd)) end 0.1))
      (setq p (vlax-curve-getpointatdist e d))
      (setq plist (cons p plist))
      (entmakex (list '(0 . "POINT")(cons 10 p)))
    )
    (foreach p (reverse plist)
      (vl-cmdf "_.break" e p "@")
      (setq e (entlast))
    )
    (princ (strcat "\nDivided " (rtos (- end start)) " long curve into (" (itoa n) ") " (rtos dd) " long pieces.\n"))
  )
  (*error* nil)
)

 Actually, we could break it but we would lose a piece.  Can you afford to lose 1 inch from an ellipse or circle?  How about 1/4 inch?

John F. Uhden

0 Likes
Message 15 of 23

Kent1Cooper
Consultant
Consultant

@Mark.E.Brinkman wrote:

.... I will try to add to the lisp by adding the select option for multiple lines and figuring out how to apply to circles and ellipses. ....


Have you not yet tried SubDivide.lsp?  It already handles multiple selection, and Circles and Ellipses as well as anything else that Break can be used on [of finite length -- not Rays or Xlines].  Revisit Messages 2, 8 & 11.

Kent Cooper, AIA
0 Likes
Message 16 of 23

john.uhden
Mentor
Mentor

@Mark.E.Brinkman 

i would first try a little of @Kent1Cooper's magic.

But, if you want, I think I have figured out how to handle circles and ellipses.

 

I'm just wondering.  Is the purpose of this to cut figures into lengths that would fit into cardboard boxes, maybe?

If so, we could add a function to tell you the size of the box required for each piece.

It's sorta like my my nesting program for swimming pool liner panels.

John F. Uhden

0 Likes
Message 17 of 23

Mark.E.Brinkman
Explorer
Explorer

No, it is for aluminum profiles.

Imagine a "C" channel and the "C" is curved into an inside or outside radius. The material comes in 10' lengths, when ran through the curving machine 6" inches of each end is disfigured. This is where the 9' max comes from. There is even another part to this, imagine trying to create an "S" shape with the "C" profile and both parts of the "S" has the same radius and are tangent in the middle. I create my parts list manually and it takes a considerable amount of time. Shapes vary, Circles, Ellipses, squares, rectangles, polygons, irregulars,  beans, squiggles, etc.

0 Likes
Message 18 of 23

john.uhden
Mentor
Mentor

@Mark.E.Brinkman ,

So why didn't you just request code to cut 9' out of a 10' length?

Actually, I don't think you need code to cut 6" off each end.

And, so yes, you will be recycling the cut-offs.

John F. Uhden

0 Likes
Message 19 of 23

Mark.E.Brinkman
Explorer
Explorer

For aesthetics, the pieces of each curve need to be exactly the same length. you don't want 5 - 9' pieces and 1 - 2' piece. 

0 Likes
Message 20 of 23

Kent1Cooper
Consultant
Consultant

@Mark.E.Brinkman wrote:

.... The material comes in 10' lengths, when ran through the curving machine 6" inches of each end is disfigured. This is where the 9' max comes from. ....


For that, if they're all separate 10' pieces, you can use the LTM command in LengthenTotalMid.lsp, >here<.  Specify 9' as the length, pick the object(s) [any number of Lines, Arcs, Polylines, Splines, even partial Ellipses], and it will take an equal amount off each end of each object for a resultant length of 9' for each.

Kent Cooper, AIA
0 Likes