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.
    https://developer.bricsys.com/bricscad/help/en_US/CurVer/DevRef/source/vl-string-split.htm

    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.

  • 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.

  • 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.