Skip to content

Commit

Permalink
Save road coordinates to create splines later and optional debug mode
Browse files Browse the repository at this point in the history
* Pilygon yielding refactoring.

* Saving polylines coordinates to create splines later.

* Debug checkbox.
  • Loading branch information
iwatkot authored Dec 28, 2024
1 parent a3e2286 commit dcf115c
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 9 deletions.
9 changes: 6 additions & 3 deletions data/fs25-texture-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"tags": { "highway": ["motorway", "trunk", "primary"] },
"width": 8,
"color": [70, 70, 70],
"priority": 1
"priority": 1,
"info_layer": "roads"
},
{
"name": "asphaltGravel",
Expand Down Expand Up @@ -134,7 +135,8 @@
"count": 2,
"tags": { "highway": ["secondary", "tertiary", "road", "service"] },
"width": 4,
"color": [140, 180, 210]
"color": [140, 180, 210],
"info_layer": "roads"
},
{
"name": "mudDark",
Expand All @@ -161,7 +163,8 @@
"count": 2,
"tags": { "highway": ["unclassified", "residential", "track"] },
"width": 2,
"color": [33, 67, 101]
"color": [33, 67, 101],
"info_layer": "roads"
},
{
"name": "mudPebbles",
Expand Down
71 changes: 65 additions & 6 deletions maps4fs/generator/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ def layers_by_priority(self) -> list[Layer]:
),
)

# pylint: disable=no-member
# pylint: disable=no-member, R0912
def draw(self) -> None:
"""Iterates over layers and fills them with polygons from OSM data."""
layers = self.layers_by_priority()
Expand Down Expand Up @@ -409,11 +409,23 @@ def draw(self) -> None:

mask = cv2.bitwise_not(cumulative_image)

for polygon in self.polygons(layer.tags, layer.width, layer.info_layer): # type: ignore
for polygon in self.objects_generator( # type: ignore
layer.tags, layer.width, layer.info_layer
):
if layer.info_layer:
info_layer_data[layer.info_layer].append(self.np_to_polygon_points(polygon))
info_layer_data[layer.info_layer].append(
self.np_to_polygon_points(polygon) # type: ignore
)
cv2.fillPoly(layer_image, [polygon], color=255) # type: ignore

if layer.info_layer == "roads":
for linestring in self.objects_generator(
layer.tags, layer.width, layer.info_layer, yield_linestrings=True
):
info_layer_data[f"{layer.info_layer}_polylines"].append(
linestring # type: ignore
)

output_image = cv2.bitwise_and(layer_image, mask)

cumulative_image = cv2.bitwise_or(cumulative_image, output_image)
Expand All @@ -422,8 +434,16 @@ def draw(self) -> None:
self.logger.debug("Texture %s saved.", layer_path)

# Save info layer data.
if os.path.isfile(self.info_layer_path):
self.logger.debug(
"File %s already exists, will update to avoid overwriting.", self.info_layer_path
)
with open(self.info_layer_path, "r", encoding="utf-8") as f:
info_layer_data.update(json.load(f))

with open(self.info_layer_path, "w", encoding="utf-8") as f:
json.dump(info_layer_data, f, ensure_ascii=False, indent=4)
self.logger.debug("Info layer data saved to %s.", self.info_layer_path)

if cumulative_image is not None:
self.draw_base_layer(cumulative_image)
Expand Down Expand Up @@ -617,21 +637,24 @@ def _converters(
converters = {"Polygon": self._skip, "LineString": self._sequence, "Point": self._sequence}
return converters.get(geom_type) # type: ignore

def polygons(
def objects_generator(
self,
tags: dict[str, str | list[str] | bool],
width: int | None,
info_layer: str | None = None,
) -> Generator[np.ndarray, None, None]:
yield_linestrings: bool = False,
) -> Generator[np.ndarray, None, None] | Generator[list[tuple[int, int]], None, None]:
"""Generator which yields numpy arrays of polygons from OSM data.
Arguments:
tags (dict[str, str | list[str]]): Dictionary of tags to search for.
width (int | None): Width of the polygon in meters (only for LineString).
info_layer (str | None): Name of the corresponding info layer.
yield_linestrings (bool): Flag to determine if the LineStrings should be yielded.
Yields:
Generator[np.ndarray, None, None]: Numpy array of polygon points.
Generator[np.ndarray, None, None] | Generator[list[tuple[int, int]], None, None]:
Numpy array of polygon points or list of point coordinates.
"""
is_fieds = info_layer == "fields"
try:
Expand All @@ -645,6 +668,42 @@ def polygons(
objects_utm = ox.projection.project_gdf(objects, to_latlong=False)
self.logger.debug("Fetched %s elements for tags: %s.", len(objects_utm), tags)

method = self.linestrings_generator if yield_linestrings else self.polygons_generator

yield from method(objects_utm, width, is_fieds)

def linestrings_generator(
self, objects_utm: pd.core.frame.DataFrame, *args, **kwargs
) -> Generator[list[tuple[int, int]], None, None]:
"""Generator which yields lists of point coordinates which represent LineStrings from OSM.
Arguments:
objects_utm (pd.core.frame.DataFrame): Dataframe with OSM objects in UTM format.
Yields:
Generator[list[tuple[int, int]], None, None]: List of point coordinates.
"""
for _, obj in objects_utm.iterrows():
geometry = obj["geometry"]
if isinstance(geometry, shapely.geometry.linestring.LineString):
points = [
(self.get_relative_x(x), self.get_relative_y(y)) for x, y in geometry.coords
]
yield points

def polygons_generator(
self, objects_utm: pd.core.frame.DataFrame, width: int | None, is_fieds: bool
) -> Generator[np.ndarray, None, None]:
"""Generator which yields numpy arrays of polygons from OSM data.
Arguments:
objects_utm (pd.core.frame.DataFrame): Dataframe with OSM objects in UTM format.
width (int | None): Width of the polygon in meters (only for LineString).
is_fieds (bool): Flag to determine if the fields should be padded.
Yields:
Generator[np.ndarray, None, None]: Numpy array of polygon points.
"""
for _, obj in objects_utm.iterrows():
polygon = self._to_polygon(obj, width)
if polygon is None:
Expand Down
7 changes: 7 additions & 0 deletions webui/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,13 @@ def add_left_widgets(self) -> None:

st.info(Messages.AUTO_PRESET_DISABLED)

if not self.public:
enable_debug = st.checkbox("Enable debug logs", key="debug_logs")
if enable_debug:
self.logger = mfs.Logger(level="DEBUG", to_file=False)
else:
self.logger = mfs.Logger(level="INFO", to_file=False)

self.custom_osm_path = None

st.write("[ALPHA] Custom OSM:")
Expand Down

0 comments on commit dcf115c

Please sign in to comment.