topologicpy 0.7.8__py3-none-any.whl → 0.7.10__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/Edge.py CHANGED
@@ -221,7 +221,7 @@ class Edge():
221
221
  """
222
222
  from topologicpy.Vertex import Vertex
223
223
  from topologicpy.Topology import Topology
224
-
224
+
225
225
  edge = None
226
226
  if not Topology.IsInstance(vertexA, "Vertex"):
227
227
  if not silent:
@@ -297,7 +297,11 @@ class Edge():
297
297
  if not silent:
298
298
  print("Edge.ByVertices - Error: The input vertices parameter has less than two vertices. Returning None.")
299
299
  return None
300
- return Edge.ByStartVertexEndVertex(vertexList[0], vertexList[-1], tolerance=tolerance, silent=silent)
300
+ edge = Edge.ByStartVertexEndVertex(vertexList[0], vertexList[-1], tolerance=tolerance, silent=silent)
301
+ if not edge:
302
+ if not silent:
303
+ print("Edge.ByVertices - Error: Could not create an edge. Returning None.")
304
+ return edge
301
305
 
302
306
  @staticmethod
303
307
  def ByVerticesCluster(cluster, tolerance: float = 0.0001):
topologicpy/Face.py CHANGED
@@ -1254,7 +1254,7 @@ class Face():
1254
1254
  return Vector.IsCollinear(dirA, dirB)
1255
1255
 
1256
1256
  @staticmethod
1257
- def Isovist(face, vertex, obstacles = None, fromAngle=0, toAngle=360, tolerance: float = 0.0001):
1257
+ def Isovist(face, vertex, obstacles: list = [], direction: list = [0,1,0], fov: float = 360, mantissa: int = 6, tolerance: float = 0.0001):
1258
1258
  """
1259
1259
  Returns the face representing the isovist projection from the input viewpoint.
1260
1260
  This method assumes all input is in 2D. Z coordinates are ignored.
@@ -1267,14 +1267,17 @@ class Face():
1267
1267
  The vertex representing the location of the viewpoint of the isovist.
1268
1268
  obstacles : list , optional
1269
1269
  A list of wires representing the obstacles within the face. All obstacles are assumed to be within the
1270
- boundary of the face.
1271
- fromAngle : float , optional
1272
- The angle in degrees from which to start creating the arc of the circle. The default is 0.
1273
- 0 is considered to be in the positive X-axis direction. 90 is considered to be in the
1274
- positive Y-axis direction.
1275
- toAngle : float , optional
1276
- The angle in degrees at which to end creating the arc of the circle. The default is 360.
1277
- Angles are measured in an anti-clockwise fashion.
1270
+ boundary of the face. The default is [].
1271
+ direction : list, optional
1272
+ The vector representing the direction (in the XY plane) in which the observer is facing. The Z component is ignored.
1273
+ The direction follows the Vector.CompassAngle convention where [0,1,0] (North) is considered to be
1274
+ in the positive Y direction, [1,0,0] (East) is considered to be in the positive X-direction.
1275
+ Angles are measured in a clockwise fashion. The default is [0,1,0] (North).
1276
+ fov : float , optional
1277
+ The horizontal field of view (fov) angle in degrees. See https://en.wikipedia.org/wiki/Field_of_view.
1278
+ The acceptable range is 1 to 360. The default is 360.
1279
+ mantissa : int , optional
1280
+ The desired length of the mantissa. The default is 6.
1278
1281
  tolerance : float , optional:
1279
1282
  The desired tolerance. The default is 0.0001.
1280
1283
 
@@ -1282,7 +1285,7 @@ class Face():
1282
1285
  -------
1283
1286
  topologic_core.Face
1284
1287
  The face representing the isovist projection from the input viewpoint.
1285
-
1288
+
1286
1289
  """
1287
1290
  from topologicpy.Vertex import Vertex
1288
1291
  from topologicpy.Edge import Edge
@@ -1291,7 +1294,8 @@ class Face():
1291
1294
  from topologicpy.Shell import Shell
1292
1295
  from topologicpy.Cluster import Cluster
1293
1296
  from topologicpy.Topology import Topology
1294
-
1297
+ from topologicpy.Vector import Vector
1298
+
1295
1299
  def vertexPartofFace(vertex, face, tolerance):
1296
1300
  vertices = []
1297
1301
  _ = face.Vertices(None, vertices)
@@ -1299,15 +1303,20 @@ class Face():
1299
1303
  if Vertex.Distance(vertex, v) < tolerance:
1300
1304
  return True
1301
1305
  return False
1302
-
1306
+
1303
1307
  if not Topology.IsInstance(face, "Face"):
1304
1308
  print("Face.Isovist - Error: The input boundary parameter is not a valid Face. Returning None")
1305
1309
  return None
1306
1310
  if not Topology.IsInstance(vertex, "Vertex"):
1307
1311
  print("Face.Isovist - Error: The input viewPoint parameter is not a valid Vertex. Returning None")
1308
1312
  return None
1313
+ if fov < 1 or fov > 360:
1314
+ print("Face.Isovist - Error: The input fov parameter is outside the acceptable range of 0 to 360 degrees. Returning None")
1315
+ return None
1309
1316
  if isinstance(obstacles, list):
1310
1317
  obstacles = [obs for obs in obstacles if Topology.IsInstance(obs, "Wire")]
1318
+ else:
1319
+ obstacles = []
1311
1320
  for obs in obstacles:
1312
1321
  face = Topology.Difference(face, Face.ByWire(obs))
1313
1322
  targets = Topology.Vertices(face)
@@ -1319,8 +1328,8 @@ class Face():
1319
1328
  edges = []
1320
1329
  for target in targets:
1321
1330
  if Vertex.Distance(vertex, target) > tolerance:
1322
- e = Edge.ByVertices(vertex, target)
1323
- e = Edge.SetLength(e, length=max_d, bothSides=False)
1331
+ e = Edge.ByVertices(vertex, target, silent=True)
1332
+ e = Edge.SetLength(e, length=max_d, bothSides=False, tolerance=tolerance)
1324
1333
  edges.append(e)
1325
1334
  shell = Topology.Slice(face, Cluster.ByTopologies(edges))
1326
1335
  faces = Topology.Faces(shell)
@@ -1330,13 +1339,25 @@ class Face():
1330
1339
  final_faces.append(face)
1331
1340
  shell = Shell.ByFaces(final_faces)
1332
1341
  return_face = Topology.RemoveCoplanarFaces(shell)
1333
- if abs(360 - toAngle - fromAngle) > tolerance:
1342
+ compAngle = 0
1343
+ if fov == 360:
1344
+ c = Wire.Circle(origin= vertex, radius=max_d, sides=180, close = True)
1345
+ pie = Face.ByWire(c)
1346
+ else:
1347
+ compAngle = Vector.CompassAngle(Vector.North(), direction, mantissa=mantissa, tolerance=tolerance) - 90
1348
+ fromAngle = -fov*0.5 - compAngle
1349
+ toAngle = fov*0.5 - compAngle
1334
1350
  c = Wire.Circle(origin= vertex, radius=max_d, sides=180, fromAngle=fromAngle, toAngle=toAngle, close = False)
1335
- e1 = Edge.ByVertices(Wire.StartVertex(c), vertex)
1336
- e2 = Edge.ByVertices(Wire.EndVertex(c), vertex)
1351
+ e1 = Edge.ByVertices(Wire.StartVertex(c), vertex, silent=True)
1352
+ e2 = Edge.ByVertices(Wire.EndVertex(c), vertex, silent=True)
1337
1353
  edges = Topology.Edges(c) + [e1,e2]
1338
1354
  pie = Face.ByWire(Topology.SelfMerge(Cluster.ByTopologies(edges)))
1339
- return_face = Topology.Intersect(pie, return_face)
1355
+ return_face = Topology.Intersect(pie, return_face)
1356
+ if not Topology.IsInstance(return_face, "face"):
1357
+ return_face = Topology.SelfMerge(return_face)
1358
+ if return_face == None:
1359
+ print("Face.Isovist - Error: Could not create isovist. Returning None.")
1360
+ return None
1340
1361
  return return_face
1341
1362
 
1342
1363
  @staticmethod
topologicpy/Graph.py CHANGED
@@ -20,6 +20,9 @@ import time
20
20
  import os
21
21
  import warnings
22
22
 
23
+ from collections import namedtuple
24
+ from multiprocessing import Process, Queue
25
+
23
26
  try:
24
27
  import numpy as np
25
28
  except:
@@ -62,6 +65,133 @@ except:
62
65
  except:
63
66
  warnings.warn("Graph - Error: Could not import tqdm.")
64
67
 
68
+
69
+ GraphQueueItem = namedtuple('GraphQueueItem', ['edges'])
70
+
71
+ class WorkerProcessPool(object):
72
+ """
73
+ Create and manage a list of Worker processes. Each worker process
74
+ creates a 2D navigation graph.
75
+ """
76
+ def __init__(self,
77
+ num_workers,
78
+ message_queue,
79
+ used,
80
+ face,
81
+ sources,
82
+ destinations,
83
+ tolerance=0.0001):
84
+ self.num_workers = num_workers
85
+ self.message_queue = message_queue
86
+ self.used = used
87
+ self.face = face
88
+ self.sources = sources
89
+ self.destinations = destinations
90
+ self.tolerance = tolerance
91
+ self.process_list = []
92
+
93
+ def startProcesses(self):
94
+ num_item_per_worker = len(self.sources) // self.num_workers
95
+ for i in range(self.num_workers):
96
+ if i == self.num_workers - 1:
97
+ begin = i * num_item_per_worker
98
+ sub_sources = self.sources[begin:]
99
+ else:
100
+ begin = i * num_item_per_worker
101
+ end = begin + num_item_per_worker
102
+ sub_sources = self.sources[begin : end]
103
+ wp = WorkerProcess(begin,
104
+ self.message_queue,
105
+ self.used,
106
+ self.face,
107
+ sub_sources,
108
+ self.destinations,
109
+ self.tolerance)
110
+ wp.start()
111
+ self.process_list.append(wp)
112
+
113
+ def stopProcesses(self):
114
+ for p in self.process_list:
115
+ p.join()
116
+ self.process_list = []
117
+
118
+ def join(self):
119
+ for p in self.process_list:
120
+ p.join()
121
+
122
+
123
+ class WorkerProcess(Process):
124
+ """
125
+ Creates a 2D navigation graph from a subset of sources and the list of destinations.
126
+ """
127
+ def __init__(self,
128
+ start_index,
129
+ message_queue,
130
+ used,
131
+ face,
132
+ sources,
133
+ destinations,
134
+ tolerance=0.0001):
135
+ Process.__init__(self, target=self.run)
136
+ self.start_index = start_index
137
+ self.message_queue = message_queue
138
+ self.used = used
139
+ self.face = face
140
+ self.sources = sources
141
+ self.destinations = destinations
142
+ self.tolerance = tolerance
143
+
144
+ def run(self):
145
+ from topologicpy.Topology import Topology
146
+ from topologicpy.Vertex import Vertex
147
+ from topologicpy.Edge import Edge
148
+
149
+ edges = []
150
+ face = Topology.ByBREPString(self.face)
151
+ sources = [Topology.ByBREPString(s) for s in self.sources]
152
+ destinations = [Topology.ByBREPString(s) for s in self.destinations]
153
+ for i in range(len(sources)):
154
+ source = sources[i]
155
+ index_b = Vertex.Index(source, destinations)
156
+ for j in range(len(destinations)):
157
+ destination = destinations[j]
158
+ index_a = Vertex.Index(destination, sources)
159
+ if self.used[i + self.start_index][j] == 1 or self.used[j][i + self.start_index]:
160
+ continue
161
+ if Vertex.Distance(source, destination) > self.tolerance:
162
+ edge = Edge.ByVertices([source, destination])
163
+ e = Topology.Boolean(edge, face, operation="intersect")
164
+ if Topology.IsInstance(e, "Edge"):
165
+ edges.append(edge)
166
+ self.used[i + self.start_index][j] = 1
167
+ if not index_a == None and not index_b == None:
168
+ self.used[j][i + self.start_index] = 1
169
+ if len(edges) > 0:
170
+ edges_str = [Topology.BREPString(s) for s in edges]
171
+ self.message_queue.put(GraphQueueItem(edges_str))
172
+
173
+
174
+ class MergingProcess(Process):
175
+ """
176
+ Receive message from other processes and merging the result
177
+ """
178
+ def __init__(self, message_queue):
179
+ Process.__init__(self, target=self.wait_message)
180
+ self.message_queue = message_queue
181
+ self.final_edges = []
182
+
183
+ def wait_message(self):
184
+ while True:
185
+ try:
186
+ item = self.message_queue.get()
187
+ if item is None:
188
+ self.message_queue.put(GraphQueueItem(self.final_edges))
189
+ break
190
+ self.final_edges.extend(item.edges)
191
+ except Exception as e:
192
+ print(str(e))
193
+
194
+
65
195
  class _Tree:
66
196
  def __init__(self, node="", *children):
67
197
  self.node = node
@@ -6724,7 +6854,7 @@ class Graph:
6724
6854
  return mst
6725
6855
 
6726
6856
  @staticmethod
6727
- def NavigationGraph(face, sources=None, destinations=None, tolerance=0.0001, progressBar=True):
6857
+ def NavigationGraph(face, sources=None, destinations=None, tolerance=0.0001, numWorkers=None):
6728
6858
  """
6729
6859
  Creates a 2D navigation graph.
6730
6860
 
@@ -6738,8 +6868,8 @@ class Graph:
6738
6868
  The input list of destinations (vertices). Navigation edges will connect these vertices to sources.
6739
6869
  tolerance : float , optional
6740
6870
  The desired tolerance. The default is 0.0001.
6741
- tqdm : bool , optional
6742
- If set to True, a tqdm progress bar is shown. Otherwise, it is not. The default is True.
6871
+ numWorkers : int, optional
6872
+ Number of workers run in parallel to process. The default is None which sets the number to twice the number of CPU cores.
6743
6873
 
6744
6874
  Returns
6745
6875
  -------
@@ -6747,15 +6877,15 @@ class Graph:
6747
6877
  The navigation graph.
6748
6878
 
6749
6879
  """
6750
- from topologicpy.Vertex import Vertex
6751
- from topologicpy.Edge import Edge
6880
+
6881
+ from topologicpy.Topology import Topology
6752
6882
  from topologicpy.Wire import Wire
6753
6883
  from topologicpy.Face import Face
6754
- from topologicpy.Graph import Graph
6755
6884
  from topologicpy.Cluster import Cluster
6756
- from topologicpy.Topology import Topology
6757
- import topologic_core as topologic
6758
- from tqdm.auto import tqdm
6885
+
6886
+ if not numWorkers:
6887
+ import multiprocessing
6888
+ numWorkers = multiprocessing.cpu_count()*2
6759
6889
 
6760
6890
  if not Topology.IsInstance(face, "Face"):
6761
6891
  print("Graph.NavigationGraph - Error: The input face parameter is not a valid face. Returning None")
@@ -6776,8 +6906,6 @@ class Graph:
6776
6906
  print("Graph.NavigationGraph - Error: The input sources parameter does not contain any vertices. Returning None")
6777
6907
  return None
6778
6908
  destinations = [v for v in destinations if Topology.IsInstance(v, "Vertex")]
6779
- #if len(destinations) < 1: #Nothing to navigate to, so return a graph made of sources
6780
- #return Graph.ByVerticesEdges(sources, [])
6781
6909
 
6782
6910
  # Add obstuse angles of external boundary to viewpoints
6783
6911
  e_boundary = Face.ExternalBoundary(face)
@@ -6804,27 +6932,28 @@ class Graph:
6804
6932
  temp_row.append(0)
6805
6933
  used.append(temp_row)
6806
6934
 
6807
- final_edges = []
6808
- if progressBar:
6809
- the_range = tqdm(range(len(sources)))
6810
- else:
6811
- the_range = range(len(sources))
6812
- for i in the_range:
6813
- source = sources[i]
6814
- index_b = Vertex.Index(source, destinations)
6815
- for j in range(len(destinations)):
6816
- destination = destinations[j]
6817
- index_a = Vertex.Index(destination, sources)
6818
- if used[i][j] == 1 or used[j][i]:
6819
- continue
6820
- if Vertex.Distance(source, destination) > tolerance:
6821
- edge = Edge.ByVertices([source,destination])
6822
- e = Topology.Boolean(edge, face, operation="intersect")
6823
- if Topology.IsInstance(e, "Edge"):
6824
- final_edges.append(edge)
6825
- used[i][j] = 1
6826
- if not index_a == None and not index_b == None:
6827
- used[j][i] = 1
6935
+ queue = Queue()
6936
+ mergingProcess = MergingProcess(queue)
6937
+ mergingProcess.start()
6938
+
6939
+ sources_str = [Topology.BREPString(s) for s in sources]
6940
+ destinations_str = [Topology.BREPString(s) for s in destinations]
6941
+ face_str = Topology.BREPString(face)
6942
+ workerProcessPool = WorkerProcessPool(numWorkers,
6943
+ queue,
6944
+ used,
6945
+ face_str,
6946
+ sources_str,
6947
+ destinations_str,
6948
+ tolerance)
6949
+ workerProcessPool.startProcesses()
6950
+ workerProcessPool.join()
6951
+
6952
+ queue.put_nowait(None)
6953
+ it = queue.get()
6954
+ final_edges = [Topology.ByBREPString(edge_str) for edge_str in it.edges]
6955
+ mergingProcess.join()
6956
+
6828
6957
  if len(i_boundaries) > 0:
6829
6958
  holes_edges = Topology.Edges(Cluster.ByTopologies(i_boundaries))
6830
6959
  final_edges += holes_edges
topologicpy/Topology.py CHANGED
@@ -6718,7 +6718,7 @@ class Topology():
6718
6718
  tolerance : float , optional
6719
6719
  The desired tolerance. The default is 0.0001.
6720
6720
  numWorkers : int, optional
6721
- Number of workers run in parallel to process.
6721
+ Number of workers run in parallel to process. The default is None which sets the number to twice the number of CPU cores.
6722
6722
 
6723
6723
  Returns
6724
6724
  -------
topologicpy/Wire.py CHANGED
@@ -2203,7 +2203,8 @@ class Wire(Topology):
2203
2203
  sv = vertices[Vertex.Index(sv, vertices)]
2204
2204
  ev = Edge.EndVertex(edge)
2205
2205
  ev = vertices[Vertex.Index(ev, vertices)]
2206
- new_edges.append(Edge.ByVertices([sv,ev]))
2206
+ if Vertex.Distance(sv, ev) > tolerance:
2207
+ new_edges.append(Edge.ByVertices([sv,ev]))
2207
2208
  new_wire = Topology.SelfMerge(Cluster.ByTopologies(new_edges), tolerance=tolerance)
2208
2209
  return new_wire
2209
2210
 
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.8'
1
+ __version__ = '0.7.10'
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Wassim Jabi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.1
2
+ Name: topologicpy
3
+ Version: 0.7.10
4
+ Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
+ Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Wassim Jabi
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/wassimj/TopologicPy
29
+ Project-URL: Bug Tracker, https://github.com/wassimj/TopologicPy/issues
30
+ Project-URL: Documentation, https://topologic.app/topologicpy_doc/
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
33
+ Classifier: Operating System :: OS Independent
34
+ Requires-Python: <3.14,>=3.8
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: numpy >=1.18.0
38
+ Requires-Dist: scipy >=1.4.1
39
+ Requires-Dist: pandas
40
+ Requires-Dist: tqdm
41
+ Requires-Dist: plotly
42
+ Requires-Dist: lark
43
+ Requires-Dist: topologic-core >=7.0.1
44
+ Provides-Extra: test
45
+ Requires-Dist: pytest-xdist >=2.4.0 ; extra == 'test'
46
+
47
+ # topologicpy
48
+
49
+ <img src="https://topologic.app/wp-content/uploads/2023/02/topologicpy-logo-no-loop.gif" alt="topologicpy logo" width="250" loop="1">
50
+
51
+ # An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction
52
+
53
+ ## Introduction
54
+ Welcome to topologicpy (rhymes with apple pie). topologicpy is an open-source python 3 implementation of [Topologic](https://topologic.app) which is a powerful spatial modelling and analysis software library that revolutionizes the way you design architectural spaces, buildings, and artefacts. Topologic's advanced features enable you to create hierarchical and topological information-rich 3D representations that offer unprecedented flexibility and control in your design process. With the integration of geometry, topology, information, and artificial intelligence, Topologic enriches Building Information Models with Building *Intelligence* Models.
55
+
56
+ Two of Topologic's main strengths are its support for *defeaturing* and *encoded meshing*. By simplifying the geometry of a model and removing small or unnecessary details not needed for analysis, defeaturing allows for faster and more accurate analysis while maintaining topological consistency. This feature enables you to transform low-quality, heavy BIM models into high-quality, lightweight representations ready for rigorous analysis effortlessly. Encoded meshing allows you to use the same base elements available in your commercial BIM platform to cleanly build 3D information-encoded models that match your exacting specifications.
57
+
58
+ Topologic's versatility extends to entities with mixed dimensionalities, enabling structural models, for example, to be represented coherently. Lines can represent columns and beams, surfaces can represent walls and slabs, and volumes can represent solids. Even non-building entities like structural loads can be efficiently attached to the structure. This approach creates mixed-dimensional models that are highly compatible with structural analysis simulation software.
59
+
60
+ Topologic's graph-based representation makes it a natural fit for integrating with Graph Machine Learning (GML), an exciting new branch of artificial intelligence. With GML, you can process vast amounts of connected data and extract valuable insights quickly and accurately. Topologic's intelligent algorithms for graph and node classification take GML to the next level by using the extracted data to classify building typologies, predict associations, and complete missing information in building information models. This integration empowers you to leverage the historical knowledge embedded in your databases and make informed decisions about your current design projects. With Topologic and GML, you can streamline your workflow, enhance your productivity, and achieve your project goals with greater efficiency and precision.
61
+
62
+ Experience Topologic's comprehensive and well-documented Application Protocol Interface (API) and enjoy the freedom and flexibility that Topologic offers in your architectural design process. Topologic uses cutting-edge C++-based non-manifold topology (NMT) core technology ([Open CASCADE](https://www.opencascade.com/)), and python bindings. Interacting with Topologic is easily accomplished through a command-Line interface and scripts, visual data flow programming (VDFP) plugins for popular BIM software, and cloud-based interfaces through [Streamlit](https://streamlit.io/). You can easily interact with Topologic in various ways to perform design and analysis tasks or even seamlessly customize and embed it in your own in-house software and workflows. Plus, Topologic includes several industry-standard methods for data transport including IFC, OBJ, BREP, HBJSON, CSV, as well serializing through cloud-based services such as [Speckle](https://speckle.systems/).
63
+
64
+ Topologic’s open-source philosophy and licensing ([AGPLv3](https://www.gnu.org/licenses/agpl-3.0.en.html)) enables you to achieve your design vision with minimal incremental costs, ensuring a high return on investment. You control and own your information outright, and nothing is ever trapped in an expensive subscription model. Topologic empowers you to build and share data apps with ease, giving you the flexibility to choose between local or cloud-based options and the peace of mind to focus on what matters most.
65
+
66
+ Join the revolution in architectural design with Topologic. Try it today and see the difference for yourself.
67
+
68
+ ## Installation
69
+ topologicpy can be installed using the **pip** command as such:
70
+
71
+ `pip install topologicpy --upgrade`
72
+
73
+ ## Prerequisites
74
+
75
+ topologicpy depends on the following python libraries which will be installed automatically from pip:
76
+
77
+ <details>
78
+ <summary>
79
+ <b>Expand to view dependencies</b>
80
+ </summary>
81
+ * [numpy](http://numpy.org) >= 1.24.0
82
+ * [scipy](http://scipy.org) >= 1.10.0
83
+ * [plotly](http://plotly.com/) >= 5.11.0
84
+ * [ifcopenshell](http://ifcopenshell.org/) >=0.7.9
85
+ * [ipfshttpclient](https://pypi.org/project/ipfshttpclient/) >= 0.7.0
86
+ * [web3](https://web3py.readthedocs.io/en/stable/) >=5.30.0
87
+ * [openstudio](https://openstudio.net/) >= 3.4.0
88
+ * [topologic_core](https://pypi.org/project/topologic_core/) >= 6.0.6
89
+ * [lbt-ladybug](https://pypi.org/project/lbt-ladybug/) >= 0.25.161
90
+ * [lbt-honeybee](https://pypi.org/project/lbt-honeybee/) >= 0.6.12
91
+ * [honeybee-energy](https://pypi.org/project/honeybee-energy/) >= 1.91.49
92
+ * [json](https://docs.python.org/3/library/json.html) >= 2.0.9
93
+ * [py2neo](https://py2neo.org/) >= 2021.2.3
94
+ * [pyvisgraph](https://github.com/TaipanRex/pyvisgraph) >= 0.2.1
95
+ * [specklepy](https://github.com/specklesystems/specklepy) >= 2.7.6
96
+ * [pandas](https://pandas.pydata.org/) >= 1.4.2
97
+ * [scipy](https://scipy.org/) >= 1.8.1
98
+ * [dgl](https://github.com/dmlc/dgl) >= 0.8.2
99
+
100
+ </details>
101
+
102
+ ## How to start using Topologic
103
+ 1. Open your favourite python editor ([jupyter notebook](https://jupyter.org/) is highly recommended)
104
+ 1. Type 'import topologicpy'
105
+ 1. Start using the API
106
+
107
+ ## API Documentation
108
+ API documentation can be found at [https://topologic.app/topologicpy_doc/](https://topologic.app/topologicpy_doc/)
109
+
110
+ topologicpy: &copy; 2023 Wassim Jabi
111
+
112
+ Topologic: &copy; 2023 Cardiff University and UCL
@@ -6,10 +6,10 @@ topologicpy/Color.py,sha256=UlmRcCSOhqcM_OyMWz4t3Kr75KcgXDhz3uctAJ2n7Ic,18031
6
6
  topologicpy/Context.py,sha256=ppApYKngZZCQBFWaxIMi2z2dokY23c935IDCBosxDAE,3055
7
7
  topologicpy/DGL.py,sha256=RpkLnAzjg6arY7cEMs2pDFYzRdkerVg1Wbm9hcE3QaM,138991
8
8
  topologicpy/Dictionary.py,sha256=pMbfE2RYGCNpVr2x58qiHRc-aBWnp1jLlyzwS9nz6-w,25891
9
- topologicpy/Edge.py,sha256=KCQm9QfwjsYO4yKE4p4elpha9c4MY6EWAEaK_6mTAjo,52239
9
+ topologicpy/Edge.py,sha256=EiOgg2HtuR-YtL5cpFcLcL1Y3A2Y-m4qPNtLjHGRZBQ,52407
10
10
  topologicpy/EnergyModel.py,sha256=ni0H1JgvLl1-q90yK9Sm1qj5P1fTuidlimEIcwuj6qE,53287
11
- topologicpy/Face.py,sha256=uPVVFF6CLzEW2JaTllQJp7nBsS2w3wAz7qwfujWTQAk,97474
12
- topologicpy/Graph.py,sha256=51VViKQaYIuaMOoU3SQtzi7LJ6yisloY7wU-Ypj1gJo,380319
11
+ topologicpy/Face.py,sha256=XqBi_wrR8qhxE8UdT-GhIoRnmaxo64E9Etm9iELjX5A,98729
12
+ topologicpy/Graph.py,sha256=IFEGU0MCE4_fPe2j8sx1vuXPKMjGaov5wTlgRAwB7ns,384631
13
13
  topologicpy/Grid.py,sha256=2uDFDxg4NqROC-7bNi1BjK5Uz__BPH13afJ-VDBRW0M,18466
14
14
  topologicpy/Helper.py,sha256=07V9IFu5ilMpvAdZVhIbdBOjBJSRTtJ0BfR1IoRaRXU,17743
15
15
  topologicpy/Honeybee.py,sha256=dlr5OEH93q51ZmEgvi8PXGfCHBDAjIZ1cm38Rft1Bz4,20235
@@ -20,14 +20,14 @@ topologicpy/Polyskel.py,sha256=MYHKFOQBlUNqoUhAdOcKRIHpSk0dWWVrZgXK34NkvFM,15936
20
20
  topologicpy/Shell.py,sha256=uPf5Ch8wQ-pbKvXMY_DV9tPXyz4BPmofFVYdIzbWFh4,76960
21
21
  topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
22
22
  topologicpy/Sun.py,sha256=3tYb8kssU882lE1gEWg2mxDvCCY_LAVElkyUT6wa-ZU,36935
23
- topologicpy/Topology.py,sha256=SymcisEpNIuqpKiBoz7zJrLtS_28R5GDbG-SiwJOirY,308743
23
+ topologicpy/Topology.py,sha256=sXvhiMShOjOp0aILjEU6uNDqKm3zEAEdrN_IJgDK47c,308819
24
24
  topologicpy/Vector.py,sha256=2OXmty9CKZZzfsg5T4ckml-lPUUvgDvqokcKDsZVN9Y,29806
25
25
  topologicpy/Vertex.py,sha256=WjQZf-r8h_Cjwkt_qNN483FCUql20fbv72Ymiq7ZYtw,67462
26
- topologicpy/Wire.py,sha256=efqePp91BvAdj4JitSW_f-xeGoTFg_AxP5g5pmbBVFw,139047
26
+ topologicpy/Wire.py,sha256=TTGVySZAbo0cY_Ykoqyv6FiQHBBHzRGOKITjRNkdzSg,139107
27
27
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
28
- topologicpy/version.py,sha256=a7wkX95rB7MKSi7_39xJlxtx2D_-UcZRwY8dnpzjx6w,22
29
- topologicpy-0.7.8.dist-info/LICENSE,sha256=TfPDBt3ar0uv_f9cqCDMZ5rIzW3CY8anRRd4PkL6ejs,34522
30
- topologicpy-0.7.8.dist-info/METADATA,sha256=5ElQumbM_dp9q0pHrGBTf585bMtBm5yQ8Is1dCFKnuE,46950
31
- topologicpy-0.7.8.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
- topologicpy-0.7.8.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
- topologicpy-0.7.8.dist-info/RECORD,,
28
+ topologicpy/version.py,sha256=yDniQ0XMYyXTl9AyH9Sr2sBx5o3HhQZmldHel-_qTEc,23
29
+ topologicpy-0.7.10.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
30
+ topologicpy-0.7.10.dist-info/METADATA,sha256=VxeJ8w5ZkcWATvgpOBWfYR3qdsZGmU0EAeYavY7JjUI,8405
31
+ topologicpy-0.7.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
32
+ topologicpy-0.7.10.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
33
+ topologicpy-0.7.10.dist-info/RECORD,,