Jump to content

Recommended Posts

Posted

Hi!

i have studyd Alisp for a while and gone through functions and stuff. But where do i stuck is when i start writing something on my own. It seems that i don ot get the logic steps how to get my result. I do not probably understand how do logically build up the program.

Any help where i could overcome that?

Thanks

Posted (edited)

May try to follow the tutorials from AfraLISP to see how a routine is build. But please keep in mind that although some common rules apply, there is no a general, imposed, one on how a routine should be build. If it works, then your technique is good. After will gain experience, then may start looking for code optimization and good programming practices.

If you have a routine in mind please describe it here and me or someone else will try to draw a code flowchart for you.

Edited by MSasu
Spelling
Posted

Welcome to CADTutor Einsener, I hope you enjoy your time here.

 

When writing a program, try to compartmentalise the various tasks required to achieve the overall result and focus on writing the code for each task before conglomerating each of the smaller segments of code to form the whole program.

 

To give an example: let's say you want to write a program that will print the length of a line in the drawing.

 

Firstly, break the program down into the general tasks:

  • Retrieve the Line

 

  • Compute the Length

Now, we can break this down further, for example, what is involved in computing the length?

  • Prompt the user to select a Line

 

  • Retrieve the coordinates of the Line endpoints

 

  • Compute the distance between the coordinates

 

  • Print the result to the command-line

Now we can think about how we might accomplish each of these tasks and what functions and logic might be involved:

 

  • Prompt the user to select a Line:
    • entsel function
    • Test for valid user input (if function)
    • Test that the object is a Line (Check DXF Group 0 of the Line DXF data)

     

 

  • Retrieve the coordinates of the Line endpoints:
    • Retrieve the DXF data for the Line using the entget function
    • Retrieve the Line endpoints: assoc function to retrieve DXF Group 10 and 11
    • Retrieve the associated coordinate values using the cdr function

 

  • Compute the distance between the coordinates:
    • AutoLISP provides the convenient distance function specifically for this purpose.

 

  • Print the result to the command-line:
    • Consider the princ / print / prin1 functions for this task.
    • Perhaps look into rtos to format the result in certain units or precision
    • strcat may be required if you want to print other content with the result.

     

Now that we have constructed a detailed list of the various operations that the program needs to perform, we can begin to write code for each task in turn:

 

  • Prompt the user to select a Line:

  • entsel
    function:

(setq ent (car (entsel "\nSelect a Line: ")))

  • Test for valid user input using
    if
    function:

(if (setq ent (car (entsel "\nSelect a Line: ")))
   ...

  • Test that the object is a Line:

(if
   (and
       (setq ent (car (entsel "\nSelect a Line: ")))
       (= "LINE" (cdr (assoc 0 (entget ent))))
   )
   ...

Now that the first task is completed, we have the Line entity to use in the remainder of the program, so we can now focus on the remaining tasks, which I leave to you to complete.

Posted

Lee, that's a really great tutorial. Congratulations!

Now, waiting for OP to accept your challenge.

Posted

Thank you Mircea, I wrote it rather hastily, no doubt it could be improved :)

Posted

Lee; excellent post, and you're exactly right... It all boils down to specified and implied tasks.

 

Well done! :beer:

Posted

Not to detract from Lee's excellent post, the OP's question is probably the hardest thing to grasp for any aspiring programmer.

 

I could describe the process as you attempting to figure out with what, where and when to prod the computer in order to get a useful result. You have to first figure out that a computer is actually an extremely stupid thing - it definitely is not complex and/or difficult. It is literally nothing more complex than a light-switch ... just multiplied many-fold.

 

So actually the problem is you need to dumb yourself down to the level where the computer can understand what you want. The way you go about this is to split your request down to a set of as small steps as you can. It sounds stupid, but it's because the computer is stupid. Fortunately you don't have to go all the way down, i.e. you don't have to figure out which switches you need to turn on and which to turn off. For that the "language" is used (in this case AutoLisp) - making it less cryptic to tell the computer "I want you to do this".

 

So to get at what Lee's indicated: I see this as a recursive process. You start of with stating your problem as a statement or order.

 

Show the length of a line

 

Next you split that into what you can see would be the steps to achieve this. E.g.:

 

  1. Ask the user "Which line"
  2. Get the line's data
  3. Calculate its length from that data
  4. Display the answer

After the first recursion, see if any of the statements can easily be done already. E.g. the 1st one is already a function in AutoLisp called entsel (for Entity Select). Note it, but don't think of it as carved in stone - perhaps later you'll see that you might need something different.

 

 

Some of those statements might need a further recursion. E.g. item 3 can be split up thus:

 

  1. Extract the endpoints from the data
  2. Get the distance between the endpoints

From this you can use the assoc function for item 3.1 to get the endpoints from the data you obtained in item 2. And the distance function for item 3.2.

 

 

After you've gone through each item (and it's sub-items) and have a set of possible code for use on each of the last splits, you're ready to attempt your code. Let's say you make it a command:

(defun c:ShowLineLength (/ en ed pt1 pt2 len)
 (setq en (entsel "Pick the line: ")) ;Item 1
 (setq ed (entget (car en))) ;Item 2
 (setq pt1 (cdr (assoc 10 ed)) pt2 (cdr (assoc 11 ed))) ;Item 3.1
 (setq len (distance pt1 pt2)) ;Item 3.2
 (princ len) ;Item 4
 (princ) ;Exit the command without displaying other stuff
)

I've added some best practice in localizing the variables in the defun, this just helps that it doesn't interfere with something outside the defun.

 

Now the above will work if nothing goes wrong. So you test it. You find it works reasonably. But you test it some more and purposefully try to give it erroneous input. And then find some strange things like, say when asked you pick a polyline instead. Something like

; error: bad argument type: 2D/3D point: nil
is displayed.

 

Or picking on a blank spot on the drawing:

; error: bad argument type: lentityp nil

 

Ok, so now you think: "I need to keep track of what entity type this is and if an entity was actually picked". So you go back to your steps and try to figure out which step you didn't think of sufficiently. Was it 1 or 2?

 

Well, they're performing what they intended to. Perhaps I missed a step in between. Perhaps there should have been a step like:

1A. Check if line is selected

 

Which you can further split to:

 

  1. Check if something is selected
  2. Check if it's a line

So now you get to similar code as per Lee's. Something with an if statement. You could have made it like this:

(if (setq (en (entsel "Pick Line: "))) ;Item 1 and 1A.1

 (if (eq (cdr (assoc 0 (entget (car en)))) "LINE") ;Item 1A.2
   (progn
     (setq ed (entget (car en))) ;Step 2

     ;; Continue the other steps here
   )
 )
)

But that's a bit silly, rather combine the 2 checks using an and (like in Lee's sample).

 

 

But you notice another thing ... the code for Step 2 is written twice. Could you make it simpler and/or more efficient? What about going this route:

(if (and (setq en (entsel "Pick line: ")) ;Step 1 and 1A.1
        (eq (cdr (assoc 0 (setq ed (entget (car en))))) "LINE")) ;Step 1A.2 and 2
 (progn
     ;; Other steps here
   )
)

This is something which happens quite often in Lisp. This is because every function in lisp returns the result of what it did last. So the setq returns the value it has just set into the ed variable. Therefore you can use that return value directly in the check.

 

 

You continue doing this until you feel you've tested it enough and sorted out any problems you may have run into. This is what's known as the debugging phase, and mostly takes up the largest portion of your time.

 

 

Don't be despondent though, with practice you tend to teach yourself the possible pitfalls and the back-and-forth on your original steps becomes less. Next time you'll think "Ah selecting a line, means I have to also check if it's a line". Thus your first try would already have such checking code. The more you get used to it, the more you find the same thing happens and it almost becomes second nature to think of such stuff.

 

 

Now, remember I said those steps are not cast in stone? What if you want to change you command to sum multiple lines' lengths together? Would you still use entsel, or would you consider ssget? Are you sure you only want lines? Perhaps you want to also include polylines, or perhaps any entity with a length that can be calculated.

Posted

Fantastic post Irné - you succeeded in providing a far more thorough, structured and detailed explanation of precisely what I was attempting to convey to the OP, well done!

Posted
Fantastic post Irné - you succeeded in providing a far more thorough, structured and detailed explanation of precisely what I was attempting to convey to the OP, well done!
Thanks Lee ... though I might have to figure out which of my teachers I've ripped off :shock: That's a lot like the Programming 101 course's 1st class :roll:
Posted

Let's just hope that our posts and time have not been in vain - it seems the OP has vanished!

Posted

The only problem I can see might be an issue is that it appears the OP has translated his post. From his moniker he must be from some Germanic language - not sure which though. And if I use Google Translate on this thread into Afrikaans (my home language) I actually have difficulty understanding the post I just wrote myself! :unsure: The grammar goes all wonky, not to mention wrong words used as in "turn switch" translates to "turn a dial" - which is simply WRONG.

Posted

Another suggestion when working with lots of polar pt answers pt1 pt2 pt3 etc I draw a hand sketch it helps to remember what point you have labelled where, eg 3d pitched roof.

Posted
OP could be from Estonia if that helps.

I figured something like that yes ... Meinsener (est) = Mining Engineer (eng). Unfortunately I can only converse in Afrikaans, Flemish & Dutch (in descending order of fluency - Dutch being extremely poor). Here'n'there a word of German, but I can hardly understand when a German speaks. So I'd not be able to explain much in Estonian at all.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...