urbanopt-geojson 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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,