In the summer of 2016 I began working at Aurora Solar as a full-stack software engineer and their 12th employee ever. Aurora Solar’s mission was to reduce the cost of solar by providing software tools that were less expensive and more accurate than the traditional workflows of solar designers.
In my first few months I developed various features including a bar chart library, a page detailing simulation results, and a feature that I would name “fill zones”.
Still one of the most-used features today, I developed the “fill zones” feature so users could quickly and accurately design large-scale solar installations. At that time the only way users could place solar panels was either one-by-one or by auto-filling an entire roof face, neither of which was performant or flexible enough for use in the commercial solar market, a market the company wanted to expand into.
Knowing this, I designed the “fill zones” feature to be the killer feature of the commercial solar designer’s workflow, automatically placing the most non-overlapping panels in a user-defined area as well as calculating the wiring of the panels and associated power electronics that would satisfy design criteria.
Users outline a polygonal section of a roof face to define the first area of a “fill zone”. A “fill zone” is a set of pre-defined areas wherein all panels, inverters and other balance-of-system (BOS) components are automatically updated according to design criteria settings stored by the “fill zone” (i.e panel tilt, dc/ac ratio, overcurrent ratio, solar access ratio, etc).
These areas are dynamic, such that if an area’s space is adjusted, the panels, inverters, stringing, and more are automatically adjusted to satisfy design criteria and place the most panels possible.
An interesting technical aspect of the “fill zones” feature was figuring out how to place the most solar panels in a roof polygon while not overlapping obstructions in the roof such as chimneys, pipes, and walkways.
I called this the panel-fitting task and my goal during its development was to achieve near-optimal results (the most panels fit) displayed in a reasonable amount of time (<1 min till results visible to user). The fact that both the roof polygon and solar panels could be tilted and/or rotated added additional complexity.
Since solar panels are installed in grids I used a gridded search algorithm to find the optimal offset of a panel grid that results in the most panels placed without overlapping obstructions. A naive implementation of this search algorithm would check for overlaps with every obstruction for every panel to be placed.
To greatly reduce this number I used spatial hashing and “supercells” to only check “boundary” panels against nearby obstructions. Along with plenty of JSBench benchmarking I was able to get good performance in the panel-fitting task’s calculation of where to place panels. Despite this, the task was annoyingly slow to display results for the user.
From profiling I discovered that slow SVG insertion (due to browser “reflow”) was the bottleneck so I refactored the code to use the DocumentFragment interface as a drawing buffer. Buffering all the inserted SVG objects in the lightweight DocumentFragment first and then inserting the entire DocumentFragment into the document greatly reduced browser “reflow” and ensured that I could meet my goals of near-optimal results displayed in a reasonable amount of time.
Compared to the pre-existing feature that auto-filled entire roof faces, “fill zones” was up to 50x faster in addition to being significantly more useful in the commercial solar market. However, using the “fill zones” feature on larger commercial sites was exposing the limits of an SVG-based CAD engine in terms of DOM pollution, real-time interactivity, and graphics fidelity.
Together with my background in OpenGL and WebGL, these issues motivated me to meet with the CEO and suggest that we re-write our CAD engine in WebGL. In turn, my idea would spur the largest remake of the company’s product in its history, Aurora reDesigned.