urbanopt-geojson 0.1.0 → 0.2.0.pre1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +19 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
  4. data/.github/pull_request_template.md +13 -0
  5. data/CONTRIBUTING.md +58 -0
  6. data/Gemfile +3 -3
  7. data/Jenkinsfile +2 -2
  8. data/LICENSE.md +1 -1
  9. data/Rakefile +1 -1
  10. data/doc_templates/LICENSE.md +1 -1
  11. data/doc_templates/copyright_erb.txt +1 -1
  12. data/doc_templates/copyright_js.txt +1 -1
  13. data/doc_templates/copyright_ruby.txt +1 -1
  14. data/docs/package-lock.json +2291 -2205
  15. data/docs/package.json +8 -1
  16. data/lib/change_log.rb +147 -0
  17. data/lib/measures/urban_geometry_creation/LICENSE.md +1 -1
  18. data/lib/measures/urban_geometry_creation/measure.rb +1 -3
  19. data/lib/measures/urban_geometry_creation/tests/shadowed_tests.rb +1 -1
  20. data/lib/measures/urban_geometry_creation/tests/urban_geometry_creation_test.rb +3 -7
  21. data/lib/measures/urban_geometry_creation_zoning/LICENSE.md +1 -1
  22. data/lib/measures/urban_geometry_creation_zoning/measure.rb +5 -6
  23. data/lib/measures/urban_geometry_creation_zoning/tests/{urban_geometry_creation_test.rb → urban_geometry_creation_zoning_test.rb} +3 -7
  24. data/lib/urbanopt-geojson.rb +31 -0
  25. data/lib/urbanopt/geojson.rb +1 -1
  26. data/lib/urbanopt/geojson/building.rb +90 -18
  27. data/lib/urbanopt/geojson/district_system.rb +1 -1
  28. data/lib/urbanopt/geojson/extension.rb +1 -1
  29. data/lib/urbanopt/geojson/feature.rb +9 -7
  30. data/lib/urbanopt/geojson/files/electrical_database.json +28 -0
  31. data/lib/urbanopt/geojson/geo_file.rb +213 -31
  32. data/lib/urbanopt/geojson/helper.rb +10 -8
  33. data/lib/urbanopt/geojson/logging.rb +1 -1
  34. data/lib/urbanopt/geojson/mapper_classes.rb +1 -1
  35. data/lib/urbanopt/geojson/model.rb +1 -1
  36. data/lib/urbanopt/geojson/region.rb +1 -1
  37. data/lib/urbanopt/geojson/schema/building_properties.json +28 -5
  38. data/lib/urbanopt/geojson/schema/district_system_properties.json +29 -28
  39. data/lib/urbanopt/geojson/schema/electrical_connector_properties.json +150 -10
  40. data/lib/urbanopt/geojson/schema/electrical_junction_properties.json +3 -2
  41. data/lib/urbanopt/geojson/schema/thermal_connector_properties.json +2 -1
  42. data/lib/urbanopt/geojson/update_areas.rb +1 -1
  43. data/lib/urbanopt/geojson/validate_geojson.rb +1 -1
  44. data/lib/urbanopt/geojson/version.rb +2 -2
  45. data/lib/urbanopt/geojson/zoning.rb +1 -1
  46. data/urbanopt-geojson-gem.gemspec +4 -1
  47. metadata +14 -8
  48. data/.travis.yml +0 -35
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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,
@@ -177,19 +177,21 @@ module URBANopt
177
177
  end
178
178
 
179
179
  if feature[:geometry].nil?
180
- raise("No geometry found in '#{feature}'")
180
+ raise("No geometry found in '#{feature[:properties][:name]}'")
181
181
  return false
182
182
  end
183
183
 
184
184
  if feature[:properties].nil?
185
- raise("No properties found in '#{feature}'")
185
+ raise("No properties found in '#{feature[:properties][:name]}'")
186
186
  return false
187
187
  end
188
188
 
189
- errors = JSON::Validator.fully_validate(schema, feature[:properties])
190
- if !errors.empty?
191
- raise("Invalid properties for '#{feature}'\n #{errors.join('\n ')}")
192
- return false
189
+ unless feature[:properties][:detailed_model_filename]
190
+ errors = JSON::Validator.fully_validate(schema, feature[:properties])
191
+ if !errors.empty?
192
+ raise("Invalid properties for '#{feature[:properties][:name]}'\n #{errors.join('\n ')}")
193
+ return false
194
+ end
193
195
  end
194
196
 
195
197
  geometry_type = feature[:geometry][:type]
@@ -0,0 +1,28 @@
1
+ {
2
+ "transformer_properties": {
3
+ "nameclass": "Transformer--25KVA CT",
4
+ "kva": 25,
5
+ "resistance": 0.1,
6
+ "phases": ["A"],
7
+ "high_voltage": 13.2,
8
+ "low_voltage": 0.24,
9
+ "is_center_tap": true,
10
+ "connection": "Delta-Wye"
11
+ },
12
+ "capacitor_properties": {
13
+ "nameclass": "Capacitor--150KVAR",
14
+ "kvar": 150,
15
+ "resistance": 0.1,
16
+ "phases": ["A","B","C"],
17
+ "control_type": "Voltage",
18
+ "connection": "Delta-Wye"
19
+ },
20
+ "wire": {
21
+ "nameclass": "OH AL 4/0",
22
+ "phase": "A",
23
+ "height": 50,
24
+ "x": 0,
25
+ "amapcity": 200
26
+ }
27
+
28
+ }
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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,
@@ -42,17 +42,15 @@ module URBANopt
42
42
  @@schema_file_lock = Mutex.new
43
43
 
44
44
  ##
45
- # Raises an error in case the GeoJSON file is not valid.
45
+ # Initialize GeoJSON file and path.
46
46
  #
47
47
  # [Parameters]
48
48
  #
49
- # * +data+ - _Type:Hash_ Contains the GeoJSON.
50
- def initialize(data, path = nil)
49
+ # * +path+ - _Type:String_ GeoJSON File path.
50
+ # * +data+ - _Type:Hash_ Contains the GeoJSON File.
51
+ def initialize(geojson_file, path = nil)
51
52
  @path = path
52
- @geojson = data
53
- if !valid?
54
- raise 'GeoJSON file does not adhere to schema'
55
- end
53
+ @geojson_file = geojson_file
56
54
  end
57
55
 
58
56
  ##
@@ -69,15 +67,69 @@ module URBANopt
69
67
  raise "GeoJSON file '#{path}' does not exist"
70
68
  end
71
69
 
72
- geojson = JSON.parse(
70
+ geojson_file = JSON.parse(
73
71
  File.open(path, 'r', &:read),
74
72
  symbolize_names: true
75
73
  )
76
- return new(geojson, path)
74
+
75
+ # validate geojson file against schema
76
+ geojson_errors = validate(@@geojson_schema, geojson_file)
77
+ unless geojson_errors.empty?
78
+ raise "GeoJSON file does not adhere to the schema: \n #{geojson_errors.join('\n ')}"
79
+ end
80
+
81
+ # initialize @@logger
82
+ @@logger ||= URBANopt::GeoJSON.logger
83
+
84
+ # validate each feature against schema
85
+ geojson_file[:features].each do |feature|
86
+ properties = feature[:properties]
87
+ type = properties[:type]
88
+
89
+ errors = []
90
+
91
+ case type
92
+ when 'Building'
93
+ # Incase detailed_model_filename present check for fewer properties
94
+ if feature[:properties][:detailed_model_filename]
95
+ if feature[:properties][:id].nil?
96
+ raise("No id found for Building Feature")
97
+ end
98
+ if feature[:properties][:name].nil?
99
+ raise("No name found for Building Feature")
100
+ end
101
+ if feature[:properties][:number_of_stories].nil?
102
+ @@logger.warn("Number of stories is required to calculate shading using the UrbanGeometryCreation measure...ignoring #{feature[:properties][:id]} in shading calculations")
103
+ end
104
+ feature[:additionalProperties] = true
105
+ # Else validate for all required properties in the schema
106
+ else
107
+ errors = validate(@@building_schema, properties)
108
+ end
109
+ when 'District System'
110
+ errors = validate(@@district_system_schema, properties)
111
+ when 'Region'
112
+ error = validate(@@district_system_schema, properties)
113
+ when 'ElectricalJunction'
114
+ errors = validate(@@electrical_junction_schema, properties)
115
+ when 'ElectricalConnector'
116
+ errors = validate(@@electrical_connector_schema, properties)
117
+ when 'ElectricalJunction'
118
+ errors = validate(@@thermal_junction_schema, properties)
119
+ when 'ThermalConnector'
120
+ errors = validate(@@thermal_connector_schema, properties)
121
+ end
122
+
123
+ unless errors.empty?
124
+ raise ("#{type} does not adhere to schema: \n #{errors.join('\n ')}")
125
+ end
126
+
127
+ end
128
+ return new(geojson_file, path)
77
129
  end
78
130
 
79
131
  def json
80
- @geojson
132
+ @geojson_file
81
133
  end
82
134
 
83
135
  attr_reader :path
@@ -88,7 +140,7 @@ module URBANopt
88
140
  #
89
141
  def features
90
142
  result = []
91
- @geojson[:features].each do |f|
143
+ @geojson_file[:features].each do |f|
92
144
  if f[:properties] && f[:properties][:type] == 'Building'
93
145
  result << URBANopt::GeoJSON::Building.new(f)
94
146
  elsif f[:properties] && f[:properties][:type] == 'District System'
@@ -101,13 +153,15 @@ module URBANopt
101
153
  ##
102
154
  # Returns feature object by feature_id from specified GeoJSON file and creates a
103
155
  # new +URBANopt::GeoJSON::Building+ or +URBANopt::GeoJSON::DistrictSystem+ based on the
104
- # feature type.
156
+ # feature type. Before returning the feature, merge 'Site Origin' properties into the feature
105
157
  #
106
158
  # [Parameters]
107
159
  # * +feature_id+ - _Type:String/Number_ - Id affiliated with feature object.
108
160
  def get_feature_by_id(feature_id)
109
- @geojson[:features].each do |f|
161
+ @geojson_file[:features].each do |f|
110
162
  if f[:properties] && f[:properties][:id] == feature_id
163
+ # merge site origin properties
164
+ f = merge_site_properties(f)
111
165
  if f[:properties][:type] == 'Building'
112
166
  return URBANopt::GeoJSON::Building.new(f)
113
167
  elsif f[:properties] && f[:properties][:type] == 'District System'
@@ -118,37 +172,165 @@ module URBANopt
118
172
  return nil
119
173
  end
120
174
 
121
- ##
122
- # Returns the file path for the +geojson_schema.json+ .
123
- def schema_file
124
- return File.join(File.dirname(__FILE__), 'schema', 'geojson_schema.json')
175
+ ##
176
+ # Merge Site Properties in Feature. Returns feature with site properties added to its properties section. Does not overwrite existing properties.
177
+ #
178
+ # [Parameters]
179
+ # +feature+ - _Type:Hash_ - feature object.
180
+ def merge_site_properties(feature)
181
+ site_origins = @geojson_file[:features].select {|f| f[:properties][:type] == 'Site Origin'}
182
+ if site_origins.size > 0
183
+ site_origin = site_origins[0]
184
+ # site origin found, do some merging
185
+ # this maps site properties to building/district system properties.
186
+ add_props = [
187
+ {site: :surface_elevation, feature: :surface_elevation},
188
+ {site: :timesteps_per_hour, feature: :timesteps_per_hour},
189
+ {site: :begin_date, feature: :begin_date},
190
+ {site: :end_date, feature: :end_date},
191
+ {site: :cec_climate_zone, feature: :cec_climate_zone},
192
+ {site: :climate_zone, feature: :climate_zone},
193
+ {site: :default_template, feature: :template},
194
+ {site: :weather_filename, feature: :weather_filename},
195
+ {site: :tariff_filename, feature: :tariff_filename}
196
+ ]
197
+
198
+ add_props.each do |prop|
199
+ if site_origin[:properties].key?(prop[:site]) and site_origin[:properties][prop[:site]]
200
+ # property exists in site
201
+ if !feature[:properties].key?(prop[:feature]) or feature[:properties][prop[:feature]].nil? or feature[:properties][prop[:feature]].empty?
202
+ # property does not exist in feature or is nil: add site property (don't overwrite)
203
+ feature[:properties][prop[:feature]] = site_origin[:properties][prop[:site]]
204
+ end
205
+ end
206
+ end
207
+ end
208
+ return feature
125
209
  end
126
210
 
127
211
  ##
128
- # Returns the +geojson_schema+ .
129
- def schema
212
+ # Validate GeoJSON against schema
213
+ #
214
+ # [Parameters]
215
+ # * +data+ - + - _Type:Hash_ - Input GeoJSON file
216
+ def self.validate(schema_json, data)
217
+ errors = JSON::Validator.fully_validate(schema_json, data, errors_as_objects: true)
218
+ return errors
219
+ end
220
+
221
+ def self.get_geojson_schema(strict)
222
+ result = nil
130
223
  if @@geojson_schema.nil?
131
224
  @@schema_file_lock.synchronize do
132
- File.open(schema_file, 'r') do |file|
133
- @@geojson_schema = JSON.parse(file.read, symbolize_names: true)
225
+ File.open(File.dirname(__FILE__) + '/schema/geojson_schema.json') do |f|
226
+ result = JSON.parse(f.read, symbolize_names: true)
134
227
  end
135
228
  end
136
229
  end
230
+ return result
231
+ end
137
232
 
138
- return @@geojson_schema
233
+ def self.get_building_schema(strict)
234
+ result = nil
235
+ File.open(File.dirname(__FILE__) + '/schema/building_properties.json') do |f|
236
+ result = JSON.parse(f.read)
237
+ end
238
+ if strict
239
+ result['additionalProperties'] = true
240
+ else
241
+ result['additionalProperties'] = false
242
+ end
243
+ return result
244
+ end
245
+
246
+ def self.get_district_system_schema(strict)
247
+ result = nil
248
+ File.open(File.dirname(__FILE__) + '/schema/district_system_properties.json') do |f|
249
+ result = JSON.parse(f.read)
250
+ end
251
+ if strict
252
+ result['additionalProperties'] = true
253
+ else
254
+ result['additionalProperties'] = false
255
+ end
256
+ return result
257
+ end
258
+
259
+ def self.get_region_schema(strict)
260
+ result = nil
261
+ File.open(File.dirname(__FILE__) + '/schema/region_properties.json') do |f|
262
+ result = JSON.parse(f.read)
263
+ end
264
+ if strict
265
+ result['additionalProperties'] = true
266
+ else
267
+ result['additionalProperties'] = false
268
+ end
269
+ return result
139
270
  end
140
271
 
141
- ##
142
- # Validates the GeoJSON file against the schema.
143
- def valid?
144
- return JSON::Validator.validate(schema, @geojson)
272
+ def self.get_electrical_connector_schema(strict)
273
+ result = nil
274
+ File.open(File.dirname(__FILE__) + '/schema/electrical_connector_properties.json') do |f|
275
+ result = JSON.parse(f.read)
276
+ end
277
+ if strict
278
+ result['additionalProperties'] = true
279
+ else
280
+ result['additionalProperties'] = false
281
+ end
282
+ return result
145
283
  end
146
284
 
147
- ##
148
- # Returns detailed validation results.
149
- def validation_errors
150
- return JSON::Validator.fully_validate(schema, @geojson)
285
+ def self.get_electrical_junction_schema(strict)
286
+ result = nil
287
+ File.open(File.dirname(__FILE__) + '/schema/electrical_junction_properties.json') do |f|
288
+ result = JSON.parse(f.read)
289
+ end
290
+ if strict
291
+ result['additionalProperties'] = true
292
+ else
293
+ result['additionalProperties'] = false
294
+ end
295
+ return result
151
296
  end
297
+
298
+ def self.get_thermal_connector_schema(strict)
299
+ result = nil
300
+ File.open(File.dirname(__FILE__) + '/schema/thermal_connector_properties.json') do |f|
301
+ result = JSON.parse(f.read)
302
+ end
303
+ if strict
304
+ result['additionalProperties'] = true
305
+ else
306
+ result['additionalProperties'] = false
307
+ end
308
+ return result
309
+ end
310
+
311
+ def self.get_thermal_junction_schema(strict)
312
+ result = nil
313
+ File.open(File.dirname(__FILE__) + '/schema/thermal_junction_properties.json') do |f|
314
+ result = JSON.parse(f.read)
315
+ end
316
+ if strict
317
+ result['additionalProperties'] = true
318
+ else
319
+ result['additionalProperties'] = false
320
+ end
321
+ return result
322
+ end
323
+
324
+ strict = true
325
+ @@geojson_schema = get_geojson_schema(strict)
326
+ @@building_schema = get_building_schema(strict)
327
+ @@district_system_schema = get_district_system_schema(strict)
328
+ @@region_schema = get_region_schema(strict)
329
+ @@electrical_connector_schema = get_electrical_connector_schema(strict)
330
+ @@electrical_junction_schema = get_electrical_junction_schema(strict)
331
+ @@thermal_connector_schema = get_thermal_connector_schema(strict)
332
+ @@thermal_junction_schema = get_thermal_junction_schema(strict)
333
+
152
334
  end
153
335
  end
154
336
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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,
@@ -216,7 +216,7 @@ module URBANopt
216
216
  #
217
217
  # [Parameters]
218
218
  # * +building+ - _Type:URBANopt::GeoJSON::Building_ - The core building that other buildings will be referenced.
219
- # * +other_building_type+ - _Type:String_ - Describes the surrounding buildings. Currently 'ShadingOnly' is the only option that is processed.
219
+ # * +other_building_type+ - _Type:String_ - Describes the surrounding buildings.
220
220
  # * +other_buildings+ - _Type:URBANopt::GeoJSON::FeatureCollection_ - List of surrounding buildings to include (self will be ignored if present in list).
221
221
  # * +model+ - _Type:OpenStudio::Model::Model_ - An instance of an OpenStudio Model.
222
222
  # * +origin_lat_lon+ - _Type:Float_ - An instance of +OpenStudio::PointLatLon+ indicating the latitude and longitude of the origin.
@@ -255,14 +255,16 @@ module URBANopt
255
255
  # find the polygon of the other_building by passing it to the get_multi_polygons method
256
256
  other_building_points = building.other_points(other_building, other_height, origin_lat_lon, runner, zoning)
257
257
  shadowed = URBANopt::GeoJSON::Helper.is_shadowed(feature_points, other_building_points, origin_lat_lon)
258
- next unless shadowed
259
- end
258
+ next unless shadowed
259
+ new_building = building.create_other_building(:space_per_building, model, origin_lat_lon, runner, zoning, other_building)
260
+ if new_building.nil? || new_building.empty?
261
+ runner.registerWarning("Failed to create spaces for other building '#{name}'")
262
+ end
263
+ other_spaces.concat(new_building)
260
264
 
261
- new_building = building.create_other_building(:space_per_building, model, origin_lat_lon, runner, zoning, other_building)
262
- if new_building.nil? || new_building.empty?
263
- runner.registerWarning("Failed to create spaces for other building '#{name}'")
265
+ elsif other_building_type == 'None'
264
266
  end
265
- other_spaces.concat(new_building)
267
+
266
268
  end
267
269
  return other_spaces
268
270
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt, 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,