topologicpy 0.4.8__py3-none-any.whl → 0.4.9__py3-none-any.whl

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.
Files changed (79) hide show
  1. topologicpy/Aperture.py +46 -0
  2. topologicpy/Cell.py +1780 -0
  3. topologicpy/CellComplex.py +791 -0
  4. topologicpy/Cluster.py +591 -0
  5. topologicpy/Color.py +157 -0
  6. topologicpy/Context.py +56 -0
  7. topologicpy/DGL.py +2661 -0
  8. topologicpy/Dictionary.py +470 -0
  9. topologicpy/Edge.py +855 -0
  10. topologicpy/EnergyModel.py +1052 -0
  11. topologicpy/Face.py +1810 -0
  12. topologicpy/Graph.py +3526 -0
  13. topologicpy/Graph_Export.py +858 -0
  14. topologicpy/Grid.py +338 -0
  15. topologicpy/Helper.py +182 -0
  16. topologicpy/Honeybee.py +424 -0
  17. topologicpy/Matrix.py +255 -0
  18. topologicpy/Neo4jGraph.py +311 -0
  19. topologicpy/Plotly.py +1396 -0
  20. topologicpy/Polyskel.py +524 -0
  21. topologicpy/Process.py +1368 -0
  22. topologicpy/SQL.py +48 -0
  23. topologicpy/Shell.py +1418 -0
  24. topologicpy/Speckle.py +433 -0
  25. topologicpy/Topology.py +5854 -0
  26. topologicpy/UnitTest.py +29 -0
  27. topologicpy/Vector.py +555 -0
  28. topologicpy/Vertex.py +714 -0
  29. topologicpy/Wire.py +2346 -0
  30. topologicpy/__init__.py +20 -0
  31. topologicpy/bin/linux/topologic/__init__.py +2 -0
  32. topologicpy/bin/linux/topologic/topologic.cpython-310-x86_64-linux-gnu.so +0 -0
  33. topologicpy/bin/linux/topologic/topologic.cpython-311-x86_64-linux-gnu.so +0 -0
  34. topologicpy/bin/linux/topologic/topologic.cpython-38-x86_64-linux-gnu.so +0 -0
  35. topologicpy/bin/linux/topologic/topologic.cpython-39-x86_64-linux-gnu.so +0 -0
  36. topologicpy/bin/linux/topologic.libs/libTKBO-6bdf205d.so.7.7.0 +0 -0
  37. topologicpy/bin/linux/topologic.libs/libTKBRep-2960a069.so.7.7.0 +0 -0
  38. topologicpy/bin/linux/topologic.libs/libTKBool-c44b74bd.so.7.7.0 +0 -0
  39. topologicpy/bin/linux/topologic.libs/libTKFillet-9a670ba0.so.7.7.0 +0 -0
  40. topologicpy/bin/linux/topologic.libs/libTKG2d-8f31849e.so.7.7.0 +0 -0
  41. topologicpy/bin/linux/topologic.libs/libTKG3d-4c6bce57.so.7.7.0 +0 -0
  42. topologicpy/bin/linux/topologic.libs/libTKGeomAlgo-26066fd9.so.7.7.0 +0 -0
  43. topologicpy/bin/linux/topologic.libs/libTKGeomBase-2116cabe.so.7.7.0 +0 -0
  44. topologicpy/bin/linux/topologic.libs/libTKMath-72572fa8.so.7.7.0 +0 -0
  45. topologicpy/bin/linux/topologic.libs/libTKMesh-2a060427.so.7.7.0 +0 -0
  46. topologicpy/bin/linux/topologic.libs/libTKOffset-6cab68ff.so.7.7.0 +0 -0
  47. topologicpy/bin/linux/topologic.libs/libTKPrim-eb1262b3.so.7.7.0 +0 -0
  48. topologicpy/bin/linux/topologic.libs/libTKShHealing-e67e5cc7.so.7.7.0 +0 -0
  49. topologicpy/bin/linux/topologic.libs/libTKTopAlgo-e4c96c33.so.7.7.0 +0 -0
  50. topologicpy/bin/linux/topologic.libs/libTKernel-fb7fe3b7.so.7.7.0 +0 -0
  51. topologicpy/bin/linux/topologic.libs/libgcc_s-32c1665e.so.1 +0 -0
  52. topologicpy/bin/linux/topologic.libs/libstdc++-672d7b41.so.6.0.30 +0 -0
  53. topologicpy/bin/windows/topologic/TKBO-f6b191de.dll +0 -0
  54. topologicpy/bin/windows/topologic/TKBRep-e56a600e.dll +0 -0
  55. topologicpy/bin/windows/topologic/TKBool-7b8d47ae.dll +0 -0
  56. topologicpy/bin/windows/topologic/TKFillet-0ddbf0a8.dll +0 -0
  57. topologicpy/bin/windows/topologic/TKG2d-2e2dee3d.dll +0 -0
  58. topologicpy/bin/windows/topologic/TKG3d-6674513d.dll +0 -0
  59. topologicpy/bin/windows/topologic/TKGeomAlgo-d240e370.dll +0 -0
  60. topologicpy/bin/windows/topologic/TKGeomBase-df87aba5.dll +0 -0
  61. topologicpy/bin/windows/topologic/TKMath-45bd625a.dll +0 -0
  62. topologicpy/bin/windows/topologic/TKMesh-d6e826b1.dll +0 -0
  63. topologicpy/bin/windows/topologic/TKOffset-79b9cc94.dll +0 -0
  64. topologicpy/bin/windows/topologic/TKPrim-aa430a86.dll +0 -0
  65. topologicpy/bin/windows/topologic/TKShHealing-bb48be89.dll +0 -0
  66. topologicpy/bin/windows/topologic/TKTopAlgo-7d0d1e22.dll +0 -0
  67. topologicpy/bin/windows/topologic/TKernel-08c8cfbb.dll +0 -0
  68. topologicpy/bin/windows/topologic/__init__.py +2 -0
  69. topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd +0 -0
  70. topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd +0 -0
  71. topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd +0 -0
  72. topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd +0 -0
  73. {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/METADATA +1 -1
  74. topologicpy-0.4.9.dist-info/RECORD +77 -0
  75. topologicpy-0.4.9.dist-info/top_level.txt +1 -0
  76. topologicpy-0.4.8.dist-info/RECORD +0 -5
  77. topologicpy-0.4.8.dist-info/top_level.txt +0 -1
  78. {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/LICENSE +0 -0
  79. {topologicpy-0.4.8.dist-info → topologicpy-0.4.9.dist-info}/WHEEL +0 -0
@@ -0,0 +1,1052 @@
1
+ import topologicpy
2
+ import topologic
3
+ from topologicpy.Topology import Topology
4
+ from topologicpy.Dictionary import Dictionary
5
+
6
+ import math
7
+ from collections import OrderedDict
8
+ import os
9
+ from os.path import exists
10
+ import json
11
+ from datetime import datetime
12
+ import sys
13
+ import subprocess
14
+ try:
15
+ from tqdm.auto import tqdm
16
+ except:
17
+ import sys, subprocess
18
+ call = [sys.executable, '-m', 'pip', 'install', 'tqdm', '-t', sys.path[0]]
19
+ subprocess.run(call)
20
+ try:
21
+ from tqdm.auto import tqdm
22
+ except:
23
+ print("EnergyModel - ERROR: Could not import tqdm")
24
+
25
+ try:
26
+ import openstudio
27
+ openstudio.Logger.instance().standardOutLogger().setLogLevel(openstudio.Fatal)
28
+ except:
29
+ call = [sys.executable, '-m', 'pip', 'install', 'openstudio', '-t', sys.path[0]]
30
+ subprocess.run(call)
31
+ try:
32
+ import openstudio
33
+ openstudio.Logger.instance().standardOutLogger().setLogLevel(openstudio.Fatal)
34
+ except:
35
+ print("EnergyModel - ERROR: Could not import openstudio")
36
+
37
+ class EnergyModel:
38
+ '''
39
+ @staticmethod
40
+ def ByOSMFile(file):
41
+ """
42
+ Creates an EnergyModel from the input OSM file path.
43
+
44
+ Parameters
45
+ ----------
46
+ path : string
47
+ The path to the input .OSM file.
48
+
49
+ Returns
50
+ -------
51
+ openstudio.openstudiomodelcore.Model
52
+ The OSM model.
53
+
54
+ """
55
+ if not file:
56
+ print("EnergyModel.ByOSMFile - Error: The input path is not valid. Returning None.")
57
+ return None
58
+ osModel = file.read()
59
+ if osModel.isNull():
60
+ print("EnergyModel.ByOSMFile - Error: The openstudio model is null. Returning None.")
61
+ return None
62
+ else:
63
+ osModel = osModel.get()
64
+ return osModel
65
+ '''
66
+
67
+ @staticmethod
68
+ def ByOSMPath(path: str):
69
+ """
70
+ Creates an EnergyModel from the input OSM file path.
71
+
72
+ Parameters
73
+ ----------
74
+ path : string
75
+ The path to the input .OSM file.
76
+
77
+ Returns
78
+ -------
79
+ openstudio.openstudiomodelcore.Model
80
+ The OSM model.
81
+
82
+ """
83
+ if not path:
84
+ print("EnergyModel.ByImportedOSM - Error: The input path is not valid. Returning None.")
85
+ return None
86
+ translator = openstudio.osversion.VersionTranslator()
87
+ osmPath = openstudio.openstudioutilitiescore.toPath(path)
88
+ osModel = translator.loadModel(osmPath)
89
+ if osModel.isNull():
90
+ print("EnergyModel.ByImportedOSM - Error: The openstudio model is null. Returning None.")
91
+ return None
92
+ else:
93
+ osModel = osModel.get()
94
+ return osModel
95
+
96
+ @staticmethod
97
+ def ByImportedOSM(path: str):
98
+ """
99
+ DEPRECATED. DO NOT USE. Instead use Topology.ByOSMPath or Topology.ByOSMFile
100
+ Creates an EnergyModel from the input OSM file path.
101
+
102
+ Parameters
103
+ ----------
104
+ path : string
105
+ The path to the input .OSM file.
106
+
107
+ Returns
108
+ -------
109
+ openstudio.openstudiomodelcore.Model
110
+ The OSM model.
111
+
112
+ """
113
+ print("Topology.ByImportedOSM - WARNING: This method is DEPRECATED. DO NOT USE. Instead use Topology.ByOSMPath")
114
+ return EnergyModel.ByOSMPath(path=path)
115
+
116
+ @staticmethod
117
+ def ByTopology(building : topologic.CellComplex,
118
+ shadingSurfaces : topologic.Topology = None,
119
+ osModelPath : str = None,
120
+ weatherFilePath : str = None,
121
+ designDayFilePath : str = None,
122
+ floorLevels : list = None,
123
+ buildingName : str = "TopologicBuilding",
124
+ buildingType : str = "Commercial",
125
+ northAxis : float = 0.0,
126
+ glazingRatio : float = 0.0,
127
+ coolingTemp : float = 25.0,
128
+ heatingTemp : float = 20.0,
129
+ defaultSpaceType : str = "189.1-2009 - Office - WholeBuilding - Lg Office - CZ4-8",
130
+ spaceNameKey : str = "TOPOLOGIC_name",
131
+ spaceTypeKey : str = "TOPOLOGIC_type"):
132
+ """
133
+ Creates an EnergyModel from the input topology and parameters.
134
+
135
+ Parameters
136
+ ----------
137
+ building : topologic.CellComplex
138
+ The input building topology.
139
+ shadingSurfaces : topologic.Topology , optional
140
+ The input topology for shading surfaces. The default is None.
141
+ osModelPath : str , optional
142
+ The path to the template OSM file. The default is "./assets/EnergyModel/OSMTemplate-OfficeBuilding-3.5.0.osm".
143
+ weatherFilePath : str , optional
144
+ The input energy plus weather (epw) file. The default is "./assets/EnergyModel/GBR_London.Gatwick.037760_IWEC.epw".
145
+ designDayFilePath : str , optional
146
+ The input design day (ddy) file path. The default is "./assets/EnergyModel/GBR_London.Gatwick.037760_IWEC.ddy",
147
+ floorLevels : list , optional
148
+ The list of floor level Z heights including the lowest most and the highest most levels. If set to None, this method will attempt to
149
+ find the floor levels from the horizontal faces of the input topology
150
+ buildingName : str , optional
151
+ The desired name of the building. The default is "TopologicBuilding".
152
+ buildingType : str , optional
153
+ The building type. The default is "Commercial".
154
+ defaultSpaceType : str , optional
155
+ The default space type to apply to spaces that do not have a type assigned in their dictionary. The default is "189.1-2009 - Office - WholeBuilding - Lg Office - CZ4-8".
156
+ northAxis : float , optional
157
+ The counter-clockwise angle in degrees from the positive Y-axis representing the direction of the north axis. The default is 0.0.
158
+ glazingRatio : float , optional
159
+ The glazing ratio (ratio of windows to wall) to use for exterior vertical walls that do not have apertures. If you do not wish to use a glazing ratio, set it to 0. The default is 0.
160
+ coolingTemp : float , optional
161
+ The desired temperature in degrees at which the cooling system should activate. The default is 25.0.
162
+ heatingTemp : float , optional
163
+ The desired temperature in degrees at which the heating system should activate. The default is 25.0..
164
+ spaceNameKey : str , optional
165
+ The dictionary key to use to find the space name value. The default is "Name".
166
+ spaceTypeKey : str , optional
167
+ The dictionary key to use to find the space type value. The default is "Type".
168
+
169
+ Returns
170
+ -------
171
+ openstudio.openstudiomodelcore.Model
172
+ The created OSM model.
173
+
174
+ """
175
+
176
+ def getKeyName(d, keyName):
177
+ keys = d.Keys()
178
+ for key in keys:
179
+ if key.lower() == keyName.lower():
180
+ return key
181
+ return None
182
+
183
+ def createUniqueName(name, nameList, number):
184
+ if not (name in nameList):
185
+ return name
186
+ elif not ((name+"_"+str(number)) in nameList):
187
+ return name+"_"+str(number)
188
+ else:
189
+ return createUniqueName(name,nameList, number+1)
190
+
191
+ def getFloorLevels(building):
192
+ from topologicpy.Vertex import Vertex
193
+ from topologicpy.CellComplex import CellComplex
194
+ from topologicpy.Dictionary import Dictionary
195
+
196
+ d = CellComplex.Decompose(building)
197
+ bhf = d['bottomHorizontalFaces']
198
+ ihf = d['internalHorizontalFaces']
199
+ thf = d ['topHorizontalFaces']
200
+ hf = bhf+ihf+thf
201
+ floorLevels = [Vertex.Z(Topology.Centroid(f)) for f in hf]
202
+ floorLevels = list(set(floorLevels))
203
+ floorLevels.sort()
204
+ return floorLevels
205
+
206
+ if not osModelPath:
207
+ import os
208
+ osModelPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "OSMTemplate-OfficeBuilding-3.5.0.osm")
209
+ if not weatherFilePath or not designDayFilePath:
210
+ import os
211
+ weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
212
+ designDayFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.ddy")
213
+ translator = openstudio.osversion.VersionTranslator()
214
+ osmFile = openstudio.openstudioutilitiescore.toPath(osModelPath)
215
+ osModel = translator.loadModel(osmFile)
216
+ if osModel.isNull():
217
+ print("EnergyModel.ByTopology - Error: The openstudio model is null. Returning None.")
218
+ return None
219
+ else:
220
+ osModel = osModel.get()
221
+ osEPWFile = openstudio.openstudioutilitiesfiletypes.EpwFile.load(openstudio.toPath(weatherFilePath))
222
+ if osEPWFile.is_initialized():
223
+ osEPWFile = osEPWFile.get()
224
+ openstudio.model.WeatherFile.setWeatherFile(osModel, osEPWFile)
225
+ ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(openstudio.toPath(designDayFilePath))
226
+ if ddyModel.is_initialized():
227
+ ddyModel = ddyModel.get()
228
+ for ddy in ddyModel.getObjectsByType(openstudio.IddObjectType("OS:SizingPeriod:DesignDay")):
229
+ osModel.addObject(ddy.clone())
230
+ else:
231
+ print("EnergyModel.ByTopology - Error: The ddy file is not initialized. Returning None.")
232
+ return None
233
+
234
+ osBuilding = osModel.getBuilding()
235
+ if not floorLevels:
236
+ floorLevels = getFloorLevels(building)
237
+ osBuilding.setStandardsNumberOfStories(len(floorLevels) - 1)
238
+ osBuilding.setNominalFloortoFloorHeight(max(floorLevels) / osBuilding.standardsNumberOfStories().get())
239
+ osBuilding.setDefaultConstructionSet(osModel.getDefaultConstructionSets()[0])
240
+ osBuilding.setDefaultScheduleSet(osModel.getDefaultScheduleSets()[0])
241
+ osBuilding.setName(buildingName)
242
+ osBuilding.setStandardsBuildingType(buildingType)
243
+ osBuilding.setSpaceType(osModel.getSpaceTypeByName(defaultSpaceType).get())
244
+ for storyNumber in range(osBuilding.standardsNumberOfStories().get()):
245
+ osBuildingStory = openstudio.model.BuildingStory(osModel)
246
+ osBuildingStory.setName("STORY_" + str(storyNumber))
247
+ osBuildingStory.setNominalZCoordinate(floorLevels[storyNumber])
248
+ osBuildingStory.setNominalFloortoFloorHeight(osBuilding.nominalFloortoFloorHeight().get())
249
+ osBuilding.setNorthAxis(northAxis)
250
+
251
+ heatingScheduleConstant = openstudio.model.ScheduleConstant(osModel)
252
+ heatingScheduleConstant.setValue(heatingTemp)
253
+ coolingScheduleConstant = openstudio.model.ScheduleConstant(osModel)
254
+ coolingScheduleConstant.setValue(coolingTemp)
255
+ osThermostat = openstudio.model.ThermostatSetpointDualSetpoint(osModel)
256
+ osThermostat.setHeatingSetpointTemperatureSchedule(heatingScheduleConstant)
257
+ osThermostat.setCoolingSetpointTemperatureSchedule(coolingScheduleConstant)
258
+
259
+ osBuildingStorys = list(osModel.getBuildingStorys())
260
+ osBuildingStorys.sort(key=lambda x: x.nominalZCoordinate().get())
261
+ osSpaces = []
262
+ spaceNames = []
263
+ for spaceNumber, buildingCell in enumerate(Topology.SubTopologies(building, "Cell")):
264
+ osSpace = openstudio.model.Space(osModel)
265
+ osSpaceZ = buildingCell.CenterOfMass().Z()
266
+ osBuildingStory = osBuildingStorys[0]
267
+ for x in osBuildingStorys:
268
+ osBuildingStoryZ = x.nominalZCoordinate().get()
269
+ if osBuildingStoryZ + x.nominalFloortoFloorHeight().get() < osSpaceZ:
270
+ continue
271
+ if osBuildingStoryZ < osSpaceZ:
272
+ osBuildingStory = x
273
+ break
274
+ osSpace.setBuildingStory(osBuildingStory)
275
+ cellDictionary = buildingCell.GetDictionary()
276
+ if cellDictionary:
277
+ if spaceTypeKey:
278
+ keyType = getKeyName(cellDictionary, spaceTypeKey)
279
+ else:
280
+ keyType = getKeyName(cellDictionary, 'type')
281
+ if keyType:
282
+ osSpaceTypeName = Dictionary.ValueAtKey(cellDictionary,keyType)
283
+ else:
284
+ osSpaceTypeName = defaultSpaceType
285
+ if osSpaceTypeName:
286
+ sp_ = osModel.getSpaceTypeByName(osSpaceTypeName)
287
+ if sp_.is_initialized():
288
+ osSpace.setSpaceType(sp_.get())
289
+ if spaceNameKey:
290
+ keyName = getKeyName(cellDictionary, spaceNameKey)
291
+
292
+ else:
293
+ keyName = getKeyName(cellDictionary, 'name')
294
+ osSpaceName = None
295
+ if keyName:
296
+ osSpaceName = createUniqueName(Dictionary.ValueAtKey(cellDictionary,keyName),spaceNames, 1)
297
+ if osSpaceName:
298
+ osSpace.setName(osSpaceName)
299
+ else:
300
+ osSpaceName = osBuildingStory.name().get() + "_SPACE_" + str(spaceNumber)
301
+ osSpace.setName(osSpaceName)
302
+ sp_ = osModel.getSpaceTypeByName(defaultSpaceType)
303
+ if sp_.is_initialized():
304
+ osSpace.setSpaceType(sp_.get())
305
+ spaceNames.append(osSpaceName)
306
+ cellFaces = Topology.SubTopologies(buildingCell, "Face")
307
+ if cellFaces:
308
+ for faceNumber, buildingFace in enumerate(cellFaces):
309
+ osFacePoints = []
310
+ for vertex in Topology.SubTopologies(buildingFace.ExternalBoundary(), "Vertex"):
311
+ osFacePoints.append(openstudio.Point3d(vertex.X(), vertex.Y(), vertex.Z()))
312
+ osSurface = openstudio.model.Surface(osFacePoints, osModel)
313
+ faceNormal = topologic.FaceUtility.NormalAtParameters(buildingFace, 0.5, 0.5)
314
+ osFaceNormal = openstudio.Vector3d(faceNormal[0], faceNormal[1], faceNormal[2])
315
+ osFaceNormal.normalize()
316
+ if osFaceNormal.dot(osSurface.outwardNormal()) < 1e-6:
317
+ osSurface.setVertices(list(reversed(osFacePoints)))
318
+ osSurface.setSpace(osSpace)
319
+ faceCells = []
320
+ _ = topologic.FaceUtility.AdjacentCells(buildingFace, building, faceCells)
321
+ if len(faceCells) == 1: #Exterior Surfaces
322
+ osSurface.setOutsideBoundaryCondition("Outdoors")
323
+ if (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) > 135) or (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) < 45):
324
+ osSurface.setSurfaceType("RoofCeiling")
325
+ osSurface.setOutsideBoundaryCondition("Outdoors")
326
+ osSurface.setName(osSpace.name().get() + "_TopHorizontalSlab_" + str(faceNumber))
327
+ if max(list(map(lambda vertex: vertex.Z(), Topology.SubTopologies(buildingFace, "Vertex")))) < 1e-6:
328
+ osSurface.setSurfaceType("Floor")
329
+ osSurface.setOutsideBoundaryCondition("Ground")
330
+ osSurface.setName(osSpace.name().get() + "_BottomHorizontalSlab_" + str(faceNumber))
331
+ else:
332
+ osSurface.setSurfaceType("Wall")
333
+ osSurface.setOutsideBoundaryCondition("Outdoors")
334
+ osSurface.setName(osSpace.name().get() + "_ExternalVerticalFace_" + str(faceNumber))
335
+ # Check for exterior apertures
336
+ faceDictionary = buildingFace.GetDictionary()
337
+ apertures = []
338
+ _ = buildingFace.Apertures(apertures)
339
+ if len(apertures) > 0:
340
+ for aperture in apertures:
341
+ osSubSurfacePoints = []
342
+ #apertureFace = TopologySubTopologies.processItem([aperture, topologic.Face])[0]
343
+ apertureFace = topologic.Aperture.Topology(aperture)
344
+ for vertex in Topology.SubTopologies(apertureFace.ExternalBoundary(), "Vertex"):
345
+ osSubSurfacePoints.append(openstudio.Point3d(vertex.X(), vertex.Y(), vertex.Z()))
346
+ osSubSurface = openstudio.model.SubSurface(osSubSurfacePoints, osModel)
347
+ apertureFaceNormal = topologic.FaceUtility.NormalAtParameters(apertureFace, 0.5, 0.5)
348
+ osSubSurfaceNormal = openstudio.Vector3d(apertureFaceNormal[0], apertureFaceNormal[1], apertureFaceNormal[2])
349
+ osSubSurfaceNormal.normalize()
350
+ if osSubSurfaceNormal.dot(osSubSurface.outwardNormal()) < 1e-6:
351
+ osSubSurface.setVertices(list(reversed(osSubSurfacePoints)))
352
+ osSubSurface.setSubSurfaceType("FixedWindow")
353
+ osSubSurface.setSurface(osSurface)
354
+ else:
355
+ # Get the dictionary keys
356
+ keys = faceDictionary.Keys()
357
+ if ('TOPOLOGIC_glazing_ratio' in keys):
358
+ faceGlazingRatio = Dictionary.ValueAtKey(faceDictionary,'TOPOLOGIC_glazing_ratio')
359
+ if faceGlazingRatio and faceGlazingRatio >= 0.01:
360
+ osSurface.setWindowToWallRatio(faceGlazingRatio)
361
+ else:
362
+ if glazingRatio > 0.01: #Glazing ratio must be more than 1% to make any sense.
363
+ osSurface.setWindowToWallRatio(glazingRatio)
364
+ else: #Interior Surfaces
365
+ if (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) > 135):
366
+ osSurface.setSurfaceType("Floor")
367
+ osSurface.setName(osSpace.name().get() + "_InternalHorizontalFace_" + str(faceNumber))
368
+ elif (math.degrees(math.acos(osSurface.outwardNormal().dot(openstudio.Vector3d(0, 0, 1)))) < 40):
369
+ osSurface.setSurfaceType("RoofCeiling")
370
+ osSurface.setName(osSpace.name().get() + "_InternalHorizontalFace_" + str(faceNumber))
371
+ else:
372
+ osSurface.setSurfaceType("Wall")
373
+ osSurface.setName(osSpace.name().get() + "_InternalVerticalFace_" + str(faceNumber))
374
+ # Check for interior apertures
375
+ faceDictionary = buildingFace.GetDictionary()
376
+ apertures = []
377
+ _ = buildingFace.Apertures(apertures)
378
+ if len(apertures) > 0:
379
+ for aperture in apertures:
380
+ osSubSurfacePoints = []
381
+ #apertureFace = TopologySubTopologies.processItem([aperture, "Face"])[0]
382
+ apertureFace = topologic.Aperture.Topology(aperture)
383
+ for vertex in Topology.SubTopologies(apertureFace.ExternalBoundary(), "Vertex"):
384
+ osSubSurfacePoints.append(openstudio.Point3d(vertex.X(), vertex.Y(), vertex.Z()))
385
+ osSubSurface = openstudio.model.SubSurface(osSubSurfacePoints, osModel)
386
+ apertureFaceNormal = topologic.FaceUtility.NormalAtParameters(apertureFace, 0.5, 0.5)
387
+ osSubSurfaceNormal = openstudio.Vector3d(apertureFaceNormal[0], apertureFaceNormal[1], apertureFaceNormal[2])
388
+ osSubSurfaceNormal.normalize()
389
+ if osSubSurfaceNormal.dot(osSubSurface.outwardNormal()) < 1e-6:
390
+ osSubSurface.setVertices(list(reversed(osSubSurfacePoints)))
391
+ osSubSurface.setSubSurfaceType("Door") #We are assuming all interior apertures to be doors
392
+ osSubSurface.setSurface(osSurface)
393
+
394
+ osThermalZone = openstudio.model.ThermalZone(osModel)
395
+ osThermalZone.setVolume(topologic.CellUtility.Volume(buildingCell))
396
+ osThermalZone.setName(osSpace.name().get() + "_THERMAL_ZONE")
397
+ osThermalZone.setUseIdealAirLoads(True)
398
+ osThermalZone.setVolume(topologic.CellUtility.Volume(buildingCell))
399
+ osThermalZone.setThermostatSetpointDualSetpoint(osThermostat)
400
+ osSpace.setThermalZone(osThermalZone)
401
+
402
+ for x in osSpaces:
403
+ if osSpace.boundingBox().intersects(x.boundingBox()):
404
+ osSpace.matchSurfaces(x)
405
+ osSpaces.append(osSpace)
406
+
407
+
408
+ if shadingSurfaces:
409
+ osShadingGroup = openstudio.model.ShadingSurfaceGroup(osModel)
410
+ for faceIndex, shadingFace in enumerate(Topology.SubTopologies(shadingSurfaces, "Face")):
411
+ facePoints = []
412
+ for aVertex in Topology.SubTopologies(shadingFace.ExternalBoundary(), "Vertex"):
413
+ facePoints.append(openstudio.Point3d(aVertex.X(), aVertex.Y(), aVertex.Z()))
414
+ aShadingSurface = openstudio.model.ShadingSurface(facePoints, osModel)
415
+ faceNormal = topologic.FaceUtility.NormalAtParameters(shadingFace, 0.5, 0.5)
416
+ osFaceNormal = openstudio.Vector3d(faceNormal[0], faceNormal[1], faceNormal[2])
417
+ osFaceNormal.normalize()
418
+ if osFaceNormal.dot(aShadingSurface.outwardNormal()) < 0:
419
+ aShadingSurface.setVertices(list(reversed(facePoints)))
420
+ aShadingSurface.setName("SHADINGSURFACE_" + str(faceIndex))
421
+ aShadingSurface.setShadingSurfaceGroup(osShadingGroup)
422
+
423
+ osModel.purgeUnusedResourceObjects()
424
+ return osModel
425
+
426
+ @staticmethod
427
+ def ColumnNames(model, reportName, tableName):
428
+ """
429
+ Returns the list of column names given an OSM model, report name, and table name.
430
+
431
+ Parameters
432
+ ----------
433
+ model : openstudio.openstudiomodelcore.Model
434
+ The input OSM model.
435
+ reportName : str
436
+ The input report name.
437
+ tableName : str
438
+ The input table name.
439
+
440
+ Returns
441
+ -------
442
+ list
443
+ the list of column names.
444
+
445
+ """
446
+ sql = model.sqlFile().get()
447
+ query = "SELECT ColumnName FROM tabulardatawithstrings WHERE ReportName = '"+reportName+"' AND TableName = '"+tableName+"'"
448
+ columnNames = sql.execAndReturnVectorOfString(query).get()
449
+ return list(OrderedDict( (x,1) for x in columnNames ).keys()) #Making a unique list and keeping its order
450
+
451
+ @staticmethod
452
+ def DefaultConstructionSets(model):
453
+ """
454
+ Returns the default construction sets in the input OSM model.
455
+
456
+ Parameters
457
+ ----------
458
+ model : openstudio.openstudiomodelcore.Model
459
+ The input OSM model.
460
+
461
+ Returns
462
+ -------
463
+ list
464
+ The default construction sets.
465
+
466
+ """
467
+ sets = model.getDefaultConstructionSets()
468
+ names = []
469
+ for aSet in sets:
470
+ names.append(aSet.name().get())
471
+ return [sets, names]
472
+
473
+ @staticmethod
474
+ def DefaultScheduleSets(model):
475
+ """
476
+ Returns the default schedule sets found in the input OSM model.
477
+
478
+ Parameters
479
+ ----------
480
+ model : openstudio.openstudiomodelcore.Model
481
+ The input OSM model.
482
+
483
+ Returns
484
+ -------
485
+ list
486
+ The list of default schedule sets.
487
+
488
+ """
489
+ sets = model.getDefaultScheduleSets()
490
+ names = []
491
+ for aSet in sets:
492
+ names.append(aSet.name().get())
493
+ return [sets, names]
494
+
495
+ @staticmethod
496
+ def ExportToGbXML(model, path, overwrite=False):
497
+ """
498
+ Exports the input OSM model to a gbxml file.
499
+
500
+ Parameters
501
+ ----------
502
+ model : openstudio.openstudiomodelcore.Model
503
+ The input OSM model.
504
+ path : str
505
+ The path for saving the file.
506
+ overwrite : bool, optional
507
+ If set to True any file with the same name is over-written. The default is False.
508
+
509
+ Returns
510
+ -------
511
+ bool
512
+ True if the file is written successfully. False otherwise.
513
+
514
+ """
515
+ ext = path[len(path)-4:len(path)]
516
+ if ext.lower() != ".xml":
517
+ path = path+".xml"
518
+ if(exists(path) and (overwrite == False)):
519
+ print("EnergyModel.ExportToGbXML - Error: Could not export the file because it already exists and overwrite is set to False. Returning None.")
520
+ return None
521
+ return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXML(model, openstudio.openstudioutilitiescore.toPath(path))
522
+
523
+
524
+ @staticmethod
525
+ def ExportToOSM(model, path, overwrite=False):
526
+ """
527
+ Exports the input OSM model to an OSM file.
528
+
529
+ Parameters
530
+ ----------
531
+ model : openstudio.openstudiomodelcore.Model
532
+ The input OSM model.
533
+ path : str
534
+ The path for saving the file.
535
+ overwrite : bool, optional
536
+ If set to True any file with the same name is over-written. The default is False.
537
+
538
+ Returns
539
+ -------
540
+ bool
541
+ True if the file is written successfully. False otherwise.
542
+
543
+ """
544
+ ext = path[len(path)-4:len(path)]
545
+ if ext.lower() != ".osm":
546
+ path = path+".osm"
547
+ osCondition = False
548
+ osPath = openstudio.openstudioutilitiescore.toPath(path)
549
+ osCondition = model.save(osPath, overwrite)
550
+ return osCondition
551
+
552
+ @staticmethod
553
+ def GbXMLString(model):
554
+ """
555
+ Returns the gbxml string of the input OSM model.
556
+
557
+ Parameters
558
+ ----------
559
+ model : openstudio.openstudiomodelcore.Model
560
+ The input OSM model.
561
+
562
+ Returns
563
+ -------
564
+ str
565
+ The gbxml string.
566
+
567
+ """
568
+ return openstudio.gbxml.GbXMLForwardTranslator().modelToGbXMLString(model)
569
+
570
+ @staticmethod
571
+ def Query(model,
572
+ reportName : str = "HVACSizingSummary",
573
+ reportForString : str = "Entire Facility",
574
+ tableName : str = "Zone Sensible Cooling",
575
+ columnName : str = "Calculated Design Load",
576
+ rowNames : list = [],
577
+ units : str = "W"):
578
+ """
579
+ Queries the model for values.
580
+
581
+ Parameters
582
+ ----------
583
+ model : openstudio.openstudiomodelcore.Model
584
+ The input OSM model.
585
+ reportName : str , optional
586
+ The input report name. The default is "HVACSizingSummary".
587
+ reportForString : str, optional
588
+ The input report for string. The default is "Entire Facility".
589
+ tableName : str , optional
590
+ The input table name. The default is "Zone Sensible Cooling".
591
+ columnName : str , optional
592
+ The input column name. The default is "Calculated Design Load".
593
+ rowNames : list , optional
594
+ The input list of row names. The default is [].
595
+ units : str , optional
596
+ The input units. The default is "W".
597
+
598
+ Returns
599
+ -------
600
+ list
601
+ The list of values.
602
+
603
+ """
604
+
605
+ def doubleValueFromQuery(sqlFile, reportName, reportForString,
606
+ tableName, columnName, rowName,
607
+ units):
608
+ query = "SELECT Value FROM tabulardatawithstrings WHERE ReportName='" + reportName + "' AND ReportForString='" + reportForString + "' AND TableName = '" + tableName + "' AND RowName = '" + rowName + "' AND ColumnName= '" + columnName + "' AND Units='" + units + "'";
609
+ osOptionalDoubleValue = sqlFile.execAndReturnFirstDouble(query)
610
+ if (osOptionalDoubleValue.is_initialized()):
611
+ return osOptionalDoubleValue.get()
612
+ else:
613
+ return None
614
+
615
+ sqlFile = model.sqlFile().get()
616
+ returnValues = []
617
+ for rowName in rowNames:
618
+ returnValues.append(doubleValueFromQuery(sqlFile, reportName, reportForString, tableName, columnName, rowName, units))
619
+ return returnValues
620
+
621
+ @staticmethod
622
+ def ReportNames(model):
623
+ """
624
+ Returns the report names found in the input OSM model.
625
+
626
+ Parameters
627
+ ----------
628
+ model : openstudio.openstudiomodelcore.Model
629
+ The input OSM model.
630
+
631
+ Returns
632
+ -------
633
+ list
634
+ The list of report names found in the input OSM model.
635
+
636
+ """
637
+ sql = model.sqlFile().get()
638
+ reportNames = sql.execAndReturnVectorOfString("SELECT ReportName FROM tabulardatawithstrings").get()
639
+ return list(OrderedDict( (x,1) for x in reportNames ).keys()) #Making a unique list and keeping its order
640
+
641
+ @staticmethod
642
+ def RowNames(model, reportName, tableName):
643
+ """
644
+ Returns the list of row names given an OSM model, report name, and table name.
645
+
646
+ Parameters
647
+ ----------
648
+ model : openstudio.openstudiomodelcore.Model
649
+ The input OSM model.
650
+ reportName : str
651
+ The input name of the report.
652
+ tableName : str
653
+ The input name of the table.
654
+
655
+ Returns
656
+ -------
657
+ list
658
+ The list of row names.
659
+
660
+ """
661
+ sql = model.sqlFile().get()
662
+ query = "SELECT RowName FROM tabulardatawithstrings WHERE ReportName = '"+reportName+"' AND TableName = '"+tableName+"'"
663
+ columnNames = sql.execAndReturnVectorOfString(query).get()
664
+ return list(OrderedDict( (x,1) for x in columnNames ).keys()) #Making a unique list and keeping its order
665
+
666
+ @staticmethod
667
+ def Run(model, weatherFilePath: str = None, osBinaryPath : str = None, outputFolder : str = None):
668
+ """
669
+ Runs an energy simulation.
670
+
671
+ Parameters
672
+ ----------
673
+ model : openstudio.openstudiomodelcore.Model
674
+ The input OSM model.
675
+ weatherFilePath : str
676
+ The path to the epw weather file.
677
+ osBinaryPath : str
678
+ The path to the openstudio binary.
679
+ outputFolder : str
680
+ The path to the output folder.
681
+
682
+ Returns
683
+ -------
684
+ model : openstudio.openstudiomodelcore.Model
685
+ The simulated OSM model.
686
+
687
+ """
688
+ import os
689
+ if not weatherFilePath:
690
+ weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
691
+ pbar = tqdm(desc='Running Simulation', total=100, leave=False)
692
+ utcnow = datetime.utcnow()
693
+ timestamp = utcnow.strftime("UTC-%Y-%m-%d-%H-%M-%S")
694
+ if not outputFolder:
695
+ home = os.path.expanduser('~')
696
+ outputFolder = os.path.join(home, "EnergyModels", timestamp)
697
+ else:
698
+ outputFolder = os.path.join(outputFolder, timestamp)
699
+ os.mkdir(outputFolder)
700
+ pbar.update(10)
701
+ osmPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osm")
702
+ model.save(openstudio.openstudioutilitiescore.toPath(osmPath), True)
703
+ oswPath = os.path.join(outputFolder, model.getBuilding().name().get() + ".osw")
704
+ pbar.update(20)
705
+ #print("oswPath = "+oswPath)
706
+ workflow = model.workflowJSON()
707
+ workflow.setSeedFile(openstudio.openstudioutilitiescore.toPath(osmPath))
708
+ pbar.update(30)
709
+ #print("Seed File Set")
710
+ workflow.setWeatherFile(openstudio.openstudioutilitiescore.toPath(weatherFilePath))
711
+ pbar.update(40)
712
+ #print("Weather File Set")
713
+ workflow.saveAs(openstudio.openstudioutilitiescore.toPath(oswPath))
714
+ pbar.update(50)
715
+ #print("OSW File Saved")
716
+ cmd = osBinaryPath+" run -w " + "\"" + oswPath + "\""
717
+ pbar.update(60)
718
+ os.system(cmd)
719
+ #print("Simulation DONE")
720
+ sqlPath = os.path.join(os.path.join(outputFolder,"run"), "eplusout.sql")
721
+ pbar.update(100)
722
+ #print("sqlPath = "+sqlPath)
723
+ osSqlFile = openstudio.SqlFile(openstudio.openstudioutilitiescore.toPath(sqlPath))
724
+ model.setSqlFile(osSqlFile)
725
+ pbar.close()
726
+ return model
727
+
728
+ @staticmethod
729
+ def SpaceDictionaries(model):
730
+ """
731
+ Return the space dictionaries found in the input OSM model.
732
+
733
+ Parameters
734
+ ----------
735
+ model : openstudio.openstudiomodelcore.Model
736
+ The input OSM model.
737
+
738
+ Returns
739
+ -------
740
+ dict
741
+ The dictionary of space types, names, and colors found in the input OSM model. The dictionary has the following keys:
742
+ - "types"
743
+ - "names"
744
+ - "colors"
745
+
746
+ """
747
+ types = model.getSpaceTypes()
748
+ names = []
749
+ colors = []
750
+ for aType in types:
751
+ names.append(aType.name().get())
752
+ red = aType.renderingColor().get().renderingRedValue()
753
+ green = aType.renderingColor().get().renderingGreenValue()
754
+ blue = aType.renderingColor().get().renderingBlueValue()
755
+ colors.append([red,green,blue])
756
+ return {'types': types, 'names': names, 'colors': colors}
757
+
758
+ @staticmethod
759
+ def SpaceTypes(model):
760
+ """
761
+ Return the space types found in the input OSM model.
762
+
763
+ Parameters
764
+ ----------
765
+ model : openstudio.openstudiomodelcore.Model
766
+ The input OSM model.
767
+
768
+ Returns
769
+ -------
770
+ list
771
+ The list of space types
772
+
773
+ """
774
+ return model.getSpaceTypes()
775
+
776
+ @staticmethod
777
+ def SpaceTypeNames(model):
778
+ """
779
+ Return the space type names found in the input OSM model.
780
+
781
+ Parameters
782
+ ----------
783
+ model : openstudio.openstudiomodelcore.Model
784
+ The input OSM model.
785
+
786
+ Returns
787
+ -------
788
+ list
789
+ The list of space type names
790
+
791
+ """
792
+ types = model.getSpaceTypes()
793
+ names = []
794
+ colors = []
795
+ for aType in types:
796
+ names.append(aType.name().get())
797
+ return names
798
+
799
+ @staticmethod
800
+ def SpaceColors(model):
801
+ """
802
+ Return the space colors found in the input OSM model.
803
+
804
+ Parameters
805
+ ----------
806
+ model : openstudio.openstudiomodelcore.Model
807
+ The input OSM model.
808
+
809
+ Returns
810
+ -------
811
+ list
812
+ The list of space colors. Each item is a three-item list representing the red, green, and blue values of the color.
813
+
814
+ """
815
+ types = model.getSpaceTypes()
816
+ colors = []
817
+ for aType in types:
818
+ red = aType.renderingColor().get().renderingRedValue()
819
+ green = aType.renderingColor().get().renderingGreenValue()
820
+ blue = aType.renderingColor().get().renderingBlueValue()
821
+ colors.append([red,green,blue])
822
+ return colors
823
+
824
+ @staticmethod
825
+ def SqlFile(model):
826
+ """
827
+ Returns the SQL file found in the input OSM model.
828
+
829
+ Parameters
830
+ ----------
831
+ model : openstudio.openstudiomodelcore.Model
832
+ The input OSM model.
833
+
834
+ Returns
835
+ -------
836
+ SQL file
837
+ The SQL file found in the input OSM model.
838
+
839
+ """
840
+ return model.sqlFile().get()
841
+
842
+ @staticmethod
843
+ def TableNames(model, reportName):
844
+ """
845
+ Returns the table names found in the input OSM model and report name.
846
+
847
+ Parameters
848
+ ----------
849
+ model : openstudio.openstudiomodelcore.Model
850
+ The input OSM model.
851
+ reportName : str
852
+ The input report name.
853
+
854
+ Returns
855
+ -------
856
+ list
857
+ The list of table names found in the input OSM model and report name.
858
+
859
+ """
860
+ sql = model.sqlFile().get()
861
+ tableNames = sql.execAndReturnVectorOfString("SELECT TableName FROM tabulardatawithstrings WHERE ReportName='"+reportName+"'").get()
862
+ return list(OrderedDict( (x,1) for x in tableNames ).keys()) #Making a unique list and keeping its order
863
+
864
+ @staticmethod
865
+ def Topologies(model):
866
+ """
867
+ Parameters
868
+ ----------
869
+ model : openstudio.openstudiomodelcore.Model
870
+ The input OSM model.
871
+
872
+ Returns
873
+ -------
874
+ dict
875
+ The dictionary of topologies found in the input OSM model. The keys of the dictionary are:
876
+ - "cells"
877
+ - "apertures"
878
+ - "shadingFaces"
879
+
880
+ """
881
+ from topologicpy.Edge import Edge
882
+ from topologicpy.Wire import Wire
883
+ from topologicpy.Face import Face
884
+ from topologicpy.Shell import Shell
885
+ from topologicpy.Cell import Cell
886
+ from topologicpy.Cluster import Cluster
887
+ from topologicpy.Dictionary import Dictionary
888
+ from topologicpy.Topology import Topology
889
+
890
+ def surfaceToFace(surface):
891
+ surfaceEdges = []
892
+ surfaceVertices = surface.vertices()
893
+ for i in range(len(surfaceVertices)-1):
894
+ sv = topologic.Vertex.ByCoordinates(surfaceVertices[i].x(), surfaceVertices[i].y(), surfaceVertices[i].z())
895
+ ev = topologic.Vertex.ByCoordinates(surfaceVertices[i+1].x(), surfaceVertices[i+1].y(), surfaceVertices[i+1].z())
896
+ edge = Edge.ByStartVertexEndVertex(sv, ev)
897
+ if not edge:
898
+ continue
899
+ surfaceEdges.append(edge)
900
+ sv = topologic.Vertex.ByCoordinates(surfaceVertices[len(surfaceVertices)-1].x(), surfaceVertices[len(surfaceVertices)-1].y(), surfaceVertices[len(surfaceVertices)-1].z())
901
+ ev = topologic.Vertex.ByCoordinates(surfaceVertices[0].x(), surfaceVertices[0].y(), surfaceVertices[0].z())
902
+ edge = Edge.ByStartVertexEndVertex(sv, ev)
903
+ surfaceEdges.append(edge)
904
+ surfaceWire = Wire.ByEdges(surfaceEdges)
905
+ internalBoundaries = []
906
+ surfaceFace = Face.ByWires(surfaceWire, internalBoundaries)
907
+ return surfaceFace
908
+
909
+ def addApertures(face, apertures):
910
+ usedFaces = []
911
+ for aperture in apertures:
912
+ cen = aperture.CenterOfMass()
913
+ try:
914
+ params = face.ParametersAtVertex(cen)
915
+ u = params[0]
916
+ v = params[1]
917
+ w = 0.5
918
+ except:
919
+ u = 0.5
920
+ v = 0.5
921
+ w = 0.5
922
+ context = topologic.Context.ByTopologyParameters(face, u, v, w)
923
+ _ = topologic.Aperture.ByTopologyContext(aperture, context)
924
+ return face
925
+ spaces = list(model.getSpaces())
926
+
927
+ vertexIndex = 0
928
+ cells = []
929
+ apertures = []
930
+ shadingFaces = []
931
+ shadingSurfaces = list(model.getShadingSurfaces())
932
+
933
+ for aShadingSurface in shadingSurfaces:
934
+ shadingFace = surfaceToFace(aShadingSurface)
935
+ if aShadingSurface.shadingSurfaceGroup().is_initialized():
936
+ shadingGroup = aShadingSurface.shadingSurfaceGroup().get()
937
+ if shadingGroup.space().is_initialized():
938
+ space = shadingGroup.space().get()
939
+ osTransformation = space.transformation()
940
+ osTranslation = osTransformation.translation()
941
+ osMatrix = osTransformation.rotationMatrix()
942
+ rotation11 = osMatrix[0, 0]
943
+ rotation12 = osMatrix[0, 1]
944
+ rotation13 = osMatrix[0, 2]
945
+ rotation21 = osMatrix[1, 0]
946
+ rotation22 = osMatrix[1, 1]
947
+ rotation23 = osMatrix[1, 2]
948
+ rotation31 = osMatrix[2, 0]
949
+ rotation32 = osMatrix[2, 1]
950
+ rotation33 = osMatrix[2, 2]
951
+ shadingFace = topologic.TopologyUtility.Transform(shadingFace, osTranslation.x(), osTranslation.y(), osTranslation.z(), rotation11, rotation12, rotation13, rotation21, rotation22, rotation23, rotation31, rotation32, rotation33)
952
+ shadingFaces.append(shadingFace)
953
+
954
+ for count, aSpace in enumerate(spaces):
955
+ osTransformation = aSpace.transformation()
956
+ osTranslation = osTransformation.translation()
957
+ osMatrix = osTransformation.rotationMatrix()
958
+ rotation11 = osMatrix[0, 0]
959
+ rotation12 = osMatrix[0, 1]
960
+ rotation13 = osMatrix[0, 2]
961
+ rotation21 = osMatrix[1, 0]
962
+ rotation22 = osMatrix[1, 1]
963
+ rotation23 = osMatrix[1, 2]
964
+ rotation31 = osMatrix[2, 0]
965
+ rotation32 = osMatrix[2, 1]
966
+ rotation33 = osMatrix[2, 2]
967
+ spaceFaces = []
968
+ surfaces = aSpace.surfaces()
969
+
970
+ for aSurface in surfaces:
971
+ aFace = surfaceToFace(aSurface)
972
+ aFace = topologic.TopologyUtility.Transform(aFace, osTranslation.x(), osTranslation.y(), osTranslation.z(), rotation11, rotation12, rotation13, rotation21, rotation22, rotation23, rotation31, rotation32, rotation33)
973
+ #aFace.__class__ = topologic.Face
974
+ subSurfaces = aSurface.subSurfaces()
975
+ for aSubSurface in subSurfaces:
976
+ aperture = surfaceToFace(aSubSurface)
977
+ aperture = topologic.TopologyUtility.Transform(aperture, osTranslation.x(), osTranslation.y(), osTranslation.z(), rotation11, rotation12, rotation13, rotation21, rotation22, rotation23, rotation31, rotation32, rotation33)
978
+ # aperture.__class__ = topologic.Face
979
+ apertures.append(aperture)
980
+ addApertures(aFace, apertures)
981
+ spaceFaces.append(aFace)
982
+ spaceFaces = [x for x in spaceFaces if isinstance(x, topologic.Face)]
983
+ spaceCell = Cell.ByFaces(spaceFaces)
984
+ if not spaceCell:
985
+ spaceCell = Shell.ByFaces(spaceFaces)
986
+ if not spaceCell:
987
+ spaceCell = Cluster.ByTopologies(spaceFaces)
988
+ if spaceCell: #debugging
989
+ # Set Dictionary for Cell
990
+ keys = []
991
+ values = []
992
+
993
+ keys.append("TOPOLOGIC_id")
994
+ keys.append("TOPOLOGIC_name")
995
+ keys.append("TOPOLOGIC_type")
996
+ keys.append("TOPOLOGIC_color")
997
+ spaceID = str(aSpace.handle()).replace('{','').replace('}','')
998
+ values.append(spaceID)
999
+ values.append(aSpace.name().get())
1000
+ spaceTypeName = "Unknown"
1001
+ red = 255
1002
+ green = 255
1003
+ blue = 255
1004
+
1005
+ if (aSpace.spaceType().is_initialized()):
1006
+ if(aSpace.spaceType().get().name().is_initialized()):
1007
+ spaceTypeName = aSpace.spaceType().get().name().get()
1008
+ if(aSpace.spaceType().get().renderingColor().is_initialized()):
1009
+ red = aSpace.spaceType().get().renderingColor().get().renderingRedValue()
1010
+ green = aSpace.spaceType().get().renderingColor().get().renderingGreenValue()
1011
+ blue = aSpace.spaceType().get().renderingColor().get().renderingBlueValue()
1012
+ values.append(spaceTypeName)
1013
+ values.append([red, green, blue])
1014
+ d = Dictionary.ByKeysValues(keys, values)
1015
+ spaceCell = Topology.SetDictionary(spaceCell, d)
1016
+ cells.append(spaceCell)
1017
+ return {'cells':cells, 'apertures':apertures, 'shadingFaces': shadingFaces}
1018
+
1019
+ @staticmethod
1020
+ def Units(model, reportName, tableName, columnName):
1021
+ """
1022
+ Parameters
1023
+ ----------
1024
+ model : openstudio.openstudiomodelcore.Model
1025
+ The input OSM model.
1026
+ reportName : str
1027
+ The input report name.
1028
+ tableName : str
1029
+ The input table name.
1030
+ columnName : str
1031
+ The input column name.
1032
+
1033
+ Returns
1034
+ -------
1035
+ str
1036
+ The units string found in the input OSM model, report name, table name, and column name.
1037
+
1038
+ """
1039
+ # model = item[0]
1040
+ # reportName = item[1]
1041
+ # tableName = item[2]
1042
+ # columnName = item[3]
1043
+ sql = model.sqlFile().get()
1044
+ query = "SELECT Units FROM tabulardatawithstrings WHERE ReportName = '"+reportName+"' AND TableName = '"+tableName+"' AND ColumnName = '"+columnName+"'"
1045
+ units = sql.execAndReturnFirstString(query)
1046
+ if (units.is_initialized()):
1047
+ units = units.get()
1048
+ else:
1049
+ print("EnergyModel.Units - Error: Could not retrieve the units. Returning None.")
1050
+ return None
1051
+ return units
1052
+