osut 0.2.2 → 0.2.3
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/lib/osut/utils.rb +218 -268
- data/lib/osut/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be4500de4b7207ef0f1bb50342c4f63e12714bf22a17779f928b51adba0b862f
|
4
|
+
data.tar.gz: 3b4aa51dff5771c31fe5edc89d1326555447d2eaa7844b4944ff43b84b01cad2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47c84a2d136ec1b6552436cdcc555469813987485f64a2a4ddfa99788f5ee1d5b99d4b369b50766652b028f39204d3efccf7793276400e256d81492bbb85127f
|
7
|
+
data.tar.gz: af28329f47ff40ac971ec3b9333c0e21cb0ef293f1c2697aeebe96d0009acba34696a1f43c9bf07828b854ae8bd110b95b295bcb849dc8e0ff3e21236e4de308
|
data/lib/osut/utils.rb
CHANGED
@@ -35,12 +35,12 @@ module OSut
|
|
35
35
|
|
36
36
|
TOL = 0.01
|
37
37
|
TOL2 = TOL * TOL
|
38
|
-
NS = "nameString" # OpenStudio IdfObject nameString method
|
39
38
|
DBG = OSut::DEBUG # mainly to flag invalid arguments to devs (buggy code)
|
40
39
|
INF = OSut::INFO # not currently used in OSut
|
41
40
|
WRN = OSut::WARN # WARN users of 'iffy' .osm inputs (yet not critical)
|
42
41
|
ERR = OSut::ERROR # flag invalid .osm inputs (then exit via 'return')
|
43
42
|
FTL = OSut::FATAL # not currently used in OSut
|
43
|
+
NS = "nameString" # OpenStudio IdfObject nameString method
|
44
44
|
|
45
45
|
# This first set of utilities (~750 lines) help distinguishing spaces that
|
46
46
|
# are directly vs indirectly CONDITIONED, vs SEMI-HEATED. The solution here
|
@@ -127,7 +127,7 @@ module OSut
|
|
127
127
|
#
|
128
128
|
# @return [Hash] min: (Float), max: (Float)
|
129
129
|
# @return [Hash] min: nil, max: nil (if invalid input)
|
130
|
-
def scheduleRulesetMinMax(sched)
|
130
|
+
def scheduleRulesetMinMax(sched = nil)
|
131
131
|
# Largely inspired from David Goldwasser's
|
132
132
|
# "schedule_ruleset_annual_min_max_value":
|
133
133
|
#
|
@@ -138,7 +138,7 @@ module OSut
|
|
138
138
|
cl = OpenStudio::Model::ScheduleRuleset
|
139
139
|
res = { min: nil, max: nil }
|
140
140
|
|
141
|
-
return invalid("sched", mth, 1, DBG, res)
|
141
|
+
return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
|
142
142
|
id = sched.nameString
|
143
143
|
return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
|
144
144
|
|
@@ -148,11 +148,11 @@ module OSut
|
|
148
148
|
|
149
149
|
profiles.each do |profile|
|
150
150
|
id = profile.nameString
|
151
|
+
|
151
152
|
profile.values.each do |val|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
end
|
153
|
+
ok = val.is_a?(Numeric)
|
154
|
+
log(WRN, "Skipping non-numeric value in '#{id}' (#{mth})") unless ok
|
155
|
+
next unless ok
|
156
156
|
|
157
157
|
res[:min] = val unless res[:min]
|
158
158
|
res[:min] = val if res[:min] > val
|
@@ -174,7 +174,7 @@ module OSut
|
|
174
174
|
#
|
175
175
|
# @return [Hash] min: (Float), max: (Float)
|
176
176
|
# @return [Hash] min: nil, max: nil (if invalid input)
|
177
|
-
def scheduleConstantMinMax(sched)
|
177
|
+
def scheduleConstantMinMax(sched = nil)
|
178
178
|
# Largely inspired from David Goldwasser's
|
179
179
|
# "schedule_constant_annual_min_max_value":
|
180
180
|
#
|
@@ -185,16 +185,14 @@ module OSut
|
|
185
185
|
cl = OpenStudio::Model::ScheduleConstant
|
186
186
|
res = { min: nil, max: nil }
|
187
187
|
|
188
|
-
return invalid("sched", mth, 1, DBG, res)
|
188
|
+
return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
|
189
189
|
id = sched.nameString
|
190
190
|
return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
|
191
191
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
res[:max] = sched.value
|
197
|
-
end
|
192
|
+
valid = sched.value.is_a?(Numeric)
|
193
|
+
mismatch("'#{id}' value", sched.value, Numeric, mth, ERR, res) unless valid
|
194
|
+
res[:min] = sched.value
|
195
|
+
res[:max] = sched.value
|
198
196
|
|
199
197
|
res
|
200
198
|
end
|
@@ -206,7 +204,7 @@ module OSut
|
|
206
204
|
#
|
207
205
|
# @return [Hash] min: (Float), max: (Float)
|
208
206
|
# @return [Hash] min: nil, max: nil (if invalid input)
|
209
|
-
def scheduleCompactMinMax(sched)
|
207
|
+
def scheduleCompactMinMax(sched = nil)
|
210
208
|
# Largely inspired from Andrew Parker's
|
211
209
|
# "schedule_compact_annual_min_max_value":
|
212
210
|
#
|
@@ -219,7 +217,7 @@ module OSut
|
|
219
217
|
prev_str = ""
|
220
218
|
res = { min: nil, max: nil }
|
221
219
|
|
222
|
-
return invalid("sched", mth, 1, DBG, res)
|
220
|
+
return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
|
223
221
|
id = sched.nameString
|
224
222
|
return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
|
225
223
|
|
@@ -233,13 +231,11 @@ module OSut
|
|
233
231
|
end
|
234
232
|
|
235
233
|
return empty("'#{id}' values", mth, ERR, res) if vals.empty?
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
log(ERR, "Non-numeric values in '#{id}' (#{mth})")
|
242
|
-
end
|
234
|
+
ok = vals.min.is_a?(Numeric) && vals.max.is_a?(Numeric)
|
235
|
+
log(ERR, "Non-numeric values in '#{id}' (#{mth})") unless ok
|
236
|
+
return res unless ok
|
237
|
+
res[:min] = vals.min
|
238
|
+
res[:max] = vals.max
|
243
239
|
|
244
240
|
res
|
245
241
|
end
|
@@ -251,24 +247,22 @@ module OSut
|
|
251
247
|
#
|
252
248
|
# @return [Hash] min: (Float), max: (Float)
|
253
249
|
# @return [Hash] min: nil, max: nil (if invalid input)
|
254
|
-
def scheduleIntervalMinMax(sched)
|
250
|
+
def scheduleIntervalMinMax(sched = nil)
|
255
251
|
mth = "OSut::#{__callee__}"
|
256
252
|
cl = OpenStudio::Model::ScheduleInterval
|
257
253
|
vals = []
|
258
254
|
prev_str = ""
|
259
255
|
res = { min: nil, max: nil }
|
260
256
|
|
261
|
-
return invalid("sched", mth, 1, DBG, res)
|
257
|
+
return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
|
262
258
|
id = sched.nameString
|
263
259
|
return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
|
264
|
-
|
265
260
|
vals = sched.timeSeries.values
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
end
|
261
|
+
ok = vals.min.is_a?(Numeric) && vals.max.is_a?(Numeric)
|
262
|
+
log(ERR, "Non-numeric values in '#{id}' (#{mth})") unless ok
|
263
|
+
return res unless ok
|
264
|
+
res[:min] = vals.min
|
265
|
+
res[:max] = vals.max
|
272
266
|
|
273
267
|
res
|
274
268
|
end
|
@@ -281,7 +275,7 @@ module OSut
|
|
281
275
|
#
|
282
276
|
# @return [Hash] spt: (Float), dual: (Bool)
|
283
277
|
# @return [Hash] spt: nil, dual: false (if invalid input)
|
284
|
-
def maxHeatScheduledSetpoint(zone)
|
278
|
+
def maxHeatScheduledSetpoint(zone = nil)
|
285
279
|
# Largely inspired from Parker & Marrec's "thermal_zone_heated?" procedure.
|
286
280
|
# The solution here is a tad more relaxed to encompass SEMI-HEATED zones as
|
287
281
|
# per Canadian NECB criteria (basically any space with at least 10 W/m2 of
|
@@ -294,7 +288,7 @@ module OSut
|
|
294
288
|
cl = OpenStudio::Model::ThermalZone
|
295
289
|
res = { spt: nil, dual: false }
|
296
290
|
|
297
|
-
return invalid("zone", mth, 1, DBG, res)
|
291
|
+
return invalid("zone", mth, 1, DBG, res) unless zone.respond_to?(NS)
|
298
292
|
id = zone.nameString
|
299
293
|
return mismatch(id, zone, cl, mth, DBG, res) unless zone.is_a?(cl)
|
300
294
|
|
@@ -310,9 +304,16 @@ module OSut
|
|
310
304
|
end
|
311
305
|
end
|
312
306
|
|
307
|
+
# unless equip.to_ZoneHVACLowTemperatureRadiantElectric.empty?
|
308
|
+
# equip = equip.to_ZoneHVACLowTemperatureRadiantElectric.get
|
309
|
+
#
|
310
|
+
# unless equip.heatingSetpointTemperatureSchedule.empty?
|
311
|
+
# sched = equip.heatingSetpointTemperatureSchedule.get
|
312
|
+
# end
|
313
|
+
# end
|
314
|
+
|
313
315
|
unless equip.to_ZoneHVACLowTemperatureRadiantElectric.empty?
|
314
316
|
equip = equip.to_ZoneHVACLowTemperatureRadiantElectric.get
|
315
|
-
|
316
317
|
unless equip.heatingSetpointTemperatureSchedule.empty?
|
317
318
|
sched = equip.heatingSetpointTemperatureSchedule.get
|
318
319
|
end
|
@@ -377,13 +378,12 @@ module OSut
|
|
377
378
|
end
|
378
379
|
end
|
379
380
|
|
380
|
-
return res if res[:spt]
|
381
381
|
return res if zone.thermostat.empty?
|
382
|
-
tstat
|
382
|
+
tstat = zone.thermostat.get
|
383
|
+
res[:spt] = nil
|
383
384
|
|
384
385
|
unless tstat.to_ThermostatSetpointDualSetpoint.empty? &&
|
385
386
|
tstat.to_ZoneControlThermostatStagedDualSetpoint.empty?
|
386
|
-
res[:dual] = true
|
387
387
|
|
388
388
|
unless tstat.to_ThermostatSetpointDualSetpoint.empty?
|
389
389
|
tstat = tstat.to_ThermostatSetpointDualSetpoint.get
|
@@ -392,7 +392,8 @@ module OSut
|
|
392
392
|
end
|
393
393
|
|
394
394
|
unless tstat.heatingSetpointTemperatureSchedule.empty?
|
395
|
-
|
395
|
+
res[:dual] = true
|
396
|
+
sched = tstat.heatingSetpointTemperatureSchedule.get
|
396
397
|
|
397
398
|
unless sched.to_ScheduleRuleset.empty?
|
398
399
|
sched = sched.to_ScheduleRuleset.get
|
@@ -456,11 +457,10 @@ module OSut
|
|
456
457
|
#
|
457
458
|
# @return [Bool] true if valid heating temperature setpoints
|
458
459
|
# @return [Bool] false if invalid input
|
459
|
-
def heatingTemperatureSetpoints?(model)
|
460
|
+
def heatingTemperatureSetpoints?(model = nil)
|
460
461
|
mth = "OSut::#{__callee__}"
|
461
|
-
cl
|
462
|
+
cl = OpenStudio::Model::Model
|
462
463
|
|
463
|
-
return invalid("model", mth, 1, DBG, false) unless model
|
464
464
|
return mismatch("model", model, cl, mth, DBG, false) unless model.is_a?(cl)
|
465
465
|
|
466
466
|
model.getThermalZones.each do |zone|
|
@@ -478,7 +478,7 @@ module OSut
|
|
478
478
|
#
|
479
479
|
# @return [Hash] spt: (Float), dual: (Bool)
|
480
480
|
# @return [Hash] spt: nil, dual: false (if invalid input)
|
481
|
-
def minCoolScheduledSetpoint(zone)
|
481
|
+
def minCoolScheduledSetpoint(zone = nil)
|
482
482
|
# Largely inspired from Parker & Marrec's "thermal_zone_cooled?" procedure.
|
483
483
|
#
|
484
484
|
# github.com/NREL/openstudio-standards/blob/
|
@@ -488,7 +488,7 @@ module OSut
|
|
488
488
|
cl = OpenStudio::Model::ThermalZone
|
489
489
|
res = { spt: nil, dual: false }
|
490
490
|
|
491
|
-
return invalid("zone", mth, 1, DBG, res)
|
491
|
+
return invalid("zone", mth, 1, DBG, res) unless zone.respond_to?(NS)
|
492
492
|
id = zone.nameString
|
493
493
|
return mismatch(id, zone, cl, mth, DBG, res) unless zone.is_a?(cl)
|
494
494
|
|
@@ -555,13 +555,12 @@ module OSut
|
|
555
555
|
end
|
556
556
|
end
|
557
557
|
|
558
|
-
return res if res[:spt]
|
559
558
|
return res if zone.thermostat.empty?
|
560
|
-
tstat
|
559
|
+
tstat = zone.thermostat.get
|
560
|
+
res[:spt] = nil
|
561
561
|
|
562
562
|
unless tstat.to_ThermostatSetpointDualSetpoint.empty? &&
|
563
563
|
tstat.to_ZoneControlThermostatStagedDualSetpoint.empty?
|
564
|
-
res[:dual] = true
|
565
564
|
|
566
565
|
unless tstat.to_ThermostatSetpointDualSetpoint.empty?
|
567
566
|
tstat = tstat.to_ThermostatSetpointDualSetpoint.get
|
@@ -570,7 +569,8 @@ module OSut
|
|
570
569
|
end
|
571
570
|
|
572
571
|
unless tstat.coolingSetpointTemperatureSchedule.empty?
|
573
|
-
|
572
|
+
res[:dual] = true
|
573
|
+
sched = tstat.coolingSetpointTemperatureSchedule.get
|
574
574
|
|
575
575
|
unless sched.to_ScheduleRuleset.empty?
|
576
576
|
sched = sched.to_ScheduleRuleset.get
|
@@ -634,11 +634,10 @@ module OSut
|
|
634
634
|
#
|
635
635
|
# @return [Bool] true if valid cooling temperature setpoints
|
636
636
|
# @return [Bool] false if invalid input
|
637
|
-
def coolingTemperatureSetpoints?(model)
|
637
|
+
def coolingTemperatureSetpoints?(model = nil)
|
638
638
|
mth = "OSut::#{__callee__}"
|
639
|
-
cl
|
639
|
+
cl = OpenStudio::Model::Model
|
640
640
|
|
641
|
-
return invalid("model", mth, 1, DBG, false) unless model
|
642
641
|
return mismatch("model", model, cl, mth, DBG, false) unless model.is_a?(cl)
|
643
642
|
|
644
643
|
model.getThermalZones.each do |zone|
|
@@ -655,11 +654,10 @@ module OSut
|
|
655
654
|
#
|
656
655
|
# @return [Bool] true if model has one or more HVAC air loops
|
657
656
|
# @return [Bool] false if invalid input
|
658
|
-
def airLoopsHVAC?(model)
|
657
|
+
def airLoopsHVAC?(model = nil)
|
659
658
|
mth = "OSut::#{__callee__}"
|
660
|
-
cl
|
659
|
+
cl = OpenStudio::Model::Model
|
661
660
|
|
662
|
-
return invalid("model", mth, 1, DBG, false) unless model
|
663
661
|
return mismatch("model", model, cl, mth, DBG, false) unless model.is_a?(cl)
|
664
662
|
|
665
663
|
model.getThermalZones.each do |zone|
|
@@ -680,68 +678,59 @@ module OSut
|
|
680
678
|
#
|
681
679
|
# @return [Bool] true if should be tagged as plenum
|
682
680
|
# @return [Bool] false if invalid input
|
683
|
-
def plenum?(space, loops, setpoints)
|
681
|
+
def plenum?(space = nil, loops = nil, setpoints = nil)
|
684
682
|
# Largely inspired from NREL's "space_plenum?" procedure:
|
685
683
|
#
|
686
684
|
# github.com/NREL/openstudio-standards/blob/
|
687
685
|
# 58964222d25783e9da4ae292e375fb0d5c902aa5/lib/openstudio-standards/
|
688
686
|
# standards/Standards.Space.rb#L1384
|
689
|
-
|
687
|
+
#
|
690
688
|
# A space may be tagged as a plenum if:
|
691
689
|
#
|
692
690
|
# CASE A: its zone's "isPlenum" == true (SDK method) for a fully-developed
|
693
691
|
# OpenStudio model (complete with HVAC air loops);
|
694
692
|
#
|
695
|
-
# CASE B: it's excluded from building's
|
696
|
-
# zone holding an
|
697
|
-
# valid setpoints
|
698
|
-
#
|
699
|
-
# CASE C: it has a spacetype whose name holds "plenum", or a spacetype with
|
700
|
-
# a 'standards spacetype' holding "plenum" (case insensitive); OR
|
693
|
+
# CASE B: (IN ABSENCE OF HVAC AIRLOOPS) if it's excluded from a building's
|
694
|
+
# total floor area yet linked to a zone holding an 'inactive'
|
695
|
+
# thermostat, i.e. can't extract valid setpoints; OR
|
701
696
|
#
|
702
|
-
# CASE
|
703
|
-
|
697
|
+
# CASE C: (IN ABSENCE OF HVAC AIRLOOPS & VALID SETPOINTS) it has "plenum"
|
698
|
+
# (case insensitive) as a spacetype (or as a spacetype's
|
699
|
+
# 'standards spacetype').
|
704
700
|
mth = "OSut::#{__callee__}"
|
705
701
|
cl = OpenStudio::Model::Space
|
706
702
|
|
707
|
-
return invalid("space", mth, 1, DBG, false)
|
703
|
+
return invalid("space", mth, 1, DBG, false) unless space.respond_to?(NS)
|
708
704
|
id = space.nameString
|
709
705
|
return mismatch(id, space, cl, mth, DBG, false) unless space.is_a?(cl)
|
710
|
-
|
711
706
|
valid = loops == true || loops == false
|
712
|
-
return invalid("loops", mth, 2, DBG, false)
|
713
|
-
|
707
|
+
return invalid("loops", mth, 2, DBG, false) unless valid
|
714
708
|
valid = setpoints == true || setpoints == false
|
715
709
|
return invalid("setpoints", mth, 3, DBG, false) unless valid
|
716
710
|
|
717
711
|
unless space.thermalZone.empty?
|
718
712
|
zone = space.thermalZone.get
|
719
|
-
return
|
713
|
+
return zone.isPlenum if loops # A
|
720
714
|
|
721
715
|
if setpoints
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
return
|
726
|
-
|
727
|
-
unless space.partofTotalFloorArea
|
728
|
-
return true if heating[:dual] || cooling[:dual] # CASE B
|
729
|
-
end
|
716
|
+
heat = maxHeatScheduledSetpoint(zone)
|
717
|
+
cool = minCoolScheduledSetpoint(zone)
|
718
|
+
return false if heat[:spt] || cool[:spt] # directly conditioned
|
719
|
+
return heat[:dual] || cool[:dual] unless space.partofTotalFloorArea # B
|
720
|
+
return false
|
730
721
|
end
|
731
722
|
end
|
732
723
|
|
733
724
|
unless space.spaceType.empty?
|
734
725
|
type = space.spaceType.get
|
735
|
-
return
|
726
|
+
return type.nameString.downcase == "plenum" # C
|
736
727
|
|
737
728
|
unless type.standardsSpaceType.empty?
|
738
729
|
type = type.standardsSpaceType.get
|
739
|
-
return
|
730
|
+
return type.downcase == "plenum" # C
|
740
731
|
end
|
741
732
|
end
|
742
733
|
|
743
|
-
return true if space.nameString.downcase.include?("plenum")
|
744
|
-
|
745
734
|
false
|
746
735
|
end
|
747
736
|
|
@@ -752,17 +741,16 @@ module OSut
|
|
752
741
|
# @param avl [String] seasonal availability choice (optional, default "ON")
|
753
742
|
#
|
754
743
|
# @return [OpenStudio::Model::Schedule] HVAC availability sched
|
755
|
-
# @return [
|
756
|
-
def availabilitySchedule(model, avl = "")
|
757
|
-
mth
|
758
|
-
cl
|
744
|
+
# @return [NilClass] if invalid input
|
745
|
+
def availabilitySchedule(model = nil, avl = "")
|
746
|
+
mth = "OSut::#{__callee__}"
|
747
|
+
cl = OpenStudio::Model::Model
|
748
|
+
limits = nil
|
759
749
|
|
760
|
-
return
|
761
|
-
return
|
750
|
+
return mismatch("model", model, cl, mth) unless model.is_a?(cl)
|
751
|
+
return invalid("availability", avl, 2, mth) unless avl.respond_to?(:to_s)
|
762
752
|
|
763
753
|
# Either fetch availability ScheduleTypeLimits object, or create one.
|
764
|
-
limits = nil
|
765
|
-
|
766
754
|
model.getScheduleTypeLimitss.each do |l|
|
767
755
|
break if limits
|
768
756
|
next if l.lowerLimitValue.empty?
|
@@ -797,7 +785,7 @@ module OSut
|
|
797
785
|
may01 = year.makeDate(OpenStudio::MonthOfYear.new("May"), 1)
|
798
786
|
oct31 = year.makeDate(OpenStudio::MonthOfYear.new("Oct"), 31)
|
799
787
|
|
800
|
-
case avl.downcase
|
788
|
+
case avl.to_s.downcase
|
801
789
|
when "winter" # available from November 1 to April 30 (6 months)
|
802
790
|
val = 1
|
803
791
|
sch = off
|
@@ -838,29 +826,29 @@ module OSut
|
|
838
826
|
unless schedule.empty?
|
839
827
|
schedule = schedule.get
|
840
828
|
default = schedule.defaultDaySchedule
|
841
|
-
ok = ok && default.nameString
|
842
|
-
ok = ok && default.times.size
|
843
|
-
ok = ok && default.values.size
|
844
|
-
ok = ok && default.times.first
|
845
|
-
ok = ok && default.values.first
|
829
|
+
ok = ok && default.nameString == dft
|
830
|
+
ok = ok && default.times.size == 1
|
831
|
+
ok = ok && default.values.size == 1
|
832
|
+
ok = ok && default.times.first == time
|
833
|
+
ok = ok && default.values.first == val
|
846
834
|
rules = schedule.scheduleRules
|
847
835
|
ok = ok && (rules.size == 0 || rules.size == 1)
|
848
836
|
|
849
837
|
if rules.size == 1
|
850
838
|
rule = rules.first
|
851
|
-
ok = ok && rule.nameString
|
839
|
+
ok = ok && rule.nameString == tag
|
852
840
|
ok = ok && !rule.startDate.empty?
|
853
841
|
ok = ok && !rule.endDate.empty?
|
854
|
-
ok = ok && rule.startDate.get
|
855
|
-
ok = ok && rule.endDate.get
|
842
|
+
ok = ok && rule.startDate.get == may01
|
843
|
+
ok = ok && rule.endDate.get == oct31
|
856
844
|
ok = ok && rule.applyAllDays
|
857
845
|
|
858
846
|
d = rule.daySchedule
|
859
|
-
ok = ok && d.nameString
|
860
|
-
ok = ok && d.times.size
|
861
|
-
ok = ok && d.values.size
|
847
|
+
ok = ok && d.nameString == day
|
848
|
+
ok = ok && d.times.size == 1
|
849
|
+
ok = ok && d.values.size == 1
|
862
850
|
ok = ok && d.times.first.totalSeconds == secs
|
863
|
-
ok = ok && d.values.first.to_i
|
851
|
+
ok = ok && d.values.first.to_i != val
|
864
852
|
end
|
865
853
|
|
866
854
|
return schedule if ok
|
@@ -869,38 +857,26 @@ module OSut
|
|
869
857
|
|
870
858
|
schedule = OpenStudio::Model::ScheduleRuleset.new(model)
|
871
859
|
schedule.setName(nom)
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
unless schedule.defaultDaySchedule.addValue(time, val)
|
879
|
-
log(ERR, "'#{nom}': Can't set default day schedule (#{mth})")
|
880
|
-
return nil
|
881
|
-
end
|
882
|
-
|
860
|
+
ok = schedule.setScheduleTypeLimits(limits)
|
861
|
+
log(ERR, "'#{nom}': Can't set schedule type limits (#{mth})") unless ok
|
862
|
+
return nil unless ok
|
863
|
+
ok = schedule.defaultDaySchedule.addValue(time, val)
|
864
|
+
log(ERR, "'#{nom}': Can't set default day schedule (#{mth})") unless ok
|
865
|
+
return nil unless ok
|
883
866
|
schedule.defaultDaySchedule.setName(dft)
|
884
867
|
|
885
868
|
unless tag.empty?
|
886
869
|
rule = OpenStudio::Model::ScheduleRule.new(schedule, sch)
|
887
870
|
rule.setName(tag)
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
end
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
end
|
898
|
-
|
899
|
-
unless rule.setApplyAllDays(true)
|
900
|
-
log(ERR, "'#{tag}': Can't apply to all days (#{mth})")
|
901
|
-
return nil
|
902
|
-
end
|
903
|
-
|
871
|
+
ok = rule.setStartDate(may01)
|
872
|
+
log(ERR, "'#{tag}': Can't set start date (#{mth})") unless ok
|
873
|
+
return nil unless ok
|
874
|
+
ok = rule.setEndDate(oct31)
|
875
|
+
log(ERR, "'#{tag}': Can't set end date (#{mth})") unless ok
|
876
|
+
return nil unless ok
|
877
|
+
ok = rule.setApplyAllDays(true)
|
878
|
+
log(ERR, "'#{tag}': Can't apply to all days (#{mth})") unless ok
|
879
|
+
return nil unless ok
|
904
880
|
rule.daySchedule.setName(day)
|
905
881
|
end
|
906
882
|
|
@@ -911,43 +887,41 @@ module OSut
|
|
911
887
|
# Validate if default construction set holds a base ground construction.
|
912
888
|
#
|
913
889
|
# @param set [OpenStudio::Model::DefaultConstructionSet] a default set
|
914
|
-
# @param
|
915
|
-
# @param
|
916
|
-
# @param
|
917
|
-
# @param
|
890
|
+
# @param bse [OpensStudio::Model::ConstructionBase] a construction base
|
891
|
+
# @param gr [Bool] true if ground-facing surface
|
892
|
+
# @param ex [Bool] true if exterior-facing surface
|
893
|
+
# @param typ [String] a surface type
|
918
894
|
#
|
919
895
|
# @return [Bool] true if default construction set holds construction
|
920
896
|
# @return [Bool] false if invalid input
|
921
|
-
def holdsConstruction?(set,
|
897
|
+
def holdsConstruction?(set = nil, bse = nil, gr = false, ex = false, typ = "")
|
922
898
|
mth = "OSut::#{__callee__}"
|
923
899
|
cl1 = OpenStudio::Model::DefaultConstructionSet
|
924
900
|
cl2 = OpenStudio::Model::ConstructionBase
|
925
901
|
|
926
|
-
return invalid("set", mth, 1, DBG, false)
|
902
|
+
return invalid("set", mth, 1, DBG, false) unless set.respond_to?(NS)
|
927
903
|
id = set.nameString
|
928
|
-
return mismatch(id, set, cl1, mth, DBG, false)
|
929
|
-
|
930
|
-
|
931
|
-
id
|
932
|
-
|
933
|
-
|
934
|
-
valid =
|
935
|
-
return invalid("
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
typ = type.to_s.downcase
|
941
|
-
valid = typ == "floor" || typ == "wall" || typ == "roofceiling"
|
904
|
+
return mismatch(id, set, cl1, mth, DBG, false) unless set.is_a?(cl1)
|
905
|
+
return invalid("base", mth, 2, DBG, false) unless bse.respond_to?(NS)
|
906
|
+
id = bse.nameString
|
907
|
+
return mismatch(id, bse, cl2, mth, DBG, false) unless bse.is_a?(cl2)
|
908
|
+
valid = gr == true || gr == false
|
909
|
+
return invalid("ground", mth, 3, DBG, false) unless valid
|
910
|
+
valid = ex == true || ex == false
|
911
|
+
return invalid("exterior", mth, 4, DBG, false) unless valid
|
912
|
+
valid = typ.respond_to?(:to_s)
|
913
|
+
return invalid("surface typ", mth, 4, DBG, false) unless valid
|
914
|
+
type = typ.to_s.downcase
|
915
|
+
valid = type == "floor" || type == "wall" || type == "roofceiling"
|
942
916
|
return invalid("surface type", mth, 5, DBG, false) unless valid
|
943
917
|
|
944
918
|
constructions = nil
|
945
919
|
|
946
|
-
if
|
920
|
+
if gr
|
947
921
|
unless set.defaultGroundContactSurfaceConstructions.empty?
|
948
922
|
constructions = set.defaultGroundContactSurfaceConstructions.get
|
949
923
|
end
|
950
|
-
elsif
|
924
|
+
elsif ex
|
951
925
|
unless set.defaultExteriorSurfaceConstructions.empty?
|
952
926
|
constructions = set.defaultExteriorSurfaceConstructions.get
|
953
927
|
end
|
@@ -959,21 +933,21 @@ module OSut
|
|
959
933
|
|
960
934
|
return false unless constructions
|
961
935
|
|
962
|
-
case
|
936
|
+
case type
|
963
937
|
when "roofceiling"
|
964
938
|
unless constructions.roofCeilingConstruction.empty?
|
965
939
|
construction = constructions.roofCeilingConstruction.get
|
966
|
-
return true if construction ==
|
940
|
+
return true if construction == bse
|
967
941
|
end
|
968
942
|
when "floor"
|
969
943
|
unless constructions.floorConstruction.empty?
|
970
944
|
construction = constructions.floorConstruction.get
|
971
|
-
return true if construction ==
|
945
|
+
return true if construction == bse
|
972
946
|
end
|
973
947
|
else
|
974
948
|
unless constructions.wallConstruction.empty?
|
975
949
|
construction = constructions.wallConstruction.get
|
976
|
-
return true if construction ==
|
950
|
+
return true if construction == bse
|
977
951
|
end
|
978
952
|
end
|
979
953
|
|
@@ -987,30 +961,25 @@ module OSut
|
|
987
961
|
# @param s [OpenStudio::Model::Surface] a surface
|
988
962
|
#
|
989
963
|
# @return [OpenStudio::Model::DefaultConstructionSet] default set
|
990
|
-
# @return [
|
991
|
-
def defaultConstructionSet(model, s)
|
964
|
+
# @return [NilClass] if invalid input
|
965
|
+
def defaultConstructionSet(model = nil, s = nil)
|
992
966
|
mth = "OSut::#{__callee__}"
|
993
967
|
cl1 = OpenStudio::Model::Model
|
994
968
|
cl2 = OpenStudio::Model::Surface
|
995
969
|
|
996
|
-
return invalid("model", mth, 1) unless model
|
997
970
|
return mismatch("model", model, cl1, mth) unless model.is_a?(cl1)
|
998
|
-
|
999
|
-
return invalid("s", mth, 2) unless s.respond_to?(NS)
|
971
|
+
return invalid("s", mth, 2) unless s.respond_to?(NS)
|
1000
972
|
id = s.nameString
|
1001
|
-
return mismatch(id, s, cl2, mth)
|
1002
|
-
|
1003
|
-
unless s.isConstructionDefaulted
|
1004
|
-
log(ERR, "'#{id}' construction not defaulted (#{mth})")
|
1005
|
-
return nil
|
1006
|
-
end
|
973
|
+
return mismatch(id, s, cl2, mth) unless s.is_a?(cl2)
|
1007
974
|
|
975
|
+
ok = s.isConstructionDefaulted
|
976
|
+
log(ERR, "'#{id}' construction not defaulted (#{mth})") unless ok
|
977
|
+
return nil unless ok
|
1008
978
|
return empty("'#{id}' construction", mth, ERR) if s.construction.empty?
|
1009
979
|
base = s.construction.get
|
1010
980
|
return empty("'#{id}' space", mth, ERR) if s.space.empty?
|
1011
981
|
space = s.space.get
|
1012
982
|
type = s.surfaceType
|
1013
|
-
|
1014
983
|
ground = false
|
1015
984
|
exterior = false
|
1016
985
|
|
@@ -1060,7 +1029,7 @@ module OSut
|
|
1060
1029
|
#
|
1061
1030
|
# @return [Bool] true if all layers are valid
|
1062
1031
|
# @return [Bool] false if invalid input
|
1063
|
-
def standardOpaqueLayers?(lc)
|
1032
|
+
def standardOpaqueLayers?(lc = nil)
|
1064
1033
|
mth = "OSut::#{__callee__}"
|
1065
1034
|
cl = OpenStudio::Model::LayeredConstruction
|
1066
1035
|
|
@@ -1068,6 +1037,7 @@ module OSut
|
|
1068
1037
|
return mismatch(lc.nameString, lc, cl, mth, DBG, false) unless lc.is_a?(cl)
|
1069
1038
|
|
1070
1039
|
lc.layers.each { |m| return false if m.to_StandardOpaqueMaterial.empty? }
|
1040
|
+
|
1071
1041
|
true
|
1072
1042
|
end
|
1073
1043
|
|
@@ -1078,21 +1048,20 @@ module OSut
|
|
1078
1048
|
#
|
1079
1049
|
# @return [Double] total layered construction thickness
|
1080
1050
|
# @return [Double] 0 if invalid input
|
1081
|
-
def thickness(lc)
|
1051
|
+
def thickness(lc = nil)
|
1082
1052
|
mth = "OSut::#{__callee__}"
|
1083
1053
|
cl = OpenStudio::Model::LayeredConstruction
|
1084
1054
|
|
1085
|
-
return invalid("lc", mth, 1, DBG, 0)
|
1055
|
+
return invalid("lc", mth, 1, DBG, 0.0) unless lc.respond_to?(NS)
|
1086
1056
|
id = lc.nameString
|
1087
|
-
return mismatch(id, lc, cl, mth, DBG, 0) unless lc.is_a?(cl)
|
1088
|
-
|
1089
|
-
unless standardOpaqueLayers?(lc)
|
1090
|
-
log(ERR, "'#{id}' holds non-StandardOpaqueMaterial(s) (#{mth})")
|
1091
|
-
return 0
|
1092
|
-
end
|
1057
|
+
return mismatch(id, lc, cl, mth, DBG, 0.0) unless lc.is_a?(cl)
|
1093
1058
|
|
1059
|
+
ok = standardOpaqueLayers?(lc)
|
1060
|
+
log(ERR, "'#{id}' holds non-StandardOpaqueMaterial(s) (#{mth})") unless ok
|
1061
|
+
return 0.0 unless ok
|
1094
1062
|
thickness = 0.0
|
1095
1063
|
lc.layers.each { |m| thickness += m.thickness }
|
1064
|
+
|
1096
1065
|
thickness
|
1097
1066
|
end
|
1098
1067
|
|
@@ -1122,11 +1091,12 @@ module OSut
|
|
1122
1091
|
# The EnergyPlus Engineering calculations were designed for vertical windows
|
1123
1092
|
# - not horizontal, slanted or domed surfaces - use with caution.
|
1124
1093
|
mth = "OSut::#{__callee__}"
|
1125
|
-
cl
|
1094
|
+
cl = Numeric
|
1126
1095
|
|
1127
|
-
return
|
1128
|
-
return
|
1129
|
-
return
|
1096
|
+
return mismatch("usi", usi, cl, mth, DBG, 0.1216) unless usi.is_a?(cl)
|
1097
|
+
return invalid("usi", mth, 1, WRN, 0.1216) if usi > 8.0
|
1098
|
+
return negative("usi", mth, WRN, 0.1216) if usi < 0
|
1099
|
+
return zero("usi", mth, WRN, 0.1216) if usi.abs < TOL
|
1130
1100
|
|
1131
1101
|
rsi = 1 / (0.025342 * usi + 29.163853) # exterior film, next interior film
|
1132
1102
|
|
@@ -1142,64 +1112,49 @@ module OSut
|
|
1142
1112
|
# @param t [Float] gas temperature (°C) (optional)
|
1143
1113
|
#
|
1144
1114
|
# @return [Float] calculated RSi at standard conditions (0 if error)
|
1145
|
-
def rsi(lc, film, t = 0.0)
|
1115
|
+
def rsi(lc = nil, film = 0.0, t = 0.0)
|
1146
1116
|
# This is adapted from BTAP's Material Module's "get_conductance" (P. Lopez)
|
1147
1117
|
#
|
1148
1118
|
# https://github.com/NREL/OpenStudio-Prototype-Buildings/blob/
|
1149
1119
|
# c3d5021d8b7aef43e560544699fb5c559e6b721d/lib/btap/measures/
|
1150
1120
|
# btap_equest_converter/envelope.rb#L122
|
1151
|
-
|
1152
1121
|
mth = "OSut::#{__callee__}"
|
1153
1122
|
cl1 = OpenStudio::Model::LayeredConstruction
|
1154
1123
|
cl2 = Numeric
|
1155
1124
|
|
1156
|
-
return invalid("lc", mth, 1, DBG, 0)
|
1125
|
+
return invalid("lc", mth, 1, DBG, 0.0) unless lc.respond_to?(NS)
|
1157
1126
|
id = lc.nameString
|
1158
|
-
return mismatch(id, lc, cl1, mth, DBG, 0)
|
1159
|
-
|
1160
|
-
return
|
1161
|
-
|
1162
|
-
|
1163
|
-
return
|
1164
|
-
return mismatch("temperature", t, cl2, mth, DBG, 0) unless t.is_a?(cl2)
|
1165
|
-
|
1166
|
-
tt = t + 273.0 # °C to K
|
1167
|
-
return negative("temp K", mth, DBG, 0) if tt < 0
|
1168
|
-
return negative("film", mth, DBG, 0) if film < 0
|
1127
|
+
return mismatch(id, lc, cl1, mth, DBG, 0.0) unless lc.is_a?(cl1)
|
1128
|
+
return mismatch("film", film, cl2, mth, DBG, 0.0) unless film.is_a?(cl2)
|
1129
|
+
return mismatch("temp K", t, cl2, mth, DBG, 0.0) unless t.is_a?(cl2)
|
1130
|
+
t += 273.0 # °C to K
|
1131
|
+
return negative("temp K", mth, DBG, 0.0) if t < 0
|
1132
|
+
return negative("film", mth, DBG, 0.0) if film < 0
|
1169
1133
|
|
1170
1134
|
rsi = film
|
1171
1135
|
|
1172
1136
|
lc.layers.each do |m|
|
1173
1137
|
# Fenestration materials first (ignoring shades, screens, etc.)
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
rsi += m.to_Gas.get.getThermalResistance(tt)
|
1185
|
-
end
|
1186
|
-
unless m.to_GasMixture.empty?
|
1187
|
-
rsi += m.to_GasMixture.get.getThermalResistance(tt)
|
1188
|
-
end
|
1138
|
+
empty = m.to_SimpleGlazing.empty?
|
1139
|
+
return 1 / m.to_SimpleGlazing.get.uFactor unless empty
|
1140
|
+
empty = m.to_StandardGlazing.empty?
|
1141
|
+
rsi += m.to_StandardGlazing.get.thermalResistance unless empty
|
1142
|
+
empty = m.to_RefractionExtinctionGlazing.empty?
|
1143
|
+
rsi += m.to_RefractionExtinctionGlazing.get.thermalResistance unless empty
|
1144
|
+
empty = m.to_Gas.empty?
|
1145
|
+
rsi += m.to_Gas.get.getThermalResistance(t) unless empty
|
1146
|
+
empty = m.to_GasMixture.empty?
|
1147
|
+
rsi += m.to_GasMixture.get.getThermalResistance(t) unless empty
|
1189
1148
|
|
1190
1149
|
# Opaque materials next.
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
end
|
1200
|
-
unless m.to_AirGap.empty?
|
1201
|
-
rsi += m.to_AirGap.get.thermalResistance
|
1202
|
-
end
|
1150
|
+
empty = m.to_StandardOpaqueMaterial.empty?
|
1151
|
+
rsi += m.to_StandardOpaqueMaterial.get.thermalResistance unless empty
|
1152
|
+
empty = m.to_MasslessOpaqueMaterial.empty?
|
1153
|
+
rsi += m.to_MasslessOpaqueMaterial.get.thermalResistance unless empty
|
1154
|
+
empty = m.to_RoofVegetation.empty?
|
1155
|
+
rsi += m.to_RoofVegetation.get.thermalResistance unless empty
|
1156
|
+
empty = m.to_AirGap.empty?
|
1157
|
+
rsi += m.to_AirGap.get.thermalResistance unless empty
|
1203
1158
|
end
|
1204
1159
|
|
1205
1160
|
rsi
|
@@ -1215,18 +1170,17 @@ module OSut
|
|
1215
1170
|
#
|
1216
1171
|
# @return [Hash] index: (Integer), type: (:standard or :massless), r: (Float)
|
1217
1172
|
# @return [Hash] index: nil, type: nil, r: 0 (if invalid input)
|
1218
|
-
def insulatingLayer(lc)
|
1173
|
+
def insulatingLayer(lc = nil)
|
1219
1174
|
mth = "OSut::#{__callee__}"
|
1220
1175
|
cl = OpenStudio::Model::LayeredConstruction
|
1221
1176
|
res = { index: nil, type: nil, r: 0.0 }
|
1222
1177
|
i = 0 # iterator
|
1223
1178
|
|
1224
|
-
return invalid("lc", mth, 1, DBG, res)
|
1179
|
+
return invalid("lc", mth, 1, DBG, res) unless lc.respond_to?(NS)
|
1225
1180
|
id = lc.nameString
|
1226
1181
|
return mismatch(id, lc, cl1, mth, DBG, res) unless lc.is_a?(cl)
|
1227
1182
|
|
1228
1183
|
lc.layers.each do |m|
|
1229
|
-
|
1230
1184
|
unless m.to_MasslessOpaqueMaterial.empty?
|
1231
1185
|
m = m.to_MasslessOpaqueMaterial.get
|
1232
1186
|
|
@@ -1269,15 +1223,13 @@ module OSut
|
|
1269
1223
|
#
|
1270
1224
|
# @return [Hash] t: (OpenStudio::Transformation), r: Float
|
1271
1225
|
# @return [Hash] t: nil, r: nil (if invalid input)
|
1272
|
-
def transforms(model, group)
|
1226
|
+
def transforms(model = nil, group = nil)
|
1273
1227
|
mth = "OSut::#{__callee__}"
|
1274
1228
|
cl1 = OpenStudio::Model::Model
|
1275
1229
|
cl2 = OpenStudio::Model::PlanarSurfaceGroup
|
1276
1230
|
res = { t: nil, r: nil }
|
1277
1231
|
|
1278
|
-
return invalid("model", mth, 1, DBG, res) unless model
|
1279
1232
|
return mismatch("model", model, cl1, mth, DBG, res) unless model.is_a?(cl1)
|
1280
|
-
|
1281
1233
|
return invalid("group", mth, 2, DBG, res) unless group.respond_to?(NS)
|
1282
1234
|
id = group.nameString
|
1283
1235
|
return mismatch(id, group, cl2, mth, DBG, res) unless group.is_a?(cl2)
|
@@ -1294,16 +1246,14 @@ module OSut
|
|
1294
1246
|
# @param pts [Array] an OpenStudio Point3D array/vector
|
1295
1247
|
#
|
1296
1248
|
# @return [Array] flattened OpenStudio 3D points
|
1297
|
-
def flatZ(pts)
|
1249
|
+
def flatZ(pts = nil)
|
1298
1250
|
mth = "OSut::#{__callee__}"
|
1299
1251
|
cl1 = OpenStudio::Point3dVector
|
1300
1252
|
cl2 = OpenStudio::Point3d
|
1301
|
-
v
|
1253
|
+
v = OpenStudio::Point3dVector.new
|
1302
1254
|
|
1303
|
-
return invalid("points", mth, 1, DBG, v) unless pts
|
1304
1255
|
valid = pts.is_a?(cl1) || pts.is_a?(Array)
|
1305
|
-
return mismatch("points", pts, cl1, mth, DBG, v)
|
1306
|
-
|
1256
|
+
return mismatch("points", pts, cl1, mth, DBG, v) unless valid
|
1307
1257
|
pts.each { |pt| mismatch("pt", pt, cl2, mth, ERR, v) unless pt.is_a?(cl2) }
|
1308
1258
|
pts.each { |pt| v << OpenStudio::Point3d.new(pt.x, pt.y, 0) }
|
1309
1259
|
|
@@ -1320,53 +1270,49 @@ module OSut
|
|
1320
1270
|
#
|
1321
1271
|
# @return [Bool] true if 1st polygon fits entirely within the 2nd polygon
|
1322
1272
|
# @return [Bool] false if invalid input
|
1323
|
-
def fits?(p1, p2, id1 = "", id2 = "")
|
1273
|
+
def fits?(p1 = nil, p2 = nil, id1 = "", id2 = "")
|
1324
1274
|
mth = "OSut::#{__callee__}"
|
1325
1275
|
cl1 = OpenStudio::Point3dVector
|
1326
1276
|
cl2 = OpenStudio::Point3d
|
1327
1277
|
a = false
|
1278
|
+
|
1279
|
+
return invalid("id1", mth, 3, DBG, a) unless id1.respond_to?(:to_s)
|
1280
|
+
return invalid("id2", mth, 4, DBG, a) unless id2.respond_to?(:to_s)
|
1328
1281
|
i1 = id1.to_s
|
1329
1282
|
i2 = id2.to_s
|
1330
1283
|
i1 = "poly1" if i1.empty?
|
1331
1284
|
i2 = "poly2" if i2.empty?
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
return mismatch(
|
1285
|
+
valid1 = p1.is_a?(cl1) || p1.is_a?(Array)
|
1286
|
+
valid2 = p2.is_a?(cl1) || p2.is_a?(Array)
|
1287
|
+
return mismatch(i1, p1, cl1, mth, DBG, a) unless valid1
|
1288
|
+
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid2
|
1336
1289
|
return empty(i1, mth, ERR, a) if p1.empty?
|
1337
|
-
|
1338
|
-
return invalid(i2, mth, 2, DBG, a) unless p2
|
1339
|
-
valid = p2.is_a?(cl1) || p2.is_a?(Array)
|
1340
|
-
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid
|
1341
1290
|
return empty(i2, mth, ERR, a) if p2.empty?
|
1342
|
-
|
1343
1291
|
p1.each { |v| return mismatch(i1, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1344
1292
|
p2.each { |v| return mismatch(i2, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1345
1293
|
|
1346
1294
|
ft = OpenStudio::Transformation::alignFace(p1).inverse
|
1347
|
-
|
1348
1295
|
ft_p1 = flatZ( (ft * p1).reverse )
|
1349
1296
|
return false if ft_p1.empty?
|
1350
1297
|
area1 = OpenStudio::getArea(ft_p1)
|
1351
|
-
return empty(i1, mth, ERR, a) if area1.empty?
|
1298
|
+
return empty("#{i1} area", mth, ERR, a) if area1.empty?
|
1352
1299
|
area1 = area1.get
|
1353
|
-
|
1354
1300
|
ft_p2 = flatZ( (ft * p2).reverse )
|
1355
1301
|
return false if ft_p2.empty?
|
1356
1302
|
area2 = OpenStudio::getArea(ft_p2)
|
1357
|
-
return empty(i2, mth, ERR, a) if area2.empty?
|
1303
|
+
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1358
1304
|
area2 = area2.get
|
1359
|
-
|
1360
1305
|
union = OpenStudio::join(ft_p1, ft_p2, TOL2)
|
1361
1306
|
return false if union.empty?
|
1362
1307
|
union = union.get
|
1363
1308
|
area = OpenStudio::getArea(union)
|
1364
|
-
return empty("union", mth, ERR, a) if area.empty?
|
1309
|
+
return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
|
1365
1310
|
area = area.get
|
1366
1311
|
|
1367
1312
|
return false if area < TOL
|
1368
1313
|
return true if (area - area2).abs < TOL
|
1369
1314
|
return false if (area - area2).abs > TOL
|
1315
|
+
|
1370
1316
|
true
|
1371
1317
|
end
|
1372
1318
|
|
@@ -1380,51 +1326,55 @@ module OSut
|
|
1380
1326
|
#
|
1381
1327
|
# @return Returns true if polygons overlaps (or either fits into the other)
|
1382
1328
|
# @return [Bool] false if invalid input
|
1383
|
-
def overlaps?(p1, p2, id1 = "", id2 = "")
|
1329
|
+
def overlaps?(p1 = nil, p2 = nil, id1 = "", id2 = "")
|
1384
1330
|
mth = "OSut::#{__callee__}"
|
1385
1331
|
cl1 = OpenStudio::Point3dVector
|
1386
1332
|
cl2 = OpenStudio::Point3d
|
1387
1333
|
a = false
|
1388
|
-
i1 = id1.to_s
|
1389
|
-
i2 = id2.to_s
|
1390
|
-
i1 = "poly1" if i1.empty?
|
1391
|
-
i2 = "poly2" if i2.empty?
|
1392
1334
|
|
1393
|
-
return invalid(
|
1394
|
-
|
1395
|
-
|
1335
|
+
return invalid("id1", mth, 3, DBG, a) unless id1.respond_to?(:to_s)
|
1336
|
+
return invalid("id2", mth, 4, DBG, a) unless id2.respond_to?(:to_s)
|
1337
|
+
i1 = id1.to_s
|
1338
|
+
i2 = id2.to_s
|
1339
|
+
i1 = "poly1" if i1.empty?
|
1340
|
+
i2 = "poly2" if i2.empty?
|
1341
|
+
valid1 = p1.is_a?(cl1) || p1.is_a?(Array)
|
1342
|
+
valid2 = p2.is_a?(cl1) || p2.is_a?(Array)
|
1343
|
+
return mismatch(i1, p1, cl1, mth, DBG, a) unless valid1
|
1344
|
+
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid2
|
1396
1345
|
return empty(i1, mth, ERR, a) if p1.empty?
|
1397
|
-
|
1398
|
-
return invalid(i2, mth, 2, DBG, a) unless p2
|
1399
|
-
valid = p2.is_a?(cl1) || p2.is_a?(Array)
|
1400
|
-
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid
|
1401
1346
|
return empty(i2, mth, ERR, a) if p2.empty?
|
1402
|
-
|
1403
1347
|
p1.each { |v| return mismatch(i1, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1404
1348
|
p2.each { |v| return mismatch(i2, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1405
1349
|
|
1406
1350
|
ft = OpenStudio::Transformation::alignFace(p1).inverse
|
1407
|
-
|
1408
1351
|
ft_p1 = flatZ( (ft * p1).reverse )
|
1409
1352
|
return false if ft_p1.empty?
|
1410
1353
|
area1 = OpenStudio::getArea(ft_p1)
|
1411
|
-
return empty(i1, mth, ERR, a) if area1.empty?
|
1354
|
+
return empty("#{i1} area", mth, ERR, a) if area1.empty?
|
1412
1355
|
area1 = area1.get
|
1413
|
-
|
1414
1356
|
ft_p2 = flatZ( (ft * p2).reverse )
|
1415
1357
|
return false if ft_p2.empty?
|
1416
1358
|
area2 = OpenStudio::getArea(ft_p2)
|
1417
|
-
return empty(i2, mth, ERR, a) if area2.empty?
|
1359
|
+
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1418
1360
|
area2 = area2.get
|
1419
|
-
|
1420
1361
|
union = OpenStudio::join(ft_p1, ft_p2, TOL2)
|
1421
1362
|
return false if union.empty?
|
1422
1363
|
union = union.get
|
1423
1364
|
area = OpenStudio::getArea(union)
|
1424
|
-
return empty("union", mth, ERR, a) if area.empty?
|
1365
|
+
return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
|
1425
1366
|
area = area.get
|
1426
1367
|
|
1427
1368
|
return false if area < TOL
|
1369
|
+
|
1428
1370
|
true
|
1429
1371
|
end
|
1372
|
+
|
1373
|
+
##
|
1374
|
+
# Callback when other modules extend OSlg
|
1375
|
+
#
|
1376
|
+
# @param base [Object] instance or class object
|
1377
|
+
def self.extended(base)
|
1378
|
+
base.send(:include, self)
|
1379
|
+
end
|
1430
1380
|
end
|
data/lib/osut/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: osut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Bourgeois
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oslg
|
@@ -90,7 +90,7 @@ licenses:
|
|
90
90
|
- BSD-3-Clause
|
91
91
|
metadata:
|
92
92
|
homepage_uri: https://github.com/rd2/osut
|
93
|
-
source_code_uri: https://github.com/rd2/osut/tree/v0.2.
|
93
|
+
source_code_uri: https://github.com/rd2/osut/tree/v0.2.3
|
94
94
|
bug_tracker_uri: https://github.com/rd2/osut/issues
|
95
95
|
post_install_message:
|
96
96
|
rdoc_options: []
|