The project I’m working on involves using Grasshopper to model vector graphics in pixel units, with the intention of exporting to a non-antialiased, “quantized” bitmap for further use in other software.
Here’s a screenshot of my sample input ( the closed circular curves) and desired output on the right.
Selecting only the hatches, and exporting as Illustrator .AI files at 1 mm = 1 point scale
Opening the AI file in Illustrator, select all
Using “Asset Export” Tool in Illustrator at 1x scale, 72 ppi, with no antialiasing
Naming the file manually ( Illustrator defaults to calling it “Asset 1.png” no matter the original filename)
These steps have to be done dozens of times a day, in an iterative design process, so I’m wondering if there there any plugins or shortcuts out there to make this more efficient?
I’ve managed to automate steps 1-3 using a Python script (attached below) but it doesn’t always work, and sometimes freezes the GH canvas when run on another computer’s installation (Windows, RH 5).
Note, Rhino’s ViewCaptureToFile doesn’t work for my purposes, because it produces an anti-aliased bitmap scaled to the viewport dimensions instead of the model scale. hatches_export_sample.gh (9.1 KB)
Thanks for the reply
There is still the issue that the exported bitmap is scaled to viewport size, not actual dimensions - i.e. I want 80 mm in the drawing to correspond exactly to 80 pixels in the output, and the boundaries to ideally correspond to the bounding box of the geometry, not the viewport window, eliminating the need for further cropping.
Perhaps there is a way of scaling the viewport’s zoom level and aspect ratio to achieve this outcome? I tried using _ViewportProperties, but that does not give direct control over the boundary coordinates.
To get the properly scaled output try this, it’s rather hacky but will do the trick:
import rhinoscriptsyntax as rs
def capture_1to1(objs):
#assuming topview capture
bbox = rs.BoundingBox(objs)
width = rs.Distance(bbox[0],bbox[1])
height = rs.Distance(bbox[0],bbox[3])
int_width = int(round(width))
int_height = int(round(height))
#command to make sure the zoom extends will zoom without a border
#running only once even outside the script would suffice but this will ensure the setting is correct
rs.Command('_SetZoomExtendsBorder ParallelView=1 Enter')
rs.Command('_NewFloatingViewport Projection Top Enter')
rs.Command('_-ViewportProperties Size {} {} Enter'.format(int_width,int_height))
rs.SelectObjects(objs)
rs.Command('ZoomSelected ')
rs.UnselectAllObjects()
filename = 'testcapture.png'
rs.Command('-ViewCaptureToFile TransparentBackground=Yes {}'.format(filename))
rs.Command('CloseViewport ')
objs = rs.GetObjects('objects to capture',preselect=True)
if objs: capture_1to1(objs)
Aha, the SetZoomExtentsBorder command turned out to be the missing piece! I adapted your code to use RhinoCommon methods so it would be a little less hacky:
import Rhino
import System.Drawing
if button:
bb = Rhino.Geometry.BoundingBox.Unset
for crv in crvs:
bb.Union(crv.GetBoundingBox(True))
solid_hatch_index = 9
hatches = Rhino.Geometry.Hatch.Create(crvs, solid_hatch_index, rotationRadians=0, scale=1.0)
for h in hatches:
Rhino.RhinoDoc.ActiveDoc.Objects.Add(h) # bake the hatches
RhinoDocument = Rhino.RhinoDoc.ActiveDoc
view = RhinoDocument.Views.Find("Top", False)
vp = view.ActiveViewport
width, height = bb.Diagonal.X, bb.Diagonal.Y
size = System.Drawing.Size(width, height)
Rhino.RhinoApp.RunScript("_SetZoomExtentsBorder _ParallelView=1 _Enter", True)
vp.ZoomBoundingBox(bb)
capture = view.CaptureToBitmap(size)
capture.Save(filename)
Discovered what seems to be another bug on the Mac version of GH when trying to run the above script -
Using either of the overload methods for CaptureToBitmap that take in (bool, bool, bool) for hiding the grid and axes, results in a NoneType instead of Bitmap being returned. (No exception is thrown by the method itself.)