openstudio-extension 0.2.0 → 0.2.5
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +45 -1
- data/Jenkinsfile +2 -2
- data/README.md +22 -28
- data/Rakefile +1 -1
- data/lib/change_log.rb +138 -128
- data/lib/measures/openstudio_extension_test_measure/measure.xml +20 -19
- data/lib/openstudio/extension.rb +27 -10
- data/lib/openstudio/extension/core/CreateResults.rb +178 -1
- data/lib/openstudio/extension/core/os_lib_constructions.rb +6 -1
- data/lib/openstudio/extension/core/os_lib_geometry.rb +255 -77
- data/lib/openstudio/extension/core/os_lib_model_generation.rb +2547 -86
- data/lib/openstudio/extension/core/os_lib_reporting.rb +133 -30
- data/lib/openstudio/extension/rake_task.rb +232 -18
- data/lib/openstudio/extension/runner.rb +32 -19
- data/lib/openstudio/extension/runner_config.rb +16 -1
- data/lib/openstudio/extension/version.rb +1 -1
- data/openstudio-extension.gemspec +12 -12
- metadata +30 -33
- data/lib/measures/openstudio_extension_test_measure/tests/openstudio_extension_test_measure_test.rb +0 -74
- data/lib/openstudio/extension/core/os_lib_cofee.rb +0 -259
@@ -1,17 +1,18 @@
|
|
1
|
+
<?xml version="1.0"?>
|
1
2
|
<measure>
|
2
3
|
<schema_version>3.0</schema_version>
|
3
4
|
<name>openstudio_extension_test_measure</name>
|
4
5
|
<uid>36b99a29-41e1-4d85-9272-85d43b966e5a</uid>
|
5
|
-
<version_id>
|
6
|
-
<version_modified>
|
6
|
+
<version_id>edf7f103-9f51-4944-a5af-1d8fa2b0c9b7</version_id>
|
7
|
+
<version_modified>20200427T230714Z</version_modified>
|
7
8
|
<xml_checksum>49BEF039</xml_checksum>
|
8
9
|
<class_name>OpenStudioExtensionTestMeasure</class_name>
|
9
10
|
<display_name>OpenStudio Extension Test Measure</display_name>
|
10
|
-
<description>
|
11
|
-
<modeler_description>
|
12
|
-
<arguments/>
|
13
|
-
<outputs/>
|
14
|
-
<provenances/>
|
11
|
+
<description>A measure that tests OpenStudio Extension gem functionality</description>
|
12
|
+
<modeler_description>This is a test measure that tests OpenStudio Extension gem functionality.</modeler_description>
|
13
|
+
<arguments />
|
14
|
+
<outputs />
|
15
|
+
<provenances />
|
15
16
|
<tags>
|
16
17
|
<tag>Envelope.Form</tag>
|
17
18
|
</tags>
|
@@ -38,12 +39,6 @@
|
|
38
39
|
</attribute>
|
39
40
|
</attributes>
|
40
41
|
<files>
|
41
|
-
<file>
|
42
|
-
<filename>LICENSE.md</filename>
|
43
|
-
<filetype>md</filetype>
|
44
|
-
<usage_type>license</usage_type>
|
45
|
-
<checksum>9640B6CB</checksum>
|
46
|
-
</file>
|
47
42
|
<file>
|
48
43
|
<filename>README.md.erb</filename>
|
49
44
|
<filetype>erb</filetype>
|
@@ -51,16 +46,16 @@
|
|
51
46
|
<checksum>703C9964</checksum>
|
52
47
|
</file>
|
53
48
|
<file>
|
54
|
-
<filename>
|
49
|
+
<filename>LICENSE.md</filename>
|
55
50
|
<filetype>md</filetype>
|
56
|
-
<usage_type>
|
57
|
-
<checksum>
|
51
|
+
<usage_type>license</usage_type>
|
52
|
+
<checksum>E0468DD6</checksum>
|
58
53
|
</file>
|
59
54
|
<file>
|
60
55
|
<filename>OpenStudioExtensionTestMeasure_Test.rb</filename>
|
61
56
|
<filetype>rb</filetype>
|
62
57
|
<usage_type>test</usage_type>
|
63
|
-
<checksum>
|
58
|
+
<checksum>66A00EA8</checksum>
|
64
59
|
</file>
|
65
60
|
<file>
|
66
61
|
<version>
|
@@ -71,13 +66,19 @@
|
|
71
66
|
<filename>measure.rb</filename>
|
72
67
|
<filetype>rb</filetype>
|
73
68
|
<usage_type>script</usage_type>
|
74
|
-
<checksum>
|
69
|
+
<checksum>51BB85EF</checksum>
|
75
70
|
</file>
|
76
71
|
<file>
|
77
72
|
<filename>os_lib_helper_methods.rb</filename>
|
78
73
|
<filetype>rb</filetype>
|
79
74
|
<usage_type>resource</usage_type>
|
80
|
-
<checksum>
|
75
|
+
<checksum>07B01D67</checksum>
|
76
|
+
</file>
|
77
|
+
<file>
|
78
|
+
<filename>README.md</filename>
|
79
|
+
<filetype>md</filetype>
|
80
|
+
<usage_type>readme</usage_type>
|
81
|
+
<checksum>7258830F</checksum>
|
81
82
|
</file>
|
82
83
|
</files>
|
83
84
|
</measure>
|
data/lib/openstudio/extension.rb
CHANGED
@@ -101,11 +101,9 @@ module OpenStudio
|
|
101
101
|
def self.all_measure_dirs
|
102
102
|
result = []
|
103
103
|
all_extensions.each do |obj|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
rescue StandardError
|
108
|
-
end
|
104
|
+
dir = obj.new.measures_dir
|
105
|
+
result << dir if dir
|
106
|
+
rescue StandardError
|
109
107
|
end
|
110
108
|
return result.uniq
|
111
109
|
end
|
@@ -117,11 +115,9 @@ module OpenStudio
|
|
117
115
|
def self.all_file_dirs
|
118
116
|
result = []
|
119
117
|
all_extensions.each do |obj|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
rescue StandardError
|
124
|
-
end
|
118
|
+
dir = obj.new.files_dir
|
119
|
+
result << dir if dir
|
120
|
+
rescue StandardError
|
125
121
|
end
|
126
122
|
return result.uniq
|
127
123
|
end
|
@@ -230,5 +226,26 @@ module OpenStudio
|
|
230
226
|
|
231
227
|
return osw
|
232
228
|
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Module method used to check whether a measure is present in an OSW file
|
232
|
+
##
|
233
|
+
# @param [Hash] in_osw Initial OSW object as a Hash, keys should be symbolized
|
234
|
+
# @param [String] measure_dir_name Directory name of measure to set argument on
|
235
|
+
# @param [String] step_name Optional argument, if present used to further identify the measure
|
236
|
+
#
|
237
|
+
# @return [Boolean] true or false
|
238
|
+
def self.measure_in_osw(osw, measure_dir_name, step_name = nil)
|
239
|
+
result = false
|
240
|
+
osw[:steps].each do |step|
|
241
|
+
if step[:measure_dir_name] == measure_dir_name
|
242
|
+
if step_name.nil? || step[:name] == step_name
|
243
|
+
result = true
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
return result
|
249
|
+
end
|
233
250
|
end
|
234
251
|
end
|
@@ -45,6 +45,23 @@ module OsLib_CreateResults
|
|
45
45
|
# @param end_mo [String] the end month for the peak demand window
|
46
46
|
# @param end_day [Integer] the end day for the peak demand window
|
47
47
|
# @param end_hr [Integer] the end hour for the peak demand window, using 24-hr clock
|
48
|
+
# @param electricity_consumption_tou_periods [Array<Hash>] optional array of hashes to add
|
49
|
+
# time-of-use electricity consumption values to the annual consumption information.
|
50
|
+
# Periods may overlap, but should be listed in the order in which they must be checked,
|
51
|
+
# where the value will be assigned to the first encountered period it falls into.
|
52
|
+
# An example hash looks like this:
|
53
|
+
# {
|
54
|
+
# 'tou_name' => 'system_peak',
|
55
|
+
# 'tou_id' => 1,
|
56
|
+
# 'skip_weekends' => true,
|
57
|
+
# 'skip_holidays' => true,
|
58
|
+
# 'start_mo' => 'July',
|
59
|
+
# 'start_day' => 1,
|
60
|
+
# 'start_hr' => 14,
|
61
|
+
# 'end_mo' => 'August',
|
62
|
+
# 'end_day' => 31,
|
63
|
+
# 'end_hr' => 18
|
64
|
+
# }
|
48
65
|
# @return [OpenStudio::AttributeVector] a vector of results needed by EDAPT
|
49
66
|
def create_results(skip_weekends = true,
|
50
67
|
skip_holidays = true,
|
@@ -53,7 +70,8 @@ module OsLib_CreateResults
|
|
53
70
|
start_hr = 14,
|
54
71
|
end_mo = 'September',
|
55
72
|
end_day = 30,
|
56
|
-
end_hr = 18
|
73
|
+
end_hr = 18,
|
74
|
+
electricity_consumption_tou_periods = [])
|
57
75
|
|
58
76
|
# get the current version of OS being used to determine if sql query
|
59
77
|
# changes are needed (for when E+ changes).
|
@@ -497,6 +515,83 @@ module OsLib_CreateResults
|
|
497
515
|
@runner.registerValue('annual_demand_electricity_peak_demand', 0.0, 'kW')
|
498
516
|
end
|
499
517
|
|
518
|
+
# Describe the TOU periods
|
519
|
+
electricity_consumption_tou_periods.each do |tou_pd|
|
520
|
+
@runner.registerInfo("TOU period #{tou_pd['tou_id']} represents #{tou_pd['tou_name']} and covers #{tou_pd['start_mo']}-#{tou_pd['start_day']} to #{tou_pd['end_mo']}-#{tou_pd['end_day']} from #{tou_pd['start_hr']} to #{tou_pd['end_hr']}, skip weekends = #{tou_pd['skip_weekends']}, skip holidays = #{tou_pd['skip_holidays']}")
|
521
|
+
end
|
522
|
+
|
523
|
+
# electricity time-of-use periods
|
524
|
+
elec = @sql.timeSeries(ann_env_pd, 'Zone Timestep', 'Electricity:Facility', '')
|
525
|
+
if elec.is_initialized && day_types
|
526
|
+
elec = elec.get
|
527
|
+
# Put timeseries into array
|
528
|
+
elec_vals = []
|
529
|
+
ann_elec_vals = elec.values
|
530
|
+
for i in 0..(ann_elec_vals.size - 1)
|
531
|
+
elec_vals << ann_elec_vals[i]
|
532
|
+
end
|
533
|
+
|
534
|
+
# Put values into array
|
535
|
+
elec_times = []
|
536
|
+
ann_elec_times = elec.dateTimes
|
537
|
+
for i in 0..(ann_elec_times.size - 1)
|
538
|
+
elec_times << ann_elec_times[i]
|
539
|
+
end
|
540
|
+
|
541
|
+
# Loop through the time/value pairs and find the peak
|
542
|
+
# excluding the times outside of the Xcel peak demand window
|
543
|
+
electricity_tou_vals = Hash.new(0)
|
544
|
+
elec_times.zip(elec_vals).each_with_index do |vs, ind|
|
545
|
+
date_time = vs[0]
|
546
|
+
joules = vs[1]
|
547
|
+
day_type = day_types[ind]
|
548
|
+
time = date_time.time
|
549
|
+
date = date_time.date
|
550
|
+
|
551
|
+
# puts("#{val_kW}kW; #{date}; #{time}; #{day_of_week.valueName}")
|
552
|
+
|
553
|
+
# Determine which TOU period this hour falls into
|
554
|
+
tou_period_assigned = false
|
555
|
+
electricity_consumption_tou_periods.each do |tou_pd|
|
556
|
+
pd_start_date = OpenStudio::DateTime.new(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(tou_pd['start_mo']), tou_pd['start_day'], timeseries_yr), OpenStudio::Time.new(0, 0, 0, 0))
|
557
|
+
pd_end_date = OpenStudio::DateTime.new(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(tou_pd['end_mo']), tou_pd['end_day'], timeseries_yr), OpenStudio::Time.new(0, 24, 0, 0))
|
558
|
+
pd_start_time = OpenStudio::Time.new(0, tou_pd['start_hr'], 0, 0)
|
559
|
+
pd_end_time = OpenStudio::Time.new(0, tou_pd['end_hr'], 0, 0)
|
560
|
+
# Skip times outside of the correct months
|
561
|
+
next if date_time < pd_start_date || date_time > pd_end_date
|
562
|
+
# Skip times before some time and after another time
|
563
|
+
next if time < pd_start_time || time > pd_end_time
|
564
|
+
# Skip weekends if asked
|
565
|
+
if tou_pd['skip_weekends']
|
566
|
+
# Sunday = 1, Saturday = 7
|
567
|
+
next if day_type == 1 || day_type == 7
|
568
|
+
end
|
569
|
+
# Skip holidays if asked
|
570
|
+
if tou_pd['skip_holidays']
|
571
|
+
# Holiday = 8
|
572
|
+
next if day_type == 8
|
573
|
+
end
|
574
|
+
# If here, this hour falls into the specified period
|
575
|
+
tou_period_assigned = true
|
576
|
+
electricity_tou_vals[tou_pd['tou_id']] += joules
|
577
|
+
break
|
578
|
+
end
|
579
|
+
# Ensure that the value fell into a period
|
580
|
+
unless tou_period_assigned
|
581
|
+
@runner.registerError("Did not find a TOU period covering #{time} on #{date}, kWh will not be included in any TOU period.")
|
582
|
+
end
|
583
|
+
end
|
584
|
+
# Register values for any time-of-use period with kWh
|
585
|
+
electricity_tou_vals.each do |tou_pd_id, joules_in_pd|
|
586
|
+
gj_in_pd = OpenStudio.convert(joules_in_pd, 'J', 'GJ').get
|
587
|
+
kwh_in_pd = OpenStudio.convert(joules_in_pd, 'J', 'kWh').get
|
588
|
+
@runner.registerValue("annual_consumption_electricity_tou_#{tou_pd_id}", gj_in_pd, 'GJ')
|
589
|
+
@runner.registerInfo("TOU period #{tou_pd_id} annual electricity consumption = #{kwh_in_pd} kWh.")
|
590
|
+
end
|
591
|
+
else
|
592
|
+
@runner.registerError('Electricity timeseries (Electricity:Facility at zone timestep) could not be found, cannot determine the information needed to calculate savings or incentives.')
|
593
|
+
end
|
594
|
+
|
500
595
|
# electricity_annual_avg_peak_demand
|
501
596
|
val = @sql.electricityTotalEndUses
|
502
597
|
if val.is_initialized
|
@@ -587,6 +682,88 @@ module OsLib_CreateResults
|
|
587
682
|
@runner.registerValue('annual_demand_district_cooling_peak_demand', 0.0, 'kW')
|
588
683
|
end
|
589
684
|
|
685
|
+
# district cooling time-of-use periods
|
686
|
+
dist_clg = @sql.timeSeries(ann_env_pd, 'Zone Timestep', 'DistrictCooling:Facility', '')
|
687
|
+
if dist_clg.is_initialized && day_types
|
688
|
+
dist_clg = dist_clg.get
|
689
|
+
# Put timeseries into array
|
690
|
+
dist_clg_vals = []
|
691
|
+
ann_dist_clg_vals = dist_clg.values
|
692
|
+
for i in 0..(ann_dist_clg_vals.size - 1)
|
693
|
+
dist_clg_vals << ann_dist_clg_vals[i]
|
694
|
+
end
|
695
|
+
|
696
|
+
# Put values into array
|
697
|
+
dist_clg_times = []
|
698
|
+
ann_dist_clg_times = dist_clg.dateTimes
|
699
|
+
for i in 0..(ann_dist_clg_times.size - 1)
|
700
|
+
dist_clg_times << ann_dist_clg_times[i]
|
701
|
+
end
|
702
|
+
|
703
|
+
# Loop through the time/value pairs and find the peak
|
704
|
+
# excluding the times outside of the Xcel peak demand window
|
705
|
+
dist_clg_tou_vals = Hash.new(0)
|
706
|
+
dist_clg_times.zip(dist_clg_vals).each_with_index do |vs, ind|
|
707
|
+
date_time = vs[0]
|
708
|
+
joules = vs[1]
|
709
|
+
day_type = day_types[ind]
|
710
|
+
time = date_time.time
|
711
|
+
date = date_time.date
|
712
|
+
|
713
|
+
# puts("#{val_kW}kW; #{date}; #{time}; #{day_of_week.valueName}")
|
714
|
+
|
715
|
+
# Determine which TOU period this hour falls into
|
716
|
+
tou_period_assigned = false
|
717
|
+
electricity_consumption_tou_periods.each do |tou_pd|
|
718
|
+
pd_start_date = OpenStudio::DateTime.new(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(tou_pd['start_mo']), tou_pd['start_day'], timeseries_yr), OpenStudio::Time.new(0, 0, 0, 0))
|
719
|
+
pd_end_date = OpenStudio::DateTime.new(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(tou_pd['end_mo']), tou_pd['end_day'], timeseries_yr), OpenStudio::Time.new(0, 24, 0, 0))
|
720
|
+
pd_start_time = OpenStudio::Time.new(0, tou_pd['start_hr'], 0, 0)
|
721
|
+
pd_end_time = OpenStudio::Time.new(0, tou_pd['end_hr'], 0, 0)
|
722
|
+
# Skip times outside of the correct months
|
723
|
+
next if date_time < pd_start_date || date_time > pd_end_date
|
724
|
+
# Skip times before some time and after another time
|
725
|
+
next if time < pd_start_time || time > pd_end_time
|
726
|
+
# Skip weekends if asked
|
727
|
+
if tou_pd['skip_weekends']
|
728
|
+
# Sunday = 1, Saturday = 7
|
729
|
+
next if day_type == 1 || day_type == 7
|
730
|
+
end
|
731
|
+
# Skip holidays if asked
|
732
|
+
if tou_pd['skip_holidays']
|
733
|
+
# Holiday = 8
|
734
|
+
next if day_type == 8
|
735
|
+
end
|
736
|
+
# If here, this hour falls into the specified period
|
737
|
+
tou_period_assigned = true
|
738
|
+
dist_clg_tou_vals[tou_pd['tou_id']] += joules
|
739
|
+
break
|
740
|
+
end
|
741
|
+
# Ensure that the value fell into a period
|
742
|
+
unless tou_period_assigned
|
743
|
+
@runner.registerError("Did not find a TOU period covering #{time} on #{date}, kWh will not be included in any TOU period.")
|
744
|
+
end
|
745
|
+
end
|
746
|
+
# Register values for any time-of-use period with kWh
|
747
|
+
dist_clg_tou_vals.each do |tou_pd_id, joules_in_pd|
|
748
|
+
gj_in_pd = OpenStudio.convert(joules_in_pd, 'J', 'GJ').get
|
749
|
+
kwh_in_pd = OpenStudio.convert(joules_in_pd, 'J', 'kWh').get
|
750
|
+
@runner.registerValue("annual_consumption_district_cooling_tou_#{tou_pd_id}", gj_in_pd, 'GJ')
|
751
|
+
@runner.registerInfo("TOU period #{tou_pd_id} annual district cooling consumption = #{kwh_in_pd} kWh.")
|
752
|
+
end
|
753
|
+
else
|
754
|
+
# If TOU periods were specified but this model has no district cooling, report zeroes
|
755
|
+
if electricity_consumption_tou_periods.size > 0
|
756
|
+
# Get the TOU ids
|
757
|
+
tou_ids = []
|
758
|
+
electricity_consumption_tou_periods.each do |tou_pd|
|
759
|
+
tou_ids << tou_pd['tou_id']
|
760
|
+
end
|
761
|
+
tou_ids.uniq.each do |tou_id|
|
762
|
+
@runner.registerValue("annual_consumption_district_cooling_tou_#{tou_id}", 0.0, 'GJ')
|
763
|
+
end
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
590
767
|
else
|
591
768
|
@runner.registerError('Could not find an annual run period')
|
592
769
|
return OpenStudio::Attribute.new('report', result_elems)
|
@@ -283,7 +283,12 @@ module OsLib_Constructions
|
|
283
283
|
# create info message
|
284
284
|
if !runner.nil? # todo - need to look for bad visible transmittance here
|
285
285
|
uFactorSiToIpConversion = OpenStudio.convert(material.uFactor, 'W/m^2*K', 'Btu/ft^2*h*R').get
|
286
|
-
|
286
|
+
# version check to support 2.x and 3.x
|
287
|
+
if Gem::Version.new(OpenStudio::openStudioVersion) > Gem::Version.new("2.9.1")
|
288
|
+
runner.registerInfo("Created #{construction.name} construction. U-factor: #{OpenStudio.toNeatString(uFactorSiToIpConversion, 2, true)}(Btu/ft^2*h*R), SHGC: #{material.solarHeatGainCoefficient}, VT: #{material.getVisibleTransmittance.get}.")
|
289
|
+
else
|
290
|
+
runner.registerInfo("Created #{construction.name} construction. U-factor: #{OpenStudio.toNeatString(uFactorSiToIpConversion, 2, true)}(Btu/ft^2*h*R), SHGC: #{material.getSolarHeatGainCoefficient}, VT: #{material.getVisibleTransmittance.get}.")
|
291
|
+
end
|
287
292
|
end
|
288
293
|
|
289
294
|
result = construction
|
@@ -327,7 +327,8 @@ module OsLib_Geometry
|
|
327
327
|
end
|
328
328
|
|
329
329
|
# sort array by floor area, this hash will be altered to reduce floor area for each space type to 0
|
330
|
-
space_types_running_count = space_types.sort_by { |k, v| v[:floor_area] }
|
330
|
+
#space_types_running_count = space_types.sort_by { |k, v| v[:floor_area] }
|
331
|
+
space_types_running_count = space_types
|
331
332
|
|
332
333
|
# array entry for each story
|
333
334
|
footprints = []
|
@@ -354,8 +355,10 @@ module OsLib_Geometry
|
|
354
355
|
|
355
356
|
space_types_running_count.each do |space_type, space_type_hash|
|
356
357
|
# next if floor area is full or space type is empty
|
357
|
-
|
358
|
-
|
358
|
+
|
359
|
+
tol_value = 0.0001
|
360
|
+
next if current_footprint_area + tol_value >= target_footprint_area
|
361
|
+
next if space_type_hash[:floor_area] <= tol_value
|
359
362
|
|
360
363
|
# special test for when total floor area is smaller than valid_bar_area_min, just make bar smaller that valid min and warn user
|
361
364
|
if target_per_space_type[space_type] < valid_bar_area_min
|
@@ -367,20 +370,18 @@ module OsLib_Geometry
|
|
367
370
|
|
368
371
|
# add entry for space type if it doesn't have one yet
|
369
372
|
if !space_types_local_count.key?(space_type)
|
370
|
-
|
373
|
+
if space_type_hash.has_key?(:children)
|
374
|
+
space_type = space_type_hash[:children][:default][:space_type] # will re-using space type create issue
|
375
|
+
space_types_local_count[space_type] = { floor_area: 0.0 }
|
376
|
+
space_types_local_count[space_type][:children] = space_type_hash[:children]
|
377
|
+
else
|
378
|
+
space_types_local_count[space_type] = { floor_area: 0.0 }
|
379
|
+
end
|
371
380
|
end
|
372
381
|
|
373
382
|
# if there is enough of this space type to fill rest of floor area
|
374
383
|
remaining_in_footprint = target_footprint_area - current_footprint_area
|
375
|
-
|
376
|
-
|
377
|
-
# add to local count for story and remove from running count from space type
|
378
|
-
raw_footprint_area_used = remaining_in_footprint
|
379
|
-
|
380
|
-
else
|
381
|
-
# if not then use up the rest of the floor area and move on to next space type
|
382
|
-
raw_footprint_area_used = space_type_hash[:floor_area]
|
383
|
-
end
|
384
|
+
raw_footprint_area_used = [space_type_hash[:floor_area],remaining_in_footprint].min
|
384
385
|
|
385
386
|
# add to local hash
|
386
387
|
space_types_local_count[space_type][:floor_area] = raw_footprint_area_used / v[:multiplier].to_f
|
@@ -389,13 +390,13 @@ module OsLib_Geometry
|
|
389
390
|
current_footprint_area += raw_footprint_area_used
|
390
391
|
space_type_hash[:floor_area] -= raw_footprint_area_used
|
391
392
|
|
392
|
-
# test if think
|
393
|
+
# test if think sliver left on current floor.
|
393
394
|
# fix by moving smallest space type to next floor and and the same amount more of the sliver space type to this story
|
394
395
|
raw_footprint_area_used < valid_bar_area_min && sliver_override == false ? (test_a = true) : (test_a = false)
|
395
396
|
|
396
397
|
# test if what would be left of the current space type would result in a sliver on the next story.
|
397
398
|
# fix by removing some of this space type so their is enough left for the next story, and replace the removed amount with the largest space type in the model
|
398
|
-
(space_type_hash[:floor_area] < valid_bar_area_min) && (space_type_hash[:floor_area] >
|
399
|
+
(space_type_hash[:floor_area] < valid_bar_area_min) && (space_type_hash[:floor_area] > tol_value) ? (test_b = true) : (test_b = false)
|
399
400
|
|
400
401
|
# identify very small slices and re-arrange spaces to different stories to avoid this
|
401
402
|
if test_a
|
@@ -422,6 +423,10 @@ module OsLib_Geometry
|
|
422
423
|
|
423
424
|
# swap size
|
424
425
|
swap_size = valid_bar_area_min * 5 # currently equal to default perimeter zone depth of 15'
|
426
|
+
# this prevents too much area from being swapped resulting in a negative number for floor area
|
427
|
+
if swap_size > space_types_local_count[space_type][:floor_area] * v[:multiplier].to_f
|
428
|
+
swap_size = space_types_local_count[space_type][:floor_area] * v[:multiplier].to_f
|
429
|
+
end
|
425
430
|
|
426
431
|
# adjust running count for current space type
|
427
432
|
space_type_hash[:floor_area] += swap_size
|
@@ -445,12 +450,18 @@ module OsLib_Geometry
|
|
445
450
|
end
|
446
451
|
|
447
452
|
# sliced bar simple creates a single sliced bar for space types passed in
|
448
|
-
#
|
453
|
+
# look at length and width to adjust slicing direction
|
449
454
|
def self.make_sliced_bar_simple_polygons(runner, space_types, length, width, footprint_origin = OpenStudio::Point3d.new(0, 0, 0), perimeter_zone_depth = OpenStudio.convert(15, 'ft', 'm').get)
|
450
455
|
hash_of_point_vectors = {} # key is name, value is a hash, one item of which is polygon. Another could be space type
|
451
456
|
|
457
|
+
reverse_slice = false
|
458
|
+
if length < width
|
459
|
+
reverse_slice = true
|
460
|
+
#runner.registerInfo("reverse typical slice direction for bar because of aspect ratio less than 1.0.")
|
461
|
+
end
|
462
|
+
|
452
463
|
# determine if core and perimeter zoning can be used
|
453
|
-
if !(length > perimeter_zone_depth * 2.5 && width > perimeter_zone_depth * 2.5)
|
464
|
+
if !([length,width].min > perimeter_zone_depth * 2.5 && [length,width].min > perimeter_zone_depth * 2.5)
|
454
465
|
perimeter_zone_depth = 0 # if any size is to small then just model floor as single zone, issue warning
|
455
466
|
runner.registerWarning('Not modeling core and perimeter zones for some portion of the model.')
|
456
467
|
end
|
@@ -461,6 +472,7 @@ module OsLib_Geometry
|
|
461
472
|
# this represents the entire bar, not individual space type slices
|
462
473
|
nw_point = OpenStudio::Point3d.new(x_delta, y_delta + width, z)
|
463
474
|
sw_point = OpenStudio::Point3d.new(x_delta, y_delta, z)
|
475
|
+
se_point = OpenStudio::Point3d.new(x_delta + length, y_delta, z) # used when length is less than width
|
464
476
|
|
465
477
|
# total building floor area to calculate ratios from space type floor areas
|
466
478
|
total_floor_area = 0.0
|
@@ -470,7 +482,7 @@ module OsLib_Geometry
|
|
470
482
|
|
471
483
|
# sort array by floor area but shift largest object to front
|
472
484
|
space_types = space_types.sort_by { |k, v| v[:floor_area] }
|
473
|
-
space_types.insert(0, space_types.delete_at(space_types.size - 1))
|
485
|
+
space_types.insert(0, space_types.delete_at(space_types.size - 1)) #.to_h
|
474
486
|
|
475
487
|
# min and max bar end values
|
476
488
|
min_bar_end_multiplier = 0.75
|
@@ -484,20 +496,20 @@ module OsLib_Geometry
|
|
484
496
|
start_perimeter_width_deduction = 0.0
|
485
497
|
end_perimeter_width_deduction = 0.0
|
486
498
|
if space_type == space_types.first[0]
|
487
|
-
if length * space_type_hash[:floor_area] / total_floor_area > max_bar_end_multiplier * perimeter_zone_depth
|
499
|
+
if [length,width].max * space_type_hash[:floor_area] / total_floor_area > max_bar_end_multiplier * perimeter_zone_depth
|
488
500
|
start_perimeter_width_deduction = perimeter_zone_depth
|
489
501
|
end
|
490
502
|
# see if last space type is too small for perimeter. If it is then save some of this space type
|
491
|
-
if length * space_types.last[1][:floor_area] / total_floor_area < perimeter_zone_depth * min_bar_end_multiplier
|
503
|
+
if [length,width].max * space_types.last[1][:floor_area] / total_floor_area < perimeter_zone_depth * min_bar_end_multiplier
|
492
504
|
re_apply_largest_space_type_at_end = true
|
493
505
|
end
|
494
506
|
end
|
495
507
|
if space_type == space_types.last[0]
|
496
|
-
if length * space_type_hash[:floor_area] / total_floor_area > max_bar_end_multiplier * perimeter_zone_depth
|
508
|
+
if [length,width].max * space_type_hash[:floor_area] / total_floor_area > max_bar_end_multiplier * perimeter_zone_depth
|
497
509
|
end_perimeter_width_deduction = perimeter_zone_depth
|
498
510
|
end
|
499
511
|
end
|
500
|
-
non_end_adjusted_width = (length * space_type_hash[:floor_area] / total_floor_area) - start_perimeter_width_deduction - end_perimeter_width_deduction
|
512
|
+
non_end_adjusted_width = ([length,width].max * space_type_hash[:floor_area] / total_floor_area) - start_perimeter_width_deduction - end_perimeter_width_deduction
|
501
513
|
|
502
514
|
# adjustment of end space type is too small and is replaced with largest space type
|
503
515
|
if (space_type == space_types.first[0]) && re_apply_largest_space_type_at_end
|
@@ -506,69 +518,223 @@ module OsLib_Geometry
|
|
506
518
|
end
|
507
519
|
if (space_type == space_types.last[0]) && re_apply_largest_space_type_at_end
|
508
520
|
end_perimeter_width_deduction = space_types.first[0]
|
521
|
+
end_b_flag = true
|
522
|
+
else
|
523
|
+
end_b_flag = false
|
509
524
|
end
|
510
525
|
|
511
|
-
#
|
526
|
+
# populate data for core and perimeter of slice
|
512
527
|
section_hash_for_space_type = {}
|
513
528
|
section_hash_for_space_type['end_a'] = start_perimeter_width_deduction
|
514
529
|
section_hash_for_space_type[''] = non_end_adjusted_width
|
515
530
|
section_hash_for_space_type['end_b'] = end_perimeter_width_deduction
|
516
531
|
|
532
|
+
# determine if this space+type is double loaded corridor, and if so what the perimeter zone depth should be based on building width
|
533
|
+
# look at reverse_slice to see if length or width should be used to determine perimeter depth
|
534
|
+
if space_type_hash.has_key?(:children)
|
535
|
+
core_ratio = space_type_hash[:children][:circ][:orig_ratio]
|
536
|
+
perim_ratio = space_type_hash[:children][:default][:orig_ratio]
|
537
|
+
core_ratio_adj = core_ratio / (core_ratio + perim_ratio)
|
538
|
+
perim_ratio_adj = perim_ratio / (core_ratio + perim_ratio)
|
539
|
+
core_space_type = space_type_hash[:children][:circ][:space_type]
|
540
|
+
perim_space_type = space_type_hash[:children][:default][:space_type]
|
541
|
+
if !reverse_slice
|
542
|
+
custom_cor_val = width * core_ratio_adj
|
543
|
+
custom_perim_val = (width - custom_cor_val)/2.0
|
544
|
+
else
|
545
|
+
custom_cor_val = length * core_ratio_adj
|
546
|
+
custom_perim_val = (length - custom_cor_val)/2.0
|
547
|
+
end
|
548
|
+
actual_perim = custom_perim_val
|
549
|
+
double_loaded_corridor = true
|
550
|
+
else
|
551
|
+
actual_perim = perimeter_zone_depth
|
552
|
+
double_loaded_corridor = false
|
553
|
+
end
|
554
|
+
|
555
|
+
# may overwrite
|
556
|
+
first_space_type_hash = space_types.first[1]
|
557
|
+
if end_b_flag && first_space_type_hash.has_key?(:children)
|
558
|
+
end_b_core_ratio = first_space_type_hash[:children][:circ][:orig_ratio]
|
559
|
+
end_b_perim_ratio = first_space_type_hash[:children][:default][:orig_ratio]
|
560
|
+
end_b_core_ratio_adj = end_b_core_ratio / (end_b_core_ratio + end_b_perim_ratio)
|
561
|
+
end_b_perim_ratio_adj = end_b_perim_ratio / (end_b_core_ratio + end_b_perim_ratio)
|
562
|
+
end_b_core_space_type = first_space_type_hash[:children][:circ][:space_type]
|
563
|
+
end_b_perim_space_type = first_space_type_hash[:children][:default][:space_type]
|
564
|
+
if !reverse_slice
|
565
|
+
end_b_custom_cor_val = width * end_b_core_ratio_adj
|
566
|
+
end_b_custom_perim_val = (width - end_b_custom_cor_val)/2.0
|
567
|
+
else
|
568
|
+
end_b_custom_cor_val = length * end_b_core_ratio_adj
|
569
|
+
end_b_custom_perim_val = (length - end_b_custom_cor_val)/2.0
|
570
|
+
end
|
571
|
+
end_b_actual_perim = end_b_custom_perim_val
|
572
|
+
end_b_double_loaded_corridor = true
|
573
|
+
else
|
574
|
+
end_b_actual_perim = perimeter_zone_depth
|
575
|
+
end_b_double_loaded_corridor = false
|
576
|
+
end
|
577
|
+
|
517
578
|
# loop through sections for space type (main and possibly one or two end perimeter sections)
|
518
|
-
section_hash_for_space_type.each do |k,
|
519
|
-
|
520
|
-
|
579
|
+
section_hash_for_space_type.each do |k, slice|
|
580
|
+
|
581
|
+
# need to use different space type for end_b
|
582
|
+
if end_b_flag && k == "end_b" && space_types.first[1].has_key?(:children)
|
583
|
+
slice = space_types.first[0]
|
584
|
+
actual_perim = end_b_actual_perim
|
585
|
+
double_loaded_corridor = end_b_double_loaded_corridor
|
586
|
+
core_ratio = end_b_core_ratio
|
587
|
+
perim_ratio = end_b_perim_ratio
|
588
|
+
core_ratio_adj = end_b_core_ratio_adj
|
589
|
+
perim_ratio_adj = end_b_perim_ratio_adj
|
590
|
+
core_space_type = end_b_core_space_type
|
591
|
+
perim_space_type = end_b_perim_space_type
|
592
|
+
end
|
593
|
+
|
594
|
+
if slice.class.to_s == 'OpenStudio::Model::SpaceType' || slice.class.to_s == 'OpenStudio::Model::Building'
|
595
|
+
space_type = slice
|
521
596
|
max_reduction = [perimeter_zone_depth, max_reduction].min
|
522
|
-
|
597
|
+
slice = max_reduction
|
523
598
|
end
|
524
|
-
if
|
599
|
+
if slice == 0
|
525
600
|
next
|
526
601
|
end
|
527
602
|
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
603
|
+
if !reverse_slice
|
604
|
+
|
605
|
+
ne_point = nw_point + OpenStudio::Vector3d.new(slice, 0, 0)
|
606
|
+
se_point = sw_point + OpenStudio::Vector3d.new(slice, 0, 0)
|
607
|
+
|
608
|
+
if actual_perim > 0 && (actual_perim * 2.0) < width
|
609
|
+
polygon_a = OpenStudio::Point3dVector.new
|
610
|
+
polygon_a << sw_point
|
611
|
+
polygon_a << sw_point + OpenStudio::Vector3d.new(0, actual_perim, 0)
|
612
|
+
polygon_a << se_point + OpenStudio::Vector3d.new(0, actual_perim, 0)
|
613
|
+
polygon_a << se_point
|
614
|
+
if double_loaded_corridor
|
615
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"] = {}
|
616
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"][:space_type] = perim_space_type
|
617
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"][:polygon] = polygon_a
|
618
|
+
else
|
619
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"] = {}
|
620
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"][:space_type] = space_type
|
621
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"][:polygon] = polygon_a
|
622
|
+
end
|
623
|
+
|
624
|
+
polygon_b = OpenStudio::Point3dVector.new
|
625
|
+
polygon_b << sw_point + OpenStudio::Vector3d.new(0, actual_perim, 0)
|
626
|
+
polygon_b << nw_point + OpenStudio::Vector3d.new(0, - actual_perim, 0)
|
627
|
+
polygon_b << ne_point + OpenStudio::Vector3d.new(0, - actual_perim, 0)
|
628
|
+
polygon_b << se_point + OpenStudio::Vector3d.new(0, actual_perim, 0)
|
629
|
+
if double_loaded_corridor
|
630
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"] = {}
|
631
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"][:space_type] = core_space_type
|
632
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"][:polygon] = polygon_b
|
633
|
+
else
|
634
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"] = {}
|
635
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"][:space_type] = space_type
|
636
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"][:polygon] = polygon_b
|
637
|
+
end
|
638
|
+
|
639
|
+
polygon_c = OpenStudio::Point3dVector.new
|
640
|
+
polygon_c << nw_point + OpenStudio::Vector3d.new(0, - actual_perim, 0)
|
641
|
+
polygon_c << nw_point
|
642
|
+
polygon_c << ne_point
|
643
|
+
polygon_c << ne_point + OpenStudio::Vector3d.new(0, - actual_perim, 0)
|
644
|
+
if double_loaded_corridor
|
645
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"] = {}
|
646
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"][:space_type] = perim_space_type
|
647
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"][:polygon] = polygon_c
|
648
|
+
else
|
649
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"] = {}
|
650
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"][:space_type] = space_type
|
651
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"][:polygon] = polygon_c
|
652
|
+
end
|
653
|
+
else
|
654
|
+
polygon_a = OpenStudio::Point3dVector.new
|
655
|
+
polygon_a << sw_point
|
656
|
+
polygon_a << nw_point
|
657
|
+
polygon_a << ne_point
|
658
|
+
polygon_a << se_point
|
659
|
+
hash_of_point_vectors["#{space_type.name} #{k}"] = {}
|
660
|
+
hash_of_point_vectors["#{space_type.name} #{k}"][:space_type] = space_type
|
661
|
+
hash_of_point_vectors["#{space_type.name} #{k}"][:polygon] = polygon_a
|
662
|
+
end
|
663
|
+
|
664
|
+
# update west points
|
665
|
+
nw_point = ne_point
|
666
|
+
sw_point = se_point
|
667
|
+
|
558
668
|
else
|
559
|
-
polygon_a = OpenStudio::Point3dVector.new
|
560
|
-
polygon_a << sw_point
|
561
|
-
polygon_a << nw_point
|
562
|
-
polygon_a << ne_point
|
563
|
-
polygon_a << se_point
|
564
|
-
hash_of_point_vectors["#{space_type.name} #{k}"] = {}
|
565
|
-
hash_of_point_vectors["#{space_type.name} #{k}"][:space_type] = space_type
|
566
|
-
hash_of_point_vectors["#{space_type.name} #{k}"][:polygon] = polygon_a
|
567
|
-
end
|
568
669
|
|
569
|
-
|
570
|
-
|
571
|
-
|
670
|
+
# create_bar at 90 degrees if aspect ration is less than 1.0
|
671
|
+
# typical order (sw,nw,ne,se)
|
672
|
+
# order used here (se,sw,nw,ne)
|
673
|
+
|
674
|
+
nw_point = sw_point + OpenStudio::Vector3d.new(0, slice, 0)
|
675
|
+
ne_point = se_point + OpenStudio::Vector3d.new(0, slice, 0)
|
676
|
+
|
677
|
+
if actual_perim > 0 && (actual_perim * 2.0) < length
|
678
|
+
polygon_a = OpenStudio::Point3dVector.new
|
679
|
+
polygon_a << se_point
|
680
|
+
polygon_a << se_point + OpenStudio::Vector3d.new(- actual_perim, 0, 0)
|
681
|
+
polygon_a << ne_point + OpenStudio::Vector3d.new(- actual_perim, 0, 0)
|
682
|
+
polygon_a << ne_point
|
683
|
+
if double_loaded_corridor
|
684
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"] = {}
|
685
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"][:space_type] = perim_space_type
|
686
|
+
hash_of_point_vectors["#{perim_space_type.name} A #{k}"][:polygon] = polygon_a
|
687
|
+
else
|
688
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"] = {}
|
689
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"][:space_type] = space_type
|
690
|
+
hash_of_point_vectors["#{space_type.name} A #{k}"][:polygon] = polygon_a
|
691
|
+
end
|
692
|
+
|
693
|
+
polygon_b = OpenStudio::Point3dVector.new
|
694
|
+
polygon_b << se_point + OpenStudio::Vector3d.new(- actual_perim, 0, 0)
|
695
|
+
polygon_b << sw_point + OpenStudio::Vector3d.new(actual_perim, 0, 0)
|
696
|
+
polygon_b << nw_point + OpenStudio::Vector3d.new(actual_perim, 0, 0)
|
697
|
+
polygon_b << ne_point + OpenStudio::Vector3d.new(- actual_perim, 0, 0)
|
698
|
+
if double_loaded_corridor
|
699
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"] = {}
|
700
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"][:space_type] = core_space_type
|
701
|
+
hash_of_point_vectors["#{core_space_type.name} B #{k}"][:polygon] = polygon_b
|
702
|
+
else
|
703
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"] = {}
|
704
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"][:space_type] = space_type
|
705
|
+
hash_of_point_vectors["#{space_type.name} B #{k}"][:polygon] = polygon_b
|
706
|
+
end
|
707
|
+
|
708
|
+
polygon_c = OpenStudio::Point3dVector.new
|
709
|
+
polygon_c << sw_point + OpenStudio::Vector3d.new(actual_perim, 0, 0)
|
710
|
+
polygon_c << sw_point
|
711
|
+
polygon_c << nw_point
|
712
|
+
polygon_c << nw_point + OpenStudio::Vector3d.new(actual_perim, 0, 0)
|
713
|
+
if double_loaded_corridor
|
714
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"] = {}
|
715
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"][:space_type] = perim_space_type
|
716
|
+
hash_of_point_vectors["#{perim_space_type.name} C #{k}"][:polygon] = polygon_c
|
717
|
+
else
|
718
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"] = {}
|
719
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"][:space_type] = space_type
|
720
|
+
hash_of_point_vectors["#{space_type.name} C #{k}"][:polygon] = polygon_c
|
721
|
+
end
|
722
|
+
else
|
723
|
+
polygon_a = OpenStudio::Point3dVector.new
|
724
|
+
polygon_a << se_point
|
725
|
+
polygon_a << sw_point
|
726
|
+
polygon_a << nw_point
|
727
|
+
polygon_a << ne_point
|
728
|
+
hash_of_point_vectors["#{space_type.name} #{k}"] = {}
|
729
|
+
hash_of_point_vectors["#{space_type.name} #{k}"][:space_type] = space_type
|
730
|
+
hash_of_point_vectors["#{space_type.name} #{k}"][:polygon] = polygon_a
|
731
|
+
end
|
732
|
+
|
733
|
+
# update west points
|
734
|
+
sw_point = nw_point
|
735
|
+
se_point = ne_point
|
736
|
+
|
737
|
+
end
|
572
738
|
end
|
573
739
|
end
|
574
740
|
|
@@ -592,13 +758,24 @@ module OsLib_Geometry
|
|
592
758
|
end
|
593
759
|
end
|
594
760
|
|
761
|
+
# hash of new spaces (only change boundary conditions for these)
|
762
|
+
new_spaces = []
|
763
|
+
|
595
764
|
# loop through story_hash and polygons to generate all of the spaces
|
596
765
|
story_hash.each_with_index do |(story_name, story_data), index|
|
597
|
-
# make new story
|
598
|
-
story =
|
599
|
-
|
600
|
-
|
601
|
-
|
766
|
+
# make new story unless story at requested height already exists.
|
767
|
+
story = nil
|
768
|
+
model.getBuildingStorys.each do |ext_story|
|
769
|
+
if (ext_story.nominalZCoordinate.to_f - story_data[:space_origin_z].to_f).abs < 0.01
|
770
|
+
story = ext_story
|
771
|
+
end
|
772
|
+
end
|
773
|
+
if story.nil?
|
774
|
+
story = OpenStudio::Model::BuildingStory.new(model)
|
775
|
+
story.setNominalFloortoFloorHeight(story_data[:space_height]) # not used for anything
|
776
|
+
story.setNominalZCoordinate (story_data[:space_origin_z]) # not used for anything
|
777
|
+
story.setName("Story #{story_name}")
|
778
|
+
end
|
602
779
|
|
603
780
|
# multiplier values for adjacent stories to be altered below as needed
|
604
781
|
multiplier_story_above = 1
|
@@ -647,6 +824,7 @@ module OsLib_Geometry
|
|
647
824
|
|
648
825
|
# make space
|
649
826
|
space = OsLib_Geometry.makeSpaceFromPolygon(model, space_data[:polygon].first, space_data[:polygon], options)
|
827
|
+
new_spaces << space
|
650
828
|
|
651
829
|
# set z origin to proper position
|
652
830
|
space.setZOrigin(story_data[:space_origin_z])
|
@@ -676,7 +854,7 @@ module OsLib_Geometry
|
|
676
854
|
# any changes to wall boundary conditions will be handled by same code that calls this method.
|
677
855
|
# this method doesn't need to know about basements and party walls.
|
678
856
|
|
679
|
-
return
|
857
|
+
return new_spaces
|
680
858
|
end
|
681
859
|
|
682
860
|
# add def to create a space from input, optionally take a name, space type, story and thermal zone.
|
@@ -714,7 +892,7 @@ module OsLib_Geometry
|
|
714
892
|
space.setName(options['name'])
|
715
893
|
end
|
716
894
|
|
717
|
-
if !options['spaceType'].nil?
|
895
|
+
if !options['spaceType'].nil? && options['spaceType'].class.to_s == 'OpenStudio::Model::SpaceType'
|
718
896
|
space.setSpaceType(options['spaceType'])
|
719
897
|
end
|
720
898
|
|