topologicpy 0.8.72__py3-none-any.whl → 0.8.74__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
@@ -913,6 +913,7 @@ class Cell():
913
913
 
914
914
  """
915
915
  from topologicpy.Topology import Topology
916
+ import math
916
917
 
917
918
  if not Topology.IsInstance(cell, "Cell"):
918
919
  print("Cell.ContainmentStatus - Error: The input cell parameter is not a valid topologic cell. Returning None.")
@@ -920,14 +921,28 @@ class Cell():
920
921
  if not Topology.IsInstance(vertex, "Vertex"):
921
922
  print("Cell.ContainmentStatus - Error: The input vertex parameter is not a valid topologic vertex. Returning None.")
922
923
  return None
924
+
925
+ # topologic.CellUtility.Contains does not seem to respect the input tolerance. Thus we need to send eight additional vertices
926
+ # to check if any are contained and take the average result.
927
+
928
+ test_vertices = [vertex]
929
+ if tolerance > 0:
930
+ test_cell = Cell.Prism(origin=vertex, width=tolerance*2, length=tolerance*2, height=tolerance*2, tolerance=tolerance)
931
+ test_vertices.extend(Topology.Vertices(test_cell))
923
932
  try:
924
- status = topologic.CellUtility.Contains(cell, vertex, tolerance) # Hook to Core
925
- if status == 0:
926
- return 0
927
- elif status == 1:
928
- return 1
929
- else:
930
- return 2
933
+ av_results = []
934
+ for v in test_vertices:
935
+
936
+ result = topologic.CellUtility.Contains(cell, v, tolerance) # Hook to Core
937
+ if result == 0:
938
+ status = 0
939
+ elif result == 1:
940
+ status = 1
941
+ else:
942
+ status = 2
943
+ av_results.append(status)
944
+ return min(av_results)
945
+
931
946
  except:
932
947
  print("Cell.ContainmentStatus - Error: Could not determine containment status. Returning None.")
933
948
  return None
topologicpy/Vertex.py CHANGED
@@ -1135,22 +1135,11 @@ class Vertex():
1135
1135
  topology,
1136
1136
  maxLeafSize: int = 4,
1137
1137
  identify: bool = False,
1138
- tolerance: float = 0.0006,
1139
- silent: bool = True,
1140
- ) -> bool:
1138
+ tolerance: float = 0.0001,
1139
+ silent: bool = False,
1140
+ ):
1141
1141
  """
1142
- Returns True if `vertex` lies inside (or on the boundary of) `topology`.
1143
-
1144
- Broad-phase:
1145
- - Build a BVH over Cells (3D) or Faces (2D) using BVH.ByTopologies.
1146
- - Query via BVH.Clashes(bvh, vertex) to get only nearby primitives.
1147
-
1148
- Narrow-phase (geometric, no Topology.IsInternal):
1149
- - Boundary snap: if Vertex.Distance(vertex, primitive) <= tolerance -> inside.
1150
- - 3D: Cast a ray (+X direction). For each candidate Cell, intersect the ray with its Faces.
1151
- For each intersected Face: project face polygon(s) to 2D (dominant-axis drop) and
1152
- test point-in-polygon (outer minus holes). Odd number of valid intersections => inside.
1153
- - 2D: Project the Face loops to 2D and do point-in-polygon (outer minus holes).
1142
+ Returns True if the input vertex lies inside the input topology.
1154
1143
 
1155
1144
  Parameters
1156
1145
  ----------
@@ -1166,9 +1155,9 @@ class Vertex():
1166
1155
  identify: bool, optional
1167
1156
  If set to True, a tuple is returned where the identified subTopology is returned (e.g. (True, edge)). Default is False.
1168
1157
  tolerance : float, optional
1169
- Distance and numeric tolerance. Default 1e-7.
1170
- silent : bool, optional
1171
- Suppress non-critical prints.
1158
+ The desired tolerance. Default 0.0001.
1159
+ silent : bool , optional
1160
+ If set to True, error and warning messages are suppressed. Default is False.
1172
1161
 
1173
1162
  Returns
1174
1163
  -------
@@ -1191,11 +1180,6 @@ class Vertex():
1191
1180
  # --------------------------
1192
1181
  # Utilities
1193
1182
  # --------------------------
1194
- def v_coords(v):
1195
- return Vertex.X(v), Vertex.Y(v), Vertex.Z(v)
1196
-
1197
- def vec_sub(a, b):
1198
- return (a[0]-b[0], a[1]-b[1], a[2]-b[2])
1199
1183
 
1200
1184
  def vec_dot(a, b):
1201
1185
  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
@@ -1212,29 +1196,6 @@ class Vertex():
1212
1196
  return (0.0, 0.0, 0.0)
1213
1197
  return (a[0]/l, a[1]/l, a[2]/l)
1214
1198
 
1215
- # Plane from 3 points
1216
- def face_plane(face):
1217
- # Returns (n, d) where plane: n·X + d = 0; n is unit normal.
1218
- # Use first 3 distinct points of the external boundary.
1219
- w_ext = Face.ExternalBoundary(face)
1220
- verts = Wire.Vertices(w_ext)
1221
- pts = [v_coords(v) for v in verts]
1222
- # Find non-collinear triplet
1223
- p0 = pts[0]
1224
- n = None
1225
- for i in range(1, len(pts)-1):
1226
- v1 = vec_sub(pts[i], p0)
1227
- v2 = vec_sub(pts[i+1], p0)
1228
- n_try = vec_cross(v1, v2)
1229
- if vec_len(n_try) > 1e-15:
1230
- n = vec_norm(n_try)
1231
- break
1232
- if n is None:
1233
- # Degenerate face; assign arbitrary normal
1234
- n = (1.0, 0.0, 0.0)
1235
- d = -vec_dot(n, p0)
1236
- return n, d
1237
-
1238
1199
  def dominant_axis(n):
1239
1200
  # Return axis to drop when projecting to 2D (index 0=x,1=y,2=z)
1240
1201
  ax = abs(n[0]); ay = abs(n[1]); az = abs(n[2])
@@ -1252,13 +1213,6 @@ class Vertex():
1252
1213
  else:
1253
1214
  return (p[0], p[1])
1254
1215
 
1255
- def ray_plane_intersection(orig, dirv, n, d):
1256
- # Solve n·(orig + t*dir) + d = 0 -> t = -(n·orig + d) / (n·dir)
1257
- ndotdir = vec_dot(n, dirv)
1258
- if abs(ndotdir) < 1e-15:
1259
- return None # parallel
1260
- t = -(vec_dot(n, orig) + d) / ndotdir
1261
- return t
1262
1216
 
1263
1217
  # 2D point-in-polygon (ray crossing). Polygon is list of 2D points (closed or open).
1264
1218
  def pip_ray_cross_2d(pt, poly):
@@ -1300,38 +1254,6 @@ class Vertex():
1300
1254
  return False
1301
1255
  return True
1302
1256
 
1303
- def face_loops_2d(face, drop_axis):
1304
- # Returns (outer2d, [hole2d,...])
1305
- w_ext = Face.ExternalBoundary(face)
1306
- outer_vs = Wire.Vertices(w_ext)
1307
- outer = [project_point(v_coords(v), drop_axis) for v in outer_vs]
1308
-
1309
- holes_2d = []
1310
- try:
1311
- inner_wires = Face.InternalBoundaries(face) or []
1312
- except Exception:
1313
- inner_wires = []
1314
- for w in inner_wires:
1315
- vs = Wire.Vertices(w)
1316
- holes_2d.append([project_point(v_coords(v), drop_axis) for v in vs])
1317
- return outer, holes_2d
1318
-
1319
- # Ray casting against one face; returns hit-point (3D) if the ray hits inside the face.
1320
- def ray_hits_face(orig, dirv, face, tol=1e-12):
1321
- n, d = face_plane(face)
1322
- t = ray_plane_intersection(orig, dirv, n, d)
1323
- if t is None or t < -tol:
1324
- return None # behind or parallel
1325
- # Intersection point
1326
- ip = (orig[0] + t*dirv[0], orig[1] + t*dirv[1], orig[2] + t*dirv[2])
1327
- # Project to 2D in face's dominant plane and do PIP against loops
1328
- ax = dominant_axis(n)
1329
- outer2d, holes2d = face_loops_2d(face, ax)
1330
- ip2d = project_point(ip, ax)
1331
- if polygon_with_holes_contains_2d(ip2d, outer2d, holes2d):
1332
- return ip
1333
- return None
1334
-
1335
1257
  # 2D containment in an Edge
1336
1258
  def point_in_vertex(vtx, vertex, tol):
1337
1259
  # Boundary snap first
@@ -1348,7 +1270,12 @@ class Vertex():
1348
1270
 
1349
1271
  # 2D containment in a Face (vertex assumed coplanar or nearly so)
1350
1272
  def point_in_face(vtx, face, tol):
1351
- status = topologic.FaceUtility.IsInside(face, vtx, tol)
1273
+ dist = Vertex.PerpendicularDistance(vtx, face)
1274
+ if dist <= tol:
1275
+ vtx2 = Vertex.Project(vtx, face)
1276
+ status = topologic.FaceUtility.IsInside(face, vtx2, tol)
1277
+ else:
1278
+ status = False
1352
1279
  return status
1353
1280
 
1354
1281
  # 3D containment in a Cell via ray casting (+X direction)
@@ -1360,7 +1287,7 @@ class Vertex():
1360
1287
  # Check if inside AABB
1361
1288
  # --------------------------
1362
1289
  points = [Vertex.Coordinates(v) for v in Topology.Vertices(topology)]
1363
- aabb = AABB.from_points(points)
1290
+ aabb = AABB.from_points(points, pad=tolerance)
1364
1291
  if not aabb.contains_point(Vertex.Coordinates(vertex)):
1365
1292
  return False
1366
1293
 
@@ -1398,8 +1325,8 @@ class Vertex():
1398
1325
  else:
1399
1326
  cells = collect_cells(topology)
1400
1327
  faces = [] if cells else collect_faces(topology)
1401
- edges = [] if faces else collect_edges(topology)
1402
- vertices = [] if edges else collect_vertices(topology)
1328
+ edges = [] if faces or cells else collect_edges(topology)
1329
+ vertices = [] if edges or faces or cells else collect_vertices(topology)
1403
1330
  if not cells and not faces and not edges and not vertices:
1404
1331
  return False
1405
1332
 
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.8.72'
1
+ __version__ = '0.8.74'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topologicpy
3
- Version: 0.8.72
3
+ Version: 0.8.74
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=ts0Ru24ILjjfHa54SYNhMc8Jkyxwej1DV0Jv7P_6BoU,22513
4
4
  topologicpy/CSG.py,sha256=09la1-xzS9vr-WnV7tpJ0I-mkZ-XY0MRSd5iB50Nfgw,15556
5
- topologicpy/Cell.py,sha256=xkt9lfutgSwr_1lah1U5n48UnrLIggznNKUmEe2FA2g,177505
5
+ topologicpy/Cell.py,sha256=8HeL2sVgvBWwsWsFD6OkyCIQf3S4JPBWc_xev0Oh1i4,178199
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
@@ -28,12 +28,12 @@ topologicpy/Speckle.py,sha256=-eiTqJugd7pHiHpD3pDUcDO6CGhVyPV14HFRzaqEoaw,18187
28
28
  topologicpy/Sun.py,sha256=8S6dhCKfOhUGVny-jEk87Q08anLYMB1JEBKRGCklvbQ,36670
29
29
  topologicpy/Topology.py,sha256=BC9JYfxComyAzmXrPdhmXlaFBGmZ_x7-oHl579E4qUY,474458
30
30
  topologicpy/Vector.py,sha256=pEC8YY3TeHGfGdeNgvdHjgMDwxGabp5aWjwYC1HSvMk,42236
31
- topologicpy/Vertex.py,sha256=eO74ZcuQUmiEHy5-Xyn7YDlt3R7YKoqB-BEwF-TUcDM,94101
31
+ topologicpy/Vertex.py,sha256=oBlBXNrB0ov-lA6uvvPNIiRCZwKa92SS_K5vfp8Elec,90882
32
32
  topologicpy/Wire.py,sha256=gjgQUGHdBdXUIijgZc_VIW0E39w-smaVhhdl0jF63fQ,230466
33
33
  topologicpy/__init__.py,sha256=RMftibjgAnHB1vdL-muo71RwMS4972JCxHuRHOlU428,928
34
- topologicpy/version.py,sha256=5keU0mboyFEsP7wnOuJd2VXsHYJviiaVppSSn9IAZJE,23
35
- topologicpy-0.8.72.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
36
- topologicpy-0.8.72.dist-info/METADATA,sha256=Ivpypd-BnC6KU2xhc4Q-rsaQpAaFoLWseDSd_NfUYuo,10535
37
- topologicpy-0.8.72.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- topologicpy-0.8.72.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
39
- topologicpy-0.8.72.dist-info/RECORD,,
34
+ topologicpy/version.py,sha256=0GBumWosBLrQf5ksbXd1cy8lfG5KK7ZxVU4oNea8mU4,23
35
+ topologicpy-0.8.74.dist-info/licenses/LICENSE,sha256=FK0vJ73LuE8PYJAn7LutsReWR47-Ooovw2dnRe5yV6Q,681
36
+ topologicpy-0.8.74.dist-info/METADATA,sha256=M7FzwXZzuTCTCHrXLwtS-i-APB3DVw3lFld3gbmedHo,10535
37
+ topologicpy-0.8.74.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ topologicpy-0.8.74.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
39
+ topologicpy-0.8.74.dist-info/RECORD,,