urbanopt-geojson 0.1.0 → 0.2.0.pre1

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