xslope 0.1.5__tar.gz → 0.1.6__tar.gz

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.
Files changed (26) hide show
  1. {xslope-0.1.5/xslope.egg-info → xslope-0.1.6}/PKG-INFO +1 -1
  2. {xslope-0.1.5 → xslope-0.1.6}/xslope/_version.py +1 -1
  3. {xslope-0.1.5 → xslope-0.1.6}/xslope/mesh.py +97 -21
  4. {xslope-0.1.5 → xslope-0.1.6/xslope.egg-info}/PKG-INFO +1 -1
  5. {xslope-0.1.5 → xslope-0.1.6}/LICENSE +0 -0
  6. {xslope-0.1.5 → xslope-0.1.6}/MANIFEST.in +0 -0
  7. {xslope-0.1.5 → xslope-0.1.6}/NOTICE +0 -0
  8. {xslope-0.1.5 → xslope-0.1.6}/README.md +0 -0
  9. {xslope-0.1.5 → xslope-0.1.6}/pyproject.toml +0 -0
  10. {xslope-0.1.5 → xslope-0.1.6}/setup.cfg +0 -0
  11. {xslope-0.1.5 → xslope-0.1.6}/xslope/__init__.py +0 -0
  12. {xslope-0.1.5 → xslope-0.1.6}/xslope/advanced.py +0 -0
  13. {xslope-0.1.5 → xslope-0.1.6}/xslope/fem.py +0 -0
  14. {xslope-0.1.5 → xslope-0.1.6}/xslope/fileio.py +0 -0
  15. {xslope-0.1.5 → xslope-0.1.6}/xslope/global_config.py +0 -0
  16. {xslope-0.1.5 → xslope-0.1.6}/xslope/plot.py +0 -0
  17. {xslope-0.1.5 → xslope-0.1.6}/xslope/plot_fem.py +0 -0
  18. {xslope-0.1.5 → xslope-0.1.6}/xslope/plot_seep.py +0 -0
  19. {xslope-0.1.5 → xslope-0.1.6}/xslope/search.py +0 -0
  20. {xslope-0.1.5 → xslope-0.1.6}/xslope/seep.py +0 -0
  21. {xslope-0.1.5 → xslope-0.1.6}/xslope/slice.py +0 -0
  22. {xslope-0.1.5 → xslope-0.1.6}/xslope/solve.py +0 -0
  23. {xslope-0.1.5 → xslope-0.1.6}/xslope.egg-info/SOURCES.txt +0 -0
  24. {xslope-0.1.5 → xslope-0.1.6}/xslope.egg-info/dependency_links.txt +0 -0
  25. {xslope-0.1.5 → xslope-0.1.6}/xslope.egg-info/requires.txt +0 -0
  26. {xslope-0.1.5 → xslope-0.1.6}/xslope.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xslope
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Slope stability analysis (limit equilibrium and FEM) in Python.
5
5
  Author: Norman L. Jones
6
6
  Project-URL: Homepage, https://github.com/njones61/xslope
@@ -1,4 +1,4 @@
1
1
  __all__ = ["__version__"]
2
- __version__ = "0.1.5"
2
+ __version__ = "0.1.6"
3
3
 
4
4
 
@@ -1235,14 +1235,8 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
1235
1235
  if max_depth is None:
1236
1236
  raise ValueError("When using only 1 profile line, max_depth must be specified")
1237
1237
 
1238
- def get_avg_y(line):
1239
- return sum(y for _, y in line) / len(line)
1240
-
1241
- # Sort profile lines from top to bottom by average y
1242
- sorted_lines = sorted(profile_lines, key=get_avg_y, reverse=True)
1243
- n = len(sorted_lines)
1244
- # Deep copy so we can insert points
1245
- 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)]
1246
1240
  tol = 1e-8
1247
1241
 
1248
1242
  for i in range(n - 1):
@@ -1282,7 +1276,7 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
1282
1276
  if not found:
1283
1277
  insert_idx = np.searchsorted(xs_lower, x_top)
1284
1278
  lower.insert(insert_idx, (round(x_top, 6), round(y_proj, 6)))
1285
-
1279
+
1286
1280
  def clean_polygon(poly, tol=1e-8):
1287
1281
  # Remove consecutive duplicate points (except for closing point)
1288
1282
  if not poly:
@@ -1304,25 +1298,107 @@ def build_polygons(slope_data, reinf_lines=None, debug=False):
1304
1298
  ys_top = np.array(ys_top)
1305
1299
  left_x, left_y = xs_top[0], ys_top[0]
1306
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 = []
1307
1308
 
1308
1309
  if i < n - 1:
1310
+ # Use the immediate next line as the lower boundary
1309
1311
  lower_line = lines[i + 1]
1310
1312
  xs_bot, ys_bot = zip(*lower_line)
1311
1313
  xs_bot = np.array(xs_bot)
1312
1314
  ys_bot = np.array(ys_bot)
1313
- # Project left and right endpoints vertically to lower profile
1314
- left_y_bot = np.interp(left_x, xs_bot, ys_bot)
1315
- right_y_bot = np.interp(right_x, xs_bot, ys_bot)
1316
- # Find all lower profile points between left_x and right_x (exclusive)
1317
- mask = (xs_bot > left_x) & (xs_bot < right_x)
1318
- xs_bot_in = xs_bot[mask]
1319
- ys_bot_in = ys_bot[mask]
1320
- # Build bottom boundary: right projection, lower profile points (right to left), left projection
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
1321
1383
  bottom = []
1322
- bottom.append((right_x, right_y_bot))
1323
- for x, y in zip(xs_bot_in[::-1], ys_bot_in[::-1]):
1324
- bottom.append((x, y))
1325
- bottom.append((left_x, left_y_bot))
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
1326
1402
  else:
1327
1403
  # For the lowest polygon, bottom is at max_depth
1328
1404
  # Only need endpoints - no intermediate points
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xslope
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: Slope stability analysis (limit equilibrium and FEM) in Python.
5
5
  Author: Norman L. Jones
6
6
  Project-URL: Homepage, https://github.com/njones61/xslope
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes