topologicpy 0.5.4__py3-none-any.whl → 0.5.6__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/Graph.py CHANGED
@@ -527,6 +527,329 @@ class Graph:
527
527
  lcc = Graph.LocalClusteringCoefficient(graph, vertices)
528
528
  acc = round(sum(lcc)/float(len(lcc)), mantissa)
529
529
  return acc
530
+
531
+ @staticmethod
532
+ def BOTGraph(graph,
533
+ bidirectional=False,
534
+ includeAttributes=False,
535
+ includeLabel=False,
536
+ siteLabel = "Site_0001",
537
+ siteDictionary = None,
538
+ buildingLabel = "Building_0001",
539
+ buildingDictionary = None ,
540
+ storeyPrefix = "Storey",
541
+ floorLevels =[],
542
+ labelKey="label",
543
+ typeKey="type",
544
+ spaceType = "space",
545
+ wallType = "wall",
546
+ slabType = "slab",
547
+ doorType = "door",
548
+ windowType = "window",
549
+ contentType = "content"
550
+ ):
551
+ """
552
+ Creates an RDF graph according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
553
+
554
+ Parameters
555
+ ----------
556
+ graph : topologic.Graph
557
+ The input graph.
558
+ bidirectional : bool , optional
559
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
560
+ includeAttributes : bool , optional
561
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
562
+ includeLabel : bool , optional
563
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
564
+ siteLabel : str , optional
565
+ The desired site label. The default is "Site_0001".
566
+ siteDictionary : dict , optional
567
+ The dictionary of site attributes to include in the output. The default is None.
568
+ buildingLabel : str , optional
569
+ The desired building label. The default is "Building_0001".
570
+ buildingDictionary : dict , optional
571
+ The dictionary of building attributes to include in the output. The default is None.
572
+ storeyPrefix : str , optional
573
+ The desired prefixed to use for each building storey. The default is "Storey".
574
+ floorLevels : list , optional
575
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
576
+ If not provided, floorLevels will be computed automatically based on the vertices' 'z' attribute.
577
+ typeKey : str , optional
578
+ The dictionary key to use to look up the type of the node. The default is "type".
579
+ labelKey : str , optional
580
+ The dictionary key to use to look up the label of the node. The default is "label".
581
+ spaceType : str , optional
582
+ The dictionary string value to use to look up vertices of type "space". The default is "space".
583
+ wallType : str , optional
584
+ The dictionary string value to use to look up vertices of type "wall". The default is "wall".
585
+ slabType : str , optional
586
+ The dictionary string value to use to look up vertices of type "slab". The default is "slab".
587
+ doorType : str , optional
588
+ The dictionary string value to use to look up vertices of type "door". The default is "door".
589
+ windowType : str , optional
590
+ The dictionary string value to use to look up vertices of type "window". The default is "window".
591
+ contentType : str , optional
592
+ The dictionary string value to use to look up vertices of type "content". The default is "contents".
593
+
594
+ Returns
595
+ -------
596
+ rdflib.graph.Graph
597
+ The rdf graph using the BOT ontology.
598
+ """
599
+
600
+ from topologicpy.Helper import Helper
601
+ import os
602
+ import warnings
603
+
604
+ try:
605
+ from rdflib import Graph as RDFGraph
606
+ from rdflib import URIRef, Literal, Namespace
607
+ from rdflib.namespace import RDF, RDFS
608
+ except:
609
+ print("Graph.BOTGraph - Installing required rdflib library.")
610
+ try:
611
+ os.system("pip install rdflib")
612
+ except:
613
+ os.system("pip install rdflib --user")
614
+ try:
615
+ from rdflib import Graph as RDFGraph
616
+ from rdflib import URIRef, Literal, Namespace
617
+ from rdflib.namespace import RDF, RDFS
618
+ print("Graph.BOTGraph - rdflib library installed correctly.")
619
+ except:
620
+ warnings.warn("Graph.BOTGraph - Error: Could not import rdflib. Please try to install rdflib manually. Returning None.")
621
+ return None
622
+
623
+ if floorLevels == None:
624
+ floorLevels = []
625
+ json_data = Graph.JSONData(graph, vertexLabelKey=labelKey)
626
+ # Create an empty RDF graph
627
+ bot_graph = RDFGraph()
628
+
629
+ # Define namespaces
630
+ rdf = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
631
+ rdfs = Namespace("http://www.w3.org/2000/01/rdf-schema#")
632
+ bot = Namespace("https://w3id.org/bot#")
633
+
634
+ # Define a custom prefix mapping
635
+ bot_graph.namespace_manager.bind("bot", bot)
636
+
637
+ # Add site
638
+ site_uri = URIRef(siteLabel)
639
+ bot_graph.add((site_uri, rdf.type, bot.Site))
640
+ if includeLabel:
641
+ bot_graph.add((site_uri, RDFS.label, Literal(siteLabel)))
642
+ if isinstance(siteDictionary, topologic.Dictionary):
643
+ keys = Dictionary.Keys(siteDictionary)
644
+ for key in keys:
645
+ value = Dictionary.ValueAtKey(siteDictionary, key)
646
+ if not (key == labelKey) and not (key == typeKey):
647
+ bot_graph.add((site_uri, bot[key], Literal(value)))
648
+ # Add building
649
+ building_uri = URIRef(buildingLabel)
650
+ bot_graph.add((building_uri, rdf.type, bot.Building))
651
+ if includeLabel:
652
+ bot_graph.add((building_uri, RDFS.label, Literal(buildingLabel)))
653
+ if isinstance(buildingDictionary, topologic.Dictionary):
654
+ keys = Dictionary.Keys(buildingDictionary)
655
+ for key in keys:
656
+ value = Dictionary.ValueAtKey(buildingDictionary, key)
657
+ if key == labelKey:
658
+ if includeLabel:
659
+ bot_graph.add((building_uri, RDFS.label, Literal(value)))
660
+ elif key != typeKey:
661
+ bot_graph.add((building_uri, bot[key], Literal(value)))
662
+ # Add stories
663
+ # if floor levels are not given, then need to be computed
664
+ if len(floorLevels) == 0:
665
+ for node, attributes in json_data['vertices'].items():
666
+ if slabType.lower() in attributes[typeKey].lower():
667
+ floorLevels.append(attributes["z"])
668
+ floorLevels = list(set(floorLevels))
669
+ floorLevels.sort()
670
+ floorLevels = floorLevels[:-1]
671
+ storey_uris = []
672
+ n = max(len(str(len(floorLevels))),4)
673
+ for i, floor_level in enumerate(floorLevels):
674
+ storey_uri = URIRef(storeyPrefix+"_"+str(i+1).zfill(n))
675
+ bot_graph.add((storey_uri, rdf.type, bot.Storey))
676
+ if includeLabel:
677
+ bot_graph.add((storey_uri, RDFS.label, Literal(storeyPrefix+"_"+str(i+1).zfill(n))))
678
+ storey_uris.append(storey_uri)
679
+
680
+ # Add triples to relate building to site and stories to building
681
+ bot_graph.add((site_uri, bot.hasBuilding, building_uri))
682
+ if bidirectional:
683
+ bot_graph.add((building_uri, bot.isPartOf, site_uri)) # might not be needed
684
+
685
+ for storey_uri in storey_uris:
686
+ bot_graph.add((building_uri, bot.hasStorey, storey_uri))
687
+ if bidirectional:
688
+ bot_graph.add((storey_uri, bot.isPartOf, building_uri)) # might not be needed
689
+
690
+ # Add vertices as RDF resources
691
+ for node, attributes in json_data['vertices'].items():
692
+ node_uri = URIRef(node)
693
+ if spaceType.lower() in attributes[typeKey].lower():
694
+ bot_graph.add((node_uri, rdf.type, bot.Space))
695
+ # Find the storey it is on
696
+ z = attributes["z"]
697
+ level = Helper.Position(z, floorLevels)
698
+ if level > len(storey_uris):
699
+ level = len(storey_uris)
700
+ storey_uri = storey_uris[level-1]
701
+ bot_graph.add((storey_uri, bot.hasSpace, node_uri))
702
+ if bidirectional:
703
+ bot_graph.add((node_uri, bot.isPartOf, storey_uri)) # might not be needed
704
+ elif windowType.lower() in attributes[typeKey].lower():
705
+ bot_graph.add((node_uri, rdf.type, bot.Window))
706
+ elif doorType.lower() in attributes[typeKey].lower():
707
+ bot_graph.add((node_uri, rdf.type, bot.Door))
708
+ elif wallType.lower() in attributes[typeKey].lower():
709
+ bot_graph.add((node_uri, rdf.type, bot.Wall))
710
+ elif slabType.lower() in attributes[typeKey].lower():
711
+ bot_graph.add((node_uri, rdf.type, bot.Slab))
712
+ else:
713
+ bot_graph.add((node_uri, rdf.type, bot.Element))
714
+
715
+ if includeAttributes:
716
+ for key, value in attributes.items():
717
+ if key == labelKey:
718
+ if includeLabel:
719
+ bot_graph.add((node_uri, RDFS.label, Literal(value)))
720
+ elif key != typeKey:
721
+ bot_graph.add((node_uri, bot[key], Literal(value)))
722
+ if includeLabel:
723
+ for key, value in attributes.items():
724
+ if key == labelKey:
725
+ bot_graph.add((node_uri, RDFS.label, Literal(value)))
726
+
727
+ # Add edges as RDF triples
728
+ for edge, attributes in json_data['edges'].items():
729
+ source = attributes["source"]
730
+ target = attributes["target"]
731
+ source_uri = URIRef(source)
732
+ target_uri = URIRef(target)
733
+ if spaceType.lower() in json_data['vertices'][source][typeKey].lower() and spaceType.lower() in json_data['vertices'][target][typeKey].lower():
734
+ bot_graph.add((source_uri, bot.adjacentTo, target_uri))
735
+ if bidirectional:
736
+ bot_graph.add((target_uri, bot.adjacentTo, source_uri))
737
+ elif spaceType.lower() in json_data['vertices'][source][typeKey].lower() and wallType.lower() in json_data['vertices'][target][typeKey].lower():
738
+ bot_graph.add((target_uri, bot.interfaceOf, source_uri))
739
+ elif spaceType.lower() in json_data['vertices'][source][typeKey].lower() and slabType.lower() in json_data['vertices'][target][typeKey].lower():
740
+ bot_graph.add((target_uri, bot.interfaceOf, source_uri))
741
+ elif spaceType.lower() in json_data['vertices'][source][typeKey].lower() and contentType.lower() in json_data['vertices'][target][typeKey].lower():
742
+ bot_graph.add((source_uri, bot.containsElement, target_uri))
743
+ if bidirectional:
744
+ bot_graph.add((target_uri, bot.isPartOf, source_uri))
745
+ else:
746
+ bot_graph.add((source_uri, bot.connectsTo, target_uri))
747
+ if bidirectional:
748
+ bot_graph.add((target_uri, bot.connectsTo, source_uri))
749
+ return bot_graph
750
+
751
+ @staticmethod
752
+ def BOTString(graph,
753
+ format="turtle",
754
+ bidirectional=False,
755
+ includeAttributes=False,
756
+ includeLabel=False,
757
+ siteLabel = "Site_0001",
758
+ siteDictionary = None,
759
+ buildingLabel = "Building_0001",
760
+ buildingDictionary = None ,
761
+ storeyPrefix = "Storey",
762
+ floorLevels =[],
763
+ labelKey="label",
764
+ typeKey="type",
765
+ spaceType = "space",
766
+ wallType = "wall",
767
+ slabType = "slab",
768
+ doorType = "door",
769
+ windowType = "window",
770
+ contentType = "content",
771
+ ):
772
+
773
+ """
774
+ Returns an RDF graph serialized string according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
775
+
776
+ Parameters
777
+ ----------
778
+ graph : topologic.Graph
779
+ The input graph.
780
+ format : str , optional
781
+ The desired output format, the options are listed below. Thde default is "turtle".
782
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
783
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
784
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
785
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
786
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
787
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
788
+ trix : Trix , RDF/XML-like format for RDF quads
789
+ nquads : N-Quads , N-Triples-like format for RDF quads
790
+ bidirectional : bool , optional
791
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
792
+ includeAttributes : bool , optional
793
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
794
+ includeLabel : bool , optional
795
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
796
+ siteLabel : str , optional
797
+ The desired site label. The default is "Site_0001".
798
+ siteDictionary : dict , optional
799
+ The dictionary of site attributes to include in the output. The default is None.
800
+ buildingLabel : str , optional
801
+ The desired building label. The default is "Building_0001".
802
+ buildingDictionary : dict , optional
803
+ The dictionary of building attributes to include in the output. The default is None.
804
+ storeyPrefix : str , optional
805
+ The desired prefixed to use for each building storey. The default is "Storey".
806
+ floorLevels : list , optional
807
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
808
+ If not provided, floorLevels will be computed automatically based on the vertices' 'z' attribute.
809
+ typeKey : str , optional
810
+ The dictionary key to use to look up the type of the node. The default is "type".
811
+ labelKey : str , optional
812
+ The dictionary key to use to look up the label of the node. The default is "label".
813
+ spaceType : str , optional
814
+ The dictionary string value to use to look up vertices of type "space". The default is "space".
815
+ wallType : str , optional
816
+ The dictionary string value to use to look up vertices of type "wall". The default is "wall".
817
+ slabType : str , optional
818
+ The dictionary string value to use to look up vertices of type "slab". The default is "slab".
819
+ doorType : str , optional
820
+ The dictionary string value to use to look up vertices of type "door". The default is "door".
821
+ windowType : str , optional
822
+ The dictionary string value to use to look up vertices of type "window". The default is "window".
823
+ contentType : str , optional
824
+ The dictionary string value to use to look up vertices of type "content". The default is "contents".
825
+
826
+
827
+ Returns
828
+ -------
829
+ str
830
+ The rdf graph serialized string using the BOT ontology.
831
+ """
832
+
833
+ bot_graph = Graph.BOTGraph(graph,
834
+ bidirectional=bidirectional,
835
+ includeAttributes=includeAttributes,
836
+ includeLabel=includeLabel,
837
+ siteLabel=siteLabel,
838
+ siteDictionary=siteDictionary,
839
+ buildingLabel=buildingLabel,
840
+ buildingDictionary=buildingDictionary,
841
+ storeyPrefix=storeyPrefix,
842
+ floorLevels=floorLevels,
843
+ labelKey=labelKey,
844
+ typeKey=typeKey,
845
+ spaceType = spaceType,
846
+ wallType = wallType,
847
+ slabType = slabType,
848
+ doorType = doorType,
849
+ windowType = windowType,
850
+ contentType = contentType
851
+ )
852
+ return bot_graph.serialize(format=format)
530
853
 
531
854
  @staticmethod
532
855
  def BetweenessCentrality(graph, vertices=None, sources=None, destinations=None, tolerance=0.001):
@@ -1469,6 +1792,7 @@ class Graph:
1469
1792
  from topologicpy.Edge import Edge
1470
1793
  from topologicpy.Cluster import Cluster
1471
1794
  from topologicpy.Topology import Topology
1795
+ from topologicpy.Aperture import Aperture
1472
1796
 
1473
1797
  def mergeDictionaries(sources):
1474
1798
  if isinstance(sources, list) == False:
@@ -1687,7 +2011,7 @@ class Graph:
1687
2011
 
1688
2012
  cells = []
1689
2013
  _ = topology.Cells(None, cells)
1690
- if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2014
+ if any([viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents]):
1691
2015
  for aCell in cells:
1692
2016
  if useInternalVertex == True:
1693
2017
  vCell = Topology.InternalVertex(aCell, tolerance=tolerance)
@@ -1710,9 +2034,9 @@ class Graph:
1710
2034
  contents = []
1711
2035
  _ = aCell.Contents(contents)
1712
2036
  for aFace in faces:
1713
- cells = []
1714
- _ = aFace.Cells(topology, cells)
1715
- if len(cells) > 1:
2037
+ cells1 = []
2038
+ _ = aFace.Cells(topology, cells1)
2039
+ if len(cells1) > 1:
1716
2040
  sharedTopologies.append(aFace)
1717
2041
  apertures = []
1718
2042
  _ = aFace.Apertures(apertures)
@@ -1724,6 +2048,7 @@ class Graph:
1724
2048
  _ = aFace.Apertures(apertures)
1725
2049
  for anAperture in apertures:
1726
2050
  exteriorApertures.append(anAperture)
2051
+
1727
2052
  if viaSharedTopologies:
1728
2053
  for sharedTopology in sharedTopologies:
1729
2054
  if useInternalVertex == True:
@@ -1746,6 +2071,8 @@ class Graph:
1746
2071
  contents = []
1747
2072
  _ = sharedTopology.Contents(contents)
1748
2073
  for content in contents:
2074
+ if isinstance(content, topologic.Aperture):
2075
+ content = Aperture.Topology(content)
1749
2076
  if useInternalVertex == True:
1750
2077
  vst2 = Topology.InternalVertex(content, tolerance)
1751
2078
  else:
@@ -1767,38 +2094,38 @@ class Graph:
1767
2094
  for sharedAperture in sharedApertures:
1768
2095
  sharedAp = sharedAperture.Topology()
1769
2096
  if useInternalVertex == True:
1770
- vst = Topology.InternalVertex(sharedAp, tolerance)
2097
+ vsa = Topology.InternalVertex(sharedAp, tolerance)
1771
2098
  else:
1772
- vst = sharedAp.CenterOfMass()
2099
+ vsa = sharedAp.CenterOfMass()
1773
2100
  d1 = sharedAp.GetDictionary()
1774
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2101
+ vsa = topologic.Vertex.ByCoordinates(vsa.X()+(tolerance*100), vsa.Y()+(tolerance*100), vsa.Z()+(tolerance*100))
1775
2102
  if storeBRep:
1776
2103
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(sharedAperture), Topology.Type(sharedAperture), Topology.TypeAsString(sharedAperture)])
1777
2104
  d3 = mergeDictionaries2([d1, d2])
1778
- _ = vst.SetDictionary(d3)
2105
+ _ = vsa.SetDictionary(d3)
1779
2106
  else:
1780
- _ = vst.SetDictionary(d1)
1781
- vertices.append(vst)
1782
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2107
+ _ = vsa.SetDictionary(d1)
2108
+ vertices.append(vsa)
2109
+ tempe = Edge.ByStartVertexEndVertex(vCell, vsa, tolerance=tolerance)
1783
2110
  tempd = Dictionary.ByKeysValues(["relationship"],["Via Shared Apertures"])
1784
2111
  _ = tempe.SetDictionary(tempd)
1785
2112
  edges.append(tempe)
1786
2113
  if toExteriorTopologies:
1787
2114
  for exteriorTopology in exteriorTopologies:
1788
2115
  if useInternalVertex == True:
1789
- vst = Topology.InternalVertex(exteriorTopology, tolerance)
2116
+ vet = Topology.InternalVertex(exteriorTopology, tolerance)
1790
2117
  else:
1791
- vst = exteriorTopology.CenterOfMass()
1792
- _ = vst.SetDictionary(exteriorTopology.GetDictionary())
2118
+ vet = exteriorTopology.CenterOfMass()
2119
+ _ = vet.SetDictionary(exteriorTopology.GetDictionary())
1793
2120
  d1 = exteriorTopology.GetDictionary()
1794
2121
  if storeBRep:
1795
2122
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(exteriorTopology), Topology.Type(exteriorTopology), Topology.TypeAsString(exteriorTopology)])
1796
2123
  d3 = mergeDictionaries2([d1, d2])
1797
- _ = vst.SetDictionary(d3)
2124
+ _ = vet.SetDictionary(d3)
1798
2125
  else:
1799
- _ = vst.SetDictionary(d1)
1800
- vertices.append(vst)
1801
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2126
+ _ = vet.SetDictionary(d1)
2127
+ vertices.append(vet)
2128
+ tempe = Edge.ByStartVertexEndVertex(vCell, vet, tolerance=tolerance)
1802
2129
  tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Topologies"])
1803
2130
  _ = tempe.SetDictionary(tempd)
1804
2131
  edges.append(tempe)
@@ -1806,6 +2133,8 @@ class Graph:
1806
2133
  contents = []
1807
2134
  _ = exteriorTopology.Contents(contents)
1808
2135
  for content in contents:
2136
+ if isinstance(content, topologic.Aperture):
2137
+ content = Aperture.Topology(content)
1809
2138
  if useInternalVertex == True:
1810
2139
  vst2 = Topology.InternalVertex(content, tolerance)
1811
2140
  else:
@@ -1819,7 +2148,7 @@ class Graph:
1819
2148
  else:
1820
2149
  _ = vst2.SetDictionary(d1)
1821
2150
  vertices.append(vst2)
1822
- tempe = Edge.ByStartVertexEndVertex(vst, vst2, tolerance=tolerance)
2151
+ tempe = Edge.ByStartVertexEndVertex(vet, vst2, tolerance=tolerance)
1823
2152
  tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
1824
2153
  _ = tempe.SetDictionary(tempd)
1825
2154
  edges.append(tempe)
@@ -1827,19 +2156,19 @@ class Graph:
1827
2156
  for exteriorAperture in exteriorApertures:
1828
2157
  extTop = exteriorAperture.Topology()
1829
2158
  if useInternalVertex == True:
1830
- vst = Topology.InternalVertex(extTop, tolerance)
2159
+ vea = Topology.InternalVertex(extTop, tolerance)
1831
2160
  else:
1832
- vst = exteriorAperture.Topology().CenterOfMass()
2161
+ vea = exteriorAperture.Topology().CenterOfMass()
1833
2162
  d1 = exteriorAperture.Topology().GetDictionary()
1834
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2163
+ vea = topologic.Vertex.ByCoordinates(vea.X()+(tolerance*100), vea.Y()+(tolerance*100), vea.Z()+(tolerance*100))
1835
2164
  if storeBRep:
1836
2165
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(exteriorAperture), Topology.Type(exteriorAperture), Topology.TypeAsString(exteriorAperture)])
1837
2166
  d3 = mergeDictionaries2([d1, d2])
1838
- _ = vst.SetDictionary(d3)
2167
+ _ = vea.SetDictionary(d3)
1839
2168
  else:
1840
- _ = vst.SetDictionary(d1)
1841
- vertices.append(vst)
1842
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2169
+ _ = vea.SetDictionary(d1)
2170
+ vertices.append(vea)
2171
+ tempe = Edge.ByStartVertexEndVertex(vCell, vea, tolerance=tolerance)
1843
2172
  tempd = Dictionary.ByKeysValues(["relationship"],["To Exterior Apertures"])
1844
2173
  _ = tempe.SetDictionary(tempd)
1845
2174
  edges.append(tempe)
@@ -1847,20 +2176,22 @@ class Graph:
1847
2176
  contents = []
1848
2177
  _ = aCell.Contents(contents)
1849
2178
  for content in contents:
2179
+ if isinstance(content, topologic.Aperture):
2180
+ content = Aperture.Topology(content)
1850
2181
  if useInternalVertex == True:
1851
- vst = Topology.InternalVertex(content, tolerance)
2182
+ vcn = Topology.InternalVertex(content, tolerance)
1852
2183
  else:
1853
- vst = content.CenterOfMass()
1854
- vst = topologic.Vertex.ByCoordinates(vst.X()+(tolerance*100), vst.Y()+(tolerance*100), vst.Z()+(tolerance*100))
2184
+ vcn = content.CenterOfMass()
2185
+ vcn = topologic.Vertex.ByCoordinates(vcn.X()+(tolerance*100), vcn.Y()+(tolerance*100), vcn.Z()+(tolerance*100))
1855
2186
  d1 = content.GetDictionary()
1856
2187
  if storeBRep:
1857
2188
  d2 = Dictionary.ByKeysValues(["brep", "brepType", "brepTypeString"], [Topology.BREPString(content), Topology.Type(content), Topology.TypeAsString(content)])
1858
2189
  d3 = mergeDictionaries2([d1, d2])
1859
- _ = vst.SetDictionary(d3)
2190
+ _ = vcn.SetDictionary(d3)
1860
2191
  else:
1861
- _ = vst.SetDictionary(d1)
1862
- vertices.append(vst)
1863
- tempe = Edge.ByStartVertexEndVertex(vCell, vst, tolerance=tolerance)
2192
+ _ = vcn.SetDictionary(d1)
2193
+ vertices.append(vcn)
2194
+ tempe = Edge.ByStartVertexEndVertex(vCell, vcn, tolerance=tolerance)
1864
2195
  tempd = Dictionary.ByKeysValues(["relationship"],["To Contents"])
1865
2196
  _ = tempe.SetDictionary(tempd)
1866
2197
  edges.append(tempe)
@@ -1885,7 +2216,7 @@ class Graph:
1885
2216
  vertices = []
1886
2217
  edges = []
1887
2218
  if useInternalVertex == True:
1888
- vCell = Topology.InternalVertex(Topology.Copy(topology), tolerance=tolerance)
2219
+ vCell = Topology.InternalVertex(topology, tolerance=tolerance)
1889
2220
  else:
1890
2221
  vCell = topology.CenterOfMass()
1891
2222
  d1 = topology.GetDictionary()
@@ -1920,7 +2251,7 @@ class Graph:
1920
2251
  tempd = Dictionary.ByKeysValues(["relationship"],["To Outposts"])
1921
2252
  _ = tempe.SetDictionary(tempd)
1922
2253
  edges.append(tempe)
1923
- if (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2254
+ if any([toExteriorTopologies, toExteriorApertures, toContents]):
1924
2255
  faces = Topology.Faces(topology)
1925
2256
  exteriorTopologies = []
1926
2257
  exteriorApertures = []
@@ -1951,6 +2282,8 @@ class Graph:
1951
2282
  contents = []
1952
2283
  _ = exteriorTopology.Contents(contents)
1953
2284
  for content in contents:
2285
+ if isinstance(content, topologic.Aperture):
2286
+ content = Aperture.Topology(content)
1954
2287
  if useInternalVertex == True:
1955
2288
  vst2 = Topology.InternalVertex(content, tolerance)
1956
2289
  else:
@@ -1992,6 +2325,8 @@ class Graph:
1992
2325
  contents = []
1993
2326
  _ = topology.Contents(contents)
1994
2327
  for content in contents:
2328
+ if isinstance(content, topologic.Aperture):
2329
+ content = Aperture.Topology(content)
1995
2330
  if useInternalVertex == True:
1996
2331
  vst = Topology.InternalVertex(content, tolerance)
1997
2332
  else:
@@ -2094,7 +2429,7 @@ class Graph:
2094
2429
 
2095
2430
  topFaces = []
2096
2431
  _ = topology.Faces(None, topFaces)
2097
- if (viaSharedTopologies == True) or (viaSharedApertures == True) or (toExteriorTopologies == True) or (toExteriorApertures == True) or (toContents == True):
2432
+ if any([viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents == True]):
2098
2433
  for aFace in topFaces:
2099
2434
  if useInternalVertex == True:
2100
2435
  vFace = Topology.InternalVertex(aFace, tolerance=tolerance)
@@ -2145,6 +2480,8 @@ class Graph:
2145
2480
  contents = []
2146
2481
  _ = sharedTopology.Contents(contents)
2147
2482
  for content in contents:
2483
+ if isinstance(content, topologic.Aperture):
2484
+ content = Aperture.Topology(content)
2148
2485
  if useInternalVertex == True:
2149
2486
  vst2 = Topology.InternalVertex(content, tolerance)
2150
2487
  else:
@@ -2203,6 +2540,8 @@ class Graph:
2203
2540
  contents = []
2204
2541
  _ = exteriorTopology.Contents(contents)
2205
2542
  for content in contents:
2543
+ if isinstance(content, topologic.Aperture):
2544
+ content = Aperture.Topology(content)
2206
2545
  if useInternalVertex == True:
2207
2546
  vst2 = Topology.InternalVertex(content, tolerance)
2208
2547
  else:
@@ -2244,6 +2583,8 @@ class Graph:
2244
2583
  contents = []
2245
2584
  _ = aFace.Contents(contents)
2246
2585
  for content in contents:
2586
+ if isinstance(content, topologic.Aperture):
2587
+ content = Aperture.Topology(content)
2247
2588
  if useInternalVertex == True:
2248
2589
  vst = Topology.InternalVertex(content, tolerance)
2249
2590
  else:
@@ -2388,6 +2729,8 @@ class Graph:
2388
2729
  contents = []
2389
2730
  _ = exteriorTopology.Contents(contents)
2390
2731
  for content in contents:
2732
+ if isinstance(content, topologic.Aperture):
2733
+ content = Aperture.Topology(content)
2391
2734
  if useInternalVertex == True:
2392
2735
  vst2 = Topology.InternalVertex(content, tolerance)
2393
2736
  else:
@@ -2429,6 +2772,8 @@ class Graph:
2429
2772
  contents = []
2430
2773
  _ = topology.Contents(contents)
2431
2774
  for content in contents:
2775
+ if isinstance(content, topologic.Aperture):
2776
+ content = Aperture.Topology(content)
2432
2777
  if useInternalVertex == True:
2433
2778
  vst = Topology.InternalVertex(content, tolerance)
2434
2779
  else:
@@ -2590,6 +2935,8 @@ class Graph:
2590
2935
  contents = []
2591
2936
  _ = sharedTopology.Contents(contents)
2592
2937
  for content in contents:
2938
+ if isinstance(content, topologic.Aperture):
2939
+ content = Aperture.Topology(content)
2593
2940
  if useInternalVertex == True:
2594
2941
  vst2 = Topology.InternalVertex(content, tolerance)
2595
2942
  else:
@@ -2639,6 +2986,8 @@ class Graph:
2639
2986
  contents = []
2640
2987
  _ = vst.Contents(contents)
2641
2988
  for content in contents:
2989
+ if isinstance(content, topologic.Aperture):
2990
+ content = Aperture.Topology(content)
2642
2991
  if useInternalVertex == True:
2643
2992
  vst2 = Topology.InternalVertex(content, tolerance)
2644
2993
  else:
@@ -2680,6 +3029,8 @@ class Graph:
2680
3029
  contents = []
2681
3030
  _ = anEdge.Contents(contents)
2682
3031
  for content in contents:
3032
+ if isinstance(content, topologic.Aperture):
3033
+ content = Aperture.Topology(content)
2683
3034
  if useInternalVertex == True:
2684
3035
  vst = Topology.InternalVertex(content, tolerance)
2685
3036
  else:
@@ -2830,6 +3181,8 @@ class Graph:
2830
3181
  contents = []
2831
3182
  _ = vst.Contents(contents)
2832
3183
  for content in contents:
3184
+ if isinstance(content, topologic.Aperture):
3185
+ content = Aperture.Topology(content)
2833
3186
  if useInternalVertex == True:
2834
3187
  vst2 = Topology.InternalVertex(content, tolerance)
2835
3188
  else:
@@ -2880,6 +3233,8 @@ class Graph:
2880
3233
  contents = []
2881
3234
  _ = topology.Contents(contents)
2882
3235
  for content in contents:
3236
+ if isinstance(content, topologic.Aperture):
3237
+ content = Aperture.Topology(content)
2883
3238
  if useInternalVertex == True:
2884
3239
  vst = Topology.InternalVertex(content, tolerance)
2885
3240
  else:
@@ -2929,7 +3284,6 @@ class Graph:
2929
3284
  if not isinstance(topology, topologic.Topology):
2930
3285
  print("Graph.ByTopology - Error: The input topology is not a valid topology. Returning None.")
2931
3286
  return None
2932
- topology = Topology.Copy(topology)
2933
3287
  graph = None
2934
3288
  item = [topology, None, None, None, direct, directApertures, viaSharedTopologies, viaSharedApertures, toExteriorTopologies, toExteriorApertures, toContents, None, useInternalVertex, storeBRep, tolerance]
2935
3289
  vertices = []
@@ -3699,6 +4053,159 @@ class Graph:
3699
4053
  except:
3700
4054
  return False
3701
4055
 
4056
+ @staticmethod
4057
+ def ExportToBOT(graph,
4058
+ path,
4059
+ format="turtle",
4060
+ overwrite = False,
4061
+ bidirectional=False,
4062
+ includeAttributes=False,
4063
+ includeLabel=False,
4064
+ siteLabel = "Site_0001",
4065
+ siteDictionary = None,
4066
+ buildingLabel = "Building_0001",
4067
+ buildingDictionary = None ,
4068
+ storeyPrefix = "Storey",
4069
+ floorLevels =[],
4070
+ labelKey="label",
4071
+ typeKey="type",
4072
+ sourceKey="source",
4073
+ targetKey="target",
4074
+ spaceType = "space",
4075
+ wallType = "wall",
4076
+ slabType = "slab",
4077
+ doorType = "door",
4078
+ windowType = "window",
4079
+ contentType = "content",
4080
+ ):
4081
+
4082
+ """
4083
+ Returns an RDF graph serialized string according to the BOT ontology. See https://w3c-lbd-cg.github.io/bot/.
4084
+
4085
+ Parameters
4086
+ ----------
4087
+ graph : topologic.Graph
4088
+ The input graph.
4089
+ format : str , optional
4090
+ The desired output format, the options are listed below. Thde default is "turtle".
4091
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
4092
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
4093
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
4094
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
4095
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
4096
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
4097
+ trix : Trix , RDF/XML-like format for RDF quads
4098
+ nquads : N-Quads , N-Triples-like format for RDF quads
4099
+ path : str
4100
+ The desired path to where the RDF/BOT file will be saved.
4101
+ overwrite : bool , optional
4102
+ If set to True, any existing file is overwritten. Otherwise, it is not. The default is False.
4103
+ bidirectional : bool , optional
4104
+ If set to True, reverse relationships are created wherever possible. Otherwise, they are not. The default is False.
4105
+ includeAttributes : bool , optional
4106
+ If set to True, the attributes associated with vertices in the graph are written out. Otherwise, they are not. The default is False.
4107
+ includeLabel : bool , optional
4108
+ If set to True, a label is attached to each node. Otherwise, it is not. The default is False.
4109
+ siteLabel : str , optional
4110
+ The desired site label. The default is "Site_0001".
4111
+ siteDictionary : dict , optional
4112
+ The dictionary of site attributes to include in the output. The default is None.
4113
+ buildingLabel : str , optional
4114
+ The desired building label. The default is "Building_0001".
4115
+ buildingDictionary : dict , optional
4116
+ The dictionary of building attributes to include in the output. The default is None.
4117
+ storeyPrefix : str , optional
4118
+ The desired prefixed to use for each building storey. The default is "Storey".
4119
+ floorLevels : list , optional
4120
+ The list of floor levels. This should be a numeric list, sorted from lowest to highest.
4121
+ If not provided, floorLevels will be computed automatically based on the nodes' 'z' attribute.
4122
+ typeKey : str , optional
4123
+ The dictionary key to use to look up the type of the node. The default is "type".
4124
+ labelKey : str , optional
4125
+ The dictionary key to use to look up the label of the node. The default is "label".
4126
+ spaceType : str , optional
4127
+ The dictionary string value to use to look up nodes of type "space". The default is "space".
4128
+ wallType : str , optional
4129
+ The dictionary string value to use to look up nodes of type "wall". The default is "wall".
4130
+ slabType : str , optional
4131
+ The dictionary string value to use to look up nodes of type "slab". The default is "slab".
4132
+ doorType : str , optional
4133
+ The dictionary string value to use to look up nodes of type "door". The default is "door".
4134
+ windowType : str , optional
4135
+ The dictionary string value to use to look up nodes of type "window". The default is "window".
4136
+ contentType : str , optional
4137
+ The dictionary string value to use to look up nodes of type "content". The default is "contents".
4138
+ format : str , optional
4139
+ The desired output format, the options are listed below. Thde default is "turtle".
4140
+ turtle, ttl or turtle2 : Turtle, turtle2 is just turtle with more spacing & linebreaks
4141
+ xml or pretty-xml : RDF/XML, Was the default format, rdflib < 6.0.0
4142
+ json-ld : JSON-LD , There are further options for compact syntax and other JSON-LD variants
4143
+ ntriples, nt or nt11 : N-Triples , nt11 is exactly like nt, only utf8 encoded
4144
+ n3 : Notation-3 , N3 is a superset of Turtle that also caters for rules and a few other things
4145
+ trig : Trig , Turtle-like format for RDF triples + context (RDF quads) and thus multiple graphs
4146
+ trix : Trix , RDF/XML-like format for RDF quads
4147
+ nquads : N-Quads , N-Triples-like format for RDF quads
4148
+
4149
+ Returns
4150
+ -------
4151
+ str
4152
+ The rdf graph serialized string using the BOT ontology.
4153
+ """
4154
+ from os.path import exists
4155
+ bot_graph = Graph.BOTGraph(graph,
4156
+ bidirectional=bidirectional,
4157
+ includeAttributes=includeAttributes,
4158
+ includeLabel=includeLabel,
4159
+ siteLabel=siteLabel,
4160
+ siteDictionary=siteDictionary,
4161
+ buildingLabel=buildingLabel,
4162
+ buildingDictionary=buildingDictionary,
4163
+ storeyPrefix=storeyPrefix,
4164
+ floorLevels=floorLevels,
4165
+ labelKey=labelKey,
4166
+ typeKey=typeKey,
4167
+ spaceType = spaceType,
4168
+ wallType = wallType,
4169
+ slabType = slabType,
4170
+ doorType = doorType,
4171
+ windowType = windowType,
4172
+ contentType = contentType
4173
+ )
4174
+ if "turtle" in format.lower() or "ttl" in format.lower() or "turtle2" in format.lower():
4175
+ ext = ".ttl"
4176
+ elif "xml" in format.lower() or "pretty=xml" in format.lower() or "rdf/xml" in format.lower():
4177
+ ext = ".xml"
4178
+ elif "json" in format.lower():
4179
+ ext = ".json"
4180
+ elif "ntriples" in format.lower() or "nt" in format.lower() or "nt11" in format.lower():
4181
+ ext = ".nt"
4182
+ elif "n3" in format.lower() or "notation" in format.lower():
4183
+ ext = ".n3"
4184
+ elif "trig" in format.lower():
4185
+ ext = ".trig"
4186
+ elif "trix" in format.lower():
4187
+ ext = ".trix"
4188
+ elif "nquads" in format.lower():
4189
+ ext = ".nquads"
4190
+ else:
4191
+ format = "turtle"
4192
+ ext = ".ttl"
4193
+ n = len(ext)
4194
+ # Make sure the file extension is .brep
4195
+ ext = path[len(path)-n:len(path)]
4196
+ if ext.lower() != ext:
4197
+ path = path+ext
4198
+ if not overwrite and exists(path):
4199
+ print("Graph.ExportToBOT - Error: a file already exists at the specified path and overwrite is set to False. Returning None.")
4200
+ return None
4201
+ status = False
4202
+ try:
4203
+ bot_graph.serialize(destination=path, format=format)
4204
+ status = True
4205
+ except:
4206
+ status = False
4207
+ return status
4208
+
3702
4209
  @staticmethod
3703
4210
  def ExportToCSV(graph, path, graphLabel, graphFeatures="",
3704
4211
  graphIDHeader="graph_id", graphLabelHeader="label", graphFeaturesHeader="feat",
@@ -4409,7 +4916,7 @@ class Graph:
4409
4916
  return True
4410
4917
 
4411
4918
  @staticmethod
4412
- def ExportToJSON(graph, path, vertexLabelKey="", edgeLabelKey="", indent=4, sortKeys=False, mantissa=6, overwrite=False):
4919
+ def ExportToJSON(graph, path, verticesKey="vertices", edgesKey="edges", vertexLabelKey="", edgeLabelKey="", xKey="x", yKey="y", zKey="z", indent=4, sortKeys=False, mantissa=6, overwrite=False):
4413
4920
  """
4414
4921
  Exports the input graph to a JSON file.
4415
4922
 
@@ -4419,12 +4926,22 @@ class Graph:
4419
4926
  The input graph.
4420
4927
  path : str
4421
4928
  The path to the JSON file.
4929
+ verticesKey : str , optional
4930
+ The desired key name to call vertices. The default is "vertices".
4931
+ edgesKey : str , optional
4932
+ The desired key name to call edges. The default is "edges".
4422
4933
  vertexLabelKey : str , optional
4423
4934
  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.
4424
4935
  Note: If vertex labels are not unique, they will be forced to be unique.
4425
4936
  edgeLabelKey : str , optional
4426
4937
  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.
4427
4938
  Note: If edge labels are not unique, they will be forced to be unique.
4939
+ xKey : str , optional
4940
+ The desired key name to use for x-coordinates. The default is "x".
4941
+ yKey : str , optional
4942
+ The desired key name to use for y-coordinates. The default is "y".
4943
+ zKey : str , optional
4944
+ The desired key name to use for z-coordinates. The default is "z".
4428
4945
  indent : int , optional
4429
4946
  The desired amount of indent spaces to use. The default is 4.
4430
4947
  sortKeys : bool , optional
@@ -4458,7 +4975,7 @@ class Graph:
4458
4975
  except:
4459
4976
  raise Exception("Graph.ExportToJSON - Error: Could not create a new file at the following location: "+path)
4460
4977
  if (f):
4461
- jsondata = Graph.JSONData(graph, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, mantissa=mantissa)
4978
+ jsondata = Graph.JSONData(graph, verticesKey=verticesKey, edgesKey=edgesKey, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, xKey=xKey, yKey=yKey, zKey=zKey, mantissa=mantissa)
4462
4979
  if jsondata != None:
4463
4980
  json.dump(jsondata, f, indent=indent, sort_keys=sortKeys)
4464
4981
  f.close()
@@ -5113,7 +5630,17 @@ class Graph:
5113
5630
  return vertices
5114
5631
 
5115
5632
  @staticmethod
5116
- def JSONData(graph, vertexLabelKey="", edgeLabelKey="", mantissa=6):
5633
+ def JSONData(graph,
5634
+ verticesKey="vertices",
5635
+ edgesKey="edges",
5636
+ vertexLabelKey="",
5637
+ edgeLabelKey="",
5638
+ sourceKey="source",
5639
+ targetKey="target",
5640
+ xKey="x",
5641
+ yKey="y",
5642
+ zKey="z",
5643
+ mantissa=6):
5117
5644
  """
5118
5645
  Converts the input graph into JSON data.
5119
5646
 
@@ -5121,12 +5648,26 @@ class Graph:
5121
5648
  ----------
5122
5649
  graph : topologic.Graph
5123
5650
  The input graph.
5651
+ verticesKey : str , optional
5652
+ The desired key name to call vertices. The default is "vertices".
5653
+ edgesKey : str , optional
5654
+ The desired key name to call edges. The default is "edges".
5124
5655
  vertexLabelKey : str , optional
5125
5656
  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.
5126
5657
  Note: If vertex labels are not unique, they will be forced to be unique.
5127
5658
  edgeLabelKey : str , optional
5128
5659
  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.
5129
5660
  Note: If edge labels are not unique, they will be forced to be unique.
5661
+ sourceKey : str , optional
5662
+ The dictionary key used to store the source vertex. The default is "source".
5663
+ targetKey : str , optional
5664
+ The dictionary key used to store the target vertex. The default is "source".
5665
+ xKey : str , optional
5666
+ The desired key name to use for x-coordinates. The default is "x".
5667
+ yKey : str , optional
5668
+ The desired key name to use for y-coordinates. The default is "y".
5669
+ zKey : str , optional
5670
+ The desired key name to use for z-coordinates. The default is "z".
5130
5671
  mantissa : int , optional
5131
5672
  The desired length of the mantissa. The default is 6.
5132
5673
 
@@ -5144,16 +5685,16 @@ class Graph:
5144
5685
 
5145
5686
  vertices = Graph.Vertices(graph)
5146
5687
  j_data = {}
5147
- j_data['nodes'] = {}
5148
- j_data['edges'] = {}
5688
+ j_data[verticesKey] = {}
5689
+ j_data[edgesKey] = {}
5149
5690
  n = max(len(str(len(vertices))), 4)
5150
5691
  v_labels = []
5151
5692
  v_dicts = []
5152
5693
  for i, v in enumerate(vertices):
5153
5694
  d = Topology.Dictionary(v)
5154
- d = Dictionary.SetValueAtKey(d, "x", Vertex.X(v, mantissa=mantissa))
5155
- d = Dictionary.SetValueAtKey(d, "y", Vertex.Y(v, mantissa=mantissa))
5156
- d = Dictionary.SetValueAtKey(d, "z", Vertex.Z(v, mantissa=mantissa))
5695
+ d = Dictionary.SetValueAtKey(d, xKey, Vertex.X(v, mantissa=mantissa))
5696
+ d = Dictionary.SetValueAtKey(d, yKey, Vertex.Y(v, mantissa=mantissa))
5697
+ d = Dictionary.SetValueAtKey(d, zKey, Vertex.Z(v, mantissa=mantissa))
5157
5698
  v_dict = Dictionary.PythonDictionary(d)
5158
5699
  v_label = Dictionary.ValueAtKey(d, vertexLabelKey)
5159
5700
  if isinstance(v_label, str):
@@ -5164,7 +5705,7 @@ class Graph:
5164
5705
  v_dicts.append(v_dict)
5165
5706
  v_labels = Helper.MakeUnique(v_labels)
5166
5707
  for i, v_label in enumerate(v_labels):
5167
- j_data['nodes'][v_label] = v_dicts[i]
5708
+ j_data[verticesKey][v_label] = v_dicts[i]
5168
5709
 
5169
5710
  edges = Graph.Edges(graph)
5170
5711
  n = len(str(len(edges)))
@@ -5179,8 +5720,8 @@ class Graph:
5179
5720
  ev_label = v_labels[evi]
5180
5721
  d = Topology.Dictionary(e)
5181
5722
 
5182
- d = Dictionary.SetValueAtKey(d, "source", sv_label)
5183
- d = Dictionary.SetValueAtKey(d, "target", ev_label)
5723
+ d = Dictionary.SetValueAtKey(d, sourceKey, sv_label)
5724
+ d = Dictionary.SetValueAtKey(d, targetKey, ev_label)
5184
5725
  e_dict = Dictionary.PythonDictionary(d)
5185
5726
  e_label = Dictionary.ValueAtKey(d, edgeLabelKey)
5186
5727
  if isinstance(e_label, str):
@@ -5191,12 +5732,22 @@ class Graph:
5191
5732
  e_dicts.append(e_dict)
5192
5733
  e_labels = Helper.MakeUnique(e_labels)
5193
5734
  for i, e_label in enumerate(e_labels):
5194
- j_data['edges'][e_label] = e_dicts[i]
5735
+ j_data[edgesKey][e_label] = e_dicts[i]
5195
5736
 
5196
5737
  return j_data
5197
5738
 
5198
5739
  @staticmethod
5199
- def JSONString(graph, vertexLabelKey="", edgeLabelKey="", indent=4, sortKeys=False, mantissa=6):
5740
+ def JSONString(graph,
5741
+ verticesKey="vertices",
5742
+ edgesKey="edges",
5743
+ vertexLabelKey="",
5744
+ edgeLabelKey="",
5745
+ xKey = "x",
5746
+ yKey = "y",
5747
+ zKey = "z",
5748
+ indent=4,
5749
+ sortKeys=False,
5750
+ mantissa=6):
5200
5751
  """
5201
5752
  Converts the input graph into JSON data.
5202
5753
 
@@ -5204,12 +5755,22 @@ class Graph:
5204
5755
  ----------
5205
5756
  graph : topologic.Graph
5206
5757
  The input graph.
5758
+ verticesKey : str , optional
5759
+ The desired key name to call vertices. The default is "vertices".
5760
+ edgesKey : str , optional
5761
+ The desired key name to call edges. The default is "edges".
5207
5762
  vertexLabelKey : str , optional
5208
5763
  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.
5209
5764
  Note: If vertex labels are not unique, they will be forced to be unique.
5210
5765
  edgeLabelKey : str , optional
5211
5766
  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.
5212
5767
  Note: If edge labels are not unique, they will be forced to be unique.
5768
+ xKey : str , optional
5769
+ The desired key name to use for x-coordinates. The default is "x".
5770
+ yKey : str , optional
5771
+ The desired key name to use for y-coordinates. The default is "y".
5772
+ zKey : str , optional
5773
+ The desired key name to use for z-coordinates. The default is "z".
5213
5774
  indent : int , optional
5214
5775
  The desired amount of indent spaces to use. The default is 4.
5215
5776
  sortKeys : bool , optional
@@ -5224,7 +5785,7 @@ class Graph:
5224
5785
 
5225
5786
  """
5226
5787
  import json
5227
- json_data = Graph.JSONData(graph, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, mantissa=mantissa)
5788
+ json_data = Graph.JSONData(graph, verticesKey=verticesKey, edgesKey=edgesKey, vertexLabelKey=vertexLabelKey, edgeLabelKey=edgeLabelKey, xKey=xKey, yKey=yKey, zKey=zKey, mantissa=mantissa)
5228
5789
  json_string = json.dumps(json_data, indent=indent, sort_keys=sortKeys)
5229
5790
  return json_string
5230
5791