help Improving autocad lisp routine

help Improving autocad lisp routine

stevie_alas
Contributor Contributor
1,225 Views
21 Replies
Message 1 of 22

help Improving autocad lisp routine

stevie_alas
Contributor
Contributor

I compiled this lisp using various programs i found online and using ai. This lisp takes a selected closed polyline and offsets the line and then selects everything inside. then it creates a file using wblock and saves it to a folder with a specified name that increases the count by one. context; this is used to quickly save drawings of insulation sheets for cutting on a cnc for precast concrete. 

 

I was wondering if anyone would be able to help me improve this in any way or help solve some of the issues.

 

issues: 

  • you are able to click on empty space and the the lisp will still continue on to the second step.
  • if you press enter without selecting anything on the second step, the counter will still go up. 
  • sometimes selecting a line in the first step will not offset or will offset to the inside rather than outside.
  • some shapes fail, especially deep u shaped pieces. sometimes changing the offset distance to something larger will resolve this, but that is not an ideal solution.

 

improvements:

  • reduce the amount of steps it takes. i would ideally like to select the line and the offset line will be automatically selected and exported in one go. 
  • improve reliability.

 

any input is appreciated! *disclaimer* i am not an autolisp expert and i have no idea what im doing. i just pieced together things i found and used ai and it seemed to work, so please excuse me if this lisp makes the experts cringe!

 

in the zip folder you will find an example dwg, a pdf explaining the command in more detail, and the lisp files. save-drawing-parts-1 offsets by 1". save-drawing-parts-2in offsets by 2".  reset-wblock will reset the file name counter.

 

 

thank you!

0 Likes
1,226 Views
21 Replies
Replies (21)
Message 2 of 22

Kent1Cooper
Consultant
Consultant

Various things I could suggest, and a few questions as a start....

(foreach) applying to a list of only one item is silly -- just use the item directly.  And it's the Offset distance in a command that uses 0,0,0 as the to-which-side pick, but that wouldn't necessarily always be outside any given outline.  I would do something like this, as one way of specifying a to-which-side point that is absolutely guaranteed to be outside:

(command "_.offset" 1 ent (polar (getvar 'extmax) (/ pi 4) 10) "")

The (_pac) function apparently builds a Window-Polygon selection outline by finding points every 100th of the way around an outlining object.  That seems appropriate if the object might be a Circle or an Ellipse or a Polyline containing arc segments or a Spline.  But in your sample drawing everything is Polylines with only line segments.  If that's always the case, their vertices can be used directly, much more simply.  And the (ssget) filter list can be greatly simplified.  Would that always be the situation?  There are numerous routines out there that select everything within a Polyline boundary using its vertices, which works well if it's all line segments.

As for "i would ideally like to select the line and the offset line will be automatically selected," after an Offset command, the result will be (entlast), so it certainly can be automatically selected by the routine.

As for "you are able to click on empty space and the lisp will still continue on to the second step," it can check whether you picked something before continuing, in a few ways.  One would be to give up if you didn't:

(if (setq ent (car (entsel "\nSelect polyline to offset: ")))

  (progn ; then

    .... do its thing ....

  )

  (progn ; else

    (alert "Ya gotta pick something!")

    (quit)

  )

)

It could also check for the kind of thing picked, etc.

Another would be to ask again, until you do:

(while

  (not (setq ent (car (entsel "\nSelect polyline to offset: "))))

)

which could also add a check on the kind of thing picked, etc.

More later, maybe....

Kent Cooper, AIA
0 Likes
Message 3 of 22

john.uhden
Mentor
Mentor

@stevie_alas ,

@Kent1Cooper is a wizard at this kind of thing.

I would probably use the approach of first determining the general direction of the polyline and then using s positive offset for to the right and a negative offset for to the left.

John F. Uhden

0 Likes
Message 4 of 22

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:

.... I would probably use the approach of first determining the general direction of the polyline and then using s positive offset for to the right and a negative offset for to the left.


Yes, but the positive-vs.-negative offset distance approach [instead of the pick-which-side approach] needs the (vla-offset) function, which requires VLA-object conversion first.  And it takes a substantial amount of code to determine whether a closed Polyline's or Spline's drawn order is CW or CCW -- there are multiple threads that get into that.

But given the VLA-object conversion [which sometimes one also wants for other reasons anyway], another approach I have used to get a result on a particular side of a closed object is to use (vla-offset) with a positive distance, compare the areas of the original and the result, and if it went the wrong way, eliminate the result and do it again with the negative distance.

Kent Cooper, AIA
0 Likes
Message 5 of 22

Sea-Haven
Mentor
Mentor
(setq num (vlax-ldata-get "AlanH" "WBLKNUM"))

(vlax-ldata-put "AlanH" "WBLKNUM" num)

@Kent1Cooper yes I use code by you to check CW or CCW. Appreciate that it works well.

 

; Checking if pline is CW or CCW and set to CCW
; Orignal idea  by Kent Cooper, 1 August 2018 Offsetinorout.lsp
; By Alan H July 2020

(defun AH:chkcwccw (ent / objnew area1 area2 obj minpoint maxpoint)
(setq obj (vlax-ename->vla-object ent))
(vla-GetBoundingBox obj 'minpoint 'maxpoint)
(setq pointmin (vlax-safearray->list minpoint))
(setq pointmax (vlax-safearray->list maxpoint))
(setq dist (/ (distance pointmin pointmax) 20.0))
(vla-offset obj dist)
(setq objnew (vlax-ename->vla-object (entlast)))
(setq area1  (vlax-get objnew 'Area))
(vla-delete objnew)
(vla-offset obj (- dist))
(setq objnew (vlax-ename->vla-object (entlast)))
(setq area2  (vlax-get objnew 'Area))
(vla-delete objnew)
(if (> area1 area2)
  (command "Pedit" ent "R" "")
)
(princ)
)

 

It is a defun so speeds up multiple calls. One thing I use Pedit Reverse, as Bricscad does not have a "Reverse" command. Then Vla-offset can be used.with a +ve value.

 

One suggestion, using "USERIX" if in any other code you run changes variables USERXX, then the number will be wrong, I use LDATA which also lives in a dwg you can put & get, the advantage is it's a mini database that you name and have control of  key names. You can have multiple keys in one LDATA.

 

(setq num (vlax-ldata-get "AlanH" "WBLKNUM"))

(vlax-ldata-put "AlanH" "WBLKNUM" num)

 I would look at the way your doing "currentnumber" there should not be a need for "nextnumber" put this after Wblock has completed. Use the get LDATA.

(setq currentNumber (+ currentNumber 1))
(vlax-ldata-put "Stevie" "WBLKNUM" currentNumber)

 

 

0 Likes
Message 6 of 22

stevie_alas
Contributor
Contributor

i tried to add the offset change but now it asks me to specify a side to offset to. this is not ideal as i would like to minimize the amount of steps/clicks/inputs from the user that it takes to complete the action. in the original i somehow managed to get it to do it automatically. these drawings are almost always outside of 0,0,0. EDIT: i was able to include the offset change and now it works regardless of the part location in regards to 0,0,0, reverse does not influence the side it offsets to, and doesnt prompt me for a side! perfection

 

 

in general the shapes we draw are rectangular in nature, but often we have arcs or circles. i am also unsure of where to add the entlast to select the newly created offset line and how to use the object to continue the rest of the lisp. also, where i would add the ya gotta pick something alert

0 Likes
Message 7 of 22

stevie_alas
Contributor
Contributor

sea haven, i tried running the chkcwccw  lisp on its own but i get an error of too few arguments. unfortunately, i am not sure where to add the suggestions you have provided. they seem like it would help solve the offset direction issue and simplify numbering. can you show me where these would need to be added to

 

0 Likes
Message 8 of 22

Kent1Cooper
Consultant
Consultant

Do you ever have outlines of such a shape [for example the yellow here] that an Offset command could result in more than one object [red]?

Kent1Cooper_0-1765901913808.png

That would throw things off, since you would have no control over which is (entlast).  [And in this case, if there was something inside that red triangle, regardless of which red result is used, it would be selected even though it's not within the area I assume you want.]

Kent Cooper, AIA
0 Likes
Message 9 of 22

Kent1Cooper
Consultant
Consultant

... and another question....
The AutoLisp routine allows the selection of LINE objects.  Are the outlines you want ever composed of Lines [as AutoCAD uses the word]?  Those are independent of each other, and even if they make up a closed shape, and you actually pick all those that make it up, Offset wouldn't be able to produce anything you could use for selection of contained objects.  If they are always either closed Polylines, closed Splines, full Ellipses, or Circles, yes, but Lines [or Arcs, though they're not allowed in your code so far] would be problematic.

Kent Cooper, AIA
0 Likes
Message 10 of 22

stevie_alas
Contributor
Contributor

i dont believe ive seen a piece that has given me two shapes when using an offest. ive attached an example of some of the more complex shapes we would potentially have. one that works and one that fails (deep u shape). in general we work in 4'x8' sheets but ive gone as small as 3" x 12" and smaller in some cases (rare)

 

0 Likes
Message 11 of 22

stevie_alas
Contributor
Contributor

no, never open line segments, always closed polylines or circles as that is what our post processor is able to read. but in the example-2 that i show we have arcs as part of the polyline. not sure what those would be called. curved polyline? 

 

* our bounding boxes are always closed polylines and circles, however some objects inside the bounding box consist of circles, lines, open polylines, closed polylines, but never splines at all*

 

0 Likes
Message 12 of 22

Kent1Cooper
Consultant
Consultant

If I understand how it's supposed to work well enough, in the one that Fails, the Offsetting should result in the yellow outline here, and the _pac function should be using the green Points [I used DIVIDE at 100] to form a WP selection [I turned it to reduce space consumed here]:

Kent1Cooper_0-1765903623242.png

Looking closely at the upper left corner:

Kent1Cooper_1-1765903760258.png

It's using those green points for a Window Polygon, which would follow that white diagonal, and the magenta outline isn't fully inside that.  If "FAILS" means it doesn't find the magenta outline in selection, that's probably why.  It would fail only when the geometric circumstances are right [or, should I say, wrong], which I suspect will happen more often on larger outlines, because of the proportion of 1-unit Offset distance to WP-defining point spacing -- i.e. the green Points get farther apart, increasing the chances of this happening.

That's why using vertices rather than hundredths of the way around would be better, but then you'd get similar failures in selection when there are arc segments.

But then, if it's all starting from selecting that magenta outline, that could simply be added to what the WP selection finds, and it wouldn't matter if that selection missed it.

Kent Cooper, AIA
0 Likes
Message 13 of 22

stevie_alas
Contributor
Contributor

you got it! yes, i need the initial outline to be included in the export. when it is not picked up, i call that a fail. it makes sense that larger perimeter objects have a harder time being "seen" if the outline is being divided into 100 sections. if we were to use the vertices, i would be concerned with the offset to inadvertently pick up objects that are outside of the initial outline. when we use the command, all the sheets are arranged in a grid (see example.dwg from my initial post) and are not individually separated as we have been discussing so far. what would a vertex selection look like and how would the program knopw to include what we first selected as our outline

0 Likes
Message 14 of 22

Kent1Cooper
Consultant
Consultant

@stevie_alas wrote:

.... how would the program know to include what we first selected as our outline


For that part, if I interpret correctly [untested], I would probably structure it a little differently, but for the least intervention, I think [I hope] adding this line:

....

    (repeat (setq i2 (sslength temp)) (ssadd (ssname temp (setq i2 (1- i2))) add))
  )
  (ssadd (ssname ss i) add)
)
(sssetfirst nil add)
(ssget "_I")

....

should do it, adding the boundary object(s) into the selection set of things found by the WP selections.  Do the failing ones work, at least in terms of including the boundaries, with that added?

Kent Cooper, AIA
0 Likes
Message 15 of 22

Kent1Cooper
Consultant
Consultant

@stevie_alas wrote:

.... what would a vertex selection look like ....


One way to do that with a Polyline is to extract all the 10-code entries in its entity data and strip the 10's off, to apply a list of vertex locations in WP selection:

  (if
    (and
      (setq pl (car (entsel "\nClosed Polyline boundary: ")))
      (= (cdr (assoc 0 (setq pldata (entget pl)))) "LWPOLYLINE")
      (vlax-curve-isClosed pl)
    ); and
    (progn ; then
      (setq ss (ssget "_WP" (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) pldata))))
      (ssadd pl ss); add the Polyline itself, just in case
    ); progn
  ); if

But if Circles are in the picture, they need to be handled entirely differently [no vertices].  They would most likely need to use something like the 100-points approach.

Kent Cooper, AIA
0 Likes
Message 16 of 22

stevie_alas
Contributor
Contributor

this unfortunately did not work. i get the same result as before. the boundary is not picked up. if i did this correctly that is 

stevie_alas_0-1765913077081.png

 

0 Likes
Message 17 of 22

stevie_alas
Contributor
Contributor

is the 100pt approach very resource demanding? i notice that when using this command in rapid succession my pc fans ramp up and get pretty loud. would increasing the number of points to 150 or 200 be an issue lead to worse preformance?

0 Likes
Message 18 of 22

Sea-Haven
Mentor
Mentor

@Kent1Cooper has provided some great code, one thing that may help add multiple vertices only where there is an arc. Again need to sort of over do it so get small chords, representing the arcs. Then total number of vertices will be less. It would be nice if could do a ssget WP OBJ.

 

Something like use divide then check is a point not an end or start point of a pline,segment, when the segment is a bulge ie ARC keep points. Still looking.

 

Lee-mac has two possible starting programs add a point to a pline, and for a pline get each segment properties. Using bulge details could work out new points. 

 

It is not code I have, will try to find. Sure something is out there. Added to my to do list.

 

SeaHaven_0-1766045346899.png

 

 

0 Likes
Message 19 of 22

Sea-Haven
Mentor
Mentor
0 Likes
Message 20 of 22

stevie_alas
Contributor
Contributor

that screenshot looks exactly what we would need here. i looked at the link you sent and the final reply from valentin_cad looks promising. the issue is, i have no clue how to even integrate that in to what i have currently or where to being. I tried opening their lisp in vs but it opens as gibberish since it is a .vlx and not .lsp

 

0 Likes