AutoLISP read and write from file line by line

Discussion of other Lisp dialects (Arc, Clojure, AutoLisp, XLISP, etc.)

AutoLISP read and write from file line by line

Postby michielmm » Tue Oct 11, 2011 9:47 pm

Hi all,
I am rather new to AutoLISP and I'm still learning how to properly program it. I am running a AutoLISP to generate a field of circular polylines with position x,y and radius R read from a (user-selected) file.
At the moment I read the file completely before I start generating the polylines, but this causes me to run into the error "internal stack limit reached (simulated)". If I understood correctly, this means that I try to have to much in the memory at the same time, right?!

What I would like to do to get rid of this problem is to read the file line-by-line and write a polyline for each line immediately so that I only have to keep single lines in stack.

Can somebody help me/give me some pointers on how to adapt the code below to do this?!

Thanks!

Code: Select all
;; convert string to list of strings
(defun strlist (strExp strDel / strLst)
  (while (setq pos (vl-string-position (ascii strDel) strExp))
    (setq itm (substr strExp 1 pos))
    (setq strLst (append strLst (list itm)))
    (setq strExp (substr strExp (+ pos 2)))
  )
  (setq strLst (append strLst (list strExp)))
)

; read file
(defun readfile    (fname / line)
  (if (setq line (read-line fname))
    (if   (eq "" line)
         (readfile fname)
          (cons ( strlist (vl-string-trim " " line) " ") (readfile fname))
      )
    )
  )

;main prog

(defun C:CONN (/ adata fd fname itema)
(setq fd (getfiled "* Select \"PointA\" Data File *" (getvar "dwgprefix") "txt" 8))
(setq fname (open fd "R"))
(setq adata (readfile fname))
(close fname)
  (setq adata (mapcar (function (lambda(x)(vl-string-subst " " "\t" (car x)))) adata)
   adata (mapcar (function (lambda(x)(vl-string-subst " " "\t" x))) adata)
   adata (mapcar (function (lambda(x)(strlist x " "))) adata)
   adata (mapcar (function (lambda (x)
               (mapcar 'atof
               (mapcar (function (lambda (y)
               (vl-string-subst "." "," y))) x))))
             adata)
   )

    (while (setq itema (car adata))
   
         (entmake (list
         '(0 . "LWPOLYLINE")
         '(100 . "AcDbEntity")
         (cons 410 (getvar "CTAB"))
         '(8 . "0")
         '(62 . 7)
         '(100 . "AcDbPolyline")
         '(90 . 2)
         '(70 . 1)
         (cons 43  0.5)
         (cons 10 (list (- (car itema)(/ (caddr itema) 2)) (cadr itema)))
         '(42 . 1.0)
         (cons 10 (list (+ (car itema)(/ (caddr itema) 2 )) (cadr itema)))
         '(42 . 1.0)
         (cons 210 (list 0.0 0.0 1.0))))
       
     
      (setq adata (cdr adata))
      )
  (command "._zoom" "_e")
  (princ)
)
michielmm
 
Posts: 2
Joined: Tue Oct 11, 2011 9:37 pm

Re: AutoLISP read and write from file line by line

Postby michielmm » Thu Oct 13, 2011 1:50 pm

Hi all,
Just for the benefit of others: I solved the issue. I decided to learn a little more about LISP and rewrite the code altogether. Here it is:

Code: Select all
;;==============START OF THE ACTUAL CODE============================================================

;===================================================================================================
;=  Function  PARSE_NUMS (string)
;=  Arguments: string - Text string to be comma parsed
;=  Returns:   A list of the elements of the string converted to numbers
;=  Copyright Jeff Winship 2003. All rights reserved.
;=  www.pixelgraphicsinc.com
;==========================================================================================30/3/2003
(defun parse_nums (st / a k lst)
(setq k 1)
(setq a "")
(setq lst nil)
(repeat (strlen st)
(if (= (substr st k 1) ",")
(progn
(setq lst (append lst (list (atof a))))
(setq a "")
)
(setq a (strcat a (substr st k 1)))
)
(setq k (+ k 1))
)
(setq lst (append lst (list (atof a))))
)   

;=========================================================================================================
;=   Main Function C:rndfield
;=   Arguments: none (prompts for user selected file)
;=  Returns: plotted circles of radius R at x and y positions as described in the file (x,y,R)
;=   
;=   IMPORTANT NOTE, READ BEFORE USE:
;=   For some reason my version of AutoCAD (2010) fails if this LISP routine and the .txt file are in the
;=  folder. I do not know why, but it might be a problem for other AutoCAD versions as well.
;=   MAKE SURE THAT THE .txt FILE IS IN A DIFFERENT FOLDER THAN THE LISP FILE (SUBFOLDER IS ALSO WORKING)
;================================================================================================12/10/2011
   
(defun C:rndfield (/ dataline line fname fd)
   ; Prompt user to pick the input file, which should be .txt
   (setq fd (getfiled "* Select \"Pillar Construction\" Data File *" (getvar "dwgprefix") "txt" 8))
   
   ; Actually open the filename for reading and give it fname as handle
   (setq fname (open fd "R"))
   
   (setq dataline (read-line fname))                  ;read the first line of data
      (while (/= dataline "EOF")                      ;the EOF should be included as last line in the datafile!!!
            (setq dataline (parse_nums dataline))        ;reformat the data to a CAD readable list
            
            ;operations to generate a circle at location dataline(1), dataline(2) with radius dataline(3)
            ;the normal circle command is not used, because outputcity prefers to have polylines
            (entmake (list
            '(0 . "LWPOLYLINE")
            '(100 . "AcDbEntity")
            (cons 410 (getvar "CTAB"))
            '(8 . "0")
            '(62 . 7)
            '(100 . "AcDbPolyline")
            '(90 . 2)
            '(70 . 1)
            (cons 43  0.5)
            (cons 10 (list (- (car dataline)(/ (caddr dataline) 2)) (cadr dataline)))
            '(42 . 1.0)
            (cons 10 (list (+ (car dataline)(/ (caddr dataline) 2 )) (cadr dataline)))
            '(42 . 1.0)
            (cons 210 (list 0.0 0.0 1.0))))
            ;end of the operation
            
            (setq dataline (read-line fname))           ;read a new line
      )
   
   ; Close the file
   (close fname)   
   
   ; Zoom to fit all structures on the screen
   (command "._zoom" "_e")
   
   ; Print empty line to avoid `nil' response from the LISP routine
   (princ)
)

;Print this command in the commandline of AutoCAD as instruction on how to execute
(princ "\n\t\t***\tType rndfield to execute\t***")
(princ)
michielmm
 
Posts: 2
Joined: Tue Oct 11, 2011 9:37 pm


Return to Other Dialects

Who is online

Users browsing this forum: No registered users and 3 guests

cron