urbanopt-geojson 0.3.0.pre1 → 0.5.1
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 +4 -4
- data/.github/pull_request_template.md +2 -2
- data/CHANGELOG.md +52 -6
- data/CONTRIBUTING.md +1 -1
- data/LICENSE.md +1 -1
- data/RDOC_MAIN.md +26 -22
- data/README.md +2 -2
- data/Rakefile +1 -1
- 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/.vuepress/components/InnerJsonSchema.vue +7 -11
- data/docs/.vuepress/config.js +11 -1
- data/docs/.vuepress/highlight.js +1 -1
- data/docs/.vuepress/json-schema-deref-loader.js +22 -0
- data/docs/README.md +3 -4
- data/docs/package-lock.json +5204 -6881
- 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 +8 -0
- data/lib/measures/urban_geometry_creation/measure.rb +21 -4
- data/lib/measures/urban_geometry_creation/measure.xml +34 -20
- data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +1 -1
- data/lib/measures/urban_geometry_creation_zoning/measure.rb +3 -3
- data/lib/measures/urban_geometry_creation_zoning/measure.xml +8 -13
- data/lib/urbanopt-geojson.rb +1 -1
- data/lib/urbanopt/geojson.rb +2 -1
- data/lib/urbanopt/geojson/building.rb +61 -10
- data/lib/urbanopt/geojson/derived_extension.rb +1 -1
- data/lib/urbanopt/geojson/district_system.rb +1 -1
- data/lib/urbanopt/geojson/feature.rb +117 -3
- data/lib/urbanopt/geojson/geo_file.rb +3 -4
- data/lib/urbanopt/geojson/helper.rb +46 -3
- data/lib/urbanopt/geojson/logging.rb +1 -1
- data/lib/urbanopt/geojson/mapper_classes.rb +1 -1
- data/lib/urbanopt/geojson/model.rb +3 -4
- data/lib/urbanopt/geojson/region.rb +1 -1
- data/lib/urbanopt/geojson/scale_area.rb +95 -0
- data/lib/urbanopt/geojson/schema/building_properties.json +248 -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 +1 -1
- data/lib/urbanopt/geojson/validate_geojson.rb +1 -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 +5 -12
- metadata +14 -30
- 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,
|
@@ -47,9 +47,8 @@ module URBANopt
|
|
47
47
|
# rubocop:disable Style/MethodMissing
|
48
48
|
def method_missing(name, *args, &blk)
|
49
49
|
# rubocop:enable Style/MethodMissing
|
50
|
-
# rubocop:disable Style/GuardClause
|
51
50
|
if @feature_json[:properties].keys.map(&:to_sym).include? name.to_sym
|
52
|
-
|
51
|
+
|
53
52
|
return @feature_json[:properties][name.to_sym]
|
54
53
|
else
|
55
54
|
super
|
@@ -99,6 +98,89 @@ module URBANopt
|
|
99
98
|
return @@feature_schema[feature_type]
|
100
99
|
end
|
101
100
|
|
101
|
+
##
|
102
|
+
# Used to calculate the aspect ratio for a given floor polygon.
|
103
|
+
#
|
104
|
+
def calculate_aspect_ratio
|
105
|
+
multi_polygons = get_multi_polygons(@feature_json)
|
106
|
+
rad_per_deg = 0.017453293
|
107
|
+
|
108
|
+
multi_polygons.each do |multi_polygon|
|
109
|
+
if multi_polygon.size > 1
|
110
|
+
runner.registerWarning('Ignoring holes in polygon')
|
111
|
+
end
|
112
|
+
multi_polygon.each do |polygon|
|
113
|
+
n = polygon.size
|
114
|
+
length = 0
|
115
|
+
north = 0
|
116
|
+
east = 0
|
117
|
+
south = 0
|
118
|
+
west = 0
|
119
|
+
aspect_ratio = 0
|
120
|
+
|
121
|
+
for i in (0..n - 2) do i
|
122
|
+
vertex_1 = nil
|
123
|
+
vertex_2 = nil
|
124
|
+
if i == n - 2
|
125
|
+
vertex_1 = polygon[n - 2]
|
126
|
+
vertex_2 = polygon[0]
|
127
|
+
else
|
128
|
+
vertex_1 = polygon[i]
|
129
|
+
vertex_2 = polygon[i + 1]
|
130
|
+
end
|
131
|
+
x_1 = vertex_1[0]
|
132
|
+
y_1 = vertex_1[1]
|
133
|
+
x_2 = vertex_2[0]
|
134
|
+
y_2 = vertex_2[1]
|
135
|
+
|
136
|
+
dist = (x_2 - x_1)**2 + (y_2 - y_1)**2
|
137
|
+
|
138
|
+
length = Math.sqrt(dist)
|
139
|
+
|
140
|
+
# delta latitude
|
141
|
+
dlat = x_2 - x_1
|
142
|
+
# delta longitude
|
143
|
+
dlon = y_2 - y_1
|
144
|
+
|
145
|
+
# convert radian to degree
|
146
|
+
sin_angle = Math.asin(dlon / length) * (1 / rad_per_deg)
|
147
|
+
sin_angle = sin_angle.round(4)
|
148
|
+
|
149
|
+
cos_angle = Math.acos(dlat / length) * (1 / rad_per_deg)
|
150
|
+
cos_angle = cos_angle.round(4)
|
151
|
+
|
152
|
+
if cos_angle >= 45 && cos_angle <= 135 && sin_angle >= 45 && sin_angle <= 90
|
153
|
+
north += length
|
154
|
+
elsif cos_angle >= 0 && cos_angle < 45 && sin_angle > -45 && sin_angle < 45
|
155
|
+
east += length
|
156
|
+
elsif cos_angle >= 45 && cos_angle <= 135 && sin_angle >= -90 && sin_angle <= -45
|
157
|
+
south += length
|
158
|
+
elsif cos_angle > 135 && cos_angle <= 180 && sin_angle > -45 && sin_angle < 45
|
159
|
+
west += length
|
160
|
+
end
|
161
|
+
|
162
|
+
if east + west != 0
|
163
|
+
aspect_ratio = (north + south) / (east + west)
|
164
|
+
else
|
165
|
+
aspect_ratio = 1
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
aspect_ratio = aspect_ratio.round(4)
|
171
|
+
return aspect_ratio
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Used to calculate the perimeter multiplier given the aspect ratio, original perimeter and area.
|
178
|
+
def get_perimeter_multiplier(area, aspect_ratio, perimeter_original)
|
179
|
+
perimeter_new = 2 * (Math.sqrt(area * aspect_ratio) + Math.sqrt(area / aspect_ratio))
|
180
|
+
perimeter_ratio = perimeter_original / perimeter_new
|
181
|
+
return perimeter_ratio
|
182
|
+
end
|
183
|
+
|
102
184
|
##
|
103
185
|
# Returns coordinate with the minimum longitute and latitude within a given +building_json+ .
|
104
186
|
def get_min_lon_lat
|
@@ -168,6 +250,38 @@ module URBANopt
|
|
168
250
|
return OpenStudio::PointLatLon.new(min_lat, min_lon, 0)
|
169
251
|
end
|
170
252
|
|
253
|
+
##
|
254
|
+
# Used to determine the centroid for the feature's coordinates.
|
255
|
+
#
|
256
|
+
# [Parameters]
|
257
|
+
# * +vertices+ - The first set polygon vertices in the array of feature coordinates.
|
258
|
+
def find_feature_center(vertices)
|
259
|
+
number_of_locations = vertices.length
|
260
|
+
|
261
|
+
return vertices.first if number_of_locations == 1
|
262
|
+
|
263
|
+
x = y = z = 0.0
|
264
|
+
vertices.each do |station|
|
265
|
+
latitude = station[0] * Math::PI / 180
|
266
|
+
longitude = station[1] * Math::PI / 180
|
267
|
+
|
268
|
+
x += Math.cos(latitude) * Math.cos(longitude)
|
269
|
+
y += Math.cos(latitude) * Math.sin(longitude)
|
270
|
+
z += Math.sin(latitude)
|
271
|
+
end
|
272
|
+
|
273
|
+
x /= number_of_locations
|
274
|
+
y /= number_of_locations
|
275
|
+
z /= number_of_locations
|
276
|
+
|
277
|
+
central_longitude = Math.atan2(y, x)
|
278
|
+
central_square_root = Math.sqrt(x * x + y * y)
|
279
|
+
central_latitude = Math.atan2(z, central_square_root)
|
280
|
+
|
281
|
+
[central_latitude * 180 / Math::PI,
|
282
|
+
central_longitude * 180 / Math::PI]
|
283
|
+
end
|
284
|
+
|
171
285
|
private
|
172
286
|
|
173
287
|
##
|
@@ -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,
|
@@ -161,9 +161,8 @@ module URBANopt
|
|
161
161
|
if f[:properties] && f[:properties][:id] == feature_id
|
162
162
|
# merge site origin properties
|
163
163
|
f = merge_site_properties(f)
|
164
|
-
# rubocop:disable Style/GuardClause
|
165
164
|
if f[:properties][:type] == 'Building'
|
166
|
-
|
165
|
+
|
167
166
|
return URBANopt::GeoJSON::Building.new(f)
|
168
167
|
elsif f[:properties] && f[:properties][:type] == 'District System'
|
169
168
|
return URBANopt::GeoJSON::DistrictSystem.new(f)
|
@@ -200,7 +199,7 @@ module URBANopt
|
|
200
199
|
add_props.each do |prop|
|
201
200
|
if project.key?(prop[:site]) && project[prop[:site]]
|
202
201
|
# property exists in site
|
203
|
-
if !feature[:properties].key?(prop[:feature]) || feature[:properties][prop[:feature]].nil? || feature[:properties][prop[:feature]].empty?
|
202
|
+
if !feature[:properties].key?(prop[:feature]) || feature[:properties][prop[:feature]].nil? || feature[:properties][prop[:feature]].to_s.empty?
|
204
203
|
# property does not exist in feature or is nil: add site property (don't overwrite)
|
205
204
|
feature[:properties][prop[:feature]] = project[prop[:site]]
|
206
205
|
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,9 +209,42 @@ 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
|
+
##
|
233
|
+
# Used to scale footprint to desired area while keeping the original shape.
|
234
|
+
#
|
235
|
+
# [Parameters]
|
236
|
+
# * +vertices+ - _Type:Array_ - An array of vertices for the original floorprint
|
237
|
+
# * +desired_area+ - _Type:String_ - Area to which you want to scale the vertices to
|
238
|
+
# * +runner+ - _Type:String_ - An instance of +Openstudio::Measure::OSRunner+ for the measure run.
|
239
|
+
#
|
240
|
+
def self.adjust_vertices_to_area(vertices, desired_area, runner, eps = 0.1)
|
241
|
+
ar = ScaleArea.new(vertices, desired_area, runner, eps)
|
242
|
+
|
243
|
+
n = Newton.nlsolve(ar, [0])
|
244
|
+
|
245
|
+
return ar.new_vertices
|
246
|
+
end
|
247
|
+
|
213
248
|
##
|
214
249
|
# Calculate which other buildings are shading the current feature and return as an array of
|
215
250
|
# +OpenStudio::Model::Space+.
|
@@ -243,6 +278,7 @@ module URBANopt
|
|
243
278
|
if number_of_stories_above_ground.nil?
|
244
279
|
number_of_stories_above_ground = number_of_stories
|
245
280
|
number_of_stories_below_ground = 0
|
281
|
+
|
246
282
|
else
|
247
283
|
number_of_stories_below_ground = number_of_stories - number_of_stories_above_ground
|
248
284
|
end
|
@@ -251,6 +287,13 @@ module URBANopt
|
|
251
287
|
if number_of_stories_above_ground && number_of_stories_above_ground > 0 && maximum_roof_height
|
252
288
|
floor_to_floor_height = maximum_roof_height / number_of_stories_above_ground
|
253
289
|
end
|
290
|
+
|
291
|
+
# check that feature has a # stories
|
292
|
+
if number_of_stories_above_ground.nil?
|
293
|
+
runner.registerWarning("[geojson process_other_buildings] Unable to include feature #{other_building[:properties][:id]} in shading calculations: no 'number of stories' data")
|
294
|
+
end
|
295
|
+
next if number_of_stories_above_ground.nil?
|
296
|
+
|
254
297
|
other_height = number_of_stories_above_ground * floor_to_floor_height
|
255
298
|
# find the polygon of the other_building by passing it to the get_multi_polygons method
|
256
299
|
other_building_points = building.other_points(other_building, other_height, origin_lat_lon, runner, zoning)
|
@@ -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,
|
@@ -65,17 +65,16 @@ module URBANopt
|
|
65
65
|
# * +runner+ - _Type:String_ - Measure run's instance of +OpenStudio::Measure::OSRunner+ .
|
66
66
|
def self.change_adjacent_surfaces_to_adiabatic(model, runner)
|
67
67
|
runner.registerInfo('Changing adjacent surfaces to adiabatic')
|
68
|
-
model.getSurfaces.each do |surface|
|
68
|
+
model.getSurfaces.sort.each do |surface|
|
69
69
|
adjacent_surface = surface.adjacentSurface
|
70
70
|
if !adjacent_surface.empty?
|
71
71
|
surface_construction = surface.construction
|
72
72
|
if !surface_construction.empty?
|
73
73
|
surface.setConstruction(surface_construction.get)
|
74
74
|
end
|
75
|
-
surface.setOutsideBoundaryCondition('Adiabatic')
|
76
|
-
|
77
75
|
adjacent_surface_construction = adjacent_surface.get.construction
|
78
76
|
if !adjacent_surface_construction.empty?
|
77
|
+
surface.setOutsideBoundaryCondition('Adiabatic')
|
79
78
|
adjacent_surface.get.setConstruction(adjacent_surface_construction.get)
|
80
79
|
end
|
81
80
|
adjacent_surface.get.setOutsideBoundaryCondition('Adiabatic')
|
@@ -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,
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt (tm), Copyright (c) 2019-2020, 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 'json'
|
32
|
+
require 'net/http'
|
33
|
+
require 'uri'
|
34
|
+
require 'openssl'
|
35
|
+
require 'bigdecimal/newton'
|
36
|
+
|
37
|
+
module Newton
|
38
|
+
def self.jacobian(f, fx, x)
|
39
|
+
Jacobian.jacobian(f, fx, x)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.ludecomp(a, n, zero = 0, one = 1)
|
43
|
+
LUSolve.ludecomp(a, n, zero, one)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.lusolve(a, b, ps, zero = 0.0)
|
47
|
+
LUSolve.lusolve(a, b, ps, zero)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module URBANopt
|
52
|
+
module GeoJSON
|
53
|
+
class ScaleArea
|
54
|
+
def initialize(vertices, desired_area, runner, eps)
|
55
|
+
@vertices = vertices
|
56
|
+
@centroid = OpenStudio.getCentroid(vertices)
|
57
|
+
raise "Cannot compute centroid for '#{vertices}'" if @centroid.empty?
|
58
|
+
@centroid = @centroid.get
|
59
|
+
@desired_area = desired_area
|
60
|
+
@new_vertices = vertices
|
61
|
+
@runner = runner
|
62
|
+
@zero = BigDecimal('0.0')
|
63
|
+
@one = BigDecimal('1.0')
|
64
|
+
@two = BigDecimal('2.0')
|
65
|
+
@ten = BigDecimal('10.0')
|
66
|
+
@eps = eps
|
67
|
+
end
|
68
|
+
|
69
|
+
attr_reader :zero
|
70
|
+
|
71
|
+
attr_reader :one
|
72
|
+
|
73
|
+
attr_reader :two
|
74
|
+
|
75
|
+
attr_reader :ten
|
76
|
+
|
77
|
+
attr_reader :eps
|
78
|
+
|
79
|
+
##
|
80
|
+
# Used to determine new scaled vertices, by iteratively passing in the perimeter distance to
|
81
|
+
# minimise the difference of the new and scaled area. Returns the difference of the new area and desired area.
|
82
|
+
#
|
83
|
+
def values(x)
|
84
|
+
@new_vertices = URBANopt::GeoJSON::Zoning.divide_floor_print(@vertices, x[0].to_f, @runner, scale = true)
|
85
|
+
new_area = OpenStudio.getArea(@new_vertices)
|
86
|
+
raise "Cannot compute area for '#{@new_vertices}'" if new_area.empty?
|
87
|
+
new_area = new_area.get
|
88
|
+
|
89
|
+
return [new_area - @desired_area]
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :new_vertices
|
93
|
+
end # ScaleArea
|
94
|
+
end # GeoJSON
|
95
|
+
end # URBANopt
|
@@ -87,7 +87,7 @@
|
|
87
87
|
"type": "string"
|
88
88
|
},
|
89
89
|
"floor_area": {
|
90
|
-
"description": "Usable floor area (ft^2).",
|
90
|
+
"description": "Usable floor area (ft^2). Required for residential buildings, this represents conditioned floor area.",
|
91
91
|
"type": "number"
|
92
92
|
},
|
93
93
|
"number_of_stories": {
|
@@ -95,7 +95,7 @@
|
|
95
95
|
"type": "integer"
|
96
96
|
},
|
97
97
|
"number_of_stories_above_ground": {
|
98
|
-
"description": "The number of building stories above ground. Defaults to number_of_stories.",
|
98
|
+
"description": "The number of building stories above ground. Defaults to number_of_stories. Required for residential buildings.",
|
99
99
|
"type": "integer"
|
100
100
|
},
|
101
101
|
"maximum_roof_height": {
|
@@ -111,6 +111,12 @@
|
|
111
111
|
"Hip"
|
112
112
|
]
|
113
113
|
},
|
114
|
+
"foundation_type": {
|
115
|
+
"$ref": "#/definitions/foundationType"
|
116
|
+
},
|
117
|
+
"attic_type": {
|
118
|
+
"$ref": "#/definitions/atticType"
|
119
|
+
},
|
114
120
|
"footprint_area": {
|
115
121
|
"description": "Area of the footprint (ft^2). Calculated on export.",
|
116
122
|
"type": "number"
|
@@ -132,6 +138,9 @@
|
|
132
138
|
"system_type": {
|
133
139
|
"$ref": "#/definitions/systemType"
|
134
140
|
},
|
141
|
+
"heating_system_fuel_type": {
|
142
|
+
"$ref": "#/definitions/heatingSystemFuelType"
|
143
|
+
},
|
135
144
|
"weekday_start_time": {
|
136
145
|
"description": "Weekday operating hours start time in 08:30 format, using 24-hr clock. Leave blank to use default. Should this be part of a mixed type struct?",
|
137
146
|
"type": "string"
|
@@ -185,7 +194,11 @@
|
|
185
194
|
"maximum": 100
|
186
195
|
},
|
187
196
|
"number_of_residential_units": {
|
188
|
-
"description": "Total number of residential units in the building. Required for
|
197
|
+
"description": "Total number of residential units in the building. Required for single-family attached and multifamily residential buildings.",
|
198
|
+
"type": "integer"
|
199
|
+
},
|
200
|
+
"number_of_bedrooms": {
|
201
|
+
"description": "Total number of bedrooms in the building. Required for residential buildings. Must be divisible by the number of residential units.",
|
189
202
|
"type": "integer"
|
190
203
|
},
|
191
204
|
"exterior_lighting_zone": {
|
@@ -214,14 +227,113 @@
|
|
214
227
|
"description": "Arbitrary user data"
|
215
228
|
}
|
216
229
|
},
|
217
|
-
"
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
230
|
+
"oneOf": [
|
231
|
+
{
|
232
|
+
"properties": {
|
233
|
+
"building_type": {
|
234
|
+
"enum": [
|
235
|
+
"Single-Family Detached"
|
236
|
+
]
|
237
|
+
}
|
238
|
+
},
|
239
|
+
"required": [
|
240
|
+
"id",
|
241
|
+
"type",
|
242
|
+
"name",
|
243
|
+
"floor_area",
|
244
|
+
"number_of_stories_above_ground",
|
245
|
+
"number_of_stories",
|
246
|
+
"building_type",
|
247
|
+
"number_of_bedrooms",
|
248
|
+
"foundation_type",
|
249
|
+
"attic_type"
|
250
|
+
]
|
251
|
+
},
|
252
|
+
{
|
253
|
+
"properties": {
|
254
|
+
"building_type": {
|
255
|
+
"enum": [
|
256
|
+
"Single-Family Attached"
|
257
|
+
]
|
258
|
+
}
|
259
|
+
},
|
260
|
+
"required": [
|
261
|
+
"id",
|
262
|
+
"type",
|
263
|
+
"name",
|
264
|
+
"floor_area",
|
265
|
+
"number_of_stories_above_ground",
|
266
|
+
"number_of_stories",
|
267
|
+
"building_type",
|
268
|
+
"number_of_residential_units",
|
269
|
+
"number_of_bedrooms",
|
270
|
+
"foundation_type",
|
271
|
+
"attic_type"
|
272
|
+
]
|
273
|
+
},
|
274
|
+
{
|
275
|
+
"properties": {
|
276
|
+
"building_type": {
|
277
|
+
"enum": [
|
278
|
+
"Multifamily"
|
279
|
+
]
|
280
|
+
}
|
281
|
+
},
|
282
|
+
"required": [
|
283
|
+
"id",
|
284
|
+
"type",
|
285
|
+
"name",
|
286
|
+
"floor_area",
|
287
|
+
"number_of_stories_above_ground",
|
288
|
+
"number_of_stories",
|
289
|
+
"building_type",
|
290
|
+
"number_of_residential_units",
|
291
|
+
"number_of_bedrooms",
|
292
|
+
"foundation_type"
|
293
|
+
]
|
294
|
+
},
|
295
|
+
{
|
296
|
+
"properties": {
|
297
|
+
"building_type": {
|
298
|
+
"enum": [
|
299
|
+
"Single-Family",
|
300
|
+
"Multifamily (2 to 4 units)",
|
301
|
+
"Multifamily (5 or more units)",
|
302
|
+
"Vacant",
|
303
|
+
"Office",
|
304
|
+
"Laboratory",
|
305
|
+
"Nonrefrigerated warehouse",
|
306
|
+
"Food sales",
|
307
|
+
"Public order and safety",
|
308
|
+
"Outpatient health care",
|
309
|
+
"Refrigerated warehouse",
|
310
|
+
"Religious worship",
|
311
|
+
"Public assembly",
|
312
|
+
"Education",
|
313
|
+
"Food service",
|
314
|
+
"Inpatient health care",
|
315
|
+
"Nursing",
|
316
|
+
"Lodging",
|
317
|
+
"Strip shopping mall",
|
318
|
+
"Enclosed mall",
|
319
|
+
"Retail other than mall",
|
320
|
+
"Service",
|
321
|
+
"Mixed use",
|
322
|
+
"Uncovered Parking",
|
323
|
+
"Covered Parking"
|
324
|
+
]
|
325
|
+
}
|
326
|
+
},
|
327
|
+
"required": [
|
328
|
+
"id",
|
329
|
+
"type",
|
330
|
+
"name",
|
331
|
+
"floor_area",
|
332
|
+
"number_of_stories",
|
333
|
+
"footprint_area",
|
334
|
+
"building_type"
|
335
|
+
]
|
336
|
+
}
|
225
337
|
],
|
226
338
|
"additionalProperties": true,
|
227
339
|
"definitions": {
|
@@ -229,10 +341,12 @@
|
|
229
341
|
"description": "Primary building space type.",
|
230
342
|
"type": "string",
|
231
343
|
"enum": [
|
344
|
+
"Single-Family Detached",
|
345
|
+
"Single-Family Attached",
|
346
|
+
"Multifamily",
|
232
347
|
"Single-Family",
|
233
348
|
"Multifamily (2 to 4 units)",
|
234
349
|
"Multifamily (5 or more units)",
|
235
|
-
"Mobile Home",
|
236
350
|
"Vacant",
|
237
351
|
"Office",
|
238
352
|
"Laboratory",
|
@@ -262,89 +376,116 @@
|
|
262
376
|
"description": "Building HVAC system type. Should this be part of a mixed type struct?",
|
263
377
|
"type": "string",
|
264
378
|
"enum": [
|
265
|
-
"
|
266
|
-
"PTAC with
|
267
|
-
"PTAC with hot water
|
268
|
-
"PTAC with gas
|
379
|
+
"PTAC with baseboard electric",
|
380
|
+
"PTAC with baseboard gas boiler",
|
381
|
+
"PTAC with baseboard district hot water",
|
382
|
+
"PTAC with gas unit heaters",
|
383
|
+
"PTAC with electric coil",
|
384
|
+
"PTAC with gas coil",
|
269
385
|
"PTAC with gas boiler",
|
270
|
-
"PTAC with electric baseboard heat",
|
271
386
|
"PTAC with no heat",
|
272
|
-
"PTAC with district hot water
|
273
|
-
"PTAC with central air source heat pump
|
387
|
+
"PTAC with district hot water",
|
388
|
+
"PTAC with central air source heat pump",
|
274
389
|
"PTHP",
|
275
|
-
"PSZ-AC with gas coil
|
276
|
-
"PSZ-AC with
|
390
|
+
"PSZ-AC with gas coil",
|
391
|
+
"PSZ-AC with baseboard electric",
|
277
392
|
"PSZ-AC with no heat",
|
278
|
-
"PSZ-AC with district hot water
|
279
|
-
"PSZ-AC with central air source heat pump
|
393
|
+
"PSZ-AC with district hot water",
|
394
|
+
"PSZ-AC with central air source heat pump",
|
280
395
|
"PSZ-HP",
|
281
396
|
"Fan coil district chilled water with no heat",
|
282
|
-
"Fan coil district chilled water
|
283
|
-
"Fan coil district chilled water
|
284
|
-
"Fan coil district chilled water unit heaters",
|
285
|
-
"Fan coil district chilled water
|
286
|
-
"Fan coil district
|
287
|
-
"Fan coil district hot water
|
288
|
-
"Fan coil district hot water
|
289
|
-
"Fan coil chiller
|
290
|
-
"Fan coil air-cooled chiller
|
291
|
-
"Fan coil chiller
|
292
|
-
"Fan coil air-cooled chiller
|
397
|
+
"Fan coil district chilled water with boiler",
|
398
|
+
"Fan coil district chilled water with central air source heat pump",
|
399
|
+
"Fan coil district chilled water with gas unit heaters",
|
400
|
+
"Fan coil district chilled water with baseboard electric",
|
401
|
+
"Fan coil district chilled water with district hot water",
|
402
|
+
"Fan coil chiller with district hot water",
|
403
|
+
"Fan coil air-cooled chiller with district hot water",
|
404
|
+
"Fan coil chiller with boiler",
|
405
|
+
"Fan coil air-cooled chiller with boiler",
|
406
|
+
"Fan coil chiller with central air source heat pump",
|
407
|
+
"Fan coil air-cooled chiller with central air source heat pump",
|
293
408
|
"Fan coil chiller with no heat",
|
294
409
|
"DOAS with fan coil district chilled water with no heat",
|
295
410
|
"DOAS with fan coil district chilled water and boiler",
|
296
|
-
"DOAS with fan coil district chilled water
|
297
|
-
"DOAS with fan coil district chilled water unit heaters",
|
298
|
-
"DOAS with fan coil district chilled water
|
299
|
-
"DOAS with fan coil district
|
300
|
-
"DOAS with fan coil district hot water
|
301
|
-
"DOAS with fan coil district hot water
|
302
|
-
"DOAS with fan coil chiller
|
303
|
-
"DOAS with fan coil air
|
304
|
-
"DOAS with fan coil chiller
|
305
|
-
"DOAS with fan coil air-cooled chiller and central air source heat pump",
|
411
|
+
"DOAS with fan coil district chilled water with central air source heat pump",
|
412
|
+
"DOAS with fan coil district chilled water with gas unit heaters",
|
413
|
+
"DOAS with fan coil district chilled water with baseboard electric",
|
414
|
+
"DOAS with fan coil district chilled water with district hot water",
|
415
|
+
"DOAS with fan coil chiller with district hot water",
|
416
|
+
"DOAS with fan coil air-cooled chiller with district hot water",
|
417
|
+
"DOAS with fan coil air-cooled chiller with boiler",
|
418
|
+
"DOAS with fan coil chiller with central air source heat pump",
|
419
|
+
"DOAS with fan coil air-cooled chiller with central air source heat pump",
|
306
420
|
"DOAS with fan coil chiller with no heat",
|
307
|
-
"
|
421
|
+
"DOAS with VRF",
|
308
422
|
"VRF",
|
309
|
-
"
|
310
|
-
"
|
311
|
-
"Baseboard district hot water
|
312
|
-
"Baseboard electric
|
313
|
-
"Baseboard
|
314
|
-
"Baseboard
|
315
|
-
"Baseboard hot water heat with direct evap coolers",
|
423
|
+
"DOAS with water source heat pumps with ground source heat pump",
|
424
|
+
"Forced air furnace",
|
425
|
+
"Baseboard district hot water",
|
426
|
+
"Baseboard electric",
|
427
|
+
"Baseboard gas boiler",
|
428
|
+
"Baseboard central air source heat pump",
|
316
429
|
"Window AC with no heat",
|
317
430
|
"Window AC with forced air furnace",
|
318
|
-
"Window AC with district hot water
|
319
|
-
"Window AC with
|
320
|
-
"Window AC with electric baseboard heat",
|
431
|
+
"Window AC with baseboard district hot water",
|
432
|
+
"Window AC with baseboard electric",
|
321
433
|
"Window AC with unit heaters",
|
322
|
-
"
|
323
|
-
"
|
324
|
-
"
|
325
|
-
"
|
326
|
-
"
|
327
|
-
"
|
328
|
-
"
|
329
|
-
"
|
330
|
-
"
|
331
|
-
"
|
332
|
-
"VAV with
|
333
|
-
"VAV
|
434
|
+
"Window AC with baseboard gas boiler",
|
435
|
+
"Window AC with baseboard central air source heat pump",
|
436
|
+
"Direct evap coolers with baseboard district hot water",
|
437
|
+
"Direct evap coolers with baseboard electric",
|
438
|
+
"Direct evap coolers with baseboard gas boiler",
|
439
|
+
"Direct evap coolers with baseboard central air source heat pump",
|
440
|
+
"Direct evap coolers with no heat",
|
441
|
+
"Direct evap coolers with gas unit heaters",
|
442
|
+
"Direct evap coolers with forced air furnace",
|
443
|
+
"Gas unit heaters",
|
444
|
+
"VAV chiller with gas boiler reheat",
|
445
|
+
"VAV chiller with gas coil reheat",
|
446
|
+
"VAV chiller with central air source heat pump reheat",
|
447
|
+
"VAV chiller with PFP boxes",
|
448
|
+
"VAV air-cooled chiller with gas boiler reheat",
|
449
|
+
"VAV air-cooled chiller with central air source heat pump reheat",
|
450
|
+
"VAV air-cooled chiller with district hot water reheat",
|
451
|
+
"VAV air-cooled chiller with gas coil reheat",
|
452
|
+
"VAV air-cooled chiller with no reheat with gas unit heaters",
|
453
|
+
"VAV district chilled water with gas boiler reheat",
|
454
|
+
"VAV district chilled water with central air source heat pump reheat",
|
455
|
+
"VAV district chilled water with no reheat with zone heat pump",
|
456
|
+
"VAV chiller with no reheat with baseboard electric",
|
457
|
+
"VAV air-cooled chiller with no reheat with zone heat pump",
|
334
458
|
"VAV district chilled water with district hot water reheat",
|
335
459
|
"VAV district chilled water with gas coil reheat",
|
336
|
-
"PVAV with reheat",
|
337
|
-
"PVAV with
|
460
|
+
"PVAV with gas heat with electric reheat",
|
461
|
+
"PVAV with central air source heat pump reheat",
|
338
462
|
"PVAV with PFP boxes",
|
339
|
-
"Residential
|
340
|
-
"Residential
|
341
|
-
"Residential
|
342
|
-
"Residential
|
343
|
-
"
|
344
|
-
"
|
345
|
-
"
|
346
|
-
"Residential
|
347
|
-
"Residential
|
463
|
+
"Residential - electric resistance and no cooling",
|
464
|
+
"Residential - electric resistance and central air conditioner",
|
465
|
+
"Residential - electric resistance and room air conditioner",
|
466
|
+
"Residential - electric resistance and evaporative cooler",
|
467
|
+
"Residential - furnace and no cooling",
|
468
|
+
"Residential - furnace and central air conditioner",
|
469
|
+
"Residential - furnace and room air conditioner",
|
470
|
+
"Residential - furnace and evaporative cooler",
|
471
|
+
"Residential - boiler and no cooling",
|
472
|
+
"Residential - boiler and central air conditioner",
|
473
|
+
"Residential - boiler and room air conditioner",
|
474
|
+
"Residential - boiler and evaporative cooler",
|
475
|
+
"Residential - air-to-air heat pump",
|
476
|
+
"Residential - mini-split heat pump",
|
477
|
+
"Residential - ground-to-air heat pump"
|
478
|
+
]
|
479
|
+
},
|
480
|
+
"heatingSystemFuelType": {
|
481
|
+
"description": "The fuel type of the heating system. This does not apply for certain system types (e.g., electric resistance or heat pumps).",
|
482
|
+
"type": "string",
|
483
|
+
"enum": [
|
484
|
+
"electricity",
|
485
|
+
"natural gas",
|
486
|
+
"fuel oil",
|
487
|
+
"propane",
|
488
|
+
"wood"
|
348
489
|
]
|
349
490
|
},
|
350
491
|
"templateType": {
|
@@ -378,8 +519,35 @@
|
|
378
519
|
"DEER 2060",
|
379
520
|
"DEER 2065",
|
380
521
|
"DEER 2070",
|
381
|
-
"DEER 2075"
|
522
|
+
"DEER 2075",
|
523
|
+
"Residential IECC 2006 - Customizable Template Sep 2020",
|
524
|
+
"Residential IECC 2009 - Customizable Template Sep 2020",
|
525
|
+
"Residential IECC 2012 - Customizable Template Sep 2020",
|
526
|
+
"Residential IECC 2015 - Customizable Template Sep 2020",
|
527
|
+
"Residential IECC 2018 - Customizable Template Sep 2020"
|
528
|
+
]
|
529
|
+
},
|
530
|
+
"foundationType": {
|
531
|
+
"description": "The foundation type of the building. Required for residential buildings.",
|
532
|
+
"type": "string",
|
533
|
+
"enum": [
|
534
|
+
"slab",
|
535
|
+
"crawlspace - vented",
|
536
|
+
"crawlspace - unvented",
|
537
|
+
"basement - unconditioned",
|
538
|
+
"basement - conditioned",
|
539
|
+
"ambient"
|
540
|
+
]
|
541
|
+
},
|
542
|
+
"atticType": {
|
543
|
+
"description": "The attic type of the building. Required for single-family residential buildings.",
|
544
|
+
"type": "string",
|
545
|
+
"enum": [
|
546
|
+
"attic - vented",
|
547
|
+
"attic - unvented",
|
548
|
+
"attic - conditioned",
|
549
|
+
"flat roof"
|
382
550
|
]
|
383
551
|
}
|
384
552
|
}
|
385
|
-
}
|
553
|
+
}
|