Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ build-backend = "flit_core.buildapi"
[dependency-groups]
dev = [
"black>=25.1.0",
"ipykernel>=6.30.1",
"pytest>=8.4.1",
]
34 changes: 27 additions & 7 deletions src/load_distribution/load_distribution.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import annotations
from collections import Counter
import math
from typing import Optional
from dataclasses import dataclass
import numpy.typing as npt
Expand Down Expand Up @@ -180,23 +182,41 @@ def singularities_to_polygon(los: list[Singularity], xy: bool = False) -> Polygo
x_acc = []
prev_x = None
n = None
# Create a list of the x-ordinates required
# Always starts on 0.0
x_acc.append(0.0)
for idx, sing in enumerate(sorted_sings):
n = sing.precision
eps = 10 ** (-2 * n)
if prev_x != sing.x0 and prev_x is not None:
x_acc.append(prev_x + eps)
x_acc.append(sing.x0)
if prev_x is not None and not math.isclose(prev_x, sing.x0):
x_acc.append(sing.x0)
x_acc.append(sing.x0 + eps)
if idx == len(sorted_sings) - 1:
x_acc.append(sing.x1 - eps)
x_acc.append(sing.x1)
x_acc.append(sing.x1 - eps)
prev_x = sing.x1
if idx == len(sorted_sings) - 1: # Last iteration of actual iterations
x_acc.append(sing.x1)

# There are two scenarios: sing functions that describe trapezoids/triangles
# and sing functions that describe step functions (rectangles). To ensure
# we get enough points to fully describe each, we end up getting too many
# x ordinates in some cases. The below is a filter to look for the unnecessary
# duplicate x-ordinates. The goal is to have the minimum amount to describe the
# required shape, even if that means the exact x value is omitted (because we are
# keeping the value immediately to the left and immediately to the right instead).
x_acc = sorted(list(set(x_acc)))
x_ord_count = Counter([round(x, 6) for x in x_acc])
to_filter = []
for key, count in x_ord_count.items():
if count == 3:
to_filter.append(key)
for filter_val in to_filter:
index = x_acc.index(filter_val)
x_acc.pop(index)

# Now, for every x value, compute the corresponding y value
y_acc = [sum([sing(x) for sing in sorted_sings]) for x in x_acc[:-1]]
y_acc += [0.0]
# Always ends on 0.0
y_acc.append(0.0)
if xy:
return x_acc, y_acc
else:
Expand Down
9 changes: 5 additions & 4 deletions tests/test_load_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,25 +175,26 @@ def test_singularities_to_polygon():

assert (
ld.singularities_to_polygon(square_45_sings[0] + square_45_sings[1]).wkt
== "POLYGON ((0 0, 0 0, 5 10, 5 10, 10 0, 10 0, 0 0))"
== "POLYGON ((0 0, 0 0, 5 10, 5 10, 10 0, 0 0))"
# == "POLYGON ((0 0, 5 10, 5 10, 10 0, 10 0, 0 0))"
)
assert (
ld.singularities_to_polygon(
square_pac_man_sings[0] + square_pac_man_sings[1]
).wkt
== "POLYGON ((0 0, 0 10, 5 10, 5 10, 10 0, 10 0, 10 0, 0 0))"
== "POLYGON ((0 0, 0 10, 5 10, 5 10, 10 0, 10 0, 0 0))"
)
assert (
ld.singularities_to_polygon(
square_bow_tie_sings[0] + square_bow_tie_sings[1]
).wkt
== "POLYGON ((0 0, 0 0, 4 10, 4 10, 6 10, 6 10, 10 0, 10 0, 10 0, 0 0))"
== "POLYGON ((0 0, 0 0, 4 10, 4 10, 6 10, 6 10, 10 0, 10 0, 0 0))"
)
assert (
ld.singularities_to_polygon(
square_with_L_hole_sings[0] + square_with_L_hole_sings[1]
).wkt
== "POLYGON ((0 0, 0 10, 2 10, 2 4, 4 4, 4 8, 8 8, 8 8, 8 10, 10 10, 10 0, 0 0))"
== "POLYGON ((0 0, 0 10, 2 10, 2 4, 4 4, 4 8, 8 8, 8 10, 10 10, 10 0, 0 0))"
)


Expand Down
Loading
Loading