Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question

Revision history [back]

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.

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)

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)

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. image description