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_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))))
--
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))
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'~
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))
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
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.
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>
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.
Also the new layers are not being cretaed and the polylines arn't going onto their corresponding new layers.
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>
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.
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
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.
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'~
Great, got a bit lost there, it's all working nicely.
Thanks very much
You're welcome
Cheers š
~'J'~
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?