topologicpy 0.5.0__py3-none-any.whl → 0.5.1__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/Face.py CHANGED
@@ -1391,7 +1391,7 @@ class Face(Topology):
1391
1391
  return returnResult
1392
1392
 
1393
1393
  @staticmethod
1394
- def NormalEdge(face: topologic.Face, length: float = 1.0) -> topologic.Edge:
1394
+ def NormalEdge(face: topologic.Face, length: float = 1.0, tolerance: float = 0.0001, silent: bool = False) -> topologic.Edge:
1395
1395
  """
1396
1396
  Returns the normal vector to the input face as an edge with the desired input length. A normal vector of a face is a vector perpendicular to it.
1397
1397
 
@@ -1401,6 +1401,8 @@ class Face(Topology):
1401
1401
  The input face.
1402
1402
  length : float , optional
1403
1403
  The desired length of the normal edge. The default is 1.
1404
+ tolerance : float , optional
1405
+ The desired tolerance. The default is 0.0001.
1404
1406
 
1405
1407
  Returns
1406
1408
  -------
@@ -1408,7 +1410,21 @@ class Face(Topology):
1408
1410
  The created normal edge to the input face. This is computed at the approximate center of the face.
1409
1411
 
1410
1412
  """
1411
- return Face.NormalEdgeAtParameters(face, u=0.5, v=0.5, length=length)
1413
+ from topologicpy.Edge import Edge
1414
+
1415
+ if not isinstance(face, topologic.Face):
1416
+ if not silent:
1417
+ print("Face.NormalEdge - Error: The input face parameter is not a valid face. Retuning None.")
1418
+ return None
1419
+ if length < tolerance:
1420
+ if not silent:
1421
+ print("Face.NormalEdge - Error: The input length parameter is less than the input tolerance. Retuning None.")
1422
+ return None
1423
+ iv = Face.InternalVertex(face)
1424
+ u, v = Face.VertexParameters(face, iv)
1425
+ vec = Face.NormalAtParameters(face, u=u, v=v)
1426
+ ev = Topology.TranslateByDirectionDistance(iv, vec, length)
1427
+ return Edge.ByVertices([iv, ev], tolerance=tolerance, silent=silent)
1412
1428
 
1413
1429
  @staticmethod
1414
1430
  def NormalEdgeAtParameters(face: topologic.Face, u: float = 0.5, v: float = 0.5, length: float = 1.0, tolerance: float = 0.0001) -> topologic.Edge:
topologicpy/Graph.py CHANGED
@@ -1604,8 +1604,8 @@ class Graph:
1604
1604
  keys = (Dictionary.Keys(mDict) or [])+["relationship"]
1605
1605
  values = (Dictionary.Values(mDict) or [])+["Direct"]
1606
1606
  else:
1607
- keys = []
1608
- values = []
1607
+ keys = ["relationship"]
1608
+ values = ["Direct"]
1609
1609
  mDict = Dictionary.ByKeysValues(keys, values)
1610
1610
  if mDict:
1611
1611
  e.SetDictionary(mDict)
@@ -2041,6 +2041,13 @@ class Graph:
2041
2041
  v2 = topFaces[j].CenterOfMass()
2042
2042
  e = Edge.ByStartVertexEndVertex(v1, v2, tolerance=tolerance)
2043
2043
  mDict = mergeDictionaries(sharedt)
2044
+ if not mDict == None:
2045
+ keys = (Dictionary.Keys(mDict) or [])+["relationship"]
2046
+ values = (Dictionary.Values(mDict) or [])+["Direct"]
2047
+ else:
2048
+ keys = ["relationship"]
2049
+ values = ["Direct"]
2050
+ mDict = Dictionary.ByKeysValues(keys, values)
2044
2051
  if mDict:
2045
2052
  e.SetDictionary(mDict)
2046
2053
  edges.append(e)
@@ -2472,6 +2479,13 @@ class Graph:
2472
2479
  v2 = topEdges[j].CenterOfMass()
2473
2480
  e = Edge.ByStartVertexEndVertex(v1, v2, tolerance=tolerance)
2474
2481
  mDict = mergeDictionaries(sharedt)
2482
+ if not mDict == None:
2483
+ keys = (Dictionary.Keys(mDict) or [])+["relationship"]
2484
+ values = (Dictionary.Values(mDict) or [])+["Direct"]
2485
+ else:
2486
+ keys = ["relationship"]
2487
+ values = ["Direct"]
2488
+ mDict = Dictionary.ByKeysValues(keys, values)
2475
2489
  if mDict:
2476
2490
  e.SetDictionary(mDict)
2477
2491
  edges.append(e)
@@ -4392,6 +4406,66 @@ class Graph:
4392
4406
  create_gexf_file(nodes, edges, defaultEdgeType, node_attributes, edge_attributes, path)
4393
4407
  return True
4394
4408
 
4409
+ @staticmethod
4410
+ def ExportToJSON(graph, path, vertexLabelKey="", edgeLabelKey="", indent=4, sortKeys=False, mantissa=6, overwrite=False):
4411
+ """
4412
+ Exports the input graph to a JSON file.
4413
+
4414
+ Parameters
4415
+ ----------
4416
+ graph : topologic.Graph
4417
+ The input graph.
4418
+ path : str
4419
+ The path to the JSON file.
4420
+ vertexLabelKey : str , optional
4421
+ If set to a valid string, the vertex label will be set to the value at this key. Otherwise it will be set to Vertex_XXXX where XXXX is a sequential unique number.
4422
+ Note: If vertex labels are not unique, they will be forced to be unique.
4423
+ edgeLabelKey : str , optional
4424
+ If set to a valid string, the edge label will be set to the value at this key. Otherwise it will be set to Edge_XXXX where XXXX is a sequential unique number.
4425
+ Note: If edge labels are not unique, they will be forced to be unique.
4426
+ indent : int , optional
4427
+ The desired amount of indent spaces to use. The default is 4.
4428
+ sortKeys : bool , optional
4429
+ If set to True, the keys will be sorted. Otherwise, they won't be. The default is False.
4430
+ mantissa : int , optional
4431
+ The desired length of the mantissa. The default is 6.
4432
+ overwrite : bool , optional
4433
+ If set to True the ouptut file will overwrite any pre-existing file. Otherwise, it won't. The default is False.
4434
+
4435
+ Returns
4436
+ -------
4437
+ bool
4438
+ The status of exporting the JSON file. If True, the operation was successful. Otherwise, it was unsuccesful.
4439
+
4440
+ """
4441
+ import json
4442
+ from os.path import exists
4443
+ # Make sure the file extension is .json
4444
+ ext = path[len(path)-5:len(path)]
4445
+ if ext.lower() != ".json":
4446
+ path = path+".json"
4447
+ if not overwrite and exists(path):
4448
+ print("Graph.ExportToJSON - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
4449
+ return None
4450
+ f = None
4451
+ try:
4452
+ if overwrite == True:
4453
+ f = open(path, "w")
4454
+ else:
4455
+ f = open(path, "x") # Try to create a new File
4456
+ except:
4457
+ raise Exception("Graph.ExportToJSON - Error: Could not create a new file at the following location: "+path)
4458
+ if (f):
4459
+ jsondata = Graph.JSONData(graph, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, mantissa=mantissa)
4460
+ if jsondata != None:
4461
+ json.dump(jsondata, f, indent=indent, sort_keys=sortKeys)
4462
+ f.close()
4463
+ return True
4464
+ else:
4465
+ f.close()
4466
+ return False
4467
+ return False
4468
+
4395
4469
  @staticmethod
4396
4470
  def Flatten(graph, layout="spring", k=0.8, seed=None, iterations=50, rootVertex=None, tolerance=0.0001):
4397
4471
  """
@@ -5036,6 +5110,122 @@ class Graph:
5036
5110
  _ = graph.IsolatedVertices(vertices)
5037
5111
  return vertices
5038
5112
 
5113
+ @staticmethod
5114
+ def JSONData(graph, vertexLabelKey="", edgeLabelKey="", mantissa=6):
5115
+ """
5116
+ Converts the input graph into JSON data.
5117
+
5118
+ Parameters
5119
+ ----------
5120
+ graph : topologic.Graph
5121
+ The input graph.
5122
+ vertexLabelKey : str , optional
5123
+ If set to a valid string, the vertex label will be set to the value at this key. Otherwise it will be set to Vertex_XXXX where XXXX is a sequential unique number.
5124
+ Note: If vertex labels are not unique, they will be forced to be unique.
5125
+ edgeLabelKey : str , optional
5126
+ If set to a valid string, the edge label will be set to the value at this key. Otherwise it will be set to Edge_XXXX where XXXX is a sequential unique number.
5127
+ Note: If edge labels are not unique, they will be forced to be unique.
5128
+ mantissa : int , optional
5129
+ The desired length of the mantissa. The default is 6.
5130
+
5131
+ Returns
5132
+ -------
5133
+ dict
5134
+ The JSON data
5135
+
5136
+ """
5137
+ from topologicpy.Vertex import Vertex
5138
+ from topologicpy.Edge import Edge
5139
+ from topologicpy.Topology import Topology
5140
+ from topologicpy.Dictionary import Dictionary
5141
+ from topologicpy.Helper import Helper
5142
+
5143
+ vertices = Graph.Vertices(graph)
5144
+ j_data = {}
5145
+ j_data['nodes'] = {}
5146
+ j_data['edges'] = {}
5147
+ n = len(str(len(vertices)))
5148
+ v_labels = []
5149
+ v_dicts = []
5150
+ for i, v in enumerate(vertices):
5151
+ d = Topology.Dictionary(v)
5152
+ d = Dictionary.SetValueAtKey(d, "x", Vertex.X(v, mantissa=mantissa))
5153
+ d = Dictionary.SetValueAtKey(d, "y", Vertex.Y(v, mantissa=mantissa))
5154
+ d = Dictionary.SetValueAtKey(d, "z", Vertex.Z(v, mantissa=mantissa))
5155
+ v_dict = Dictionary.PythonDictionary(d)
5156
+ v_label = Dictionary.ValueAtKey(d, vertexLabelKey)
5157
+ if isinstance(v_label, str):
5158
+ v_label = Dictionary.ValueAtKey(d, vertexLabelKey)
5159
+ else:
5160
+ v_label = "Vertex_"+str(i).zfill(n)
5161
+ v_labels.append(v_label)
5162
+ v_dicts.append(v_dict)
5163
+ v_labels = Helper.MakeUnique(v_labels)
5164
+ for i, v_label in enumerate(v_labels):
5165
+ j_data['nodes'][v_label] = v_dicts[i]
5166
+
5167
+ edges = Graph.Edges(graph)
5168
+ n = len(str(len(edges)))
5169
+ e_labels = []
5170
+ e_dicts = []
5171
+ for i, e in enumerate(edges):
5172
+ sv = Edge.StartVertex(e)
5173
+ ev = Edge.EndVertex(e)
5174
+ svi = Vertex.Index(sv, vertices)
5175
+ evi = Vertex.Index(ev, vertices)
5176
+ sv_label = v_labels[svi]
5177
+ ev_label = v_labels[evi]
5178
+ d = Topology.Dictionary(e)
5179
+
5180
+ d = Dictionary.SetValueAtKey(d, "source", sv_label)
5181
+ d = Dictionary.SetValueAtKey(d, "target", ev_label)
5182
+ e_dict = Dictionary.PythonDictionary(d)
5183
+ e_label = Dictionary.ValueAtKey(d, edgeLabelKey)
5184
+ if isinstance(e_label, str):
5185
+ e_label = Dictionary.ValueAtKey(d, edgeLabelKey)
5186
+ else:
5187
+ e_label = "Edge_"+str(i).zfill(n)
5188
+ e_labels.append(e_label)
5189
+ e_dicts.append(e_dict)
5190
+ e_labels = Helper.MakeUnique(e_labels)
5191
+ for i, e_label in enumerate(e_labels):
5192
+ j_data['edges'][e_label] = e_dicts[i]
5193
+
5194
+ return j_data
5195
+
5196
+ @staticmethod
5197
+ def JSONString(graph, vertexLabelKey="", edgeLabelKey="", indent=4, sortKeys=False, mantissa=6):
5198
+ """
5199
+ Converts the input graph into JSON data.
5200
+
5201
+ Parameters
5202
+ ----------
5203
+ graph : topologic.Graph
5204
+ The input graph.
5205
+ vertexLabelKey : str , optional
5206
+ If set to a valid string, the vertex label will be set to the value at this key. Otherwise it will be set to Vertex_XXXX where XXXX is a sequential unique number.
5207
+ Note: If vertex labels are not unique, they will be forced to be unique.
5208
+ edgeLabelKey : str , optional
5209
+ If set to a valid string, the edge label will be set to the value at this key. Otherwise it will be set to Edge_XXXX where XXXX is a sequential unique number.
5210
+ Note: If edge labels are not unique, they will be forced to be unique.
5211
+ indent : int , optional
5212
+ The desired amount of indent spaces to use. The default is 4.
5213
+ sortKeys : bool , optional
5214
+ If set to True, the keys will be sorted. Otherwise, they won't be. The default is False.
5215
+ mantissa : int , optional
5216
+ The desired length of the mantissa. The default is 6.
5217
+
5218
+ Returns
5219
+ -------
5220
+ str
5221
+ The JSON str
5222
+
5223
+ """
5224
+ import json
5225
+ json_data = Graph.JSONData(graph, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, mantissa=mantissa)
5226
+ json_string = json.dumps(json_data, indent=indent, sort_keys=sortKeys)
5227
+ return json_string
5228
+
5039
5229
  @staticmethod
5040
5230
  def LocalClusteringCoefficient(graph, vertices=None, mantissa=6):
5041
5231
  """
topologicpy/Helper.py CHANGED
@@ -232,7 +232,42 @@ class Helper:
232
232
  merged_list.append(listA[i])
233
233
 
234
234
  return merged_list
235
+
236
+ @staticmethod
237
+ def MakeUnique(listA):
238
+ """
239
+ Forces the strings in the input list to be unique if they have duplicates.
240
+
241
+ Parameters
242
+ ----------
243
+ listA : list
244
+ The input list of strings.
245
+
246
+ Returns
247
+ -------
248
+ list
249
+ The input list, but with each item ensured to be unique if they have duplicates.
235
250
 
251
+ """
252
+ # Create a dictionary to store counts of each string
253
+ counts = {}
254
+ # Create a list to store modified strings
255
+ unique_strings = []
256
+
257
+ for string in listA:
258
+ # If the string already exists in the counts dictionary
259
+ if string in counts:
260
+ # Increment the count
261
+ counts[string] += 1
262
+ # Append the modified string with underscore and count
263
+ unique_strings.append(f"{string}_{counts[string]}")
264
+ else:
265
+ # If it's the first occurrence of the string, add it to the counts dictionary
266
+ counts[string] = 0
267
+ unique_strings.append(string)
268
+
269
+ return unique_strings
270
+
236
271
  @staticmethod
237
272
  def Normalize(listA, mantissa: int = 6):
238
273
  """
topologicpy/Vertex.py CHANGED
@@ -1513,6 +1513,8 @@ class Vertex(Topology):
1513
1513
  if not isinstance(face, topologic.Face):
1514
1514
  return None
1515
1515
  eq = Face.PlaneEquation(face, mantissa= mantissa)
1516
+ if direction == None:
1517
+ direction = Face.Normal(face)
1516
1518
  pt = project_point_onto_plane(Vertex.Coordinates(vertex), [eq["a"], eq["b"], eq["c"], eq["d"]], direction)
1517
1519
  return Vertex.ByCoordinates(pt[0], pt[1], pt[2])
1518
1520
 
topologicpy/__init__.py CHANGED
@@ -18,7 +18,7 @@ import sys
18
18
  import os, re
19
19
  from sys import platform
20
20
 
21
- __version__ = '0.5.0'
21
+ __version__ = '0.5.1'
22
22
  __version_info__ = tuple([ int(num) for num in __version__.split('.')])
23
23
 
24
24
  if platform == 'win32':
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
5
  Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/wassimj/TopologicPy
@@ -8,10 +8,10 @@ topologicpy/DGL.py,sha256=-FDDTANjQb4fBtLHI433_KPmmGlTEPE7boYybXkoPuI,138321
8
8
  topologicpy/Dictionary.py,sha256=vGhiXPu7e7GsgQyTsX6rZBncnnrDlcYfM9xRb9h-l3U,24799
9
9
  topologicpy/Edge.py,sha256=C4VKk8leXTQySsGKCE4RSt3HiUhA12Ny_rGhEr71LWY,50009
10
10
  topologicpy/EnergyModel.py,sha256=VPWkMP2uhJORiVqEomb2Dlx5VgKcVUbqnZBZX1IpF_Y,51771
11
- topologicpy/Face.py,sha256=PlrXxQMPpH_ZGSTxZCYQk1JgR5UGi87k-Plz0LmyAec,81747
12
- topologicpy/Graph.py,sha256=D3JQVPeC1afjsf0yNliUqfJv2UEjYFPi-5HZx0k6Efk,320339
11
+ topologicpy/Face.py,sha256=81sURmH5TjbvSUzzSTGWPwb4jjqle4vplPeEo4Cwuvk,82576
12
+ topologicpy/Graph.py,sha256=IVJnb3JxKs_RwXwjqv2MTFhz7HVw04oqAK52JQYZizY,329199
13
13
  topologicpy/Grid.py,sha256=q6uAs8MGbdteYNbjqRjqlhFMquYAvSngwzxsFl9-338,17371
14
- topologicpy/Helper.py,sha256=MEndR1LzSxLnjyjoQBA1ByQyshGXM1BjqhmcZhOXilA,16064
14
+ topologicpy/Helper.py,sha256=VkOCa3-z31uQj1ZTuufOtg4Ly5WZYHJ6bCmJndDpEGc,17242
15
15
  topologicpy/Honeybee.py,sha256=p5OZi8tGPxUNH91_8peChEkYJdg5vpRyeqHVz8S9OS0,20356
16
16
  topologicpy/Matrix.py,sha256=1aH7QKP6eNUbUXmZbB7e_4dw1ZSVQ8bsOsKJXtQq3_4,8357
17
17
  topologicpy/Neo4j.py,sha256=4B_lYgZIDztqINkHL_J6gsfkZQ043wEsZpD_9uPYOMU,19356
@@ -21,9 +21,9 @@ topologicpy/Shell.py,sha256=ebXCT8pDq3lbWWHZ2yWASAU4mpINoYNT4C3gW1NuAeo,76292
21
21
  topologicpy/Speckle.py,sha256=zKqiHYuw7498W_9UWvDn2xsdBskhahNjJejxegMpbJA,14773
22
22
  topologicpy/Topology.py,sha256=7zmDexNyS9v4hQLPj7YWbrcYgKBk9DCsqzM1BHhgcJE,305269
23
23
  topologicpy/Vector.py,sha256=EZ4vJbZfxcUVtKkmiUJnOM_II2Z4l6_zEWTJyfNEtiY,30362
24
- topologicpy/Vertex.py,sha256=RVcmTK8G4UHxW4OF0w-1nCyCzzp5eI9lEUEnfu9Vwrc,66375
24
+ topologicpy/Vertex.py,sha256=bzjLi-4XSg2Jg9hO9iH4g1CpF-_CHzjAd3kdDYi78ao,66449
25
25
  topologicpy/Wire.py,sha256=RUeD_bDfUpc5iLZtUMuK-e6lXpvSRHBHuEzxJUBrbaY,131490
26
- topologicpy/__init__.py,sha256=yEDkogZubOWdlQtzadmVyxfer3nqiJLkfvaUQahUVu8,1444
26
+ topologicpy/__init__.py,sha256=f8czF2FmoUshgIKYVdvf00lAuKQIcvYQRhuwHVmNJFU,1444
27
27
  topologicpy/bin/linux/topologic/__init__.py,sha256=XlFReDf3FWlYdM9uXtanYPIafgPb6GVTQczS_xJAXD0,60
28
28
  topologicpy/bin/linux/topologic/libTKBO-6bdf205d.so.7.7.0,sha256=ANok9DQKcnWcLd9T_LAt-i-X4nsYYy16q9kQlcTre1E,2996488
29
29
  topologicpy/bin/linux/topologic/libTKBRep-2960a069.so.7.7.0,sha256=OJ3XesL79du8LeBHrsleGPXub6OpJdOilxha0mwjqQo,1378768
@@ -84,8 +84,8 @@ topologicpy/bin/windows/topologic/topologic.cp310-win_amd64.pyd,sha256=F0sPLuMpD
84
84
  topologicpy/bin/windows/topologic/topologic.cp311-win_amd64.pyd,sha256=aBAJQj3OmJ58MOAF1ZIFybL_5fFK7FNR9hrIps6b6pc,1551872
85
85
  topologicpy/bin/windows/topologic/topologic.cp38-win_amd64.pyd,sha256=aLgNf54nbJmGc7Tdmkuy-V0m6B9zLxabIbpRwAy7cBA,1551360
86
86
  topologicpy/bin/windows/topologic/topologic.cp39-win_amd64.pyd,sha256=_8cp205hiRxkFHtzQQOweA4DhCPk8caH4kTVLWGQeVw,1411584
87
- topologicpy-0.5.0.dist-info/LICENSE,sha256=RUmXeeqj63bBySLJjEfhwb9OE7M8h9K6HuOBF3ASVyI,35697
88
- topologicpy-0.5.0.dist-info/METADATA,sha256=2nFTApTy5IsKdEAASDRuQgwGE_BLZwWJ5dwuLKIVsoM,7277
89
- topologicpy-0.5.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
90
- topologicpy-0.5.0.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
91
- topologicpy-0.5.0.dist-info/RECORD,,
87
+ topologicpy-0.5.1.dist-info/LICENSE,sha256=RUmXeeqj63bBySLJjEfhwb9OE7M8h9K6HuOBF3ASVyI,35697
88
+ topologicpy-0.5.1.dist-info/METADATA,sha256=khzpXTId9tt4uLByqWsgneDO-DdCeyb38qlm2Yv0JMk,7277
89
+ topologicpy-0.5.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
90
+ topologicpy-0.5.1.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
91
+ topologicpy-0.5.1.dist-info/RECORD,,