urbanopt-geojson 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rakeTasks +7 -0
  4. data/.rdoc_options +43 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +10 -0
  7. data/.travis.yml +35 -0
  8. data/CHANGELOG.md +5 -0
  9. data/Gemfile +27 -0
  10. data/Jenkinsfile +10 -0
  11. data/LICENSE.md +27 -0
  12. data/RDOC_MAIN.md +48 -0
  13. data/README.md +40 -0
  14. data/Rakefile +45 -0
  15. data/deploy_docs.sh +4 -0
  16. data/doc_templates/LICENSE.md +27 -0
  17. data/doc_templates/README.md.erb +42 -0
  18. data/doc_templates/copyright_erb.txt +31 -0
  19. data/doc_templates/copyright_js.txt +4 -0
  20. data/doc_templates/copyright_ruby.txt +29 -0
  21. data/docs/.gitignore +3 -0
  22. data/docs/.vuepress/components/BuildingProperties.vue +12 -0
  23. data/docs/.vuepress/components/DistrictSystemProperties.vue +12 -0
  24. data/docs/.vuepress/components/ElectricalConnectorProperties.vue +12 -0
  25. data/docs/.vuepress/components/ElectricalJunctionProperties.vue +12 -0
  26. data/docs/.vuepress/components/InnerJsonSchema.vue +80 -0
  27. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  28. data/docs/.vuepress/components/RegionProperties.vue +12 -0
  29. data/docs/.vuepress/components/SiteProperties.vue +12 -0
  30. data/docs/.vuepress/components/StaticLink.vue +8 -0
  31. data/docs/.vuepress/components/ThermalConnectorProperties.vue +12 -0
  32. data/docs/.vuepress/components/ThermalJunctionProperties.vue +12 -0
  33. data/docs/.vuepress/config.js +22 -0
  34. data/docs/.vuepress/highlight.js +8 -0
  35. data/docs/.vuepress/public/custom_rdoc_styles.css +64 -0
  36. data/docs/.vuepress/utils.js +17 -0
  37. data/docs/README.md +30 -0
  38. data/docs/doc/created.rid +0 -0
  39. data/docs/package-lock.json +11771 -0
  40. data/docs/package.json +22 -0
  41. data/docs/schemas/building-properties.md +3 -0
  42. data/docs/schemas/district-system-properties.md +3 -0
  43. data/docs/schemas/electrical-connector-properties.md +3 -0
  44. data/docs/schemas/electrical-junction-properties.md +3 -0
  45. data/docs/schemas/region-properties.md +3 -0
  46. data/docs/schemas/site-properties.md +3 -0
  47. data/docs/schemas/thermal-connector-properties.md +3 -0
  48. data/docs/schemas/thermal-junction-properties.md +3 -0
  49. data/lib/measures/.rubocop.yml +5 -0
  50. data/lib/measures/urban_geometry_creation/LICENSE.md +27 -0
  51. data/lib/measures/urban_geometry_creation/README.md +48 -0
  52. data/lib/measures/urban_geometry_creation/README.md.erb +42 -0
  53. data/lib/measures/urban_geometry_creation/measure.rb +199 -0
  54. data/lib/measures/urban_geometry_creation/measure.xml +139 -0
  55. data/lib/measures/urban_geometry_creation/tests/nrel_stm_footprints.geojson +3238 -0
  56. data/lib/measures/urban_geometry_creation/tests/shadowed_tests.rb +80 -0
  57. data/lib/measures/urban_geometry_creation/tests/urban_geometry_creation_test.rb +143 -0
  58. data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +27 -0
  59. data/lib/measures/urban_geometry_creation_zoning/README.md +48 -0
  60. data/lib/measures/urban_geometry_creation_zoning/README.md.erb +42 -0
  61. data/lib/measures/urban_geometry_creation_zoning/measure.rb +203 -0
  62. data/lib/measures/urban_geometry_creation_zoning/measure.xml +133 -0
  63. data/lib/measures/urban_geometry_creation_zoning/tests/nrel_stm_footprints.geojson +3238 -0
  64. data/lib/measures/urban_geometry_creation_zoning/tests/urban_geometry_creation_test.rb +143 -0
  65. data/lib/urbanopt/geojson.rb +41 -0
  66. data/lib/urbanopt/geojson/building.rb +341 -0
  67. data/lib/urbanopt/geojson/district_system.rb +53 -0
  68. data/lib/urbanopt/geojson/extension.rb +63 -0
  69. data/lib/urbanopt/geojson/feature.rb +206 -0
  70. data/lib/urbanopt/geojson/geo_file.rb +154 -0
  71. data/lib/urbanopt/geojson/helper.rb +340 -0
  72. data/lib/urbanopt/geojson/logging.rb +46 -0
  73. data/lib/urbanopt/geojson/mapper_classes.rb +85 -0
  74. data/lib/urbanopt/geojson/model.rb +133 -0
  75. data/lib/urbanopt/geojson/region.rb +55 -0
  76. data/lib/urbanopt/geojson/schema/building_properties.json +358 -0
  77. data/lib/urbanopt/geojson/schema/district_system_properties.json +137 -0
  78. data/lib/urbanopt/geojson/schema/electrical_connector_properties.json +77 -0
  79. data/lib/urbanopt/geojson/schema/electrical_junction_properties.json +64 -0
  80. data/lib/urbanopt/geojson/schema/geojson_schema.json +323 -0
  81. data/lib/urbanopt/geojson/schema/region_properties.json +93 -0
  82. data/lib/urbanopt/geojson/schema/site_properties.json +87 -0
  83. data/lib/urbanopt/geojson/schema/thermal_connector_properties.json +107 -0
  84. data/lib/urbanopt/geojson/schema/thermal_junction_properties.json +83 -0
  85. data/lib/urbanopt/geojson/update_areas.rb +102 -0
  86. data/lib/urbanopt/geojson/validate_geojson.rb +147 -0
  87. data/lib/urbanopt/geojson/version.rb +35 -0
  88. data/lib/urbanopt/geojson/workflows/building.osw +187 -0
  89. data/lib/urbanopt/geojson/workflows/building.osw.out +2806 -0
  90. data/lib/urbanopt/geojson/workflows/district_system.osw +84 -0
  91. data/lib/urbanopt/geojson/workflows/district_system.osw.out +646 -0
  92. data/lib/urbanopt/geojson/zoning.rb +134 -0
  93. data/package-lock.json +3 -0
  94. data/urbanopt-geojson-gem.gemspec +39 -0
  95. metadata +238 -0
@@ -0,0 +1,340 @@
1
+ # *********************************************************************************
2
+ # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
3
+ # contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list
9
+ # of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright notice, this
12
+ # list of conditions and the following disclaimer in the documentation and/or other
13
+ # materials provided with the distribution.
14
+ #
15
+ # Neither the name of the copyright holder nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without specific
17
+ # prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ # *********************************************************************************
30
+
31
+ module URBANopt
32
+ module GeoJSON
33
+ module Helper
34
+ ##
35
+ # This method loops though all the surfaces of the space and creates shading
36
+ # surfaces. It also removes the thermal zone and space type assigned to the space,
37
+ # if any.
38
+ #
39
+ # Returns an Array of instances of +OpenStudio::Model::ShadingSurfaceGroup+ .
40
+ #
41
+ # Used to convert adjacent buildings to shading surfaces.
42
+ # [Parameters]
43
+ # * +space+ - _Type:String_ - An instance of +OpenStudio::Model::Space+ .
44
+ def self.convert_to_shading_surface_group(space)
45
+ name = space.name.to_s
46
+ model = space.model
47
+ shading_group = OpenStudio::Model::ShadingSurfaceGroup.new(model)
48
+ space.surfaces.each do |surface|
49
+ shading_surface = OpenStudio::Model::ShadingSurface.new(surface.vertices, model)
50
+ shading_surface.setShadingSurfaceGroup(shading_group)
51
+ end
52
+ thermal_zone = space.thermalZone
53
+ if !thermal_zone.empty?
54
+ thermal_zone.get.remove
55
+ end
56
+ space_type = space.spaceType
57
+ space.remove
58
+ if !space_type.empty? && space_type.get.spaces.empty?
59
+ space_type.get.remove
60
+ end
61
+ shading_group.setName(name)
62
+ return [shading_group]
63
+ end
64
+
65
+ ##
66
+ # Returns array containing instance of +OpenStudio::Model::ShadingSurface+ .
67
+ #
68
+ # Used to create Photovoltaics and assign efficiency.
69
+ #
70
+ # [Parameters]
71
+ # * +feature+ - _Type:String_ - An instance of Feature class.
72
+ # * +height+ - _Type:Integer_ - Indicates the building height.
73
+ # * +model+ - _Type:String_ - An instance of +OpenStudio::Model::Model+ .
74
+ # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the
75
+ # origin's latitude & longitude.
76
+ # * +runner+ - _Type:String_ - An instance of +Openstudio::Measure::OSRunner+ for the measure run.
77
+ def self.create_photovoltaics(feature, height, model, origin_lat_lon, runner)
78
+ feature_id = feature.feature_json[:properties][:properties]
79
+ name = feature.name
80
+ floor_prints = []
81
+ multi_polygons = feature.get_multi_polygons
82
+ multi_polygons.each do |multi_polygon|
83
+ if multi_polygon.size > 1
84
+ runner.registerWarning('Ignoring holes in polygon')
85
+ end
86
+ multi_polygon.each do |polygon|
87
+ floor_print = floor_print_from_polygon(polygon, height, origin_lat_lon, runner)
88
+ if floor_print
89
+ floor_prints << OpenStudio.reverse(floor_print)
90
+ else
91
+ runner.registerWarning("Cannot create footprint for '#{name}'")
92
+ end
93
+ break
94
+ end
95
+ end
96
+ shading_surfaces = []
97
+ floor_prints.each do |floor_print|
98
+ shading_group = OpenStudio::Model::ShadingSurfaceGroup.new(model)
99
+ shading_surface = OpenStudio::Model::ShadingSurface.new(floor_print, model)
100
+ shading_surface.setShadingSurfaceGroup(shading_group)
101
+ shading_surface.setName('Photovoltaic Panel')
102
+ shading_surfaces << shading_surface
103
+ end
104
+ # create the inverter # :nodoc:
105
+ inverter = OpenStudio::Model::ElectricLoadCenterInverterSimple.new(model)
106
+ inverter.setInverterEfficiency(0.95)
107
+ # create the distribution system # :nodoc:
108
+ elcd = OpenStudio::Model::ElectricLoadCenterDistribution.new(model)
109
+ elcd.setInverter(inverter)
110
+ shading_surfaces.each do |shading_surface|
111
+ panel = OpenStudio::Model::GeneratorPhotovoltaic.simple(model)
112
+ panel.setSurface(shading_surface)
113
+ performance = panel.photovoltaicPerformance.to_PhotovoltaicPerformanceSimple.get
114
+ performance.setFractionOfSurfaceAreaWithActiveSolarCells(1.0)
115
+ performance.setFixedEfficiency(0.3)
116
+ elcd.addGenerator(panel)
117
+ end
118
+ return shading_surfaces
119
+ end
120
+
121
+ ##
122
+ # Returns array containing instance of +OpenStudio::Model::ShadingSurface+ .
123
+ #
124
+ # [Parameters]
125
+ # * +feature+ - _Type:String_ - An instance of Feature class.
126
+ # * +model+ - _Type:String_ - An instance of _OpenStudio::Model::Model_ .
127
+ # * +origin_lat_lon+ - _Type:Float_ - An instance of _OpenStudio::PointLatLon_ indicating the
128
+ # origin's latitude and longitude.
129
+ # * +runner+ - _Type:String_ - The measure run's instance of _OpenStudio::Measure::OSRunner_ .
130
+ # * +spaces+ -_Type:Array_ - Instances of _OpenStudio::Model::Space_ .
131
+ def self.create_shading_surfaces(feature, model, origin_lat_lon, runner, spaces)
132
+ max_z = 0
133
+ spaces.each do |space|
134
+ bb = space.boundingBox
135
+ max_z = [max_z, bb.maxZ.get].max
136
+ end
137
+ return create_photovoltaics(feature, max_z + 1, model, origin_lat_lon, runner)
138
+ end
139
+
140
+ ##
141
+ # This method loops through all the stories in the model, and returns any space
142
+ # types previously assigned.
143
+ #
144
+ # Returns array of +OpenStudio::Model::SpaceTypes+ .
145
+ #
146
+ # Used to create space types for each building story.
147
+ #
148
+ # [Parameters]
149
+ # * +stories+ - _Type:Array_ - An array of model/building stories.
150
+ # * +model+ - _Type:String_ - An instance of _OpenStudio::Model::Model_ .
151
+ # * +runner+ - _Type:String_ - The measure run's instance of _OpenStudio::Measure::OSRunner_ .
152
+ def self.create_space_types(stories, model, runner)
153
+ space_types = []
154
+ stories.each_index do |i|
155
+ space_type = nil
156
+ space = stories[i].spaces.first
157
+ if space && space.spaceType.is_initialized
158
+ space_type = space.spaceType.get
159
+ else
160
+ space_type = OpenStudio::Model::SpaceType.new(model)
161
+ runner.registerInfo("Story #{i} does not have a space type, creating new one")
162
+ end
163
+ space_types[i] = space_type
164
+ end
165
+ return space_types
166
+ end
167
+
168
+ ##
169
+ # Returns an +OpenStudio::Point3dVector+ .
170
+ #
171
+ # Creates the floor print for a given polygon.
172
+ #
173
+ # [Parameters]
174
+ # * +polygon+ - _Type:Array_ - An array of coordinate pairs.
175
+ # e.g.
176
+ # polygon = [
177
+ # [1, 5],
178
+ # [5, 5],
179
+ # [5, 1],
180
+ # ]
181
+ #
182
+ # * +elevation+ - _Type:Integer_ - Indicates the elevation.
183
+ # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the origin's latitude and longitude.
184
+ # * +runner+ - _Type:String_ - The measure run's instance of +OpenStudio::Measure::OSRunner+ .
185
+ # * +zoning+ - _Type:Boolean_ - Value is +True+ if utilizing detailed zoning, else +False+. Zoning is set to False by default.
186
+ def self.floor_print_from_polygon(polygon, elevation, origin_lat_lon, runner, zoning = false)
187
+ floor_print = OpenStudio::Point3dVector.new
188
+ all_points = OpenStudio::Point3dVector.new
189
+ polygon.each do |p|
190
+ lon = p[0]
191
+ lat = p[1]
192
+ point_3d = origin_lat_lon.toLocalCartesian(OpenStudio::PointLatLon.new(lat, lon, 0))
193
+ point_3d = OpenStudio::Point3d.new(point_3d.x, point_3d.y, elevation)
194
+ curr_print = zoning ? OpenStudio.getCombinedPoint(point_3d, all_points, 1.0) : point_3d
195
+ floor_print << curr_print
196
+ end
197
+ if floor_print.size < 3
198
+ runner.registerWarning('Cannot create floor print, fewer than 3 points')
199
+ return nil
200
+ end
201
+ floor_print = OpenStudio.removeCollinear(floor_print)
202
+ normal = OpenStudio.getOutwardNormal(floor_print)
203
+ if normal.empty?
204
+ runner.registerWarning('Cannot create floor print, cannot compute outward normal')
205
+ return nil
206
+ elsif normal.get.z > 0
207
+ floor_print = OpenStudio.reverse(floor_print)
208
+ runner.registerWarning('Reversing floor print')
209
+ end
210
+ return floor_print
211
+ end
212
+
213
+ ##
214
+ # Calculate which other buildings are shading the current feature and return as an array of
215
+ # +OpenStudio::Model::Space+.
216
+ #
217
+ # [Parameters]
218
+ # * +building+ - _Type:URBANopt::GeoJSON::Building_ - The core building that other buildings will be referenced.
219
+ # * +other_building_type+ - _Type:String_ - Describes the surrounding buildings. Currently 'ShadingOnly' is the only option that is processed.
220
+ # * +other_buildings+ - _Type:URBANopt::GeoJSON::FeatureCollection_ - List of surrounding buildings to include (self will be ignored if present in list).
221
+ # * +model+ - _Type:OpenStudio::Model::Model_ - An instance of an OpenStudio Model.
222
+ # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the latitude and longitude of the origin.
223
+ # * +runner+ - _Type:String_ - An instance of +Openstudio::Measure::OSRunner+ for the measure run.
224
+ # * +zoning+ - _Type:Boolean_ - Value is +true+ if utilizing detailed zoning, else
225
+ # +false+. Zoning is set to false by default. Currently, zoning set to +false+ is
226
+ # only supported.
227
+ def self.process_other_buildings(building, other_building_type, other_buildings, model, origin_lat_lon, runner, zoning = false)
228
+ # Empty array to store the new OpenStudio model spaces that need to be converted to shading objects
229
+ feature_points = building.feature_points(origin_lat_lon, runner, zoning)
230
+
231
+ other_spaces = []
232
+ runner.registerInfo("#{other_buildings[:features].size} nearby buildings found")
233
+ other_buildings[:features].each do |other_building|
234
+ other_id = other_building[:properties][:id]
235
+ next if other_id == building.id
236
+ if other_building_type == 'ShadingOnly'
237
+ # Checks if any building point is shaded by any other building point.
238
+ roof_elevation = other_building[:properties][:roof_elevation]
239
+ number_of_stories = other_building[:properties][:number_of_stories]
240
+ number_of_stories_above_ground = other_building[:properties][:number_of_stories_above_ground]
241
+ maximum_roof_height = other_building[:properties][:maximum_roof_height]
242
+
243
+ if number_of_stories_above_ground.nil?
244
+ number_of_stories_above_ground = number_of_stories
245
+ number_of_stories_below_ground = 0
246
+ else
247
+ number_of_stories_below_ground = number_of_stories - number_of_stories_above_ground
248
+ end
249
+
250
+ floor_to_floor_height = 3
251
+ if number_of_stories_above_ground && number_of_stories_above_ground > 0 && maximum_roof_height
252
+ floor_to_floor_height = maximum_roof_height / number_of_stories_above_ground
253
+ end
254
+ other_height = number_of_stories_above_ground * floor_to_floor_height
255
+ # find the polygon of the other_building by passing it to the get_multi_polygons method
256
+ other_building_points = building.other_points(other_building, other_height, origin_lat_lon, runner, zoning)
257
+ shadowed = URBANopt::GeoJSON::Helper.is_shadowed(feature_points, other_building_points, origin_lat_lon)
258
+ next unless shadowed
259
+ end
260
+
261
+ new_building = building.create_other_building(:space_per_building, model, origin_lat_lon, runner, zoning, other_building)
262
+ if new_building.nil? || new_building.empty?
263
+ runner.registerWarning("Failed to create spaces for other building '#{name}'")
264
+ end
265
+ other_spaces.concat(new_building)
266
+ end
267
+ return other_spaces
268
+ end
269
+
270
+ ##
271
+ # Returns Boolean which indicates whether the specified building is shadowed by
272
+ # other building.
273
+ #
274
+ # [Parameters]
275
+ # * +potentially_shaded+ - _Type:Array_ - An array of instances of +OpenStudio::Point3d+ .
276
+ # * +potential_shader+ - _Type:Array_ - Other array of instances of +OpenStudio::Point3d+ .
277
+ # * +origin_lat_lon+ _Type:Float_ - An instance of OpenStudio::PointLatLon indicating the origin's
278
+ # latitude and longitude.
279
+ def self.is_shadowed(potentially_shaded, potential_shader, origin_lat_lon)
280
+ all_pairs = []
281
+ potentially_shaded.each do |building_point|
282
+ potential_shader.each do |other_building_point|
283
+ vector = other_building_point - building_point
284
+ all_pairs << {
285
+ building_point: building_point,
286
+ other_building_point: other_building_point,
287
+ vector: vector,
288
+ distance: vector.length
289
+ }
290
+ end
291
+ end
292
+ all_pairs.sort! { |x, y| x[:distance] <=> y[:distance] }
293
+ all_pairs.each do |pair|
294
+ if is_shaded(pair[:building_point], pair[:other_building_point], origin_lat_lon)
295
+ return true
296
+ end
297
+ end
298
+ return false
299
+ end
300
+
301
+ ##
302
+ # Returns Boolean indicating if specified building is shadowed.
303
+ #
304
+ # [Parameters]
305
+ # * +building_point+ - _Type:Float_ - An instance of +OpenStudio::Point3d+ .
306
+ # * +other_building_point+ - _Type:Float_ - Other instance of +OpenStudio::Point3d+ .
307
+ # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the
308
+ # origin's latitude and longitude.
309
+ def self.is_shaded(building_point, other_building_point, origin_lat_lon)
310
+ vector = other_building_point - building_point
311
+ height = vector.z
312
+ distance = Math.sqrt(vector.x * vector.x + vector.y * vector.y)
313
+ if distance < 1
314
+ return true
315
+ end
316
+ hour_angle_rad = Math.atan2(-vector.x, -vector.y)
317
+ hour_angle = OpenStudio.radToDeg(hour_angle_rad)
318
+ latitude_rad = OpenStudio.degToRad(origin_lat_lon.lat)
319
+ result = false
320
+ (-24..24).each do |declination|
321
+ declination_rad = OpenStudio.degToRad(declination)
322
+ zenith_angle_rad = Math.acos(Math.sin(latitude_rad) * Math.sin(declination_rad) + Math.cos(latitude_rad) * Math.cos(declination_rad) * Math.cos(hour_angle_rad))
323
+ zenith_angle = OpenStudio.radToDeg(zenith_angle_rad)
324
+ elevation_angle = 90 - zenith_angle
325
+ apparent_angle_rad = Math.atan2(height, distance)
326
+ apparent_angle = OpenStudio.radToDeg(apparent_angle_rad)
327
+ if elevation_angle > 0 && elevation_angle < apparent_angle
328
+ result = true
329
+ break
330
+ end
331
+ end
332
+ return result
333
+ end
334
+
335
+ class << self
336
+ private :is_shaded
337
+ end
338
+ end
339
+ end
340
+ end
@@ -0,0 +1,46 @@
1
+ # *********************************************************************************
2
+ # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
3
+ # contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list
9
+ # of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright notice, this
12
+ # list of conditions and the following disclaimer in the documentation and/or other
13
+ # materials provided with the distribution.
14
+ #
15
+ # Neither the name of the copyright holder nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without specific
17
+ # prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ # *********************************************************************************
30
+
31
+ require 'logger'
32
+
33
+ module URBANopt
34
+ module GeoJSON
35
+ @@logger = Logger.new(STDERR)
36
+ @@logger.progname = 'URBANopt::GeoJSON'
37
+
38
+ def self.logger
39
+ @@logger
40
+ end
41
+
42
+ def self.setLogger(l)
43
+ @@logger = l
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,85 @@
1
+ # *********************************************************************************
2
+ # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
3
+ # contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list
9
+ # of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright notice, this
12
+ # list of conditions and the following disclaimer in the documentation and/or other
13
+ # materials provided with the distribution.
14
+ #
15
+ # Neither the name of the copyright holder nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without specific
17
+ # prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ # *********************************************************************************
30
+
31
+ require 'urbanopt/scenario'
32
+ require 'json'
33
+
34
+ module URBANopt
35
+ module GeoJSON
36
+ class Mapper < MapperBase
37
+ @@instance_lock = Mutex.new
38
+ @@osw = nil
39
+
40
+ ##
41
+ # This class inherits from the +MapperBase+ .
42
+ # Used to perform initializing functions, used to define the osw_path for
43
+ # baseline.osw for the URBANopt GeoJSON example project and the weather file.
44
+
45
+ def initialize()
46
+ @@instance_lock.synchronize do
47
+ if @@osw.nil?
48
+ osw_path = File.join(File.dirname(__FILE__), 'baseline.osw')
49
+ File.open(osw_path, 'r') do |file|
50
+ @@osw = JSON.parse(file.read, symbolize_names: true)
51
+ end
52
+ @@osw[:file_paths] << File.join(File.dirname(__FILE__), '../weather/')
53
+ @@osw = OpenStudio::Extension.configure_osw(@@osw)
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Creates an OpenStudio Workflow file for a given ScenarioBase object,
59
+ # feature id and feature name.
60
+ #
61
+ # [Parameters]
62
+ # * +scenario+ - _Type:String_ - Used to define the Scenario for the osw.
63
+
64
+ # * +feature_id+ - _Type:String/Number_ - Used to define the feature_id for
65
+ # which the osw is implemented.
66
+ #
67
+ # * +feature_name+ - _Type:String_ - The name of the feature.
68
+ def create_osw(scenario, feature_id, feature_name)
69
+ # get the feature from the scenario's feature_file #:nodoc:
70
+ feature_file = scenario.feature_file
71
+ feature = feature_file.get_feature_by_id(feature_id)
72
+
73
+ raise "Cannot find feature '#{feature_id}' in '#{scenario.geometry_file}'" if feature.nil?
74
+
75
+ # deep clone of @@osw before we configure it #:nodoc:
76
+ osw = Marshal.load(Marshal.dump(@@osw))
77
+
78
+ osw[:name] = feature_name
79
+ osw[:description] = feature_name
80
+
81
+ return osw
82
+ end
83
+ end
84
+ end
85
+ end