topologicpy 0.4.94__py3-none-any.whl → 0.4.96__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/Topology.py CHANGED
@@ -129,6 +129,7 @@ class WorkerProcess(Process):
129
129
  self.tolerance = tolerance
130
130
 
131
131
  def run(self):
132
+ from topologicpy.Vertex import Vertex
132
133
  for sink_item in self.sinks:
133
134
  sink = Topology.ByBREPString(sink_item.sink_str)
134
135
  sinkKeys = []
@@ -138,9 +139,9 @@ class WorkerProcess(Process):
138
139
  source = Topology.ByBREPString(source_str)
139
140
  flag = False
140
141
  if isinstance(source, topologic.Vertex):
141
- flag = Topology.IsInternal(sink, source, self.tolerance)
142
+ flag = Vertex.IsInternal(source, sink, self.tolerance)
142
143
  else:
143
- flag = Topology.IsInternal(source, iv, self.tolerance)
144
+ flag = Vertex.IsInternal(iv, source, self.tolerance)
144
145
  if flag:
145
146
  d = Dictionary.ByPythonDictionary(self.so_dicts[j])
146
147
  if d == None:
@@ -883,7 +884,273 @@ class Topology():
883
884
  See Topology.Boolean().
884
885
 
885
886
  """
886
- return Topology.Boolean(topologyA=topologyA, topologyB=topologyB, operation="intersect", tranDict=tranDict, tolerance=tolerance)
887
+ from topologicpy.Vertex import Vertex
888
+ from topologicpy.Cluster import Cluster
889
+ # Sort the two topologies by their type from lower to higher so comparison can be eased.
890
+ if Topology.Type(topologyB) < Topology.Type(topologyA):
891
+ temp = topologyA
892
+ topologyA = topologyB
893
+ topologyB = temp
894
+ # Vertex:
895
+ if isinstance(topologyA, topologic.Vertex):
896
+ # Vertex:
897
+ if isinstance(topologyB, topologic.Vertex):
898
+ if Vertex.Distance(topologyA, topologyB) < tolerance:
899
+ return topologyA
900
+ else:
901
+ return None
902
+ # Edge/Wire/Face/Shell/Cell/CellComplex:
903
+ elif Topology.Type(topologyB) < 256:
904
+ if Vertex.IsInternal(topologyA, topologyB):
905
+ return topologyA
906
+ else:
907
+ return None
908
+ # Cluster:
909
+ elif isinstance(topologyB, topologic.Cluster):
910
+ free_topologies = Cluster.FreeTopologies(topologyB)
911
+ for f_t in free_topologies:
912
+ if not Topology.Intersect(topologyA, f_t) == None:
913
+ return topologyA
914
+ return None
915
+ # Edge:
916
+ elif isinstance(topologyA, topologic.Edge):
917
+ if isinstance(topologyB, topologic.Shell):
918
+ vertices = Topology.Vertices(topologyB)
919
+ edges = Topology.Edges(topologyB)
920
+ faces = Topology.Faces(topologyB)
921
+ intersections = [topologyA.Intersect(x) for x in vertices]
922
+ intersections += [topologyA.Intersect(x) for x in edges]
923
+ intersections += [topologyA.Intersect(x) for x in faces]
924
+ intersections = [x for x in intersections if not x == None]
925
+ if len(intersections) == 0:
926
+ return None
927
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
928
+ elif isinstance(topologyB, topologic.CellComplex):
929
+ vertices = Topology.Vertices(topologyB)
930
+ edges = Topology.Edges(topologyB)
931
+ faces = Topology.Faces(topologyB)
932
+ cells = Topology.Cells(topologyB)
933
+ intersections = [topologyA.Intersect(x) for x in vertices]
934
+ intersections += [topologyA.Intersect(x) for x in edges]
935
+ intersections += [topologyA.Intersect(x) for x in faces]
936
+ intersections += [topologyA.Intersect(x) for x in cells]
937
+ intersections = [x for x in intersections if not x == None]
938
+ if len(intersections) == 0:
939
+ return None
940
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
941
+ elif isinstance(topologyB, topologic.Cluster):
942
+ free_topologies = Cluster.FreeTopologies(topologyB)
943
+ intersections = []
944
+ for f_t in free_topologies:
945
+ intersections.append(Topology.Intersect(topologyA, f_t))
946
+ intersections = [x for x in intersections if not x == None]
947
+ if len(intersections) == 0:
948
+ return None
949
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
950
+ else:
951
+ return topologyA.Intersect(topologyB)
952
+ # Wire:
953
+ elif isinstance(topologyA, topologic.Wire):
954
+ if isinstance(topologyB, topologic.Face):
955
+ edges = Topology.Edges(topologyA)
956
+ intersections = []
957
+ for edge in edges:
958
+ intersections.append(Topology.Intersect(edge, topologyB))
959
+ intersections = [x for x in intersections if not x == None]
960
+ if len(intersections) == 0:
961
+ return None
962
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
963
+ elif isinstance(topologyB, topologic.Wire):
964
+ edges_a = Topology.Edges(topologyA)
965
+ intersections = []
966
+ for edge_a in edges_a:
967
+ vertices = Topology.Vertices(topologyB)
968
+ edges = Topology.Edges(topologyB)
969
+ intersections += [edge_a.Intersect(x) for x in vertices]
970
+ intersections += [edge_a.Intersect(x) for x in edges]
971
+ intersections = [x for x in intersections if not x == None]
972
+ if len(intersections) == 0:
973
+ return None
974
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
975
+ elif isinstance(topologyB, topologic.Shell):
976
+ edges_a = Topology.Edges(topologyA)
977
+ intersections = []
978
+ for edge_a in edges_a:
979
+ vertices = Topology.Vertices(topologyB)
980
+ edges = Topology.Edges(topologyB)
981
+ faces = Topology.Faces(topologyB)
982
+ intersections += [edge_a.Intersect(x) for x in vertices]
983
+ intersections += [edge_a.Intersect(x) for x in edges]
984
+ intersections += [edge_a.Intersect(x) for x in faces]
985
+ intersections = [x for x in intersections if not x == None]
986
+ if len(intersections) == 0:
987
+ return None
988
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
989
+ elif isinstance(topologyB, topologic.Cell):
990
+ edges = Topology.Edges(topologyA)
991
+ intersections = []
992
+ for edge in edges:
993
+ intersections.append(Topology.Intersect(edge, topologyB))
994
+ intersections = [x for x in intersections if not x == None]
995
+ if len(intersections) == 0:
996
+ return None
997
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
998
+ elif isinstance(topologyB, topologic.CellComplex):
999
+ edges = Topology.Edges(topologyA)
1000
+ intersections = []
1001
+ for edge in edges:
1002
+ intersections.append(Topology.Intersect(edge, topologyB))
1003
+ intersections = [x for x in intersections if not x == None]
1004
+ if len(intersections) == 0:
1005
+ return None
1006
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1007
+ elif isinstance(topologyB, topologic.Cluster):
1008
+ free_topologies = Cluster.FreeTopologies(topologyB)
1009
+ intersections = []
1010
+ for f_t in free_topologies:
1011
+ intersections.append(Topology.Intersect(topologyA, f_t))
1012
+ intersections = [x for x in intersections if not x == None]
1013
+ if len(intersections) == 0:
1014
+ return None
1015
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1016
+ # Face:
1017
+ elif isinstance(topologyA, topologic.Face):
1018
+ if isinstance(topologyB, topologic.Face):
1019
+ return Topology.SelfMerge(topologyA.Intersect(topologyB), tolerance=tolerance)
1020
+ elif isinstance(topologyB, topologic.Shell):
1021
+ intersections = []
1022
+ faces = Topology.Faces(topologyB)
1023
+ for face in faces:
1024
+ inter = Topology.Intersect(topologyA, face)
1025
+ if isinstance(inter, topologic.Cluster):
1026
+ inter = Topology.SelfMerge(inter, tolerance=tolerance)
1027
+ intersections.append(inter)
1028
+ intersections = [x for x in intersections if not x == None]
1029
+ if len(intersections) == 0:
1030
+ return None
1031
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1032
+ elif isinstance(topologyB, topologic.Cell):
1033
+ diff1 = Topology.Difference(topologyA, topologyB)
1034
+ if diff1 == None:
1035
+ return topologyA
1036
+ else:
1037
+ return Topology.Difference(topologyA,diff1)
1038
+ elif isinstance(topologyB, topologic.CellComplex):
1039
+ cells = Topology.Cells(topologyB)
1040
+ intersections = []
1041
+ for cell in cells:
1042
+ intersections.append(Topology.Intersect(topologyA, cell))
1043
+ intersections = [x for x in intersections if not x == None]
1044
+ if len(intersections) == 0:
1045
+ return None
1046
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1047
+ elif isinstance(topologyB, topologic.Cluster):
1048
+ free_topologies = Cluster.FreeTopologies(topologyB)
1049
+ intersections = []
1050
+ for f_t in free_topologies:
1051
+ intersections.append(Topology.Intersect(topologyA, f_t))
1052
+ intersections = [x for x in intersections if not x == None]
1053
+ if len(intersections) == 0:
1054
+ return None
1055
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1056
+ else:
1057
+ return Topology.SelfMerge(topologyA.Intersect(topologyB), tolerance=tolerance)
1058
+ # Shell:
1059
+ elif isinstance(topologyA, topologic.Shell):
1060
+ if isinstance(topologyB, topologic.Shell) or isinstance(topologyB, topologic.Cell) or isinstance(topologyB, topologic.CellComplex):
1061
+ intersections = []
1062
+ faces = Topology.Faces(topologyA)
1063
+ for face in faces:
1064
+ inter = Topology.Intersect(face, topologyB)
1065
+ if isinstance(inter, topologic.Cluster):
1066
+ inter = Topology.SelfMerge(inter, tolerance=tolerance)
1067
+ intersections.append(inter)
1068
+ intersections = [x for x in intersections if not x == None]
1069
+ if len(intersections) == 0:
1070
+ return None
1071
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1072
+ elif isinstance(topologyB, topologic.Cluster):
1073
+ free_topologies = Cluster.FreeTopologies(topologyB)
1074
+ intersections = []
1075
+ for f_t in free_topologies:
1076
+ intersections.append(Topology.Intersect(topologyA, f_t))
1077
+ intersections = [x for x in intersections if not x == None]
1078
+ if len(intersections) == 0:
1079
+ return None
1080
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1081
+ # Cell:
1082
+ elif isinstance(topologyA, topologic.Cell):
1083
+ if isinstance(topologyB, topologic.Cell) or isinstance(topologyB, topologic.CellComplex):
1084
+ vertices = Topology.Vertices(topologyA)
1085
+ edges = Topology.Edges(topologyA)
1086
+ faces = Topology.Faces(topologyA)
1087
+ subs = vertices + edges + faces
1088
+ if isinstance(topologyB, topologic.Topology):
1089
+ diff1 = Topology.Difference(topologyA,topologyB)
1090
+ else:
1091
+ diff1 = topologyA
1092
+ if isinstance(diff1, topologic.Topology):
1093
+ diff2 = Topology.Difference(topologyA, diff1)
1094
+ else:
1095
+ diff2 = topologyA
1096
+ intersections = []
1097
+ if not diff2 == None:
1098
+ intersections.append(diff2)
1099
+ for i, sub in enumerate(subs):
1100
+ inter = Topology.Intersect(sub, topologyB)
1101
+ if isinstance(inter, topologic.Cluster):
1102
+ inter = Topology.SelfMerge(inter, tolerance=tolerance)
1103
+ intersections.append(inter)
1104
+ intersections = [x for x in intersections if not x == None]
1105
+ if len(intersections) == 0:
1106
+ return None
1107
+ return Topology.SelfMerge(Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance), tolerance=tolerance) # Hack to return proper topology type
1108
+ elif isinstance(topologyB, topologic.Cluster):
1109
+ free_topologies = Cluster.FreeTopologies(topologyB)
1110
+ intersections = []
1111
+ for f_t in free_topologies:
1112
+ intersections.append(Topology.Intersect(topologyA, f_t))
1113
+ intersections = [x for x in intersections if not x == None]
1114
+ if len(intersections) == 0:
1115
+ return None
1116
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1117
+ # CellComplex:
1118
+ elif isinstance(topologyA, topologic.CellComplex):
1119
+ if isinstance(topologyB, topologic.CellComplex):
1120
+ intersections = []
1121
+ cells_a = Topology.Cells(topologyA)
1122
+ cells_b = Topology.Cells(topologyB)
1123
+ for cell_a in cells_a:
1124
+ for cell_b in cells_b:
1125
+ intersections.append(Topology.Intersect(cell_a, cell_b))
1126
+ intersections = [x for x in intersections if not x == None]
1127
+ if len(intersections) == 0:
1128
+ return None
1129
+ return Topology.SelfMerge(Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance), tolerance=tolerance) # Hack to return proper topology type
1130
+ elif isinstance(topologyB, topologic.Cluster):
1131
+ free_topologies = Cluster.FreeTopologies(topologyB)
1132
+ intersections = []
1133
+ for f_t in free_topologies:
1134
+ intersections.append(Topology.Intersect(topologyA, f_t))
1135
+ intersections = [x for x in intersections if not x == None]
1136
+ if len(intersections) == 0:
1137
+ return None
1138
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1139
+ # Cluster:
1140
+ elif isinstance(topologyA, topologic.Cluster):
1141
+ if isinstance(topologyB, topologic.Cluster):
1142
+ free_topologies_a = Cluster.FreeTopologies(topologyA)
1143
+ free_topologies_b = Cluster.FreeTopologies(topologyB)
1144
+ intersections = []
1145
+ for f_t_a in free_topologies_a:
1146
+ for f_t_b in free_topologies_b:
1147
+ intersections.append(Topology.Intersect(f_t_a, f_t_b))
1148
+ intersections = [x for x in intersections if not x == None]
1149
+ if len(intersections) == 0:
1150
+ return None
1151
+ return Topology.SelfMerge(Cluster.ByTopologies(intersections), tolerance=tolerance)
1152
+ else:
1153
+ return topologyA.Intersect(topologyB)
887
1154
 
888
1155
  @staticmethod
889
1156
  def SymmetricDifference(topologyA, topologyB, tranDict=False, tolerance=0.0001):
@@ -980,6 +1247,9 @@ class Topology():
980
1247
  return None
981
1248
  if not isinstance(topologyB, topologic.Topology):
982
1249
  print("Topology.Boolean - Error: the input topologyB parameter is not a valid topology. Returning None.")
1250
+ print("TopologyA:", topologyA)
1251
+ print("TopologyB:", topologyB)
1252
+ Topology.Show(topologyA, renderer="offline")
983
1253
  return None
984
1254
  if not isinstance(operation, str):
985
1255
  print("Topology.Boolean - Error: the input operation parameter is not a valid string. Returning None.")
@@ -996,8 +1266,9 @@ class Topology():
996
1266
  topologyC = topologyA.Union(topologyB, False)
997
1267
  elif operation.lower() == "difference":
998
1268
  topologyC = topologyA.Difference(topologyB, False)
999
- elif operation.lower() == "intersect":
1000
- topologyC = topologyA.Intersect(topologyB, False)
1269
+ elif operation.lower() == "intersect": #Intersect in Topologic (Core) is faulty. This is a workaround.
1270
+ #topologyC = topologyA.Intersect(topologyB, False)
1271
+ topologyC = Topology.Intersect(topologyA, topologyB)
1001
1272
  elif operation.lower() == "symdif":
1002
1273
  topologyC = topologyA.XOR(topologyB, False)
1003
1274
  elif operation.lower() == "merge":
@@ -1403,8 +1674,11 @@ class Topology():
1403
1674
  if len(faceEdges) > 2:
1404
1675
  faceWire = Wire.ByEdges(faceEdges, tolerance=tolerance)
1405
1676
  try:
1406
- topFace = Face.ByWire(faceWire, tolerance=tolerance)
1407
- topFaces.append(topFace)
1677
+ topFace = Face.ByWire(faceWire, tolerance=tolerance, silent=True)
1678
+ if isinstance(topFace, topologic.Face):
1679
+ topFaces.append(topFace)
1680
+ elif isinstance(topFace, list):
1681
+ topFaces += topFace
1408
1682
  except:
1409
1683
  pass
1410
1684
  if len(topFaces) > 0:
@@ -2227,7 +2501,7 @@ class Topology():
2227
2501
  topology = Topology.ByGeometry(vertices = vertices, faces = faces, outputMode="default", tolerance=tolerance)
2228
2502
  if transposeAxes == True:
2229
2503
  topology = Topology.Rotate(topology, Vertex.Origin(), 1,0,0,90)
2230
- return topology
2504
+ return Topology.SelfMerge(topology)
2231
2505
  print("Topology.ByOBJString - Error: Could not find vertices or faces. Returning None.")
2232
2506
  return None
2233
2507
 
@@ -3690,6 +3964,7 @@ class Topology():
3690
3964
  lines = []
3691
3965
  version = Helper.Version()
3692
3966
  lines.append("# topologicpy "+version)
3967
+ topology = Topology.Triangulate(topology, tolerance=tolerance)
3693
3968
  d = Topology.Geometry(topology, mantissa=mantissa)
3694
3969
  vertices = d['vertices']
3695
3970
  faces = d['faces']
@@ -3834,9 +4109,10 @@ class Topology():
3834
4109
  otherTopologies.append(aTopology)
3835
4110
  return {"filtered": filteredTopologies, "other": otherTopologies}
3836
4111
 
4112
+ @staticmethod
3837
4113
  def Flatten(topology, origin=None, direction=[0,0,1]):
3838
4114
  """
3839
- Flattens the input topology such that the input origin is located at the world origin and the input topology is rotated such that the input vector is pointed in the positive Z axis.
4115
+ Flattens the input topology such that the input origin is located at the world origin and the input topology is rotated such that the input vector is pointed in the Up direction (see Vector.Up()).
3840
4116
 
3841
4117
  Parameters
3842
4118
  ----------
@@ -3854,34 +4130,17 @@ class Topology():
3854
4130
 
3855
4131
  """
3856
4132
  from topologicpy.Vertex import Vertex
3857
- from topologicpy.Dictionary import Dictionary
4133
+ from topologicpy.Vector import Vector
3858
4134
 
3859
4135
  if not isinstance(topology, topologic.Topology):
3860
4136
  print("Topology.Flatten - Error: the input topology parameter is not a valid topology. Returning None.")
3861
4137
  return None
3862
- world_origin = Vertex.Origin()
3863
4138
  if origin == None:
3864
4139
  origin = Topology.Centroid(topology)
3865
- x1 = origin.X()
3866
- y1 = origin.Y()
3867
- z1 = origin.Z()
3868
- x2 = origin.X() + direction[0]
3869
- y2 = origin.Y() + direction[1]
3870
- z2 = origin.Z() + direction[2]
3871
- dx = x2 - x1
3872
- dy = y2 - y1
3873
- dz = z2 - z1
3874
- dist = math.sqrt(dx**2 + dy**2 + dz**2)
3875
- phi = math.degrees(math.atan2(dy, dx)) # Rotation around Y-Axis
3876
- if dist < 0.0001:
3877
- theta = 0
3878
- else:
3879
- theta = math.degrees(math.acos(dz/dist)) # Rotation around Z-Axis
3880
- flat_topology = Topology.Translate(topology, -origin.X(), -origin.Y(), -origin.Z())
3881
- flat_topology = Topology.Rotate(flat_topology, world_origin, 0, 0, 1, -phi)
3882
- flat_topology = Topology.Rotate(flat_topology, world_origin, 0, 1, 0, -theta)
3883
- d = Dictionary.ByKeysValues(['phi', 'theta', 'x', 'y', 'z'], [phi, theta, origin.X(), origin.Y(), origin.Z()])
3884
- flat_topology = Topology.SetDictionary(flat_topology, d)
4140
+ up = Vector.Up()
4141
+ flat_topology = Topology.Translate(topology, -Vertex.X(origin), -Vertex.Y(origin), -Vertex.Z(origin))
4142
+ tran_mat = Vector.TransformationMatrix(direction, up)
4143
+ flat_topology = Topology.Transform(flat_topology, tran_mat)
3885
4144
  return flat_topology
3886
4145
 
3887
4146
  @staticmethod
@@ -4090,106 +4349,6 @@ class Topology():
4090
4349
  vst = Topology.Centroid(topology)
4091
4350
  return vst
4092
4351
 
4093
- @staticmethod
4094
- def IsInside(topology, vertex, tolerance=0.0001):
4095
- """
4096
- DEPRECATED METHOD. DO NOT USE. INSTEAD USE Topology.IsInternal.
4097
- """
4098
- print("Topology.IsInside - Warning: Deprecated method. This method will be removed in the future. Instead, use Topology.IsInternal.")
4099
- return Topology.IsInternal(topology=topology, vertex=vertex, tolerance=tolerance)
4100
-
4101
- @staticmethod
4102
- def IsInternal(topology, vertex, tolerance=0.0001):
4103
- """
4104
- Returns True if the input vertex is an internal vertex of the input topology. Returns False otherwise.
4105
-
4106
- Parameters
4107
- ----------
4108
- topology : topologic.Topology
4109
- The input topology.
4110
- vertex : topologic.Vertex
4111
- The input Vertex.
4112
- tolerance : float , optional
4113
- The desired tolerance. The default is 0.0001.
4114
-
4115
- Returns
4116
- -------
4117
- bool
4118
- True if the input vertex is inside the input topology. False otherwise.
4119
-
4120
- """
4121
- from topologicpy.Vertex import Vertex
4122
- from topologicpy.Edge import Edge
4123
- from topologicpy.Wire import Wire
4124
- from topologicpy.Face import Face
4125
- from topologicpy.Cell import Cell
4126
- from topologicpy.Shell import Shell
4127
- from topologicpy.CellComplex import CellComplex
4128
- from topologicpy.Cluster import Cluster
4129
-
4130
- if not isinstance(topology, topologic.Topology):
4131
- print("Topology.IsInternal - Error: the input topology parameter is not a valid topology. Returning None.")
4132
- return None
4133
- if not isinstance(vertex, topologic.Vertex):
4134
- print("Topology.IsInternal - Error: the input vertex parameter is not a valid vertex. Returning None.")
4135
- return None
4136
- is_internal = False
4137
- if topology.Type() == topologic.Vertex.Type():
4138
- try:
4139
- is_internal = (Vertex.Distance(vertex, topology) <= tolerance)
4140
- except:
4141
- is_internal = False
4142
- return is_internal
4143
- elif topology.Type() == topologic.Edge.Type():
4144
- u = Edge.ParameterAtVertex(topology, vertex)
4145
- d = Vertex.Distance(vertex, topology)
4146
- if not u == None:
4147
- is_internal = (0 <= u <= 1) and (d <= tolerance)
4148
- else:
4149
- is_internal = False
4150
- return is_internal
4151
- elif topology.Type() == topologic.Wire.Type():
4152
- edges = Wire.Edges(topology)
4153
- for edge in edges:
4154
- is_internal = (Vertex.Distance(vertex, edge) <= tolerance)
4155
- if is_internal:
4156
- return is_internal
4157
- elif topology.Type() == topologic.Face.Type():
4158
- return Face.IsInternal(topology, vertex, tolerance)
4159
- elif topology.Type() == topologic.Shell.Type():
4160
- faces = Shell.Faces(topology)
4161
- for face in faces:
4162
- is_internal = Face.IsInternal(face, vertex, tolerance)
4163
- if is_internal:
4164
- return is_internal
4165
- elif topology.Type() == topologic.Cell.Type():
4166
- return Cell.IsInternal(topology, vertex, tolerance)
4167
- elif topology.Type() == topologic.CellComplex.Type():
4168
- cells = CellComplex.Cells(topology)
4169
- for cell in cells:
4170
- is_internal = Cell.IsInternal(cell, vertex, tolerance)
4171
- if is_internal:
4172
- return is_internal
4173
- elif topology.Type() == topologic.Cluster.Type():
4174
- cells = Cluster.Cells(topology)
4175
- faces = Cluster.Faces(topology)
4176
- edges = Cluster.Edges(topology)
4177
- vertices = Cluster.Vertices(topology)
4178
- subTopologies = []
4179
- if isinstance(cells, list):
4180
- subTopologies += cells
4181
- if isinstance(faces, list):
4182
- subTopologies += faces
4183
- if isinstance(edges, list):
4184
- subTopologies += edges
4185
- if isinstance(vertices, list):
4186
- subTopologies += vertices
4187
- for subTopology in subTopologies:
4188
- is_internal = Topology.IsInternal(subTopology, vertex, tolerance)
4189
- if is_internal:
4190
- return is_internal
4191
- return False
4192
-
4193
4352
  @staticmethod
4194
4353
  def IsPlanar(topology, tolerance=0.0001):
4195
4354
  """
@@ -4482,33 +4641,17 @@ class Topology():
4482
4641
 
4483
4642
  """
4484
4643
  from topologicpy.Vertex import Vertex
4644
+ from topologicpy.Vector import Vector
4485
4645
  if not isinstance(topology, topologic.Topology):
4486
4646
  print("Topology.Orient - Error: the input topology parameter is not a valid topology. Returning None.")
4487
4647
  return None
4488
4648
  if not isinstance(origin, topologic.Vertex):
4489
4649
  origin = Topology.Centroid(topology)
4490
- topology = Topology.Flatten(topology, origin=origin, direction=dirA)
4491
- x1 = origin.X()
4492
- y1 = origin.Y()
4493
- z1 = origin.Z()
4494
- x2 = origin.X() + dirB[0]
4495
- y2 = origin.Y() + dirB[1]
4496
- z2 = origin.Z() + dirB[2]
4497
- dx = x2 - x1
4498
- dy = y2 - y1
4499
- dz = z2 - z1
4500
- dist = math.sqrt(dx**2 + dy**2 + dz**2)
4501
- world_origin = Vertex.ByCoordinates(0,0,0)
4502
-
4503
- phi = math.degrees(math.atan2(dy, dx)) # Rotation around Y-Axis
4504
- if dist < 0.0001:
4505
- theta = 0
4506
- else:
4507
- theta = math.degrees(math.acos(dz/dist)) # Rotation around Z-Axis
4508
- returnTopology = Topology.Rotate(topology, world_origin, 0, 1, 0, theta)
4509
- returnTopology = Topology.Rotate(returnTopology, world_origin, 0, 0, 1, phi)
4510
- returnTopology = Topology.Place(returnTopology, world_origin, origin)
4511
- return returnTopology
4650
+ return_topology = Topology.Place(topology, originA=origin, originB=Vertex.Origin())
4651
+ tran_mat = Vector.TransformationMatrix(dirA, dirB)
4652
+ return_topology = Topology.Transform(return_topology, tran_mat)
4653
+ return_topology = Topology.Place(return_topology, originA=Vertex.Origin(), originB=origin)
4654
+ return return_topology
4512
4655
 
4513
4656
  @staticmethod
4514
4657
  def Place(topology, originA=None, originB=None):
@@ -4604,7 +4747,7 @@ class Topology():
4604
4747
  faces = Topology.Faces(topology)
4605
4748
  for face in faces:
4606
4749
  topologies.append(Face.RemoveCollinearEdges(topology, angTolerance=angTolerance, tolerance=tolerance))
4607
- return_topology = Topology.SelfMerge(Cluster.ByTopologies(topologies))
4750
+ return_topology = Topology.SelfMerge(Cluster.ByTopologies(topologies), tolerance=tolerance)
4608
4751
  return return_topology
4609
4752
 
4610
4753
  @staticmethod
@@ -4699,7 +4842,7 @@ class Topology():
4699
4842
  face_clusters = cluster_faces_on_planes(faces, epsilon=epsilon)
4700
4843
  final_faces = []
4701
4844
  for face_cluster in face_clusters:
4702
- t = Topology.SelfMerge(Cluster.ByTopologies(face_cluster))
4845
+ t = Topology.SelfMerge(Cluster.ByTopologies(face_cluster), tolerance=tolerance)
4703
4846
  if isinstance(t, topologic.Face):
4704
4847
  #final_faces.append(Face.RemoveCollinearEdges(t))
4705
4848
  final_faces.append(t)
@@ -4864,9 +5007,9 @@ class Topology():
4864
5007
  The input topology with the identified faces removed.
4865
5008
 
4866
5009
  """
4867
-
5010
+ from topologic.Vertex import Vertex
4868
5011
  from topologicpy.Face import Face
4869
- from topologicpy.Cluster import Cluster
5012
+
4870
5013
  if not isinstance(topology, topologic.Topology):
4871
5014
  return None
4872
5015
  selectors = [v for v in selectors if isinstance(v, topologic.Vertex)]
@@ -4877,7 +5020,7 @@ class Topology():
4877
5020
  for t_f in t_faces:
4878
5021
  remove = False
4879
5022
  for i, v in enumerate(selectors):
4880
- if Face.IsInternal(face=t_f, vertex=v, tolerance=tolerance):
5023
+ if Vertex.IsInternal(v, t_f, tolerance=tolerance):
4881
5024
  remove = True
4882
5025
  selectors = selectors[:i]+ selectors[i:]
4883
5026
  break
@@ -5178,7 +5321,7 @@ class Topology():
5178
5321
 
5179
5322
 
5180
5323
  @staticmethod
5181
- def SelfMerge(topology, tolerance=0.0001):
5324
+ def SelfMerge(topology, transferDictionaries: bool = False, tolerance: float = 0.0001):
5182
5325
  """
5183
5326
  Self merges the input topology to return the most logical topology type given the input data.
5184
5327
 
@@ -5721,6 +5864,8 @@ class Topology():
5721
5864
  A dictionary containing the list of sorted and unsorted topologies. The keys are "sorted" and "unsorted".
5722
5865
 
5723
5866
  """
5867
+
5868
+ from topologicpy.Vertex import Vertex
5724
5869
  usedTopologies = []
5725
5870
  sortedTopologies = []
5726
5871
  unsortedTopologies = []
@@ -5731,7 +5876,7 @@ class Topology():
5731
5876
  found = False
5732
5877
  for j in range(len(topologies)):
5733
5878
  if usedTopologies[j] == 0:
5734
- if Topology.IsInternal(topologies[j], selectors[i], tolerance):
5879
+ if Vertex.IsInternal( selectors[i], topologies[j], tolerance):
5735
5880
  sortedTopologies.append(topologies[j])
5736
5881
  if exclusive == True:
5737
5882
  usedTopologies[j] = 1
@@ -5967,6 +6112,40 @@ class Topology():
5967
6112
  return_topology = Topology.Fix(return_topology, topologyType=Topology.TypeAsString(topology))
5968
6113
  return return_topology
5969
6114
 
6115
+ @staticmethod
6116
+ def Unflatten(topology, origin=None, direction=[0,0,1]):
6117
+ """
6118
+ Unflattens the input topology such that the world origin is translated to the input origin and the input topology is rotated such that the Up direction (see Vector.Up()) is aligned with the input vector.
6119
+
6120
+ Parameters
6121
+ ----------
6122
+ topology : topologic.Topology
6123
+ The input topology.
6124
+ origin : topologic.Vertex , optional
6125
+ The input origin. If set to None, The object's centroid will be used to translate the world origin. The default is None.
6126
+ vector : list , optional
6127
+ The input direction vector. The input topology will be rotated such that this vector is pointed in the positive Z axis.
6128
+
6129
+ Returns
6130
+ -------
6131
+ topologic.Topology
6132
+ The flattened topology.
6133
+
6134
+ """
6135
+ from topologicpy.Vertex import Vertex
6136
+ from topologicpy.Vector import Vector
6137
+
6138
+ if not isinstance(topology, topologic.Topology):
6139
+ print("Topology.Unflatten - Error: the input topology parameter is not a valid topology. Returning None.")
6140
+ return None
6141
+ if origin == None:
6142
+ origin = Vertex.Origin()
6143
+ up = Vector.Up()
6144
+ tran_mat = Vector.TransformationMatrix(up, direction)
6145
+ unflat_topology = Topology.Transform(topology, tran_mat)
6146
+ unflat_topology = Topology.Translate(unflat_topology, Vertex.X(origin), Vertex.Y(origin), Vertex.Z(origin))
6147
+ return unflat_topology
6148
+
5970
6149
  @staticmethod
5971
6150
  def Vertices(topology):
5972
6151
  """
@@ -6554,7 +6733,7 @@ class Topology():
6554
6733
  return_topology = Topology.TransferDictionariesBySelectors(return_topology, selectors, tranFaces=True, tolerance=tolerance)
6555
6734
 
6556
6735
  if return_topology == None:
6557
- return_topology = Topology.SelfMerge(Cluster.ByTopologies(faceTriangles))
6736
+ return_topology = Topology.SelfMerge(Cluster.ByTopologies(faceTriangles), tolerance=tolerance)
6558
6737
  if transferDictionaries == True:
6559
6738
  return_topology = Topology.TransferDictionariesBySelectors(return_topology, selectors, tranFaces=True, tolerance=tolerance)
6560
6739