topologicpy 0.8.59__py3-none-any.whl → 0.8.61__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 CHANGED
@@ -226,7 +226,7 @@ class Cell():
226
226
  return new_cell
227
227
 
228
228
  @staticmethod
229
- def ByShell(shell, planarize: bool = False, tolerance: float = 0.0001):
229
+ def ByShell(shell, planarize: bool = False, tolerance: float = 0.0001, silent: bool = False):
230
230
  """
231
231
  Creates a cell from the input shell.
232
232
 
@@ -238,6 +238,8 @@ class Cell():
238
238
  If set to True, the input faces of the input shell are planarized before building the cell. Otherwise, they are not. Default is False.
239
239
  tolerance : float , optional
240
240
  The desired tolerance. Default is 0.0001.
241
+ silent : bool , optional
242
+ If set to True, error and warning messages are suppressed. Default is False.
241
243
 
242
244
  Returns
243
245
  -------
@@ -248,7 +250,8 @@ class Cell():
248
250
  from topologicpy.Topology import Topology
249
251
 
250
252
  if not Topology.IsInstance(shell, "Shell"):
251
- print("Cell.ByShell - Error: The input shell parameter is not a valid topologic shell. Returning None.")
253
+ if not silent:
254
+ print("Cell.ByShell - Error: The input shell parameter is not a valid topologic shell. Returning None.")
252
255
  return None
253
256
  faces = Topology.SubTopologies(shell, subTopologyType="face")
254
257
  return Cell.ByFaces(faces, planarize=planarize, tolerance=tolerance)
topologicpy/Graph.py CHANGED
@@ -64,20 +64,6 @@ except:
64
64
  print("Graph - tqdm library installed correctly.")
65
65
  except:
66
66
  warnings.warn("Graph - Error: Could not import tqdm.")
67
-
68
- try:
69
- from graphviz import Digraph
70
- except:
71
- print("Graph - Installing required graphviz library.")
72
- try:
73
- os.system("pip install graphviz")
74
- except:
75
- os.system("pip install graphviz --user")
76
- try:
77
- from graphviz import Digraph
78
- print("Graph - graphviz library installed correctly.")
79
- except:
80
- warnings.warn("Graph - Error: Could not import graphviz.")
81
67
 
82
68
  GraphQueueItem = namedtuple('GraphQueueItem', ['edges'])
83
69
 
@@ -4060,6 +4046,380 @@ class Graph:
4060
4046
  removeCoplanarFaces=removeCoplanarFaces,
4061
4047
  xMin=xMin, yMin=yMin, zMin=zMin, xMax=xMax, yMax=yMax, zMax=zMax)
4062
4048
 
4049
+ @staticmethod
4050
+ def ByJSONDictionary(
4051
+ jsonDictionary: dict,
4052
+ xKey: str = "x",
4053
+ yKey: str = "y",
4054
+ zKey: str = "z",
4055
+ vertexIDKey: str = None,
4056
+ edgeSourceKey: str = "source",
4057
+ edgeTargetKey: str = "target",
4058
+ edgeIDKey: str = None,
4059
+ graphPropsKey: str = "properties",
4060
+ verticesKey: str = "vertices",
4061
+ edgesKey: str = "edges",
4062
+ mantissa: int = 6,
4063
+ tolerance: float = 0.0001,
4064
+ silent: bool = False,
4065
+ ):
4066
+ """
4067
+ Loads a Graph from a JSON file and attaches graph-, vertex-, and edge-level dictionaries.
4068
+
4069
+ Parameters
4070
+ ----------
4071
+ path : str
4072
+ Path to a JSON file containing:
4073
+ - graph-level properties under `graphPropsKey` (default "properties"),
4074
+ - a vertex dict under `verticesKey` (default "vertices") keyed by vertex IDs,
4075
+ - an edge dict under `edgesKey` (default "edges") keyed by edge IDs.
4076
+ xKey: str , optional
4077
+ JSON key used to read vertex's x coordinate. Default is "x".
4078
+ yKey: str , optional
4079
+ JSON key used to read vertex's y coordinate. Default is "y".
4080
+ zKey: str , optional
4081
+ JSON key used to read vertex's z coordinate. Default is "z".
4082
+ vertexIDKey : str , optional
4083
+ If not None, the vertex dictionary key under which to store the JSON vertex id. Default is "id".
4084
+ edgeSourceKey: str , optional
4085
+ JSON key used to read edge's start vertex. Default is "source".
4086
+ edgeTargetKey: str , optional
4087
+ JSON key used to read edge's end vertex. Default is "target".
4088
+ edgeIDKey : str , optional
4089
+ If not None, the edge dictionary key under which to store the JSON edge id. Default is "id".
4090
+ graphPropsKey: str , optional
4091
+ JSON key for the graph properties section. Default is "properties".
4092
+ verticesKey: str , optional
4093
+ JSON key for the vertices section. Default is "vertices".
4094
+ edgesKey: str , optional
4095
+ JSON key for the edges section. Default is "edges".
4096
+ mantissa : int , optional
4097
+ The desired length of the mantissa. Default is 6.
4098
+ tolerance : float , optional
4099
+ The desired tolerance. Default is 0.0001.
4100
+ silent : bool , optional
4101
+ If set to True, no warnings or error messages are displayed. Default is False.
4102
+
4103
+ Returns
4104
+ -------
4105
+ topologic_core.Graph
4106
+ """
4107
+ # --- Imports kept local by request ---
4108
+ import json
4109
+ import math
4110
+ from typing import Any, Iterable
4111
+
4112
+ # TopologicPy imports
4113
+ from topologicpy.Graph import Graph
4114
+ from topologicpy.Vertex import Vertex
4115
+ from topologicpy.Edge import Edge
4116
+ from topologicpy.Topology import Topology
4117
+ from topologicpy.Dictionary import Dictionary
4118
+
4119
+ # --- Helper functions kept local by request ---
4120
+ def _to_plain(value: Any) -> Any:
4121
+ "Convert numpy/pandas-ish scalars/arrays and nested containers to plain Python."
4122
+ try:
4123
+ import numpy as _np # optional
4124
+ if isinstance(value, _np.generic):
4125
+ return value.item()
4126
+ if isinstance(value, _np.ndarray):
4127
+ return [_to_plain(v) for v in value.tolist()]
4128
+ except Exception:
4129
+ pass
4130
+ if isinstance(value, (list, tuple)):
4131
+ return [_to_plain(v) for v in value]
4132
+ if isinstance(value, dict):
4133
+ return {str(k): _to_plain(v) for k, v in value.items()}
4134
+ if isinstance(value, float):
4135
+ if not math.isfinite(value):
4136
+ return 0.0
4137
+ # normalize -0.0
4138
+ return 0.0 if abs(value) < tolerance else float(value)
4139
+ return value
4140
+
4141
+ def _round_num(x: Any, m: int) -> float:
4142
+ "Safe float conversion + rounding + tolerance clamp."
4143
+ try:
4144
+ xf = float(x)
4145
+ except Exception:
4146
+ return 0.0
4147
+ if not math.isfinite(xf):
4148
+ return 0.0
4149
+ # clamp tiny values to zero to avoid -0.0 drift and floating trash
4150
+ if abs(xf) < tolerance:
4151
+ xf = 0.0
4152
+ return round(xf, max(0, int(m)))
4153
+
4154
+ def _dict_from(obj: dict, drop_keys: Iterable[str] = ()):
4155
+ "Create a Topologic Dictionary from a Python dict (optionally dropping some keys)."
4156
+ data = {k: _to_plain(v) for k, v in obj.items() if k not in drop_keys}
4157
+ if not data:
4158
+ return None
4159
+ keys = list(map(str, data.keys()))
4160
+ vals = list(data.values())
4161
+ try:
4162
+ return Dictionary.ByKeysValues(keys, vals)
4163
+ except Exception:
4164
+ # As a last resort, stringify nested types
4165
+ import json as _json
4166
+ vals2 = [_json.dumps(v) if isinstance(v, (list, dict)) else v for v in vals]
4167
+ return Dictionary.ByKeysValues(keys, vals2)
4168
+
4169
+ # --- Load JSON ---
4170
+ if not isinstance(jsonDictionary, dict):
4171
+ if not silent:
4172
+ print(f"Graph.ByJSONDictionary - Error: The input JSON Dictionary parameter is not a valid python dictionary. Returning None.")
4173
+ return None
4174
+
4175
+ gprops = jsonDictionary.get(graphPropsKey, {}) or {}
4176
+ verts = jsonDictionary.get(verticesKey, {}) or {}
4177
+ edges = jsonDictionary.get(edgesKey, {}) or {}
4178
+
4179
+ # --- Build vertices ---
4180
+ id_to_vertex = {}
4181
+ vertex_list = []
4182
+ for v_id, v_rec in verts.items():
4183
+ x = _round_num(v_rec.get(xKey, 0.0), mantissa)
4184
+ y = _round_num(v_rec.get(yKey, 0.0), mantissa)
4185
+ z = _round_num(v_rec.get(zKey, 0.0), mantissa)
4186
+ try:
4187
+ v = Vertex.ByCoordinates(x, y, z)
4188
+ except Exception as e:
4189
+ if not silent:
4190
+ print(f"Graph.ByJSONDictionary - Warning: failed to create Vertex {v_id} at ({x},{y},{z}): {e}")
4191
+ continue
4192
+
4193
+ # Attach vertex dictionary with all attributes except raw coords
4194
+ v_dict_py = dict(v_rec)
4195
+ if vertexIDKey:
4196
+ v_dict_py[vertexIDKey] = v_id
4197
+ v_dict = _dict_from(v_dict_py, drop_keys={xKey, yKey, zKey})
4198
+ if v_dict:
4199
+ v = Topology.SetDictionary(v, v_dict)
4200
+
4201
+ id_to_vertex[str(v_id)] = v
4202
+ vertex_list.append(v)
4203
+
4204
+ # --- Build edges ---
4205
+ edge_list = []
4206
+ for e_id, e_rec in edges.items():
4207
+ s_id = e_rec.get(edgeSourceKey)
4208
+ t_id = e_rec.get(edgeTargetKey)
4209
+ if s_id is None or t_id is None:
4210
+ if not silent:
4211
+ print(f"Graph.ByJSONDictionary - Warning: skipping Edge {e_id}: missing '{edgeSourceKey}' or '{edgeTargetKey}'.")
4212
+ continue
4213
+ s_id = str(s_id)
4214
+ t_id = str(t_id)
4215
+ if s_id not in id_to_vertex or t_id not in id_to_vertex:
4216
+ if not silent:
4217
+ print(f"Graph.ByJSONDictionary - Warning: skipping Edge {e_id}: unknown endpoint(s) {s_id}->{t_id}.")
4218
+ continue
4219
+ u = id_to_vertex[s_id]
4220
+ v = id_to_vertex[t_id]
4221
+ try:
4222
+ e = Edge.ByVertices(u, v)
4223
+ except Exception as ee:
4224
+ if not silent:
4225
+ print(f"Graph.ByJSONDictionary - Warning: failed to create Edge {e_id}: {ee}")
4226
+ continue
4227
+
4228
+ # Attach full edge record as dictionary (including source/target keys)
4229
+ e_dict = _dict_from(dict(e_rec), drop_keys=())
4230
+ if edgeIDKey:
4231
+ Dictionary.SetValueAtKey(e_dict, edgeIDKey, e_id)
4232
+ if e_dict:
4233
+ e = Topology.SetDictionary(e, e_dict)
4234
+ edge_list.append(e)
4235
+
4236
+ # --- Assemble graph ---
4237
+ try:
4238
+ g = Graph.ByVerticesEdges(vertex_list, edge_list)
4239
+ except Exception:
4240
+ # Fallback: create empty, then add
4241
+ g = Graph.ByVerticesEdges([], [])
4242
+ for v in vertex_list:
4243
+ try:
4244
+ g = Graph.AddVertex(g, v)
4245
+ except Exception:
4246
+ pass
4247
+ for e in edge_list:
4248
+ try:
4249
+ g = Graph.AddEdge(g, e)
4250
+ except Exception:
4251
+ pass
4252
+
4253
+ # --- Graph-level dictionary ---
4254
+ g_dict = _dict_from(dict(gprops), drop_keys=())
4255
+ if g_dict:
4256
+ g = Topology.SetDictionary(g, g_dict)
4257
+
4258
+ return g
4259
+
4260
+ @staticmethod
4261
+ def ByJSONFile(file,
4262
+ xKey: str = "x",
4263
+ yKey: str = "y",
4264
+ zKey: str = "z",
4265
+ vertexIDKey: str = "id",
4266
+ edgeSourceKey: str = "source",
4267
+ edgeTargetKey: str = "target",
4268
+ edgeIDKey: str = "id",
4269
+ graphPropsKey: str = "properties",
4270
+ verticesKey: str = "vertices",
4271
+ edgesKey: str = "edges",
4272
+ mantissa: int = 6,
4273
+ tolerance: float = 0.0001,
4274
+ silent: bool = False):
4275
+ """
4276
+ Imports the graph from a JSON file.
4277
+
4278
+ Parameters
4279
+ ----------
4280
+ file : file object
4281
+ The input JSON file.
4282
+ xKey: str , optional
4283
+ JSON key used to read vertex's x coordinate. Default is "x".
4284
+ yKey: str , optional
4285
+ JSON key used to read vertex's y coordinate. Default is "y".
4286
+ zKey: str , optional
4287
+ JSON key used to read vertex's z coordinate. Default is "z".
4288
+ vertexIDKey : str , optional
4289
+ If not None, the vertex dictionary key under which to store the JSON vertex id. Default is "id".
4290
+ edgeSourceKey: str , optional
4291
+ JSON key used to read edge's start vertex. Default is "source".
4292
+ edgeTargetKey: str , optional
4293
+ JSON key used to read edge's end vertex. Default is "target".
4294
+ edgeIDKey : str , optional
4295
+ If not None, the edge dictionary key under which to store the JSON edge id. Default is "id".
4296
+ graphPropsKey: str , optional
4297
+ JSON key for the graph properties section. Default is "properties".
4298
+ verticesKey: str , optional
4299
+ JSON key for the vertices section. Default is "vertices".
4300
+ edgesKey: str , optional
4301
+ JSON key for the edges section. Default is "edges".
4302
+ mantissa : int , optional
4303
+ The desired length of the mantissa. Default is 6.
4304
+ tolerance : float , optional
4305
+ The desired tolerance. Default is 0.0001.
4306
+ silent : bool , optional
4307
+ If set to True, no warnings or error messages are displayed. Default is False.
4308
+
4309
+ Returns
4310
+ -------
4311
+ topologic_graph
4312
+ the imported graph.
4313
+
4314
+ """
4315
+ import json
4316
+ if not file:
4317
+ if not silent:
4318
+ print("Topology.ByJSONFile - Error: the input file parameter is not a valid file. Returning None.")
4319
+ return None
4320
+ try:
4321
+ json_dict = json.load(file)
4322
+ except Exception as e:
4323
+ if not silent:
4324
+ print("Graph.ByJSONFile - Error: Could not load the JSON file: {e}. Returning None.")
4325
+ return None
4326
+ return Graph.ByJSONDictionary(json_dict,
4327
+ xKey=xKey,
4328
+ yKey=yKey,
4329
+ zKey=zKey,
4330
+ vertexIDKey=vertexIDKey,
4331
+ edgeSourceKey=edgeSourceKey,
4332
+ edgeTargetKey=edgeTargetKey,
4333
+ edgeIDKey=edgeIDKey,
4334
+ graphPropsKey=graphPropsKey,
4335
+ verticesKey=verticesKey,
4336
+ edgesKey=edgesKey,
4337
+ mantissa=mantissa,
4338
+ tolerance=tolerance,
4339
+ silent=silent)
4340
+
4341
+ @staticmethod
4342
+ def ByJSONPath(path,
4343
+ xKey: str = "x",
4344
+ yKey: str = "y",
4345
+ zKey: str = "z",
4346
+ vertexIDKey: str = "id",
4347
+ edgeSourceKey: str = "source",
4348
+ edgeTargetKey: str = "target",
4349
+ edgeIDKey: str = "id",
4350
+ graphPropsKey: str = "properties",
4351
+ verticesKey: str = "vertices",
4352
+ edgesKey: str = "edges",
4353
+ mantissa: int = 6,
4354
+ tolerance: float = 0.0001,
4355
+ silent: bool = False):
4356
+ """
4357
+ Imports the graph from a JSON file.
4358
+
4359
+ Parameters
4360
+ ----------
4361
+ path : str
4362
+ The file path to the json file.
4363
+ xKey: str , optional
4364
+ JSON key used to read vertex's x coordinate. Default is "x".
4365
+ yKey: str , optional
4366
+ JSON key used to read vertex's y coordinate. Default is "y".
4367
+ zKey: str , optional
4368
+ JSON key used to read vertex's z coordinate. Default is "z".
4369
+ vertexIDKey : str , optional
4370
+ If not None, the vertex dictionary key under which to store the JSON vertex id. Default is "id".
4371
+ edgeSourceKey: str , optional
4372
+ JSON key used to read edge's start vertex. Default is "source".
4373
+ edgeTargetKey: str , optional
4374
+ JSON key used to read edge's end vertex. Default is "target".
4375
+ edgeIDKey : str , optional
4376
+ If not None, the edge dictionary key under which to store the JSON edge id. Default is "id".
4377
+ graphPropsKey: str , optional
4378
+ JSON key for the graph properties section. Default is "properties".
4379
+ verticesKey: str , optional
4380
+ JSON key for the vertices section. Default is "vertices".
4381
+ edgesKey: str , optional
4382
+ JSON key for the edges section. Default is "edges".
4383
+ mantissa : int , optional
4384
+ The desired length of the mantissa. Default is 6.
4385
+ tolerance : float , optional
4386
+ The desired tolerance. Default is 0.0001.
4387
+ silent : bool , optional
4388
+ If set to True, no warnings or error messages are displayed. Default is False.
4389
+
4390
+ Returns
4391
+ -------
4392
+ list
4393
+ The list of imported topologies.
4394
+
4395
+ """
4396
+ import json
4397
+ if not path:
4398
+ if not silent:
4399
+ print("Graph.ByJSONPath - Error: the input path parameter is not a valid path. Returning None.")
4400
+ return None
4401
+ try:
4402
+ with open(path) as file:
4403
+ json_dict = json.load(file)
4404
+ except Exception as e:
4405
+ if not silent:
4406
+ print(f"Graph.ByJSONPath - Error: Could not load file: {e}. Returning None.")
4407
+ return None
4408
+ return Graph.ByJSONDictionary(json_dict,
4409
+ xKey=xKey,
4410
+ yKey=yKey,
4411
+ zKey=zKey,
4412
+ vertexIDKey=vertexIDKey,
4413
+ edgeSourceKey=edgeSourceKey,
4414
+ edgeTargetKey=edgeTargetKey,
4415
+ edgeIDKey=edgeIDKey,
4416
+ graphPropsKey=graphPropsKey,
4417
+ verticesKey=verticesKey,
4418
+ edgesKey=edgesKey,
4419
+ mantissa=mantissa,
4420
+ tolerance=tolerance,
4421
+ silent=silent)
4422
+
4063
4423
  @staticmethod
4064
4424
  def ByMeshData(vertices, edges, vertexDictionaries=None, edgeDictionaries=None, tolerance=0.0001):
4065
4425
  """
@@ -4119,7 +4479,7 @@ class Graph:
4119
4479
  return Graph.ByVerticesEdges(g_vertices, g_edges)
4120
4480
 
4121
4481
  @staticmethod
4122
- def ByNetworkXGraph(nxGraph, xKey="x", yKey="y", zKey="z", range=(-1, 1), mantissa: int = 6, tolerance: float = 0.0001):
4482
+ def ByNetworkXGraph(nxGraph, xKey="x", yKey="y", zKey="z", coordsKey='coords', randomRange=(-1, 1), mantissa: int = 6, tolerance: float = 0.0001):
4123
4483
  """
4124
4484
  Converts the input NetworkX graph into a topologic Graph. See http://networkx.org
4125
4485
 
@@ -4133,8 +4493,10 @@ class Graph:
4133
4493
  The dictionary key under which to find the Y-Coordinate of the vertex. Default is 'y'.
4134
4494
  zKey : str , optional
4135
4495
  The dictionary key under which to find the Z-Coordinate of the vertex. Default is 'z'.
4136
- range : tuple , optional
4137
- The range to use for position coordinates if no values are found in the dictionaries. Default is (-1,1)
4496
+ coordsKey : str , optional
4497
+ The dictionary key under which to find the list of the coordinates vertex. Default is 'coords'.
4498
+ randomRange : tuple , optional
4499
+ The range to use for random position coordinates if no values are found in the dictionaries. Default is (-1,1)
4138
4500
  mantissa : int , optional
4139
4501
  The number of decimal places to round the result to. Default is 6.
4140
4502
  tolerance : float , optional
@@ -4153,38 +4515,221 @@ class Graph:
4153
4515
 
4154
4516
  import random
4155
4517
  import numpy as np
4518
+ import math
4519
+ import torch
4520
+ from collections.abc import Mapping, Sequence
4521
+
4522
+ def _is_iterable_but_not_str(x):
4523
+ return isinstance(x, Sequence) and not isinstance(x, (str, bytes, bytearray))
4524
+
4525
+ def _to_python_scalar(x):
4526
+ """Return a plain Python scalar if x is a numpy/pandas/Decimal/torch scalar; otherwise return x."""
4527
+ # numpy scalar
4528
+ if np is not None and isinstance(x, np.generic):
4529
+ return x.item()
4530
+ # pandas NA
4531
+ if pd is not None and x is pd.NA:
4532
+ return None
4533
+ # pandas Timestamp/Timedelta
4534
+ if pd is not None and isinstance(x, (pd.Timestamp, pd.Timedelta)):
4535
+ return x.isoformat()
4536
+ # torch scalar tensor
4537
+ if torch is not None and isinstance(x, torch.Tensor) and x.dim() == 0:
4538
+ return _to_python_scalar(x.item())
4539
+ # decimal
4540
+ try:
4541
+ from decimal import Decimal
4542
+ if isinstance(x, Decimal):
4543
+ return float(x)
4544
+ except Exception:
4545
+ pass
4546
+ return x
4547
+
4548
+ def _to_python_list(x):
4549
+ """Convert arrays/series/tensors/sets/tuples to Python lists (recursively)."""
4550
+ if torch is not None and isinstance(x, torch.Tensor):
4551
+ x = x.detach().cpu().tolist()
4552
+ elif np is not None and isinstance(x, (np.ndarray,)):
4553
+ x = x.tolist()
4554
+ elif pd is not None and isinstance(x, (pd.Series, pd.Index)):
4555
+ x = x.tolist()
4556
+ elif isinstance(x, (set, tuple)):
4557
+ x = list(x)
4558
+ return x
4559
+
4560
+ def _round_number(x, mantissa):
4561
+ """Round finite floats; keep ints; sanitize NaNs/Infs to None."""
4562
+ if isinstance(x, bool): # bool is int subclass; keep as bool
4563
+ return x
4564
+ if isinstance(x, int):
4565
+ return x
4566
+ # try float conversion
4567
+ try:
4568
+ xf = float(x)
4569
+ except Exception:
4570
+ return x # not a number
4571
+ if math.isfinite(xf):
4572
+ return round(xf, mantissa)
4573
+ return None # NaN/Inf -> None
4574
+
4575
+ def clean_value(value, mantissa):
4576
+ """
4577
+ Recursively convert value into TopologicPy-friendly types:
4578
+ - numbers rounded to mantissa
4579
+ - sequences -> lists (cleaned)
4580
+ - mappings -> dicts (cleaned)
4581
+ - datetime -> isoformat
4582
+ - other objects -> str(value)
4583
+ """
4584
+ # First, normalize common library wrappers
4585
+ value = _to_python_scalar(value)
4586
+
4587
+ # Datetime from stdlib
4588
+ import datetime
4589
+ if isinstance(value, (datetime.datetime, datetime.date, datetime.time)):
4590
+ try:
4591
+ return value.isoformat()
4592
+ except Exception:
4593
+ return str(value)
4594
+
4595
+ # Mapping (dict-like)
4596
+ if isinstance(value, Mapping):
4597
+ return {str(k): clean_value(v, mantissa) for k, v in value.items()}
4598
+
4599
+ # Sequences / arrays / tensors -> list
4600
+ if _is_iterable_but_not_str(value) or (
4601
+ (np is not None and isinstance(value, (np.ndarray,))) or
4602
+ (torch is not None and isinstance(value, torch.Tensor)) or
4603
+ (pd is not None and isinstance(value, (pd.Series, pd.Index)))
4604
+ ):
4605
+ value = _to_python_list(value)
4606
+ return [clean_value(v, mantissa) for v in value]
4607
+
4608
+ # Strings stay as-is
4609
+ if isinstance(value, (str, bytes, bytearray)):
4610
+ return value.decode() if isinstance(value, (bytes, bytearray)) else value
4611
+
4612
+ # Numbers (or things that can be safely treated as numbers)
4613
+ out = _round_number(value, mantissa)
4614
+ # If rounder didn't change type and it's still a weird object, stringify it
4615
+ if out is value and not isinstance(out, (type(None), bool, int, float, str)):
4616
+ return str(out)
4617
+ return out
4618
+
4619
+ def coerce_xyz(val, mantissa, default=0.0):
4620
+ """
4621
+ Coerce a candidate XYZ value into a float:
4622
+ - if mapping with 'x' or 'value' -> try those
4623
+ - if sequence -> use first element
4624
+ - if string -> try float
4625
+ - arrays/tensors -> first element
4626
+ - fallback to default
4627
+ """
4628
+ if val is None:
4629
+ return round(float(default), mantissa)
4630
+ # library scalars
4631
+ val = _to_python_scalar(val)
4632
+
4633
+ # Mapping with common keys
4634
+ if isinstance(val, Mapping):
4635
+ for k in ("x", "value", "val", "coord", "0"):
4636
+ if k in val:
4637
+ return coerce_xyz(val[k], mantissa, default)
4638
+ # otherwise try to take first value
4639
+ try:
4640
+ first = next(iter(val.values()))
4641
+ return coerce_xyz(first, mantissa, default)
4642
+ except Exception:
4643
+ return round(float(default), mantissa)
4644
+
4645
+ # Sequence / array / tensor
4646
+ if _is_iterable_but_not_str(val) or \
4647
+ (np is not None and isinstance(val, (np.ndarray,))) or \
4648
+ (torch is not None and isinstance(val, torch.Tensor)) or \
4649
+ (pd is not None and isinstance(val, (pd.Series, pd.Index))):
4650
+ lst = _to_python_list(val)
4651
+ if len(lst) == 0:
4652
+ return round(float(default), mantissa)
4653
+ return coerce_xyz(lst[0], mantissa, default)
4654
+
4655
+ # String
4656
+ if isinstance(val, str):
4657
+ try:
4658
+ return round(float(val), mantissa)
4659
+ except Exception:
4660
+ return round(float(default), mantissa)
4661
+
4662
+ # Numeric
4663
+ try:
4664
+ return _round_number(val, mantissa)
4665
+ except Exception:
4666
+ return round(float(default), mantissa)
4156
4667
 
4157
- # Create a mapping from NetworkX nodes to TopologicPy vertices
4158
- nx_to_topologic_vertex = {}
4668
+ # Create a mapping from NetworkX nodes to TopologicPy vertices
4669
+ nx_to_topologic_vertex = {}
4159
4670
 
4160
4671
  # Create TopologicPy vertices for each node in the NetworkX graph
4161
4672
  vertices = []
4162
4673
  for node, data in nxGraph.nodes(data=True):
4163
- # Attempt to get X, Y, Z from the node data
4164
- x = round(data.get(xKey, random.uniform(*range)), mantissa)
4165
- y = round(data.get(yKey, random.uniform(*range)), mantissa)
4166
- z = round(data.get(zKey, 0), mantissa) # If there are no Z values, this is probably a flat graph.
4167
- # Create a TopologicPy vertex with the node data dictionary
4168
- vertex = Vertex.ByCoordinates(x,y,z)
4674
+ # Clean the node dictionary
4169
4675
  cleaned_values = []
4170
- for value in data.values():
4171
- if isinstance(value, np.ndarray):
4172
- value = list(value)
4173
- cleaned_values.append(value)
4174
-
4175
- node_dict = Dictionary.ByKeysValues(list(data.keys()), cleaned_values)
4676
+ cleaned_keys = []
4677
+ for k, v in data.items():
4678
+ cleaned_keys.append(str(k))
4679
+ cleaned_values.append(clean_value(v, mantissa))
4680
+ data = dict(zip(cleaned_keys, cleaned_values))
4681
+ # Defensive defaults for coordinates
4682
+ x_raw = y_raw = z_raw = None
4683
+ try:
4684
+ x_raw = data.get(xKey, None)
4685
+ y_raw = data.get(yKey, None)
4686
+ z_raw = data.get(zKey, None)
4687
+ except Exception:
4688
+ x_raw = y_raw = z_raw = None
4689
+
4690
+ if x_raw == None:
4691
+ coords = data.get(coordsKey, None)
4692
+ if coords:
4693
+ coords = clean_value(coords, mantissa)
4694
+ if isinstance(coords, list):
4695
+ if len(coords) == 2:
4696
+ x_raw = coords[0]
4697
+ y_raw = coords[1]
4698
+ z_raw = 0
4699
+ elif len(coords) == 3:
4700
+ x_raw = coords[0]
4701
+ y_raw = coords[1]
4702
+ z_raw = coords[2]
4703
+
4704
+ # Fall back to random only if missing / invalid
4705
+ x = coerce_xyz(x_raw, mantissa, default=random.uniform(*randomRange))
4706
+ y = coerce_xyz(y_raw, mantissa, default=random.uniform(*randomRange))
4707
+ z = coerce_xyz(z_raw, mantissa, default=0.0)
4708
+
4709
+ # Create vertex
4710
+ vertex = Vertex.ByCoordinates(x, y, z)
4711
+
4712
+ # Build and attach TopologicPy dictionary
4713
+ node_dict = Dictionary.ByKeysValues(cleaned_keys, cleaned_values)
4176
4714
  vertex = Topology.SetDictionary(vertex, node_dict)
4177
- nx_to_topologic_vertex[node] = vertex
4715
+
4716
+ #nx_to_topologic_vertex[node] = vertex
4178
4717
  vertices.append(vertex)
4179
4718
 
4180
4719
  # Create TopologicPy edges for each edge in the NetworkX graph
4181
4720
  edges = []
4182
4721
  for u, v, data in nxGraph.edges(data=True):
4183
- start_vertex = nx_to_topologic_vertex[u]
4184
- end_vertex = nx_to_topologic_vertex[v]
4722
+ start_vertex = vertices[u]
4723
+ end_vertex = vertices[v]
4185
4724
 
4186
4725
  # Create a TopologicPy edge with the edge data dictionary
4187
- edge_dict = Dictionary.ByKeysValues(list(data.keys()), list(data.values()))
4726
+ # Clean the node dictionary
4727
+ cleaned_values = []
4728
+ cleaned_keys = []
4729
+ for k, v in data.items():
4730
+ cleaned_keys.append(str(k))
4731
+ cleaned_values.append(clean_value(v, mantissa))
4732
+ edge_dict = Dictionary.ByKeysValues(cleaned_keys, cleaned_values)
4188
4733
  edge = Edge.ByVertices([start_vertex, end_vertex], tolerance=tolerance)
4189
4734
  edge = Topology.SetDictionary(edge, edge_dict)
4190
4735
  edges.append(edge)
@@ -8015,13 +8560,13 @@ class Graph:
8015
8560
  1 for validate, and 2 for test. If no key is found, the ratio of train/validate/test will be used. Default is "mask".
8016
8561
  nodeTrainRatio : float , optional
8017
8562
  The desired ratio of the node data to use for training. The number must be between 0 and 1. Default is 0.8 which means 80% of the data will be used for training.
8018
- This value is ignored if an nodeMaskKey is foud.
8563
+ This value is ignored if an nodeMaskKey is found.
8019
8564
  nodeValidateRatio : float , optional
8020
8565
  The desired ratio of the node data to use for validation. The number must be between 0 and 1. Default is 0.1 which means 10% of the data will be used for validation.
8021
- This value is ignored if an nodeMaskKey is foud.
8566
+ This value is ignored if an nodeMaskKey is found.
8022
8567
  nodeTestRatio : float , optional
8023
8568
  The desired ratio of the node data to use for testing. The number must be between 0 and 1. Default is 0.1 which means 10% of the data will be used for testing.
8024
- This value is ignored if an nodeMaskKey is foud.
8569
+ This value is ignored if an nodeMaskKey is found.
8025
8570
  mantissa : int , optional
8026
8571
  The number of decimal places to round the result to. Default is 6.
8027
8572
  tolerance : float , optional
@@ -8888,7 +9433,7 @@ class Graph:
8888
9433
  return False
8889
9434
 
8890
9435
  @staticmethod
8891
- def ExportToJSON(graph, path, verticesKey="vertices", edgesKey="edges", vertexLabelKey="", edgeLabelKey="", xKey="x", yKey="y", zKey="z", indent=4, sortKeys=False, mantissa=6, overwrite=False):
9436
+ def ExportToJSON(graph, path, propertiesKey="properties", verticesKey="vertices", edgesKey="edges", vertexLabelKey="", edgeLabelKey="", xKey="x", yKey="y", zKey="z", indent=4, sortKeys=False, mantissa=6, overwrite=False):
8892
9437
  """
8893
9438
  Exports the input graph to a JSON file.
8894
9439
 
@@ -8898,6 +9443,8 @@ class Graph:
8898
9443
  The input graph.
8899
9444
  path : str
8900
9445
  The path to the JSON file.
9446
+ propertiesKey : str , optional
9447
+ The desired key name to call graph properties. Default is "properties".
8901
9448
  verticesKey : str , optional
8902
9449
  The desired key name to call vertices. Default is "vertices".
8903
9450
  edgesKey : str , optional
@@ -8947,7 +9494,7 @@ class Graph:
8947
9494
  except:
8948
9495
  raise Exception("Graph.ExportToJSON - Error: Could not create a new file at the following location: "+path)
8949
9496
  if (f):
8950
- jsondata = Graph.JSONData(graph, verticesKey=verticesKey, edgesKey=edgesKey, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, xKey=xKey, yKey=yKey, zKey=zKey, mantissa=mantissa)
9497
+ jsondata = Graph.JSONData(graph, propertiesKey=propertiesKey, verticesKey=verticesKey, edgesKey=edgesKey, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, xKey=xKey, yKey=yKey, zKey=zKey, mantissa=mantissa)
8951
9498
  if jsondata != None:
8952
9499
  json.dump(jsondata, f, indent=indent, sort_keys=sortKeys)
8953
9500
  f.close()
@@ -10467,8 +11014,26 @@ class Graph:
10467
11014
  The created GraphViz graph.
10468
11015
  """
10469
11016
 
10470
- from graphviz import Digraph
10471
- from graphviz import Graph as Udgraph
11017
+ import os
11018
+ import warnings
11019
+
11020
+ try:
11021
+ from graphviz import Digraph
11022
+ from graphviz import Graph as Udgraph
11023
+
11024
+ except:
11025
+ print("Graph - Installing required graphviz library.")
11026
+ try:
11027
+ os.system("pip install graphviz")
11028
+ except:
11029
+ os.system("pip install graphviz --user")
11030
+ try:
11031
+ from graphviz import Digraph
11032
+ from graphviz import Graph as Udgraph
11033
+ print("Graph - graphviz library installed correctly.")
11034
+ except:
11035
+ warnings.warn("Graph - Error: Could not import graphviz.")
11036
+
10472
11037
  from topologicpy.Graph import Graph
10473
11038
  from topologicpy.Topology import Topology
10474
11039
  from topologicpy.Dictionary import Dictionary
@@ -11662,6 +12227,7 @@ class Graph:
11662
12227
 
11663
12228
  @staticmethod
11664
12229
  def JSONData(graph,
12230
+ propertiesKey: str = "properties",
11665
12231
  verticesKey: str = "vertices",
11666
12232
  edgesKey: str = "edges",
11667
12233
  vertexLabelKey: str = "",
@@ -11681,6 +12247,8 @@ class Graph:
11681
12247
  ----------
11682
12248
  graph : topologic_core.Graph
11683
12249
  The input graph.
12250
+ propertiesKey : str , optional
12251
+ The desired key name to call the graph properties. Default is "properties".
11684
12252
  verticesKey : str , optional
11685
12253
  The desired key name to call vertices. Default is "vertices".
11686
12254
  edgesKey : str , optional
@@ -11720,8 +12288,10 @@ class Graph:
11720
12288
  from topologicpy.Dictionary import Dictionary
11721
12289
  from topologicpy.Helper import Helper
11722
12290
 
12291
+ graph_d = Dictionary.PythonDictionary(Topology.Dictionary(graph))
11723
12292
  vertices = Graph.Vertices(graph)
11724
12293
  j_data = {}
12294
+ j_data[propertiesKey] = graph_d
11725
12295
  j_data[verticesKey] = {}
11726
12296
  j_data[edgesKey] = {}
11727
12297
  n = max(len(str(len(vertices))), 4)
@@ -14266,6 +14836,54 @@ class Graph:
14266
14836
  _ = graph.RemoveEdges([edge], tolerance) # Hook to Core
14267
14837
  return graph
14268
14838
 
14839
+ @staticmethod
14840
+ def RemoveIsolatedEdges(graph, removeVertices: bool = True, tolerance: float = 0.0001, silent: bool = False):
14841
+ """
14842
+ Removes all isolated edges from the input graph.
14843
+ Isolated edges are those whose vertices are not connected to any other edges.
14844
+ That is, they have a degree of 1.
14845
+
14846
+ Parameters
14847
+ ----------
14848
+ graph : topologic_core.Graph
14849
+ The input graph.
14850
+ removeVertices : bool , optional
14851
+ If set to True, the end vertices of the edges are also removed. Default is True.
14852
+ tolerance : float , optional
14853
+ The desired tolerance. Default is 0.0001.
14854
+ silent : bool , optional
14855
+ If set to True, error and warning messages are suppressed. Default is False.
14856
+
14857
+ Returns
14858
+ -------
14859
+ topologic_core.Graph
14860
+ The input graph with all isolated vertices removed.
14861
+
14862
+ """
14863
+ from topologicpy.Topology import Topology
14864
+ from topologicpy.Edge import Edge
14865
+
14866
+
14867
+ if not Topology.IsInstance(graph, "graph"):
14868
+ if not silent:
14869
+ print("Graph.RemoveIsolatedEdges - Error: The input graph parameter is not a valid graph. Returning None.")
14870
+ return None
14871
+
14872
+ edges = Graph.Edges(graph)
14873
+ if removeVertices == True:
14874
+ for edge in edges:
14875
+ va, vb = Edge.Vertices(edge)
14876
+ if Graph.VertexDegree(graph, va, tolerance=tolerance, silent=silent) == 1 and Graph.VertexDegree(graph, vb, tolerance=tolerance, silent=silent) == 1:
14877
+ graph = Graph.RemoveEdge(graph, edge, tolerance=tolerance)
14878
+ graph = Graph.RemoveVertex(graph, va, tolerance=tolerance)
14879
+ graph = Graph.RemoveVertex(graph, vb, tolerance=tolerance)
14880
+ else:
14881
+ for edge in edges:
14882
+ va, vb = Edge.Vertices(edge)
14883
+ if Graph.VertexDegree(graph, va, tolerance=tolerance, silent=silent) == 1 and Graph.VertexDegree(graph, vb, tolerance=tolerance, silent=silent) == 1:
14884
+ graph = Graph.RemoveEdge(graph, edge, tolerance=tolerance)
14885
+ return graph
14886
+
14269
14887
  @staticmethod
14270
14888
  def RemoveIsolatedVertices(graph, tolerance=0.0001):
14271
14889
  """
topologicpy/Kuzu.py CHANGED
@@ -476,7 +476,7 @@ class Kuzu:
476
476
  def GraphsByQuery(
477
477
  manager,
478
478
  query: str,
479
- params: dict | None = None,
479
+ params: dict = None,
480
480
  silent: bool = False,
481
481
  ):
482
482
  """
topologicpy/Topology.py CHANGED
@@ -2390,7 +2390,7 @@ class Topology():
2390
2390
  return topology
2391
2391
  '''
2392
2392
  @staticmethod
2393
- def ByJSONFile(file, tolerance=0.0001):
2393
+ def ByJSONFile(file, tolerance: float = 0.0001, silent: bool = False):
2394
2394
  """
2395
2395
  Imports the topology from a JSON file.
2396
2396
 
@@ -2400,6 +2400,8 @@ class Topology():
2400
2400
  The input JSON file.
2401
2401
  tolerance : float , optional
2402
2402
  The desired tolerance. Default is 0.0001.
2403
+ silent : bool , optional
2404
+ If set to True, error and warning messages are suppressed. Default is False.
2403
2405
 
2404
2406
  Returns
2405
2407
  -------
@@ -2407,14 +2409,21 @@ class Topology():
2407
2409
  The list of imported topologies (Warning: the list could contain 0, 1, or many topologies, but this method will always return a list)
2408
2410
 
2409
2411
  """
2412
+ import json
2410
2413
  if not file:
2411
- print("Topology.ByJSONFile - Error: the input file parameter is not a valid file. Returning None.")
2414
+ if not silent:
2415
+ print("Topology.ByJSONFile - Error: the input file parameter is not a valid file. Returning None.")
2416
+ return None
2417
+ try:
2418
+ json_dict = json.load(file)
2419
+ except Exception as e:
2420
+ if not silent:
2421
+ print("Topology.ByJSONFile - Error: Could not load the JSON file: {e}. Returning None.")
2412
2422
  return None
2413
- json_dict = json.load(file)
2414
- return Topology.ByJSONDictionary(json_dict, tolerance=tolerance)
2423
+ return Topology.ByJSONDictionary(json_dict, tolerance=tolerance, silent=silent)
2415
2424
 
2416
2425
  @staticmethod
2417
- def ByJSONPath(path, tolerance=0.0001):
2426
+ def ByJSONPath(path, tolerance: float = 0.0001, silent: bool = False):
2418
2427
  """
2419
2428
  Imports the topology from a JSON file.
2420
2429
 
@@ -2424,6 +2433,8 @@ class Topology():
2424
2433
  The file path to the json file.
2425
2434
  tolerance : float , optional
2426
2435
  The desired tolerance. Default is 0.0001.
2436
+ silent : bool , optional
2437
+ If set to True, error and warning messages are suppressed. Default is False.
2427
2438
 
2428
2439
  Returns
2429
2440
  -------
@@ -2433,15 +2444,20 @@ class Topology():
2433
2444
  """
2434
2445
  import json
2435
2446
  if not path:
2436
- print("Topology.ByJSONPath - Error: the input path parameter is not a valid path. Returning None.")
2447
+ if not silent:
2448
+ print("Topology.ByJSONPath - Error: the input path parameter is not a valid path. Returning None.")
2437
2449
  return None
2438
- with open(path) as file:
2439
- json_dict = json.load(file)
2440
- entities = Topology.ByJSONDictionary(json_dict, tolerance=tolerance)
2441
- return entities
2450
+ try:
2451
+ with open(path) as file:
2452
+ json_dict = json.load(file)
2453
+ except Exception as e:
2454
+ if not silent:
2455
+ print("Topology.ByJSONPath - Error: Could not load file: {e}. Returning None.")
2456
+ return None
2457
+ return Topology.ByJSONDictionary(json_dict, tolerance=tolerance, silent=silent)
2442
2458
 
2443
2459
  @staticmethod
2444
- def ByJSONDictionary(jsonDictionary, tolerance=0.0001):
2460
+ def ByJSONDictionary(jsonDictionary: dict, tolerance: float = 0.0001, silent: bool = False):
2445
2461
  """
2446
2462
  Imports the topology from a JSON dictionary.
2447
2463
 
@@ -2451,6 +2467,8 @@ class Topology():
2451
2467
  The input JSON dictionary.
2452
2468
  tolerance : float , optional
2453
2469
  The desired tolerance. Default is 0.0001.
2470
+ silent : bool , optional
2471
+ If set to True, error and warning messages are suppressed. Default is False.
2454
2472
 
2455
2473
  Returns
2456
2474
  -------
@@ -2489,41 +2507,41 @@ class Topology():
2489
2507
  # Create basic topological entities
2490
2508
  if entity_type == 'Vertex':
2491
2509
  parent_entity = Vertex.ByCoordinates(*entity['coordinates'])
2492
- parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
2510
+ parent_entity = Topology.SetDictionary(parent_entity, entity_dict, silent=silent)
2493
2511
  vertices[entity['uuid']] = parent_entity
2494
2512
 
2495
2513
  elif entity_type == 'Edge':
2496
2514
  vertex1 = vertices[entity['vertices'][0]]
2497
2515
  vertex2 = vertices[entity['vertices'][1]]
2498
- parent_entity = Edge.ByVertices([vertex1, vertex2])
2499
- parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
2516
+ parent_entity = Edge.ByVertices([vertex1, vertex2], tolerance=tolerance, silent=silent)
2517
+ parent_entity = Topology.SetDictionary(parent_entity, entity_dict, silent=silent)
2500
2518
  edges[entity['uuid']] = parent_entity
2501
2519
 
2502
2520
  elif entity_type == 'Wire':
2503
2521
  wire_edges = [edges[uuid] for uuid in entity['edges']]
2504
- parent_entity = Wire.ByEdges(wire_edges)
2505
- parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
2522
+ parent_entity = Wire.ByEdges(wire_edges, tolerance=tolerance, silent=silent)
2523
+ parent_entity = Topology.SetDictionary(parent_entity, entity_dict, silent=silent)
2506
2524
  wires[entity['uuid']] = parent_entity
2507
2525
 
2508
2526
  elif entity_type == 'Face':
2509
2527
  face_wires = [wires[uuid] for uuid in entity['wires']]
2510
2528
  if len(face_wires) > 1:
2511
- parent_entity = Face.ByWires(face_wires[0], face_wires[1:])
2529
+ parent_entity = Face.ByWires(face_wires[0], face_wires[1:], tolerance=tolerance, silent=silent)
2512
2530
  else:
2513
- parent_entity = Face.ByWire(face_wires[0])
2514
- parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
2531
+ parent_entity = Face.ByWire(face_wires[0], tolerance=tolerance, silent=silent)
2532
+ parent_entity = Topology.SetDictionary(parent_entity, entity_dict, silent=silent)
2515
2533
  faces[entity['uuid']] = parent_entity
2516
2534
 
2517
2535
  elif entity_type == 'Shell':
2518
2536
  shell_faces = [faces[uuid] for uuid in entity['faces']]
2519
- parent_entity = Shell.ByFaces(shell_faces)
2520
- parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
2537
+ parent_entity = Shell.ByFaces(shell_faces, tolerance=tolerance, silent=silent)
2538
+ parent_entity = Topology.SetDictionary(parent_entity, entity_dict, silent=silent)
2521
2539
  shells[entity['uuid']] = parent_entity
2522
2540
 
2523
2541
  elif entity_type == 'Cell':
2524
2542
  cell_shells = [shells[uuid] for uuid in entity['shells']]
2525
2543
  if len(cell_shells) > 1:
2526
- parent_entity = Cell.ByShells(cell_shells[0], cell_shells[1:])
2544
+ parent_entity = Cell.ByShells(cell_shells[0], cell_shells[1:], tolerance=tolerance, silent=silent)
2527
2545
  else:
2528
2546
  parent_entity = Cell.ByShell(cell_shells[0])
2529
2547
  parent_entity = Topology.SetDictionary(parent_entity, entity_dict)
@@ -2649,7 +2667,7 @@ class Topology():
2649
2667
  return top_level_list
2650
2668
 
2651
2669
  @staticmethod
2652
- def ByJSONString(string, tolerance=0.0001):
2670
+ def ByJSONString(string: str, tolerance: float = 0.0001, silent: bool = False):
2653
2671
  """
2654
2672
  Imports the topology from a JSON string.
2655
2673
 
@@ -2659,6 +2677,8 @@ class Topology():
2659
2677
  The input JSON string.
2660
2678
  tolerance : float , optional
2661
2679
  The desired tolerance. Default is 0.0001.
2680
+ silent : bool , optional
2681
+ If set to True, error and warning messages are suppressed. Default is False.
2662
2682
 
2663
2683
  Returns
2664
2684
  -------
@@ -2666,9 +2686,13 @@ class Topology():
2666
2686
  The list of imported topologies (Warning: the list could contain 0, 1, or many topologies, but this method will always return a list)
2667
2687
 
2668
2688
  """
2669
-
2670
- json_dict = json.loads(string)
2671
- return Topology.ByJSONDictionary(json_dict, tolerance=tolerance)
2689
+ try:
2690
+ json_dict = json.loads(string)
2691
+ except Exception as e:
2692
+ if not silent:
2693
+ print(f"Topology.ByJSONString - Error: Could not read the input string: {e}. Returning None.")
2694
+ return None
2695
+ return Topology.ByJSONDictionary(json_dict, tolerance=tolerance, silent=silent)
2672
2696
 
2673
2697
  @staticmethod
2674
2698
  def ByMeshData(dictionary, transferDictionaries: bool = False, mantissa: int = 6, tolerance: float = 0.0001, silent: bool = False):
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.8.59'
1
+ __version__ = '0.8.61'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topologicpy
3
- Version: 0.8.59
3
+ Version: 0.8.61
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=ndrfovjwEEQTJ0B5DuthuCBDdVg9-1i_MX8Dtj-wD4E,177330
5
+ topologicpy/Cell.py,sha256=xkt9lfutgSwr_1lah1U5n48UnrLIggznNKUmEe2FA2g,177505
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
@@ -12,11 +12,11 @@ topologicpy/Dictionary.py,sha256=Z4YQ88tONWd-0X0dENQ8IZqIOa9mbBqhJkTBsHmft2g,446
12
12
  topologicpy/Edge.py,sha256=DifItuyabFDUFC7CVMlt2DeMFMNaGOqCg43iU9CPP0A,74029
13
13
  topologicpy/EnergyModel.py,sha256=hB1aiJe45gdDMFm1AhkBr-1djjtXSzn24iRpQMk43-4,57749
14
14
  topologicpy/Face.py,sha256=aX9EcR3JGbLITElhd25J0Z8m9U8KkmbYivGg3oZN-Uw,202296
15
- topologicpy/Graph.py,sha256=LMK-YceKCPP4-8s32mTF2QPRaxbUiKSwytV3WcpQJIE,756629
15
+ topologicpy/Graph.py,sha256=ytXl9VLj243o9LhY0A8P_gp4_Ce_VrHW5oaC2WK6Mbc,782718
16
16
  topologicpy/Grid.py,sha256=3OsBMyHh4w8gpFOTMKHMNTpo62V0CwRNu5cwm87yDUA,18421
17
17
  topologicpy/Helper.py,sha256=Nr6pyzl0sZm4Cu11wOqoYKu6yYal5N6A9jErXnaZBJc,31765
18
18
  topologicpy/Honeybee.py,sha256=DzaG9wpkJdcDWcjOGXhuN5X0gCqypmZGBa1y5E2MkjU,48964
19
- topologicpy/Kuzu.py,sha256=THmXfImCVTZhvt0fH0M2-PJeFNyTnmBCf_sjXDxOraE,36305
19
+ topologicpy/Kuzu.py,sha256=fxaDPWM5Xam7Tot0olPZsazS_7xgE_Vo-jf0Sbv3VZE,36298
20
20
  topologicpy/Matrix.py,sha256=bOofT34G3YHu9aMIWx60YHAJga4R0GbDjsZBUD4Hu_k,22706
21
21
  topologicpy/Neo4j.py,sha256=J8jU_mr5-mWC0Lg_D2dMjMlx1rY_eh8ks_aubUuTdWw,22319
22
22
  topologicpy/Plotly.py,sha256=OQvCzAXqu_QYn8iY0rjc8ZB4XwwK70pWjnnoMzDdcc0,123167
@@ -26,14 +26,14 @@ topologicpy/ShapeGrammar.py,sha256=KYsKDLXWdflAcYMAIz84AUF-GMkbTmaBDd2-ovbilqU,2
26
26
  topologicpy/Shell.py,sha256=ioO4raCJfXtYldQg-adpcLVeJPEA6od6cAA5ro7t6r4,96792
27
27
  topologicpy/Speckle.py,sha256=-eiTqJugd7pHiHpD3pDUcDO6CGhVyPV14HFRzaqEoaw,18187
28
28
  topologicpy/Sun.py,sha256=8S6dhCKfOhUGVny-jEk87Q08anLYMB1JEBKRGCklvbQ,36670
29
- topologicpy/Topology.py,sha256=_D1E8c8lnbu4Eii4YjkJhWoNb-q2ELdnLIE-xQFloPg,472580
29
+ topologicpy/Topology.py,sha256=O3K4B47K0ic4jMj4OC9ZuqDPV6I7QRZ6r7Q9SHPEqaI,474206
30
30
  topologicpy/Vector.py,sha256=pEC8YY3TeHGfGdeNgvdHjgMDwxGabp5aWjwYC1HSvMk,42236
31
31
  topologicpy/Vertex.py,sha256=r_3cicgpino96ymm1ANptfOuqE59b99YWwksxyPOYK4,85914
32
32
  topologicpy/Wire.py,sha256=gjgQUGHdBdXUIijgZc_VIW0E39w-smaVhhdl0jF63fQ,230466
33
33
  topologicpy/__init__.py,sha256=RMftibjgAnHB1vdL-muo71RwMS4972JCxHuRHOlU428,928
34
- topologicpy/version.py,sha256=JBWmeYi_9RclzA_WCIMX3fzJxg3vh3eyKLFiq90X2mA,23
35
- topologicpy-0.8.59.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
36
- topologicpy-0.8.59.dist-info/METADATA,sha256=hEPFnN0ZWkV_YPvQ5wemo_9nnmV9H6qW42XErgpUvSs,10535
37
- topologicpy-0.8.59.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- topologicpy-0.8.59.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
39
- topologicpy-0.8.59.dist-info/RECORD,,
34
+ topologicpy/version.py,sha256=v9RYfeFVriaSopTI1WMyzj0QSU9vvxnXtU_efzx9Iek,23
35
+ topologicpy-0.8.61.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
36
+ topologicpy-0.8.61.dist-info/METADATA,sha256=AUdc_jfqI7o0MlB6Izlr_BIUcpjbN71DLKCHBY1UYsA,10535
37
+ topologicpy-0.8.61.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ topologicpy-0.8.61.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
39
+ topologicpy-0.8.61.dist-info/RECORD,,