top of page
Search
  • Writer's pictureWill

Make your own easy-to-use shadow study tool


There are numerous ready-made tools out on the interweb to help designers visualize shadows buildings cast on its surroundings. Some of them are even free. For example, Ladybug comes to mind when we think of a rather complete package of environmental analysis particularly applicable to building designs. However, in my experience these ready-made tools are too big for my small task of shadow study. The interface of those tools are usually designed so that every function is an integral part to a whole. When I try to access a specific function such as shadow study, the learning curve of familiarizing myself with how the entire package works becomes a hindrance, especially considering I have some programming background to make just the lean, mean version of my own.

So if you are interested, here it is, serving also as a case study for python programming in real world applications. The script is rather simple. We feed it a time range (hours of the day) and it automatically screen-captures the viewport at the time intervals with shadow rendering on.


I made the component such that it has five inputs. The first is a Boolean to tell the component to actually execute exporting viewport as bitmaps. An ‘YMD’ input takes in a string that is formatted like 2018-4-1 with the first being the year, second month, third day.

I know intuitively people would want to split YMD into three different sliders so they can change the year, month, or day easily. But for succinct interface, combining them this way wouldn’t be a bad idea because the study is within a day that represents a meaningful time of the year (typical summer, typical winter, equinoxes, solstices, etc.). Changing the YMD is very deliberate and one has to know what day s/he wants to study. Having sliders is an unnecessary flexibility.

An ‘HR’ input takes in an hour range and it has to be in the form of an interval (range in Grasshopper). ‘intv’ stands for time interval (not to be confused with the interval data type which is a single object representing a range of values) and this input tells the component how long apart in time between each frame of the capture. For example, 15 means every minutes. Also for simplicity sake, there is no intervals above 30 minutes. It would just be the whole hour if a number greater than 30 is used here. Lastly we have a folder path to which the screen captures are saved.


Let’s get to the code. First off I’m putting a few lines that translate the hour range into a list of hour marks into a function, just to reduce clutter later in the code. If you look up the interval data type in RhinoCommon SDK you’ll see some properties or methods of use. Here my code first sees if the interval has the same beginning and end. Line 28 means that if my interval isn’t a singleton (same beginning and end), iterate through the range and get the hours. Line 32 catches the ‘else’ condition. In that case the list only has one number in it, which could be either the beginning (T0) or end (T1). There are some type casting in this function mainly to get nice integers from float numbers.


A second function is written so the export process is easily called later. One of the key codes here is the EnableRedraw method in rhinoscriptsyntax shown here on line 36 and 39. By turning the redraw off and on, I can make Rhino refresh its viewport. I’ve noticed that without this code, the shading or shadows of the viewport will not update unless another mouse action takes place. In an automated process like ours, there is no mouse action so the viewport must be deliberately refreshed.

On line 37 ‘dt’ is just short for System.DateTime. It’s part of the imports I have at the beginning of the script (not shown here). Line 38 has a variable sun which is initiated outside of the function. It may be better practice if you declare it using the global keyword at the beginning of this function. As you see, the ‘sun’ variable has a method called SetDateTime. This is from a Sun object. See more on RhinoCommonSDK. After new DateTime is set, the redraw is back and line 40 execute the screen grab.


Here is the main set-up code. You see ‘sun’ is declared on line 50. Line 42 to 45 takes care of erroneous inputs if any. Line 46 turns the YMD string into a tuple of number which I can use later as actual numbers representing the year, month and day.

Line 48 is critical as the entire script relies on querying the sun already set up in the Rhino document, NOT the GH document. To better explain, I need to back up a little. My script doesn’t create sun objects. It simply queries the one in the document. That means to use my script, one has to have the sun turned on and already geo-located the model correctly. After querying the document sun, the script will set it to the different times within the defined interval and capture a screenshot. In that regard, it’s clear that the sun object in the document is a pass-by data type or mutable in python terms, just like a dictionary. The variable ‘sun’ is only set to reference the actually Sun class object in the document and when I call methods such as the SetDateTime, it changes the Sun object in the doc. So line 48 tells this script to look into Rhino document that is currently open, not this GH file per se.

I’ve written into my script two custom display modes that’s called PCPA_AO and PCPA_SS. This is the identifiers for the script to switch back and forth from a normal display to a shadow-study-tailored display. Both display mode are provided with the script. I recommend importing them in options. Or make sure you create two display modes that are named such so my script can recognize. PCPA_SS is the one used when exporting shadow study frames.


Main routine happens now. Line 56 is where it saves the state of document sun. Then the script changes the display mode to PCPA_SS on line 59. Previously we’ve declared ‘ss’ as the variable for the display mode. The loopy loop on lines 62 to 64 goes to every minute interval of an hour and every hour, and runs Capture(). Line 67 resets the document sun back to the beginning state as remembered by variable T. Lastly but definitely not the least, return the script back to GH document scope. I’m not sure if anything breaks if I omit line 70 or 72 but it’s become a habit of mine to have it whenever I switch script scope, just like closing curly brackets in C# programming.

That’s the bulk of the coding. Now kick back and enjoy the automated shadow study. Once you have the frames, a thing to do is to load them into Photoshop and generate GIF. The ‘load file into stack’ function of Photoshop lets you quickly import a series of images and put each on a layer. Then in the timeline tab, one of the items in the upper right corner menu is to make frames from layers. This will place the layers one after another as frames. After you adjust the time each frame pauses, you can go to file menu, select ‘save for web’ to create GIF.

Another thing to do is to go to Rhino’s display settings and change the shadow color of display mode PCPA_SS. If there is an obvious color that isn’t used in any of the render materials, use that as the shadow color so in Photoshop you can select only the shadow regions. Then color fill that region on a blank layer. Repeat this for all frames and you can create a composite shadow map. You can even automate some of this in the Photoshop action tab!

A demo video of this tool can found here.

Resources are up on Food4Rhino.

Recent Posts

See All

How to pass all ARE exams

Now that I’ve finished all my ARE exams and registered as an architect, I can summarize a few pointers for anyone still in pursuit. These are things that I found to be noticeably helpful along my way

ARE 5 and prep materials

Here is an update on my progress on ARE 5 exams and my experiences with the preparation materials on the market. Ever since I passed my three managerial exams (PjM, PcM, CE), I've taken a long hiatus

GhPy can multi-thread too! But wait...

GhPy component is known to be a bit slow in its performance because of the JIT compiler it utilizes. However, GhPy is a powerful widget to test out scripting logic without the baggage associated with

bottom of page