edit part of the command line lisp

edit part of the command line lisp

nychoe1
Advocate Advocate
1,043 Views
9 Replies
Message 1 of 10

edit part of the command line lisp

nychoe1
Advocate
Advocate

When I run Lisp, the following appears.
Delete two rows among these,
<line> and <d> I want to fix this.

 

I am receiving a lot of help thanks to many experts. thank you

 

command: FLEXS
Path type [Existing/Line/Arc/Circle/Pline/ELlipse/Spline/3dpoly] <Line>: _.line   <---here

Retain or Delete base path [R/D] <D>: d                                                                       <---here

 

Width (overall) of sine wave: 50

Full-S cycle length as ratio of width <1.0>:

 

This is Lisp.

 

;| FlexSpline.LSP [Command name: FlexS]
To draw a Spline approximation of a sine wave Centered on a path, such as is used by many
to represent flexible duct or conduit. [Not a precisely accurate sine-wave shape, but close.]
Draws continuous Spline along fit points zig-zagging across center of path object.
[Non-tangent changes in direction in Polyline paths, or overly tight curves relative to wave
width in various entity types, will yield quirky results.Allows selecting or drawing planar
3D Polyline, "because it can," however unlikely that one would want to because of this; if 3D
Polyline is fully collinear, will pick a UCS related to current one. Forbids 3D Spline.]
Divides path length into half-wave-length increments to make waves end at path ends; forces
an even number of half-waves for closed paths so that result is complete S-waves continuous
across start/end point.
Draws on current Layer, unless Deleting pre-Existing path; if so, draws on its Layer, assuming
the intent is to replace it (i.e. to replace something drawn only to establish path), but pre-drawn
path is not necessary -- User can create path within command.
Under select-Existing option, asks User to select again if nothing is selected, or if selected object
is an inappropriate entity type.
Accounts for different Coordinate Systems of selected existing path objects.
Remembers option choices and offers them as defaults on subsequent use.
Options:
1. draw new within routine, or select pre-Existing, path of any planar finite type with linearity;
2. if selected Existing object is on locked Layer, whether to unlock it and Proceed, or Quit;
3. PRevious = redraw along prior path (whether retained or deleted) allowing different choices;
4. Retain or Delete base path (whether new or selected Existing);
5. sine-wave Width (overall/outer);
6. sine-wave full-S-cycle approximate Length as ratio of width (actual length will be adjusted to
fit overall path length), offering same value as Width (ratio of 1.0) as initial default.
See FlexPline.lsp with its FLEXP command to do likewise as zig-zag Polyline.
Kent Cooper, last edited 21 June 2019
|;

(vl-load-com)

(defun C:FLEXS
(/ *error* flexreset doc svnames svvals pathent pathdata pathtype 3DP u3p1
u3p2 u3p3pt u3p3 ptno ucschanged pathlength hwsegs steplength ptdist)

(defun *error* (errmsg)
(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
(princ (strcat "\nError: " errmsg))
); if
(if ucschanged (vl-cmdf "_.ucs" "_prev"))
; ^ i.e. don't go back unless routine reached UCS change but didn't change it back
(flexreset)
); defun -- *error*

(defun flexreset ()
(mapcar 'setvar svnames svvals)
(vla-endundomark doc)
); defun -- flexreset

(setq doc (vla-get-activedocument (vlax-get-acad-object)))
(vla-startundomark doc)
(setq
svnames '(cmdecho osmode blipmode ucsfollow clayer)
svvals (mapcar 'getvar svnames); current System Variable values
); setq

(initget
(strcat
"Existing Line Arc Circle Pline ELlipse Spline 3dpoly"
(if *flexs* " PRevious" ""); add PR option only if not first use
); strcat
); initget
(setq *flexstype*
(cond
( (getkword
(strcat
"\nPath type [Existing/Line/Arc/Circle/Pline/ELlipse/Spline/3dpoly"
(if *flexs* "/PRevious" ""); offer PR option if not first use
"] <"
(cond (*flexstype*) ("Line")); prior choice default if present; otherwise Line
">: "
); strcat
); getkword
); User option condition
(*flexstype*); Enter with prior choice
("Line"); Enter on first use
); cond & *flexstype*
); setq

(cond ; re-establish/select/make path
((= *flexstype* "PRevious")
(if (= *flexsdel* "Delete")
(progn ; then
(if *isLocked* (command "_.layer" "_unlock" *pathlay* ""))
; unlock layer w/o asking [Proceed option chosen before] so it can:
(entdel *flexspath*); bring back previous path
); progn
); if
(entdel *flexs*); delete previous result
; under Retain-path option where it draws on current Layer, not that of path object,
; will fail IF current Layer is locked [not accounted for as being highly unlikely];
; under Delete-path option where it draws on object's Layer, already unlocked above
); PRevious-path condition
((= *flexstype* "Existing")
(while
(not
(and
(setq
pathent (car (entsel "\nSelect object to draw sine-wave along an Existing path: "))
pathdata (if pathent (entget pathent))
pathtype (if pathent (substr (cdr (assoc 100 (reverse pathdata))) 5 3))
; ^ = 3 characters [enough to distinguish] of entity type from second (assoc 100)
; without "AcDb" prefix; using this because (assoc 0) value is the same for 2D &
; 3D Plines; 2D OK, 3D only if planar (if not, result would flatten in current CS
); setq
(or
(wcmatch pathtype "Lin,Arc,Cir,Ell,Pol,2dP")
; other types than Spline/3DPoly
(and (wcmatch pathtype "Spl,3dP") (vlax-curve-isPlanar pathent))
; those two only if flat
); or
); and
); not
(prompt "\nNothing selected, or not a finite planar path type; try again:")
); while
); Existing-object condition
((= *flexstype* "Line") (command "_.line" pause pause "")); only single Line
((/= *flexstype* "PRevious"); all other draw-new entity types
(command (strcat "_." *flexstype*)); start drawing command
(while (> (getvar 'cmdactive) 0) (command pause)); complete it
); draw-new condition
); cond

(mapcar 'setvar svnames '(0 0 0 0)); turn off System Variables after path selected/drawn

(setq
*flexspath* ; set object as base path [not localized, so it can be brought back if PR and D options]
(cond
((= *flexstype* "Existing") pathent); selected object
((= *flexstype* "PRevious") *flexspath*); keep the same
((entlast)); otherwise, newly drawn path
); cond & *flexspath*
pathdata (entget *flexspath*)
pathtype (substr (cdr (assoc 100 (reverse pathdata))) 5 3)
); setq
(if
(and ; User drew Spline or 3DPolyline that is not planar
(or
(= pathtype "Spl")
(setq 3DP (= pathtype "3dP")); separately from Spline, for UCS alignment
); or
(not (vlax-curve-isPlanar *flexspath*))
); and
(progn ; then
(prompt "\nCannot use non-planar Spline/3DPolyline.")
(flexreset) (quit)
); progn -- then [no else]
); if
(setq
*pathlay* (cdr (assoc 8 pathdata))
; ^ not localized, so that under PRevious option, knows what layer to unlock if needed
*isLocked* ; not localized, so that under PRevious option, don't need to ask again
(if (and (= *flexstype* "PRevious") *isLocked*)
T ; keep with PR if previous object was on locked layer [will be unlocked by now]
(= (logand (cdr (assoc 70 (tblsearch "layer" *pathlay*))) 4) 4)
; other types: 0 = Unlocked [nil]; 4 = Locked [T]
); if & *isLocked*
); setq

(initget "Retain Delete")
(setq *flexsdel*
(cond
( (getkword
(strcat
"\nRetain or Delete base path [R/D] <"
(if *flexs* (substr *flexsdel* 1 1) "D"); prior choice default, Delete on first use
">: "
); strcat
); getkword
); User-input condition
(*flexsdel*); Enter with prior choice
("Delete"); Enter on first use
); cond & *flexsdel*
); setq

(if (and *isLocked* (= *flexsdel* "Delete"))
(if (/= *flexstype* "PRevious"); then -- check for not redoing on previous object
(progn ; then -- ask whether to unlock
(initget "Proceed Quit")
(setq *flexsunlk*
(cond
( (getkword
(strcat
"\nLayer is locked; temporarily unlock and Proceed, or Quit? [P/Q] <"
(if *flexsunlk* (substr *flexsunlk* 1 1) "P"); prior choice default, Proceed on first use
">: "
); strcat
); getkword
); User-input condition
(*flexsunlk*); Enter with prior choice
("Proceed"); Enter on first use
); cond & *flexsunlk*
); setq
(if (= *flexsunlk* "Proceed")
(command "_.layer" "_unlock" *pathlay* ""); then
(progn (flexreset) (quit)); else
); if
); progn & inner then argument
); inner if & outer then argument
); outer if -- no else argument [no issue if not on locked layer with Delete option]

(initget (if *flexswid* 6 7)); no zero, no negative, no Enter on first use
(setq *flexswid*
(cond
( (getdist
(strcat
"\nWidth (overall) of sine wave"
(if *flexswid* (strcat " <" (rtos *flexswid*) ">") ""); default only if not first use
; EDIT to add mode & precision above if current Units settings not desired
": "
); strcat
); getdist
); User-input condition
(*flexswid*); Enter with prior value
); cond & *flexswid*
); setq

(initget 6); no zero, no negative
(setq *flexslenratio* ; LENgth of full wave as RATIO of width
(cond
( (getreal
(strcat
"\nFull-S cycle length as ratio of width <"
(if *flexslenratio* (rtos *flexslenratio* 2 3) "1.0"); EDIT precision as desired
; prior as default only if present; 1 as default on first use
">: "
); strcat
); getreal
); User-input condition
(*flexslenratio*); Enter with prior value
(1.0); Enter on first use
); cond & *flexslenratio*
); setq

(if 3DP
(progn ; then -- 3DPolyline doesn't define UCS under object option, so:
(setq
u3p1 (trans (vlax-curve-getStartPoint *flexspath*) 0 1); first vertex
u3p2 (trans (vlax-curve-getPointAtParam *flexspath* 1) 0 1); second
u3p3pt (vlax-curve-getPointAtParam *flexspath* (setq ptno 2))
; third [if present] -- WCS point only, un-translated [(trans) fails if nil]
); setq
(if u3p3pt ; at least 3 vertices
(progn ; then
(while
(and
u3p3pt ; still a remaining vertex
(not (inters u3p1 u3p2 u3p1 (setq u3p3 (trans u3p3pt 0 1)))); collinear with first 2 vertices
); and
; will usually finish at 3rd vertex; if first 3 are collinear, will look further
; until it finds one not collinear with 1st & 2nd
(setq u3p3pt (vlax-curve-getPointAtParam *flexspath* (setq ptno (1+ ptno))))
; next vertex [finally nil if all collinear to end]
); while
(if (not u3p3pt); reached end without finding non-collinear point
(setq u3p3 ""); accept offered default for 3rd point [UCS will be parallel to current UCS]
); if
); progn -- then
(setq u3p3 ""); else [single-segment] -- accept offered default for 3rd point [as above]
); if [3 or more vertices vs. 2]
(command "_.ucs" "_new" "_3point" u3p1 u3p2 u3p3); use vertices to define UCS
); progn -- then [3DP]
(command "_.ucs" "_new" "_object" *flexspath*); else [other types] -- set UCS to match object
); if
(setq
ucschanged T ; marker for *error* to reset UCS if routine doesn't get to it
ptno 0 ; starting value for intermediate point multiplier [replace prior use if 3DP]
); setq

(setq
pathlength (vlax-curve-getDistAtParam *flexspath* (vlax-curve-getEndParam *flexspath*))
hwsegs ; closed path needs even number of Half-Wave SEGmentS; open can have odd number
(if (vlax-curve-isClosed *flexspath*)
(* (fix (+ (/ pathlength *flexswid* *flexslenratio*) 0.5)) 2); then -- round to nearest *even* number
(fix (+ (/ pathlength *flexswid* *flexslenratio* 0.5) 0.5)); else -- round to nearest *whole* number
); if & hwsegs
steplength (/ pathlength hwsegs 2)
); setq

(if (and (wcmatch *flexstype* "Existing,PRevious") (= *flexsdel* "Delete")) (setvar 'clayer *pathlay*))
; if Deleting Existing/PRevious path, draw on same Layer [already will for new path]

(command "_.spline" (trans (vlax-curve-getStartPoint *flexspath*) 0 1)); [leave in Spline command]
(repeat (1- (* hwsegs 2)); for Fit Points not including final at end
(command ; feed out to Spline command:
(polar
(trans
(vlax-curve-getPointAtDist ; advance point along path
*flexspath*
(setq ptdist (* (setq ptno (1+ ptno)) steplength))
); getPointAtDist
0 1 ; from World coordinates to object's coordinates
); trans
(+ ; localized angle of offset
(angle
'(0 0 0)
(trans
(vlax-curve-getFirstDeriv
*flexspath*
(vlax-curve-getParamAtDist *flexspath* ptdist)
); getFirstDeriv
0 1 T ; world to current CS, as displacement
); trans
); angle
(/ pi 2); perpendicular to center-line path [sine +/- gives left/right]
); +
(* *flexswid* 0.5 (sin (* (/ pi 2) (rem ptno 4))))
; proportion of sine-wave width [alternates between +/- 0.5 & 0]
); polar
); command
); repeat
(if (vlax-curve-isClosed *flexspath*); finish Spline
; (command "_close" ""); then
; Close option used because end-at-path's-end 'else' line below results in "kinked"
; start/end on most closed paths. Using plain Close line above, accepting default
; for tangent direction, though start/end "flows" across, result has noticeable variance
; there from typical wave shape elsewhere. Following is a compromise tangent-
; direction determination, better than default above but slightly too steep in some
; situations and not steep enough in others. There is no universal ideal -- it would
; differ depending on degrees of curvature within first & last wavelengths of path.
(command ; then [closed path]
"_close"
(polar ; tangent-direction found as before, but farther out from last 'ptno' location
(trans
(vlax-curve-getPointAtDist
*flexspath*
(setq ptdist (* ptno steplength)); re-use from last wave-crest fit point
); getPointAtDist
0 1
); trans
(+
(angle
'(0 0 0)
(trans
(vlax-curve-getFirstDeriv
*flexspath*
(vlax-curve-getParamAtDist *flexspath* ptdist)
); getFirstDeriv
0 1 T
); trans
); angle
(/ pi 2)
); +
(* *flexswid* (sin (* (/ pi 2) (rem ptno 4)))); tangent-direction defining point:
; outboard of last wave crest, twice as far from path, for compromise location
); polar
); command
(command (trans (vlax-curve-getEndPoint *flexspath*) 0 1) "" "" ""); else [open-ended]
); if

(command "_.ucs" "_prev")
(setq
ucschanged nil ; eliminate UCS reset in *error* since routine did it already
*flexs* (entlast); save result in case of recall of routine with PRevious option
); setq
(if (= *flexsdel* "Delete") (entdel *flexspath*)); remove base path under Delete option

(if *isLocked* (command "_.layer" "_lock" *pathlay* "")); re-lock layer if appropriate
(flexreset)
(princ)
); defun -- FLEXS

(prompt "Type FLEXS to draw Sine-wave-approximation Spline centered along path.")

 

 

0 Likes
Accepted solutions (1)
1,044 Views
9 Replies
Replies (9)
Message 2 of 10

paullimapa
Mentor
Mentor

Please clarify.

Are you saying you don't want the code to ask you withthese 2 lines but just always be Line and D:

Path type [Existing/Line/Arc/Circle/Pline/ELlipse/Spline/3dpoly] <Line>: _.line   <---here

Retain or Delete base path [R/D] <D>: d                                                                       <---here


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 3 of 10

nychoe1
Advocate
Advocate

Thanks for reading.
I always want <line> and <D>

 

0 Likes
Message 4 of 10

Kent1Cooper
Consultant
Consultant

[It's better to attach a file than to paste hundreds of lines of code into a Message.]

 

The prompt line you show is only the prompt at first use.  After you have drawn the first one, on subsequent use the regular command offers not just those path types to choose from, but also a PRevious option, which will let you make different choices re-using the last path you drew without needing to draw it again, if you want to change the width and/or cycle proportion.  Do you want that option kept in the command?  It would be offered only on subsequent use, never on the first use.

Kent Cooper, AIA
0 Likes
Message 5 of 10

paullimapa
Mentor
Mentor
Accepted solution

Replace this portion of the code

 

(initget
(strcat
"Existing Line Arc Circle Pline ELlipse Spline 3dpoly"
(if *flexs* " PRevious" ""); add PR option only if not first use
); strcat
); initget
(setq *flexstype*
(cond
( (getkword
(strcat
"\nPath type [Existing/Line/Arc/Circle/Pline/ELlipse/Spline/3dpoly"
(if *flexs* "/PRevious" ""); offer PR option if not first use
"] <"
(cond (*flexstype*) ("Line")); prior choice default if present; otherwise Line
">: "
); strcat
); getkword
); User option condition
(*flexstype*); Enter with prior choice
("Line"); Enter on first use
); cond & *flexstype*
); setq

 

with this 

 

(setq *flexstype* "Line")

and this portion of the code

(initget "Retain Delete")
(setq *flexsdel*
(cond
( (getkword
(strcat
"\nRetain or Delete base path [R/D] <"
(if *flexs* (substr *flexsdel* 1 1) "D"); prior choice default, Delete on first use
">: "
); strcat
); getkword
); User-input condition
(*flexsdel*); Enter with prior choice
("Delete"); Enter on first use
); cond & *flexsdel*
); setq

with this 

(setq *flexsdel* "Delete")

 


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
Message 6 of 10

nychoe1
Advocate
Advocate

thank you very well

It works fine.

0 Likes
Message 7 of 10

nychoe1
Advocate
Advocate

thank you

From next time, if the content is long,
I will upload the file.

0 Likes
Message 8 of 10

paullimapa
Mentor
Mentor

glad to have helped...cheers!!!


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 9 of 10

Kent1Cooper
Consultant
Consultant

@nychoe1 wrote:

.... From next time, if the content is long, I will upload the file.


One reason I asked the question that you didn't answer is for the sake of the length of the file.  @paullimapa's suggestion may work, but it leaves a lot of unnecessary code in the file elsewhere.  For example, it makes various choices based on whether the path object is open or closed, which is never a consideration if it's always a Line.  And it offers another option and takes other steps if a selected existing object is on a locked Layer, but if you're never selecting an existing object, I assume that doesn't matter [unless you operate with the current Layer locked, which is possible but would be really unexpected].

 

If you want a version with all the irrelevant fluff removed, I could do that, given an answer to my question.

Kent Cooper, AIA
0 Likes
Message 10 of 10

Sea-Haven
Mentor
Mentor

In the Multi radio buttons lsp is hidden remember the last choice and high lite that. The BUT variable holds the value of the last selected button. The dcl produced needs a couple of extra items like the Width and Delete again can be preset or remembered. 

SeaHaven_0-1717380565458.png

 

 

 

 

(if (not AH:Butts)(load "Multi Radio buttons.lsp"))
(if (= but nil)(setq but 1))
(setq ans (ah:butts but "v"  '("Choose Existing" "Line" "Arc" "Circle" "Pline" "ELlipse" "Spline" "3dpoly"))) ; ans holds the button picked value

 

 

Would be easier than rewriting code leave all the extra checks in. Happy to do a new dcl with other inputs required.

0 Likes