tbd 3.3.0 → 3.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 840a07d7ac8aab45d2c2e377c9aecfc7bfb6e02a2aa00736bd3d07da271d619e
4
- data.tar.gz: 0f41e81875c54f81c00e8788b40569bde04e75233fd3a7d1f9b5e905aecf866c
3
+ metadata.gz: 4d894d405f77c1eb33517cb957ca0a9a8f87319841c983047acdb8055aa5d79c
4
+ data.tar.gz: 6788f593ac0bb66c52b81d0be2f5140dd6c4ef9c6dfb0f9df5e684bdd41c714a
5
5
  SHA512:
6
- metadata.gz: bf7839e2518c1fdff231b7f9ad9ac8a8b8fd6a2e3ca79e7441ca58c5c8d6dcf22d64ee6414fecd9160ec0cc1203f1a07ec862e7337ed27b1812f0ef59617d94b
7
- data.tar.gz: f3fe90266432320e562a7119a4f11c9097cb958533c4b9e1c53089330b2fd79ca15884c798f9f49f3cb751ca8374f10801f77a0b070f8f039c242e4874338863
6
+ metadata.gz: 753541a1202a93df6346b8ce164679fbecdce11413d017977d62f9edb386ad0ab03e8b4b2a43be00eac01f0b0d3f45f9f4c91d9ec3db9c5e34a482a2b45a3600
7
+ data.tar.gz: 945278734bc73490690e8fdc37e0bf9fe910ea29f4eef43370234f76f3032c8f0d25cf38a648ffde44f990db39c17fcc0fc115662dc4150b4fa1b0c5df8a8776
@@ -111,8 +111,8 @@ jobs:
111
111
  run: |
112
112
  echo $(pwd)
113
113
  echo $(ls)
114
- docker pull nrel/openstudio:dev-3.7.0-alpha
115
- docker run --name test --rm -d -t -v $(pwd):/work -w /work nrel/openstudio:dev-3.7.0-alpha
114
+ docker pull nrel/openstudio:3.7.0
115
+ docker run --name test --rm -d -t -v $(pwd):/work -w /work nrel/openstudio:3.7.0
116
116
  docker exec -t test pwd
117
117
  docker exec -t test ls
118
118
  docker exec -t test bundle update
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/json/tbd_z5.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "schema": "https://github.com/rd2/tbd/blob/master/tbd.schema.json",
3
+ "description": "testing TBD JSON for 5Zone (plenum)",
4
+ "psis": [{
5
+ "id": "salk",
6
+ "ceiling": 0.1
7
+ }],
8
+ "spaces": [{
9
+ "id": "PLENUM-1",
10
+ "psi": "salk"
11
+ }]
12
+ }
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.1</schema_version>
4
4
  <name>tbd_measure</name>
5
5
  <uid>8890787b-8c25-4dc8-8641-b6be1b6c2357</uid>
6
- <version_id>80f7038a-762a-4f4d-81f4-f4e9daa64925</version_id>
7
- <version_modified>2023-10-22T13:14:49Z</version_modified>
6
+ <version_id>4eec2792-b3ef-4152-95c8-a7dd6a6bf9c4</version_id>
7
+ <version_modified>2024-04-17T14:29:06Z</version_modified>
8
8
  <xml_checksum>99772807</xml_checksum>
9
9
  <class_name>TBDMeasure</class_name>
10
10
  <display_name>Thermal Bridging and Derating - TBD</display_name>
@@ -464,7 +464,7 @@
464
464
  <filename>LICENSE.md</filename>
465
465
  <filetype>md</filetype>
466
466
  <usage_type>license</usage_type>
467
- <checksum>A91E64A0</checksum>
467
+ <checksum>5C9BFB50</checksum>
468
468
  </file>
469
469
  <file>
470
470
  <filename>README.md</filename>
@@ -493,13 +493,13 @@
493
493
  <filename>measure.rb</filename>
494
494
  <filetype>rb</filetype>
495
495
  <usage_type>script</usage_type>
496
- <checksum>D1FC18B2</checksum>
496
+ <checksum>A472E915</checksum>
497
497
  </file>
498
498
  <file>
499
499
  <filename>geo.rb</filename>
500
500
  <filetype>rb</filetype>
501
501
  <usage_type>resource</usage_type>
502
- <checksum>7A491A3B</checksum>
502
+ <checksum>6C7ACC99</checksum>
503
503
  </file>
504
504
  <file>
505
505
  <filename>geometry.rb</filename>
@@ -517,19 +517,19 @@
517
517
  <filename>oslog.rb</filename>
518
518
  <filetype>rb</filetype>
519
519
  <usage_type>resource</usage_type>
520
- <checksum>E4978588</checksum>
520
+ <checksum>8CD57B9A</checksum>
521
521
  </file>
522
522
  <file>
523
523
  <filename>psi.rb</filename>
524
524
  <filetype>rb</filetype>
525
525
  <usage_type>resource</usage_type>
526
- <checksum>0CBB060B</checksum>
526
+ <checksum>5ABDEC60</checksum>
527
527
  </file>
528
528
  <file>
529
529
  <filename>tbd.rb</filename>
530
530
  <filetype>rb</filetype>
531
531
  <usage_type>resource</usage_type>
532
- <checksum>A4E8433C</checksum>
532
+ <checksum>E8D38E59</checksum>
533
533
  </file>
534
534
  <file>
535
535
  <filename>transformation.rb</filename>
@@ -541,13 +541,13 @@
541
541
  <filename>ua.rb</filename>
542
542
  <filetype>rb</filetype>
543
543
  <usage_type>resource</usage_type>
544
- <checksum>1AEE3C54</checksum>
544
+ <checksum>928C5E7B</checksum>
545
545
  </file>
546
546
  <file>
547
547
  <filename>utils.rb</filename>
548
548
  <filetype>rb</filetype>
549
549
  <usage_type>resource</usage_type>
550
- <checksum>7385DFE0</checksum>
550
+ <checksum>E3B4AF4B</checksum>
551
551
  </file>
552
552
  <file>
553
553
  <filename>version.rb</filename>
@@ -565,7 +565,7 @@
565
565
  <filename>tbd_tests.rb</filename>
566
566
  <filetype>rb</filetype>
567
567
  <usage_type>test</usage_type>
568
- <checksum>85067AF6</checksum>
568
+ <checksum>2ECE06CA</checksum>
569
569
  </file>
570
570
  </files>
571
571
  </measure>
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -251,7 +251,7 @@ module TBD
251
251
  #
252
252
  # @return [Topolys::Vector3D] true normal vector of s
253
253
  # @return [nil] if invalid input (see logs)
254
- def trueNormal(s = nil, r = 0)
254
+ def truNormal(s = nil, r = 0)
255
255
  mth = "TBD::#{__callee__}"
256
256
  cl = OpenStudio::Model::PlanarSurface
257
257
  return mismatch("surface", s, cl, mth) unless s.is_a?(cl)
@@ -285,18 +285,18 @@ module TBD
285
285
  surf = {}
286
286
  subs = {}
287
287
  fd = false
288
- return invalid("#{nom}", mth, 1, FTL) if poly(surface).empty?
288
+ return invalid("#{nom}", mth, 1, ERR) if poly(surface).empty?
289
289
  return empty("#{nom} space", mth, ERR) if surface.space.empty?
290
290
 
291
291
  space = surface.space.get
292
292
  stype = space.spaceType
293
293
  story = space.buildingStory
294
294
  tr = transforms(space)
295
- return invalid("#{nom} transform", mth, 0, FTL) unless tr[:t] && tr[:r]
295
+ return invalid("#{nom} transform", mth, 0, ERR) unless tr[:t] && tr[:r]
296
296
 
297
297
  t = tr[:t]
298
- n = trueNormal(surface, tr[:r])
299
- return invalid("#{nom} normal", mth, 0, FTL) unless n
298
+ n = truNormal(surface, tr[:r])
299
+ return invalid("#{nom} normal", mth, 0, ERR) unless n
300
300
 
301
301
  type = surface.surfaceType.downcase
302
302
  facing = surface.outsideBoundaryCondition
@@ -347,6 +347,7 @@ module TBD
347
347
 
348
348
  surf[:conditioned] = surf.key?(:heating) || surf.key?(:cooling)
349
349
  surf[:space ] = space
350
+ surf[:occupied ] = space.partofTotalFloorArea
350
351
  surf[:boundary ] = facing
351
352
  surf[:ground ] = surface.isGroundSurface
352
353
  surf[:type ] = :floor
@@ -1,6 +1,6 @@
1
1
  # BSD 3-Clause License
2
2
  #
3
- # Copyright (c) 2022-2023, Denis Bourgeois
3
+ # Copyright (c) 2022-2024, Denis Bourgeois
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -156,6 +156,7 @@ module TBD
156
156
  rimjoist: 1.000000, # re: BETBG
157
157
  parapet: 0.800000, # re: BETBG
158
158
  roof: 0.800000, # same as parapet
159
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
159
160
  fenestration: 0.500000, # re: BETBG
160
161
  door: 0.500000, # inferred, same as (vertical) fenestration
161
162
  skylight: 0.500000, # inferred, same as (vertical) fenestration
@@ -176,6 +177,7 @@ module TBD
176
177
  rimjoist: 0.500000, # re: BETBG
177
178
  parapet: 0.450000, # re: BETBG
178
179
  roof: 0.450000, # same as parapet
180
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
179
181
  fenestration: 0.350000, # re: BETBG
180
182
  door: 0.350000, # inferred, same as (vertical) fenestration
181
183
  skylight: 0.350000, # inferred, same as (vertical) fenestration
@@ -196,6 +198,7 @@ module TBD
196
198
  rimjoist: 0.200000, # re: BETBG
197
199
  parapet: 0.200000, # re: BETBG
198
200
  roof: 0.200000, # same as parapet
201
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
199
202
  fenestration: 0.199999, # re: BETBG
200
203
  door: 0.199999, # inferred, same as (vertical) fenestration
201
204
  skylight: 0.199999, # inferred, same as (vertical) fenestration
@@ -216,6 +219,7 @@ module TBD
216
219
  rimjoist: 0.615000, # Detail 1.2.1
217
220
  parapet: 1.000000, # Detail 1.3.2
218
221
  roof: 1.000000, # same as parapet
222
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
219
223
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
220
224
  door: 0.000000, # inferred, generally part of clear-field RSi
221
225
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -236,6 +240,7 @@ module TBD
236
240
  rimjoist: 0.170000, # Detail 1.2.7
237
241
  parapet: 0.660000, # Detail 1.3.2
238
242
  roof: 0.660000, # same as parapet
243
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
239
244
  fenestration: 0.000000, # inferred, generally part of clear-field RSi
240
245
  door: 0.000000, # inferred, generally part of clear-field RSi
241
246
  skylight: 0.350000, # same as "regular (BETBG)"
@@ -256,6 +261,7 @@ module TBD
256
261
  rimjoist: 0.300000, # re I1
257
262
  parapet: 0.325000, # re I1
258
263
  roof: 0.325000, # same as parapet
264
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
259
265
  fenestration: 0.200000, # re I1
260
266
  door: 0.200000, # re I1
261
267
  skylight: 0.200000, # re I1
@@ -276,6 +282,7 @@ module TBD
276
282
  rimjoist: 0.850000, # re I1
277
283
  parapet: 0.800000, # re I1
278
284
  roof: 0.800000, # same as parapet
285
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
279
286
  fenestration: 0.500000, # re I1
280
287
  door: 0.500000, # re I1
281
288
  skylight: 0.500000, # re I1
@@ -296,6 +303,7 @@ module TBD
296
303
  rimjoist: 0.307000, # "intermediate floor to wall intersection"
297
304
  parapet: 0.260000, # "parapet" edge
298
305
  roof: 0.020000, # (non-parapet) "roof" edge
306
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
299
307
  fenestration: 0.194000, # "wall to vertical fenestration intersection"
300
308
  door: 0.000000, # (unspecified, defaults to 0)
301
309
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -316,6 +324,7 @@ module TBD
316
324
  rimjoist: 0.842000, # "intermediate floor to wall intersection"
317
325
  parapet: 0.500000, # "parapet" edge
318
326
  roof: 0.650000, # (non-parapet) "roof" edge
327
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
319
328
  fenestration: 0.505000, # "wall to vertical fenestration intersection"
320
329
  door: 0.000000, # (unspecified, defaults to 0)
321
330
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -336,6 +345,7 @@ module TBD
336
345
  rimjoist: 0.205000, # "intermediate floor to wall intersection"
337
346
  parapet: 0.217000, # "parapet" edge
338
347
  roof: 0.150000, # (non-parapet) "roof" edge
348
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
339
349
  fenestration: 0.226000, # "wall to vertical fenestration intersection"
340
350
  door: 0.000000, # (unspecified, defaults to 0)
341
351
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -356,6 +366,7 @@ module TBD
356
366
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
357
367
  parapet: 0.412000, # "parapet" edge
358
368
  roof: 0.750000, # (non-parapet) "roof" edge
369
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
359
370
  fenestration: 0.325000, # "wall to vertical fenestration intersection"
360
371
  door: 0.000000, # (unspecified, defaults to 0)
361
372
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -376,6 +387,7 @@ module TBD
376
387
  rimjoist: 0.495000, # "intermediate floor to wall intersection"
377
388
  parapet: 0.393000, # "parapet" edge
378
389
  roof: 0.150000, # (non-parapet) "roof" edge
390
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
379
391
  fenestration: 0.143000, # "wall to vertical fenestration intersection"
380
392
  door: 0.000000, # (unspecified, defaults to 0)
381
393
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -396,6 +408,7 @@ module TBD
396
408
  rimjoist: 0.824000, # "intermediate floor to wall intersection"
397
409
  parapet: 0.884000, # "parapet" edge
398
410
  roof: 0.750000, # (non-parapet) "roof" edge
411
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
399
412
  fenestration: 0.543000, # "wall to vertical fenestration intersection"
400
413
  door: 0.000000, # (unspecified, defaults to 0)
401
414
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -416,6 +429,7 @@ module TBD
416
429
  rimjoist: 0.084000, # "intermediate floor to wall intersection"
417
430
  parapet: 0.056000, # "parapet" edge
418
431
  roof: 0.020000, # (non-parapet) "roof" edge
432
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
419
433
  fenestration: 0.171000, # "wall to vertical fenestration intersection"
420
434
  door: 0.000000, # (unspecified, defaults to 0)
421
435
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -436,6 +450,7 @@ module TBD
436
450
  rimjoist: 0.582000, # "intermediate floor to wall intersection"
437
451
  parapet: 0.056000, # "parapet" edge
438
452
  roof: 0.150000, # (non-parapet) "roof" edge
453
+ ceiling: 0.000000, # e.g. suspended ceiling tiles
439
454
  fenestration: 0.260000, # "wall to vertical fenestration intersection"
440
455
  door: 0.000000, # (unspecified, defaults to 0)
441
456
  skylight: 0.000000, # (unspecified, defaults to 0)
@@ -452,20 +467,22 @@ module TBD
452
467
 
453
468
  @set["(non thermal bridging)"] =
454
469
  {
455
- rimjoist: 0.000000, # defaults to 0
456
- parapet: 0.000000, # defaults to 0
457
- roof: 0.000000, # defaults to 0
458
- fenestration: 0.000000, # defaults to 0
459
- door: 0.000000, # defaults to 0
460
- skylight: 0.000000, # defaults to 0
461
- spandrel: 0.000000, # defaults to 0
462
- corner: 0.000000, # defaults to 0
463
- balcony: 0.000000, # defaults to 0
464
- balconysill: 0.000000, # defaults to 0
465
- party: 0.000000, # defaults to 0
466
- grade: 0.000000, # defaults to 0
467
- joint: 0.000000, # defaults to 0
468
- transition: 0.000000 # defaults to 0
470
+ rimjoist: 0.000000, # defaults to 0
471
+ parapet: 0.000000, # defaults to 0
472
+ roof: 0.000000, # defaults to 0
473
+ ceiling: 0.000000, # defaults to 0
474
+ fenestration: 0.000000, # defaults to 0
475
+ door: 0.000000, # defaults to 0
476
+ skylight: 0.000000, # defaults to 0
477
+ spandrel: 0.000000, # defaults to 0
478
+ corner: 0.000000, # defaults to 0
479
+ balcony: 0.000000, # defaults to 0
480
+ balconysill: 0.000000, # defaults to 0
481
+ balconydoorsill: 0.000000, # defaults to 0
482
+ party: 0.000000, # defaults to 0
483
+ grade: 0.000000, # defaults to 0
484
+ joint: 0.000000, # defaults to 0
485
+ transition: 0.000000 # defaults to 0
469
486
  }.freeze
470
487
 
471
488
  @set.keys.each { |k| self.gen(k) }
@@ -530,6 +547,9 @@ module TBD
530
547
  h[:roof ] = @set[id].key?(:roof)
531
548
  h[:roofconcave ] = @set[id].key?(:roofconcave)
532
549
  h[:roofconvex ] = @set[id].key?(:roofconvex)
550
+ h[:ceiling ] = @set[id].key?(:ceiling)
551
+ h[:ceilingconcave ] = @set[id].key?(:ceilingconcave)
552
+ h[:ceilingconvex ] = @set[id].key?(:ceilingconvex)
533
553
  h[:grade ] = @set[id].key?(:grade)
534
554
  h[:gradeconcave ] = @set[id].key?(:gradeconcave)
535
555
  h[:gradeconvex ] = @set[id].key?(:gradeconvex)
@@ -562,6 +582,7 @@ module TBD
562
582
  v[:corner ] = 0; v[:cornerconcave ] = 0; v[:cornerconvex ] = 0
563
583
  v[:parapet ] = 0; v[:parapetconcave ] = 0; v[:parapetconvex ] = 0
564
584
  v[:roof ] = 0; v[:roofconcave ] = 0; v[:roofconvex ] = 0
585
+ v[:ceiling ] = 0; v[:ceilingconcave ] = 0; v[:ceilingconvex ] = 0
565
586
  v[:party ] = 0; v[:partyconcave ] = 0; v[:partyconvex ] = 0
566
587
  v[:grade ] = 0; v[:gradeconcave ] = 0; v[:gradeconvex ] = 0
567
588
  v[:balcony ] = 0; v[:balconyconcave ] = 0; v[:balconyconvex ] = 0
@@ -697,6 +718,11 @@ module TBD
697
718
  v[:roofconvex ] = @set[id][:roof ] if h[:roof ]
698
719
  v[:roofconcave ] = @set[id][:roofconcave ] if h[:roofconcave ]
699
720
  v[:roofconvex ] = @set[id][:roofconvex ] if h[:roofconvex ]
721
+ v[:ceiling ] = @set[id][:ceiling ] if h[:ceiling ]
722
+ v[:ceilingconcave ] = @set[id][:ceiling ] if h[:ceiling ]
723
+ v[:ceilingconvex ] = @set[id][:ceiling ] if h[:ceiling ]
724
+ v[:ceilingconcave ] = @set[id][:ceilingconcave ] if h[:ceilingconcave ]
725
+ v[:ceilingconvex ] = @set[id][:ceilingconvex ] if h[:ceilingconvex ]
700
726
  v[:party ] = @set[id][:party ] if h[:party ]
701
727
  v[:partyconcave ] = @set[id][:party ] if h[:party ]
702
728
  v[:partyconvex ] = @set[id][:party ] if h[:party ]
@@ -764,6 +790,7 @@ module TBD
764
790
 
765
791
  max = [v[:roofconcave], v[:roofconvex]].max
766
792
  v[:roof] = max unless @has[:roof]
793
+
767
794
  @val[id] = v
768
795
 
769
796
  true
@@ -783,6 +810,9 @@ module TBD
783
810
  # @option set [#to_f] :roof roof-to-wall intersection
784
811
  # @option set [#to_f] :roofconcave basilaire variant
785
812
  # @option set [#to_f] :roofconvex typical
813
+ # @option set [#to_f] :ceiling intermediate (uninsulated) ceiling perimeter
814
+ # @option set [#to_f] :ceilingconcave cantilever variant
815
+ # @option set [#to_f] :ceilingconvex colonnade variant
786
816
  # @option set [#to_f] :fenestration head/sill/jamb interface
787
817
  # @option set [#to_f] :head (fenestrated) header interface
788
818
  # @option set [#to_f] :headconcave (fenestrated) basilaire variant
@@ -870,6 +900,9 @@ module TBD
870
900
  s[:roof ] = set[:roof ] if set.key?(:roof)
871
901
  s[:roofconcave ] = set[:roofconcave ] if set.key?(:roofconcave)
872
902
  s[:roofconvex ] = set[:roofconvex ] if set.key?(:roofconvex)
903
+ s[:ceiling ] = set[:ceiling ] if set.key?(:ceiling)
904
+ s[:ceilingconcave ] = set[:ceilingconcave ] if set.key?(:ceilingconcave)
905
+ s[:ceilingconvex ] = set[:ceilingconvex ] if set.key?(:ceilingconvex)
873
906
  s[:fenestration ] = set[:fenestration ] if set.key?(:fenestration)
874
907
  s[:head ] = set[:head ] if set.key?(:head)
875
908
  s[:headconcave ] = set[:headconcave ] if set.key?(:headconcave)
@@ -926,6 +959,7 @@ module TBD
926
959
 
927
960
  s[:joint ] = 0.000 unless set.key?(:joint)
928
961
  s[:transition ] = 0.000 unless set.key?(:transition)
962
+ s[:ceiling ] = 0.000 unless set.key?(:ceiling)
929
963
 
930
964
  @set[id] = s
931
965
  self.gen(id)
@@ -941,13 +975,13 @@ module TBD
941
975
  #
942
976
  # @param id [#to_s] PSI set identifier
943
977
  # @example intermediate floor slab intersection
944
- # shorthands("A901")
978
+ # shorthands("90.1.22|steel.m|default")
945
979
  #
946
980
  # @return [Hash] has: Hash (Bool), val: Hash (PSI factors) see logs if empty
947
981
  def shorthands(id = "")
948
982
  mth = "TBD::#{__callee__}"
949
983
  sh = { has: {}, val: {} }
950
- id = trim(id)
984
+ id = trim(id)
951
985
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
952
986
  return hashkey(id, @set , id, mth, ERR, sh) unless @set.key?(id)
953
987
  return hashkey(id, @has , id, mth, ERR, sh) unless @has.key?(id)
@@ -969,7 +1003,7 @@ module TBD
969
1003
  def complete?(id = "")
970
1004
  mth = "TBD::#{__callee__}"
971
1005
  a = false
972
- id = trim(id)
1006
+ id = trim(id)
973
1007
  return mismatch("set ID", id, String, mth, ERR, a) if id.empty?
974
1008
  return hashkey(id, @set , id, mth, ERR, a) unless @set.key?(id)
975
1009
  return hashkey(id, @has , id, mth, ERR, a) unless @has.key?(id)
@@ -1564,14 +1598,14 @@ module TBD
1564
1598
  tr = transforms(group)
1565
1599
  t = tr[:t] if tr[:t] && tr[:r]
1566
1600
 
1567
- log(FTL, "Can't process '#{id}' transformation (#{mth})") unless t
1568
- return tbd unless t
1601
+ log(ERR, "Can't process '#{id}' transformation (#{mth})") unless t
1602
+ next unless t
1569
1603
 
1570
1604
  space = group.space
1571
1605
  tr[:r] += space.get.directionofRelativeNorth unless space.empty?
1572
- n = trueNormal(s, tr[:r])
1573
- log(FTL, "Can't process '#{id}' true normal (#{mth})") unless n
1574
- return tbd unless n
1606
+ n = truNormal(s, tr[:r])
1607
+ log(ERR, "Can't process '#{id}' true normal (#{mth})") unless n
1608
+ next unless n
1575
1609
 
1576
1610
  points = (t * s.vertices).map { |v| Topolys::Point3D.new(v.x, v.y, v.z) }
1577
1611
 
@@ -1661,14 +1695,10 @@ module TBD
1661
1695
  dx = (origin.x - terminal.x).abs
1662
1696
  dy = (origin.y - terminal.y).abs
1663
1697
  dz = (origin.z - terminal.z).abs
1664
- horizontal = dz.abs < TOL
1698
+ horizontal = dz < TOL
1665
1699
  vertical = dx < TOL && dy < TOL
1666
1700
  edge_V = terminal - origin
1667
-
1668
- if edge_V.magnitude < TOL
1669
- invalid("1x edge length < TOL", mth, 0, ERROR)
1670
- next
1671
- end
1701
+ next if edge_V.magnitude < TOL
1672
1702
 
1673
1703
  edge_plane = Topolys::Plane3D.new(origin, edge_V)
1674
1704
 
@@ -1732,10 +1762,8 @@ module TBD
1732
1762
  farthest_V = origin_point_V if farther
1733
1763
  end
1734
1764
 
1735
- angle = reference_V.angle(farthest_V)
1736
- invalid("#{id} polar angle", mth, 0, ERROR, 0) if angle.nil?
1737
- angle = 0 if angle.nil?
1738
-
1765
+ angle = reference_V.angle(farthest_V)
1766
+ angle = 0 if angle.nil?
1739
1767
  adjust = false # adjust angle [180°, 360°] if necessary
1740
1768
 
1741
1769
  if vertical
@@ -1853,9 +1881,6 @@ module TBD
1853
1881
 
1854
1882
  # Evaluate current set content before processing a new linked surface.
1855
1883
  is = {}
1856
- is[:head ] = set.keys.to_s.include?("head")
1857
- is[:sill ] = set.keys.to_s.include?("sill")
1858
- is[:jamb ] = set.keys.to_s.include?("jamb")
1859
1884
  is[:doorhead ] = set.keys.to_s.include?("doorhead")
1860
1885
  is[:doorsill ] = set.keys.to_s.include?("doorsill")
1861
1886
  is[:doorjamb ] = set.keys.to_s.include?("doorjamb")
@@ -1866,6 +1891,7 @@ module TBD
1866
1891
  is[:corner ] = set.keys.to_s.include?("corner")
1867
1892
  is[:parapet ] = set.keys.to_s.include?("parapet")
1868
1893
  is[:roof ] = set.keys.to_s.include?("roof")
1894
+ is[:ceiling ] = set.keys.to_s.include?("ceiling")
1869
1895
  is[:party ] = set.keys.to_s.include?("party")
1870
1896
  is[:grade ] = set.keys.to_s.include?("grade")
1871
1897
  is[:balcony ] = set.keys.to_s.include?("balcony")
@@ -1873,6 +1899,12 @@ module TBD
1873
1899
  is[:balconydoorsill ] = set.keys.to_s.include?("balconydoorsill")
1874
1900
  is[:rimjoist ] = set.keys.to_s.include?("rimjoist")
1875
1901
 
1902
+ if is.empty?
1903
+ is[:head] = set.keys.to_s.include?("head")
1904
+ is[:sill] = set.keys.to_s.include?("sill")
1905
+ is[:jamb] = set.keys.to_s.include?("jamb")
1906
+ end
1907
+
1876
1908
  # Label edge as ...
1877
1909
  # :head, :sill, :jamb (vertical fenestration)
1878
1910
  # :doorhead, :doorsill, :doorjamb (opaque door)
@@ -2092,6 +2124,41 @@ module TBD
2092
2124
  is[:corner ] = true
2093
2125
  end
2094
2126
 
2127
+ # Label edge as :ceiling if linked to:
2128
+ # +1 deratable surfaces
2129
+ # 1x underatable CONDITIONED floor linked to an unoccupied space
2130
+ # 1x adjacent CONDITIONED ceiling linked to an occupied space
2131
+ edge[:surfaces].keys.each do |i|
2132
+ break if is[:ceiling]
2133
+ break unless deratables.size > 0
2134
+ break if floors.key?(id)
2135
+ next if i == id
2136
+ next unless floors.key?(i)
2137
+ next if floors[i][:ground ]
2138
+ next unless floors[i][:conditioned]
2139
+ next if floors[i][:occupied ]
2140
+
2141
+ ceiling = floors[i][:boundary]
2142
+ next unless ceilings.key?(ceiling)
2143
+ next unless ceilings[ceiling][:conditioned]
2144
+ next unless ceilings[ceiling][:occupied ]
2145
+
2146
+ other = deratables.first unless deratables.first == id
2147
+ other = deratables.last unless deratables.last == id
2148
+ other = id if deratables.size == 1
2149
+
2150
+ s1 = edge[:surfaces][id]
2151
+ s2 = edge[:surfaces][other]
2152
+ concave = concave?(s1, s2)
2153
+ convex = convex?(s1, s2)
2154
+ flat = !concave && !convex
2155
+
2156
+ set[:ceiling ] = shorts[:val][:ceiling ] if flat
2157
+ set[:ceilingconcave] = shorts[:val][:ceilingconcave] if concave
2158
+ set[:ceilingconvex ] = shorts[:val][:ceilingconvex ] if convex
2159
+ is[:ceiling ] = true
2160
+ end
2161
+
2095
2162
  # Label edge as :parapet/:roof if linked to:
2096
2163
  # 1x deratable wall
2097
2164
  # 1x deratable ceiling
@@ -2172,22 +2239,23 @@ module TBD
2172
2239
  is[:grade ] = true
2173
2240
  end
2174
2241
 
2175
- # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill if linked to:
2242
+ # Label edge as :rimjoist, :balcony, :balconysill or :balconydoorsill,
2243
+ # if linked to:
2176
2244
  # 1x deratable surface
2177
2245
  # 1x CONDITIONED floor
2178
2246
  # 1x shade (optional)
2179
2247
  # 1x subsurface (optional)
2180
- #
2181
- # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2182
- # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2183
- # fenestratio/door head. ASHRAE 90.1 2022 does not make the distinction
2184
- # between sill vs head when intermediatre floor, balcony and vertical
2185
- # fenestration meet. 'Sills' are simply the most common occurrence.
2186
2248
  balcony = false
2187
2249
  balconysill = false # vertical fenestration
2188
2250
  balconydoorsill = false # opaque door
2189
2251
 
2252
+ # Despite referring to 'sill' or 'doorsill', a 'balconysill' or
2253
+ # 'balconydoorsill' edge may instead link (rarer) cases of balcony and a
2254
+ # fenestration/door head. ASHRAE 90.1 2022 does not make the distinction
2255
+ # between sill vs head when intermediate floor, balcony and vertical
2256
+ # fenestration meet. 'Sills' are simply the most common occurrence.
2190
2257
  edge[:surfaces].keys.each do |i|
2258
+ break if is[:ceiling]
2191
2259
  break if balcony
2192
2260
  next if i == id
2193
2261
 
@@ -2259,15 +2327,17 @@ module TBD
2259
2327
  end
2260
2328
 
2261
2329
  edge[:surfaces].keys.each do |i|
2262
- break if is[:rimjoist ] || is[:balcony ] ||
2263
- is[:balconysill] || is[:balconydoorsill]
2330
+ break if is[:ceiling ]
2331
+ break if is[:rimjoist ]
2332
+ break if is[:balcony ]
2333
+ break if is[:balconysill ]
2334
+ break if is[:balconydoorsill]
2264
2335
  break unless deratables.size > 0
2265
2336
  break if floors.key?(id)
2266
2337
  next if i == id
2267
2338
  next unless floors.key?(i)
2268
- next unless floors[i].key?(:conditioned)
2269
- next unless floors[i][:conditioned]
2270
2339
  next if floors[i][:ground ]
2340
+ next unless floors[i][:conditioned]
2271
2341
 
2272
2342
  other = deratables.first unless deratables.first == id
2273
2343
  other = deratables.last unless deratables.last == id
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
  #
3
- # Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
3
+ # Copyright (c) 2020-2024 Denis Bourgeois & Dan Macumber
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -1000,7 +1000,7 @@ module TBD
1000
1000
  model = "* modèle : #{ua[:file]}" if ua.key?(:file) && lang == :fr
1001
1001
  model += " (v#{ua[:version]})" if ua.key?(:version)
1002
1002
  report << model unless model.empty?
1003
- report << "* TBD : v3.3.0"
1003
+ report << "* TBD : v3.4.0"
1004
1004
  report << "* date : #{ua[:date]}"
1005
1005
 
1006
1006
  if lang == :en