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 +22 -7
- topologicpy/Vertex.py +16 -89
- topologicpy/version.py +1 -1
- {topologicpy-0.8.72.dist-info → topologicpy-0.8.74.dist-info}/METADATA +1 -1
- {topologicpy-0.8.72.dist-info → topologicpy-0.8.74.dist-info}/RECORD +8 -8
- {topologicpy-0.8.72.dist-info → topologicpy-0.8.74.dist-info}/WHEEL +0 -0
- {topologicpy-0.8.72.dist-info → topologicpy-0.8.74.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.72.dist-info → topologicpy-0.8.74.dist-info}/top_level.txt +0 -0
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
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
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.
|
1139
|
-
silent: bool =
|
1140
|
-
)
|
1138
|
+
tolerance: float = 0.0001,
|
1139
|
+
silent: bool = False,
|
1140
|
+
):
|
1141
1141
|
"""
|
1142
|
-
Returns True if
|
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
|
-
|
1170
|
-
silent : bool, optional
|
1171
|
-
|
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
|
-
|
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.
|
1
|
+
__version__ = '0.8.74'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: topologicpy
|
3
|
-
Version: 0.8.
|
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=
|
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=
|
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=
|
35
|
-
topologicpy-0.8.
|
36
|
-
topologicpy-0.8.
|
37
|
-
topologicpy-0.8.
|
38
|
-
topologicpy-0.8.
|
39
|
-
topologicpy-0.8.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|