Unknown Command Problem

Unknown Command Problem

Anonymous
Not applicable
6,768 Views
48 Replies
Message 1 of 49

Unknown Command Problem

Anonymous
Not applicable

I'm brand new to the forums and to Visual LISP, so forgive me if this is in the wrong area or if I seem a bit lost.

 

I'm working in Carlson/Civil 3D and I'm trying to write a LISP that lets me select some polylines and then it sets them to the zero elevation and reduces the vertices. However, every time I try to call the LISP in the command line, it says "unknown command '3dto2d'". I know 3dto2d is a valid command in Carlson, so I assume I'm missing something in my code to make it look there. Any help would be greatly appreciated.

 

(DEFUN C:ZR ()
	(setq ss (ssget))
	(Command-s "._3dto2d" "0" ss "")
	(Command-s "._reduce" "5" ss "")
	(princ)
)

 

Thanks,

Mike

0 Likes
Accepted solutions (1)
6,769 Views
48 Replies
Replies (48)
Message 21 of 49

Anonymous
Not applicable

I just gave that a shot. What it ends up doing is it makes me step through all of the arguments of 3dto2d before moving on to the next line. Because of that, it gives me "unknown command '0'" when it moves to the line (command "0" ss ""). Similarly, adding "(command)" before the "0" still gives me an error along the same lines since I had to manually input all of the arguments for 3dto2d prior to the program reading that next line.

0 Likes
Message 22 of 49

john.uhden
Mentor
Mentor
Did you catch my response about using vlax-add-cmd?
BTW, a .FAS file is just a compiled AutoLisp file to "encrypt" it so that others can't change it or steal any contents for use in other home-grown creations.

John F. Uhden

0 Likes
Message 23 of 49

Anonymous
Not applicable

Yes, sorry it probably got buried by my response to Steve. I was curious if adding those lines you mentioned would allow me to automate the arguments for the 3dto2d and reduce commands? Right now, It makes me manually go through each step of each command in the command line and I'm not sure how to make it so that the lisp automatically completes those steps.

0 Likes
Message 24 of 49

john.uhden
Mentor
Mentor
That's exactly the purpose of my suggestion... to make your original code work.

BTW, I just realized that the vlax-add-cmd calls have to be invoked AFTER Carlson is loaded so that the c: functions exist. I'm not sure if I remember how to do that. I did a lot of Land Desktop customization back in the day, so we can probably figure it out if you have any problems.

John F. Uhden

0 Likes
Message 25 of 49

Anonymous
Not applicable

Oh ok, Great. I'll give that a shot then!

0 Likes
Message 26 of 49

Anonymous
Not applicable

That worked! Sort of. It now recognizes the commands and automates everything, however for whatever reason it didn't reduce the vertices. It looks like the selection set part of that line didn't work. I'll keep playing and see if I can figure it out though. Thanks again!

0 Likes
Message 27 of 49

john.uhden
Mentor
Mentor
I wouldn't be surprised if the 3DTO2D function deletes the 3D objects and creates new 2D objects so that there are no members of the selection set left for Reduce to work on. So try this:
Before the call to 3DTO2D, get the last entity created...
(setq elast (entlast))
Then after the call to 3DTO2D, get all the new objects created and add them to the original selection set (even if it became empty)...
(while (setq elast (entnext elast))
(ssadd elast ss)
)

You should also localize your variables so they don't remain global and possibly impact any of the other work you will have created.

John F. Uhden

0 Likes
Message 28 of 49

john.uhden
Mentor
Mentor
Of course if elast was a member of the selection set then it would no longer exist after 3DTO2D so that (entnext elast) would return nil. To combat that you could create a dummy circle or point or text (or anything that 3DTO2D would ignore) before (setq elast (entlast)).

Too bad there isn't an entprevious function, but the way I see it, it would require building a list of ALL the entities and picking the one just before (entlast)... very tedious in a mid to large DWG.

John F. Uhden

0 Likes
Message 29 of 49

Kent1Cooper
Consultant
Consultant

@john.uhden wrote:
.... if elast was a member of the selection set then it would no longer exist after 3DTO2D so that (entnext elast) would return nil. To combat that you could create a dummy ... before (setq elast (entlast)).
....

Another approach:  As things are drawn, they get handles that seem [I haven't tested this very far] to increase by one hexadecimally for each new object.  Get the handle of the last object with:

 

(cdr (assoc 5 (entget (entlast))))

 

before running 3Dto2D.  Then after 3Dto2D, do a (while) function looking at successively higher hexadecimal numbers for handles, something like:

 

(ssget "_X" (list (cons 5 theNextHexadecimalNumberUp)))

 

and at whether it's reached the new (entlast) yet [stop when it does].  Add everything it finds that way to the selection set for the Reduce command.  Even if handle numbers don't always count up by one each time, I think they do at least always increase, and even if there may be gaps, it could keep going through those until it gets to (entlast).

 

That wouldn't use (entlast) itself as an entity name for the starting point, nor would it use (entnext) [which I believe is handles-based], so it wouldn't matter whether or not the last thing prior to 3Dto2D was eliminated by that command, and no dummy object would be needed.

 

It would require making a hexadecimal counter-upper, but that shouldn't be difficult.  Or, I have an integer-to-hexadecimal converter function, and the reverse, so the initial handle number could be converted to a base-10 integer, incremented that way with (1+), and converted back to hexadecimal for each (ssget).

Kent Cooper, AIA
0 Likes
Message 30 of 49

hmsilva
Mentor
Mentor

@john.uhden wrote:
Of course if elast was a member of the selection set then it would no longer exist after 3DTO2D so that (entnext elast) would return nil.
...
...

If memory serves, an entity after being deleted continues in dwg database until the dwg is closed.
i.e.

_$ (command "_circle" '(0.0 0.0) 1)
nil
_$ (setq elast (entlast))
<Entity name: 7ffffb05b20>
_$ (command "_erase" "all" "")
nil
_$ (command "_circle" '(1.0 1.0) 1)
nil
_$ (setq enext (entnext elast))
<Entity name: 7ffffb05b30>
_$

 

 

Hope this helps,
Henrique

EESignature

0 Likes
Message 31 of 49

steve_carson
Enthusiast
Enthusiast

Mike,

 

A couple questions:

 

1. Will the Reduce function work on 3dPolylines? If so, try running the reduce function before the 3dto2d.

 

2. Do you actually need the entities to be LWPolylines at elev 0, or is a 3dPolyline acceptable provided all the vertices are at elevation 0? If a 3dPolyline is acceptable, it may be easier to create a function that does what you need instead of trying to make what you have work.

 

I have a vertex reducing program that asks the user for the maximum error (acceptable distance from original) that works on a selection set of Polylines, 3dpolylines, and LWPolylines that it wouldn't be too difficult to tweek to hard-code the 5 in to if it helps.

 

 

Steve

 

 

0 Likes
Message 32 of 49

john.uhden
Mentor
Mentor
Or... another way would be to do a DXFOUT before and after, read each of the files, and create a before list and an after list of handles from the ENTITIES SECTION. Then remove all the befores present in the afters. \___/ But I think Mr. Silva's wisdom prevails.

John F. Uhden

0 Likes
Message 33 of 49

Anonymous
Not applicable
Thanks for all the suggestions and help, I'll have to try them all out if I have time tomorrow.

Steve, in response to your questions, yes the reduce function works on 3D polylines. That is a great suggestion, so I'll try that out since it sounds like the easiest fix. While the lines definitely don't HAVE to be LWPolylines, it's nice to have the mid-line grips that you don't get with a 3d poly.

I'm a pit designer for a coal mine and I mainly use these functions when trying to achieve cut/fill balances in my designs. Since the drill and blast folks like my lines to remain on specific azimuths and such, those midline grips make it easy to move my cut/fill lines without risking messing up their angles.
0 Likes
Message 34 of 49

john.uhden
Mentor
Mentor
Just what is Reduce supposed to do? Sounds like it might be easier for me to write you a custom routine that does both 2D and Reduction. How about if 3DTO2D gave you the choice of target elevation?

John F. Uhden

0 Likes
Message 35 of 49

Anonymous
Not applicable

This is what the help doc says about it:

 

 

Reduce Polyline Vertices

This command removes points from a polyline, without significantly changing the polyline. The offset cutoff is the maximum amount that the polyline can move horizontally and vertically when removing a point. For example, in a polyline with three points in a straight line, the middle point can be removed without changing the polyline.

Prompts

Enter the offset cutoff <0.1>: .5
Select polylines to reduce.
Select objects:
pick polylines
Processed polylines: 1
Total number of vertices: 10
Number of vertices removed: 1

Pulldown Menu Location: Edit > Polyline Utilities
Keyboard Command: reduce
Prerequisite: A polyline

 

 

So it's a pretty simple command and I'm sure you guys could easily write something that does the same thing. I just figured that if I could use the command without too much effort, it would be easier than rewriting something.

 

As for the 3Dto2D command, one of the arguments you choose is what elevation to set the line to. I've just chosen to automate it because 99% of the time I end up setting it to 0.

0 Likes
Message 36 of 49

Anonymous
Not applicable

So I tried putting reduce before 3dto2d and now it reduces the line, but doesn't do the 3dto2d part. So it seems like these commands do something to the selection set that doesn't make it reusable.

 

Another issue I'm coming across is that since using the vlax-add-cmd commands, I get "error: Visual LISP command document mismatch: 3DTO2D" (same thing for reduce) when I try to use the commands in other drawings that I open. I googled around for a fix to this and found a bunch of stuff on making a dummy command or some such thing, but I guess I don't understand what exactly it does and I'm not applying it right. Below is what I'm up to so far, and I still get those errors. The dummy command bit is something I took from one of the sites I googled.

 

;; Comments by JRF: This code should be
;;; run before adding any other commands with vlr-add-cmd.
;;; Otherwise, when using added commands in multiple documents
;;; (MDI mode), sometimes the commands fail with a "Visual LISP
;;; command document mismatch" error.  Apparently vlax-add-cmd
;;; must be called in a document in order to activate commands
;;; in that document.
(defun DummyCommand () NIL)
(vlax-add-cmd "DummyCommand" 'DummyCommand)
(defun AddCommandsHelper (a b)
  (vlax-add-cmd "DummyCommand" 'DummyCommand)
)
;; Install dummy command reactor only if it's not
;; defined already
(or DummyCommandReactor
    (setq DummyCommandReactor
           (vlr-docmanager-reactor
             NIL
             '((:vlr-documentBecameCurrent . AddCommandsHelper))
           )
    )
)

(DEFUN C:ZR ( / ss)
	(setq ss (ssget))
	(vl-load-com)
	(vlax-add-cmd "REDUCE" 'c:reduce)
	(vlax-add-cmd "3DTO2D" 'c:3dto2d)
	(Command "reduce" "5" ss "")
	(Command "3dto2d" "0" ss "")
	(princ)
)

 

0 Likes
Message 37 of 49

Anonymous
Not applicable

I'll give yours and John's ideas here a shot. However, in regard to yours, what does the "5" mean in your lines (assoc 5...), (cons 5...)?

 

And the idea of the hexadecimal counter is to just count up until it can't find any elements with a higher value and whatever the highest value element is, that is the most recent entity created?

0 Likes
Message 38 of 49

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

... what does the "5" mean in your lines (assoc 5...), (cons 5...)?

 

And the idea of the hexadecimal counter is to just count up until it can't find any elements with a higher value and whatever the highest value element is, that is the most recent entity created?


The 5 is the DXF code number in entity data lists for the entity handle.  [The entity's handle has the benefit over other identifiers such as its entity name that it stays the same for the object, no matter what, even after closing and getting back into the drawing.]

 

Since there can be gaps between entity handle numbers [such as if something has been eliminated by something like 3Dto2D, and replaced with a new entity], if it counts up until it doesn't find the next handle number in the drawing, that doesn't mean it's gotten to the most recent entity.  I'm not sure there's a reliable way to decide, only from not finding further entity handles, that it's reached the end -- how many might it not find before finding a next one [i.e. how long might a gap be?], and so how far further upward should it try before giving up?  For that, I would check, for each thing it finds, whether that is also the same entity as (entlast) -- if so, stop looking, but if not, keep looking, through however many missing entity handle numbers it passes in between, because there should be another one that is there, coming eventually.

Kent Cooper, AIA
0 Likes
Message 39 of 49

steve_carson
Enthusiast
Enthusiast
Accepted solution

Doing something like this (untested) seems like it would be easier than trying to deal with a selection set of newly created objects:

 

(defun C:zr ( / ss i lastobj obj)

    (setq ss (ssget)
     lastobj (entlast) )

    (repeat (setq i (sslength ss))
        (setq obj (ssname ss (setq i (1- i)))
        (C:reduce 5 obj "")
        (if (= lastobj (entlast))
            (C:3dto2d 0 obj "")
            (progn
                (C:3dto2d 0 (entlast) "")
                (setq lastobj (entlast))
            )
        )
    )
)

 

 

Steve

0 Likes
Message 40 of 49

john.uhden
Mentor
Mentor
Though that is an inventive idea, I am pretty sure that the C:reduce and C:3dto2d functions were not written to accept arguments, thus the need to turn them into AutoCAD commands via vlax-add-cmd. Mike said he had found .FAS files of the same names in his Carlson directory. OR... one of us writes them from scratch (or from some of my old code) for his use.

John F. Uhden

0 Likes