AutoLISP read and write from file line by line

Discussion of other Lisp dialects (Arc, Clojure, AutoLisp, XLISP, etc.)
Post Reply
michielmm
Posts: 2
Joined: Tue Oct 11, 2011 9:37 pm

AutoLISP read and write from file line by line

Post by 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

Post by 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)

Post Reply