Due to the containment measures in place for COVID-19 in Portugal, CreativeMornings Porto events had to move online. Thus making it impossible to do any sort of event photography. This got us thinking how we could replace the empty space on flickr albums. Space is the key word here. The events no longer occur in a shared physical space for all participants but on a virtual one. Nonetheless, there are multiple physical spaces for each participant and these physical spaces are all spread on a larger geographical context. A map then came up as a natural way to capture the physical space of these events.

There would be multiple ways to achieve this, some simpler than others, but since I was doing the job I took it has a challenge to do it with Grasshopper. There are a number of plugins for grasshopper that allow it to import SHP files, work with OpenStreetMaps, or GoogleMaps, for instance Heron, Elk, Meerkat or Mosquito, besides Grasshoppers default Import SHP. For this I decided to use Mosquito to import the Maps from OpenStreetMaps, Heron to get the Lat/Lon coordinates from addresses. Mosquito also has a component that returns coordinates from street addresses but it is not as effective in dealing with a large amount of addresses. Also, one of the initial ideas was to use the geotags in the images’ metadata but they arrived without any geographical information.

Each participant was asked to provide two pictures with the address from where they were participating in the CM event. I was sent the images named with the following format: FirstName LastName_Borough_City.jpg. To display the images of each participant at its geographic location I used Human plugin to map the images to surfaces. Lastly, since the participant addresses were only discriminated to borough (freguesia) level there were a few overlapping participants on the map. Two solve this I used Kangaroo to optimize the placement of each frame, as close as possible to the original point with as little overlap as possible.

Step 1

First feed an address to the Location component. It returns Lat/Lon coordinates of several candidate locations. Select the first and feed it into a circle component. Use a small number for radius and feed that to the Area input of Map Vector component. Optionally is possible to get specific features from OpenStreetMaps using custom search, like for instance the administrative boundaries. If you like it is possible to center the map to the Rhino origin connecting a true value to CenterToWorld.


Step 2

Then get the names of the images in the folder. For this you can use this C# script. And parse the files names into a format that the Heron’s ESRI REST Service Geocode component expects.


Step 3

Then reproject the points from Lat/Lon to the coordinate system used by mosquito with the MapProject component. This component takes coordinates in Lon/Lat order. ProjPoint and CenterPoint inputs come from the MapVector component in the first step.

One unforeseen hurdle was that there were many participants outside Porto’s metropolitan area. Mosquito is not ideal to deal with national level data since it always requests major roads from OpenStreetMaps. The problem is that at large scales it can quickly turn into large amounts of data to fetch from the internet, making the script sluggish to work on. A makeshift solution was to import a SHP file with the national borders, which can be found here, and scale the national border and the point locations down to fit in a smaller area next to the city level map.

Step 4

The X/Y coordinates and the country map are scaled into a smaller area. The first step is to check which points lie outside the boundary of the metropolitan area map. I used an unreleased component of a plugin I’m working on but it can be replaced by Grasshopper’s own Point in Curve.


Step 5

The last step is to optimize the point locations to solve any point overlap or image frame overlap. The first thing is to move the points randomly a bit, for this I’m using a component that generates random vectors. The same can be accomplished using the grasshopper random number generator to generate random lengths and random angles. The next stage is to place the rectangles test for collisions and optimize their placement on the map. Lastly, the rectangles are turned into surfaces to which the images are mapped using Human’s Custom Preview Materials.



CM Map

The end result is on Rhino’s top view and can be exported to multiple formats.

Leave a Reply

Your email address will not be published. Required fields are marked *

4 × four =