osut 0.2.7 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bbbc6887949cfd0d1aed5c460d993196fa86d1a13f366f7f852e418aa9457a0
4
- data.tar.gz: b38eaa81d84a79655adb10a06bb1fa299ffff60051d187f2b36bad38fa4d78e0
3
+ metadata.gz: bec97227aeda04a933080c621650e72003d97816d01d2a4716f146e6501b7571
4
+ data.tar.gz: 82c0d1c211238120894a1bfaffed802b09461f22713957ed5c4a6b9bcb0ef757
5
5
  SHA512:
6
- metadata.gz: 1eb2cd49987ce2a4bf7a6a9fe0ed7048bc78dce644aa88e68173861ce4e52fc2bfe59bb3c4a7b353426a1bfa30f45af102ca3e509ac91945b82673545f1a4d4d
7
- data.tar.gz: bb8075d22d660b3f177716463baf3bc2b0e788269dc05f60086272dc5fec193b93a207f94500fa26cf8d786fdcd3810c0d3defb50eca4c39b3a05cf7c8d2412c
6
+ metadata.gz: e3897a390ef6f90524503ce63ff70a3e5275b1d3abf6148ac7752eb82ec64d5bfa2eedbf56898accdd87c7f394adf435e20b30dec457d3ebe4b3fc92e9130be5
7
+ data.tar.gz: 51529559490ab5f48e16a696ce657b867fe538ade32d07237b9fffc28e48b6da98905998c7819e019cdf8232fc2e16d8bc9cdb673280c2cc64861289f24370a5
@@ -7,7 +7,7 @@ on:
7
7
 
8
8
  jobs:
9
9
  test_300x:
10
- runs-on: ubuntu-18.04
10
+ runs-on: ubuntu-22.04
11
11
  steps:
12
12
  - name: Check out repository
13
13
  uses: actions/checkout@v2
@@ -23,7 +23,7 @@ jobs:
23
23
  docker exec -t test bundle exec rake
24
24
  docker kill test
25
25
  test_321x:
26
- runs-on: ubuntu-18.04
26
+ runs-on: ubuntu-22.04
27
27
  steps:
28
28
  - name: Check out repository
29
29
  uses: actions/checkout@v2
@@ -39,7 +39,7 @@ jobs:
39
39
  docker exec -t test bundle exec rake
40
40
  docker kill test
41
41
  test_330x:
42
- runs-on: ubuntu-20.04
42
+ runs-on: ubuntu-22.04
43
43
  steps:
44
44
  - name: Check out repository
45
45
  uses: actions/checkout@v2
@@ -55,7 +55,7 @@ jobs:
55
55
  docker exec -t test bundle exec rake
56
56
  docker kill test
57
57
  test_340x:
58
- runs-on: ubuntu-20.04
58
+ runs-on: ubuntu-22.04
59
59
  steps:
60
60
  - name: Check out repository
61
61
  uses: actions/checkout@v2
@@ -70,3 +70,19 @@ jobs:
70
70
  docker exec -t test bundle update
71
71
  docker exec -t test bundle exec rake
72
72
  docker kill test
73
+ test_351x:
74
+ runs-on: ubuntu-22.04
75
+ steps:
76
+ - name: Check out repository
77
+ uses: actions/checkout@v2
78
+ - name: Run Tests
79
+ run: |
80
+ echo $(pwd)
81
+ echo $(ls)
82
+ docker pull nrel/openstudio:3.5.1
83
+ docker run --name test --rm -d -t -v $(pwd):/work -w /work nrel/openstudio:3.5.1
84
+ docker exec -t test pwd
85
+ docker exec -t test ls
86
+ docker exec -t test bundle update
87
+ docker exec -t test bundle exec rake
88
+ docker kill test
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  BSD 3-Clause License
2
2
 
3
- Copyright (c) 2022, Denis Bourgeois
3
+ Copyright (c) 2022-2023, Denis Bourgeois
4
4
  All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
data/lib/osut/utils.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # BSD 3-Clause License
2
2
  #
3
- # Copyright (c) 2022, Denis Bourgeois
3
+ # Copyright (c) 2022-2023, Denis Bourgeois
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -59,7 +59,7 @@ module OSut
59
59
  # cooling system of sufficient size to maintain temperatures suitable
60
60
  # for HUMAN COMFORT:
61
61
  # - COOLED: cooled by a system >= 10 W/m2
62
- # - HEATED: heated by a system e.g., >= 50 W/m2 in Climate Zone CZ-7
62
+ # - HEATED: heated by a system, e.g. >= 50 W/m2 in Climate Zone CZ-7
63
63
  # - INDIRECTLY: heated or cooled via adjacent space(s) provided:
64
64
  # - UA of adjacent surfaces > UA of other surfaces
65
65
  # or
@@ -89,7 +89,7 @@ module OSut
89
89
  # response to the exterior ambient temperature by the provision, either
90
90
  # DIRECTLY or INDIRECTLY, of heating or cooling [...]". Although criteria
91
91
  # differ (e.g., not sizing-based), the general idea is sufficiently similar
92
- # to ASHRAE 90.1 (e.g., heating and/or cooling based, no distinction for
92
+ # to ASHRAE 90.1 (e.g. heating and/or cooling based, no distinction for
93
93
  # INDIRECTLY conditioned spaces like plenums).
94
94
  #
95
95
  # SEMI-HEATED spaces are also a defined NECB term, but again the distinction
@@ -109,16 +109,16 @@ module OSut
109
109
  # processes. As discussed in greater detail elswhere, methods are developed to
110
110
  # rely on zoning info and/or "intended" temperature setpoints.
111
111
  #
112
- # For an OpenStudio model (OSM) in an incomplete or preliminary state, e.g.
113
- # holding fully-formed ENCLOSED spaces without thermal zoning information or
114
- # setpoint temperatures (early design stage assessments of form, porosity or
115
- # envelope), all OSM spaces will be considered CONDITIONED, presuming
116
- # setpoints of ~21°C (heating) and ~24°C (cooling).
112
+ # For an OpenStudio model in an incomplete or preliminary state, e.g. holding
113
+ # fully-formed ENCLOSED spaces without thermal zoning information or setpoint
114
+ # temperatures (early design stage assessments of form, porosity or envelope),
115
+ # all OpenStudio spaces will be considered CONDITIONED, presuming setpoints of
116
+ # ~21°C (heating) and ~24°C (cooling).
117
117
  #
118
- # If ANY valid space/zone-specific temperature setpoints are found in the OSM,
119
- # spaces/zones WITHOUT valid heating or cooling setpoints are considered as
120
- # UNCONDITIONED or UNENCLOSED spaces (like attics), or INDIRECTLY CONDITIONED
121
- # spaces (like plenums), see "plenum?" method.
118
+ # If ANY valid space/zone-specific temperature setpoints are found in the
119
+ # OpenStudio model, spaces/zones WITHOUT valid heating or cooling setpoints
120
+ # are considered as UNCONDITIONED or UNENCLOSED spaces (like attics), or
121
+ # INDIRECTLY CONDITIONED spaces (like plenums), see "plenum?" method.
122
122
 
123
123
  ##
124
124
  # Return min & max values of a schedule (ruleset).
@@ -139,6 +139,7 @@ module OSut
139
139
  res = { min: nil, max: nil }
140
140
 
141
141
  return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
142
+
142
143
  id = sched.nameString
143
144
  return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
144
145
 
@@ -186,6 +187,7 @@ module OSut
186
187
  res = { min: nil, max: nil }
187
188
 
188
189
  return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
190
+
189
191
  id = sched.nameString
190
192
  return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
191
193
 
@@ -218,6 +220,7 @@ module OSut
218
220
  res = { min: nil, max: nil }
219
221
 
220
222
  return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
223
+
221
224
  id = sched.nameString
222
225
  return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
223
226
 
@@ -231,9 +234,11 @@ module OSut
231
234
  end
232
235
 
233
236
  return empty("'#{id}' values", mth, ERR, res) if vals.empty?
237
+
234
238
  ok = vals.min.is_a?(Numeric) && vals.max.is_a?(Numeric)
235
239
  log(ERR, "Non-numeric values in '#{id}' (#{mth})") unless ok
236
240
  return res unless ok
241
+
237
242
  res[:min] = vals.min
238
243
  res[:max] = vals.max
239
244
 
@@ -248,19 +253,21 @@ module OSut
248
253
  # @return [Hash] min: (Float), max: (Float)
249
254
  # @return [Hash] min: nil, max: nil (if invalid input)
250
255
  def scheduleIntervalMinMax(sched = nil)
251
- mth = "OSut::#{__callee__}"
252
- cl = OpenStudio::Model::ScheduleInterval
253
- vals = []
254
- prev_str = ""
255
- res = { min: nil, max: nil }
256
+ mth = "OSut::#{__callee__}"
257
+ cl = OpenStudio::Model::ScheduleInterval
258
+ vals = []
259
+ res = { min: nil, max: nil }
256
260
 
257
261
  return invalid("sched", mth, 1, DBG, res) unless sched.respond_to?(NS)
262
+
258
263
  id = sched.nameString
259
264
  return mismatch(id, sched, cl, mth, DBG, res) unless sched.is_a?(cl)
265
+
260
266
  vals = sched.timeSeries.values
261
- ok = vals.min.is_a?(Numeric) && vals.max.is_a?(Numeric)
267
+ ok = vals.min.is_a?(Numeric) && vals.max.is_a?(Numeric)
262
268
  log(ERR, "Non-numeric values in '#{id}' (#{mth})") unless ok
263
269
  return res unless ok
270
+
264
271
  res[:min] = vals.min
265
272
  res[:max] = vals.max
266
273
 
@@ -289,6 +296,7 @@ module OSut
289
296
  res = { spt: nil, dual: false }
290
297
 
291
298
  return invalid("zone", mth, 1, DBG, res) unless zone.respond_to?(NS)
299
+
292
300
  id = zone.nameString
293
301
  return mismatch(id, zone, cl, mth, DBG, res) unless zone.is_a?(cl)
294
302
 
@@ -369,6 +377,7 @@ module OSut
369
377
  end
370
378
 
371
379
  return res if zone.thermostat.empty?
380
+
372
381
  tstat = zone.thermostat.get
373
382
  res[:spt] = nil
374
383
 
@@ -427,6 +436,7 @@ module OSut
427
436
 
428
437
  sched.getScheduleWeeks.each do |week|
429
438
  next if week.winterDesignDaySchedule.empty?
439
+
430
440
  dd = week.winterDesignDaySchedule.get
431
441
  next unless dd.values.empty?
432
442
 
@@ -479,6 +489,7 @@ module OSut
479
489
  res = { spt: nil, dual: false }
480
490
 
481
491
  return invalid("zone", mth, 1, DBG, res) unless zone.respond_to?(NS)
492
+
482
493
  id = zone.nameString
483
494
  return mismatch(id, zone, cl, mth, DBG, res) unless zone.is_a?(cl)
484
495
 
@@ -546,6 +557,7 @@ module OSut
546
557
  end
547
558
 
548
559
  return res if zone.thermostat.empty?
560
+
549
561
  tstat = zone.thermostat.get
550
562
  res[:spt] = nil
551
563
 
@@ -604,6 +616,7 @@ module OSut
604
616
 
605
617
  sched.getScheduleWeeks.each do |week|
606
618
  next if week.summerDesignDaySchedule.empty?
619
+
607
620
  dd = week.summerDesignDaySchedule.get
608
621
  next unless dd.values.empty?
609
622
 
@@ -691,10 +704,13 @@ module OSut
691
704
  cl = OpenStudio::Model::Space
692
705
 
693
706
  return invalid("space", mth, 1, DBG, false) unless space.respond_to?(NS)
707
+
694
708
  id = space.nameString
695
709
  return mismatch(id, space, cl, mth, DBG, false) unless space.is_a?(cl)
710
+
696
711
  valid = loops == true || loops == false
697
712
  return invalid("loops", mth, 2, DBG, false) unless valid
713
+
698
714
  valid = setpoints == true || setpoints == false
699
715
  return invalid("setpoints", mth, 3, DBG, false) unless valid
700
716
 
@@ -714,11 +730,11 @@ module OSut
714
730
  unless space.spaceType.empty?
715
731
  type = space.spaceType.get
716
732
  return type.nameString.downcase == "plenum" # C
733
+ end
717
734
 
718
- unless type.standardsSpaceType.empty?
719
- type = type.standardsSpaceType.get
720
- return type.downcase == "plenum" # C
721
- end
735
+ unless type.standardsSpaceType.empty?
736
+ type = type.standardsSpaceType.get
737
+ return type.downcase == "plenum" # C
722
738
  end
723
739
 
724
740
  false
@@ -751,6 +767,7 @@ module OSut
751
767
  next unless l.numericType.get.downcase == "discrete"
752
768
  next unless l.unitType.downcase == "availability"
753
769
  next unless l.nameString.downcase == "hvac operation scheduletypelimits"
770
+
754
771
  limits = l
755
772
  end
756
773
 
@@ -771,6 +788,7 @@ module OSut
771
788
  # Seasonal availability start/end dates.
772
789
  year = model.yearDescription
773
790
  return empty("yearDescription", mth, ERR) if year.empty?
791
+
774
792
  year = year.get
775
793
  may01 = year.makeDate(OpenStudio::MonthOfYear.new("May"), 1)
776
794
  oct31 = year.makeDate(OpenStudio::MonthOfYear.new("Oct"), 31)
@@ -850,9 +868,11 @@ module OSut
850
868
  ok = schedule.setScheduleTypeLimits(limits)
851
869
  log(ERR, "'#{nom}': Can't set schedule type limits (#{mth})") unless ok
852
870
  return nil unless ok
871
+
853
872
  ok = schedule.defaultDaySchedule.addValue(time, val)
854
873
  log(ERR, "'#{nom}': Can't set default day schedule (#{mth})") unless ok
855
874
  return nil unless ok
875
+
856
876
  schedule.defaultDaySchedule.setName(dft)
857
877
 
858
878
  unless tag.empty?
@@ -861,12 +881,15 @@ module OSut
861
881
  ok = rule.setStartDate(may01)
862
882
  log(ERR, "'#{tag}': Can't set start date (#{mth})") unless ok
863
883
  return nil unless ok
884
+
864
885
  ok = rule.setEndDate(oct31)
865
886
  log(ERR, "'#{tag}': Can't set end date (#{mth})") unless ok
866
887
  return nil unless ok
888
+
867
889
  ok = rule.setApplyAllDays(true)
868
890
  log(ERR, "'#{tag}': Can't apply to all days (#{mth})") unless ok
869
891
  return nil unless ok
892
+
870
893
  rule.daySchedule.setName(day)
871
894
  end
872
895
 
@@ -874,7 +897,7 @@ module OSut
874
897
  end
875
898
 
876
899
  ##
877
- # Validate if default construction set holds a base ground construction.
900
+ # Validate if default construction set holds a base construction.
878
901
  #
879
902
  # @param set [OpenStudio::Model::DefaultConstructionSet] a default set
880
903
  # @param bse [OpensStudio::Model::ConstructionBase] a construction base
@@ -890,17 +913,23 @@ module OSut
890
913
  cl2 = OpenStudio::Model::ConstructionBase
891
914
 
892
915
  return invalid("set", mth, 1, DBG, false) unless set.respond_to?(NS)
916
+
893
917
  id = set.nameString
894
918
  return mismatch(id, set, cl1, mth, DBG, false) unless set.is_a?(cl1)
895
919
  return invalid("base", mth, 2, DBG, false) unless bse.respond_to?(NS)
920
+
896
921
  id = bse.nameString
897
922
  return mismatch(id, bse, cl2, mth, DBG, false) unless bse.is_a?(cl2)
923
+
898
924
  valid = gr == true || gr == false
899
925
  return invalid("ground", mth, 3, DBG, false) unless valid
926
+
900
927
  valid = ex == true || ex == false
901
928
  return invalid("exterior", mth, 4, DBG, false) unless valid
929
+
902
930
  valid = typ.respond_to?(:to_s)
903
931
  return invalid("surface typ", mth, 4, DBG, false) unless valid
932
+
904
933
  type = typ.to_s.downcase
905
934
  valid = type == "floor" || type == "wall" || type == "roofceiling"
906
935
  return invalid("surface type", mth, 5, DBG, false) unless valid
@@ -959,6 +988,7 @@ module OSut
959
988
 
960
989
  return mismatch("model", model, cl1, mth) unless model.is_a?(cl1)
961
990
  return invalid("s", mth, 2) unless s.respond_to?(NS)
991
+
962
992
  id = s.nameString
963
993
  return mismatch(id, s, cl2, mth) unless s.is_a?(cl2)
964
994
 
@@ -966,8 +996,10 @@ module OSut
966
996
  log(ERR, "'#{id}' construction not defaulted (#{mth})") unless ok
967
997
  return nil unless ok
968
998
  return empty("'#{id}' construction", mth, ERR) if s.construction.empty?
999
+
969
1000
  base = s.construction.get
970
1001
  return empty("'#{id}' space", mth, ERR) if s.space.empty?
1002
+
971
1003
  space = s.space.get
972
1004
  type = s.surfaceType
973
1005
  ground = false
@@ -1043,12 +1075,14 @@ module OSut
1043
1075
  cl = OpenStudio::Model::LayeredConstruction
1044
1076
 
1045
1077
  return invalid("lc", mth, 1, DBG, 0.0) unless lc.respond_to?(NS)
1078
+
1046
1079
  id = lc.nameString
1047
1080
  return mismatch(id, lc, cl, mth, DBG, 0.0) unless lc.is_a?(cl)
1048
1081
 
1049
1082
  ok = standardOpaqueLayers?(lc)
1050
1083
  log(ERR, "'#{id}' holds non-StandardOpaqueMaterial(s) (#{mth})") unless ok
1051
1084
  return 0.0 unless ok
1085
+
1052
1086
  thickness = 0.0
1053
1087
  lc.layers.each { |m| thickness += m.thickness }
1054
1088
 
@@ -1113,11 +1147,14 @@ module OSut
1113
1147
  cl2 = Numeric
1114
1148
 
1115
1149
  return invalid("lc", mth, 1, DBG, 0.0) unless lc.respond_to?(NS)
1150
+
1116
1151
  id = lc.nameString
1152
+
1117
1153
  return mismatch(id, lc, cl1, mth, DBG, 0.0) unless lc.is_a?(cl1)
1118
1154
  return mismatch("film", film, cl2, mth, DBG, 0.0) unless film.is_a?(cl2)
1119
1155
  return mismatch("temp K", t, cl2, mth, DBG, 0.0) unless t.is_a?(cl2)
1120
- t += 273.0 # °C to K
1156
+
1157
+ t += 273.0 # °C to K
1121
1158
  return negative("temp K", mth, DBG, 0.0) if t < 0
1122
1159
  return negative("film", mth, DBG, 0.0) if film < 0
1123
1160
 
@@ -1127,6 +1164,7 @@ module OSut
1127
1164
  # Fenestration materials first (ignoring shades, screens, etc.)
1128
1165
  empty = m.to_SimpleGlazing.empty?
1129
1166
  return 1 / m.to_SimpleGlazing.get.uFactor unless empty
1167
+
1130
1168
  empty = m.to_StandardGlazing.empty?
1131
1169
  rsi += m.to_StandardGlazing.get.thermalResistance unless empty
1132
1170
  empty = m.to_RefractionExtinctionGlazing.empty?
@@ -1167,6 +1205,7 @@ module OSut
1167
1205
  i = 0 # iterator
1168
1206
 
1169
1207
  return invalid("lc", mth, 1, DBG, res) unless lc.respond_to?(NS)
1208
+
1170
1209
  id = lc.nameString
1171
1210
  return mismatch(id, lc, cl1, mth, DBG, res) unless lc.is_a?(cl)
1172
1211
 
@@ -1221,6 +1260,7 @@ module OSut
1221
1260
 
1222
1261
  return mismatch("model", model, cl1, mth, DBG, res) unless model.is_a?(cl1)
1223
1262
  return invalid("group", mth, 2, DBG, res) unless group.respond_to?(NS)
1263
+
1224
1264
  id = group.nameString
1225
1265
  return mismatch(id, group, cl2, mth, DBG, res) unless group.is_a?(cl2)
1226
1266
 
@@ -1244,10 +1284,10 @@ module OSut
1244
1284
  cl2 = Numeric
1245
1285
 
1246
1286
  return mismatch("vector", v, cl1, mth, DBG, v) unless v.is_a?(cl1)
1247
- return mismatch("x", v.x, cl2, mth, DBG, v) unless v.x.respond_to?(:to_f)
1248
- return mismatch("y", v.y, cl2, mth, DBG, v) unless v.y.respond_to?(:to_f)
1249
- return mismatch("z", v.z, cl2, mth, DBG, v) unless v.z.respond_to?(:to_f)
1250
- return mismatch("m", m, cl2, mth, DBG, v) unless m.respond_to?(:to_f)
1287
+ return mismatch("x", v.x, cl2, mth, DBG, v) unless v.x.respond_to?(:to_f)
1288
+ return mismatch("y", v.y, cl2, mth, DBG, v) unless v.y.respond_to?(:to_f)
1289
+ return mismatch("z", v.z, cl2, mth, DBG, v) unless v.z.respond_to?(:to_f)
1290
+ return mismatch("m", m, cl2, mth, DBG, v) unless m.respond_to?(:to_f)
1251
1291
 
1252
1292
  OpenStudio::Vector3d.new(m * v.x, m * v.y, m * v.z)
1253
1293
  end
@@ -1266,6 +1306,7 @@ module OSut
1266
1306
 
1267
1307
  valid = pts.is_a?(cl1) || pts.is_a?(Array)
1268
1308
  return mismatch("points", pts, cl1, mth, DBG, v) unless valid
1309
+
1269
1310
  pts.each { |pt| mismatch("pt", pt, cl2, mth, ERR, v) unless pt.is_a?(cl2) }
1270
1311
  pts.each { |pt| v << OpenStudio::Point3d.new(pt.x, pt.y, 0) }
1271
1312
 
@@ -1311,23 +1352,29 @@ module OSut
1311
1352
  ft = OpenStudio::Transformation.alignFace(p1)
1312
1353
  ft_p1 = flatZ( (ft.inverse * p1) )
1313
1354
  return false if ft_p1.empty?
1355
+
1314
1356
  cw = OpenStudio.pointInPolygon(ft_p1.first, ft_p1, TOL)
1315
1357
  ft_p1 = flatZ( (ft.inverse * p1).reverse ) unless cw
1316
1358
  ft_p2 = flatZ( (ft.inverse * p2).reverse ) unless cw
1317
1359
  ft_p2 = flatZ( (ft.inverse * p2) ) if cw
1318
1360
  return false if ft_p2.empty?
1361
+
1319
1362
  area1 = OpenStudio.getArea(ft_p1)
1320
1363
  area2 = OpenStudio.getArea(ft_p2)
1321
1364
  return empty("#{i1} area", mth, ERR, a) if area1.empty?
1322
1365
  return empty("#{i2} area", mth, ERR, a) if area2.empty?
1366
+
1323
1367
  area1 = area1.get
1324
1368
  area2 = area2.get
1325
1369
  union = OpenStudio.join(ft_p1, ft_p2, TOL2)
1326
1370
  return false if union.empty?
1371
+
1327
1372
  union = union.get
1328
1373
  area = OpenStudio.getArea(union)
1329
1374
  return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
1375
+
1330
1376
  area = area.get
1377
+
1331
1378
  return false if area < TOL
1332
1379
  return true if (area - area2).abs < TOL
1333
1380
  return false if (area - area2).abs > TOL
@@ -1376,22 +1423,27 @@ module OSut
1376
1423
  ft_p2 = flatZ( (ft.inverse * p2) )
1377
1424
  return false if ft_p1.empty?
1378
1425
  return false if ft_p2.empty?
1426
+
1379
1427
  cw = OpenStudio.pointInPolygon(ft_p1.first, ft_p1, TOL)
1380
1428
  ft_p1 = flatZ( (ft.inverse * p1).reverse ) unless cw
1381
1429
  ft_p2 = flatZ( (ft.inverse * p2).reverse ) unless cw
1382
1430
  return false if ft_p1.empty?
1383
1431
  return false if ft_p2.empty?
1432
+
1384
1433
  area1 = OpenStudio.getArea(ft_p1)
1385
1434
  area2 = OpenStudio.getArea(ft_p2)
1386
1435
  return empty("#{i1} area", mth, ERR, a) if area1.empty?
1387
1436
  return empty("#{i2} area", mth, ERR, a) if area2.empty?
1437
+
1388
1438
  area1 = area1.get
1389
1439
  area2 = area2.get
1390
1440
  union = OpenStudio.join(ft_p1, ft_p2, TOL2)
1391
1441
  return false if union.empty?
1442
+
1392
1443
  union = union.get
1393
1444
  area = OpenStudio.getArea(union)
1394
1445
  return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
1446
+
1395
1447
  area = area.get
1396
1448
  return false if area < TOL
1397
1449
 
@@ -1415,12 +1467,15 @@ module OSut
1415
1467
  valid = p1.is_a?(OpenStudio::Point3dVector) || p1.is_a?(Array)
1416
1468
  return mismatch("pts", p1, cl1, mth, DBG, p1) unless valid
1417
1469
  return empty("pts", mth, ERR, p1) if p1.empty?
1470
+
1418
1471
  valid = p1.size == 3 || p1.size == 4
1419
1472
  iv = true if p1.size == 4
1420
1473
  return invalid("pts", mth, 1, DBG, p1) unless valid
1421
1474
  return invalid("width", mth, 2, DBG, p1) unless w.respond_to?(:to_f)
1475
+
1422
1476
  w = w.to_f
1423
1477
  return p1 if w < 0.0254
1478
+
1424
1479
  v = v.to_i if v.respond_to?(:to_i)
1425
1480
  v = 0 unless v.respond_to?(:to_i)
1426
1481
  v = vrsn if v.zero?
@@ -1432,16 +1487,19 @@ module OSut
1432
1487
  ft = OpenStudio::Transformation::alignFace(p1)
1433
1488
  ft_pts = flatZ( (ft.inverse * p1) )
1434
1489
  return p1 if ft_pts.empty?
1490
+
1435
1491
  cw = OpenStudio::pointInPolygon(ft_pts.first, ft_pts, TOL)
1436
1492
  ft_pts = flatZ( (ft.inverse * p1).reverse ) unless cw
1437
1493
  offset = OpenStudio.buffer(ft_pts, w, TOL)
1438
1494
  return p1 if offset.empty?
1495
+
1439
1496
  offset = offset.get
1440
1497
  offset = ft * offset if cw
1441
1498
  offset = (ft * offset).reverse unless cw
1442
1499
 
1443
1500
  pz = OpenStudio::Point3dVector.new
1444
1501
  offset.each { |o| pz << OpenStudio::Point3d.new(o.x, o.y, o.z ) }
1502
+
1445
1503
  return pz
1446
1504
  else # brute force approach
1447
1505
  pz = {}
data/lib/osut/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # BSD 3-Clause License
2
2
  #
3
- # Copyright (c) 2022, Denis Bourgeois
3
+ # Copyright (c) 2022-2023, Denis Bourgeois
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -29,5 +29,5 @@
29
29
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
31
  module OSut
32
- VERSION = "0.2.7".freeze
32
+ VERSION = "0.2.8".freeze
33
33
  end
data/lib/osut.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # BSD 3-Clause License
2
2
  #
3
- # Copyright (c) 2022, Denis Bourgeois
3
+ # Copyright (c) 2022-2023, Denis Bourgeois
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
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.7
4
+ version: 0.2.8
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-08-21 00:00:00.000000000 Z
11
+ date: 2023-01-01 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.7
93
+ source_code_uri: https://github.com/rd2/osut/tree/v0.2.8
94
94
  bug_tracker_uri: https://github.com/rd2/osut/issues
95
95
  post_install_message:
96
96
  rdoc_options: []