osut 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|