render in img
This commit is contained in:
parent
5df83c4398
commit
4ec48fc21c
@ -2,6 +2,6 @@ fn main() {
|
|||||||
glib_build_tools::compile_resources(
|
glib_build_tools::compile_resources(
|
||||||
&["src/resources"],
|
&["src/resources"],
|
||||||
"src/resources/resources.gresource.xml",
|
"src/resources/resources.gresource.xml",
|
||||||
"monitor.gresource",
|
"p.gresource",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
BIN
src/assets/Roboto-Bold.ttf
Normal file
BIN
src/assets/Roboto-Bold.ttf
Normal file
Binary file not shown.
BIN
src/assets/Roboto-Light.ttf
Normal file
BIN
src/assets/Roboto-Light.ttf
Normal file
Binary file not shown.
BIN
src/assets/Roboto-Regular.ttf
Normal file
BIN
src/assets/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
src/assets/amiri-regular.ttf
Normal file
BIN
src/assets/amiri-regular.ttf
Normal file
Binary file not shown.
BIN
src/assets/entypo.ttf
Normal file
BIN
src/assets/entypo.ttf
Normal file
Binary file not shown.
@ -1,21 +1,20 @@
|
|||||||
|
use super::{proj::ProjectionS, Range};
|
||||||
use geo_types::{coord, Coord as GCoord, LineString};
|
use geo_types::{coord, Coord as GCoord, LineString};
|
||||||
use proj::{Proj, ProjError};
|
use proj::{Proj, ProjError};
|
||||||
use std::ops::Range;
|
use std::ops;
|
||||||
|
|
||||||
use super::proj::ProjectionS;
|
|
||||||
|
|
||||||
pub struct Mapper {
|
pub struct Mapper {
|
||||||
proj: Proj,
|
proj: Proj,
|
||||||
range: (Range<f64>, Range<f64>),
|
pub range: (Range, Range),
|
||||||
bounds: (f64, f64, f64, f64),
|
bounds: (f64, f64, f64, f64),
|
||||||
}
|
}
|
||||||
impl From<Proj> for Mapper {
|
impl From<Proj> for Mapper {
|
||||||
fn from(proj: Proj) -> Self {
|
fn from(proj: Proj) -> Self {
|
||||||
let default_range: (Range<f64>, Range<f64>) = (-180.0..180.0, -90.0..90.0);
|
let default_range: (Range, Range) = ((-180.0..180.0).into(), (-90.0..90.0).into());
|
||||||
let bounds = Self::bound(&proj, default_range.clone()).unwrap();
|
let bounds = Self::bound(&proj, default_range.clone()).unwrap();
|
||||||
Self {
|
Self {
|
||||||
proj: proj,
|
proj: proj,
|
||||||
range: default_range,
|
range: (default_range.0.into(), default_range.1.into()),
|
||||||
bounds,
|
bounds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,9 +28,13 @@ impl<C: ProjectionS> From<C> for Mapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Mapper {
|
impl Mapper {
|
||||||
pub fn new(proj: Proj, lon_range: Range<f64>, lat_range: Range<f64>) -> Self {
|
pub fn new(
|
||||||
let bounds = Self::bound(&proj, (lon_range.clone(), lat_range.clone())).unwrap();
|
proj: Proj,
|
||||||
let range = (lon_range, lat_range);
|
lon_range: std::ops::Range<f64>,
|
||||||
|
lat_range: std::ops::Range<f64>,
|
||||||
|
) -> Self {
|
||||||
|
let bounds = Self::bound(&proj, (lon_range.clone().into(), lat_range.clone().into())).unwrap();
|
||||||
|
let range = (lon_range.into(), lat_range.into());
|
||||||
Self {
|
Self {
|
||||||
proj: proj,
|
proj: proj,
|
||||||
range,
|
range,
|
||||||
@ -50,22 +53,19 @@ impl Mapper {
|
|||||||
Ok((x, y))
|
Ok((x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lon_range(&mut self, range: Range<f64>) {
|
pub fn set_lon_range(&mut self, range: std::ops::Range<f64>) {
|
||||||
self.range.0 = range;
|
self.range.0 = range.into();
|
||||||
self.bounds = Self::bound(&self.proj, self.range.clone()).unwrap();
|
self.bounds = Self::bound(&self.proj, self.range.clone()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lat_range(&mut self, range: Range<f64>) {
|
pub fn set_lat_range(&mut self, range: std::ops::Range<f64>) {
|
||||||
self.range.1 = range;
|
self.range.1 = range.into();
|
||||||
self.bounds = Self::bound(&self.proj, self.range.clone()).unwrap();
|
self.bounds = Self::bound(&self.proj, self.range.clone()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bound(
|
fn bound(proj: &Proj, range: (Range, Range)) -> Result<(f64, f64, f64, f64), ProjError> {
|
||||||
proj: &Proj,
|
let left_bottom = proj.convert((range.0 .0.to_radians(), range.1 .0.to_radians()))?;
|
||||||
range: (Range<f64>, Range<f64>),
|
let right_top = proj.convert((range.0 .1.to_radians(), range.1 .1.to_radians()))?;
|
||||||
) -> Result<(f64, f64, f64, f64), ProjError> {
|
|
||||||
let left_bottom = proj.convert((range.0.start.to_radians(), range.1.start.to_radians()))?;
|
|
||||||
let right_top = proj.convert((range.0.end.to_radians(), range.1.end.to_radians()))?;
|
|
||||||
Ok((left_bottom.0, right_top.0, left_bottom.1, right_top.1))
|
Ok((left_bottom.0, right_top.0, left_bottom.1, right_top.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ impl Mapper {
|
|||||||
let delta2 = 0.5;
|
let delta2 = 0.5;
|
||||||
let depth = 16;
|
let depth = 16;
|
||||||
let mut res: Vec<GCoord> = Vec::new();
|
let mut res: Vec<GCoord> = Vec::new();
|
||||||
res.push(l.start);
|
res.push(p.start);
|
||||||
self.resample_line_to(
|
self.resample_line_to(
|
||||||
start_projected,
|
start_projected,
|
||||||
end_projected,
|
end_projected,
|
||||||
@ -94,7 +94,7 @@ impl Mapper {
|
|||||||
depth,
|
depth,
|
||||||
&mut res,
|
&mut res,
|
||||||
)?;
|
)?;
|
||||||
res.push(l.end);
|
res.push(p.end);
|
||||||
result.extend(res);
|
result.extend(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ pub mod proj;
|
|||||||
pub mod wgs84;
|
pub mod wgs84;
|
||||||
|
|
||||||
pub use mapper::Mapper;
|
pub use mapper::Mapper;
|
||||||
pub use wgs84::LatLonCoord;
|
// pub use wgs84::LatLonCoord;
|
||||||
|
|
||||||
pub type ScreenCoord = (f64, f64);
|
pub type ScreenCoord = (f64, f64);
|
||||||
type Lat = f64;
|
type Lat = f64;
|
||||||
@ -114,6 +114,14 @@ impl<T: AsPrimitive<f64> + Num> From<(T, T)> for Range {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Num + AsPrimitive<f64>> From<std::ops::Range<T>> for Range {
|
||||||
|
fn from(value: std::ops::Range<T>) -> Self {
|
||||||
|
let value = (value.start.as_(), value.end.as_());
|
||||||
|
let (_min, _max) = (value.0.min(value.1), value.0.max(value.1));
|
||||||
|
Self(_min, _max)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl<T, Raw> RadarData2d<T, Raw>
|
// impl<T, Raw> RadarData2d<T, Raw>
|
||||||
// where
|
// where
|
||||||
// T: Num + Clone + PartialEq + PartialOrd,
|
// T: Num + Clone + PartialEq + PartialOrd,
|
||||||
|
|||||||
@ -8,10 +8,6 @@ use geo_macros::Prj;
|
|||||||
pub struct Mercator {
|
pub struct Mercator {
|
||||||
/// The central longitude of the projection.
|
/// The central longitude of the projection.
|
||||||
pub central_lon: f64,
|
pub central_lon: f64,
|
||||||
/// The minimum latitude of the projection.
|
|
||||||
pub min_latitude: f64,
|
|
||||||
/// The maximum latitude of the projection.
|
|
||||||
pub max_latitude: f64,
|
|
||||||
/// The false easting of the projection.
|
/// The false easting of the projection.
|
||||||
pub false_easting: f64,
|
pub false_easting: f64,
|
||||||
/// The false northing of the projection.
|
/// The false northing of the projection.
|
||||||
@ -32,8 +28,6 @@ impl Mercator {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
central_lon: 0.0,
|
central_lon: 0.0,
|
||||||
min_latitude: -82.0,
|
|
||||||
max_latitude: 82.0,
|
|
||||||
false_easting: 0.0,
|
false_easting: 0.0,
|
||||||
false_northing: 0.0,
|
false_northing: 0.0,
|
||||||
latitude_true_scale: 0.0,
|
latitude_true_scale: 0.0,
|
||||||
@ -61,20 +55,4 @@ impl ProjectionS for Mercator {
|
|||||||
_proj_string
|
_proj_string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logic_range(&self, lon_range: Option<Range>, lat_range: Option<Range>) -> (Range, Range) {
|
|
||||||
let lon_range = lon_range.unwrap_or(Range {
|
|
||||||
0: -180f64,
|
|
||||||
1: 180f64,
|
|
||||||
});
|
|
||||||
let lat_range = lat_range.unwrap_or(Range {
|
|
||||||
0: self.min_latitude,
|
|
||||||
1: self.max_latitude,
|
|
||||||
});
|
|
||||||
|
|
||||||
let lat_range = Range {
|
|
||||||
0: lat_range.0.max(self.min_latitude),
|
|
||||||
1: lat_range.1.min(self.max_latitude),
|
|
||||||
};
|
|
||||||
(lon_range, lat_range)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,18 +18,6 @@ pub enum Projs {
|
|||||||
pub trait ProjectionS {
|
pub trait ProjectionS {
|
||||||
/// Returns a proj-string of the projection.
|
/// Returns a proj-string of the projection.
|
||||||
fn build(&self) -> String;
|
fn build(&self) -> String;
|
||||||
|
|
||||||
/// Returns the logical range of the projection.
|
|
||||||
/// In common, different projections have different logical ranges.
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `lon_range` - An optional longitude range.
|
|
||||||
/// * `lat_range` - An optional latitude range.
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// A tuple containing the longitude and latitude ranges.
|
|
||||||
fn logic_range(&self, lon_range: Option<Range>, lat_range: Option<Range>) -> (Range, Range);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@ -38,42 +26,42 @@ pub(super) enum ProjError {
|
|||||||
ProjError(#[from] proj::ProjError),
|
ProjError(#[from] proj::ProjError),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct PCS<T: ProjectionS> {
|
// pub(super) struct PCS<T: ProjectionS> {
|
||||||
pub lon_range: Range,
|
// pub lon_range: Range,
|
||||||
pub lat_range: Range,
|
// pub lat_range: Range,
|
||||||
pub proj_param: T,
|
// pub proj_param: T,
|
||||||
// pub proj_target: proj5::CoordinateBuf,
|
// // pub proj_target: proj5::CoordinateBuf,
|
||||||
pub transformer: Proj,
|
// pub transformer: Proj,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<T: ProjectionS> PCS<T> {
|
// impl<T: ProjectionS> PCS<T> {
|
||||||
pub(super) fn new(proj_param: T, lon_range: Option<Range>, lat_range: Option<Range>) -> Self {
|
// pub(super) fn new(proj_param: T, lon_range: Option<Range>, lat_range: Option<Range>) -> Self {
|
||||||
let (lon_range, lat_range) = proj_param.logic_range(lon_range, lat_range);
|
// let (lon_range, lat_range) = proj_param.logic_range(lon_range, lat_range);
|
||||||
Self {
|
// Self {
|
||||||
lon_range,
|
// lon_range,
|
||||||
lat_range,
|
// lat_range,
|
||||||
transformer: Proj::new(proj_param.build().as_str()).unwrap(),
|
// transformer: Proj::new(proj_param.build().as_str()).unwrap(),
|
||||||
proj_param: proj_param,
|
// proj_param: proj_param,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn bbox(&self) -> Result<(Range, Range), ProjError> {
|
// pub fn bbox(&self) -> Result<(Range, Range), ProjError> {
|
||||||
let _proj_transformer = &self.transformer;
|
// let _proj_transformer = &self.transformer;
|
||||||
let lb = (self.lon_range.0.to_radians(), self.lat_range.0.to_radians());
|
// let lb = (self.lon_range.0.to_radians(), self.lat_range.0.to_radians());
|
||||||
let rt = (self.lon_range.1.to_radians(), self.lat_range.1.to_radians());
|
// let rt = (self.lon_range.1.to_radians(), self.lat_range.1.to_radians());
|
||||||
|
|
||||||
let bl = _proj_transformer.convert(lb)?;
|
// let bl = _proj_transformer.convert(lb)?;
|
||||||
let rt = _proj_transformer.convert(rt)?;
|
// let rt = _proj_transformer.convert(rt)?;
|
||||||
|
|
||||||
Ok((Range::from((bl.0, rt.0)), Range::from((bl.1, rt.1))))
|
// Ok((Range::from((bl.0, rt.0)), Range::from((bl.1, rt.1))))
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn map(&self, lon_lat: (Lat, Lon)) -> (f64, f64) {
|
// pub fn map(&self, lon_lat: (Lat, Lon)) -> (f64, f64) {
|
||||||
let _proj_transformer = &self.transformer;
|
// let _proj_transformer = &self.transformer;
|
||||||
let _lon_lat = _proj_transformer
|
// let _lon_lat = _proj_transformer
|
||||||
.convert((lon_lat.0.to_radians(), lon_lat.1.to_radians()))
|
// .convert((lon_lat.0.to_radians(), lon_lat.1.to_radians()))
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
|
|
||||||
_lon_lat
|
// _lon_lat
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::proj::{ProjectionS, PCS};
|
// use super::proj::{ProjectionS, PCS};
|
||||||
use super::Coord;
|
use super::Coord;
|
||||||
use super::{Lat, Lon, Range};
|
use super::{Lat, Lon, Range};
|
||||||
use proj::ProjError;
|
use proj::ProjError;
|
||||||
@ -13,76 +13,76 @@ pub enum CoordError {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LatLonCoord<T: ProjectionS> {
|
// pub struct LatLonCoord<T: ProjectionS> {
|
||||||
actual: (Range, Range),
|
// actual: (Range, Range),
|
||||||
logical: (Range, Range),
|
// logical: (Range, Range),
|
||||||
pcs: PCS<T>,
|
// pcs: PCS<T>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<T: ProjectionS> LatLonCoord<T> {
|
// impl<T: ProjectionS> LatLonCoord<T> {
|
||||||
/// Creates a new `LatLonCoord` instance.
|
// /// Creates a new `LatLonCoord` instance.
|
||||||
///
|
// ///
|
||||||
/// # Arguments
|
// /// # Arguments
|
||||||
///
|
// ///
|
||||||
/// * `lon` - An optional longitude range.
|
// /// * `lon` - An optional longitude range.
|
||||||
/// * `lat` - An optional latitude range.
|
// /// * `lat` - An optional latitude range.
|
||||||
/// * `actual` - A tuple containing the actual ranges.
|
// /// * `actual` - A tuple containing the actual ranges.
|
||||||
/// * `project` - A projection.
|
// /// * `project` - A projection.
|
||||||
///
|
// ///
|
||||||
/// # Returns
|
// /// # Returns
|
||||||
///
|
// ///
|
||||||
/// A new `LatLonCoord` instance.
|
// /// A new `LatLonCoord` instance.
|
||||||
pub fn new(
|
// pub fn new(
|
||||||
lon: Option<Range>,
|
// lon: Option<Range>,
|
||||||
lat: Option<Range>,
|
// lat: Option<Range>,
|
||||||
actual: ((i32, i32), (i32, i32)),
|
// actual: ((i32, i32), (i32, i32)),
|
||||||
// actual: (Range, Range),
|
// // actual: (Range, Range),
|
||||||
project: T,
|
// project: T,
|
||||||
) -> Self {
|
// ) -> Self {
|
||||||
let pcs = PCS::new(project, lon, lat);
|
// let pcs = PCS::new(project, lon, lat);
|
||||||
let _box = pcs.bbox().unwrap();
|
// let _box = pcs.bbox().unwrap();
|
||||||
Self {
|
// Self {
|
||||||
actual: (Range::from(actual.0), Range::from(actual.1)),
|
// actual: (Range::from(actual.0), Range::from(actual.1)),
|
||||||
pcs: pcs,
|
// pcs: pcs,
|
||||||
logical: _box,
|
// logical: _box,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn set_actual(&mut self, actual: ((i32, i32), (i32, i32))) {
|
// pub fn set_actual(&mut self, actual: ((i32, i32), (i32, i32))) {
|
||||||
self.actual = (Range::from(actual.0), Range::from(actual.1));
|
// self.actual = (Range::from(actual.0), Range::from(actual.1));
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn lon_range(&self) -> Range {
|
// pub fn lon_range(&self) -> Range {
|
||||||
self.pcs.lon_range
|
// self.pcs.lon_range
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn lat_range(&self) -> Range {
|
// pub fn lat_range(&self) -> Range {
|
||||||
self.pcs.lat_range
|
// self.pcs.lat_range
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<T: ProjectionS> Coord<f64> for LatLonCoord<T> {
|
// impl<T: ProjectionS> Coord<f64> for LatLonCoord<T> {
|
||||||
fn map(&self, axis_1: f64, axis_2: f64) -> super::ScreenCoord {
|
// fn map(&self, axis_1: f64, axis_2: f64) -> super::ScreenCoord {
|
||||||
let point = self.pcs.map((axis_1, axis_2));
|
// let point = self.pcs.map((axis_1, axis_2));
|
||||||
let logical_dim1_span = self.logical.0 .1 - self.logical.0 .0;
|
// let logical_dim1_span = self.logical.0 .1 - self.logical.0 .0;
|
||||||
|
|
||||||
let dim1_rate = (point.0 - self.logical.0 .0) / logical_dim1_span;
|
// let dim1_rate = (point.0 - self.logical.0 .0) / logical_dim1_span;
|
||||||
let logical_dim2_span = self.logical.1 .1 - self.logical.1 .0;
|
// let logical_dim2_span = self.logical.1 .1 - self.logical.1 .0;
|
||||||
let dim2_rate = (point.1 - self.logical.1 .0) / logical_dim2_span;
|
// let dim2_rate = (point.1 - self.logical.1 .0) / logical_dim2_span;
|
||||||
|
|
||||||
(
|
// (
|
||||||
(dim1_rate * (self.actual.0 .1 - self.actual.0 .0) as f64) + self.actual.0 .0,
|
// (dim1_rate * (self.actual.0 .1 - self.actual.0 .0) as f64) + self.actual.0 .0,
|
||||||
(dim2_rate * (self.actual.1 .1 - self.actual.1 .0) as f64) + self.actual.1 .0,
|
// (dim2_rate * (self.actual.1 .1 - self.actual.1 .0) as f64) + self.actual.1 .0,
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn dim1_range(&self) -> (f64, f64) {
|
// fn dim1_range(&self) -> (f64, f64) {
|
||||||
let v = self.lon_range();
|
// let v = self.lon_range();
|
||||||
(v.0, v.1)
|
// (v.0, v.1)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn dim2_range(&self) -> (f64, f64) {
|
// fn dim2_range(&self) -> (f64, f64) {
|
||||||
let v = self.lat_range();
|
// let v = self.lat_range();
|
||||||
(v.0, v.1)
|
// (v.0, v.1)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|||||||
15
src/main.rs
15
src/main.rs
@ -1,6 +1,7 @@
|
|||||||
use coords::proj::Mercator;
|
use coords::proj::Mercator;
|
||||||
use coords::Mapper;
|
use coords::Mapper;
|
||||||
use data::{Npz, Radar2d};
|
use data::{Npz, Radar2d};
|
||||||
|
use femtovg::{Color, Paint};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{gio, glib, Application, ApplicationWindow};
|
use gtk::{gio, glib, Application, ApplicationWindow};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@ -10,7 +11,6 @@ mod errors;
|
|||||||
mod monitor;
|
mod monitor;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod render;
|
mod render;
|
||||||
mod tree;
|
|
||||||
mod window;
|
mod window;
|
||||||
use monitor::Monitor;
|
use monitor::Monitor;
|
||||||
use render::{BackgroundConfig, BackgroundWidget, ForegroundConfig, ForegroundWidget, Render};
|
use render::{BackgroundConfig, BackgroundWidget, ForegroundConfig, ForegroundWidget, Render};
|
||||||
@ -29,8 +29,11 @@ fn main() -> glib::ExitCode {
|
|||||||
.or_else(|_| libloading::os::windows::Library::open_already_loaded("epoxy-0.dll"))
|
.or_else(|_| libloading::os::windows::Library::open_already_loaded("epoxy-0.dll"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
gio::resources_register_include!("p.gresource")
|
||||||
|
.expect("Failed to register resources.");
|
||||||
|
|
||||||
epoxy::load_with(|name| {
|
epoxy::load_with(|name| {
|
||||||
unsafe { library.get::<_>(name.as_bytes()) }
|
unsafe { library.get::<>(name.as_bytes()) }
|
||||||
.map(|symbol| *symbol)
|
.map(|symbol| *symbol)
|
||||||
.unwrap_or(ptr::null())
|
.unwrap_or(ptr::null())
|
||||||
});
|
});
|
||||||
@ -52,16 +55,20 @@ fn build_ui(app: &Application) {
|
|||||||
.title("My GTK App")
|
.title("My GTK App")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut background_config = BackgroundConfig::new();
|
let mut background_config = BackgroundConfig::new()
|
||||||
|
.change_painter(Paint::color(Color::white()))
|
||||||
|
.change_show_lat_lines(true)
|
||||||
|
.change_show_lon_lines(true);
|
||||||
let mut foreground_config = ForegroundConfig::new();
|
let mut foreground_config = ForegroundConfig::new();
|
||||||
|
|
||||||
let background_widget = BackgroundWidget::new(background_config);
|
let background_widget = BackgroundWidget::new(background_config);
|
||||||
let foreground_widget = ForegroundWidget::new(foreground_config);
|
let foreground_widget = ForegroundWidget::new(foreground_config);
|
||||||
let render = Render::new(background_widget, foreground_widget);
|
let render = Render::new(background_widget, foreground_widget);
|
||||||
|
|
||||||
let path = "/Users/ruomu/projects/cinrad_g/test2.npz";
|
let path = "/Users/tsuki/projects/radar-g/test2.npz";
|
||||||
let data = Radar2d::<i8>::load(path, Npz).unwrap();
|
let data = Radar2d::<i8>::load(path, Npz).unwrap();
|
||||||
let projection = Mercator::new();
|
let projection = Mercator::new();
|
||||||
|
|
||||||
let mut mapper: Mapper = projection.into();
|
let mut mapper: Mapper = projection.into();
|
||||||
mapper.set_lat_range(29.960..30.764);
|
mapper.set_lat_range(29.960..30.764);
|
||||||
mapper.set_lon_range(120.038..120.965);
|
mapper.set_lon_range(120.038..120.965);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
use anyhow::{Ok, Result};
|
use anyhow::{Ok, Result};
|
||||||
use femtovg;
|
use femtovg::{self};
|
||||||
use geo_types::{line_string, LineString};
|
use geo_types::{line_string, LineString};
|
||||||
use image::RgbImage;
|
use image::RgbImage;
|
||||||
use ndarray::Array2;
|
use ndarray::parallel::prelude::*;
|
||||||
use num_traits::Num;
|
use ndarray::{Array2, ArrayView2};
|
||||||
|
use num_traits::{Num, AsPrimitive, FromPrimitive};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
coords::Mapper,
|
coords::Mapper,
|
||||||
@ -18,22 +19,34 @@ impl Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<femtovg::Color> for Color {
|
||||||
|
fn from(value: femtovg::Color) -> Self {
|
||||||
|
Self(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Pipeline<T> {
|
pub trait Pipeline<T> {
|
||||||
type Output;
|
type Output;
|
||||||
fn run(&self, input: T) -> Result<Self::Output>;
|
fn run(&self, input: T) -> Result<Self::Output>;
|
||||||
}
|
}
|
||||||
pub struct ProjPipe {
|
pub struct ProjPipe<'a> {
|
||||||
pub mapper: Mapper,
|
pub mapper: &'a Mapper,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Raw> Pipeline<RadarData2d<T, Raw>> for ProjPipe
|
impl<'a> ProjPipe<'a> {
|
||||||
|
pub fn new(mapper: &'a Mapper) -> Self {
|
||||||
|
Self { mapper }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b: 'a, T, Raw> Pipeline<&'b RadarData2d<T, Raw>> for ProjPipe<'a>
|
||||||
where
|
where
|
||||||
T: Num + Clone + PartialEq + PartialOrd,
|
T: Num + Clone + PartialEq + PartialOrd,
|
||||||
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
|
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
|
||||||
{
|
{
|
||||||
type Output = Array2<LineString>;
|
type Output = Array2<LineString>;
|
||||||
|
|
||||||
fn run(&self, input: RadarData2d<T, Raw>) -> Result<Self::Output> {
|
fn run(&self, input: &'b RadarData2d<T, Raw>) -> Result<Self::Output> {
|
||||||
let dim1 = input.dim1.view();
|
let dim1 = input.dim1.view();
|
||||||
let dim2 = input.dim2.view();
|
let dim2 = input.dim2.view();
|
||||||
|
|
||||||
@ -92,3 +105,26 @@ impl<T: Num + PartialOrd> ShadePipe<T> {
|
|||||||
&self.colors[left]
|
&self.colors[left]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T, Raw> Pipeline<&'a RadarData2d<T, Raw>> for ShadePipe<T>
|
||||||
|
where
|
||||||
|
T: Num + PartialEq + PartialOrd + Clone + FromPrimitive,
|
||||||
|
Raw: ndarray::Data<Elem = T> + Clone + ndarray::RawDataClone,
|
||||||
|
{
|
||||||
|
type Output = Array2<Option<femtovg::Color>>;
|
||||||
|
|
||||||
|
fn run(&self, input: &'a RadarData2d<T, Raw>) -> Result<Array2<Option<femtovg::Color>>> {
|
||||||
|
let data = input.data.view();
|
||||||
|
|
||||||
|
let result = data.mapv(|v| {
|
||||||
|
if T::from_i8(-125).unwrap() == v {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let color = self.get_color(v);
|
||||||
|
Some(color.0)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ use std::cell::RefCell;
|
|||||||
pub struct BackgroundConfig {
|
pub struct BackgroundConfig {
|
||||||
pub show_lat_lines: bool,
|
pub show_lat_lines: bool,
|
||||||
pub show_lon_lines: bool,
|
pub show_lon_lines: bool,
|
||||||
pub lat_lines: Vec<Vec<WindowCoord>>,
|
pub lat_lines: Vec<f64>,
|
||||||
pub lon_lines: Vec<Vec<WindowCoord>>,
|
pub lon_lines: Vec<f64>,
|
||||||
pub painter: Paint,
|
pub painter: Paint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
mod imp;
|
mod imp;
|
||||||
use crate::render::WindowCoord;
|
use crate::coords::{Mapper, Range};
|
||||||
use femtovg::{renderer::OpenGl, Canvas, Path};
|
use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path};
|
||||||
|
use geo_types::{line_string, LineString, Point};
|
||||||
use glib::subclass::types::ObjectSubclassIsExt;
|
use glib::subclass::types::ObjectSubclassIsExt;
|
||||||
use gtk::{ffi::gtk_widget_get_width, glib, graphene::Rect, prelude::SnapshotExtManual};
|
use std::cell::Ref;
|
||||||
use std::ops::Range;
|
|
||||||
|
|
||||||
pub use self::imp::BackgroundConfig;
|
pub use self::imp::BackgroundConfig;
|
||||||
|
|
||||||
@ -25,36 +25,122 @@ impl BackgroundWidget {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mesh_lines(&self, canvas: &mut Canvas<OpenGl>) {
|
fn draw_lines<V: IntoIterator<Item = LineString<f32>>>(
|
||||||
let imp = self.imp();
|
&self,
|
||||||
let line_painter = &imp.config.borrow().painter;
|
canvas: &mut Canvas<OpenGl>,
|
||||||
if imp.config.borrow().show_lat_lines {
|
line_painter: &Paint,
|
||||||
for lat_line in imp.config.borrow().lat_lines.iter() {
|
p: V,
|
||||||
|
) {
|
||||||
|
p.into_iter().for_each(|line| {
|
||||||
let mut path = Path::new();
|
let mut path = Path::new();
|
||||||
lat_line.iter().for_each(|v| {
|
let points: Vec<Point<f32>> = line.points().collect();
|
||||||
let (x, y) = *v;
|
path.move_to(points[0].x() as f32, points[0].y() as f32);
|
||||||
path.move_to(x, y);
|
points[1..].into_iter().for_each(|p| {
|
||||||
|
path.line_to(p.x() as f32, p.y() as f32);
|
||||||
});
|
});
|
||||||
canvas.stroke_path(&mut path, line_painter);
|
canvas.stroke_path(&mut path, line_painter);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
if imp.config.borrow().show_lon_lines {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self, canvas: &mut Canvas<OpenGl>, scale: f32, dpi: i32) {
|
fn mesh_lines(
|
||||||
let canvas_widht = canvas.width();
|
&self,
|
||||||
|
canvas: &mut Canvas<OpenGl>,
|
||||||
|
canvas_width: f32,
|
||||||
|
canvas_height: f32,
|
||||||
|
mapper: Ref<'_, Mapper>,
|
||||||
|
bound: (Range, Range),
|
||||||
|
) {
|
||||||
|
let imp = self.imp();
|
||||||
|
let line_painter = &imp.config.borrow().painter;
|
||||||
|
let (left, right) = (bound.0 .0, bound.0 .1);
|
||||||
|
let (bottom, top) = (bound.1 .0, bound.1 .1);
|
||||||
|
let config = imp.config.borrow();
|
||||||
|
|
||||||
|
if config.show_lat_lines {
|
||||||
|
let r = config.lat_lines.iter().map(|lat| {
|
||||||
|
let line = LineString::new(vec![(left, *lat).into(), (right, *lat).into()]);
|
||||||
|
let result = mapper.map_line(&line).unwrap();
|
||||||
|
LineString::new(
|
||||||
|
result
|
||||||
|
.points()
|
||||||
|
.map(|p| (p.x() as f32 * canvas_width, p.y() as f32 * canvas_height).into())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.draw_lines(canvas, line_painter, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.show_lat_lines {
|
||||||
|
config.lat_lines.iter().for_each(|lat| {
|
||||||
|
let mut paint = Paint::color(Color::white());
|
||||||
|
paint.set_font_size(35.0);
|
||||||
|
paint.set_line_width(1.0);
|
||||||
|
let text_location = mapper.map((left, *lat)).unwrap();
|
||||||
|
|
||||||
|
let _ = canvas.stroke_text(
|
||||||
|
text_location.0 as f32 * canvas_width,
|
||||||
|
text_location.1 as f32 * canvas_height,
|
||||||
|
format!("{:.2} N", lat),
|
||||||
|
&paint,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.show_lon_lines {
|
||||||
|
config.lon_lines.iter().for_each(|lon| {
|
||||||
|
let mut paint = Paint::color(Color::white());
|
||||||
|
paint.set_font_size(35.0);
|
||||||
|
paint.set_line_width(1.0);
|
||||||
|
let text_location = mapper.map((*lon, top + 0.1)).unwrap();
|
||||||
|
|
||||||
|
let _ = canvas.stroke_text(
|
||||||
|
text_location.0 as f32 * canvas_width,
|
||||||
|
text_location.1 as f32 * canvas_height,
|
||||||
|
format!("{:.2}", lon),
|
||||||
|
&paint,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if imp.config.borrow().show_lon_lines {
|
||||||
|
let r = config.lon_lines.iter().map(|lon| {
|
||||||
|
let line = LineString::new(vec![(*lon, bottom).into(), (*lon, top).into()]);
|
||||||
|
let result = mapper.map_line(&line).unwrap();
|
||||||
|
LineString::new(
|
||||||
|
result
|
||||||
|
.points()
|
||||||
|
.map(|p| (p.x() as f32 * canvas_width, p.y() as f32 * canvas_height).into())
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.draw_lines(canvas, line_painter, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(
|
||||||
|
&self,
|
||||||
|
canvas: &mut Canvas<OpenGl>,
|
||||||
|
scale: f32,
|
||||||
|
dpi: i32,
|
||||||
|
mapper: Ref<'_, Mapper>,
|
||||||
|
bound: (Range, Range),
|
||||||
|
) {
|
||||||
|
let canvas_width = canvas.width();
|
||||||
let canvas_height = canvas.height();
|
let canvas_height = canvas.height();
|
||||||
|
|
||||||
let config = self.imp().config.borrow();
|
let config = self.imp().config.borrow();
|
||||||
|
|
||||||
self.mesh_lines(canvas);
|
self.mesh_lines(canvas, canvas_width, canvas_height, mapper, bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lat_lines(&self, lat_lines: Vec<Vec<WindowCoord>>) {
|
pub fn set_lat_lines(&self, lat_lines: Vec<f64>) {
|
||||||
let imp = self.imp();
|
let imp = self.imp();
|
||||||
imp.config.borrow_mut().lat_lines = lat_lines;
|
imp.config.borrow_mut().lat_lines = lat_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_lon_lines(&self, lon_lines: Vec<Vec<WindowCoord>>) {
|
pub fn set_lon_lines(&self, lon_lines: Vec<f64>) {
|
||||||
let imp = self.imp();
|
let imp = self.imp();
|
||||||
imp.config.borrow_mut().lon_lines = lon_lines;
|
imp.config.borrow_mut().lon_lines = lon_lines;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::render::{imp, WindowCoord};
|
use crate::render::{imp, WindowCoord};
|
||||||
use femtovg::{ImageId, Paint};
|
use femtovg::{ImageId, Paint, Color};
|
||||||
use geo_macros::Prj;
|
use geo_macros::Prj;
|
||||||
use geo_types::LineString;
|
use geo_types::LineString;
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
@ -29,6 +29,7 @@ pub struct ForegroundWidget {
|
|||||||
pub(super) dim2: RefCell<Option<Array2<f64>>>,
|
pub(super) dim2: RefCell<Option<Array2<f64>>>,
|
||||||
pub(super) image: RefCell<Option<ImageId>>,
|
pub(super) image: RefCell<Option<ImageId>>,
|
||||||
pub(super) data: RefCell<Option<Array2<LineString>>>,
|
pub(super) data: RefCell<Option<Array2<LineString>>>,
|
||||||
|
pub(super) color: RefCell<Option<Array2<Option<Color>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
mod imp;
|
mod imp;
|
||||||
use crate::coords::Mapper;
|
use crate::coords::Mapper;
|
||||||
use crate::tree::get;
|
|
||||||
use femtovg::{renderer::OpenGl, Canvas, Path};
|
use femtovg::{renderer::OpenGl, Canvas, Path};
|
||||||
use femtovg::{Color, FontId, ImageFlags, Paint};
|
use femtovg::{Color, FontId, ImageFlags, ImageId, Paint};
|
||||||
use geo_types::LineString;
|
use geo_types::{LineString, Point};
|
||||||
use glib::subclass::types::ObjectSubclassIsExt;
|
use glib::subclass::types::ObjectSubclassIsExt;
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
use ndarray::{s, Array2, Axis, Zip};
|
use ndarray::{s, Array2, Axis, Zip};
|
||||||
@ -34,12 +33,12 @@ impl ForegroundWidget {
|
|||||||
let canvas_height = canvas.height();
|
let canvas_height = canvas.height();
|
||||||
let config = self.imp().config.borrow();
|
let config = self.imp().config.borrow();
|
||||||
|
|
||||||
println!("Resize: {} {}", canvas.width(), canvas.height());
|
let colors = self.imp().color.borrow();
|
||||||
|
let data = self.imp().data.borrow();
|
||||||
|
|
||||||
let mut img = self.imp().image.borrow_mut();
|
if self.imp().image.borrow().is_none() {
|
||||||
|
println!("rebuild image");
|
||||||
if img.is_none() {
|
let img_id = canvas
|
||||||
let mut img_id = canvas
|
|
||||||
.create_image_empty(
|
.create_image_empty(
|
||||||
canvas_width as usize,
|
canvas_width as usize,
|
||||||
canvas_height as usize,
|
canvas_height as usize,
|
||||||
@ -47,44 +46,75 @@ impl ForegroundWidget {
|
|||||||
ImageFlags::empty(),
|
ImageFlags::empty(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
canvas.save();
|
if let Ok(v) = canvas.image_size(img_id) {
|
||||||
canvas.reset();
|
println!("create image: {:?}", v);
|
||||||
if let Ok(size) = canvas.image_size(img_id) {
|
canvas.set_render_target(femtovg::RenderTarget::Image(img_id));
|
||||||
// canvas.set_render_target(femtovg::RenderTarget::Image(img_id));
|
let colors = self.imp().color.borrow();
|
||||||
canvas.clear_rect(0, 0, size.0 as u32, size.1 as u32, Color::rgb(255, 255, 0));
|
let data = self.imp().data.borrow();
|
||||||
|
if colors.is_some() && data.is_some() {
|
||||||
img.replace(img_id);
|
for (i, c) in colors
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.t()
|
||||||
|
.iter()
|
||||||
|
.zip(data.as_ref().unwrap().iter())
|
||||||
|
{
|
||||||
|
if i.is_none() {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
let pts = c.points().collect::<Vec<Point>>();
|
||||||
canvas.restore();
|
let first_point = pts[0];
|
||||||
canvas.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
let img = canvas
|
|
||||||
.load_image_file("test.png", ImageFlags::NEAREST)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut path = Path::new();
|
let mut path = Path::new();
|
||||||
|
path.move_to(
|
||||||
path.rect(0.0, 0.0, canvas_width, canvas_height);
|
first_point.x() as f32 * v.0 as f32 + 0.8,
|
||||||
canvas.fill_path(
|
first_point.y() as f32 * v.1 as f32 + 0.8,
|
||||||
&path,
|
|
||||||
&Paint::image(img, 0.0, 0.0, canvas_width, canvas_height, 0.0, 1.0),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
canvas.flush();
|
pts[1..].into_iter().for_each(|p| {
|
||||||
|
path.line_to(p.x() as f32 * v.0 as f32, p.y() as f32 * v.1 as f32)
|
||||||
|
});
|
||||||
|
let c = i.unwrap();
|
||||||
|
canvas.fill_path(&path, &Paint::color(c));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_dims(&mut self, dims: (Array2<f64>, Array2<f64>)) {
|
self.imp().image.replace(Some(img_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.set_render_target(femtovg::RenderTarget::Screen);
|
||||||
|
|
||||||
|
let mut path = Path::new();
|
||||||
|
path.rect(0.0, 0.0, canvas_width, canvas_height);
|
||||||
|
|
||||||
|
canvas.fill_path(
|
||||||
|
&path,
|
||||||
|
&Paint::image(
|
||||||
|
self.imp().image.borrow().as_ref().unwrap().to_owned(),
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
canvas_width,
|
||||||
|
canvas_height,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn set_dims(&self, dims: (Array2<f64>, Array2<f64>)) {
|
||||||
self.imp().dim1.replace(Some(dims.0));
|
self.imp().dim1.replace(Some(dims.0));
|
||||||
self.imp().dim2.replace(Some(dims.1));
|
self.imp().dim2.replace(Some(dims.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub(super) fn set_image(&mut self, image: Vec<u8>) {
|
pub(super) fn set_image(&self, image: ImageId) {
|
||||||
// self.imp().image.replace(Some(image));
|
self.imp().image.replace(Some(image));
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub(super) fn set_data(&mut self, data: Array2<LineString>) {
|
pub fn set_colors(&self, colors: Array2<Option<Color>>) {
|
||||||
|
self.imp().color.replace(Some(colors));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_data(&self, data: Array2<LineString>) {
|
||||||
self.imp().data.replace(Some(data));
|
self.imp().data.replace(Some(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use super::foreground::ForegroundWidget;
|
|||||||
use super::WindowCoord;
|
use super::WindowCoord;
|
||||||
use crate::coords::proj::Mercator;
|
use crate::coords::proj::Mercator;
|
||||||
use crate::coords::Mapper;
|
use crate::coords::Mapper;
|
||||||
use femtovg::{Color, Paint, Path};
|
use femtovg::{Color, Paint, Path, FontId};
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use gtk::traits::{GLAreaExt, WidgetExt};
|
use gtk::traits::{GLAreaExt, WidgetExt};
|
||||||
@ -20,6 +20,12 @@ pub struct RenderConfig {
|
|||||||
pub transform: WindowCoord,
|
pub transform: WindowCoord,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Fonts {
|
||||||
|
sans: FontId,
|
||||||
|
bold: FontId,
|
||||||
|
light: FontId,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Render {
|
pub struct Render {
|
||||||
pub(super) background: RefCell<BackgroundWidget>,
|
pub(super) background: RefCell<BackgroundWidget>,
|
||||||
pub(super) foreground: RefCell<ForegroundWidget>,
|
pub(super) foreground: RefCell<ForegroundWidget>,
|
||||||
@ -81,24 +87,42 @@ impl GLAreaImpl for Render {
|
|||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
|
|
||||||
let dpi = self.obj().scale_factor();
|
let dpi = self.obj().scale_factor();
|
||||||
let w = self.obj().width();
|
let w = canvas.width();
|
||||||
let h = self.obj().width();
|
let h = canvas.height();
|
||||||
let configs = self.config.borrow();
|
let configs = self.config.borrow();
|
||||||
|
|
||||||
canvas.clear_rect(
|
canvas.clear_rect(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(w * dpi) as u32,
|
(w as i32 * dpi) as u32,
|
||||||
(h * dpi) as u32,
|
(h as i32 * dpi) as u32,
|
||||||
Color::rgba(0, 0, 0, 255),
|
Color::rgba(0, 0, 0, 255),
|
||||||
);
|
);
|
||||||
|
|
||||||
// self.background.borrow().draw(canvas, configs.scale, dpi);
|
let mapper = self.mapper.borrow();
|
||||||
|
let (lon_range, lat_range) = mapper.range.clone();
|
||||||
|
|
||||||
|
{
|
||||||
|
let background_widget = self.background.borrow_mut();
|
||||||
|
background_widget.set_lat_lines(lat_range.key_points(5));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let background_widget = self.background.borrow_mut();
|
||||||
|
background_widget.set_lon_lines(lon_range.key_points(10));
|
||||||
|
}
|
||||||
|
|
||||||
self.foreground
|
self.foreground
|
||||||
.borrow()
|
.borrow()
|
||||||
.draw(canvas, configs.scale, dpi, self.mapper.borrow());
|
.draw(canvas, configs.scale, dpi, self.mapper.borrow());
|
||||||
|
|
||||||
|
self.background.borrow().draw(
|
||||||
|
canvas,
|
||||||
|
configs.scale,
|
||||||
|
dpi,
|
||||||
|
self.mapper.borrow(),
|
||||||
|
(lon_range, lat_range),
|
||||||
|
);
|
||||||
|
|
||||||
canvas.flush();
|
canvas.flush();
|
||||||
|
|
||||||
true
|
true
|
||||||
@ -113,6 +137,7 @@ impl Render {
|
|||||||
if self.canvas.borrow().is_some() {
|
if self.canvas.borrow().is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let widget = self.obj();
|
let widget = self.obj();
|
||||||
widget.attach_buffers();
|
widget.attach_buffers();
|
||||||
|
|
||||||
@ -131,7 +156,8 @@ impl Render {
|
|||||||
(renderer, glow::NativeFramebuffer(id))
|
(renderer, glow::NativeFramebuffer(id))
|
||||||
};
|
};
|
||||||
renderer.set_screen_target(Some(fbo));
|
renderer.set_screen_target(Some(fbo));
|
||||||
let canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
let mut canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
||||||
|
canvas.add_font_dir("/Users/tsuki/projects/radar-g/src/assets").unwrap();
|
||||||
self.canvas.replace(Some(canvas));
|
self.canvas.replace(Some(canvas));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
mod background;
|
mod background;
|
||||||
mod foreground;
|
mod foreground;
|
||||||
mod imp;
|
mod imp;
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use crate::coords::Mapper;
|
use crate::coords::Mapper;
|
||||||
use crate::data::{MultiDimensionData, RadarData2d};
|
use crate::data::{MultiDimensionData, RadarData2d};
|
||||||
|
use crate::pipeline::ProjPipe;
|
||||||
|
use crate::pipeline::{Pipeline, ShadePipe};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub use self::background::{BackgroundConfig, BackgroundWidget};
|
pub use self::background::{BackgroundConfig, BackgroundWidget};
|
||||||
pub use self::foreground::{ForegroundConfig, ForegroundWidget};
|
pub use self::foreground::{ForegroundConfig, ForegroundWidget};
|
||||||
use self::imp::RenderConfig;
|
use self::imp::RenderConfig;
|
||||||
use crate::data::DownSampleMeth;
|
use crate::data::DownSampleMeth;
|
||||||
|
use femtovg::Color;
|
||||||
pub use glib::subclass::prelude::*;
|
pub use glib::subclass::prelude::*;
|
||||||
use image::RgbImage;
|
use image::RgbImage;
|
||||||
use ndarray::{self, s, Array2, Axis, Dimension, Ix2, Zip};
|
use ndarray::{self, s, Array2, Axis, Dimension, Ix2, Zip};
|
||||||
@ -70,45 +72,37 @@ impl Render {
|
|||||||
{
|
{
|
||||||
assert!(data.dim1.shape().len() == data.dim2.shape().len());
|
assert!(data.dim1.shape().len() == data.dim2.shape().len());
|
||||||
|
|
||||||
|
let levels: Vec<T> = vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65]
|
||||||
|
.into_iter()
|
||||||
|
.map(|b| T::from_i8(b).unwrap())
|
||||||
|
.collect();
|
||||||
|
let colors = vec![
|
||||||
|
Color::rgb(0, 172, 164),
|
||||||
|
Color::rgb(192, 192, 254),
|
||||||
|
Color::rgb(122, 114, 238),
|
||||||
|
Color::rgb(30, 38, 208),
|
||||||
|
Color::rgb(166, 252, 168),
|
||||||
|
Color::rgb(0, 234, 0),
|
||||||
|
Color::rgb(16, 146, 26),
|
||||||
|
Color::rgb(252, 244, 100),
|
||||||
|
Color::rgb(200, 200, 2),
|
||||||
|
Color::rgb(140, 140, 0),
|
||||||
|
Color::rgb(254, 172, 172),
|
||||||
|
Color::rgb(254, 100, 92),
|
||||||
|
Color::rgb(238, 2, 48),
|
||||||
|
Color::rgb(212, 142, 254),
|
||||||
|
Color::rgb(170, 36, 250),
|
||||||
|
];
|
||||||
|
|
||||||
let mapper = self.imp().mapper.borrow();
|
let mapper = self.imp().mapper.borrow();
|
||||||
// data.downsample((801 * 2 / 3, 947 * 2 / 3), DownSampleMeth::VAR);
|
|
||||||
|
let pjp = ProjPipe::new(&mapper);
|
||||||
|
let rrp = ShadePipe::new(levels, colors.into_iter().map(|v| v.into()).collect());
|
||||||
|
|
||||||
|
let rainbow = pjp.run(&data).unwrap();
|
||||||
|
self.imp().foreground.borrow_mut().set_data(rainbow);
|
||||||
|
let pbow:Array2<Option<Color>> = rrp.run(&data).unwrap();
|
||||||
|
self.imp().foreground.borrow_mut().set_colors(pbow);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let levels: Vec<i8> = vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65];
|
|
||||||
// let colors = vec![
|
|
||||||
// Color::rgb(0, 172, 164),
|
|
||||||
// Color::rgb(192, 192, 254),
|
|
||||||
// Color::rgb(122, 114, 238),
|
|
||||||
// Color::rgb(30, 38, 208),
|
|
||||||
// Color::rgb(166, 252, 168),
|
|
||||||
// Color::rgb(0, 234, 0),
|
|
||||||
// Color::rgb(16, 146, 26),
|
|
||||||
// Color::rgb(252, 244, 100),
|
|
||||||
// Color::rgb(200, 200, 2),
|
|
||||||
// Color::rgb(140, 140, 0),
|
|
||||||
// Color::rgb(254, 172, 172),
|
|
||||||
// Color::rgb(254, 100, 92),
|
|
||||||
// Color::rgb(238, 2, 48),
|
|
||||||
// Color::rgb(212, 142, 254),
|
|
||||||
// Color::rgb(170, 36, 250),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let c = d.map(|v| {
|
|
||||||
// let c = get(&levels, &colors, *v);
|
|
||||||
// image::Rgb([
|
|
||||||
// (c.r * 255.0) as u8,
|
|
||||||
// (c.g * 255.0) as u8,
|
|
||||||
// (c.b * 255.0) as u8,
|
|
||||||
// ])
|
|
||||||
// });
|
|
||||||
|
|
||||||
// let mut img = RgbImage::from_fn(927, 801, |x, y| c[[y as usize, x as usize]]);
|
|
||||||
|
|
||||||
// img.save("test.png").unwrap();
|
|
||||||
|
|
||||||
// self.imp()
|
|
||||||
// .foreground
|
|
||||||
// .borrow_mut()
|
|
||||||
// .set_dims((meshed.dim1, meshed.dim2));
|
|
||||||
|
|||||||
BIN
src/resources/Roboto-Bold.ttf
Normal file
BIN
src/resources/Roboto-Bold.ttf
Normal file
Binary file not shown.
BIN
src/resources/Roboto-Light.ttf
Normal file
BIN
src/resources/Roboto-Light.ttf
Normal file
Binary file not shown.
BIN
src/resources/Roboto-Regular.ttf
Normal file
BIN
src/resources/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
src/resources/amiri-regular.ttf
Normal file
BIN
src/resources/amiri-regular.ttf
Normal file
Binary file not shown.
BIN
src/resources/entypo.ttf
Normal file
BIN
src/resources/entypo.ttf
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<gresources>
|
<gresources>
|
||||||
<gresource prefix="/org/cinrad_g/">
|
<gresource prefix="/org/cinrad_g/">
|
||||||
<file compressed="true" preprocess="xml-stripblanks">monitor.ui</file>
|
<file alias="bold.ttf">Roboto-Bold.ttf</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
||||||
|
|||||||
23
src/tree.rs
23
src/tree.rs
@ -1,23 +0,0 @@
|
|||||||
use femtovg::Color;
|
|
||||||
use num_traits::Num;
|
|
||||||
|
|
||||||
pub fn get<T, V: Copy>(levels: &Vec<T>, colors: &Vec<V>, v: T) -> V
|
|
||||||
where
|
|
||||||
T: Num + PartialOrd + Copy,
|
|
||||||
{
|
|
||||||
let len = levels.len();
|
|
||||||
|
|
||||||
let mut left = 0;
|
|
||||||
let mut right = len - 1;
|
|
||||||
|
|
||||||
while left < right - 1 {
|
|
||||||
let middle = (right + left) / 2;
|
|
||||||
if v > levels[middle] {
|
|
||||||
left = middle;
|
|
||||||
} else {
|
|
||||||
right = middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
colors[left]
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user