Openstudio SDK - Generate DOE building from OpenStreetMap
Hello,
First time here.
My goal is to generate a typical DOE building from OpenStreetMap data. In the Openstudio application I have used the following workflow:
- Use the background map in FloorspaceJS
- Trace the footprint
- Apply a typical WWR
- Assign stub spaces
- Apply the
Create typical doe building from model
measure
I would like to replicate this workflow with the Ruby SDK.
I understand how to do it if I have a initial model, but I am struggling to understand how to build a geometry in the SDK. I have had a look at the code of Create bar from space type ratios
from openstudio-extension
, but apart from being quite complex, it seems to generate only rectangular footprints.
Can you suggest an approach? I was thinking that maybe I could start by generating a gbXML model, but before embarking in a big task I wanted to look for advice.
EDIT: Initial progress
I managed to create an initial version. I have used two gems: openstreetmap and geoutm.
This is the code
require "/Applications/OpenStudio-3.4.0/Ruby/openstudio.rb"
# OSM
require "openstreetmap"
require "geoutm"
model_name = "testOSM"
osm_way_id = 183091005
api = OpenStreetMap::Api.new
no_stories = 2
floor_to_floor_height = 3.0
osm_nodes = api.find_way(osm_way_id).nodes
osm_footprint = []
osm_nodes[0..-2].each do |osm_node|
osm_node_obj = api.find_node(osm_node)
latlon = GeoUtm::LatLon.new osm_node_obj.lat, osm_node_obj.lon
osm_footprint << [latlon.to_utm.e, latlon.to_utm.n]
end
pp osm_footprint
x_centre = osm_footprint.map { |v| v[0] }.reduce(:+) / osm_footprint.size
y_centre = osm_footprint.map { |v| v[1] }.reduce(:+) / osm_footprint.size
osm_footprint.map! { |v| [v[0] - x_centre, v[1] - y_centre] }
model = OpenStudio::Model::Model.new
spaces = OpenStudio::Model::SpaceVector.new
(0..(no_stories - 1)).each do |level|
z0 = level * floor_to_floor_height
footprint_vertices = OpenStudio::Point3dVector.new
osm_footprint.reverse.each do |vertex|
footprint_vertices << OpenStudio::Point3d.new(vertex[0], vertex[1], z0)
end
space = OpenStudio::Model::Space.fromFloorPrint(footprint_vertices, floor_to_floor_height, model)
space = space.get
spaces << space
space.setName("Level #{level}")
story = OpenStudio::Model::BuildingStory.new(model)
story.setName("Floor #{level}")
space.setBuildingStory(story)
zone = OpenStudio::Model::ThermalZone.new(model)
space.setThermalZone(zone)
zone.setName("Zone #{space.name}")
end
spaces[0].intersectSurfaces(spaces[1])
spaces[0].matchSurfaces(spaces[1])
model.save("#{model_name}.osm", true)
I think I am using intersectSurfaces
and matchSurfaces
incorrecty as I still have a roof in the middle and I get these messages when I run it
[openstudio.model.Surface] <1> Initial area of surface 'Surface 16' 340.807 does not equal post intersection area 340.828
[openstudio.model.Surface] <1> Initial area of other surface 'Surface 17' 340.807 does not equal post intersection area 340.828
Same issue if I use the model level version.
OpenStudio::Model.intersectSurfaces(spaces)
OpenStudio::Model.matchSurfaces(spaces)
See attached picture.