xslope 0.1.4__py3-none-any.whl → 0.1.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.
- xslope/_version.py +1 -1
- xslope/mesh.py +103 -22
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/METADATA +1 -1
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/RECORD +8 -8
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/LICENSE +0 -0
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/NOTICE +0 -0
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/WHEEL +0 -0
- {xslope-0.1.4.dist-info → xslope-0.1.6.dist-info}/top_level.txt +0 -0
xslope/_version.py
CHANGED
xslope/mesh.py
CHANGED
|
@@ -26,8 +26,13 @@ def _get_gmsh():
|
|
|
26
26
|
_gmsh = gmsh
|
|
27
27
|
except (ImportError, OSError) as e:
|
|
28
28
|
error_msg = str(e)
|
|
29
|
+
error_repr = repr(e)
|
|
29
30
|
# Check for OpenGL library issues (common in Colab/headless environments)
|
|
30
|
-
|
|
31
|
+
# Check both str() and repr() to catch all variations, and check exception args
|
|
32
|
+
error_text = error_msg + " " + error_repr
|
|
33
|
+
if hasattr(e, 'args') and e.args:
|
|
34
|
+
error_text += " " + " ".join(str(arg) for arg in e.args)
|
|
35
|
+
if ("libGL" in error_text or "libGLU" in error_text):
|
|
31
36
|
help_msg = (
|
|
32
37
|
"gmsh is required for mesh generation but could not be imported due to missing OpenGL libraries. "
|
|
33
38
|
"This is common in headless environments like Google Colab.\n\n"
|
|
@@ -1230,14 +1235,8 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
|
|
|
1230
1235
|
if max_depth is None:
|
|
1231
1236
|
raise ValueError("When using only 1 profile line, max_depth must be specified")
|
|
1232
1237
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
# Sort profile lines from top to bottom by average y
|
|
1237
|
-
sorted_lines = sorted(profile_lines, key=get_avg_y, reverse=True)
|
|
1238
|
-
n = len(sorted_lines)
|
|
1239
|
-
# Deep copy so we can insert points
|
|
1240
|
-
lines = [list(line) for line in copy.deepcopy(sorted_lines)]
|
|
1238
|
+
n = len(profile_lines)
|
|
1239
|
+
lines = [list(line) for line in copy.deepcopy(profile_lines)]
|
|
1241
1240
|
tol = 1e-8
|
|
1242
1241
|
|
|
1243
1242
|
for i in range(n - 1):
|
|
@@ -1277,7 +1276,7 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
|
|
|
1277
1276
|
if not found:
|
|
1278
1277
|
insert_idx = np.searchsorted(xs_lower, x_top)
|
|
1279
1278
|
lower.insert(insert_idx, (round(x_top, 6), round(y_proj, 6)))
|
|
1280
|
-
|
|
1279
|
+
|
|
1281
1280
|
def clean_polygon(poly, tol=1e-8):
|
|
1282
1281
|
# Remove consecutive duplicate points (except for closing point)
|
|
1283
1282
|
if not poly:
|
|
@@ -1299,25 +1298,107 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
|
|
|
1299
1298
|
ys_top = np.array(ys_top)
|
|
1300
1299
|
left_x, left_y = xs_top[0], ys_top[0]
|
|
1301
1300
|
right_x, right_y = xs_top[-1], ys_top[-1]
|
|
1301
|
+
|
|
1302
|
+
# Initialize variables for debug output
|
|
1303
|
+
lower_left_x = None
|
|
1304
|
+
lower_right_x = None
|
|
1305
|
+
proj_left_x = None
|
|
1306
|
+
proj_right_x = None
|
|
1307
|
+
bottom_cleaned = []
|
|
1302
1308
|
|
|
1303
1309
|
if i < n - 1:
|
|
1310
|
+
# Use the immediate next line as the lower boundary
|
|
1304
1311
|
lower_line = lines[i + 1]
|
|
1305
1312
|
xs_bot, ys_bot = zip(*lower_line)
|
|
1306
1313
|
xs_bot = np.array(xs_bot)
|
|
1307
1314
|
ys_bot = np.array(ys_bot)
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
#
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1315
|
+
lower_left_x = xs_bot[0]
|
|
1316
|
+
lower_right_x = xs_bot[-1]
|
|
1317
|
+
|
|
1318
|
+
# Collect actual points from all lower lines within the top line's x-range
|
|
1319
|
+
# But only include a point if it's actually on the highest lower profile at that x
|
|
1320
|
+
bottom_points = [] # List of (x, y, line_idx) tuples
|
|
1321
|
+
|
|
1322
|
+
for j in range(i + 1, n):
|
|
1323
|
+
lower_candidate = lines[j]
|
|
1324
|
+
xs_cand = np.array([x for x, y in lower_candidate])
|
|
1325
|
+
ys_cand = np.array([y for x, y in lower_candidate])
|
|
1326
|
+
|
|
1327
|
+
# Only include points that are within the top line's x-range
|
|
1328
|
+
mask = (xs_cand >= left_x - tol) & (xs_cand <= right_x + tol)
|
|
1329
|
+
for x, y in zip(xs_cand[mask], ys_cand[mask]):
|
|
1330
|
+
# Check if this point is actually on the highest lower profile at this x
|
|
1331
|
+
# Compare with all other lower lines at this x-coordinate
|
|
1332
|
+
is_highest = True
|
|
1333
|
+
for k in range(i + 1, n):
|
|
1334
|
+
if k == j:
|
|
1335
|
+
continue
|
|
1336
|
+
other_line = lines[k]
|
|
1337
|
+
xs_other = np.array([x_o for x_o, y_o in other_line])
|
|
1338
|
+
ys_other = np.array([y_o for x_o, y_o in other_line])
|
|
1339
|
+
if xs_other[0] - tol <= x <= xs_other[-1] + tol:
|
|
1340
|
+
y_other = np.interp(x, xs_other, ys_other)
|
|
1341
|
+
if y_other > y + tol: # Other line is higher
|
|
1342
|
+
is_highest = False
|
|
1343
|
+
break
|
|
1344
|
+
|
|
1345
|
+
if is_highest:
|
|
1346
|
+
bottom_points.append((x, y, j))
|
|
1347
|
+
|
|
1348
|
+
# Group by x-coordinate (within tolerance) and keep only the highest y at each x
|
|
1349
|
+
# This handles cases where multiple lines have points at the same x
|
|
1350
|
+
bottom_dict = {} # x_key -> (y, line_idx, orig_x, orig_y)
|
|
1351
|
+
for x, y, line_idx in bottom_points:
|
|
1352
|
+
x_key = round(x / tol) * tol # Round to tolerance to group nearby points
|
|
1353
|
+
if x_key not in bottom_dict or y > bottom_dict[x_key][0]:
|
|
1354
|
+
bottom_dict[x_key] = (y, line_idx, x, y)
|
|
1355
|
+
|
|
1356
|
+
# Convert to sorted list
|
|
1357
|
+
bottom_cleaned = sorted([(orig_x, orig_y) for _, _, orig_x, orig_y in bottom_dict.values()])
|
|
1358
|
+
|
|
1359
|
+
# Project endpoints - find highest lower profile or use max_depth
|
|
1360
|
+
left_y_bot = -np.inf
|
|
1361
|
+
right_y_bot = -np.inf
|
|
1362
|
+
for j in range(i + 1, n):
|
|
1363
|
+
lower_candidate = lines[j]
|
|
1364
|
+
xs_cand = np.array([x for x, y in lower_candidate])
|
|
1365
|
+
ys_cand = np.array([y for x, y in lower_candidate])
|
|
1366
|
+
if xs_cand[0] - tol <= left_x <= xs_cand[-1] + tol:
|
|
1367
|
+
y_cand = np.interp(left_x, xs_cand, ys_cand)
|
|
1368
|
+
if y_cand > left_y_bot:
|
|
1369
|
+
left_y_bot = y_cand
|
|
1370
|
+
if xs_cand[0] - tol <= right_x <= xs_cand[-1] + tol:
|
|
1371
|
+
y_cand = np.interp(right_x, xs_cand, ys_cand)
|
|
1372
|
+
if y_cand > right_y_bot:
|
|
1373
|
+
right_y_bot = y_cand
|
|
1374
|
+
|
|
1375
|
+
# If no lower profile at endpoints, use max_depth
|
|
1376
|
+
if left_y_bot == -np.inf:
|
|
1377
|
+
left_y_bot = max_depth if max_depth is not None else -np.inf
|
|
1378
|
+
if right_y_bot == -np.inf:
|
|
1379
|
+
right_y_bot = max_depth if max_depth is not None else -np.inf
|
|
1380
|
+
|
|
1381
|
+
# Build bottom boundary: right projection, intermediate points (right to left), left projection
|
|
1382
|
+
# The bottom should go from right to left to close the polygon
|
|
1316
1383
|
bottom = []
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1384
|
+
|
|
1385
|
+
# Start with right endpoint
|
|
1386
|
+
if right_y_bot != -np.inf:
|
|
1387
|
+
bottom.append((right_x, right_y_bot))
|
|
1388
|
+
|
|
1389
|
+
# Add intermediate points in reverse order (right to left)
|
|
1390
|
+
# Filter out points too close to endpoints
|
|
1391
|
+
for x, y in reversed(bottom_cleaned):
|
|
1392
|
+
if abs(x - left_x) > tol and abs(x - right_x) > tol:
|
|
1393
|
+
bottom.append((x, y))
|
|
1394
|
+
|
|
1395
|
+
# End with left endpoint
|
|
1396
|
+
if left_y_bot != -np.inf:
|
|
1397
|
+
bottom.append((left_x, left_y_bot))
|
|
1398
|
+
|
|
1399
|
+
# Store for debug output
|
|
1400
|
+
proj_left_x = left_x
|
|
1401
|
+
proj_right_x = right_x
|
|
1321
1402
|
else:
|
|
1322
1403
|
# For the lowest polygon, bottom is at max_depth
|
|
1323
1404
|
# Only need endpoints - no intermediate points
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
xslope/__init__.py,sha256=ZygAIkX6Nbjag1czWdQa-yP-GM1mBE_9ss21Xh__JFc,34
|
|
2
|
-
xslope/_version.py,sha256=
|
|
2
|
+
xslope/_version.py,sha256=El5otyOm5tn7_NTNUcawnWQ_lZMwfYOTw_-GGhANHSI,50
|
|
3
3
|
xslope/advanced.py,sha256=35k_ekQJ-mQJ1wHnoIHMc5TVfYn-2EPCJyHz827Cpbc,18281
|
|
4
4
|
xslope/fem.py,sha256=K4_Pq06HFBpRkN3JwtXF2zw_AMnCkXvj0ggrlRFMQQw,115731
|
|
5
5
|
xslope/fileio.py,sha256=DnFUYmJedjKXOuVPZUfTRxGfTjiIz8KyHkRDK7ddQg0,28840
|
|
6
6
|
xslope/global_config.py,sha256=Cj8mbPidIuj5Ty-5cZM-c8H12kNvyHsk5_ofNGez-3M,2253
|
|
7
|
-
xslope/mesh.py,sha256=
|
|
7
|
+
xslope/mesh.py,sha256=OhaAMlunbO86Sx4iF5sRsk4eEN7-AG-_TYPUvYVTGA4,122513
|
|
8
8
|
xslope/plot.py,sha256=rr1D-6KzYyJtq51o4yLyaFkowBa1LtygIk9rtA3GxgQ,54592
|
|
9
9
|
xslope/plot_fem.py,sha256=al9zjqjxWKooLl4SAds77Zz-j9cjD4TJGygyU9QK5vo,71111
|
|
10
10
|
xslope/plot_seep.py,sha256=3wbKp85cmK_6EniFnK9x-FaZtYBZ3KZbRn9U1GsInmk,28775
|
|
@@ -12,9 +12,9 @@ xslope/search.py,sha256=dvgKn8JCobuvyD7fClF5lcbeHESCvV8gZ_U_lQnYRok,16867
|
|
|
12
12
|
xslope/seep.py,sha256=zVX8NJOp8e6VJ6y99YLkmOh_RPQFly9Z9UI3tka6yQQ,85765
|
|
13
13
|
xslope/slice.py,sha256=QHawTk7XPLziHoN_ZS0jrEPYKlhPT62caUc_q-_EGjs,45236
|
|
14
14
|
xslope/solve.py,sha256=j7N66QBjBpDAo-aizTiP8auwd5Ey1SiYAYeySaMVzkw,48554
|
|
15
|
-
xslope-0.1.
|
|
16
|
-
xslope-0.1.
|
|
17
|
-
xslope-0.1.
|
|
18
|
-
xslope-0.1.
|
|
19
|
-
xslope-0.1.
|
|
20
|
-
xslope-0.1.
|
|
15
|
+
xslope-0.1.6.dist-info/LICENSE,sha256=NU5J88FUai_4Ixu5DqOQukA-gcXAyX8pXLhIg8OB3AM,10969
|
|
16
|
+
xslope-0.1.6.dist-info/METADATA,sha256=8eM1VvzchbN-xSlSrTzbRMX86Vy2L3WDUVrdt3_BJq4,2027
|
|
17
|
+
xslope-0.1.6.dist-info/NOTICE,sha256=E-sbN0MWwvJC27Z-2_G4VUHIx4IsfvLDTmOstvY4-OQ,530
|
|
18
|
+
xslope-0.1.6.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
|
|
19
|
+
xslope-0.1.6.dist-info/top_level.txt,sha256=5qHbWJ1R2pdTNIainFyrVtFk8R1tRcwIn0kzTuwuV1Q,7
|
|
20
|
+
xslope-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|