Skip to content

Commit

Permalink
Reversed splines, show tags in spline names.
Browse files Browse the repository at this point in the history
  • Loading branch information
iwatkot committed Feb 4, 2025
1 parent cd4f852 commit 34ebf1d
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 37 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ You can also apply some advanced settings to the map generation process.<br>
### Splines Advanced settings

- Splines density - number of points, which will be added (interpolate) between each pair of existing points. The higher the value, the denser the spline will be. It can smooth the splines, but high values can in opposite make the splines look unnatural.
- Add reversed splines - if enabled, the tool will add the reversed copies of the splines. It can be useful if you want to have the splines on both directions. By default, it's set to False.

### Satellite Advanced settings

Expand Down
82 changes: 46 additions & 36 deletions maps4fs/generator/component/i3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,17 @@ def _add_splines(self) -> None:
return

node_id = SPLINES_NODE_ID_STARTING_VALUE
for road_id, road in enumerate(roads_polylines, start=1):
for road_id, road_info in enumerate(roads_polylines, start=1):
# Add to scene node
# <Shape name="spline01_CSV" translation="0 0 0" nodeId="11" shapeId="11"/>

road_info: dict[str, str | list[tuple[int, int]]]
points = road_info.get("points")
tags = road_info.get("tags")

try:
fitted_road = self.fit_object_into_bounds(
linestring_points=road, angle=self.rotation
linestring_points=points, angle=self.rotation
)
except ValueError as e:
self.logger.debug(
Expand All @@ -168,52 +172,58 @@ def _add_splines(self) -> None:
fitted_road = self.interpolate_points(
fitted_road, num_points=self.map.spline_settings.spline_density
)
fitted_roads = [(fitted_road, "original")]

spline_name = f"spline{road_id}"
if self.map.spline_settings.add_reversed_splines:
reversed_fitted_road = fitted_road[::-1]
fitted_roads.append((reversed_fitted_road, "reversed"))

data = {
"name": spline_name,
"translation": "0 0 0",
"nodeId": str(node_id),
"shapeId": str(node_id),
}
for fitted_road, direction in fitted_roads:
spline_name = f"spline_{road_id}_{direction}_{tags}"

scene_node.append(self.create_element("Shape", data))
data = {
"name": spline_name,
"translation": "0 0 0",
"nodeId": str(node_id),
"shapeId": str(node_id),
}

road_ccs = [self.top_left_coordinates_to_center(point) for point in fitted_road]
scene_node.append(self.create_element("Shape", data))

data = {
"name": spline_name,
"shapeId": str(node_id),
"degree": "3",
"form": "open",
}
nurbs_curve_node = self.create_element("NurbsCurve", data)
road_ccs = [self.top_left_coordinates_to_center(point) for point in fitted_road]

for point_ccs, point in zip(road_ccs, fitted_road):
cx, cy = point_ccs
x, y = point
data = {
"name": spline_name,
"shapeId": str(node_id),
"degree": "3",
"form": "open",
}
nurbs_curve_node = self.create_element("NurbsCurve", data)

x = max(0, min(int(x), dem_x_size - 1))
y = max(0, min(int(y), dem_y_size - 1))
for point_ccs, point in zip(road_ccs, fitted_road):
cx, cy = point_ccs
x, y = point

z = not_resized_dem[y, x]
z *= self.get_z_scaling_factor()
x = max(0, min(int(x), dem_x_size - 1))
y = max(0, min(int(y), dem_y_size - 1))

nurbs_curve_node.append(self.create_element("cv", {"c": f"{cx}, {z}, {cy}"}))
z = not_resized_dem[y, x]
z *= self.get_z_scaling_factor()

shapes_node.append(nurbs_curve_node)
nurbs_curve_node.append(self.create_element("cv", {"c": f"{cx}, {z}, {cy}"}))

user_attribute_node = self.get_user_attribute_node(
node_id,
attributes=[
("maxSpeedScale", "integer", "1"),
("speedLimit", "integer", "100"),
],
)
shapes_node.append(nurbs_curve_node)

user_attributes_node.append(user_attribute_node)
node_id += 1
user_attribute_node = self.get_user_attribute_node(
node_id,
attributes=[
("maxSpeedScale", "integer", "1"),
("speedLimit", "integer", "100"),
],
)

user_attributes_node.append(user_attribute_node)
node_id += 1

tree.write(splines_i3d_path) # type: ignore
self.logger.debug("Splines I3D file saved to: %s.", splines_i3d_path)
Expand Down
6 changes: 5 additions & 1 deletion maps4fs/generator/component/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,11 @@ def _add_roads(self, layer: Layer, info_layer_data: dict[str, list[list[int]]])
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
linestring_entry = {
"points": linestring,
"tags": str(layer.tags),
}
info_layer_data[f"{layer.info_layer}_polylines"].append(linestring_entry)

def dissolve(self) -> None:
"""Dissolves textures of the layers with tags into sublayers for them to look more
Expand Down
1 change: 1 addition & 0 deletions maps4fs/generator/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class SplineSettings(SettingsModel):
"""

spline_density: int = 2
add_reversed_splines: bool = False


class SatelliteSettings(SettingsModel):
Expand Down
4 changes: 4 additions & 0 deletions webui/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ class Settings:
"more smooth. Be careful with high values, because it may make your spline too complex. \n"
"ℹ️ **Units:** number of additional points between each pair of existing points."
)
ADD_REVERSED_SPLINES = (
"If add reversed splines is enabled, the splines will be generated in both directions. "
"Otherwise, only one direction will be generated (as in the OSM data)."
)

# Satellite Settings

Expand Down

0 comments on commit 34ebf1d

Please sign in to comment.