WiGLE is a popular platform which can be used for finding the location of a device using the names of WiFi networks in its vicinity. I’ve written about this before, and wrote some Python code to interact with their API. This API has since been retired and replaced with a new one, as of December […]

This post won’t be for everyone, but if you’re into using Python there’s a lot you can do to make EnergyPlus input files easier understand and analyse.

I’m slowly putting together a few useful functions to help with analysing models I and others have built, and one of the basic building blocks is a way of measuring the surface area of each building element. For anyone not interested in EnergyPlus, it’s also a set of Python functions for getting the area of any polygon in 3D space.

This is basically the VBA function for polygon area in a 2D coordinate system, translated into Python and extended to a 3D coordinate system.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import numpy as np #area of polygon, poly def poly_area(poly): if len(poly) < 3: # not a polygon - no area return 0 total = [0, 0, 0] N = len(poly) for i in range(N): vi1 = poly[i] vi2 = poly[(i+1) % N] prod = np.cross(vi1, vi2) total[0] += prod[0] total[1] += prod[1] total[2] += prod[2] result = np.dot(total, unit_normal(poly[0], poly[1], poly[2])) return abs(result/2) #unit normal vector of plane defined by points a, b, and c def unit_normal(a, b, c): x = np.linalg.det([[1,a[1],a[2]], [1,b[1],b[2]], [1,c[1],c[2]]]) y = np.linalg.det([[a[0],1,a[2]], [b[0],1,b[2]], [c[0],1,c[2]]]) z = np.linalg.det([[a[0],a[1],1], [b[0],b[1],1], [c[0],c[1],1]]) magnitude = (x**2 + y**2 + z**2)**.5 return (x/magnitude, y/magnitude, z/magnitude) |

To use the function you pass it a set of vertices as a list of lists in the form `[[x1,y1,z1],[x2,y2,z2],...,[xn,yn,zn]]`

.

If you’re not using EnergyPlus then that’s all you need to know. If you are, how you get that list depends on which version of EnergyPlus you’re using. If you’re using version 5.x then the vertices listed in lines with the form:

1 |
0, 0, 0, !- X,Y,Z 1 {m} |

And in version 6.x they are:

1 2 3 |
40.3011335121, !- Vertex 1 X-coordinate {m} -11.5445805184, !- Vertex 1 Y-coordinate {m} 14.5813950138, !- Vertex 1 Z-coordinate {m} |

The functions to extract the vertices for a building surface are:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def gv_5(surface): # for EnergyPlus version 5.x vertices = [] for line in surface: if "X,Y,Z" in line: line = line.replace(";",",").strip().split(",") vtx = float(line[0]), float(line[1]), float(line[2]) vertices.append(vtx) return vertices def gv_6(surface): # for EnergyPlus version 6.x v_temp = [] vertices = [] for line in surface: if "Vertex" in line: v_temp.append(float(line.split().pop(0).replace(",","").replace(";",""))) for i in range(len(v_temp) / 3): vertices.append([v_temp[i*3],v_temp[i*3+1],v_temp[i*3+2]]) return vertices |

The parameter `surface`

refers to either a `BuildingSurface:Detailed`

object or a `FenestrationSurface:Detailed`

object. To get these, open your .idf or .imf as read only, and whenever you reach a line which contains “Surface:Detailed” call the `get_surface()`

function on your open file:

1 2 3 4 5 6 7 |
def get_surface(f): surface = [] while True: line = f.readline() surface.append(line) if ";" in line: # end of object return surface |

Here’s some test code you can try out. Without a bit of additional work, all it does it print a list of surface areas to the console but keep your eyes open for more options here in the future. If you’re using version 5 then just swap out `gv_6(surface)`

for `gv_5(surface)`

:

1 2 3 4 5 6 7 8 9 |
f = open(filename, 'r') while 1: line = f.readline() if not line: break # Break at end of file if "Surface:Detailed" in line: surface = get_surface(f) vertices = gv_6(surface) area = poly_area(vertices) print area |

Hope it helps.