Hello,
We are two french architects, and we are trying to use Rhino as the (nearly) only tool for our practice
In order to do that, we created a serie of python scripts aiming at easing the plot styles and layout in Rhino. Even if we want to use Rhino only, we are trying to keep a good level of interoperability (with Adobe Illustrator and AutoCAD).
We would be happy to receive some feedback and critics.
1. The Excel file that contains everything
As you probably expect, we are taking the CTB function from AutoCAD as an example of managing plot styles.
Here, instead of a CTB file, the data is stored in an Excel file.
In red are the global informations:
1 - Layer hierarchy
2 - Full layer names
3 - Layer color
4 - Layer print color
5 - Layer linetype
In blue are the informations specific to each scale (1:1000 ; 1:500 ; 1:200 ; 1:100 ; 1:50)
6 - Line thickness (in pt)
7 - Line thickness (in mm)
8 - Pattern (for Illustrator only)
9a - Then we created a worksheet (createLayers) that recaps the full layer names and their rgb colors (will be used for step 3)
9a - And finally we created a worksheet for each scale, that recaps only the information of the specific scale (will be used for step 2) :
2. The python script that generates all the .csv and .js files from the Excel file
This script generates three kinds of outputs that will be used in the next steps:
- Will be used for step 3 : layers.csv (according to the createLayers worksheet in Excel)
- Will be used for step 4 : 1000.csv ; 500.csv ; 200.csv ; 100.csv ; 50.csv (plot styles for each scale)
- Will be used for step 5 : 1000.js ; 500.js ; 200.js ; 100.js ; 50.js (plot styles for each scale). These files are created to be used in Illustrator.
import pandas as pd # import pandas library : used to read xls and xlsx files (pandas library needs also xlrd and openyxl)
import csv # import csv library to handle csv reading and writing
scales = ['1000', '500', '200', '100', '50'] # set the scales in an array
def XLStoCSV(scales): # first function of the script : export each excel sheet into a CSV file
x = 2 # initialize the sheet index
for scale in scales: # loop through the scales
file = pd.read_excel("MLAVPlotStyles.xlsx", sheet_name=x) # open the excel file at the sheet specified by x
file.to_csv(scale + ".csv", index = None, header=True) # create the corresponding csv file
x += 1 # indent the sheet index
file = pd.read_excel("MLAVPlotStyles.xlsx", sheet_name=1) # open the excel file at the sheet that specifies the layer list and its rgb values
file.to_csv("layers.csv", index = None, header=True) # create the corresponding csv file
def CSVtoJS(scales): # second function of the script : get infos from CSV to generate JS files, ready to use for Adobe Illustrator
for scale in scales: # loop through each scale
f = open(scale + ".js", "w") # create the corresponding .js file
f.write("var doc = app.activeDocument;\r\nfunction makeColor(r,g,b){\r\n var c = new RGBColor();\r\n c.red = r;\r\n c.green = g;\r\n c.blue = b;\r\n return c;\r\n};\r\n") # write the first part of the constant code in JS
f.write("const continuous = [];\r\nconst dots = new Array(0, 1);\r\nconst dashed = new Array(2, 3);\r\nconst dashdot = new Array(2, 2, 0, 2);\r\nvar lines;\r\n") # write the first part of the constant code in JS
with open(scale + ".csv") as csvfile: # open the csv file corresponding to the current scale
reader = csv.reader(csvfile)
next(reader) # jump to next line (first line is data headers)
for row in reader: # iterate through each row
layer_name = row[0] # put the values from the columns in variables
r = row[1]
g = row[2]
b = row[3]
linetype = row[4]
thickness = row[5]
pattern = row[7]
f.write("\r\ntry {\r\n lines = doc.layers['" + layer_name + "'].pathItems;\r\n\r\n for (i = 0; i < lines.length; i++) {\r\n pathArt = lines[i];\r\n pathArt.strokeDashes = " + linetype + ";\r\n pathArt.strokeColor = makeColor(" + r + "," + g + "," + b + ");\r\n pathArt.strokeWidth = " + thickness + ";\r\n") # write the corresponding code in js for illustrator
if pattern != '[Sans]': # if the layer contains a pattern the following line is added to handle it in illustrator
f.write(" pathArt.filled = true;\r\n pathArt.fillColor = doc.swatches['"+ pattern + "'].color;")
f.write(" }\r\n } catch (e) {\r\n}") # end of the js code for one layer
f.close() # close the js file
if( __name__ == "__main__" ): # perform function
XLStoCSV(scales)
CSVtoJS(scales)
3. The python script that creates the right layers in Rhino
We know we could use a template file to create this, but in our practice, we find it more practical to generate our working layers this way.
import csv # import csv library to handle csv reading and writing
import rhinoscriptsyntax as rs # import rhinoscriptsyntax to handle rhino actions
def OpenCSV(): # first function of the script : open the csv file
with open("layers.csv") as csvfile:
reader = csv.reader(csvfile)
next(reader) # jump to next line (first line is data headers)
for row in reader: # iterate through each row
full_layer_name = row[0] # put the values from the columns in variables
color = rs.CreateColor(row[1], row[2], row[3])
CreateLayer(full_layer_name, color) # send variables to the next function
def CreateLayer(full_layer_name, color): # second function of the script : create the layer in Rhino
layer_names = rs.LayerNames() # create array of existing layers in Rhino
for layer_name in layer_names: # iterate through each layer
if layer_name == full_layer_name: # if layer already exists update its color
rs.LayerColor(layer_name, color)
else: # if it doesn't exist create the layer
rs.AddLayer(full_layer_name, color)
if( __name__ == "__main__" ): # perform function
OpenCSV()
4. The python script that assign the right plot style according to a chosen scale in Rhino
For this step we used this .rvb script as a starting point. We recreated it in python, and changed it a bit.
The idea is that the user runs the python script, choses an option of scale in a popup, and the script loads the right csv to apply the right plot style to each layer.
import csv # import csv library to handle csv reading and writing
import rhinoscriptsyntax as rs # import rhinoscriptsyntax to handle rhino actions
def SetPrintInfo(): # first function : options in a popup in Rhino
options = ('50e', '100e', '200e', '500e', '1000e')
if options:
result = rs.ListBox(options, "Pick an option")
if result == "50e": # get the option from the user
filename = "50.csv" # fetch the right csv, corresponding to the user's choice
elif result == "100e":
filename = "100.csv"
elif result == "200e":
filename = "200.csv"
elif result == "500e":
filename = "500.csv"
elif result == "1000e":
filename = "1000.csv"
else:
exit()
OpenCSV(filename)
def OpenCSV(filename): # second function : open the csv file containing the plot styles infos
with open(filename) as csvfile:
reader = csv.reader(csvfile)
next(reader) # jump to next line (first line is data headers)
for row in reader: # iterate through each row
full_layer_name = row[0] # put the values from the columns in variables
print_color = rs.CreateColor(row[1], row[2], row[3])
linetype = row[4]
thickness = row[6]
SetLayerPrintValues(full_layer_name, print_color, linetype, thickness) # send variables to the next function
def SetLayerPrintValues(full_layer_name, print_color, linetype, thickness): # third function : assign the values from the csv to the Rhino layers
layer_names = rs.LayerNames() # create array of existing layers in Rhino
for layer_name in layer_names:# iterate through each layer
if layer_name == full_layer_name: # select the layer
rs.LayerPrintColor(layer_name, print_color) # assign print color
rs.LayerLinetype(layer_name, linetype) # assign linetype
rs.LayerPrintWidth(layer_name, float(thickness)) # assign line thickness
if( __name__ == "__main__" ): # perform function
SetPrintInfo()
5. The .js scripts that can be used in Illustrator
These files are generated by the script in step 2. They are used in the following case : something has been drawn in Rhino, but the layout and plot styles are handled in Illustrator.
When the exported Rhino file is opened in Illustrator, the .js script will apply the same plot styles as the one created for Rhino.
If you wish to see more about these scripts, you can find them in the gitlab repository.
6. The Gitlab link if you wish to download, use, criticize, enhance
This project is published under GNU GPL v3 license, so feel free to download, use, share and contribute : MLAV.LAND / rhinoPlotStyles Β· GitLab
Thank you for your feedback and critics!