Author Topic: Code to auto-update blocks. . . help?  (Read 10317 times)

0 Members and 1 Guest are viewing this topic.

tcdan

  • Guest
Code to auto-update blocks. . . help?
« on: July 05, 2005, 11:18:18 AM »
I would like to write a LISP and would really appreciate some help (to be honest – this will be the first time I’ve really attempted to write one – I have always been able to find one already written before).

PSEUDOCODE:
Program ‘annotatep’
1.   User chooses polyline as an object (ensure object is polyline)

Program ‘annotate’
1.   Let user choose point on polyline (ensure point is on polyline)
2.   Insert block ‘anno’ at point
  a.   Predefined block has text in it including an integer (ex. “Air Release Valve Sta. 200")
  b.   Value of integer should be the distance from the beginning of the pline to the insertion point of the block on the pline
3.   If block is moved along pline, update integer field (only if insertion point of block is on polyline)


MY FIRST ATTEMPT (OK, so I have a LONG way to go):
Code: [Select]

(vl-load-com)

; Program loops until user selects a polyline
(defun c:annotatep ( \ obj pline)
  (while type( = pline ???)
    (setq obj (car (entsel “\n Select polyline: “)))
    (setq anno_pline (vlax-ename->vlax-object obj))
  )
)


; Determines if point ‘pt’ is on the polyline
(defun c:pointOnLineCheck (pt)

)


(defun c:annotate (userPt)
  (if anno_pline ; check to see that pline has been selected
   (progn

    ;; loop until user picks point on polyline
    (while (= -1 pointOnLineCheck(userPt))
      (setq userPt (getpoint “\n Pick a point on the polyline: “))
    ) ; end while

    ;; insert block ‘anno’ at point ‘userPt’
    (command insert ? ? ? ) ; bad to use 'command' with VLISP I think


    ; determine distance along pline to selected point
    (vlax-curve-getdist distOnPline ? ? ?)


    ;update block to reflect distance along curve ? ? ?
    ; use field/rtext/reactor?


   )
  princ “A polyline has not been selected with ANNOTATEP”)
)




OK, well anyone care to throw a bone? (with some meat on it)?  I plan on writing this code until it works, even if it takes me all month of working on it here and there and learning the language.  I told my boss how I wanted to automate some of the work we do and he just laughed at me like “Yeah, that’s nice and after you’re done dreaming just finish it OK?”

daron

  • Guest
Code to auto-update blocks. . . help?
« Reply #1 on: July 05, 2005, 12:37:55 PM »
First, ask yourself, what's TYPE going to return? Check the help files for this. You won't see that it returns a PLINE or any specific object type. To get a specific object type, use (ssget ":S" '((0 . "*POLYLINE"))). You can use entsel or nentsel, but it takes more work to get the filter working.

What is the point going to represent on the pline? Take note that a point is a set of coordinates in space, not on an object. If you have overlaps, you could inadvertently pick a different object if you intend to use these coords for selecting objects.

tcdan

  • Guest
Code to auto-update blocks. . . help?
« Reply #2 on: July 05, 2005, 01:20:31 PM »
OK, thanks for the help on the TYPE function.

Quote
What is the point going to represent on the pline?

I would snap the insertion point of the block to a point on the polyline.  This point would be referenced as a coordinate.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Code to auto-update blocks. . . help?
« Reply #3 on: July 05, 2005, 01:38:57 PM »
A quick problem you might run into is determining where on the pline the point lies ... at least programmatically it is difficult.

If you are using 2d polylines (lwpolyline), you might need to extract the entire list of points and attempt to determine (likely with a fuzz factor) if your selected point falls between two points of the polyline. In 3d space it gets decidedly more difficult too.

A quick primer follows:
Code: [Select]

(defun ispointbetween (BeginPoint EndPoint TestPoint FuzzFactor / ang1 ang2 RetVal)(setq ang1(angle BeginPoint EndPoint)
        ang2(angle BeginPoint TestPoint))
(If (equal ang1 ang2 FuzzFactor)
  (setq RetVal T)
  (setq RetVal nil)
)
RetVal
)


Now you will have to do a whole lot more math to determine if the point is on an arc of a polyline, but the abovce should get you pointed in the right direction for actually getting this part done.

You need to loop through the entire polyline until you get a T returned or reach the end of the polyline. You might find it easier to extract the distance between the points as you go ... once T is returned you can calculate the distance between the last beginpoint and your testpoint.

One more caveat .... seldom does comparing points and/or angles relating to points that the user selects return a T value since the test is to a limited number of decimal points that the user can see, which is why you need to have a fuzz factor. To see what I mean, draw a line and use this:
Code: [Select]

(ISPOINTBETWEEN (GETPOINT) (GETPOINT) (GETPOINT) 0.0)


Now try this one selecting the same points
Code: [Select]

(ISPOINTBETWEEN (GETPOINT) (GETPOINT) (GETPOINT) 0.01)


You also need to add to the code above something to make sure the point is actually BETWEEN the two points and not just along the same line
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Find me on https://parler.com @kblackie

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Code to auto-update blocks. . . help?
« Reply #4 on: July 05, 2005, 02:10:58 PM »
Well here is lisp I started, perhaps too much for a start.
It gives you the outline & error function with sys var routines.
You will need them eventually.
I got you to the pick a point on a lwpolyline & the distance.
I did not complete the subroutines so you may want to make some
choices there.
I'll leave it with you to play with.

anno.lsp
This is a rather ambitious routine for your first time out. :)

The final piece of the pie will require a reactor.
I'm sorry I can not participate anymore but I will be busy for the rest of this week.
Looks like you are in good hands though.
Lot's of em around here.
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

tcdan

  • Guest
Code to auto-update blocks. . . help?
« Reply #5 on: July 05, 2005, 02:14:25 PM »
Wow Keith, I see this part alone could take some work.

I want the user to tell CAD where to put the insertion point of a block.  So what if I just turned osnap on, checked to see if the user clicked on the polyline, and then found the coords of the insertion point of the block. . . that way I wouldn't have to find any coords on the pline at all.

daron

  • Guest
Code to auto-update blocks. . . help?
« Reply #6 on: July 05, 2005, 02:22:51 PM »
Don't forget to look into vlax-curve-parameters. These beauties are a treat when dealing with polylines.

As far as placing a block on a "LINE", I'm soon going to get to work on a procedure that will have the user select a line and a point at which to insert the block, then have it figure out the angle of the line and the coordinates where to place it based on what was originally selected. I'll see how generic I can make it, so it'll hopefully work with more than just line objects.

tcdan

  • Guest
Code to auto-update blocks. . . help?
« Reply #7 on: July 05, 2005, 05:01:04 PM »
Hey thanks CAB!  I'll have a look later on - kinda busy today and prolly tomorrow.  I hope you didn't do ALL of it for me :)

I hope to learn as I piece some of it together.

daron

  • Guest
Code to auto-update blocks. . . help?
« Reply #8 on: July 07, 2005, 10:15:09 AM »
tcdan, for this:
Code: [Select]
; Program loops until user selects a polyline
(defun c:annotatep ( \ obj pline)
  (while type( = pline ???)
    (setq obj (car (entsel “\n Select polyline: “)))
    (setq anno_pline (vlax-ename->vlax-object obj))
  )
)

take note of  >this<.
Stig does an excellent job at making sure you get the desired object.

tcdan

  • Guest
Code to auto-update blocks. . . help?
« Reply #9 on: July 18, 2005, 07:20:51 PM »
OK - I finally have a few minutes to look at this code again. . . progress at a turtle's pace, but still moving.


CAB - still haven't looked at your code, but I will soon.  I need to take a good chunk of time to read through all that you wrote and learn what the functions do.  I really appreciate your help though.


Daron -
I used CAD's help menus trying to get a handle on the difference between SSGET and NENTSEL to understand why I wouldn't always just use SSGET to pick the object I want. . . All that I'm coming up with right now is that NENTSEL works with attributes and subentities (both of which I'm not concerned with in picking a polyline).

So I don't know why I wouldn't use (ssget ":S" '((0 . "*POLYLINE"))) as you suggested at first.

However, I DID look at Stig's code for awhile, via your link.  I don't know the scope of the applications of the code, getSubent, but it seems quite versatile and reusable since you can pass it whatever user prompt and entity type for filtering that you desire.  I can see it being more useful than ssget due to its ability to select subentities.  Thanks for the learning - I discovered nentsel, member, and the variable ERRNO (although I don't know why the variable 'parent' was declared in the function...)

edited: EERNO --> ERRNO

tcdan

  • Guest
Code to auto-update blocks. . . help?
« Reply #10 on: July 18, 2005, 07:39:23 PM »
Maybe I should say progress at a newt's pace :)

daron

  • Guest
Code to auto-update blocks. . . help?
« Reply #11 on: July 18, 2005, 11:24:32 PM »
To add to the stress. Think about this: At the moment, you have no need for a nested object selection and you may never. Anyhow, all of a sudden you have a need for a selection of an object or a user other than yourself gets ahold of your code and starts using it. If he selects a nested object, the code could very well be set and ready to go. However, if you don't have the ability to grab a nested object, your user is most likely going to come up to you one day complaining about how that "Killer" app you asked him to use isn't working. You want to tell him that it's probably because he selected an object that he shouldn't be selecting, except Mark can tell you all about how you should never blame your users for selecting objects they shouldn't. If you expect that someone else might use your code, you should have checks and balances built into it, so that if your users pick something they shouldn't they are either told they need to select a different object or allow them the option to exit out safely. The nentsel and *(ssget ":SN" '((0 . "*POLYLINE"))) will ensure that nested selected items can still get processed or their lists can still be collected. It's just nice to have failsafes for such occasions. I know there are times when you really just don't need to care, but you never know.

*Not sure if I got the ":SN" in there correctly. That can be a tricky filter at times. S=single object selection mode and N=nested object selection. If I remember correctly, you can combine them as I've shown and you should be able to only select one nested object as long as you select an object.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

daron

  • Guest
Code to auto-update blocks. . . help?
« Reply #13 on: July 19, 2005, 11:27:04 AM »
Well, I thought you should be able to group those together. Either way, S for single selection and N for nested selection.

whdjr

  • Guest
Code to auto-update blocks. . . help?
« Reply #14 on: July 19, 2005, 11:49:06 AM »
You can group those togethor Daron:

Code: [Select]
(ssget ":S:N")