urbanopt-geojson 0.2.0.pre3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +77 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +0 -3
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -2
- data/doc_templates/LICENSE.md +1 -1
- data/doc_templates/copyright_erb.txt +1 -1
- data/doc_templates/copyright_js.txt +1 -1
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/README.md +1 -1
- data/docs/package-lock.json +5206 -6883
- data/docs/package.json +12 -9
- data/lib/measures/.rubocop.yml +1 -1
- data/lib/measures/urban_geometry_creation/LICENSE.md +1 -1
- data/lib/measures/urban_geometry_creation/README.md +2 -2
- data/lib/measures/urban_geometry_creation/measure.rb +21 -2
- data/lib/measures/urban_geometry_creation/measure.xml +17 -20
- data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +1 -1
- data/lib/measures/urban_geometry_creation_zoning/README.md +1 -1
- data/lib/measures/urban_geometry_creation_zoning/measure.rb +5 -4
- data/lib/measures/urban_geometry_creation_zoning/measure.xml +15 -18
- data/lib/urbanopt-geojson.rb +1 -1
- data/lib/urbanopt/geojson.rb +2 -1
- data/lib/urbanopt/geojson/building.rb +74 -26
- data/lib/urbanopt/geojson/derived_extension.rb +1 -1
- data/lib/urbanopt/geojson/district_system.rb +1 -1
- data/lib/urbanopt/geojson/feature.rb +116 -2
- data/lib/urbanopt/geojson/geo_file.rb +28 -29
- data/lib/urbanopt/geojson/helper.rb +42 -7
- data/lib/urbanopt/geojson/logging.rb +1 -1
- data/lib/urbanopt/geojson/mapper_classes.rb +47 -47
- data/lib/urbanopt/geojson/model.rb +3 -4
- data/lib/urbanopt/geojson/region.rb +1 -1
- data/lib/urbanopt/geojson/scale_area.rb +91 -0
- data/lib/urbanopt/geojson/schema/building_properties.json +252 -80
- data/lib/urbanopt/geojson/schema/electrical_connector_properties.json +9 -9
- data/lib/urbanopt/geojson/schema/electrical_junction_properties.json +4 -5
- data/lib/urbanopt/geojson/schema/thermal_connector_properties.json +1 -1
- data/lib/urbanopt/geojson/schema/thermal_junction_properties.json +1 -1
- data/lib/urbanopt/geojson/update_areas.rb +2 -2
- data/lib/urbanopt/geojson/validate_geojson.rb +3 -1
- data/lib/urbanopt/geojson/version.rb +2 -2
- data/lib/urbanopt/geojson/workflows/building.osw.out +4 -4
- data/lib/urbanopt/geojson/zoning.rb +21 -16
- data/urbanopt-geojson-gem.gemspec +10 -17
- metadata +29 -48
- data/lib/change_log.rb +0 -147
- data/lib/measures/urban_geometry_creation/tests/nrel_stm_footprints.geojson +0 -3238
- data/lib/measures/urban_geometry_creation/tests/shadowed_tests.rb +0 -80
- data/lib/measures/urban_geometry_creation/tests/urban_geometry_creation_test.rb +0 -139
- data/lib/measures/urban_geometry_creation_zoning/tests/nrel_stm_footprints.geojson +0 -3238
- data/lib/measures/urban_geometry_creation_zoning/tests/urban_geometry_creation_zoning_test.rb +0 -139
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -44,8 +44,11 @@ module URBANopt
|
|
44
44
|
@feature_json = validate_feat(feature)
|
45
45
|
end
|
46
46
|
|
47
|
+
# rubocop:disable Style/MethodMissing
|
47
48
|
def method_missing(name, *args, &blk)
|
49
|
+
# rubocop:enable Style/MethodMissing
|
48
50
|
if @feature_json[:properties].keys.map(&:to_sym).include? name.to_sym
|
51
|
+
|
49
52
|
return @feature_json[:properties][name.to_sym]
|
50
53
|
else
|
51
54
|
super
|
@@ -95,6 +98,84 @@ module URBANopt
|
|
95
98
|
return @@feature_schema[feature_type]
|
96
99
|
end
|
97
100
|
|
101
|
+
def calculate_aspect_ratio
|
102
|
+
multi_polygons = get_multi_polygons(@feature_json)
|
103
|
+
rad_per_deg = 0.017453293
|
104
|
+
|
105
|
+
multi_polygons.each do |multi_polygon|
|
106
|
+
if multi_polygon.size > 1
|
107
|
+
runner.registerWarning('Ignoring holes in polygon')
|
108
|
+
end
|
109
|
+
multi_polygon.each do |polygon|
|
110
|
+
n = polygon.size
|
111
|
+
length = 0
|
112
|
+
north = 0
|
113
|
+
east = 0
|
114
|
+
south = 0
|
115
|
+
west = 0
|
116
|
+
aspect_ratio = 0
|
117
|
+
|
118
|
+
for i in (0..n - 2) do i
|
119
|
+
vertex_1 = nil
|
120
|
+
vertex_2 = nil
|
121
|
+
if i == n - 2
|
122
|
+
vertex_1 = polygon[n - 2]
|
123
|
+
vertex_2 = polygon[0]
|
124
|
+
else
|
125
|
+
vertex_1 = polygon[i]
|
126
|
+
vertex_2 = polygon[i + 1]
|
127
|
+
end
|
128
|
+
x_1 = vertex_1[0]
|
129
|
+
y_1 = vertex_1[1]
|
130
|
+
x_2 = vertex_2[0]
|
131
|
+
y_2 = vertex_2[1]
|
132
|
+
|
133
|
+
dist = (x_2 - x_1)**2 + (y_2 - y_1)**2
|
134
|
+
|
135
|
+
length = Math.sqrt(dist)
|
136
|
+
|
137
|
+
# delta latitude
|
138
|
+
dlat = x_2 - x_1
|
139
|
+
# delta longitude
|
140
|
+
dlon = y_2 - y_1
|
141
|
+
|
142
|
+
# convert radian to degree
|
143
|
+
sin_angle = Math.asin(dlon / length) * (1 / rad_per_deg)
|
144
|
+
sin_angle = sin_angle.round(4)
|
145
|
+
|
146
|
+
cos_angle = Math.acos(dlat / length) * (1 / rad_per_deg)
|
147
|
+
cos_angle = cos_angle.round(4)
|
148
|
+
|
149
|
+
if cos_angle >= 45 && cos_angle <= 135 && sin_angle >= 45 && sin_angle <= 90
|
150
|
+
north += length
|
151
|
+
elsif cos_angle >= 0 && cos_angle < 45 && sin_angle > -45 && sin_angle < 45
|
152
|
+
east += length
|
153
|
+
elsif cos_angle >= 45 && cos_angle <= 135 && sin_angle >= -90 && sin_angle <= -45
|
154
|
+
south += length
|
155
|
+
elsif cos_angle > 135 && cos_angle <= 180 && sin_angle > -45 && sin_angle < 45
|
156
|
+
west += length
|
157
|
+
end
|
158
|
+
|
159
|
+
if east + west != 0
|
160
|
+
aspect_ratio = (north + south) / (east + west)
|
161
|
+
else
|
162
|
+
aspect_ratio = 1
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
aspect_ratio = aspect_ratio.round(4)
|
168
|
+
return aspect_ratio
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def get_perimeter_multiplier(area, aspect_ratio, perimeter_original)
|
174
|
+
perimeter_new = 2 * (Math.sqrt(area * aspect_ratio) + Math.sqrt(area / aspect_ratio))
|
175
|
+
perimeter_ratio = perimeter_original / perimeter_new
|
176
|
+
return perimeter_ratio
|
177
|
+
end
|
178
|
+
|
98
179
|
##
|
99
180
|
# Returns coordinate with the minimum longitute and latitude within a given +building_json+ .
|
100
181
|
def get_min_lon_lat
|
@@ -164,13 +245,46 @@ module URBANopt
|
|
164
245
|
return OpenStudio::PointLatLon.new(min_lat, min_lon, 0)
|
165
246
|
end
|
166
247
|
|
248
|
+
##
|
249
|
+
# Used to determine the centroid for the feature's coordinates.
|
250
|
+
#
|
251
|
+
# [Parameters]
|
252
|
+
# * +vertices+ - The first set polygon vertices in the array of feature coordinates.
|
253
|
+
def find_feature_center(vertices)
|
254
|
+
number_of_locations = vertices.length
|
255
|
+
|
256
|
+
return vertices.first if number_of_locations == 1
|
257
|
+
|
258
|
+
x = y = z = 0.0
|
259
|
+
vertices.each do |station|
|
260
|
+
latitude = station[0] * Math::PI / 180
|
261
|
+
longitude = station[1] * Math::PI / 180
|
262
|
+
|
263
|
+
x += Math.cos(latitude) * Math.cos(longitude)
|
264
|
+
y += Math.cos(latitude) * Math.sin(longitude)
|
265
|
+
z += Math.sin(latitude)
|
266
|
+
end
|
267
|
+
|
268
|
+
x /= number_of_locations
|
269
|
+
y /= number_of_locations
|
270
|
+
z /= number_of_locations
|
271
|
+
|
272
|
+
central_longitude = Math.atan2(y, x)
|
273
|
+
central_square_root = Math.sqrt(x * x + y * y)
|
274
|
+
central_latitude = Math.atan2(z, central_square_root)
|
275
|
+
|
276
|
+
[central_latitude * 180 / Math::PI,
|
277
|
+
central_longitude * 180 / Math::PI]
|
278
|
+
end
|
279
|
+
|
167
280
|
private
|
168
281
|
|
169
282
|
##
|
170
283
|
# Used to validate the feature by checking +feature_id+ , +geometry+, +properties+
|
171
284
|
# and +geometry_type+ .
|
172
|
-
|
285
|
+
# rubocop:disable Style/CommentedKeyword
|
173
286
|
def validate_feat(feature) #:doc:
|
287
|
+
# rubocop:enable Style/CommentedKeyword
|
174
288
|
if feature.nil? || feature.empty?
|
175
289
|
raise("Feature '#{feature_id}' could not be found")
|
176
290
|
return false
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -80,7 +80,7 @@ module URBANopt
|
|
80
80
|
|
81
81
|
# initialize @@logger
|
82
82
|
@@logger ||= URBANopt::GeoJSON.logger
|
83
|
-
|
83
|
+
|
84
84
|
# validate each feature against schema
|
85
85
|
geojson_file[:features].each do |feature|
|
86
86
|
properties = feature[:properties]
|
@@ -93,16 +93,16 @@ module URBANopt
|
|
93
93
|
# Incase detailed_model_filename present check for fewer properties
|
94
94
|
if feature[:properties][:detailed_model_filename]
|
95
95
|
if feature[:properties][:id].nil?
|
96
|
-
raise(
|
96
|
+
raise('No id found for Building Feature')
|
97
97
|
end
|
98
98
|
if feature[:properties][:name].nil?
|
99
|
-
raise(
|
99
|
+
raise('No name found for Building Feature')
|
100
100
|
end
|
101
101
|
if feature[:properties][:number_of_stories].nil?
|
102
102
|
@@logger.warn("Number of stories is required to calculate shading using the UrbanGeometryCreation measure...ignoring #{feature[:properties][:id]} in shading calculations")
|
103
103
|
end
|
104
104
|
feature[:additionalProperties] = true
|
105
|
-
# Else validate for all required properties in the schema
|
105
|
+
# Else validate for all required properties in the schema
|
106
106
|
else
|
107
107
|
errors = validate(@@building_schema, properties)
|
108
108
|
end
|
@@ -114,16 +114,15 @@ module URBANopt
|
|
114
114
|
errors = validate(@@electrical_junction_schema, properties)
|
115
115
|
when 'ElectricalConnector'
|
116
116
|
errors = validate(@@electrical_connector_schema, properties)
|
117
|
-
when '
|
117
|
+
when 'ThermalJunction'
|
118
118
|
errors = validate(@@thermal_junction_schema, properties)
|
119
119
|
when 'ThermalConnector'
|
120
120
|
errors = validate(@@thermal_connector_schema, properties)
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
unless errors.empty?
|
124
|
-
raise
|
124
|
+
raise "#{type} does not adhere to schema: \n #{errors.join('\n ')}"
|
125
125
|
end
|
126
|
-
|
127
126
|
end
|
128
127
|
return new(geojson_file, path)
|
129
128
|
end
|
@@ -163,6 +162,7 @@ module URBANopt
|
|
163
162
|
# merge site origin properties
|
164
163
|
f = merge_site_properties(f)
|
165
164
|
if f[:properties][:type] == 'Building'
|
165
|
+
|
166
166
|
return URBANopt::GeoJSON::Building.new(f)
|
167
167
|
elsif f[:properties] && f[:properties][:type] == 'District System'
|
168
168
|
return URBANopt::GeoJSON::DistrictSystem.new(f)
|
@@ -172,9 +172,9 @@ module URBANopt
|
|
172
172
|
return nil
|
173
173
|
end
|
174
174
|
|
175
|
-
##
|
176
|
-
# Merge Site Properties in Feature.
|
177
|
-
#
|
175
|
+
##
|
176
|
+
# Merge Site Properties in Feature. Returns feature with site properties added to its properties section. Does not overwrite existing properties.
|
177
|
+
#
|
178
178
|
# [Parameters]
|
179
179
|
# +feature+ - _Type:Hash_ - feature object.
|
180
180
|
def merge_site_properties(feature)
|
@@ -183,23 +183,23 @@ module URBANopt
|
|
183
183
|
project = @geojson_file[:project]
|
184
184
|
end
|
185
185
|
|
186
|
-
# this maps site properties to building/district system properties.
|
186
|
+
# this maps site properties to building/district system properties.
|
187
187
|
add_props = [
|
188
|
-
{site: :surface_elevation, feature: :surface_elevation},
|
189
|
-
{site: :timesteps_per_hour, feature: :timesteps_per_hour},
|
190
|
-
{site: :begin_date, feature: :begin_date},
|
191
|
-
{site: :end_date, feature: :end_date},
|
192
|
-
{site: :cec_climate_zone, feature: :cec_climate_zone},
|
193
|
-
{site: :climate_zone, feature: :climate_zone},
|
194
|
-
{site: :default_template, feature: :template},
|
195
|
-
{site: :weather_filename, feature: :weather_filename},
|
196
|
-
{site: :tariff_filename, feature: :tariff_filename}
|
188
|
+
{ site: :surface_elevation, feature: :surface_elevation },
|
189
|
+
{ site: :timesteps_per_hour, feature: :timesteps_per_hour },
|
190
|
+
{ site: :begin_date, feature: :begin_date },
|
191
|
+
{ site: :end_date, feature: :end_date },
|
192
|
+
{ site: :cec_climate_zone, feature: :cec_climate_zone },
|
193
|
+
{ site: :climate_zone, feature: :climate_zone },
|
194
|
+
{ site: :default_template, feature: :template },
|
195
|
+
{ site: :weather_filename, feature: :weather_filename },
|
196
|
+
{ site: :tariff_filename, feature: :tariff_filename }
|
197
197
|
]
|
198
198
|
|
199
199
|
add_props.each do |prop|
|
200
|
-
if project.key?(prop[:site])
|
200
|
+
if project.key?(prop[:site]) && project[prop[:site]]
|
201
201
|
# property exists in site
|
202
|
-
if !feature[:properties].key?(prop[:feature])
|
202
|
+
if !feature[:properties].key?(prop[:feature]) || feature[:properties][prop[:feature]].nil? || feature[:properties][prop[:feature]].empty?
|
203
203
|
# property does not exist in feature or is nil: add site property (don't overwrite)
|
204
204
|
feature[:properties][prop[:feature]] = project[prop[:site]]
|
205
205
|
end
|
@@ -210,10 +210,10 @@ module URBANopt
|
|
210
210
|
end
|
211
211
|
|
212
212
|
##
|
213
|
-
# Validate GeoJSON against schema
|
213
|
+
# Validate GeoJSON against schema.
|
214
214
|
#
|
215
215
|
# [Parameters]
|
216
|
-
# * +data+ - + - _Type:Hash_ - Input GeoJSON file
|
216
|
+
# * +data+ - + - _Type:Hash_ - Input GeoJSON file
|
217
217
|
def self.validate(schema_json, data)
|
218
218
|
errors = JSON::Validator.fully_validate(schema_json, data, errors_as_objects: true)
|
219
219
|
return errors
|
@@ -243,7 +243,7 @@ module URBANopt
|
|
243
243
|
end
|
244
244
|
return result
|
245
245
|
end
|
246
|
-
|
246
|
+
|
247
247
|
def self.get_district_system_schema(strict)
|
248
248
|
result = nil
|
249
249
|
File.open(File.dirname(__FILE__) + '/schema/district_system_properties.json') do |f|
|
@@ -256,7 +256,7 @@ module URBANopt
|
|
256
256
|
end
|
257
257
|
return result
|
258
258
|
end
|
259
|
-
|
259
|
+
|
260
260
|
def self.get_region_schema(strict)
|
261
261
|
result = nil
|
262
262
|
File.open(File.dirname(__FILE__) + '/schema/region_properties.json') do |f|
|
@@ -331,7 +331,6 @@ module URBANopt
|
|
331
331
|
@@electrical_junction_schema = get_electrical_junction_schema(strict)
|
332
332
|
@@thermal_connector_schema = get_thermal_connector_schema(strict)
|
333
333
|
@@thermal_junction_schema = get_thermal_junction_schema(strict)
|
334
|
-
|
335
334
|
end
|
336
335
|
end
|
337
336
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -154,7 +154,7 @@ module URBANopt
|
|
154
154
|
stories.each_index do |i|
|
155
155
|
space_type = nil
|
156
156
|
space = stories[i].spaces.first
|
157
|
-
if space
|
157
|
+
if space&.spaceType&.is_initialized
|
158
158
|
space_type = space.spaceType.get
|
159
159
|
else
|
160
160
|
space_type = OpenStudio::Model::SpaceType.new(model)
|
@@ -183,7 +183,9 @@ module URBANopt
|
|
183
183
|
# * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the origin's latitude and longitude.
|
184
184
|
# * +runner+ - _Type:String_ - The measure run's instance of +OpenStudio::Measure::OSRunner+ .
|
185
185
|
# * +zoning+ - _Type:Boolean_ - Value is +True+ if utilizing detailed zoning, else +False+. Zoning is set to False by default.
|
186
|
-
|
186
|
+
# * +scaled_footprint_area+ - Used to scale the footprint area using the floor area. 0 by
|
187
|
+
# default (no scaling).
|
188
|
+
def self.floor_print_from_polygon(polygon, elevation, origin_lat_lon, runner, zoning = false, scaled_footprint_area = 0)
|
187
189
|
floor_print = OpenStudio::Point3dVector.new
|
188
190
|
all_points = OpenStudio::Point3dVector.new
|
189
191
|
polygon.each do |p|
|
@@ -207,22 +209,48 @@ module URBANopt
|
|
207
209
|
floor_print = OpenStudio.reverse(floor_print)
|
208
210
|
runner.registerWarning('Reversing floor print')
|
209
211
|
end
|
212
|
+
|
213
|
+
# check for scaling
|
214
|
+
if scaled_footprint_area > 0
|
215
|
+
|
216
|
+
# check that the scaled_footprint_area desired is no less than X % of the original
|
217
|
+
original_floor_print_area = OpenStudio.getArea(floor_print).get
|
218
|
+
if scaled_footprint_area / original_floor_print_area <= 0.5 || scaled_footprint_area / original_floor_print_area >= 2
|
219
|
+
# TOO MUCH SCALING...using original footprint when scaled is 2x bigger or smaller than the original
|
220
|
+
runner.registerWarning('Desired scaled_footprint_area is a factor of 2 of the original footprint...keeping original footprint (no scaling!)')
|
221
|
+
else
|
222
|
+
new_floor_print = adjust_vertices_to_area(floor_print, scaled_footprint_area, runner)
|
223
|
+
new_footprint_area = OpenStudio.getArea(new_floor_print).get
|
224
|
+
runner.registerInfo("New floor area: #{new_footprint_area}, compared to scaled area desired: #{scaled_footprint_area}")
|
225
|
+
floor_print = new_floor_print
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
210
229
|
return floor_print
|
211
230
|
end
|
212
231
|
|
232
|
+
# scale footprint to desired area, keeping the shape
|
233
|
+
def self.adjust_vertices_to_area(vertices, desired_area, runner, eps = 0.1)
|
234
|
+
ar = ScaleArea.new(vertices, desired_area, runner, eps)
|
235
|
+
|
236
|
+
n = Newton.nlsolve(ar, [0])
|
237
|
+
|
238
|
+
return ar.new_vertices
|
239
|
+
end
|
240
|
+
|
213
241
|
##
|
214
242
|
# Calculate which other buildings are shading the current feature and return as an array of
|
215
243
|
# +OpenStudio::Model::Space+.
|
216
244
|
#
|
217
245
|
# [Parameters]
|
218
246
|
# * +building+ - _Type:URBANopt::GeoJSON::Building_ - The core building that other buildings will be referenced.
|
219
|
-
# * +other_building_type+ - _Type:String_ - Describes the surrounding buildings.
|
247
|
+
# * +other_building_type+ - _Type:String_ - Describes the surrounding buildings.
|
220
248
|
# * +other_buildings+ - _Type:URBANopt::GeoJSON::FeatureCollection_ - List of surrounding buildings to include (self will be ignored if present in list).
|
221
249
|
# * +model+ - _Type:OpenStudio::Model::Model_ - An instance of an OpenStudio Model.
|
222
250
|
# * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the latitude and longitude of the origin.
|
223
251
|
# * +runner+ - _Type:String_ - An instance of +Openstudio::Measure::OSRunner+ for the measure run.
|
224
252
|
# * +zoning+ - _Type:Boolean_ - Value is +true+ if utilizing detailed zoning, else
|
225
|
-
# +false+. Zoning is set to false by default.
|
253
|
+
# +false+. Zoning is set to false by default.
|
226
254
|
def self.process_other_buildings(building, other_building_type, other_buildings, model, origin_lat_lon, runner, zoning = false)
|
227
255
|
# Empty array to store the new OpenStudio model spaces that need to be converted to shading objects
|
228
256
|
feature_points = building.feature_points(origin_lat_lon, runner, zoning)
|
@@ -243,6 +271,7 @@ module URBANopt
|
|
243
271
|
if number_of_stories_above_ground.nil?
|
244
272
|
number_of_stories_above_ground = number_of_stories
|
245
273
|
number_of_stories_below_ground = 0
|
274
|
+
|
246
275
|
else
|
247
276
|
number_of_stories_below_ground = number_of_stories - number_of_stories_above_ground
|
248
277
|
end
|
@@ -251,11 +280,18 @@ module URBANopt
|
|
251
280
|
if number_of_stories_above_ground && number_of_stories_above_ground > 0 && maximum_roof_height
|
252
281
|
floor_to_floor_height = maximum_roof_height / number_of_stories_above_ground
|
253
282
|
end
|
283
|
+
|
284
|
+
# check that feature has a # stories
|
285
|
+
if number_of_stories_above_ground.nil?
|
286
|
+
runner.registerWarning("[geojson process_other_buildings] Unable to include feature #{other_building[:properties][:id]} in shading calculations: no 'number of stories' data")
|
287
|
+
end
|
288
|
+
next if number_of_stories_above_ground.nil?
|
289
|
+
|
254
290
|
other_height = number_of_stories_above_ground * floor_to_floor_height
|
255
291
|
# find the polygon of the other_building by passing it to the get_multi_polygons method
|
256
292
|
other_building_points = building.other_points(other_building, other_height, origin_lat_lon, runner, zoning)
|
257
293
|
shadowed = URBANopt::GeoJSON::Helper.is_shadowed(feature_points, other_building_points, origin_lat_lon)
|
258
|
-
next unless shadowed
|
294
|
+
next unless shadowed
|
259
295
|
new_building = building.create_other_building(:space_per_building, model, origin_lat_lon, runner, zoning, other_building)
|
260
296
|
if new_building.nil? || new_building.empty?
|
261
297
|
runner.registerWarning("Failed to create spaces for other building '#{name}'")
|
@@ -264,7 +300,6 @@ module URBANopt
|
|
264
300
|
|
265
301
|
elsif other_building_type == 'None'
|
266
302
|
end
|
267
|
-
|
268
303
|
end
|
269
304
|
return other_spaces
|
270
305
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -32,54 +32,54 @@ require 'urbanopt/scenario'
|
|
32
32
|
require 'json'
|
33
33
|
|
34
34
|
module URBANopt
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
module GeoJSON
|
36
|
+
class Mapper < MapperBase
|
37
|
+
@@instance_lock = Mutex.new
|
38
|
+
@@osw = nil
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
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)
|
82
51
|
end
|
52
|
+
@@osw[:file_paths] << File.join(File.dirname(__FILE__), '../weather/')
|
53
|
+
@@osw = OpenStudio::Extension.configure_osw(@@osw)
|
54
|
+
end
|
83
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
|
+
# * +feature_id+ - _Type:String/Number_ - Used to define the feature_id for
|
64
|
+
# which the osw is implemented.
|
65
|
+
#
|
66
|
+
# * +feature_name+ - _Type:String_ - The name of the feature.
|
67
|
+
# rubocop:disable Lint/NestedMethodDefinition
|
68
|
+
def create_osw(scenario, feature_id, feature_name)
|
69
|
+
# rubocop:enable Lint/NestedMethodDefinition
|
70
|
+
# get the feature from the scenario's feature_file #:nodoc:
|
71
|
+
feature_file = scenario.feature_file
|
72
|
+
feature = feature_file.get_feature_by_id(feature_id)
|
73
|
+
raise "Cannot find feature '#{feature_id}' in '#{scenario.geometry_file}'" if feature.nil?
|
74
|
+
# deep clone of @@osw before we configure it #:nodoc:
|
75
|
+
osw = Marshal.load(Marshal.dump(@@osw))
|
76
|
+
osw[:name] = feature_name
|
77
|
+
osw[:description] = feature_name
|
78
|
+
end
|
79
|
+
# rubocop:disable Lint/ReturnInVoidContext
|
80
|
+
return osw
|
81
|
+
# rubocop:enable Lint/ReturnInVoidContext
|
82
|
+
end
|
84
83
|
end
|
85
|
-
end
|
84
|
+
end
|
85
|
+
end
|