Visual LISP, AutoLISP and General Customization
cancel
Showing results forĀ 
ShowĀ Ā onlyĀ  | Search instead forĀ 
Did you mean:Ā 

Read a file and cons question question

17 REPLIES 17
Reply
Message 1 of 18
richie_hodgson
889 Views, 17 Replies

Read a file and cons question question

Hi i have a file that contains a list of 3 space deliminated entities, first is a two letter code, then  x and y coordinates. There are only 5 diferent codes. I would like to construct 5 seperate lists based on their code containing just their coordinates so I can draw 5 seperate polylines. I am suffdering from holiday brain at the moment and can't think this one out.

Richie
17 REPLIES 17
Message 2 of 18


@richie_hodgson wrote:

Hi i have a file that contains a list of 3 space deliminated entities, first is a two letter code, then  x and y coordinates. There are only 5 diferent codes. I would like to construct 5 seperate lists based on their code containing just their coordinates so I can draw 5 seperate polylines. I am suffdering from holiday brain at the moment and can't think this one out.


I am not quite sure exactly what you are trying to do, but the following might be useful working with this:

 

(defun file-to-list (filename / file result line)
  (if (findfile filename)
      (progn (setq file (open filename "r"))
             (while (setq line (read-line file))
               (setq result (cons line result)))
             (close file)
             (reverse result))
      (alert (strcat "File " filename " not found!"))))


(defun split-string (str delim / pos)
  ;; Splits a string into a list of strings at every occurrence of the delim (single-letter string).
  (setq pos (vl-string-position (ascii delim) str))
  (if (null pos)
      (list str)
      (cons (substr str 1 pos)
            (split-string (substr str (+ pos 2)) delim))))

 --

Message 3 of 18
stevor
in reply to: richie_hodgson

Then, post enough of that data  list to try.

 

 One way, make type-point sub-lists,

then separate them into point lists for each type.

As martti posted, you probably get a sublist of 4 strings:

a 2 character type, then the x, y and z strings.

The type 'code' would be that 2 letter string, and

the point data wold be 'ATOF of each x, y, and z string:

(list (ATOF sx) (Atof sy) (ATOF sz))

S
Message 4 of 18
Hallex
in reply to: richie_hodgson

If I understand you right

something like this might helps

(Martti beat me for that šŸ™‚

_____________________________________

;;tryit.lsp

 

(defun file-to-list (filename / file result line)
  (if (findfile filename)
    (progn (setq file (open filename "r"))
    (while (setq line (read-line file))
      (setq result (cons line result))
    )
    (close file)
    (reverse result)
    )
    (alert (strcat "File " filename " not found!"))
  )
)

(defun split  (txt sep)
  (if (not (eq sep txt))
    (if (setq pos (vl-string-search sep txt 0))
      (cons (substr txt 1 pos)
     (split (substr txt (+ pos 1 (strlen sep))) sep))
      (list txt)) )
  )

(defun split-string (str delim / pos)
  ;; Splits a string into a list of strings at every
  ;; occurrence of the delimiter (single-letter string).
  (setq pos (vl-string-position (ascii delim) str))
  (if (null pos)
    (list str)
    (cons (substr str 1 pos)
   (split-string (substr str (+ pos 2)) delim)
    )
  )
)


(defun uniques (lst)
  (if (car lst)
    (cons (car lst)
     (uniques (vl-remove (car lst)(cddr lst))
   )
    )
  )
)

 

(defun C:tryit(/ acsp delim dirty fn groupped pline_coords uniq_list x)
  (setq fn (strcat (getvar "dwgprefix") "aha.csv"));<-- change file path here
  (setq delim ";")
  (if (findfile fn)
    (setq dirty (file-to-list fn)))
     (setq dirty (mapcar '(lambda(x)(split x delim))dirty))
  (setq uniq_list (uniques (mapcar 'car dirty)))
(setq groupped nil)
  (while (car uniq_list)
    (setq groupped (cons (cons (car uniq_list)
          (mapcar 'cdr
           (vl-remove-if
      '(lambda (a)
         (eq (car a) (car uniq_list))
       )
      dirty
           )
          )
    )
    groupped
     )
    )
    (setq uniq_list (cdr uniq_list))
  )
(setq pline_coords ( mapcar '(lambda(x)(mapcar 'atof (mapcar 'car x)))(mapcar 'cdr groupped)))
(if pline_coords
  (progn
    ;; you may want to use other methods to draw plines here
    (vl-load-com)
 (setq acsp (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object)))))
    (foreach item pline_coords
      (vl-catch-all-apply 'vlax-invoke
 (list acsp 'AddLightWeightPolyline item)
 )
;;;     if every vertex record contains X,Y,Z:
;;;      (vl-catch-all-apply 'vlax-invoke
;;; (list acsp 'AddPolyline  'item))
 )
      )
 
  (alert "problem with return coordinates\ncheck your data file")
  )

  (princ)
  )

______________________________________________

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 18
stevor
in reply to: richie_hodgson

Here is a start, for 2D:

 

  In case there are extra spaces in the data file:

 ; parse  rs by space character delimiter  into a List of strs
 (defun Pars_S (rs / d L i a b Q n)  (setq @u "pars_s"   i 1  d " ")
  (if (and rs (= 'STR (type rs)) (setq Q (strLen rs) ))
   (whiLe (<= i Q)
    (whiLe (and (=  (substr rs i 1) d) (<= i Q))  (setq i (1+ i)) )
    (setq n i)
    (whiLe (and (/= (substr rs i 1) d) (<= i Q))  (setq i (1+ i)) )
    (setq a (substr rs n (- i n))  i (1+ i) )
    (if (and a (/= "" a)) (setq L (cons a L)))  ) )
  (if L (reverse L))  )
 
(princ" s_typtl ") (textscr)

 

To convert each line of data to a cod-type and a 2D point:


 ; use split-string, or pars_s if extra spaces
 ; string to type-pt list   
 (defun S_TyPtl ( rs / sl pl tpl  )
  (if (and rs (setq sl (Pars_S rs )))
    (setq tys (car sl)  
          pl  (list (distof (cadr sl)) (distof (caddr sl))  )
          tpl (list tys pl) ) ) )


 Use some file read routine, like Martti's, to make a Read-string-List.

 

To the read-strings to lists of code + pts:


   (setq tpll nil  tyl nil  gtypll nil )
   (foreach rs rsl
    (setq tpl  (S_TyPtl rs))
    (setq ty   (car tpl) pt (cadr tpl)
          tpll (cons tpl tpll) )
    (if (not (member ty tyl))  (setq tyl (cons ty tyl)))
   )
   (foreach gty tyl   (setq  pl nil)
    (foreach tpl tpll ; in reverse -Spoon    
     (setq ty (car tpl)  pt (cadr tpl) )
     (if (eq gty ty) (setq pl (cons pt pl)))
    )
    (setq gtpl (cons gty pl )) ; groupcode, pt-list
    (setq gtypll (cons gtpl gtypll)) ; list of them
   )
   (foreach l gtypll (princ"\n ")(prin1 l)) 

S
Message 6 of 18
richie_hodgson
in reply to: Hallex

Hi, thanks for that, what I was looking for was something more like

 

(defun C:plist ()

  (setq FH (findfile "log.txt"))

        (setq FC (open FH "r"))

         (while (setq LN (read-line FC))

    (setq data (read (strcat "(" LN ")")))

    (if (= "bi" (car data)) (setq bi (cons (cdr data))))

    (if (= "bp" (car data)) (setq bp (cons (cdr data))))

    (if (= "sq" (car data)) (setq sq (cons (cdr data))))

    (if (= "tr" (car data)) (setq tr (cons (cdr data))))

    (if (= "bc" (car data)) (setq bc (cons (cdr data))))

    (if (= "sh" (car data)) (setq sh (cons (cdr data))))

         )

        (close Fc)

 )


I am separating them out so I can control linetype and colour when I draw the polyline, the if statement isnt working can you help. I would also like to mapcar a selected origin to the coordinates.

 

log file contains

 

bi 0.72 100 0

bp 0.8 80 0

sq 0.8 100 0

tr 0.8 40 0

bc 0.8 50 0

sh 0.8 60 0

bi 6.2 100 0

bp 6.2 80 0

sq 6.2 100 0

tr 6.2 40 0

bc 6.2 50 0

sh 6.2 60 0

bi 12.8 100 0

bp 12.8 80 0

sq 12.8 100 0

tr 12.8 40 0

bc 12.8 50 0

sh 12.8 60 0

Richie
Message 7 of 18
stevor
in reply to: richie_hodgson

You can code it many ways, my example was for more than just those constraints.

To make the plines for that data format, from my example:

   (setq lci 0)
   (foreach l gtypll  
    (setq lyn (car L)  pl (cdr l)  lci (1+ lci))  
    (princ "\n lyn:  ")(princ lyn)(princ ",  applied color  ") (prin1 lci)
    (command "layer" "m" lyn "co" (itoa lci) "" "" "pline" )
    (foreach p pl (command p)) (command)
   )  ; done foreach

 

Your data, albiet copied as a text, not read by a file, has some overlapped plines.

 

S
Message 8 of 18
Hallex
in reply to: richie_hodgson

Sorry I don't understand what you mean about origin of polyline

Change this code to your suit:

<code>

(defun read-by-match (filename matchlist / file result line)
  (if (findfile filename)
    (progn (setq file (open filename "r"))
    (while (setq line (read-line file))
      (foreach item  matchlist
        (if (wcmatch line (strcat item "*"))
      (setq result (cons line result))
    )
        )
      )
    (close file)
    (reverse result)
    )
    (alert (strcat "File " filename " not found!"))
  )
)

(defun split  (txt sep)
  (if (not (eq sep txt))
    (if (setq pos (vl-string-search sep txt 0))
      (cons (substr txt 1 pos)
     (split (substr txt (+ pos 1 (strlen sep))) sep))
      (list txt)) )
  )

(defun uniques (lst)
  (if (car lst)
    (cons (car lst)
     (uniques (vl-remove (car lst)(cddr lst))
   )
    )
  )
)

(defun C:tryit(/ acsp delim dirty fn groupped layer_list pline pline_coords tmp uniq_list x)
  (setq fn (strcat (getvar "dwgprefix") "log.txt"));<-- change file path here
  (setq delim (chr 32));<--change separator here I'm currently using blank space, if tab delimited you have to use "\t" instead
  (setq layer_list (list "bi" "bp" "sq" "tr" "bc" "sh"));<-- change match list here
  (if (findfile fn)
    (setq dirty (read-by-match fn layer_list)))
     (setq dirty (mapcar '(lambda(x)(split x delim))dirty))
  (setq uniq_list (uniques (mapcar 'car dirty)))
(setq groupped nil)
  (foreach item uniq_list
  (foreach sublist dirty
    (if (eq item (car sublist))
    (setq tmp (cons (reverse( cdr(reverse (cdr sublist))))
    tmp
     )
    )
    )
    )
    (setq groupped (cons
       (append
      (list
        (list item (last (assoc item dirty))))
     (mapcar 'atof(apply 'append  tmp)))
       groupped)
   )
    (setq tmp nil)
  );;
 
  ;; debug oly:
 
  ;|(foreach laylist (mapcar 'car groupped)
    (command "-layer" "m" (car laylist) "lw" (cadr laylist) (car laylist) ""))|;
 
(if groupped
  (progn
    ;; you may want to use other methods to draw plines here
    (vl-load-com)
 (setq acsp (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object)))))
    (foreach item groupped
     (setq pline (vl-catch-all-apply 'vlax-invoke
 (list acsp 'AddLightWeightPolyline (cdr item)))
 )
       (vl-catch-all-apply 'vlax-put (list pline 'layer (caar item)))
 )
      )
  (alert "problem with return coordinates\ncheck your data file")
  )
  (princ)
  )

</code>

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 9 of 18
richie_hodgson
in reply to: Hallex

Hi Hallex

I mean I want to "select" where the polylines start, (setq orign "\nPlease select start point: ") not from 0,0,0. I think this will need a mapcar statement somewhere in the code to add orign to each vertex of the polylines.

Richie
Message 10 of 18
richie_hodgson
in reply to: Hallex

Also the new layers are not being cretaed and the polylines arn't going onto their corresponding new layers.

Richie
Message 11 of 18
Hallex
in reply to: richie_hodgson

Do you mean that all these layers does not exist

and you need to create all of them in code?

if so just uncomment code after: :debug only

About mapcar I do it easily, just I need to be sure

about layers, and also I don't understand what the values

in the last column

______________________

Check thius out with origin:

<code>

(defun read-by-match (filename matchlist / file result line)
  (if (findfile filename)
    (progn (setq file (open filename "r"))
    (while (setq line (read-line file))
      (foreach item  matchlist
        (if (wcmatch line (strcat item "*"))
      (setq result (cons line result))
    )
        )
      )
    (close file)
    (reverse result)
    )
    (alert (strcat "File " filename " not found!"))
  )
)

(defun split  (txt sep)
  (if (not (eq sep txt))
    (if (setq pos (vl-string-search sep txt 0))
      (cons (substr txt 1 pos)
     (split (substr txt (+ pos 1 (strlen sep))) sep))
      (list txt)) )
  )

(defun uniques (lst)
  (if (car lst)
    (cons (car lst)
     (uniques (vl-remove (car lst)(cddr lst))
   )
    )
  )
)

(defun C:tryit(/ acsp delim dirty fn groupped layer_list orig pline pline_coords tmp uniq_list x)
  (setq orig (getpoint "\nPick origin: "))
  (setq fn (strcat (getvar "dwgprefix") "log.txt"));<-- change file path here
  (setq delim (chr 32));<--change separator here I'm currently using blank space, if tab delimited you have to use "\t" instead
  (setq layer_list (list "bi" "bp" "sq" "tr" "bc" "sh"));<-- change match list here
  (if (findfile fn)
    (setq dirty (read-by-match fn layer_list)))
     (setq dirty (mapcar '(lambda(x)(split x delim))dirty))
  (setq uniq_list (uniques (mapcar 'car dirty)))
(setq groupped nil)
  (foreach item uniq_list
  (foreach sublist dirty
    (if (eq item (car sublist))
    (setq tmp (cons (reverse( cdr (reverse  (mapcar '+ orig (mapcar 'atof (cdr sublist))))))
;;;  (reverse( cdr(reverse (cdr sublist))))
    tmp
     )
    )
    )
    )
    (setq groupped (cons
       (append
      (list
        (list item (last (assoc item dirty))))
;;;     (mapcar 'atof(apply 'append  tmp))
      (apply 'append  tmp)
      )
       groupped)
   )
    (setq tmp nil)
  );;
 
  ;; debug oly:
 
  ;|(foreach laylist (mapcar 'car groupped)
    (command "-layer" "m" (car laylist) "lw" (cadr laylist) (car laylist) ""))|;
 
(if groupped
  (progn
    ;; you may want to use other methods to draw plines here
    (vl-load-com)
 (setq acsp (vla-get-block (vla-get-activelayout (vla-get-activedocument (vlax-get-acad-object)))))
    (foreach item groupped
     (setq pline (vl-catch-all-apply 'vlax-invoke
 (list acsp 'AddLightWeightPolyline (cdr item)))
 )
       (vl-catch-all-apply 'vlax-put (list pline 'layer (caar item)))
 )
      )
  (alert "problem with return coordinates\ncheck your data file")
  )
  (princ)
  )

</code>

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 12 of 18
richie_hodgson
in reply to: Hallex

layers are now working wonderfull and I can chose my own linetypes with a little tweek, all I need now is for you to tweek the code to be able to select the origin of the lines, I.e, (setq start "\nplease select start point") so that the lines are drawn relative to that point. 

Richie
Message 13 of 18
Hallex
in reply to: richie_hodgson

Again, problem with my stupidy šŸ™‚

Don't you want to pick points for every separate line (or layer)

or just one point that will be like an ucs origin,

and all other coordinates will be recalculated relatively to

this origin

Seems too late for me though, I will be back tomorrow

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 14 of 18
richie_hodgson
in reply to: Hallex

just one point that will be like an ucs origin,

and all other coordinates will be recalculated relatively to

this origin

 

Thanks so much for your help in this.

Richie
Message 15 of 18
Hallex
in reply to: richie_hodgson

Just a hint

search for this line in the code above:

(setq orig (getpoint "\nPick origin: "))

 

I need to go away from there, zzzzzz

 

cu

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 16 of 18
richie_hodgson
in reply to: Hallex

Great, got a bit lost there, it's all working nicely.

 

Thanks very much

Richie
Message 17 of 18
Hallex
in reply to: richie_hodgson

You're welcome

Cheers šŸ™‚

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 18 of 18
richie_hodgson
in reply to: Hallex

Just a quick question, I have had a bit of time to generate some more data, the lisp isn't quite working, I have attache the lisp and the data for you to look at, all the linetypes are working, but it apears to be setting up only the sh, tr, sq layers and only drawing sh and sq lines on the grid. What is going on?

Richie

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

ā€Boost