urbanopt-geojson 0.3.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/pull_request_template.md +2 -2
- data/CHANGELOG.md +54 -4
- 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 +5205 -6885
- data/docs/package.json +13 -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 +1 -1
- 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 +57 -7
- 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/zoning.rb +21 -16
- data/urbanopt-geojson-gem.gemspec +4 -8
- metadata +12 -23
@@ -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,
|
@@ -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": {
|
@@ -194,7 +194,7 @@
|
|
194
194
|
"maximum": 100
|
195
195
|
},
|
196
196
|
"number_of_residential_units": {
|
197
|
-
"description": "Total number of residential units in the building. Required for single-family attached
|
197
|
+
"description": "Total number of residential units in the building. Required for single-family attached and multifamily residential buildings.",
|
198
198
|
"type": "integer"
|
199
199
|
},
|
200
200
|
"number_of_bedrooms": {
|
@@ -225,6 +225,45 @@
|
|
225
225
|
},
|
226
226
|
"user_data": {
|
227
227
|
"description": "Arbitrary user data"
|
228
|
+
},
|
229
|
+
"ev_charging": {
|
230
|
+
"description": "Should be set to true if EV charging is associated with the building.",
|
231
|
+
"type": "boolean"
|
232
|
+
},
|
233
|
+
"ev_charging_station_type": {
|
234
|
+
"description": "Indicates whether EV charging associated with the building is for Typical Home, Public or Work charging station",
|
235
|
+
"type": "string",
|
236
|
+
"enum": [
|
237
|
+
"Typical Home",
|
238
|
+
"Typical Public",
|
239
|
+
"Typical Work"
|
240
|
+
]
|
241
|
+
},
|
242
|
+
"delay_type": {
|
243
|
+
"description": "Adds workplace charging flexibility for different scenarios. Min delay scenario indicates EV charging immediately upon arriving to work, Max delay indicates not charging until necessary thereby shifting EV charging load to later in the day and Min power indicates charging EVs at a minimum rate over the parking event.",
|
244
|
+
"type": "string",
|
245
|
+
"enum": [
|
246
|
+
"Min Delay",
|
247
|
+
"Max Delay",
|
248
|
+
"Min Power"
|
249
|
+
]
|
250
|
+
},
|
251
|
+
"ev_charging_behavior": {
|
252
|
+
"description": "Describes scenarios for EV charging behavior, Business as Usual implies home dominant charging behavior, Free Workplace Charging at Project Site implies peak power draw from EV charging during morning hours due to EV charging at workplaces and Free Workplace Charging Across Metro Area scenario reduces Home EV charging relative to Free Workplace Charging at Project Site for residents who work elsewhere and can charge their vehicles for free at those workplaces.",
|
253
|
+
"type": "string",
|
254
|
+
"enum": [
|
255
|
+
"Business as Usual",
|
256
|
+
"Free Workplace Charging at Project Site",
|
257
|
+
"Free Workplace Charging Across Metro Area"
|
258
|
+
]
|
259
|
+
},
|
260
|
+
"ev_percent": {
|
261
|
+
"description": "Denotes the % of vehicles parked at the building that are EVs.",
|
262
|
+
"type": "number"
|
263
|
+
},
|
264
|
+
"ev_curtailment_frac": {
|
265
|
+
"description": "Fraction between 0 and 1 that denotes curtailment of EV charging load to better align EV charging with expected energy production from a solar PV system",
|
266
|
+
"type": "number"
|
228
267
|
}
|
229
268
|
},
|
230
269
|
"oneOf": [
|
@@ -241,8 +280,8 @@
|
|
241
280
|
"type",
|
242
281
|
"name",
|
243
282
|
"floor_area",
|
283
|
+
"number_of_stories_above_ground",
|
244
284
|
"number_of_stories",
|
245
|
-
"footprint_area",
|
246
285
|
"building_type",
|
247
286
|
"number_of_bedrooms",
|
248
287
|
"foundation_type",
|
@@ -262,8 +301,8 @@
|
|
262
301
|
"type",
|
263
302
|
"name",
|
264
303
|
"floor_area",
|
304
|
+
"number_of_stories_above_ground",
|
265
305
|
"number_of_stories",
|
266
|
-
"footprint_area",
|
267
306
|
"building_type",
|
268
307
|
"number_of_residential_units",
|
269
308
|
"number_of_bedrooms",
|
@@ -284,8 +323,8 @@
|
|
284
323
|
"type",
|
285
324
|
"name",
|
286
325
|
"floor_area",
|
326
|
+
"number_of_stories_above_ground",
|
287
327
|
"number_of_stories",
|
288
|
-
"footprint_area",
|
289
328
|
"building_type",
|
290
329
|
"number_of_residential_units",
|
291
330
|
"number_of_bedrooms",
|
@@ -296,6 +335,9 @@
|
|
296
335
|
"properties": {
|
297
336
|
"building_type": {
|
298
337
|
"enum": [
|
338
|
+
"Single-Family",
|
339
|
+
"Multifamily (2 to 4 units)",
|
340
|
+
"Multifamily (5 or more units)",
|
299
341
|
"Vacant",
|
300
342
|
"Office",
|
301
343
|
"Laboratory",
|
@@ -341,6 +383,9 @@
|
|
341
383
|
"Single-Family Detached",
|
342
384
|
"Single-Family Attached",
|
343
385
|
"Multifamily",
|
386
|
+
"Single-Family",
|
387
|
+
"Multifamily (2 to 4 units)",
|
388
|
+
"Multifamily (5 or more units)",
|
344
389
|
"Vacant",
|
345
390
|
"Office",
|
346
391
|
"Laboratory",
|
@@ -513,7 +558,12 @@
|
|
513
558
|
"DEER 2060",
|
514
559
|
"DEER 2065",
|
515
560
|
"DEER 2070",
|
516
|
-
"DEER 2075"
|
561
|
+
"DEER 2075",
|
562
|
+
"Residential IECC 2006 - Customizable Template Sep 2020",
|
563
|
+
"Residential IECC 2009 - Customizable Template Sep 2020",
|
564
|
+
"Residential IECC 2012 - Customizable Template Sep 2020",
|
565
|
+
"Residential IECC 2015 - Customizable Template Sep 2020",
|
566
|
+
"Residential IECC 2018 - Customizable Template Sep 2020"
|
517
567
|
]
|
518
568
|
},
|
519
569
|
"foundationType": {
|