Polyline from CSV

Polyline from CSV

nicolasR6NGC
Contributor Contributor
864 Views
4 Replies
Message 1 of 5

Polyline from CSV

nicolasR6NGC
Contributor
Contributor

I'm not sure why my script works 10 percent of the time but any help would be great. Essentially I have a LISP that accesses an exe file that creates a CSV where a row represents a point on a polygon and the columns represent the polygon it is part of, the y coordinate, and the x coordinate. The order the CSV lists the points is the order they should be drawn in (I have attached a CSV of what the output looks like). The LISP then accesses the CSV and runs through the points creating the necessary polylines for some reason the output changes between runs and I'm not sure why (LISP shared as well). 

 

 

(defun c:DrawPolylineFromCSV ()
;; Function to split a line by a delimiter
(defun split-line (line delimiter)
(if (not (vl-string-search delimiter line))
(list line)
(cons (substr line 1 (vl-string-search delimiter line))
(split-line (substr line (+ (vl-string-search delimiter line) 2)) delimiter))))

;; Function to create a polyline from the points
(defun create-polyline (points)
;; Start the polyline command
(if points
(progn
(print points)
(command "_.pline")

;; Iterate over each point in the points list
(foreach point points
(print point)
(command point))

(command "Close")

;; End the polyline command
(command ""))))

;; Function to read the CSV and extract points
(defun read-csv (file-path)
(setq points '())
(setq polyind 1)
(setq file (open file-path "r"))

;; Skip the first line (header)
(read-line file)

;; Read the file line by line
(while (setq line (read-line file))
(setq fields (split-line line ","))
(setq polycount (atoi (nth 0 fields))) ;; Convert to integer
(setq latitude (distof (nth 1 fields)))
(setq longitude (distof (nth 2 fields)))

;; Check for valid numeric values
(if (= polycount polyind)
(setq points (append points (list (list longitude latitude))))
(progn
(create-polyline points) ;; Create polyline for previous points
(setq points '()) ;; Start new polyline
(setq polyind (+ polyind 1))))) ;; Update polygon index

;; Handle the last polyline

(close file)
)

;;(setq start-time (getvar "cputicks"))
;; Main code starts here
(setq file-path (getfiled "Select CSV File" "" "csv" 4))
(if file-path
(progn
(princ "\nProcessing CSV...")
(read-csv file-path)
(princ "\nCompleted successfully!"))
(princ "\nNo file selected."))
;;(setq checkpoint (getvar "cputicks"))
;;(setq elapsed-op (- checkpoint start-time))
;;(print elapsed-op)
)

0 Likes
Accepted solutions (1)
865 Views
4 Replies
Replies (4)
Message 2 of 5

Moshe-A
Mentor
Mentor
Accepted solution

@nicolasR6NGC  hi,

 

Maybe your problem is running object snap?

anyway here is my version to this command called CSV2PL uses (entmakex) function instead of (command) runs at maximum speed 😀

 

enjoy

Moshe

 

(defun c:csv2pl (/ LM:str->lst read_csv_file  draw_pline ; local functions
                   fname points^ itm)
  
  ;; String to List  -  Lee Mac
  ;; Separates a string using a given delimiter
  ;; str - [str] String to process
  ;; del - [str] Delimiter by which to separate the string
  ;; Returns: [lst] List of strings
 
  (defun LM:str->lst ( str del / pos )
    (if (setq pos (vl-string-search del str))
      (cons (substr str 1 pos) (LM:str->lst (substr str (+ pos 1 (strlen del))) del))
      (list str)
    )
  ); LM:str->lst
  
  
  (defun read_csv_file (filepath / _chop_spaces _isexit ; local functions
                                   f idx rec pid latitude longitude item slst nlst pts)
    ; anonymous functions
    (setq _chop_spaces (lambda (s) (vl-string-right-trim " " (vl-string-left-trim " " s))))
    (setq _isexit (lambda (id lst) (vl-some (function (lambda (itm) (if (= id (car itm)) itm))) lst)))
    
    (if (and
          (setq filepath (findfile filepath))
          (setq f (open filepath "r"))
	    )
      (progn
        (setq idx 0)
        (while (setq rec (read-line f))
          (if (and
                (> (setq idx (1+ idx)) 1)
                (setq slst (LM:str->lst rec ","))
		      )
            (progn
             (setq pid (atoi (_chop_spaces (car slst))))
             (setq latitude (distof (_chop_spaces (cadr slst))))
             (setq longitude (distof (_chop_spaces (caddr slst))))
              
             (cond
              ((not (setq item (_isexit pid nlst)))
               (setq nlst (cons (list pid (list latitude longitude)) nlst))
              ); case
              ( t
                (setq nlst (vl-remove item nlst))
                (setq pts (cdr item))
                (setq item (cons pid (append pts (list (list latitude longitude)))))
                (setq nlst (cons item nlst))
              ); case
			 ); cond
            ); progn
          ); if
        ); while
         
        (setq f (close f))
      ); progn
    ); if
    
    (reverse nlst) ; return
  ); read_csv_file
  
  
  (defun draw_pline (lst val / pt)
   (entmakex
     (append
       (list '(0 . "LWPOLYLINE")
             '(100 . "AcDbEntity")
             '(100 . "AcDbPolyline")
              (cons '90 (length lst))
	          (cons '70 val)
       )
       (mapcar
         '(lambda (pt)
            (cons '10 pt)
          )
          lst
       )
     ); append
   ); entmake
  ); draw_pline

  
  ; here starts c:csv2pl
  (if (setq fname (getfiled "Select CSV file" "" "csv" 8))
    (foreach itm (read_csv_file fname)
      (draw_pline (cdr itm) 1)
    ); foreach
  ); if
  
  (princ "\nCompleted successfully!")
  (princ)
); c:csv2pl

 

 

 

Message 3 of 5

marko_ribar
Advisor
Advisor

You haven't localized any of used variables and defuns... Perhaps that's issue you are facing in not obtaining the same results each time you consecutively run - execute your routine...

Marko Ribar, d.i.a. (graduated engineer of architecture)
Message 4 of 5

Kent1Cooper
Consultant
Consultant

@nicolasR6NGC wrote:

(command "_.pline")
....
;; Iterate over each point in the points list
....
(command "Close")
;; End the polyline command
(command ""))))
....


There's a problem I see.  The Close option ends the Polyline command, so that subsequent unneeded Enter "" will recall whatever the last command was that you used prior to the routine.

Kent Cooper, AIA
Message 5 of 5

nicolasR6NGC
Contributor
Contributor

This was perfect, thank you! At first it brought in the lines with the coordinates flipped but that's my fault for having my csv read y then x flipped it and it works great! New to lisp as I have only worked in python so these functions are new to me thanks for the insight too.

0 Likes