tbd 3.3.0 → 3.4.1

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: 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