osut 0.2.6 → 0.2.7
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/lib/osut/utils.rb +336 -70
- data/lib/osut/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6bbbc6887949cfd0d1aed5c460d993196fa86d1a13f366f7f852e418aa9457a0
|
4
|
+
data.tar.gz: b38eaa81d84a79655adb10a06bb1fa299ffff60051d187f2b36bad38fa4d78e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1eb2cd49987ce2a4bf7a6a9fe0ed7048bc78dce644aa88e68173861ce4e52fc2bfe59bb3c4a7b353426a1bfa30f45af102ca3e509ac91945b82673545f1a4d4d
|
7
|
+
data.tar.gz: bb8075d22d660b3f177716463baf3bc2b0e788269dc05f60086272dc5fec193b93a207f94500fa26cf8d786fdcd3810c0d3defb50eca4c39b3a05cf7c8d2412c
|
data/lib/osut/utils.rb
CHANGED
@@ -628,7 +628,7 @@ module OSut
|
|
628
628
|
mth = "OSut::#{__callee__}"
|
629
629
|
cl = OpenStudio::Model::Model
|
630
630
|
|
631
|
-
return mismatch("model", model, cl, mth, DBG, false)
|
631
|
+
return mismatch("model", model, cl, mth, DBG, false) unless model.is_a?(cl)
|
632
632
|
|
633
633
|
model.getThermalZones.each do |zone|
|
634
634
|
return true if minCoolScheduledSetpoint(zone)[:spt]
|
@@ -648,12 +648,12 @@ module OSut
|
|
648
648
|
mth = "OSut::#{__callee__}"
|
649
649
|
cl = OpenStudio::Model::Model
|
650
650
|
|
651
|
-
return mismatch("model", model, cl, mth, DBG, false)
|
651
|
+
return mismatch("model", model, cl, mth, DBG, false) unless model.is_a?(cl)
|
652
652
|
|
653
653
|
model.getThermalZones.each do |zone|
|
654
|
-
next
|
655
|
-
return true
|
656
|
-
return true
|
654
|
+
next if zone.canBePlenum
|
655
|
+
return true unless zone.airLoopHVACs.empty?
|
656
|
+
return true if zone.isPlenum
|
657
657
|
end
|
658
658
|
|
659
659
|
false
|
@@ -678,7 +678,7 @@ module OSut
|
|
678
678
|
# A space may be tagged as a plenum if:
|
679
679
|
#
|
680
680
|
# CASE A: its zone's "isPlenum" == true (SDK method) for a fully-developed
|
681
|
-
# OpenStudio model (complete with HVAC air loops);
|
681
|
+
# OpenStudio model (complete with HVAC air loops); OR
|
682
682
|
#
|
683
683
|
# CASE B: (IN ABSENCE OF HVAC AIRLOOPS) if it's excluded from a building's
|
684
684
|
# total floor area yet linked to a zone holding an 'inactive'
|
@@ -737,8 +737,8 @@ module OSut
|
|
737
737
|
cl = OpenStudio::Model::Model
|
738
738
|
limits = nil
|
739
739
|
|
740
|
-
return mismatch("model", model, cl, mth)
|
741
|
-
return invalid("availability", avl, 2, mth)
|
740
|
+
return mismatch("model", model, cl, mth) unless model.is_a?(cl)
|
741
|
+
return invalid("availability", avl, 2, mth) unless avl.respond_to?(:to_s)
|
742
742
|
|
743
743
|
# Either fetch availability ScheduleTypeLimits object, or create one.
|
744
744
|
model.getScheduleTypeLimitss.each do |l|
|
@@ -769,9 +769,9 @@ module OSut
|
|
769
769
|
off = OpenStudio::Model::ScheduleDay.new(model, 0)
|
770
770
|
|
771
771
|
# Seasonal availability start/end dates.
|
772
|
-
year
|
773
|
-
return
|
774
|
-
year
|
772
|
+
year = model.yearDescription
|
773
|
+
return empty("yearDescription", mth, ERR) if year.empty?
|
774
|
+
year = year.get
|
775
775
|
may01 = year.makeDate(OpenStudio::MonthOfYear.new("May"), 1)
|
776
776
|
oct31 = year.makeDate(OpenStudio::MonthOfYear.new("Oct"), 31)
|
777
777
|
|
@@ -957,17 +957,17 @@ module OSut
|
|
957
957
|
cl1 = OpenStudio::Model::Model
|
958
958
|
cl2 = OpenStudio::Model::Surface
|
959
959
|
|
960
|
-
return mismatch("model", model, cl1, mth)
|
961
|
-
return invalid("s", mth, 2)
|
962
|
-
id
|
963
|
-
return mismatch(id, s, cl2, mth)
|
960
|
+
return mismatch("model", model, cl1, mth) unless model.is_a?(cl1)
|
961
|
+
return invalid("s", mth, 2) unless s.respond_to?(NS)
|
962
|
+
id = s.nameString
|
963
|
+
return mismatch(id, s, cl2, mth) unless s.is_a?(cl2)
|
964
964
|
|
965
965
|
ok = s.isConstructionDefaulted
|
966
966
|
log(ERR, "'#{id}' construction not defaulted (#{mth})") unless ok
|
967
967
|
return nil unless ok
|
968
|
-
return empty("'#{id}' construction", mth, ERR)
|
968
|
+
return empty("'#{id}' construction", mth, ERR) if s.construction.empty?
|
969
969
|
base = s.construction.get
|
970
|
-
return empty("'#{id}' space", mth, ERR)
|
970
|
+
return empty("'#{id}' space", mth, ERR) if s.space.empty?
|
971
971
|
space = s.space.get
|
972
972
|
type = s.surfaceType
|
973
973
|
ground = false
|
@@ -981,7 +981,7 @@ module OSut
|
|
981
981
|
|
982
982
|
unless space.defaultConstructionSet.empty?
|
983
983
|
set = space.defaultConstructionSet.get
|
984
|
-
return set
|
984
|
+
return set if holdsConstruction?(set, base, ground, exterior, type)
|
985
985
|
end
|
986
986
|
|
987
987
|
unless space.spaceType.empty?
|
@@ -989,7 +989,7 @@ module OSut
|
|
989
989
|
|
990
990
|
unless spacetype.defaultConstructionSet.empty?
|
991
991
|
set = spacetype.defaultConstructionSet.get
|
992
|
-
return set
|
992
|
+
return set if holdsConstruction?(set, base, ground, exterior, type)
|
993
993
|
end
|
994
994
|
end
|
995
995
|
|
@@ -998,7 +998,7 @@ module OSut
|
|
998
998
|
|
999
999
|
unless story.defaultConstructionSet.empty?
|
1000
1000
|
set = story.defaultConstructionSet.get
|
1001
|
-
return set
|
1001
|
+
return set if holdsConstruction?(set, base, ground, exterior, type)
|
1002
1002
|
end
|
1003
1003
|
end
|
1004
1004
|
|
@@ -1006,7 +1006,7 @@ module OSut
|
|
1006
1006
|
|
1007
1007
|
unless building.defaultConstructionSet.empty?
|
1008
1008
|
set = building.defaultConstructionSet.get
|
1009
|
-
return set
|
1009
|
+
return set if holdsConstruction?(set, base, ground, exterior, type)
|
1010
1010
|
end
|
1011
1011
|
|
1012
1012
|
nil
|
@@ -1036,15 +1036,15 @@ module OSut
|
|
1036
1036
|
#
|
1037
1037
|
# @param lc [OpenStudio::LayeredConstruction] a layered construction
|
1038
1038
|
#
|
1039
|
-
# @return [
|
1040
|
-
# @return [
|
1039
|
+
# @return [Float] total layered construction thickness
|
1040
|
+
# @return [Float] 0 if invalid input
|
1041
1041
|
def thickness(lc = nil)
|
1042
1042
|
mth = "OSut::#{__callee__}"
|
1043
1043
|
cl = OpenStudio::Model::LayeredConstruction
|
1044
1044
|
|
1045
|
-
return invalid("lc", mth, 1, DBG, 0.0)
|
1045
|
+
return invalid("lc", mth, 1, DBG, 0.0) unless lc.respond_to?(NS)
|
1046
1046
|
id = lc.nameString
|
1047
|
-
return mismatch(id, lc, cl, mth, DBG, 0.0)
|
1047
|
+
return mismatch(id, lc, cl, mth, DBG, 0.0) unless lc.is_a?(cl)
|
1048
1048
|
|
1049
1049
|
ok = standardOpaqueLayers?(lc)
|
1050
1050
|
log(ERR, "'#{id}' holds non-StandardOpaqueMaterial(s) (#{mth})") unless ok
|
@@ -1166,9 +1166,9 @@ module OSut
|
|
1166
1166
|
res = { index: nil, type: nil, r: 0.0 }
|
1167
1167
|
i = 0 # iterator
|
1168
1168
|
|
1169
|
-
return invalid("lc", mth, 1, DBG, res)
|
1170
|
-
id
|
1171
|
-
return mismatch(id, lc, cl1, mth, DBG, res)
|
1169
|
+
return invalid("lc", mth, 1, DBG, res) unless lc.respond_to?(NS)
|
1170
|
+
id = lc.nameString
|
1171
|
+
return mismatch(id, lc, cl1, mth, DBG, res) unless lc.is_a?(cl)
|
1172
1172
|
|
1173
1173
|
lc.layers.each do |m|
|
1174
1174
|
unless m.to_MasslessOpaqueMaterial.empty?
|
@@ -1178,9 +1178,9 @@ module OSut
|
|
1178
1178
|
i += 1
|
1179
1179
|
next
|
1180
1180
|
else
|
1181
|
-
res[:r]
|
1181
|
+
res[:r ] = m.thermalResistance
|
1182
1182
|
res[:index] = i
|
1183
|
-
res[:type]
|
1183
|
+
res[:type ] = :massless
|
1184
1184
|
end
|
1185
1185
|
end
|
1186
1186
|
|
@@ -1193,9 +1193,9 @@ module OSut
|
|
1193
1193
|
i += 1
|
1194
1194
|
next
|
1195
1195
|
else
|
1196
|
-
res[:r]
|
1196
|
+
res[:r ] = d / k
|
1197
1197
|
res[:index] = i
|
1198
|
-
res[:type]
|
1198
|
+
res[:type ] = :standard
|
1199
1199
|
end
|
1200
1200
|
end
|
1201
1201
|
|
@@ -1230,6 +1230,28 @@ module OSut
|
|
1230
1230
|
res
|
1231
1231
|
end
|
1232
1232
|
|
1233
|
+
##
|
1234
|
+
# Return a scalar product of an OpenStudio Vector3d.
|
1235
|
+
#
|
1236
|
+
# @param v [OpenStudio::Vector3d] a vector
|
1237
|
+
# @param m [Float] a scalar
|
1238
|
+
#
|
1239
|
+
# @return [OpenStudio::Vector3d] modified vector
|
1240
|
+
# @return [OpenStudio::Vector3d] provided (or empty) vector if invalid input
|
1241
|
+
def scalar(v = OpenStudio::Vector3d.new(0,0,0), m = 0)
|
1242
|
+
mth = "OSut::#{__callee__}"
|
1243
|
+
cl1 = OpenStudio::Vector3d
|
1244
|
+
cl2 = Numeric
|
1245
|
+
|
1246
|
+
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)
|
1251
|
+
|
1252
|
+
OpenStudio::Vector3d.new(m * v.x, m * v.y, m * v.z)
|
1253
|
+
end
|
1254
|
+
|
1233
1255
|
##
|
1234
1256
|
# Flatten OpenStudio 3D points vs Z-axis (Z=0).
|
1235
1257
|
#
|
@@ -1243,8 +1265,8 @@ module OSut
|
|
1243
1265
|
v = OpenStudio::Point3dVector.new
|
1244
1266
|
|
1245
1267
|
valid = pts.is_a?(cl1) || pts.is_a?(Array)
|
1246
|
-
return mismatch("points", pts, cl1, mth, DBG, v)
|
1247
|
-
pts.each { |pt| mismatch("pt", pt, cl2, mth, ERR, v)
|
1268
|
+
return mismatch("points", pts, cl1, mth, DBG, v) unless valid
|
1269
|
+
pts.each { |pt| mismatch("pt", pt, cl2, mth, ERR, v) unless pt.is_a?(cl2) }
|
1248
1270
|
pts.each { |pt| v << OpenStudio::Point3d.new(pt.x, pt.y, 0) }
|
1249
1271
|
|
1250
1272
|
v
|
@@ -1268,40 +1290,47 @@ module OSut
|
|
1268
1290
|
|
1269
1291
|
return invalid("id1", mth, 3, DBG, a) unless id1.respond_to?(:to_s)
|
1270
1292
|
return invalid("id2", mth, 4, DBG, a) unless id2.respond_to?(:to_s)
|
1293
|
+
|
1271
1294
|
i1 = id1.to_s
|
1272
1295
|
i2 = id2.to_s
|
1273
1296
|
i1 = "poly1" if i1.empty?
|
1274
1297
|
i2 = "poly2" if i2.empty?
|
1298
|
+
|
1275
1299
|
valid1 = p1.is_a?(cl1) || p1.is_a?(Array)
|
1276
1300
|
valid2 = p2.is_a?(cl1) || p2.is_a?(Array)
|
1301
|
+
|
1277
1302
|
return mismatch(i1, p1, cl1, mth, DBG, a) unless valid1
|
1278
1303
|
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid2
|
1279
|
-
return empty(i1, mth, ERR, a)
|
1280
|
-
return empty(i2, mth, ERR, a)
|
1304
|
+
return empty(i1, mth, ERR, a) if p1.empty?
|
1305
|
+
return empty(i2, mth, ERR, a) if p2.empty?
|
1306
|
+
|
1281
1307
|
p1.each { |v| return mismatch(i1, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1282
1308
|
p2.each { |v| return mismatch(i2, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1283
1309
|
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1310
|
+
# XY-plane transformation matrix ... needs to be clockwise for boost.
|
1311
|
+
ft = OpenStudio::Transformation.alignFace(p1)
|
1312
|
+
ft_p1 = flatZ( (ft.inverse * p1) )
|
1313
|
+
return false if ft_p1.empty?
|
1314
|
+
cw = OpenStudio.pointInPolygon(ft_p1.first, ft_p1, TOL)
|
1315
|
+
ft_p1 = flatZ( (ft.inverse * p1).reverse ) unless cw
|
1316
|
+
ft_p2 = flatZ( (ft.inverse * p2).reverse ) unless cw
|
1317
|
+
ft_p2 = flatZ( (ft.inverse * p2) ) if cw
|
1318
|
+
return false if ft_p2.empty?
|
1319
|
+
area1 = OpenStudio.getArea(ft_p1)
|
1320
|
+
area2 = OpenStudio.getArea(ft_p2)
|
1321
|
+
return empty("#{i1} area", mth, ERR, a) if area1.empty?
|
1322
|
+
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1289
1323
|
area1 = area1.get
|
1290
|
-
ft_p2 = flatZ( (ft * p2).reverse )
|
1291
|
-
return false if ft_p2.empty?
|
1292
|
-
area2 = OpenStudio::getArea(ft_p2)
|
1293
|
-
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1294
1324
|
area2 = area2.get
|
1295
|
-
union = OpenStudio
|
1296
|
-
return
|
1325
|
+
union = OpenStudio.join(ft_p1, ft_p2, TOL2)
|
1326
|
+
return false if union.empty?
|
1297
1327
|
union = union.get
|
1298
|
-
area
|
1299
|
-
return
|
1328
|
+
area = OpenStudio.getArea(union)
|
1329
|
+
return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
|
1300
1330
|
area = area.get
|
1301
|
-
|
1302
|
-
return
|
1303
|
-
return
|
1304
|
-
return false if (area - area2).abs > TOL
|
1331
|
+
return false if area < TOL
|
1332
|
+
return true if (area - area2).abs < TOL
|
1333
|
+
return false if (area - area2).abs > TOL
|
1305
1334
|
|
1306
1335
|
true
|
1307
1336
|
end
|
@@ -1324,42 +1353,279 @@ module OSut
|
|
1324
1353
|
|
1325
1354
|
return invalid("id1", mth, 3, DBG, a) unless id1.respond_to?(:to_s)
|
1326
1355
|
return invalid("id2", mth, 4, DBG, a) unless id2.respond_to?(:to_s)
|
1356
|
+
|
1327
1357
|
i1 = id1.to_s
|
1328
1358
|
i2 = id2.to_s
|
1329
1359
|
i1 = "poly1" if i1.empty?
|
1330
1360
|
i2 = "poly2" if i2.empty?
|
1361
|
+
|
1331
1362
|
valid1 = p1.is_a?(cl1) || p1.is_a?(Array)
|
1332
1363
|
valid2 = p2.is_a?(cl1) || p2.is_a?(Array)
|
1364
|
+
|
1333
1365
|
return mismatch(i1, p1, cl1, mth, DBG, a) unless valid1
|
1334
1366
|
return mismatch(i2, p2, cl1, mth, DBG, a) unless valid2
|
1335
|
-
return empty(i1, mth, ERR, a)
|
1336
|
-
return empty(i2, mth, ERR, a)
|
1367
|
+
return empty(i1, mth, ERR, a) if p1.empty?
|
1368
|
+
return empty(i2, mth, ERR, a) if p2.empty?
|
1369
|
+
|
1337
1370
|
p1.each { |v| return mismatch(i1, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1338
1371
|
p2.each { |v| return mismatch(i2, v, cl2, mth, ERR, a) unless v.is_a?(cl2) }
|
1339
1372
|
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
return
|
1373
|
+
# XY-plane transformation matrix ... needs to be clockwise for boost.
|
1374
|
+
ft = OpenStudio::Transformation.alignFace(p1)
|
1375
|
+
ft_p1 = flatZ( (ft.inverse * p1) )
|
1376
|
+
ft_p2 = flatZ( (ft.inverse * p2) )
|
1377
|
+
return false if ft_p1.empty?
|
1378
|
+
return false if ft_p2.empty?
|
1379
|
+
cw = OpenStudio.pointInPolygon(ft_p1.first, ft_p1, TOL)
|
1380
|
+
ft_p1 = flatZ( (ft.inverse * p1).reverse ) unless cw
|
1381
|
+
ft_p2 = flatZ( (ft.inverse * p2).reverse ) unless cw
|
1382
|
+
return false if ft_p1.empty?
|
1383
|
+
return false if ft_p2.empty?
|
1384
|
+
area1 = OpenStudio.getArea(ft_p1)
|
1385
|
+
area2 = OpenStudio.getArea(ft_p2)
|
1386
|
+
return empty("#{i1} area", mth, ERR, a) if area1.empty?
|
1387
|
+
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1345
1388
|
area1 = area1.get
|
1346
|
-
ft_p2 = flatZ( (ft * p2).reverse )
|
1347
|
-
return false if ft_p2.empty?
|
1348
|
-
area2 = OpenStudio::getArea(ft_p2)
|
1349
|
-
return empty("#{i2} area", mth, ERR, a) if area2.empty?
|
1350
1389
|
area2 = area2.get
|
1351
|
-
union = OpenStudio
|
1352
|
-
return
|
1390
|
+
union = OpenStudio.join(ft_p1, ft_p2, TOL2)
|
1391
|
+
return false if union.empty?
|
1353
1392
|
union = union.get
|
1354
|
-
area
|
1355
|
-
return empty("#{i1}:#{i2} union area", mth, ERR, a)
|
1393
|
+
area = OpenStudio.getArea(union)
|
1394
|
+
return empty("#{i1}:#{i2} union area", mth, ERR, a) if area.empty?
|
1356
1395
|
area = area.get
|
1357
|
-
|
1358
|
-
return false if area < TOL
|
1396
|
+
return false if area < TOL
|
1359
1397
|
|
1360
1398
|
true
|
1361
1399
|
end
|
1362
1400
|
|
1401
|
+
##
|
1402
|
+
# Generate offset vertices (by width) for a 3- or 4-sided, convex polygon.
|
1403
|
+
#
|
1404
|
+
# @param p1 [OpenStudio::Point3dVector] OpenStudio Point3D vector/array
|
1405
|
+
# @param w [Float] offset width (min: 0.0254m)
|
1406
|
+
# @param v [Integer] OpenStudio SDK version, eg '321' for 'v3.2.1' (optional)
|
1407
|
+
#
|
1408
|
+
# @return [OpenStudio::Point3dVector] offset points if successful
|
1409
|
+
# @return [OpenStudio::Point3dVector] original points if invalid input
|
1410
|
+
def offset(p1 = [], w = 0, v = 0)
|
1411
|
+
mth = "TBD::#{__callee__}"
|
1412
|
+
cl = OpenStudio::Point3d
|
1413
|
+
vrsn = OpenStudio.openStudioVersion.split(".").map(&:to_i).join.to_i
|
1414
|
+
|
1415
|
+
valid = p1.is_a?(OpenStudio::Point3dVector) || p1.is_a?(Array)
|
1416
|
+
return mismatch("pts", p1, cl1, mth, DBG, p1) unless valid
|
1417
|
+
return empty("pts", mth, ERR, p1) if p1.empty?
|
1418
|
+
valid = p1.size == 3 || p1.size == 4
|
1419
|
+
iv = true if p1.size == 4
|
1420
|
+
return invalid("pts", mth, 1, DBG, p1) unless valid
|
1421
|
+
return invalid("width", mth, 2, DBG, p1) unless w.respond_to?(:to_f)
|
1422
|
+
w = w.to_f
|
1423
|
+
return p1 if w < 0.0254
|
1424
|
+
v = v.to_i if v.respond_to?(:to_i)
|
1425
|
+
v = 0 unless v.respond_to?(:to_i)
|
1426
|
+
v = vrsn if v.zero?
|
1427
|
+
|
1428
|
+
p1.each { |x| return mismatch("p", x, cl, mth, ERR, p1) unless x.is_a?(cl) }
|
1429
|
+
|
1430
|
+
unless v < 340
|
1431
|
+
# XY-plane transformation matrix ... needs to be clockwise for boost.
|
1432
|
+
ft = OpenStudio::Transformation::alignFace(p1)
|
1433
|
+
ft_pts = flatZ( (ft.inverse * p1) )
|
1434
|
+
return p1 if ft_pts.empty?
|
1435
|
+
cw = OpenStudio::pointInPolygon(ft_pts.first, ft_pts, TOL)
|
1436
|
+
ft_pts = flatZ( (ft.inverse * p1).reverse ) unless cw
|
1437
|
+
offset = OpenStudio.buffer(ft_pts, w, TOL)
|
1438
|
+
return p1 if offset.empty?
|
1439
|
+
offset = offset.get
|
1440
|
+
offset = ft * offset if cw
|
1441
|
+
offset = (ft * offset).reverse unless cw
|
1442
|
+
|
1443
|
+
pz = OpenStudio::Point3dVector.new
|
1444
|
+
offset.each { |o| pz << OpenStudio::Point3d.new(o.x, o.y, o.z ) }
|
1445
|
+
return pz
|
1446
|
+
else # brute force approach
|
1447
|
+
pz = {}
|
1448
|
+
pz[:A] = {}
|
1449
|
+
pz[:B] = {}
|
1450
|
+
pz[:C] = {}
|
1451
|
+
pz[:D] = {} if iv
|
1452
|
+
|
1453
|
+
pz[:A][:p] = OpenStudio::Point3d.new(p1[0].x, p1[0].y, p1[0].z)
|
1454
|
+
pz[:B][:p] = OpenStudio::Point3d.new(p1[1].x, p1[1].y, p1[1].z)
|
1455
|
+
pz[:C][:p] = OpenStudio::Point3d.new(p1[2].x, p1[2].y, p1[2].z)
|
1456
|
+
pz[:D][:p] = OpenStudio::Point3d.new(p1[3].x, p1[3].y, p1[3].z) if iv
|
1457
|
+
|
1458
|
+
pzAp = pz[:A][:p]
|
1459
|
+
pzBp = pz[:B][:p]
|
1460
|
+
pzCp = pz[:C][:p]
|
1461
|
+
pzDp = pz[:D][:p] if iv
|
1462
|
+
|
1463
|
+
# Generate vector pairs, from next point & from previous point.
|
1464
|
+
# :f_n : "from next"
|
1465
|
+
# :f_p : "from previous"
|
1466
|
+
#
|
1467
|
+
#
|
1468
|
+
#
|
1469
|
+
#
|
1470
|
+
#
|
1471
|
+
#
|
1472
|
+
# A <---------- B
|
1473
|
+
# ^
|
1474
|
+
# \
|
1475
|
+
# \
|
1476
|
+
# C (or D)
|
1477
|
+
#
|
1478
|
+
pz[:A][:f_n] = pzAp - pzBp
|
1479
|
+
pz[:A][:f_p] = pzAp - pzCp unless iv
|
1480
|
+
pz[:A][:f_p] = pzAp - pzDp if iv
|
1481
|
+
|
1482
|
+
pz[:B][:f_n] = pzBp - pzCp
|
1483
|
+
pz[:B][:f_p] = pzBp - pzAp
|
1484
|
+
|
1485
|
+
pz[:C][:f_n] = pzCp - pzAp unless iv
|
1486
|
+
pz[:C][:f_n] = pzCp - pzDp if iv
|
1487
|
+
pz[:C][:f_p] = pzCp - pzBp
|
1488
|
+
|
1489
|
+
pz[:D][:f_n] = pzDp - pzAp if iv
|
1490
|
+
pz[:D][:f_p] = pzDp - pzCp if iv
|
1491
|
+
|
1492
|
+
# Generate 3D plane from vectors.
|
1493
|
+
#
|
1494
|
+
#
|
1495
|
+
# | <<< 3D plane ... from point A, with normal B>A
|
1496
|
+
# |
|
1497
|
+
# |
|
1498
|
+
# |
|
1499
|
+
# <---------- A <---------- B
|
1500
|
+
# |\
|
1501
|
+
# | \
|
1502
|
+
# | \
|
1503
|
+
# | C (or D)
|
1504
|
+
#
|
1505
|
+
pz[:A][:pl_f_n] = OpenStudio::Plane.new(pzAp, pz[:A][:f_n])
|
1506
|
+
pz[:A][:pl_f_p] = OpenStudio::Plane.new(pzAp, pz[:A][:f_p])
|
1507
|
+
|
1508
|
+
pz[:B][:pl_f_n] = OpenStudio::Plane.new(pzBp, pz[:B][:f_n])
|
1509
|
+
pz[:B][:pl_f_p] = OpenStudio::Plane.new(pzBp, pz[:B][:f_p])
|
1510
|
+
|
1511
|
+
pz[:C][:pl_f_n] = OpenStudio::Plane.new(pzCp, pz[:C][:f_n])
|
1512
|
+
pz[:C][:pl_f_p] = OpenStudio::Plane.new(pzCp, pz[:C][:f_p])
|
1513
|
+
|
1514
|
+
pz[:D][:pl_f_n] = OpenStudio::Plane.new(pzDp, pz[:D][:f_n]) if iv
|
1515
|
+
pz[:D][:pl_f_p] = OpenStudio::Plane.new(pzDp, pz[:D][:f_p]) if iv
|
1516
|
+
|
1517
|
+
# Project an extended point (pC) unto 3D plane.
|
1518
|
+
#
|
1519
|
+
# pC <<< projected unto extended B>A 3D plane
|
1520
|
+
# eC |
|
1521
|
+
# \ |
|
1522
|
+
# \ |
|
1523
|
+
# \|
|
1524
|
+
# <---------- A <---------- B
|
1525
|
+
# |\
|
1526
|
+
# | \
|
1527
|
+
# | \
|
1528
|
+
# | C (or D)
|
1529
|
+
#
|
1530
|
+
pz[:A][:p_n_pl] = pz[:A][:pl_f_n].project(pz[:A][:p] + pz[:A][:f_p])
|
1531
|
+
pz[:A][:n_p_pl] = pz[:A][:pl_f_p].project(pz[:A][:p] + pz[:A][:f_n])
|
1532
|
+
|
1533
|
+
pz[:B][:p_n_pl] = pz[:B][:pl_f_n].project(pz[:B][:p] + pz[:B][:f_p])
|
1534
|
+
pz[:B][:n_p_pl] = pz[:B][:pl_f_p].project(pz[:B][:p] + pz[:B][:f_n])
|
1535
|
+
|
1536
|
+
pz[:C][:p_n_pl] = pz[:C][:pl_f_n].project(pz[:C][:p] + pz[:C][:f_p])
|
1537
|
+
pz[:C][:n_p_pl] = pz[:C][:pl_f_p].project(pz[:C][:p] + pz[:C][:f_n])
|
1538
|
+
|
1539
|
+
pz[:D][:p_n_pl] = pz[:D][:pl_f_n].project(pz[:D][:p] + pz[:D][:f_p]) if iv
|
1540
|
+
pz[:D][:n_p_pl] = pz[:D][:pl_f_p].project(pz[:D][:p] + pz[:D][:f_n]) if iv
|
1541
|
+
|
1542
|
+
# Generate vector from point (e.g. A) to projected extended point (pC).
|
1543
|
+
#
|
1544
|
+
# pC
|
1545
|
+
# eC ^
|
1546
|
+
# \ |
|
1547
|
+
# \ |
|
1548
|
+
# \|
|
1549
|
+
# <---------- A <---------- B
|
1550
|
+
# |\
|
1551
|
+
# | \
|
1552
|
+
# | \
|
1553
|
+
# | C (or D)
|
1554
|
+
#
|
1555
|
+
pz[:A][:n_p_n_pl] = pz[:A][:p_n_pl] - pzAp
|
1556
|
+
pz[:A][:n_n_p_pl] = pz[:A][:n_p_pl] - pzAp
|
1557
|
+
|
1558
|
+
pz[:B][:n_p_n_pl] = pz[:B][:p_n_pl] - pzBp
|
1559
|
+
pz[:B][:n_n_p_pl] = pz[:B][:n_p_pl] - pzBp
|
1560
|
+
|
1561
|
+
pz[:C][:n_p_n_pl] = pz[:C][:p_n_pl] - pzCp
|
1562
|
+
pz[:C][:n_n_p_pl] = pz[:C][:n_p_pl] - pzCp
|
1563
|
+
|
1564
|
+
pz[:D][:n_p_n_pl] = pz[:D][:p_n_pl] - pzDp if iv
|
1565
|
+
pz[:D][:n_n_p_pl] = pz[:D][:n_p_pl] - pzDp if iv
|
1566
|
+
|
1567
|
+
# Fetch angle between both extended vectors (A>pC & A>pB),
|
1568
|
+
# ... then normalize (Cn).
|
1569
|
+
#
|
1570
|
+
# pC
|
1571
|
+
# eC ^
|
1572
|
+
# \ |
|
1573
|
+
# \ Cn
|
1574
|
+
# \|
|
1575
|
+
# <---------- A <---------- B
|
1576
|
+
# |\
|
1577
|
+
# | \
|
1578
|
+
# | \
|
1579
|
+
# | C (or D)
|
1580
|
+
#
|
1581
|
+
a1 = OpenStudio.getAngle(pz[:A][:n_p_n_pl], pz[:A][:n_n_p_pl])
|
1582
|
+
a2 = OpenStudio.getAngle(pz[:B][:n_p_n_pl], pz[:B][:n_n_p_pl])
|
1583
|
+
a3 = OpenStudio.getAngle(pz[:C][:n_p_n_pl], pz[:C][:n_n_p_pl])
|
1584
|
+
a4 = OpenStudio.getAngle(pz[:D][:n_p_n_pl], pz[:D][:n_n_p_pl]) if iv
|
1585
|
+
|
1586
|
+
# Generate new 3D points A', B', C' (and D') ... zigzag.
|
1587
|
+
#
|
1588
|
+
#
|
1589
|
+
#
|
1590
|
+
#
|
1591
|
+
# A' ---------------------- B'
|
1592
|
+
# \
|
1593
|
+
# \ A <---------- B
|
1594
|
+
# \ \
|
1595
|
+
# \ \
|
1596
|
+
# \ \
|
1597
|
+
# C' C
|
1598
|
+
pz[:A][:f_n].normalize
|
1599
|
+
pz[:A][:n_p_n_pl].normalize
|
1600
|
+
pzAp = pzAp + scalar(pz[:A][:n_p_n_pl], w)
|
1601
|
+
pzAp = pzAp + scalar(pz[:A][:f_n], w * Math.tan(a1/2))
|
1602
|
+
|
1603
|
+
pz[:B][:f_n].normalize
|
1604
|
+
pz[:B][:n_p_n_pl].normalize
|
1605
|
+
pzBp = pzBp + scalar(pz[:B][:n_p_n_pl], w)
|
1606
|
+
pzBp = pzBp + scalar(pz[:B][:f_n], w * Math.tan(a2/2))
|
1607
|
+
|
1608
|
+
pz[:C][:f_n].normalize
|
1609
|
+
pz[:C][:n_p_n_pl].normalize
|
1610
|
+
pzCp = pzCp + scalar(pz[:C][:n_p_n_pl], w)
|
1611
|
+
pzCp = pzCp + scalar(pz[:C][:f_n], w * Math.tan(a3/2))
|
1612
|
+
|
1613
|
+
pz[:D][:f_n].normalize if iv
|
1614
|
+
pz[:D][:n_p_n_pl].normalize if iv
|
1615
|
+
pzDp = pzDp + scalar(pz[:D][:n_p_n_pl], w) if iv
|
1616
|
+
pzDp = pzDp + scalar(pz[:D][:f_n], w * Math.tan(a4/2)) if iv
|
1617
|
+
|
1618
|
+
# Re-convert to OpenStudio 3D points.
|
1619
|
+
vec = OpenStudio::Point3dVector.new
|
1620
|
+
vec << OpenStudio::Point3d.new(pzAp.x, pzAp.y, pzAp.z)
|
1621
|
+
vec << OpenStudio::Point3d.new(pzBp.x, pzBp.y, pzBp.z)
|
1622
|
+
vec << OpenStudio::Point3d.new(pzCp.x, pzCp.y, pzCp.z)
|
1623
|
+
vec << OpenStudio::Point3d.new(pzDp.x, pzDp.y, pzDp.z) if iv
|
1624
|
+
|
1625
|
+
return vec
|
1626
|
+
end
|
1627
|
+
end
|
1628
|
+
|
1363
1629
|
##
|
1364
1630
|
# Callback when other modules extend OSlg
|
1365
1631
|
#
|
data/lib/osut/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: osut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
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-
|
11
|
+
date: 2022-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oslg
|
@@ -90,7 +90,7 @@ licenses:
|
|
90
90
|
- BSD-3-Clause
|
91
91
|
metadata:
|
92
92
|
homepage_uri: https://github.com/rd2/osut
|
93
|
-
source_code_uri: https://github.com/rd2/osut/tree/v0.2.
|
93
|
+
source_code_uri: https://github.com/rd2/osut/tree/v0.2.7
|
94
94
|
bug_tracker_uri: https://github.com/rd2/osut/issues
|
95
95
|
post_install_message:
|
96
96
|
rdoc_options: []
|