topologicpy 0.8.51__py3-none-any.whl → 0.8.54__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.
- topologicpy/Cell.py +84 -16
- topologicpy/EnergyModel.py +111 -10
- topologicpy/Graph.py +285 -1
- topologicpy/Helper.py +57 -43
- topologicpy/Plotly.py +4 -2
- topologicpy/Topology.py +27 -2
- topologicpy/version.py +1 -1
- {topologicpy-0.8.51.dist-info → topologicpy-0.8.54.dist-info}/METADATA +1 -1
- {topologicpy-0.8.51.dist-info → topologicpy-0.8.54.dist-info}/RECORD +12 -12
- {topologicpy-0.8.51.dist-info → topologicpy-0.8.54.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.51.dist-info → topologicpy-0.8.54.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.51.dist-info → topologicpy-0.8.54.dist-info}/top_level.txt +0 -0
topologicpy/Cell.py
CHANGED
@@ -1552,7 +1552,6 @@ class Cell():
|
|
1552
1552
|
cluster = Cluster.ByTopologies(pentagons)
|
1553
1553
|
|
1554
1554
|
cluster2 = Topology.Rotate(cluster, origin=Vertex.Origin(), axis=[1, 0, 0], angle=180)
|
1555
|
-
#cluster2 = Topology.Rotate(cluster2, origin=Vertex.Origin(), axis=[0, 0, 1], angle=36)
|
1556
1555
|
vertices = Topology.Vertices(cluster)
|
1557
1556
|
zList = [Vertex.Z(v) for v in vertices]
|
1558
1557
|
zList = list(set(zList))
|
@@ -1566,6 +1565,7 @@ class Cell():
|
|
1566
1565
|
dodecahedron = Topology.Translate(dodecahedron, -Vertex.X(centroid), -Vertex.Y(centroid), -Vertex.Z(centroid))
|
1567
1566
|
vertices = Topology.Vertices(dodecahedron)
|
1568
1567
|
d = Vertex.Distance(Vertex.Origin(), vertices[0])
|
1568
|
+
# Make sure the distance from the origin to the vertices is equal to the radius.
|
1569
1569
|
dodecahedron = Topology.Scale(dodecahedron, origin=Vertex.Origin(), x=radius/d, y=radius/d, z=radius/d)
|
1570
1570
|
if placement == "bottom":
|
1571
1571
|
dodecahedron = Topology.Translate(dodecahedron, 0, 0, radius)
|
@@ -3091,9 +3091,9 @@ class Cell():
|
|
3091
3091
|
|
3092
3092
|
@staticmethod
|
3093
3093
|
def Sphere(origin= None, radius: float = 0.5, uSides: int = 16, vSides: int = 8, direction: list = [0, 0, 1],
|
3094
|
-
placement: str = "center", tolerance: float = 0.0001):
|
3094
|
+
placement: str = "center", tolerance: float = 0.0001, silent: bool = False):
|
3095
3095
|
"""
|
3096
|
-
Creates a sphere.
|
3096
|
+
Creates an approximation of a sphere using a UV grid of triangular faces.
|
3097
3097
|
|
3098
3098
|
Parameters
|
3099
3099
|
----------
|
@@ -3111,6 +3111,9 @@ class Cell():
|
|
3111
3111
|
The description of the placement of the origin of the sphere. This can be "bottom", "center", or "lowerleft". It is case insensitive. Default is "center".
|
3112
3112
|
tolerance : float , optional
|
3113
3113
|
The desired tolerance. Default is 0.0001.
|
3114
|
+
silent : bool, optional
|
3115
|
+
If set to True, suppresses warning and error messages. Default is False.
|
3116
|
+
|
3114
3117
|
|
3115
3118
|
Returns
|
3116
3119
|
-------
|
@@ -3118,24 +3121,89 @@ class Cell():
|
|
3118
3121
|
The created sphere.
|
3119
3122
|
|
3120
3123
|
"""
|
3121
|
-
|
3124
|
+
|
3125
|
+
import math
|
3122
3126
|
from topologicpy.Vertex import Vertex
|
3123
|
-
from topologicpy.
|
3124
|
-
from topologicpy.
|
3127
|
+
from topologicpy.Face import Face
|
3128
|
+
from topologicpy.Cell import Cell
|
3125
3129
|
from topologicpy.Topology import Topology
|
3126
3130
|
|
3127
|
-
|
3131
|
+
# Validate inputs
|
3132
|
+
if radius <= 0 or uSides < 3 or vSides < 2:
|
3133
|
+
if not silent:
|
3134
|
+
print("Sphere - Error: radius must be > 0, uSides >= 3, vSides >= 2. Returning None.")
|
3135
|
+
return None
|
3136
|
+
|
3137
|
+
# Center
|
3138
|
+
if origin is None:
|
3128
3139
|
origin = Vertex.ByCoordinates(0, 0, 0)
|
3129
|
-
|
3130
|
-
|
3140
|
+
ox = Vertex.X(origin)
|
3141
|
+
oy = Vertex.Y(origin)
|
3142
|
+
oz = Vertex.Z(origin)
|
3143
|
+
|
3144
|
+
# Poles
|
3145
|
+
top_pole = Vertex.ByCoordinates(ox, oy, oz + radius)
|
3146
|
+
bottom_pole = Vertex.ByCoordinates(ox, oy, oz - radius)
|
3147
|
+
|
3148
|
+
# Latitude rings (exclude poles)
|
3149
|
+
rings = [] # list of list[Vertex]
|
3150
|
+
for vi in range(1, vSides):
|
3151
|
+
phi = math.pi * vi / vSides # 0..pi
|
3152
|
+
sin_phi = math.sin(phi)
|
3153
|
+
cos_phi = math.cos(phi)
|
3154
|
+
ring = []
|
3155
|
+
for ui in range(uSides):
|
3156
|
+
theta = 2.0 * math.pi * ui / uSides
|
3157
|
+
x = ox + radius * sin_phi * math.cos(theta)
|
3158
|
+
y = oy + radius * sin_phi * math.sin(theta)
|
3159
|
+
z = oz + radius * cos_phi
|
3160
|
+
ring.append(Vertex.ByCoordinates(x, y, z))
|
3161
|
+
rings.append(ring)
|
3162
|
+
|
3163
|
+
faces = []
|
3164
|
+
|
3165
|
+
# Top cap: triangles from top pole to first ring
|
3166
|
+
first_ring = rings[0]
|
3167
|
+
for u in range(uSides):
|
3168
|
+
v1 = first_ring[u]
|
3169
|
+
v2 = first_ring[(u + 1) % uSides]
|
3170
|
+
f = Face.ByVertices([top_pole, v1, v2], tolerance=tolerance)
|
3171
|
+
if f:
|
3172
|
+
faces.append(f)
|
3173
|
+
|
3174
|
+
# Middle bands: split quads into two triangles
|
3175
|
+
for i in range(len(rings) - 1):
|
3176
|
+
curr = rings[i]
|
3177
|
+
nxt = rings[i + 1]
|
3178
|
+
for u in range(uSides):
|
3179
|
+
a = curr[u]
|
3180
|
+
b = nxt[u]
|
3181
|
+
c = nxt[(u + 1) % uSides]
|
3182
|
+
d = curr[(u + 1) % uSides]
|
3183
|
+
f1 = Face.ByVertices([a, b, c], tolerance=tolerance)
|
3184
|
+
if f1:
|
3185
|
+
faces.append(f1)
|
3186
|
+
f2 = Face.ByVertices([a, c, d], tolerance=tolerance)
|
3187
|
+
if f2:
|
3188
|
+
faces.append(f2)
|
3189
|
+
|
3190
|
+
# Bottom cap: triangles from last ring to bottom pole
|
3191
|
+
last_ring = rings[-1]
|
3192
|
+
for u in range(uSides):
|
3193
|
+
v1 = last_ring[(u + 1) % uSides]
|
3194
|
+
v2 = last_ring[u]
|
3195
|
+
f = Face.ByVertices([bottom_pole, v1, v2], tolerance=tolerance)
|
3196
|
+
if f:
|
3197
|
+
faces.append(f)
|
3198
|
+
|
3199
|
+
# Sew faces into a shell
|
3200
|
+
sphere = None
|
3201
|
+
try:
|
3202
|
+
sphere = Cell.ByFaces(faces, tolerance=tolerance)
|
3203
|
+
except Exception:
|
3204
|
+
if not silent:
|
3205
|
+
print("Cell.Sphere - Error: could not create a sphere. Returning None.")
|
3131
3206
|
return None
|
3132
|
-
c = Wire.Circle(origin=Vertex.Origin(), radius=radius, sides=vSides, fromAngle=0, toAngle=180, close=False, direction=[0, 0, 1], placement="center")
|
3133
|
-
c = Topology.Rotate(c, origin=Vertex.Origin(), axis=[1, 0, 0], angle=90)
|
3134
|
-
sphere = Topology.Spin(c, origin=Vertex.Origin(), triangulate=False, direction=[0, 0, 1], angle=360, sides=uSides, tolerance=tolerance)
|
3135
|
-
if Topology.Type(sphere) == Topology.TypeID("CellComplex"):
|
3136
|
-
sphere = CellComplex.ExternalBoundary(sphere)
|
3137
|
-
if Topology.Type(sphere) == Topology.TypeID("Shell"):
|
3138
|
-
sphere = Cell.ByShell(sphere)
|
3139
3207
|
if placement.lower() == "bottom":
|
3140
3208
|
sphere = Topology.Translate(sphere, 0, 0, radius)
|
3141
3209
|
elif placement.lower() == "lowerleft":
|
topologicpy/EnergyModel.py
CHANGED
@@ -201,6 +201,51 @@ class EnergyModel:
|
|
201
201
|
warnings.warn("EnergyModel.ByTopology - Error: Could not import openstudio.Please try to install openstudio manually. Returning None.")
|
202
202
|
return None
|
203
203
|
|
204
|
+
|
205
|
+
def load_openstudio_model(osm_path: str, allow_newer: bool = True):
|
206
|
+
"""
|
207
|
+
Load an OpenStudio .osm file and return an openstudio.model.Model.
|
208
|
+
Uses loadModelFromString to avoid SWIG path overload issues.
|
209
|
+
"""
|
210
|
+
import os
|
211
|
+
|
212
|
+
if not os.path.exists(osm_path):
|
213
|
+
raise FileNotFoundError(osm_path)
|
214
|
+
|
215
|
+
vt = openstudio.osversion.VersionTranslator()
|
216
|
+
if allow_newer:
|
217
|
+
vt.setAllowNewerVersions(True)
|
218
|
+
|
219
|
+
# 1) Robust path-agnostic route: read text and load from string
|
220
|
+
with open(osm_path, "r", encoding="utf-8") as f:
|
221
|
+
txt = f.read()
|
222
|
+
model_opt = vt.loadModelFromString(txt) # <- avoids path type mismatches
|
223
|
+
|
224
|
+
# 2) Fallback: try the filesystem-path overloads if needed
|
225
|
+
if (not model_opt) or (not model_opt.is_initialized()):
|
226
|
+
os_path = None
|
227
|
+
for maker in (
|
228
|
+
lambda s: getattr(openstudio, "path")(s),
|
229
|
+
lambda s: getattr(openstudio, "toPath")(s),
|
230
|
+
lambda s: getattr(openstudio.openstudioutilitiescore, "toPath")(s),
|
231
|
+
):
|
232
|
+
try:
|
233
|
+
os_path = maker(osm_path)
|
234
|
+
break
|
235
|
+
except Exception:
|
236
|
+
pass
|
237
|
+
if os_path is not None:
|
238
|
+
try:
|
239
|
+
model_opt = vt.loadModel(os_path)
|
240
|
+
except TypeError:
|
241
|
+
model_opt = openstudio.model.Model.load(os_path)
|
242
|
+
|
243
|
+
if (not model_opt) or (not model_opt.is_initialized()):
|
244
|
+
raise RuntimeError(f"Failed to load OpenStudio model from: {osm_path}")
|
245
|
+
|
246
|
+
model = model_opt.get()
|
247
|
+
return model
|
248
|
+
|
204
249
|
def getKeyName(d, keyName):
|
205
250
|
keys = d.Keys()
|
206
251
|
for key in keys:
|
@@ -243,21 +288,23 @@ class EnergyModel:
|
|
243
288
|
|
244
289
|
if not osModelPath:
|
245
290
|
import os
|
246
|
-
osModelPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "OSMTemplate-OfficeBuilding-3.
|
291
|
+
osModelPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "OSMTemplate-OfficeBuilding-3.10.0.osm")
|
247
292
|
if not weatherFilePath or not designDayFilePath:
|
248
293
|
import os
|
249
294
|
weatherFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.epw")
|
250
295
|
designDayFilePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "assets", "EnergyModel", "GBR_London.Gatwick.037760_IWEC.ddy")
|
251
|
-
|
296
|
+
|
297
|
+
#translator = openstudio.osversion.VersionTranslator()
|
252
298
|
# DEBUGGING
|
253
299
|
#osmFile = openstudio.openstudioutilitiescore.toPath(osModelPath)
|
254
300
|
#osModel = translator.loadModel(osmFile)
|
255
|
-
osModel = translator.loadModel(osModelPath)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
301
|
+
#osModel = translator.loadModel(osModelPath)
|
302
|
+
osModel = load_openstudio_model(osModelPath, allow_newer=True)
|
303
|
+
# if osModel.isNull():
|
304
|
+
# print("EnergyModel.ByTopology - Error: The openstudio model is null. Returning None.")
|
305
|
+
# return None
|
306
|
+
# else:
|
307
|
+
# osModel = osModel.get()
|
261
308
|
# DEBUGGING
|
262
309
|
#osEPWFile = openstudio.openstudioutilitiesfiletypes.EpwFile.load(openstudio.toPath(weatherFilePath))
|
263
310
|
osEPWFile = openstudio.openstudioutilitiesfiletypes.EpwFile.load(weatherFilePath)
|
@@ -265,8 +312,8 @@ class EnergyModel:
|
|
265
312
|
osEPWFile = osEPWFile.get()
|
266
313
|
openstudio.model.WeatherFile.setWeatherFile(osModel, osEPWFile)
|
267
314
|
# DEBUGGING
|
268
|
-
|
269
|
-
ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(designDayFilePath)
|
315
|
+
ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(openstudio.toPath(designDayFilePath))
|
316
|
+
#ddyModel = openstudio.openstudioenergyplus.loadAndTranslateIdf(designDayFilePath)
|
270
317
|
if ddyModel.is_initialized():
|
271
318
|
ddyModel = ddyModel.get()
|
272
319
|
for ddy in ddyModel.getObjectsByType(openstudio.IddObjectType("OS:SizingPeriod:DesignDay")):
|
@@ -1195,3 +1242,57 @@ class EnergyModel:
|
|
1195
1242
|
return None
|
1196
1243
|
return units
|
1197
1244
|
|
1245
|
+
@staticmethod
|
1246
|
+
def Version(check: bool = True, silent: bool = False):
|
1247
|
+
"""
|
1248
|
+
Returns the OpenStudio SDK version number.
|
1249
|
+
|
1250
|
+
Parameters
|
1251
|
+
----------
|
1252
|
+
check : bool , optional
|
1253
|
+
if set to True, the version number is checked with the latest version on PyPi. Default is True.
|
1254
|
+
|
1255
|
+
silent : bool , optional
|
1256
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
1257
|
+
|
1258
|
+
Returns
|
1259
|
+
-------
|
1260
|
+
str
|
1261
|
+
The OpenStudio SDK version number.
|
1262
|
+
|
1263
|
+
"""
|
1264
|
+
from topologicpy.Helper import Helper
|
1265
|
+
try:
|
1266
|
+
import openstudio
|
1267
|
+
openstudio.Logger.instance().standardOutLogger().setLogLevel(openstudio.Fatal)
|
1268
|
+
except:
|
1269
|
+
if not silent:
|
1270
|
+
print("EnergyModel.Version - Information: Installing required openstudio library.")
|
1271
|
+
try:
|
1272
|
+
os.system("pip install openstudio")
|
1273
|
+
except:
|
1274
|
+
os.system("pip install openstudio --user")
|
1275
|
+
try:
|
1276
|
+
import openstudio
|
1277
|
+
openstudio.Logger.instance().standardOutLogger().setLogLevel(openstudio.Fatal)
|
1278
|
+
if not silent:
|
1279
|
+
print("EnergyModel.Version - Information: openstudio library installed correctly.")
|
1280
|
+
except:
|
1281
|
+
if not silent:
|
1282
|
+
print("EnergyModel.Version - Error: Could not import openstudio.Please try to install openstudio manually. Returning None.")
|
1283
|
+
return None
|
1284
|
+
import requests
|
1285
|
+
from packaging import version
|
1286
|
+
|
1287
|
+
result = getattr(openstudio, "openStudioVersion", None)
|
1288
|
+
if callable(result):
|
1289
|
+
result = result()
|
1290
|
+
else:
|
1291
|
+
if not silent:
|
1292
|
+
print("EnergyModel.Version - Error: Could not retrieve the openstudio SDK version number. Returning None.")
|
1293
|
+
return None
|
1294
|
+
if check == True:
|
1295
|
+
result = Helper.CheckVersion("openstudio", result, silent=silent)
|
1296
|
+
return result
|
1297
|
+
|
1298
|
+
|
topologicpy/Graph.py
CHANGED
@@ -784,7 +784,291 @@ class Graph:
|
|
784
784
|
return csv_buffer.getvalue()
|
785
785
|
except Exception as e:
|
786
786
|
return ""
|
787
|
-
|
787
|
+
|
788
|
+
@staticmethod
|
789
|
+
def AdjacencyMatrixFigure(graph,
|
790
|
+
vertexKey: str = None,
|
791
|
+
showZero: bool = False,
|
792
|
+
zeroChar: str = "·",
|
793
|
+
zeroColor: str = 'rgba(0,0,0,0)',
|
794
|
+
valueColor: str = 'rgba(0,0,0,0.05)',
|
795
|
+
diagonalHighlight: bool = True,
|
796
|
+
diagonalColor: str = 'rgba(0,0,0,0)',
|
797
|
+
title: str = None,
|
798
|
+
cellSize: int = 24,
|
799
|
+
fontFamily: str = "Arial",
|
800
|
+
fontSize: int = 12,
|
801
|
+
fontColor: str = 'rgba(0,0,0,0)',
|
802
|
+
backgroundColor: str = 'rgba(0,0,0,0)',
|
803
|
+
headerColor: str = 'rgba(0,0,0,0)',
|
804
|
+
reverse=False,
|
805
|
+
edgeKeyFwd=None,
|
806
|
+
edgeKeyBwd=None,
|
807
|
+
bidirKey=None,
|
808
|
+
bidirectional=True,
|
809
|
+
useEdgeIndex=False,
|
810
|
+
useEdgeLength=False,
|
811
|
+
mantissa: int = 6,
|
812
|
+
tolerance=0.0001,
|
813
|
+
silent: bool = False):
|
814
|
+
"""
|
815
|
+
Returns a Plotly table figure visualizing the adjacency matrix of a Graph.
|
816
|
+
|
817
|
+
Parameters
|
818
|
+
----------
|
819
|
+
graph : topologic_core.Graph
|
820
|
+
The input graph.
|
821
|
+
vertexKey : str , optional
|
822
|
+
If set, the returned list of vertices is sorted according to the dictionary values stored under this key. Default is None.
|
823
|
+
showZero : bool, optional
|
824
|
+
If True, show zeros as "0"; if False, show a subtle glyph (zero_char) or blank. Default is False.
|
825
|
+
zeroChar : str, optional
|
826
|
+
Character to display for zero entries when show_zero is False. Default is "·".
|
827
|
+
zeroColor : list or str , optional
|
828
|
+
The desired color to display for zero-valued cells. This can be any color list or plotly color string and may be specified as:
|
829
|
+
- An rgb list (e.g. [255,0,0])
|
830
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
831
|
+
- A hex string (e.g. '#ff0000')
|
832
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
833
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
834
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
835
|
+
- A named CSS color.
|
836
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
837
|
+
valueColor : list or str , optional
|
838
|
+
The desired color to display for non-zero-valued cells. This can be any color list or plotly color string and may be specified as:
|
839
|
+
- An rgb list (e.g. [255,0,0])
|
840
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
841
|
+
- A hex string (e.g. '#ff0000')
|
842
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
843
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
844
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
845
|
+
- A named CSS color.
|
846
|
+
The default is 'rgba(0,0,0,0.35)' (slight highlight).
|
847
|
+
diagonalHighlight : bool, optional
|
848
|
+
If True, lightly highlight diagonal cells. Default is True.
|
849
|
+
diagonalColor : list or str , optional
|
850
|
+
The desired diagonal highlight color. This can be any color list or plotly color string and may be specified as:
|
851
|
+
- An rgb list (e.g. [255,0,0])
|
852
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
853
|
+
- A hex string (e.g. '#ff0000')
|
854
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
855
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
856
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
857
|
+
- A named CSS color.
|
858
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
859
|
+
title : str, optional
|
860
|
+
Optional figure title.
|
861
|
+
cellSize : int, optional
|
862
|
+
Approximate pixel height of each table row. Default is 24.
|
863
|
+
fontFamily : str, optional
|
864
|
+
Font family for table text. Default is "Arial".
|
865
|
+
fontSize : int, optional
|
866
|
+
Font size for table text. Default is 12.
|
867
|
+
fontColor : list or str , optional
|
868
|
+
The desired font color. This can be any color list or plotly color string and may be specified as:
|
869
|
+
- An rgb list (e.g. [255,0,0])
|
870
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
871
|
+
- A hex string (e.g. '#ff0000')
|
872
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
873
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
874
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
875
|
+
- A named CSS color.
|
876
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
877
|
+
backgroundColor : list or str , optional
|
878
|
+
The desired background color. This can be any color list or plotly color string and may be specified as:
|
879
|
+
- An rgb list (e.g. [255,0,0])
|
880
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
881
|
+
- A hex string (e.g. '#ff0000')
|
882
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
883
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
884
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
885
|
+
- A named CSS color.
|
886
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
887
|
+
headerColor : list or str , optional
|
888
|
+
The desired header color. This can be any color list or plotly color string and may be specified as:
|
889
|
+
- An rgb list (e.g. [255,0,0])
|
890
|
+
- A cmyk list (e.g. [0.5, 0, 0.25, 0.2])
|
891
|
+
- A hex string (e.g. '#ff0000')
|
892
|
+
- An rgb/rgba string (e.g. 'rgb(255,0,0)')
|
893
|
+
- An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
|
894
|
+
- An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
|
895
|
+
- A named CSS color.
|
896
|
+
The default is 'rgba(0,0,0,0)' (transparent).
|
897
|
+
reverse : bool , optional
|
898
|
+
If set to True, the vertices are sorted in reverse order (only if vertexKey is set). Otherwise, they are not. Default is False.
|
899
|
+
edgeKeyFwd : str , optional
|
900
|
+
If set, the value at this key in the connecting edge from start vertex to end vertex (forward) will be used instead of the value 1. Default is None. useEdgeIndex and useEdgeLength override this setting.
|
901
|
+
edgeKeyBwd : str , optional
|
902
|
+
If set, the value at this key in the connecting edge from end vertex to start vertex (backward) will be used instead of the value 1. Default is None. useEdgeIndex and useEdgeLength override this setting.
|
903
|
+
bidirKey : bool , optional
|
904
|
+
If set to True or False, this key in the connecting edge will be used to determine is the edge is supposed to be bidirectional or not. If set to None, the input variable bidrectional will be used instead. Default is None
|
905
|
+
bidirectional : bool , optional
|
906
|
+
If set to True, the edges in the graph that do not have a bidireKey in their dictionaries will be treated as being bidirectional. Otherwise, the start vertex and end vertex of the connecting edge will determine the direction. Default is True.
|
907
|
+
useEdgeIndex : bool , optional
|
908
|
+
If set to True, the adjacency matrix values will the index of the edge in Graph.Edges(graph). Default is False. Both useEdgeIndex, useEdgeLength should not be True at the same time. If they are, useEdgeLength will be used.
|
909
|
+
useEdgeLength : bool , optional
|
910
|
+
If set to True, the adjacency matrix values will the length of the edge in Graph.Edges(graph). Default is False. Both useEdgeIndex, useEdgeLength should not be True at the same time. If they are, useEdgeLength will be used.
|
911
|
+
mantissa : int , optional
|
912
|
+
The number of decimal places to round the result to. Default is 6.
|
913
|
+
tolerance : float , optional
|
914
|
+
The desired tolerance. Default is 0.0001.
|
915
|
+
silent : bool, optional
|
916
|
+
If True, suppresses warning messages. Default is False.
|
917
|
+
|
918
|
+
Returns
|
919
|
+
-------
|
920
|
+
plotly.graph_objs._figure.Figure
|
921
|
+
A Plotly table figure containing the adjacency matrix table.
|
922
|
+
"""
|
923
|
+
|
924
|
+
from topologicpy.Topology import Topology
|
925
|
+
from topologicpy.Graph import Graph
|
926
|
+
from topologicpy.Dictionary import Dictionary
|
927
|
+
import plotly.graph_objects as go
|
928
|
+
|
929
|
+
if not Topology.IsInstance(graph, "Graph"):
|
930
|
+
if not silent:
|
931
|
+
print("Plotly.AdjacencyMatrixTable - Error: The input is not a valid Graph. Returning None.")
|
932
|
+
return None
|
933
|
+
|
934
|
+
# Build adjacency matrix
|
935
|
+
adj = Graph.AdjacencyMatrix(graph,
|
936
|
+
vertexKey=vertexKey,
|
937
|
+
reverse=reverse,
|
938
|
+
edgeKeyFwd=edgeKeyFwd,
|
939
|
+
edgeKeyBwd=edgeKeyBwd,
|
940
|
+
bidirKey=bidirKey,
|
941
|
+
bidirectional=bidirectional,
|
942
|
+
useEdgeIndex=useEdgeIndex,
|
943
|
+
useEdgeLength=useEdgeLength,
|
944
|
+
mantissa=mantissa,
|
945
|
+
tolerance=tolerance)
|
946
|
+
|
947
|
+
if adj is None or not isinstance(adj, list) or len(adj) == 0:
|
948
|
+
if not silent:
|
949
|
+
print("Plotly.AdjacencyMatrixTable - Warning: Empty adjacency matrix. Returning None.")
|
950
|
+
return None
|
951
|
+
|
952
|
+
n = len(adj)
|
953
|
+
# Validate squareness
|
954
|
+
if any((not isinstance(row, list) or len(row) != n) for row in adj):
|
955
|
+
if not silent:
|
956
|
+
print("Plotly.AdjacencyMatrixTable - Error: Adjacency matrix must be square. Returning None.")
|
957
|
+
return None
|
958
|
+
|
959
|
+
# Derive labels
|
960
|
+
verts = Graph.Vertices(graph)
|
961
|
+
labels = [Dictionary.ValueAtKey(Topology.Dictionary(v), vertexKey, str(i)) for i, v in enumerate(verts)]
|
962
|
+
if len(labels) > 0 and not vertexKey == None:
|
963
|
+
labels.sort()
|
964
|
+
if reverse == True:
|
965
|
+
labels.reverse()
|
966
|
+
# Build display matrix (strings) while keeping a parallel style mask for diagonal
|
967
|
+
display_matrix = []
|
968
|
+
diag_mask = []
|
969
|
+
for r in range(n):
|
970
|
+
row_vals = []
|
971
|
+
row_diag = []
|
972
|
+
for c in range(n):
|
973
|
+
v = adj[r][c]
|
974
|
+
if v == 0:
|
975
|
+
row_vals.append("0" if showZero else (zeroChar if zeroChar else ""))
|
976
|
+
else:
|
977
|
+
# Keep integers unpadded for clarity; cast others nicely
|
978
|
+
row_vals.append(str(int(v)) if isinstance(v, (int, float)) and float(v).is_integer() else str(v))
|
979
|
+
row_diag.append(r == c)
|
980
|
+
display_matrix.append(row_vals)
|
981
|
+
diag_mask.append(row_diag)
|
982
|
+
|
983
|
+
# Construct header and cells for Plotly Table
|
984
|
+
# Header: blank corner + column labels
|
985
|
+
header_values = [""] + labels
|
986
|
+
|
987
|
+
# Body: first column is row labels, then matrix cells as strings
|
988
|
+
# Plotly Table expects columns as lists; we need to transpose
|
989
|
+
columns = []
|
990
|
+
# Column 0: row labels
|
991
|
+
columns.append(labels)
|
992
|
+
# Subsequent columns: for each c, collect display_matrix[r][c]
|
993
|
+
for c in range(n):
|
994
|
+
columns.append([display_matrix[r][c] for r in range(n)])
|
995
|
+
|
996
|
+
# Flatten cell fill_colors to highlight diagonal subtly.
|
997
|
+
# Plotly Table allows per-cell fillcolor via a 2D list matching the table shape for 'cells'.
|
998
|
+
# Our cells shape is n rows x (n+1) cols (including row label column).
|
999
|
+
|
1000
|
+
fill_colors = []
|
1001
|
+
# Column 0: row labels (no highlight)
|
1002
|
+
fill_colors.append([headerColor] * n)
|
1003
|
+
|
1004
|
+
# Columns 1..n: highlight diagonal where row index r == (column_index-1)
|
1005
|
+
for c in range(1, n + 1):
|
1006
|
+
col_colors = []
|
1007
|
+
for r in range(n):
|
1008
|
+
if diagonalHighlight and r == (c - 1):
|
1009
|
+
col_colors.append(diagonalColor)
|
1010
|
+
elif columns[c][r] == "0" or columns[c][r] == zeroChar:
|
1011
|
+
col_colors.append(zeroColor)
|
1012
|
+
else:
|
1013
|
+
col_colors.append(valueColor)
|
1014
|
+
fill_colors.append(col_colors)
|
1015
|
+
|
1016
|
+
# Minimal line style
|
1017
|
+
line_color = "rgba(0,0,0,0.12)"
|
1018
|
+
# --- Sizing to prevent cropped text ---
|
1019
|
+
# Heuristic widths (pixels)
|
1020
|
+
max_label_len = max(len(str(x)) for x in labels) if labels else 1
|
1021
|
+
row_label_px = max(120, min(320, 8 * max_label_len)) # scale with label length
|
1022
|
+
cell_px = 36 if n <= 30 else (30 if n <= 50 else 24) # narrower cells for very wide matrices
|
1023
|
+
|
1024
|
+
# Adaptive cell font size for many columns
|
1025
|
+
fontSize = max(fontSize, 3)
|
1026
|
+
cell_font_size = fontSize if n <= 35 else (fontSize-1 if n <= 60 else fontSize-2)
|
1027
|
+
|
1028
|
+
# Figure width: row label column + all matrix columns
|
1029
|
+
fig_width = row_label_px + n * cell_px
|
1030
|
+
fig_width = max(600, min(2400, fig_width)) # clamp to reasonable bounds
|
1031
|
+
|
1032
|
+
# Increase row height a bit for readability
|
1033
|
+
cellSize = max(cellSize, 26)
|
1034
|
+
|
1035
|
+
# Column widths in px (Plotly Table accepts pixel widths)
|
1036
|
+
columnwidth = [row_label_px] + [cell_px] * n
|
1037
|
+
fig = go.Figure(
|
1038
|
+
data=[
|
1039
|
+
go.Table(
|
1040
|
+
header=dict(
|
1041
|
+
values=header_values,
|
1042
|
+
align="center",
|
1043
|
+
font=dict(family=fontFamily, size=cell_font_size, color=fontColor),
|
1044
|
+
fill_color=headerColor,
|
1045
|
+
line_color=line_color,
|
1046
|
+
height=cellSize + 4 # a touch taller for the header
|
1047
|
+
),
|
1048
|
+
cells=dict(
|
1049
|
+
values=columns,
|
1050
|
+
align=["right"] + ["center"] * n,
|
1051
|
+
font=dict(family=fontFamily, size=cell_font_size, color=fontColor),
|
1052
|
+
fill_color=fill_colors,
|
1053
|
+
line_color=line_color,
|
1054
|
+
height=cellSize
|
1055
|
+
),
|
1056
|
+
columnorder=list(range(n + 1)),
|
1057
|
+
columnwidth=columnwidth
|
1058
|
+
)
|
1059
|
+
]
|
1060
|
+
)
|
1061
|
+
|
1062
|
+
# Layout: generous margins, white background, optional title
|
1063
|
+
fig.update_layout(
|
1064
|
+
title=dict(text=title, x=0.5, xanchor="center") if title else None,
|
1065
|
+
paper_bgcolor="white",
|
1066
|
+
plot_bgcolor=backgroundColor,
|
1067
|
+
margin=dict(l=20, r=20, t=40 if title else 10, b=20)
|
1068
|
+
)
|
1069
|
+
|
1070
|
+
return fig
|
1071
|
+
|
788
1072
|
@staticmethod
|
789
1073
|
def AdjacencyList(graph, vertexKey=None, reverse=True, tolerance=0.0001):
|
790
1074
|
"""
|
topologicpy/Helper.py
CHANGED
@@ -90,6 +90,53 @@ class Helper:
|
|
90
90
|
|
91
91
|
return sorted(bin_averages)
|
92
92
|
|
93
|
+
def CheckVersion(library: str = None, version: str = None, silent: bool = False):
|
94
|
+
"""
|
95
|
+
Compare an input version with the latest version of a Python library on PyPI.
|
96
|
+
|
97
|
+
Parameters
|
98
|
+
----------
|
99
|
+
library : str
|
100
|
+
The input software library name. Default is None.
|
101
|
+
version : str
|
102
|
+
The input software version number to compare. Default is None.
|
103
|
+
silent : bool , optional
|
104
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
str: A message indicating whether the input version is less than,
|
108
|
+
equal to, or greater than the latest version on PyPI.
|
109
|
+
"""
|
110
|
+
import requests
|
111
|
+
from packaging import version as ver
|
112
|
+
|
113
|
+
try:
|
114
|
+
# Fetch library data from PyPI
|
115
|
+
url = f"https://pypi.org/pypi/{library}/json"
|
116
|
+
response = requests.get(url)
|
117
|
+
response.raise_for_status()
|
118
|
+
|
119
|
+
# Extract the latest version from the JSON response
|
120
|
+
data = response.json()
|
121
|
+
latest_version = data['info']['version']
|
122
|
+
|
123
|
+
# Compare versions using the packaging library
|
124
|
+
if ver.parse(version) < ver.parse(latest_version):
|
125
|
+
return (f"The version that you are using ({version}) is OLDER than the latest version ({latest_version}) from PyPI. Please consider upgrading to the latest version.")
|
126
|
+
elif ver.parse(version) == ver.parse(latest_version):
|
127
|
+
return (f"The version that you are using ({version}) is EQUAL TO the latest version available on PyPI.")
|
128
|
+
else:
|
129
|
+
return (f"The version that you are using ({version}) is NEWER than the latest version ({latest_version}) available from PyPI.")
|
130
|
+
|
131
|
+
except requests.exceptions.RequestException as e:
|
132
|
+
if not silent:
|
133
|
+
print("Helper.CheckVersion - Error: Could not fetch data from PyPI. Returning None")
|
134
|
+
return None
|
135
|
+
except KeyError:
|
136
|
+
if not silent:
|
137
|
+
print("Helper.CheckVersion - Error: Could not fetch data from PyPI. Returning None")
|
138
|
+
return None
|
139
|
+
|
93
140
|
@staticmethod
|
94
141
|
def ClosestMatch(item, listA):
|
95
142
|
"""
|
@@ -788,58 +835,25 @@ class Helper:
|
|
788
835
|
return returnList
|
789
836
|
|
790
837
|
@staticmethod
|
791
|
-
def Version():
|
838
|
+
def Version(check: bool = True, silent: bool = False):
|
792
839
|
"""
|
793
840
|
Returns the current version of the software.
|
794
841
|
|
795
842
|
Parameters
|
796
843
|
----------
|
797
|
-
|
844
|
+
check : bool , optional
|
845
|
+
if set to True, the version number is checked with the latest version on PyPi. Default is True.
|
846
|
+
silent : bool , optional
|
847
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
848
|
+
|
798
849
|
Returns
|
799
850
|
-------
|
800
851
|
str
|
801
|
-
The current version of the software.
|
852
|
+
The current version of the software. Optionally, includes a check with PyPi.
|
802
853
|
|
803
854
|
"""
|
804
855
|
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
def compare_version_with_pypi(library_name, input_version):
|
809
|
-
"""
|
810
|
-
Compare an input version with the latest version of a Python library on PyPI.
|
811
|
-
|
812
|
-
Args:
|
813
|
-
library_name (str): The name of the Python library on PyPI.
|
814
|
-
input_version (str): The version number to compare (e.g., "0.7.58").
|
815
|
-
|
816
|
-
Returns:
|
817
|
-
str: A message indicating whether the input version is less than,
|
818
|
-
equal to, or greater than the latest version on PyPI.
|
819
|
-
"""
|
820
|
-
try:
|
821
|
-
# Fetch library data from PyPI
|
822
|
-
url = f"https://pypi.org/pypi/{library_name}/json"
|
823
|
-
response = requests.get(url)
|
824
|
-
response.raise_for_status()
|
825
|
-
|
826
|
-
# Extract the latest version from the JSON response
|
827
|
-
data = response.json()
|
828
|
-
latest_version = data['info']['version']
|
829
|
-
|
830
|
-
# Compare versions using the packaging library
|
831
|
-
if version.parse(input_version) < version.parse(latest_version):
|
832
|
-
return (f"The version that you are using ({input_version}) is OLDER than the latest version {latest_version} from PyPI. Please consider upgrading to the latest version.")
|
833
|
-
elif version.parse(input_version) == version.parse(latest_version):
|
834
|
-
return (f"The version that you are using ({input_version}) is the latest version available on PyPI.")
|
835
|
-
else:
|
836
|
-
return (f"The version that you are using ({input_version}) is NEWER than the latest version ({latest_version}) available from PyPI.")
|
837
|
-
|
838
|
-
except requests.exceptions.RequestException as e:
|
839
|
-
return f"Error fetching data from PyPI: {e}"
|
840
|
-
except KeyError:
|
841
|
-
return "Error: Unable to find the latest version in the PyPI response."
|
842
|
-
|
843
|
-
current_version = topologicpy.__version__
|
844
|
-
result = compare_version_with_pypi("topologicpy", current_version)
|
856
|
+
result = topologicpy.__version__
|
857
|
+
if check == True:
|
858
|
+
result = Helper.CheckVersion("topologicpy", result, silent=silent)
|
845
859
|
return result
|
topologicpy/Plotly.py
CHANGED
@@ -1447,8 +1447,10 @@ class Plotly:
|
|
1447
1447
|
----------
|
1448
1448
|
matrix : list or numpy.array
|
1449
1449
|
The matrix to display.
|
1450
|
-
|
1451
|
-
The list of categories to use on the X
|
1450
|
+
xCategories : list
|
1451
|
+
The list of categories to use on the X axis.
|
1452
|
+
yCategories : list
|
1453
|
+
The list of categories to use on the Y axis.
|
1452
1454
|
minValue : float , optional
|
1453
1455
|
The desired minimum value to use for the color scale. If set to None, the minmum value found in the input matrix will be used. Default is None.
|
1454
1456
|
maxValue : float , optional
|
topologicpy/Topology.py
CHANGED
@@ -8320,6 +8320,8 @@ class Topology():
|
|
8320
8320
|
absolute=False,
|
8321
8321
|
sides=8,
|
8322
8322
|
angle=0,
|
8323
|
+
|
8324
|
+
showFigure=True,
|
8323
8325
|
mantissa=6,
|
8324
8326
|
tolerance=0.0001,
|
8325
8327
|
silent=False):
|
@@ -8507,6 +8509,8 @@ class Topology():
|
|
8507
8509
|
The units used in the colorbar. Default is ""
|
8508
8510
|
colorScale : str , optional
|
8509
8511
|
The desired type of plotly color scales to use (e.g. "viridis", "plasma"). Default is "viridis". For a full list of names, see https://plotly.com/python/builtin-colorscales/.
|
8512
|
+
showFigure : bool , optional
|
8513
|
+
If set to True, the figure will be shown and a None is returned. If not, the figure will be returned, but not shown. Default is True.
|
8510
8514
|
mantissa : int , optional
|
8511
8515
|
The desired length of the mantissa for the values listed on the colorbar. Default is 6.
|
8512
8516
|
tolerance : float , optional
|
@@ -8516,7 +8520,8 @@ class Topology():
|
|
8516
8520
|
|
8517
8521
|
Returns
|
8518
8522
|
-------
|
8519
|
-
|
8523
|
+
Plotly figure
|
8524
|
+
The created plotly figure.
|
8520
8525
|
|
8521
8526
|
"""
|
8522
8527
|
|
@@ -8691,7 +8696,27 @@ class Topology():
|
|
8691
8696
|
tolerance=tolerance)
|
8692
8697
|
if showScale:
|
8693
8698
|
figure = Plotly.AddColorBar(figure, values=cbValues, nTicks=cbTicks, xPosition=cbX, width=cbWidth, outlineWidth=cbOutlineWidth, title=cbTitle, subTitle=cbSubTitle, units=cbUnits, colorScale=colorScale, mantissa=mantissa)
|
8694
|
-
|
8699
|
+
if showFigure:
|
8700
|
+
Plotly.Show(figure=figure, renderer=renderer, camera=camera, center=center, up=up, projection=projection)
|
8701
|
+
return None
|
8702
|
+
if "ortho" in projection.lower():
|
8703
|
+
camera_settings = dict(eye=dict(x=camera[0], y=camera[1], z=camera[2]),
|
8704
|
+
center=dict(x=center[0], y=center[1], z=center[2]),
|
8705
|
+
up=dict(x=up[0], y=up[1], z=up[2]),
|
8706
|
+
projection=dict(type="orthographic"))
|
8707
|
+
else:
|
8708
|
+
camera_settings = dict(eye=dict(x=camera[0], y=camera[1], z=camera[2]),
|
8709
|
+
center=dict(x=center[0], y=center[1], z=center[2]),
|
8710
|
+
up=dict(x=up[0], y=up[1], z=up[2]),
|
8711
|
+
projection=dict(type="perspective"))
|
8712
|
+
|
8713
|
+
figure.update_layout(
|
8714
|
+
scene_camera = camera_settings,
|
8715
|
+
scene=dict(aspectmode="data"),
|
8716
|
+
autosize=True,
|
8717
|
+
margin=dict(l=40, r=40, t=40, b=40)
|
8718
|
+
)
|
8719
|
+
return figure
|
8695
8720
|
|
8696
8721
|
@staticmethod
|
8697
8722
|
def SmallestFaces(topology, removeCoplanarFaces: bool = False, epsilon: float = 0.001, tolerance: float = 0.0001, silent: bool = False):
|
topologicpy/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = '0.8.
|
1
|
+
__version__ = '0.8.54'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.54
|
4
4
|
Summary: An AI-Powered Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
|
5
5
|
Author-email: Wassim Jabi <wassim.jabi@gmail.com>
|
6
6
|
License: AGPL v3 License
|
@@ -2,7 +2,7 @@ topologicpy/ANN.py,sha256=gpflv4lFypOW789vO7mSkMLaMF_ZftVOCqCvtGr6-JA,47873
|
|
2
2
|
topologicpy/Aperture.py,sha256=wNn5miB_IrGCBYuQ18HXQYRva20dUC3id4AJCulL7to,2723
|
3
3
|
topologicpy/BVH.py,sha256=JA4bb-9hgMfVZ_syzmSmTL3ueCq-0vMUGMPZxNcawAY,13023
|
4
4
|
topologicpy/CSG.py,sha256=09la1-xzS9vr-WnV7tpJ0I-mkZ-XY0MRSd5iB50Nfgw,15556
|
5
|
-
topologicpy/Cell.py,sha256=
|
5
|
+
topologicpy/Cell.py,sha256=ndrfovjwEEQTJ0B5DuthuCBDdVg9-1i_MX8Dtj-wD4E,177330
|
6
6
|
topologicpy/CellComplex.py,sha256=Kbz63rGeE08bJfMXFvB-AptoKHiaCK5OtiV1wz8Y-Fk,68081
|
7
7
|
topologicpy/Cluster.py,sha256=G49AuhJHQ1s819cB5MtVdmAGgkag19IC3dRP1ub1Wh4,58608
|
8
8
|
topologicpy/Color.py,sha256=hzSmgBWhiuYc55RSipkQNIgGtgyhC5BqY8AakNYEK-U,24486
|
@@ -10,29 +10,29 @@ topologicpy/Context.py,sha256=G3CwMvN8Jw2rnQRwB-n4MaQq_wLS0vPimbXKwsdMJ80,3055
|
|
10
10
|
topologicpy/DGL.py,sha256=O7r22ss0tgak4kWaACkyExhR_rZ46O_bqIBpxAcwJkw,138918
|
11
11
|
topologicpy/Dictionary.py,sha256=Z4YQ88tONWd-0X0dENQ8IZqIOa9mbBqhJkTBsHmft2g,44619
|
12
12
|
topologicpy/Edge.py,sha256=DifItuyabFDUFC7CVMlt2DeMFMNaGOqCg43iU9CPP0A,74029
|
13
|
-
topologicpy/EnergyModel.py,sha256=
|
13
|
+
topologicpy/EnergyModel.py,sha256=hB1aiJe45gdDMFm1AhkBr-1djjtXSzn24iRpQMk43-4,57749
|
14
14
|
topologicpy/Face.py,sha256=aX9EcR3JGbLITElhd25J0Z8m9U8KkmbYivGg3oZN-Uw,202296
|
15
|
-
topologicpy/Graph.py,sha256=
|
15
|
+
topologicpy/Graph.py,sha256=Oa0oOrPoOSUGL5fvJYHBH_r6kRZ944wk-P828GyAjk4,705757
|
16
16
|
topologicpy/Grid.py,sha256=3OsBMyHh4w8gpFOTMKHMNTpo62V0CwRNu5cwm87yDUA,18421
|
17
|
-
topologicpy/Helper.py,sha256=
|
17
|
+
topologicpy/Helper.py,sha256=Nr6pyzl0sZm4Cu11wOqoYKu6yYal5N6A9jErXnaZBJc,31765
|
18
18
|
topologicpy/Honeybee.py,sha256=C7Am0kCK3a5rt7Jpu2EIgqeR114ZJWtsx4_DBcr5hQA,21716
|
19
19
|
topologicpy/Matrix.py,sha256=bOofT34G3YHu9aMIWx60YHAJga4R0GbDjsZBUD4Hu_k,22706
|
20
20
|
topologicpy/Neo4j.py,sha256=J8jU_mr5-mWC0Lg_D2dMjMlx1rY_eh8ks_aubUuTdWw,22319
|
21
|
-
topologicpy/Plotly.py,sha256=
|
21
|
+
topologicpy/Plotly.py,sha256=kF7JwBMWJQAuGezaJYI6Cq7ErNwEtcKzaExOfdGPIMc,123003
|
22
22
|
topologicpy/Polyskel.py,sha256=oVfM4lqSMPTjnkHfsRU9VI8Blt6Vf0LVPkD9ebz7Wmw,27082
|
23
23
|
topologicpy/PyG.py,sha256=wOsoBFxMgwZYWjj86OMkz_PJuQ02locV_djhSDD6dVc,109644
|
24
24
|
topologicpy/ShapeGrammar.py,sha256=KYsKDLXWdflAcYMAIz84AUF-GMkbTmaBDd2-ovbilqU,23336
|
25
25
|
topologicpy/Shell.py,sha256=ioO4raCJfXtYldQg-adpcLVeJPEA6od6cAA5ro7t6r4,96792
|
26
26
|
topologicpy/Speckle.py,sha256=-eiTqJugd7pHiHpD3pDUcDO6CGhVyPV14HFRzaqEoaw,18187
|
27
27
|
topologicpy/Sun.py,sha256=8S6dhCKfOhUGVny-jEk87Q08anLYMB1JEBKRGCklvbQ,36670
|
28
|
-
topologicpy/Topology.py,sha256=
|
28
|
+
topologicpy/Topology.py,sha256=R5Ac3V_ADDRDZjhpcNvhM3AvDOLU6ORvB3yILyEkxnI,472559
|
29
29
|
topologicpy/Vector.py,sha256=pEC8YY3TeHGfGdeNgvdHjgMDwxGabp5aWjwYC1HSvMk,42236
|
30
30
|
topologicpy/Vertex.py,sha256=0f6HouARKaCuxhdxsUEYi8T9giJycnWhQ8Cn70YILBA,84885
|
31
31
|
topologicpy/Wire.py,sha256=gjgQUGHdBdXUIijgZc_VIW0E39w-smaVhhdl0jF63fQ,230466
|
32
32
|
topologicpy/__init__.py,sha256=RMftibjgAnHB1vdL-muo71RwMS4972JCxHuRHOlU428,928
|
33
|
-
topologicpy/version.py,sha256=
|
34
|
-
topologicpy-0.8.
|
35
|
-
topologicpy-0.8.
|
36
|
-
topologicpy-0.8.
|
37
|
-
topologicpy-0.8.
|
38
|
-
topologicpy-0.8.
|
33
|
+
topologicpy/version.py,sha256=4rZKb5aqUqZkGV-bsREBGvAbGTFOte68oezCn9q__NM,23
|
34
|
+
topologicpy-0.8.54.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
|
35
|
+
topologicpy-0.8.54.dist-info/METADATA,sha256=mfbs0io_WTGxQzjuphNKxMpb12yRIYEt43sfj9gSVc4,10535
|
36
|
+
topologicpy-0.8.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
37
|
+
topologicpy-0.8.54.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
|
38
|
+
topologicpy-0.8.54.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|