Author Topic: Need LISP Routine to read ASCII file and generate a 3Dpoly  (Read 13508 times)

0 Members and 1 Guest are viewing this topic.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #15 on: February 19, 2005, 06:15:42 PM »
I can't recommend a book, but Stig Madsen and Kenny Ramage have some excellent web articles / tutorials:

www.SMadsen.com
www.AfraLISP.com


3Dpolys cannot be joined using the vanilla product, but a roll-yer-own utility could emulate that.

:)
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Carl

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #16 on: February 19, 2005, 07:07:58 PM »
Not to dissuade you from pursuing writing a routine, but....
Quote
I'm doing that now - copy/paste - but its very time consuming.


If you have a file of coordinates, or a column of coordinates in Excel, you need only *one* copy and paste of all the coordinates....were you doing it this way?

Anonymous

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #17 on: February 19, 2005, 08:23:04 PM »
Carl - No I was doing it one at a time - never thought of taking a list of them from excel and putting them into AutoCAD - thanks for the tip.

Not to worry - I will still work on making that Lisp routine that started this whole discusion.

Thanks again,

grdruck

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #18 on: February 21, 2005, 12:07:21 AM »
Hi all - here is what I have so far.  I found a Lisp routine that reads a file so I copied it (hope thats not Plagiarism) and cut out the lines that did not pertain to what I was trying to do.

So here we go... (drum roll please...)
Code: [Select]

;   My3Dpoly.LSP
;   Written by Garth Druckenmiller on February 20, 2005
;      with help from various sources.  

(defun C:MY3DPOLY ()

(Prompt "\nMY3DPOLY - Draws a 3Dpolyline by reading input from coordinates file")

(Setq FILENAME (getstring "\nName of coordinate file to input : "))

(Setq FILEUNIT (open FILENAME "r"))

(setq OLD_CMDECHO (getvar "CMDECHO"))
(setvar "CMDECHO" 0)

(setq COUNTER 1)

(While (setq LINE_INPUT (read-line FILEUNIT))

(prompt (strcat "\rProcessing line number : " (itoa COUNTER)))

(setq PT LINE_INPUT)

(command ".3DPOLY" PT "")

(setq COUNTER (1+ COUNTER))
)

(close FILEUNIT)

(setvar "CMDECHO" OLD_CMDECHO)

(prompt " Program complete.")
(princ)
)

sample data...

5713.10,1208.40,40.00
5762.70,1260.90,40.00
5766.40,1262.10,45.00
5934.50,1316.80,45.00
5989.00,1325.10,47.00
6279.70,1365.90,49.00
6284.80,1366.30,36.00
6421.40,1356.00,36.00
6570.60,1347.60,49.00
6771.80,1348.00,49.00
7081.90,1321.20,43.00
7138.80,1367.00,22.00
7226.20,1354.70,21.00
7298.50,1344.80,21.00
7346.10,1319.60,25.00
7454.90,1294.00,30.00


It runs but I don't see anything in AutoCAD.  My thinking is that is has something to do with the 3DPOLY command - I have an old AutoLISP book and that command is not in it - Can someone tell me the sintex of that command.  Thanks,

Talk with you guys soon,

Fuccaro

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #19 on: February 21, 2005, 01:37:56 AM »
Grdruck

You have the coords in a text file. It should be simple to transform it in a script file.

SMadsen

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #20 on: February 21, 2005, 04:16:55 AM »
The code you picked is very well demonstrating the overall technique of reading a text file in AutoLISP. It asks for a filename, opens the file, enters a loop while reading lines and closes the files. That's pretty much the way to do it. As you correctly suspect, the problem is with the use of COMMAND.

The "syntax" of any native AutoCAD command when executed via the COMMAND function corresponds to the sequence of execution in AutoCAD. With that in mind, what does the COMMAND function inside the loop do? If you're not aware of it already, an empty string passed to COMMAND acts as Enter/Return. So the command will initiate 3DPOLY, give it a point and return to the command line, i.e. finish the command. It does this for each line - or each point - in your file, which means that it'll create tiny zero length 3DPOLY's all over your drawing.

The trick is to call 3DPOLY one time, pass it points while the command is still active and terminate the command after you run out of lines to read (i.e. points):
Code: [Select]
...
;; start 3DPOLY command (as you would in AutoCAD)
  (command ".3DPOLY")
  (While (setq LINE_INPUT (read-line FILEUNIT))
    (setq PT LINE_INPUT)
    ;; pass the active command a point (as you would in AutoCAD)
    (command PT)
  )
  ;; finish the command (as you would in AutoCAD)
  (command "")
...


Try incorporate this piece in the code. After you got it working, we can maybe hint at some other improvements.

grdruck

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #21 on: February 21, 2005, 10:50:00 AM »
Thanks

Fuccaro
Not sure what a script is except a list of item one after another - in all my years doing drawings with AutoCAD I never used one - I should look into this - where could I find it

SMadsen
Thanks for your advice - Last night when I went to bed I thought I should break that line up (ie: command ".3DPOLY" PT "") but didn't know how to do that - since I very new to this programming LISP

Yes I have a file called MY3DPOLYDATA.DAT that I created with a text editor

I added your suggestions into my routine and it works!  But it exicutes very, very slowly.  It maybe my computer.

This is what I have now...

(defun C:MY3DPOLY ()

   (Prompt "\nMY3DPOLY - Draws a 3Dpolyline by reading input from coordinates file")

   (Setq FILENAME 3(getstring "\nName of coordinate file to input : "))

   (Setq FILEUNIT (open FILENAME "r"))

   (setq OLD_CMDECHO (getvar "CMDECHO"))
   (setvar "CMDECHO" 0)

   (setq COUNTER 1)

   ;; start 3DPOLY command (as you would in AutoCAD)
   (command ".3DPOLY")

   (While (setq LINE_INPUT (read-line FILEUNIT))

      (prompt (strcat "\rProcessing line number : " (itoa COUNTER)))

      (setq PT LINE_INPUT)
      
      ;; pass the active command a point (as you would in AutoCAD)
      (command PT)

      (setq COUNTER (1+ COUNTER))
   )

   ;; finish the command (as you would in AutoCAD)
   (command " ")

   (close FILEUNIT)

   (setvar "CMDECHO" OLD_CMDECHO)

   (prompt " Program complete.")
   (princ)
)

Why would it exitcute so slow?  any suggestions on that

Also, when it stoped I got the error message:

Point or option keyword required.
; error: Function cancelled

this was displayed after no more records in file.

grdruck

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #22 on: February 21, 2005, 11:00:48 AM »
I ran it with the debuger on - after turning it off it works quickly - except for the error and also the (command "") is not ending the command bc It still looking for a point or <return> character - how do you type a return character into the above code?

Thanks

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #23 on: February 21, 2005, 11:20:41 AM »
Not an answer to your question but, you might want to turn your osnaps off before running that.
TheSwamp.org  (serving the CAD community since 2003)

SMadsen

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #24 on: February 21, 2005, 11:26:30 AM »
The "" -thingie is not a space but an empty string. Just type two double quotes as close as if they were trying to make single quotes.

nivuahc

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #25 on: February 21, 2005, 11:27:15 AM »
Isn't it great when people catch on so quickly?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16899
  • Superior Stupidity at its best
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #26 on: February 21, 2005, 11:55:26 AM »
Where you have
Code: [Select]

(command " ")


change it to
Code: [Select]

(command "")


FYI if you paste your code into a code window using the BBCode tags, it will differentiate it a little better and make it easier to read.
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
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #27 on: February 21, 2005, 12:01:09 PM »
You could do something like this to break the plines.
Look into the getfile function, you may want to use it.

Code: [Select]
(defun c:my3dpoly ()

  (prompt
    "\nMY3DPOLY - Draws a 3Dpolyline by reading input from coordinates file"
  )

  (setq filename 3
        (getstring T "\nName of coordinate file to input : ")
  ) ; T added to allow spaces in file name, CHR 32
  ;;  need to check for a valid file name or loop using findfile

  (setq fileunit (open filename "r"))

  (setq old_cmdecho (getvar "CMDECHO"))
  (setvar "CMDECHO" 0)

  (setq counter 1) ; vertix counter

  ;; start 3DPOLY command (as you would in AutoCAD)
  (command ".3DPOLY")
  ;;  read the text file & create a pline
  (while (setq line_input (read-line fileunit))
    (prompt (strcat "\rProcessing line number : " (itoa counter)))
    (setq pt line_input)
    (if (= pt "") ; blank line, so break pline
      (progn
        (command "") ; end current pline
        (command ".3DPOLY") ; start another pline
      )
      (command pt)
    )
    (setq counter (1+ counter))
  )

  ;; finish the command (as you would in AutoCAD)
  (command "")

  (close fileunit)

  (setvar "CMDECHO" old_cmdecho)

  (prompt " Program complete.")
  (princ)
)


Quote
5713.10,1208.40,40.00
5762.70,1260.90,40.00
5766.40,1262.10,45.00
5934.50,1316.80,45.00  ; creates a gap in the line

5989.00,1325.10,47.00
6279.70,1365.90,49.00
6284.80,1366.30,36.00
6421.40,1356.00,36.00
6570.60,1347.60,49.00

6570.60,1347.60,49.00  ; same point as above so break pline but no gap
6771.80,1348.00,49.00
7081.90,1321.20,43.00
7138.80,1367.00,22.00
7226.20,1354.70,21.00
7298.50,1344.80,21.00
7346.10,1319.60,25.00
7454.90,1294.00,30.00
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.

t-bear

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #28 on: February 21, 2005, 04:08:11 PM »
Garth......

I told you!!! :lol:  :wink:  :lol:

Peter Jamtgaard

  • Guest
Need LISP Routine to read ASCII file and generate a 3Dpoly
« Reply #29 on: February 21, 2005, 05:47:45 PM »
:roll:

Hey swamp...

I was just reviewing a few posts and stumbed onto this thread. I noticed some code that was creating a 3dpoly from an ascii text file. I was just playing around and came up with this routine. It includes a couple useful routines that you all might enjoy reviewing.

Bon apetite.

Peter Jamtgaard

Code: [Select]

; Create a 3dpolyline in the active viewport
; From a specified CSV file using activeX
; Syntax (asciipoly "mycsvfile.csv") for example


(defun ASCIIPOLY (strCSVFileName / lstCoordinates lstVertices)
 (setq lstVertices (csvfiletolist (findfile strCSVFileName) ","))
 (foreach lstPoint (reverse lstVertices)
  (foreach sngCoord (reverse lstPoint)
   (setq lstCoordinates (cons sngCoord lstCoordinates))
  )
 )
 (vla-add3dpoly
  (vla-get-block
   (vla-get-activelayout
    (vla-get-activedocument
     (vlax-get-acad-object)
    )
   )
  )
  (listToSafeArray 5 lstCoordinates); the #5 specifies a real number
 )
)

; Convert a csv file to a list
; Syntax (csvfiletolist "mycsvfilename.csv" ",")
; The comma being the delimiter

(defun csvFiletoList (strFilename strChar / lstOfSublists strText z)
 (setq z (open strFilename "r"))
 (while (setq strText (read-line z))
  (setq lstOfSublists (cons (CSVStringToList strText strChar)
                                     lstOfSublists)))
 (close z)
 (reverse lstOfSublists)
)

; Convert a list into a safearray

(defun ListToSafearray (symVariableType lstValues / safValues)
 (setq safValues (vlax-make-safearray symVariableType
                                                        (cons 0 (1- (length lstValues)))))
 (vlax-safearray-fill safValues lstValues)
)


; Safearray types for your reference

;vlax-vbInteger  (2)  Integer
;vlax-vbLong     (3)  Long integer
;vlax-vbSingle   (4)  Single-precision floating-point number
;vlax-vbDouble   (5)  Double-precision floating-point number
;vlax-vbString   (8)  String
;vlax-vbObject   (9)  Object
;vlax-vbBoolean (11)  Boolean
;vlax-vbVariant (12)  Variant