How accurate is AutoCad then?

Roderic Potter

Usenet Archive
Joined
Jan 23, 2004
Messages
20
Reaction score
0
With the help of some brilliant members of this newsgroup I have managed to write some code that allows me to automatically ascertain the layer of an existing entity just by picking somewhere on it.

Example:
I have a line representing a pipe, and the line resides on layer H-SM-PIP-P, for "mechanical schematic piping planned" (Canadian PWGSC layer standard). I want to insert a block on this line to represent an "elbow" in the pipe, and I want this block to automatically jump to the related H-SM-PIP-FTG-P layer, for "fittings".

I normally used to make sure the piping layer was current, then insert the block, and my existing code flipped the block to the right layer after insertion.

My new code now allows me to do all of this automatically without having to set the particular layer current first, because when I osnap onto the line, the pick function reveals what layer the pipe line is on, thus revealing to the code what the associated layer is.

This works brilliantly under normal circumstances, UNTIL I am not zoomed in far enough.

If I try this from too far out (zoom-wise), and osnap endpoint onto the line, AutoCad does not find the line - in fact it finds NOTHING and thinks the layer of the entity is layer ZERO.

This is not cricket as they say.

Is there a setting somewhere in AutoCad that will alter its ability to look deep inside a pick?

regards
 
Try setting a filter to only gather endpoint of a given line.

Besides, your command alone commits to what will the utility will be set to.

In either case, you can also apply conditions
(cond
((= <val> <setting>)(Do_this))
((= <val> <setting>)(Do_that))
)

(setq ent (ssget (list (cons 8 <layer>))))

Under an circumstances you can define an infinite amount of conditions solutions.

You can even have it do it for you automatically.

(setq ob (ssget (list (cons 8 <layer,layer,layer,etc>))))

Foreach endpoint of given line on layer, check assoc 10 and 11 for block insertion and given point, if not insert block, trim as required. Complete Automation can be accieved by each step you predefine. Even drawing the lines can be set to automatically insert a given block and the right elbow.

To break and insert a connection can be predefined by assuming that you have a clear understanding of given posibilities, distance, location, angle, type.
 
Excellent advice Rudy
many thanks

Rudy Tovar said:
Try setting a filter to only gather endpoint of a given line.

Besides, your command alone commits to what will the utility will be set to.

In either case, you can also apply conditions
(cond
((= <val> <setting>)(Do_this))
((= <val> <setting>)(Do_that))
)

(setq ent (ssget (list (cons 8 <layer>))))

Under an circumstances you can define an infinite amount of conditions solutions.

You can even have it do it for you automatically.

(setq ob (ssget (list (cons 8 <layer,layer,layer,etc>))))

Foreach endpoint of given line on layer, check assoc 10 and 11 for block insertion and given point, if not insert block, trim as required. Complete Automation can be accieved by each step you predefine. Even drawing the lines can be set to automatically insert a given block and the right elbow.

To break and insert a connection can be predefined by assuming that you have a clear understanding of given posibilities, distance, location, angle, type.
 
What function are you using to 'get' the picked object. ? (entget (... or (vlx-get... In either case, you could examine the 'returned' entity.
Like so:
(setq obj nil)
(setq obj (entsel..)
(if obj
(progn
..do your thing
))
(if (= obj nil)
(prompt "\nZoom in a bit..nothing selected..")
);eif

Bob
 
Hi Bob

Following is a sample bit of my code:

(setq pt1 (getvar "lastpoint"))
(setq ee1 (nentselp pt1))
(setq ee (car ee1))
(if ee
(progn
(setq e (entget ee))
(setq n (cdr (assoc 8 e)))
(command "LAYER" "SET" n "")
))

As you can see, I am using the "nentselp" statement for getting the object.
 
Hi Roderic,
All I'm saying here (based on your post of the problem)... You may want to nil out the ee variable - somewhere in the loop, so next time in, it is nil to begin with. If you don't set it to nil, may be set to (last run) value, and execute.
So:
(setq ee nil)
(setq pt1 (getvar "lastpoint"))
...
IF ee
do the work
IF NOT ee
(zoom out a little)
..
You could also set in while loop, waiting for ee to be set. E.G. (setq ee nil) (while (= ee nil) (progn ..... do your thing ) (if (= ee nil) (prompt "\nZoom out a little..") )
); e while
 
Excellent response from the group, as normal
I owe you a beer!

ECCAD said:
Hi Roderic,
All I'm saying here (based on your post of the problem)... You may want to nil out the ee variable - somewhere in the loop, so next
time in, it is nil to begin with. If you don't set it to nil, may be set to (last run) value, and execute.
 
Really don't mean to bust you; just rattling your brain a little.

If you're picking the object, why don't you use (nentsel) instead of (nentselp)? Depending on your zoom level and the proximity of other objects, (nentselp) can be hit or miss or hit the wrong target.

Anyway, (nentselx) will return nested entities as well, so if you pick an entity within an xref, you can't possibly set its externally referenced layer current, so you ought to use (entsel) instead. Then again, you should have available what AutoCAD already provides... ai_molc.
 
Not having a thorough knowledge of Lisp and the various commands that are available, I was not aware that I could simply use (nestsel) instead. I muddle through normally and was pointed towards (nentselp) by another kind person in this newsgroup.

Thanks, I will try it out.

I find it interesting that no-one has commented on the REAL problem here, that is, the accuracy of AutoCad. If I osnap onto the endpoint of a line, even when I am zoomed a LONG way out, AutoCad should find the line, not nothing. No-one has commented on this...

best regards
 
Roderic Potter said:
I find it interesting that no-one has commented on the REAL problem here, that is, the accuracy of AutoCad. If I osnap onto the endpoint of a line, even when I am zoomed a LONG way out, AutoCad should find the line, not nothing. No-one has commented on this...

Actually, a few of the posts pointed you in the right direction to answer this question. The biggest problem I see is that we/you have no way of knowing what "lastpoint" was and what entity it may, or may not, be near.

First, how do you know "it finds nothing"? As John pointed out, if it finds a nested entity in an xref the layer can't be made current which will cause an error.

With (entsel) you are picking the object and when the pickbox is a certain size larger than 0 it is relatively easy to pick the object you intend. Now, change the pickbox smaller, 1 size at a time, until you get to 0, trying to pick the same entity at each stage. It gets tougher, doesn't it?

Now with (nentsel) you are passing it a specific point, without the benefit of a pickbox, and expect it to find an entity from far away. Now IF the point is EXACTLY on the intended object, it should find it, but if it falls to the side, even by a small amount, it probably won't.

Hence John's suggestion of using (entsel), you are ensured of getting a valid object.

Just some thoughts,
Jeff
 
Thanks, Jeff. You said it better than I could. :)

Meanwhile, doesn't everyone have a little icon for "Make object's layer current"?
 
I would like to add to Jeff's comments.

1. In your first post on 1/23/04, you wanted to use running osnaps in conjunction with entsel. I offered an example of using getpoint and nentselp to accomplish this. Someone may be able to prove me wrong on this, but I have never been able to make this method fail.

2. In your second post on 1/23/04, you wanted to know of a way to obtain the point at which the user just inserted a block for later use in obtaining the layer in which the block was inserted on.

Now you are trying to use nentselp to obtain the layer of the object that the block was inserted on. If the insertion point of the block is touching an entity in the block then your chances are good that nentselp will grab the insert instead of the entity that you inserted the block on to. Hope this makes sense.

I guess my point is that if you ask for solutions to specific tasks that is what you are going to get. You are going to get a way to use osnaps and entsel. You are going to get a way to obtain the last point picked by a user. But this doesn't mean that these specific task are the correct direction to head in accomplishing your overall goal. Your question has been answered in this thread just as they were in the previous two, but it looks to me that you are no closer to completion. Try posting your overall goal and code and I bet you get all the answers you need or at the very least a good head start and direction.

Ken Alexander
 
You guys are really great taking such an interest in this, thanks!

Jeff asked the question "how do you know that AutoCad finds nothing?" - well I assume this because if I am zoomed a long way out and I use the code to osnap onto the endpoint of a line, the layer that is made current is layer ZERO, not the layer of the line itself.

Now to give you a bit of background, as I explained in an earlier post, I draw mechanical building systems, including pipes.

On a typical floor plan or maybe schematic, I will have a bunch of lines quite near to each other representing many different pipes such as domestic cold water, natural gas, steam, you name it.

Typically all of these pipes will run along together and all bend through 90deg at the same spot, because we are neat people and that's the way we do things.

After drawing all of these "bends", I have to add the "elbow" blocks which are simply blocks that represent the "joints" at the elbows. These blocks have to flip onto associated layers, and I wrote the code to make that happen automatically some time ago, but for this to work, I have to be on the correct pipeline layer (for each pipe) before I insert the elbow block.

This requires me to use the "set entity layer current" icon as mentioned by John, before each block insertion, otherwise the elbow for the cold water pipe will flip onto the layer associated with natural gas (hypothetically).

(bored yet?)

Anyway assuming I have a bunch of these insertions to do, it occurred to me that having to pick/make layer current each time prior to block insertion was tedious at best, and I have tried to make this all happen automatically by virtue of picking on the entity itself. Therefore I could be sitting on layer zero, and proceed to insert all of these blocks one after the other, never having to worry about being on a pipeline layer first, because when I osnap onto the endpoint of each line, it determines the layer of the line, makes that layer current, and flips the block insertion onto the associated layer.

(phew)

I trust that this explains what I am trying to achieve.

Now getting back to a previous bit of code I posted:

(COMMAND "insert" blank PAUSE 1.0 "" 0)

(setq pt1 (getvar "lastpoint"))
(setq ee1 (nentselp pt1))
(setq ee (car ee1))
(if ee
(progn
(setq e (entget ee))
(setq n (cdr (assoc 8 e)))
(command "LAYER" "SET" n "")
))

(do insertion stuff)....

This is where I am. The original insert command determines the point at which I want the insertion to take place, and the "blank" is merely a preview block that helps me see the size of the block before insertion.

I will experiment with using (nentsel) instead of (nentselp).

best regards
 
Roderic,
I now see what, how, & why you are doing things. I would be willing to bet that your "elbow" block entities are created on Layer 0, so as to take the on the properties of the layer inserted on. Now, when using (nentselp pt) it will return the entity it finds at that point, whether it is a line inside the elbow block, the line you intended, or something else, all depends on how many things are in the same area, your "sort order" for object selection, etc. Which means that, based on your reply, (nentselp pt) IS finding something, and that something is in the elbow block and is on layer 0, otherwise your routine wouldn't complete........(try using (entget) on a var that is set to nil)

As for a solution? I would suggest that, since you seem to have a number of these elbows to insert in any one area, do something like this (someone else may have a better idea, this is just the first thing I thought of):
create a filtered selection set (ss) of the lines
pick a point (pt1) close to the end(s) of the line(s) that you want the elbow placed pick another pt (pt2) for the rotation angle (setq ang (angle pt1 pt2)) loop thru the (ss) for each line, insert the elbow at the endpoint of the line closest to (pt), with the rotation of (ang) and change the insert's layer to match that line.
Done....

HTH,
Jeff
 
Interesting idea in your second paragraph about automating the whole set of insertions....

As far as (nentselp pt) finding something, and that thing being in the elbow block itself, this cannot be right, because when the code portion I posetd actually runs, the elbow block has NOT yet been inserted. All I have done is determined the insertion point of LATER FOLLOWING insertion of the elbow...

Of course a solution to all of this is to simply make sure I am zoomed far enough in!

thanks guys
 
See if this get you going. You should select your pipe where you want the elbow. If no pipe is selected then nothing, if there is then elbow will be inserted on the same layer as the pipe. You can add to this to do as Jeff suggested. Also I would look into error handlers. BTW I'm assuming that blank is your elbow???

(defun C:test (/ o-osmode a ent ee e n o-layer)
(setq o-osmode (getvar "osmode"))
(setvar "osmode" 512)
(setq a (getpoint "\nSelect Insert Point: "))
(setq ss (ssget "c" a a))
(setvar "osmode" o-osmode)

(if ss
(progn
(setq ee (ssname ss 0)
e (entget ee)
n (cdr (assoc 8 e))
)
(setq o-layer (getvar "clayer"))
(setvar "clayer" n)
(COMMAND "insert" "blank" a 1.0 "" 0)
(setvar "clayer" o-layer)
)
(princ "\nPipe not selected. ")
)
(princ)
)
 
More of my code; as discussed earlier, "blank" is simply a preview block for help on-screen when choosing the insertion point; this preview block is sized to apply to a multitude of my blocks that I insert using this same method, not just elbows...

(PROMPT "\nPick insertion point <Cancel to exit>... ")
(COMMAND "insert" blank PAUSE 1.0 "" 0)
(setq pt1 (getvar "lastpoint"))
(setq ee1 (nentselp pt1))
(setq ee (car ee1))
(if ee
(progn
(setq e (entget ee))
(setq n (cdr (assoc 8 e)))
(command "LAYER" "SET" n "")
))
(SETVAR "osmode" save_osmode)
(COMMAND "erase" "l" "");erase the blank after learning the insertion point

....
....insert the elbow or other block now...

(fittingname
(COMMAND "insert"
(STRCAT rootdir fitting)
"@"
skale
""
pause
)
(c:chgtofittinglayer); flip to the fitting layer

I see in your code Ken that you save the current layer name and reset it back after the routine; I eventually would have added that too.

best regards
 

Latest threads

Back
Top