Cant split list into separate element (LISP noob)
im trying to split the closestContent variable into seperate values. For example T7/0.5/5 would be spread = 7, diameter = 0.5 and height = 5. When I run this code all the values are zero for some reason. I'm a bit of a coding newbie so take that into account :) Here is the code:
(defun c:fixtrees ()
"Selects all TREE blocks, retrieves their position (X, Y, Z), checks for text in TREE_PT_CODE layer, and prints the data in table format."
;; Select all blocks named "TREE"
(setq treeBlocks (ssget "X" '((0 . "INSERT")(2 . "TREE"))))
;; Check if any blocks were found
(if treeBlocks
(progn
(princ (strcat "\nNumber of TREE blocks found: " (itoa (sslength treeBlocks)))) ; Display the number of blocks found
(setq numTrees (sslength treeBlocks)) ; Get the number of trees
(setq index 0) ; Initialize index for iteration
(setq treeDataList '()) ; Initialize the list to store tree data
;; Iterate through each tree block
(while (< index numTrees)
(setq treeEnt (ssname treeBlocks index)) ; Get the tree entity
(setq treePos (cdr (assoc 10 (entget treeEnt)))) ; Get the position (X, Y, Z)
;; Store the tree data (X, Y, Z) and a placeholder for the associated entity
(setq treeData (list treePos nil)) ; Create a list with the position
(setq treeDataList (cons treeData treeDataList)) ; Add it to the main list
;; Increment the index for the next iteration
(setq index (1+ index))
)
;; Now, check for all entities in the "TREE_PT_CODE" layer
(setq entitiesOnLayer (ssget "X" '((8 . "TREE_PT_CODE")))) ; Get all entities on the layer
;; Check if any entities were found
(if entitiesOnLayer
(progn
;; Iterate through each tree and find the closest entity
(setq treeIndex 0) ; Reset tree index for the next loop
(foreach treeData treeDataList
(setq treePos (car treeData)) ; Get the tree position
(setq closestEntity nil)
(setq closestDistance nil)
(setq closestContent nil) ; Placeholder for entity content
;; Iterate through each entity in TREE_PT_CODE layer
(setq entityCount (sslength entitiesOnLayer))
(setq entityIndex 0)
(while (< entityIndex entityCount)
(setq entityEnt (ssname entitiesOnLayer entityIndex)) ; Get the entity
(setq entityData (entget entityEnt)) ; Get its data
(setq entityPos (cdr (assoc 10 entityData))) ; Get the position (X, Y, Z)
(setq entityContent (cdr (assoc 1 entityData))) ; Get the text content
;; Calculate the distance
(setq dist (distance treePos entityPos))
;; Check if this entity is the closest
(if (or (null closestDistance) (< dist closestDistance))
(progn
(setq closestDistance dist) ; Update closest distance
(setq closestEntity entityPos) ; Update closest entity
(setq closestContent entityContent) ; Update closest entity content
)
)
;; Increment the entity index for the next iteration
(setq entityIndex (1+ entityIndex))
)
;; Debugging output: check closest content
(if closestEntity
(progn
(princ (strcat "\nClosest content for tree at "
(rtos (car treePos) 2 2) ", "
(rtos (cadr treePos) 2 2) ": "
closestContent))
;; Directly split the content string into parts without trimming
(setq splitContent (vl-string-split closestContent "/"))
;; Debugging output: show raw content and split result
(princ (strcat "\nRaw content: '" closestContent "'"))
(princ (strcat "\nSplit content: " (vl-princ-to-string splitContent)))
;; Retrieve individual components, ensuring we handle potential errors
(setq spread (if (>= (length splitContent) 1) (atoi (nth 0 splitContent)) 0))
(setq diameter (if (>= (length splitContent) 2) (atof (nth 1 splitContent)) 0))
(setq height (if (>= (length splitContent) 3) (atoi (nth 2 splitContent)) 0))
;; Update the tree data with split values
(setq treeDataList (subst (list treePos spread diameter height) treeData treeDataList))
)
)
;; Increment the tree index for the next iteration
(setq treeIndex (1+ treeIndex))
)
;; Print the final associations in a table format
(princ "\n\nAssociations between Trees and TREE_PT_CODE entities:")
(princ "\n-----------------------------------------------------------------")
(princ "\n| Tree Position (X, Y, Z) | Spread | Diameter | Height |")
(princ "\n-----------------------------------------------------------------")
;; Print the final data
(foreach treeData treeDataList
(setq treePos (car treeData))
(setq spread (cadr treeData))
(setq diameter (caddr treeData))
(setq height (if (> (length treeData) 3) (cadddr treeData) 0)) ; Get height safely
(princ (strcat "\n| ("
(rtos (car treePos) 2 2) ", " ; X coordinate
(rtos (cadr treePos) 2 2) ", " ; Y coordinate
(rtos (caddr treePos) 2 2) ") | "
(itoa spread) " | "
(rtos diameter 2 2) " | "
(itoa height) " |"))
)
(princ "\n-----------------------------------------------------------------")
)
(princ "\nNo entities found on TREE_PT_CODE layer.") ; If no entities found
)
)
(princ "\nNo TREE blocks found.") ; If no blocks are found
)
(princ) ; End cleanly
)
Comments
-
Hello.
The arguments of the (vl-string-split) function are reversed in this case.
Instead of:
(vl-string-split closestContent "/")
you should use:
(vl-string-split "/" closestContent)
One way of testing would be to use the command line to check the return of the function for a particular case.
1 -
I use a function By Lee-Mac, Parse lisp. you can define the delimeter.
; tab 9 space 32 (chr 32) comma 44 semicolum 59 slash / 47
; thanks to Lee-mac for this defun
(defun csv->lst ( str / pos )
(if (setq pos (vl-string-position 47 str))
(cons (substr str 1 pos) (csv->lst (substr str (+ pos 2))))
(list str)
)
)Just a comment I have a dynamic tree block it has a circle for trunk and a foliage shape so you have 2 independant objects scale to match your tree code as you mention.
Can you post a sample dwg and will see what I can do, need a sample Table as can match details like text height and column widths.
Will check code.
0 -
Thank you both, I didn't even realise I was using the vl-string-split function back to front. I got it to work now.
0