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 +4 -4
- data/.github/workflows/pull_request.yml +2 -2
- data/LICENSE.md +1 -1
- data/json/tbd_z5.json +12 -0
- data/lib/measures/tbd/LICENSE.md +1 -1
- data/lib/measures/tbd/measure.rb +1 -1
- data/lib/measures/tbd/measure.xml +11 -11
- data/lib/measures/tbd/resources/geo.rb +7 -6
- data/lib/measures/tbd/resources/oslog.rb +1 -1
- data/lib/measures/tbd/resources/psi.rb +117 -47
- data/lib/measures/tbd/resources/tbd.rb +1 -1
- data/lib/measures/tbd/resources/ua.rb +2 -2
- data/lib/measures/tbd/resources/utils.rb +4365 -1052
- data/lib/measures/tbd/tests/tbd_tests.rb +1 -1
- data/lib/tbd/geo.rb +7 -6
- data/lib/tbd/psi.rb +117 -47
- data/lib/tbd/ua.rb +2 -2
- data/lib/tbd/version.rb +2 -2
- data/lib/tbd.rb +1 -1
- data/tbd.gemspec +1 -1
- data/tbd.schema.json +15 -0
- metadata +5 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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/lib/tbd/geo.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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
|
|
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,
|
|
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,
|
|
295
|
+
return invalid("#{nom} transform", mth, 0, ERR) unless tr[:t] && tr[:r]
|
|
296
296
|
|
|
297
297
|
t = tr[:t]
|
|
298
|
-
n =
|
|
299
|
-
return invalid("#{nom} normal", mth, 0,
|
|
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
|
data/lib/tbd/psi.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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:
|
|
456
|
-
parapet:
|
|
457
|
-
roof:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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("
|
|
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
|
|
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
|
|
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(
|
|
1568
|
-
|
|
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 =
|
|
1573
|
-
log(
|
|
1574
|
-
|
|
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
|
|
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
|
|
1736
|
-
|
|
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
|
|
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[:
|
|
2263
|
-
|
|
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
|
data/lib/tbd/ua.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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.
|
|
1003
|
+
report << "* TBD : v3.4.0"
|
|
1004
1004
|
report << "* date : #{ua[:date]}"
|
|
1005
1005
|
|
|
1006
1006
|
if lang == :en
|
data/lib/tbd/version.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
23
|
module TBD
|
|
24
|
-
VERSION = "3.
|
|
24
|
+
VERSION = "3.4.1".freeze # TBD release version
|
|
25
25
|
end
|
data/lib/tbd.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
#
|
|
3
|
-
# Copyright (c) 2020-
|
|
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/tbd.gemspec
CHANGED
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
s.bindir = "exe"
|
|
26
26
|
s.require_paths = ["lib"]
|
|
27
27
|
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
-
s.required_ruby_version = [">= 2.5.0", "<
|
|
28
|
+
s.required_ruby_version = [">= 2.5.0", "< 4"]
|
|
29
29
|
s.metadata = {}
|
|
30
30
|
|
|
31
31
|
s.add_dependency "topolys", "~> 0"
|
data/tbd.schema.json
CHANGED
|
@@ -122,6 +122,18 @@
|
|
|
122
122
|
"title": "Convex (other than parapet/overhang) roof/wall edge PSI",
|
|
123
123
|
"type": "number"
|
|
124
124
|
},
|
|
125
|
+
"ceiling": {
|
|
126
|
+
"title": "Intermediate ceiling (not floor) edge PSI",
|
|
127
|
+
"type": "number"
|
|
128
|
+
},
|
|
129
|
+
"ceilingconcave": {
|
|
130
|
+
"title": "Concave intermediate ceiling (not floor) edge PSI",
|
|
131
|
+
"type": "number"
|
|
132
|
+
},
|
|
133
|
+
"ceilingconvex": {
|
|
134
|
+
"title": "Convex intermediate ceiling (not floor) edge PSI",
|
|
135
|
+
"type": "number"
|
|
136
|
+
},
|
|
125
137
|
"fenestration": {
|
|
126
138
|
"title": "Window or glazed door perimeter PSI",
|
|
127
139
|
"type": "number"
|
|
@@ -369,6 +381,9 @@
|
|
|
369
381
|
"roof",
|
|
370
382
|
"roofconcave",
|
|
371
383
|
"roofconvex",
|
|
384
|
+
"ceiling",
|
|
385
|
+
"ceilingconcave",
|
|
386
|
+
"ceilingconvex",
|
|
372
387
|
"fenestration",
|
|
373
388
|
"head",
|
|
374
389
|
"headconcave",
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tbd
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Denis Bourgeois & Dan Macumber
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-04-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: topolys
|
|
@@ -133,6 +133,7 @@ files:
|
|
|
133
133
|
- json/tbd_warehouse17.json
|
|
134
134
|
- json/tbd_warehouse18.json
|
|
135
135
|
- json/tbd_warehouse4.json
|
|
136
|
+
- json/tbd_z5.json
|
|
136
137
|
- lib/measures/tbd/LICENSE.md
|
|
137
138
|
- lib/measures/tbd/README.md
|
|
138
139
|
- lib/measures/tbd/README.md.erb
|
|
@@ -165,7 +166,7 @@ licenses:
|
|
|
165
166
|
- MIT
|
|
166
167
|
metadata:
|
|
167
168
|
homepage_uri: https://github.com/rd2/tbd
|
|
168
|
-
source_code_uri: https://github.com/rd2/tbd/tree/v3.
|
|
169
|
+
source_code_uri: https://github.com/rd2/tbd/tree/v3.4.1
|
|
169
170
|
bug_tracker_uri: https://github.com/rd2/tbd/issues
|
|
170
171
|
post_install_message:
|
|
171
172
|
rdoc_options: []
|
|
@@ -178,7 +179,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
178
179
|
version: 2.5.0
|
|
179
180
|
- - "<"
|
|
180
181
|
- !ruby/object:Gem::Version
|
|
181
|
-
version: '
|
|
182
|
+
version: '4'
|
|
182
183
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
184
|
requirements:
|
|
184
185
|
- - ">="
|