urbanopt-geojson 0.3.1 → 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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/LICENSE.md +1 -1
  5. data/RDOC_MAIN.md +1 -1
  6. data/README.md +1 -1
  7. data/Rakefile +1 -1
  8. data/doc_templates/LICENSE.md +1 -1
  9. data/doc_templates/copyright_erb.txt +1 -1
  10. data/doc_templates/copyright_js.txt +1 -1
  11. data/doc_templates/copyright_ruby.txt +1 -1
  12. data/docs/README.md +1 -1
  13. data/docs/package-lock.json +5232 -6909
  14. data/docs/package.json +9 -8
  15. data/lib/measures/urban_geometry_creation/LICENSE.md +1 -1
  16. data/lib/measures/urban_geometry_creation/README.md +1 -1
  17. data/lib/measures/urban_geometry_creation/measure.rb +19 -4
  18. data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +1 -1
  19. data/lib/measures/urban_geometry_creation_zoning/README.md +1 -1
  20. data/lib/measures/urban_geometry_creation_zoning/measure.rb +1 -3
  21. data/lib/urbanopt-geojson.rb +1 -1
  22. data/lib/urbanopt/geojson.rb +2 -1
  23. data/lib/urbanopt/geojson/building.rb +53 -8
  24. data/lib/urbanopt/geojson/derived_extension.rb +1 -1
  25. data/lib/urbanopt/geojson/district_system.rb +1 -1
  26. data/lib/urbanopt/geojson/feature.rb +80 -2
  27. data/lib/urbanopt/geojson/geo_file.rb +2 -2
  28. data/lib/urbanopt/geojson/helper.rb +30 -2
  29. data/lib/urbanopt/geojson/logging.rb +1 -1
  30. data/lib/urbanopt/geojson/mapper_classes.rb +1 -1
  31. data/lib/urbanopt/geojson/model.rb +1 -1
  32. data/lib/urbanopt/geojson/region.rb +1 -1
  33. data/lib/urbanopt/geojson/scale_area.rb +91 -0
  34. data/lib/urbanopt/geojson/schema/building_properties.json +12 -7
  35. data/lib/urbanopt/geojson/schema/electrical_connector_properties.json +1 -1
  36. data/lib/urbanopt/geojson/update_areas.rb +1 -1
  37. data/lib/urbanopt/geojson/validate_geojson.rb +1 -1
  38. data/lib/urbanopt/geojson/version.rb +2 -2
  39. data/lib/urbanopt/geojson/zoning.rb +21 -16
  40. data/urbanopt-geojson-gem.gemspec +5 -8
  41. metadata +15 -14
@@ -10,22 +10,23 @@
10
10
  },
11
11
  "author": "Brian Schiller",
12
12
  "dependencies": {
13
- "highlight.js": "^9.15.6",
14
- "json-schema-ref-parser": "^6.1.0",
13
+ "highlight.js": "^10.2.0",
14
+ "json-schema-ref-parser": "^9.0.6",
15
15
  "json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
16
- "vuepress": "^0.14.10",
16
+ "vuepress": "^1.5.4",
17
17
  "webpack-dev-middleware": "^3.6.0"
18
18
  },
19
19
  "devDependencies": {
20
- "braces": ">=2.3.1",
20
+ "braces": "^3.0.2",
21
21
  "dot-prop": ">=5.1.1",
22
- "gh-pages": "^2.0.1",
22
+ "gh-pages": "^3.1.0",
23
23
  "js-yaml": ">=3.13.1",
24
24
  "lodash": ">=4.17.19",
25
25
  "lodash.template": ">=4.5.0",
26
26
  "minimist": ">=1.2.3",
27
- "mixin-deep": ">=1.3.2",
28
- "serialize-javascript": ">=2.1.1",
29
- "set-value": ">=2.0.1"
27
+ "mixin-deep": "^2.0.1",
28
+ "serialize-javascript": "^5.0.1",
29
+ "set-value": "^3.0.2",
30
+ "yargs-parser": ">=18.1.1"
30
31
  }
31
32
  }
@@ -1,4 +1,4 @@
1
- URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
1
+ URBANopt™, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
2
  contributors. All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
@@ -5,7 +5,7 @@
5
5
  # UrbanGeometryCreation
6
6
 
7
7
  ## Description
8
- This measure reads an URBANopt GeoJSON and creates geometry for a particular building. Surrounding buildings are included as shading structures.
8
+ This measure reads an URBANopt GeoJSON and creates geometry for a particular building. Surrounding buildings are included as shading structures.
9
9
 
10
10
  ## Modeler Description
11
11
  This measure takes in the GeoJSON file, the feature_id of the building and the surrounding buildings as arguments and add has methods to create space types and add default construction sets.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # *********************************************************************************
4
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
4
+ # URBANopt™, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
5
5
  # contributors. All rights reserved.
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without modification,
@@ -75,13 +75,17 @@ class UrbanGeometryCreation < OpenStudio::Measure::ModelMeasure
75
75
  surrounding_buildings.setDescription('Select which surrounding buildings to include.')
76
76
  surrounding_buildings.setDefaultValue('ShadingOnly')
77
77
  args << surrounding_buildings
78
+ # not a required argument
79
+ scale_footprint_area_by_floor_area = OpenStudio::Ruleset::OSArgument.makeBoolArgument('scale_footprint_area_by_floor_area', false)
80
+ scale_footprint_area_by_floor_area.setDisplayName('Scale Footprint Area by the Floor Area?')
81
+ scale_footprint_area_by_floor_area.setDescription('If true, the footprint area from GeoJSON will be scaled by the floor_area provided by the user in URBANopt.')
82
+ scale_footprint_area_by_floor_area.setDefaultValue(false)
83
+ args << scale_footprint_area_by_floor_area
78
84
  return args
79
85
  end
80
86
 
81
87
  # define what happens when the measure is run
82
- # rubocop:disable Metrics/AbcSize
83
88
  def run(model, runner, user_arguments)
84
- # rubocop:enable Metrics/AbcSize
85
89
  super(model, runner, user_arguments)
86
90
  # use the built-in error checking
87
91
  if !runner.validateUserArguments(arguments(model), user_arguments)
@@ -92,6 +96,7 @@ class UrbanGeometryCreation < OpenStudio::Measure::ModelMeasure
92
96
  geojson_file = runner.getStringArgumentValue('geojson_file', user_arguments)
93
97
  feature_id = runner.getStringArgumentValue('feature_id', user_arguments)
94
98
  surrounding_buildings = runner.getStringArgumentValue('surrounding_buildings', user_arguments)
99
+ scale_footprint_area_by_floor_area = runner.getBoolArgumentValue('scale_footprint_area_by_floor_area', user_arguments)
95
100
 
96
101
  default_construction_set = URBANopt::GeoJSON::Model.create_construction_set(model, runner)
97
102
 
@@ -135,7 +140,17 @@ class UrbanGeometryCreation < OpenStudio::Measure::ModelMeasure
135
140
 
136
141
  if feature.type == 'Building'
137
142
  # make requested building
138
- spaces = feature.create_building(:space_per_floor, model, @origin_lat_lon, @runner)
143
+ # pass in scaled_footprint_area (calculated from floor_area / number_of_stories)
144
+ scaled_footprint_area = 0
145
+ if scale_footprint_area_by_floor_area
146
+ building_hash = feature.to_hash
147
+ if building_hash[:number_of_stories] && building_hash[:floor_area]
148
+ scaled_footprint_area = building_hash[:floor_area].to_f / building_hash[:number_of_stories].to_f
149
+ @runner.registerInfo("Desired footprint area in ft2: #{scaled_footprint_area}")
150
+ end
151
+ end
152
+
153
+ spaces = feature.create_building(:space_per_floor, model, @origin_lat_lon, @runner, false, scaled_footprint_area)
139
154
  if spaces.nil?
140
155
  @runner.registerError("Failed to create spaces for building '#{name}'")
141
156
  return false
@@ -1,4 +1,4 @@
1
- URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
1
+ URBANopt™, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
2
  contributors. All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without modification,
@@ -5,7 +5,7 @@
5
5
  # UrbanGeometryCreationZoning
6
6
 
7
7
  ## Description
8
- This measure reads an URBANopt GeoJSON and creates geometry with zoning for a particular building. Surrounding buildings are included as shading structures.
8
+ This measure reads an URBANopt GeoJSON and creates geometry with zoning for a particular building. Surrounding buildings are included as shading structures.
9
9
 
10
10
  ## Modeler Description
11
11
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # *********************************************************************************
4
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
4
+ # URBANopt™, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
5
5
  # contributors. All rights reserved.
6
6
  #
7
7
  # Redistribution and use in source and binary forms, with or without modification,
@@ -83,9 +83,7 @@ class UrbanGeometryCreationZoning < OpenStudio::Measure::ModelMeasure
83
83
  end
84
84
 
85
85
  # define what happens when the measure is run
86
- # rubocop:disable Metrics/AbcSize
87
86
  def run(model, runner, user_arguments)
88
- # rubocop:enable Metrics/AbcSize
89
87
  super(model, runner, user_arguments)
90
88
  # use the built-in error checking
91
89
  if !runner.validateUserArguments(arguments(model), user_arguments)
@@ -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,
@@ -39,3 +39,4 @@ require 'urbanopt/geojson/zoning'
39
39
  require 'urbanopt/geojson/model'
40
40
  require 'urbanopt/geojson/derived_extension'
41
41
  require 'urbanopt/geojson/logging'
42
+ require 'urbanopt/geojson/scale_area'
@@ -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,
@@ -87,9 +87,11 @@ module URBANopt
87
87
  # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the latitude and longitude of the origin.
88
88
  # * +runner+ - _Type:String_ - An instance of +OpenStudio::Measure::OSRunner+ for the measure run.
89
89
  # * +zoning+ - _Type:Boolean_ - Value is +true+ if utilizing detailed zoning, else
90
- # +false+. Zoning is set to False by default.
90
+ # +false+ Zoning is set to False by default.
91
+ # * +scaled_footprint_area+ - Used to scale the footprint area using the floor area. 0 by
92
+ # default (no scaling).
91
93
  # * +other_building+ - _Type:URBANopt::GeoJSON::Feature - Optional, allow the user to pass in a different building to process. This is used for creating the other buildings for shading.
92
- def create_building(create_method, model, origin_lat_lon, runner, zoning = false, other_building = @feature_json)
94
+ def create_building(create_method, model, origin_lat_lon, runner, zoning = false, scaled_footprint_area = 0, other_building = @feature_json)
93
95
  number_of_stories = other_building[:properties][:number_of_stories]
94
96
  number_of_stories_above_ground = other_building[:properties][:number_of_stories_above_ground]
95
97
  number_of_stories_below_ground = other_building[:properties][:number_of_stories_below_ground]
@@ -128,7 +130,7 @@ module URBANopt
128
130
  spaces = []
129
131
  if create_method == :space_per_floor || create_method == :spaces_per_floor
130
132
  (-number_of_stories_below_ground + 1..number_of_stories_above_ground).each do |story_number|
131
- new_spaces = create_space_per_floor(story_number, floor_to_floor_height, model, origin_lat_lon, runner, zoning)
133
+ new_spaces = create_space_per_floor(story_number, floor_to_floor_height, model, origin_lat_lon, runner, zoning, scaled_footprint_area)
132
134
  spaces.concat(new_spaces)
133
135
  end
134
136
  elsif create_method == :space_per_building
@@ -247,6 +249,41 @@ module URBANopt
247
249
  end
248
250
  end
249
251
 
252
+ def calculate_perimeter(feature)
253
+ model = OpenStudio::Model::Model.new
254
+ runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new)
255
+ origin_lat_lon = nil
256
+ origin_lat_lon = feature.create_origin_lat_lon(runner)
257
+ spaces = feature.create_building(:space_per_building, model, origin_lat_lon, runner)
258
+ surfaces = spaces[0].surfaces
259
+ ground_surface = nil
260
+ surfaces.each do |surface|
261
+ boundary_condition = surface.outsideBoundaryCondition
262
+ if boundary_condition == 'Ground'
263
+ ground_surface = surface
264
+ end
265
+ end
266
+ vertices = ground_surface.vertices
267
+ n = vertices.size
268
+ perimeter = 0
269
+ for i in (0..n - 1) do i
270
+ vertex_1 = nil
271
+ vertex_2 = nil
272
+ if i == n - 1
273
+ vertex_1 = vertices[n - 1]
274
+ vertex_2 = vertices[0]
275
+ else
276
+ vertex_1 = vertices[i]
277
+ vertex_2 = vertices[i + 1]
278
+ end
279
+ length = OpenStudio::Vector3d.new(vertex_2 - vertex_1).length
280
+ perimeter += length
281
+ end
282
+ perimeter = OpenStudio.convert(perimeter, 'm', 'ft').get
283
+ perimeter = perimeter.round(4)
284
+ return perimeter
285
+ end
286
+
250
287
  ##
251
288
  # Convert to a Hash equivalent for JSON serialization
252
289
  ##
@@ -354,10 +391,18 @@ module URBANopt
354
391
  # * +zoning+ - _Type:Boolean_ - Value is +true+ if utilizing detailed zoning, else
355
392
  # +false+. Zoning is set to False by default.
356
393
  # rubocop:disable Style/CommentedKeyword
357
- def create_space_per_floor(story_number, floor_to_floor_height, model, origin_lat_lon, runner, zoning = false) #:doc:
394
+ def create_space_per_floor(story_number, floor_to_floor_height, model, origin_lat_lon, runner, zoning = false, scaled_footprint_area) #:doc:
358
395
  # rubocop:enable Style/CommentedKeyword
359
- geometry = @feature_json[:geometry]
360
- properties = @feature_json[:properties]
396
+ begin
397
+ if other_building
398
+ geometry = other_building[:geometry]
399
+ properties = other_building[:properties]
400
+ else
401
+ geometry = @feature_json[:geometry]
402
+ properties = @feature_json[:properties]
403
+ end
404
+ rescue StandardError
405
+ end
361
406
  floor_prints = []
362
407
  multi_polygons = get_multi_polygons
363
408
  multi_polygons.each do |multi_polygon|
@@ -366,7 +411,7 @@ module URBANopt
366
411
  end
367
412
  multi_polygon.each do |polygon|
368
413
  elevation = (story_number - 1) * floor_to_floor_height
369
- floor_print = URBANopt::GeoJSON::Helper.floor_print_from_polygon(polygon, elevation, origin_lat_lon, runner, zoning)
414
+ floor_print = URBANopt::GeoJSON::Helper.floor_print_from_polygon(polygon, elevation, origin_lat_lon, runner, zoning, scaled_footprint_area)
370
415
  if floor_print
371
416
  if zoning
372
417
  this_floor_prints = URBANopt::GeoJSON::Zoning.divide_floor_print(floor_print, 4.0, runner)
@@ -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,
@@ -48,7 +48,7 @@ module URBANopt
48
48
  def method_missing(name, *args, &blk)
49
49
  # rubocop:enable Style/MethodMissing
50
50
  if @feature_json[:properties].keys.map(&:to_sym).include? name.to_sym
51
- # rubocop:enable Style/GuardClause
51
+
52
52
  return @feature_json[:properties][name.to_sym]
53
53
  else
54
54
  super
@@ -98,6 +98,84 @@ module URBANopt
98
98
  return @@feature_schema[feature_type]
99
99
  end
100
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
+
101
179
  ##
102
180
  # Returns coordinate with the minimum longitute and latitude within a given +building_json+ .
103
181
  def get_min_lon_lat
@@ -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,
@@ -162,7 +162,7 @@ module URBANopt
162
162
  # merge site origin properties
163
163
  f = merge_site_properties(f)
164
164
  if f[:properties][:type] == 'Building'
165
- # rubocop:enable Style/GuardClause
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)
@@ -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,
@@ -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
- def self.floor_print_from_polygon(polygon, elevation, origin_lat_lon, runner, zoning = false)
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,35 @@ 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+.
@@ -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,