Skip to content

Commit

Permalink
Fix pointy lines rendering on low resolution (Maximkaaa#25)
Browse files Browse the repository at this point in the history
This change also adds LODs to feature layers
  • Loading branch information
Maximkaaa authored Jan 16, 2024
1 parent df3cecd commit 77689e7
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 168 deletions.
10 changes: 6 additions & 4 deletions galileo-types/src/cartesian/rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::cartesian::traits::cartesian_point::CartesianPoint2d;
use nalgebra::{Point2, Scalar};
use num_traits::{FromPrimitive, Num};
use serde::{Deserialize, Serialize};
use std::ops::Deref;

#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
pub struct Rect<N = f64> {
Expand Down Expand Up @@ -93,16 +94,17 @@ impl<N: Num + Copy + PartialOrd + Scalar + FromPrimitive> Rect<N> {
}
}

pub fn from_points<'a, P: CartesianPoint2d<Num = N> + 'a>(
mut points: impl Iterator<Item = &'a P>,
pub fn from_points<'a, P: CartesianPoint2d<Num = N> + 'a, T: Deref<Target = P> + 'a>(
points: impl IntoIterator<Item = T>,
) -> Option<Self> {
let first = points.next()?;
let mut iterator = points.into_iter();
let first = iterator.next()?;
let mut x_min = first.x();
let mut y_min = first.y();
let mut x_max = first.x();
let mut y_max = first.y();

for p in points {
for p in iterator {
if x_min > p.x() {
x_min = p.x();
}
Expand Down
11 changes: 8 additions & 3 deletions galileo/examples/feature_layers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ pub fn load_cities() -> Vec<City> {
pub async fn run(builder: MapBuilder) {
let countries = load_countries();

let feature_layer = FeatureLayer::new(countries, CountrySymbol {}, Crs::EPSG3857);
let feature_layer = FeatureLayer::with_lods(
countries,
CountrySymbol {},
Crs::EPSG3857,
vec![8000.0, 1000.0, 1.0],
);
let feature_layer = Arc::new(RwLock::new(feature_layer));

let point_layer = FeatureLayer::new(load_cities(), CitySymbol {}, Crs::WGS84);
Expand Down Expand Up @@ -132,8 +137,8 @@ impl CountrySymbol {
};
SimplePolygonSymbol::new(fill_color)
.with_stroke_color(stroke_color)
.with_stroke_width(1.0)
.with_stroke_offset(-0.5)
.with_stroke_width(2.0)
.with_stroke_offset(-1.0)
}
}

Expand Down
4 changes: 2 additions & 2 deletions galileo/examples/lambert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ impl CountrySymbol {
};
SimplePolygonSymbol::new(fill_color)
.with_stroke_color(stroke_color)
.with_stroke_width(1.0)
.with_stroke_offset(-0.5)
.with_stroke_width(2.0)
.with_stroke_offset(-1.0)
}
}

Expand Down
40 changes: 32 additions & 8 deletions galileo/src/layer/feature_layer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ where
render_bundle: RwLock<Option<Box<dyn PackedBundle>>>,
feature_render_map: RwLock<Vec<Vec<PrimitiveId>>>,
crs: Crs,
lods: Option<Vec<f32>>,
messenger: RwLock<Option<Box<dyn Messenger>>>,

space: PhantomData<Space>,
Expand All @@ -53,6 +54,20 @@ where
feature_render_map: RwLock::new(Vec::new()),
crs,
messenger: RwLock::new(None),
lods: None,
space: Default::default(),
}
}

pub fn with_lods(features: Vec<F>, style: S, crs: Crs, lods: Vec<f32>) -> Self {
Self {
features,
symbol: style,
render_bundle: RwLock::new(None),
feature_render_map: RwLock::new(Vec::new()),
crs,
messenger: RwLock::new(None),
lods: Some(lods),
space: Default::default(),
}
}
Expand Down Expand Up @@ -144,12 +159,12 @@ where
F::Geom: Geometry<Point = P>,
S: Symbol<F> + MaybeSend + MaybeSync,
{
fn render(&self, position: &MapView, canvas: &mut dyn Canvas) {
fn render(&self, view: &MapView, canvas: &mut dyn Canvas) {
if self.render_bundle.read().unwrap().is_none() {
let mut bundle = canvas.create_bundle();
let mut bundle = canvas.create_bundle(&self.lods);
let mut render_map = self.feature_render_map.write().unwrap();
let projection = ChainProjection::new(
position.crs().get_projection::<P, Point2d>().unwrap(),
view.crs().get_projection::<P, Point2d>().unwrap(),
Box::new(AddDimensionProjection::new(0.0)),
);

Expand All @@ -167,7 +182,10 @@ where
*self.render_bundle.write().unwrap() = Some(packed);
}

canvas.draw_bundles(&[&**self.render_bundle.read().unwrap().as_ref().unwrap()]);
canvas.draw_bundles(
&[&**self.render_bundle.read().unwrap().as_ref().unwrap()],
view.resolution() as f32,
);
}

fn prepare(&self, _view: &MapView, _renderer: &Arc<RwLock<dyn Renderer>>) {
Expand All @@ -188,7 +206,7 @@ where
{
fn render(&self, view: &MapView, canvas: &mut dyn Canvas) {
if self.render_bundle.read().unwrap().is_none() {
let mut bundle = canvas.create_bundle();
let mut bundle = canvas.create_bundle(&self.lods);
let mut render_map = self.feature_render_map.write().unwrap();

let projection: Box<dyn Projection<InPoint = _, OutPoint = Point3d>> =
Expand Down Expand Up @@ -219,7 +237,10 @@ where
*self.render_bundle.write().unwrap() = Some(packed);
}

canvas.draw_bundles(&[&**self.render_bundle.read().unwrap().as_ref().unwrap()]);
canvas.draw_bundles(
&[&**self.render_bundle.read().unwrap().as_ref().unwrap()],
view.resolution() as f32,
);
}

fn prepare(&self, _view: &MapView, _renderer: &Arc<RwLock<dyn Renderer>>) {
Expand All @@ -246,7 +267,7 @@ where
}

if self.render_bundle.read().unwrap().is_none() {
let mut bundle = canvas.create_bundle();
let mut bundle = canvas.create_bundle(&self.lods);
let mut render_map = self.feature_render_map.write().unwrap();

for feature in &self.features {
Expand All @@ -263,7 +284,10 @@ where
*self.render_bundle.write().unwrap() = Some(packed);
}

canvas.draw_bundles(&[&**self.render_bundle.read().unwrap().as_ref().unwrap()]);
canvas.draw_bundles(
&[&**self.render_bundle.read().unwrap().as_ref().unwrap()],
view.resolution() as f32,
);
}

fn prepare(&self, _view: &MapView, _renderer: &Arc<RwLock<dyn Renderer>>) {
Expand Down
4 changes: 2 additions & 2 deletions galileo/src/layer/feature_layer/symbol/contour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ impl<F> Symbol<F> for SimpleContourSymbol {
};

match geometry {
Geom::Contour(contour) => vec![bundle.add_line(contour, paint, 10000.0)],
Geom::Contour(contour) => vec![bundle.add_line(contour, paint)],
Geom::MultiContour(contours) => contours
.contours()
.map(|contour| bundle.add_line(contour, paint, 10000.0))
.map(|contour| bundle.add_line(contour, paint))
.collect(),
_ => vec![],
}
Expand Down
3 changes: 1 addition & 2 deletions galileo/src/layer/feature_layer/symbol/polygon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ impl SimplePolygonSymbol {
Paint {
color: self.fill_color,
},
10000.0,
);

ids.push(id);
Expand All @@ -71,7 +70,7 @@ impl SimplePolygonSymbol {
};

for contour in polygon.iter_contours() {
ids.push(bundle.add_line(contour, line_paint, 10000.0));
ids.push(bundle.add_line(contour, line_paint));
}

ids
Expand Down
4 changes: 2 additions & 2 deletions galileo/src/layer/raster_tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl RasterTileLayer {
}

if tile_renders.get(&tile.index).is_none() {
let mut bundle = canvas.create_bundle();
let mut bundle = canvas.create_bundle(&None);

// todo: there should not be clone() here
let id = bundle.add_image(
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Layer for RasterTileLayer {
}
}

canvas.draw_bundles(&to_draw);
canvas.draw_bundles(&to_draw, view.resolution() as f32);
*self.prev_drawn_tiles.lock() = tiles.iter().map(|t| t.index).collect();
}

Expand Down
2 changes: 1 addition & 1 deletion galileo/src/layer/vector_tile_layer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<Provider: VectorTileProvider + 'static> Layer for VectorTileLayer<Provider>
let tiles = self.get_tiles_to_draw(view, &tiles_store);
let to_render: Vec<&dyn PackedBundle> = tiles.iter().map(|v| &*v.bundle).collect();

canvas.draw_bundles(&to_render);
canvas.draw_bundles(&to_render, view.resolution() as f32);
}

fn prepare(&self, view: &MapView, renderer: &Arc<RwLock<dyn Renderer>>) {
Expand Down
3 changes: 0 additions & 3 deletions galileo/src/layer/vector_tile_layer/vector_tile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ impl VectorTile {
Paint {
color: style.background,
},
lod_resolution,
);

for layer in &mvt_tile.layers {
Expand All @@ -80,7 +79,6 @@ impl VectorTile {
.collect(),
},
paint,
lod_resolution,
);
}
}
Expand All @@ -93,7 +91,6 @@ impl VectorTile {
Self::transform_point(p, bbox, tile_resolution)
}),
paint,
lod_resolution,
);
}
}
Expand Down
8 changes: 2 additions & 6 deletions galileo/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ pub mod render_bundle;
#[derive(Debug, Copy, Clone, PartialEq, Hash)]
pub struct PrimitiveId(usize);

impl PrimitiveId {
const INVALID: PrimitiveId = PrimitiveId(usize::MAX);
}

pub trait Renderer: MaybeSend + MaybeSync {
fn create_bundle(&self) -> RenderBundle;
fn pack_bundle(&self, bundle: RenderBundle) -> Box<dyn PackedBundle>;
Expand All @@ -25,10 +21,10 @@ pub trait Renderer: MaybeSend + MaybeSync {

pub trait Canvas {
fn size(&self) -> Size;
fn create_bundle(&self) -> RenderBundle;
fn create_bundle(&self, lods: &Option<Vec<f32>>) -> RenderBundle;
fn pack_bundle(&self, bundle: RenderBundle) -> Box<dyn PackedBundle>;
fn pack_unpacked(&self, bundle: Box<dyn UnpackedBundle>) -> Box<dyn PackedBundle>;
fn draw_bundles(&mut self, bundles: &[&dyn PackedBundle]);
fn draw_bundles(&mut self, bundles: &[&dyn PackedBundle], resolution: f32);
}

pub trait PackedBundle: MaybeSend + MaybeSync {
Expand Down
13 changes: 4 additions & 9 deletions galileo/src/render/render_bundle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,26 @@ impl RenderBundle {
}
}

pub fn add_line<N, P, C>(&mut self, line: &C, paint: LinePaint, resolution: f64) -> PrimitiveId
pub fn add_line<N, P, C>(&mut self, line: &C, paint: LinePaint) -> PrimitiveId
where
N: AsPrimitive<f32>,
P: CartesianPoint3d<Num = N>,
C: Contour<Point = P>,
{
match self {
RenderBundle::Tessellating(inner) => inner.add_line(line, paint, resolution),
RenderBundle::Tessellating(inner) => inner.add_line(line, paint),
}
}

pub fn add_polygon<N, P, Poly>(
&mut self,
polygon: &Poly,
paint: Paint,
resolution: f64,
) -> PrimitiveId
pub fn add_polygon<N, P, Poly>(&mut self, polygon: &Poly, paint: Paint) -> PrimitiveId
where
N: AsPrimitive<f32>,
P: CartesianPoint3d<Num = N>,
Poly: Polygon,
Poly::Contour: Contour<Point = P>,
{
match self {
RenderBundle::Tessellating(inner) => inner.add_polygon(polygon, paint, resolution),
RenderBundle::Tessellating(inner) => inner.add_polygon(polygon, paint),
}
}

Expand Down
Loading

0 comments on commit 77689e7

Please sign in to comment.