Here is a Rhino script that I have worked with. The goal of the script is to read a CSV file that has either a one line description or X,Y,Z coordinates. When it hits a description, it creates a layer and adds the following points to that layer. The plan was for the script to create the new layers a sublayers of the current layer. However, in practice is creates the first few layers as sublayers of the current layer then makes the rest top level layers.
I was wondering if someone could identify what is wrong. I have the script and sample data attached.
Your script seems to work here in Rhino 6 (Windows). Personally, I don’t like relying on exceptions to to make logic work. I’d do a little parsing to determine if a row represents a point or a layer.
For me it works sometimes and sometimes it doesn’t. Sometimes it puts all the new layers as sublayers of the current layer. Other times it does not. It’s pretty random in its behavior which makes me thing something is wrong.
Here is an example. Fresh file. I run that script and the first 18 sublayers were created at the top level. The remaining sublayers were created below the active layer (where I expected the all to be created). This suggests to me there is a subtle programming error of some type (or a Rhino bug?).
Clearly, your parser is interpreting a point as a layer name.
Here is an alternative that seems to work here (on Windows):
import System
import Rhino
import rhinoscriptsyntax as rs
def read_delimited_file():
path = rs.OpenFileName(filter='CSV files|*.csv||')
if not path: return
lines = System.IO.File.ReadAllLines(path)
if not lines or len(lines) == 0: return
parent_layer = rs.CurrentLayer()
layer = parent_layer
rs.EnableRedraw(False)
chars = System.Array[System.Char](',')
for line in lines:
tokens = line.Split(chars, System.StringSplitOptions.RemoveEmptyEntries)
if not tokens: continue
if len(tokens) == 3:
rc, point = Rhino.Geometry.Point3d.TryParse(line)
if rc and point.IsValid:
id = rs.AddPoint(point)
if id:
rs.ObjectLayer(id, layer)
elif len(tokens) == 1:
layer = rs.AddLayer(tokens[0], parent=parent_layer)
rs.EnableRedraw(True)
read_delimited_file()
Thanks, so far I have not seen the random behavior. I modified yours slightly to give each layer a different color.
I wish Rhino would ignore records it cannot import rather than puke on such headings in its regular CSV import.
import System
import Rhino
import rhinoscriptsyntax as rs
import random
def read_delimited_file():
path = rs.OpenFileName(filter=‘CSV files|*.csv||’)
if not path: return
lines = System.IO.File.ReadAllLines(path)
if not lines or len(lines) == 0: return
parent_layer = rs.CurrentLayer()
layer = parent_layer
rs.EnableRedraw(False)
chars = System.Array[System.Char](',')
for line in lines:
tokens = line.Split(chars, System.StringSplitOptions.RemoveEmptyEntries)
if not tokens: continue
if len(tokens) == 3:
rc, point = Rhino.Geometry.Point3d.TryParse(line)
if rc and point.IsValid:
id = rs.AddPoint(point)
if id:
rs.ObjectLayer(id, layer)
elif len(tokens) == 1:
color = rs.CreateColor (random.randint (0, 255), random.randint (0, 255), random.randint (0, 255))
layer = rs.AddLayer(tokens[0], color=color, parent=parent_layer)
rs.EnableRedraw(True)