Skip to content

Commit

Permalink
fix: show layer
Browse files Browse the repository at this point in the history
  • Loading branch information
zerj9 committed Oct 22, 2024
1 parent f732a5f commit 9085f9d
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 70 deletions.
2 changes: 1 addition & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ strum = "0.26"
strum_macros = "0.26"
tokio = { version = "1.40.0", features = ["full"] }
tokio-postgres = "0.7.12"
tower-http = { version = "0.5", features = ["trace"] }
tower-http = { version = "0.5", features = ["trace", "cors"] }
tracing = "0.1"
tracing-subscriber = "0.3"
url = "2.5.2"
Expand Down
56 changes: 35 additions & 21 deletions backend/src/core/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub trait GeoConnector: Send + Sync {
async fn connect(&mut self) -> Result<()>;
async fn disconnect(&mut self) -> Result<()>;
async fn list_sources(&self) -> Result<Vec<String>>;
async fn get_tile(&self) -> Result<Vec<u8>>;
async fn get_tile(&self, z: u32, x: u32, y: u32) -> Result<Vec<u8>>;
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -129,33 +129,47 @@ impl GeoConnector for PostgisConfig {
Ok(sources)
}

async fn get_tile(&self) -> Result<Vec<u8>> {
println!("Fetching all data as MVT...");
async fn get_tile(&self, z: u32, x: u32, y: u32) -> Result<Vec<u8>> {
println!("Fetching MVT for tile z:{} x:{} y:{}", z, x, y);
let pool = self.pool.as_ref();
let client = pool.get().await?;

// Replace these with your actual table and geometry column names
let table_name = "your_table_name";
let table_name = "test";
let geom_column = "geom";

let query = format!(
"SELECT ST_AsMVT(q, 'layer', 4096, 'geom')
FROM (
SELECT ST_AsMVTGeom(
{geom},
ST_TileEnvelope(0, 0, 0), -- World bounds
4096, 256, true
) AS geom,
*
FROM {table}
) AS q",
geom = geom_column,
table = table_name
"
WITH
bounds AS (
-- Get tile envelope in EPSG:4326
SELECT ST_Transform(ST_TileEnvelope({z}, {x}, {y}), 4326) AS geom
),
mvt_data AS (
SELECT
-- Use the geometry directly in 4326 and prepare for MVT
ST_AsMVTGeom(
t.geom,
bounds.geom,
4096,
256,
true
) AS geom,
t.name
FROM
test t,
bounds
WHERE
ST_Intersects(t.geom, bounds.geom)
)
SELECT ST_AsMVT(mvt_data.*, 'blah', 4096, 'geom') AS mvt
FROM mvt_data;
",
z = z,
x = x,
y = y,
);

let row = client.query_one(&query, &[]).await?;
println!("{row:?}");
let mvt_data: Vec<u8> = row.get(0);

println!("{mvt_data:?}");
Ok(mvt_data)
}
}
Expand Down
1 change: 1 addition & 0 deletions backend/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ mod workspace;

pub use connector::*;
pub use os_token::*;
pub use tiles::*;
pub use user::*;
pub use workspace::*;
106 changes: 68 additions & 38 deletions backend/src/routes/tiles.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,70 @@
//use crate::app_state::AppState;
use crate::app_state::AppState;
use crate::core::Connection;
//use crate::data::Database;
//use axum::{
// extract::{Path, State},
// http::{header, StatusCode},
// response::{IntoResponse, Response},
//};
use axum::{
extract::{Path, State},
http::{header, StatusCode},
response::{IntoResponse, Response},
};
//use martin_tile_utils::TileCoord;
//use std::sync::Arc;
//
//pub async fn tiles<D: Database>(
// Path((z, y, x)): Path<(u32, u32, u32)>,
// State(state): State<Arc<AppState<D>>>,
//) -> Response {
// if let Some(tile_info_source) = state.sources.get("pois") {
// let xyz = TileCoord {
// x,
// y,
// z: z.try_into().unwrap(),
// };
// match tile_info_source.get_tile(xyz, None).await {
// Ok(tile_data) => (
// StatusCode::OK,
// [
// (header::CONTENT_TYPE, "application/vnd.mapbox-vector-tile"),
// (header::ACCESS_CONTROL_ALLOW_ORIGIN, "*"),
// ],
// tile_data,
// )
// .into_response(),
// Err(_) => (StatusCode::NOT_FOUND, "Tile not found".to_string()).into_response(),
// }
// } else {
// (
// StatusCode::NOT_FOUND,
// "Tile info source not found".to_string(),
// )
// .into_response()
// }
//}
use std::sync::Arc;

pub async fn tiles(
State(state): State<Arc<AppState>>,
Path((workspace_id, connection_id, z, x, y)): Path<(String, String, u32, u32, u32)>,
) -> impl IntoResponse {
let connection = Connection::from_id(&state.app_data, &workspace_id, &connection_id)
.await
.unwrap();

let geoconnector = state
.geospatial_config
.get_connection(&connection.id)
.await
.unwrap();

let tile = geoconnector.get_tile(z, x, y).await.unwrap();

println!("tile");
println!("{tile:?}");

Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/x-protobuf")
.header(header::ACCESS_CONTROL_ALLOW_ORIGIN, "http://localhost:3000")
.header(
header::ACCESS_CONTROL_ALLOW_METHODS,
"GET, POST, PUT, DELETE, OPTIONS",
)
.header(header::ACCESS_CONTROL_ALLOW_HEADERS, "*")
//.header(header::CONTENT_ENCODING, "gzip")
.body(axum::body::Body::from(tile))
.unwrap()
.into_response()

//if let Some(tile_info_source) = state.geospatial_config.get("pois") {
// let xyz = TileCoord {
// x,
// y,
// z: z.try_into().unwrap(),
// };
// match tile_info_source.get_tile(xyz, None).await {
// Ok(tile_data) => (
// StatusCode::OK,
// [
// (header::CONTENT_TYPE, "application/vnd.mapbox-vector-tile"),
// (header::ACCESS_CONTROL_ALLOW_ORIGIN, "*"),
// ],
// tile_data,
// )
// .into_response(),
// Err(_) => (StatusCode::NOT_FOUND, "Tile not found".to_string()).into_response(),
// }
//} else {
// (
// StatusCode::NOT_FOUND,
// "Tile info source not found".to_string(),
// )
// .into_response()
//}
}
11 changes: 9 additions & 2 deletions backend/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@ use crate::app_state::AppState;
use crate::auth::auth_middleware;
use crate::routes::{
add_workspace_member, create_connection, create_workspace, generate_os_token, health_check,
list_sources, login, logout, profile, register, remove_workspace_member,
list_sources, login, logout, profile, register, remove_workspace_member, tiles,
};
use axum::{
middleware,
routing::{delete, get, post},
Router,
};
use std::sync::Arc;
use tower_http::cors::{Any, CorsLayer};
use tower_http::trace::{self, TraceLayer};
use tracing::Level;

pub fn create_app(app_state: AppState) -> Router {
let cors = CorsLayer::new()
.allow_origin(Any)
.allow_methods(Any)
.allow_headers(Any);

let shared_state = Arc::new(app_state);

Router::new()
Expand All @@ -31,11 +37,11 @@ pub fn create_app(app_state: AppState) -> Router {
"/workspace/:workspace_id/connection/:connection_id/sources",
get(list_sources),
)
//.route("/tiles/:z/:x/:y", get(tiles::<D>))
.layer(middleware::from_fn_with_state(
shared_state.clone(),
auth_middleware,
))
.route("/tiles/:workspace_id/:connection_id/:z/:x/:y", get(tiles))
.route("/register", post(register))
.route("/login", post(login))
.route("/os-token", get(generate_os_token))
Expand All @@ -45,4 +51,5 @@ pub fn create_app(app_state: AppState) -> Router {
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
)
.layer(cors)
}
102 changes: 96 additions & 6 deletions frontend/src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,83 @@ import {
transformGeoJsonData,
} from "../../utils/mapHandler";

const addNewVectorLayer = (map: maplibregl.Map | null) => {
console.log("Adding New Vector Layer");
if (!map) return;

// 1. First, check if source already exists and remove it
if (map.getSource('new-vector-source')) {
if (map.getLayer('new-vector-layer')) {
map.removeLayer('new-vector-layer');
}
map.removeSource('new-vector-source');
}

// 2. Add the vector tile source
map.addSource('new-vector-source', {
type: 'vector',
tiles: ['http://localhost:3001/tiles/3793c7d4-60b5-44ec-a4c3-42a91515b11a/4cf82baf-31d2-4428-b0b3-a3ca9583a5a2/{z}/{x}/{y}'],
minzoom: 0,
maxzoom: 14
});

// 3. Add debug listeners for source loading
map.on('sourcedataloading', (e) => {
if (e.sourceId === 'new-vector-source') {
console.log('Vector source loading...');
}
});

// 4. Add layer with more explicit options
map.addLayer({
id: 'new-vector-layer',
type: 'fill',
source: 'new-vector-source',
'source-layer': 'blah',
layout: {
visibility: 'visible'
},
paint: {
'fill-color': '#FF0000',
'fill-opacity': 0.5,
'fill-outline-color': '#000000'
}
});

// 5. Add error handling for tile loading
map.on('error', (e) => {
console.error('Map error:', e.error);
if (e.error.status === 404) {
console.error('Tile not found. Check the tile URL and source-layer name');
}
});

// 6. Debug source loading
map.on('sourcedata', (e) => {
if (e.sourceId === 'new-vector-source') {
if (e.isSourceLoaded) {
console.log('Vector source loaded successfully');
// Query features to verify data
const features = map.querySourceFeatures('new-vector-source', {
sourceLayer: 'default'
});
console.log('Features found:', features.length);

// Log the viewport bounds
const bounds = map.getBounds();
console.log('Current viewport bounds:', bounds.toString());
} else {
console.log('Source still loading...');
}
}
});


console.log('New vector layer added');
};



// Form Component to change paint properties
const LayerStyleForm: React.FC<{
layerId: string;
Expand Down Expand Up @@ -98,11 +175,11 @@ const initMap = async (
style: baseLayer,
center: [INITIAL_VIEW_STATE.longitude, INITIAL_VIEW_STATE.latitude],
zoom: INITIAL_VIEW_STATE.zoom,
minZoom: 6,
maxBounds: [
[-10.7, 49.5], // Southwest coordinates
[1.9, 61.0], // Northeast coordinates
],
minZoom: 0,
//maxBounds: [
// [-10.7, 49.5], // Southwest coordinates
// [1.9, 61.0], // Northeast coordinates
//],
transformRequest: (url) => {
if (url.startsWith("https://api.os.uk")) {
return {
Expand All @@ -121,7 +198,16 @@ const initMap = async (
},
});

map.current.on("load", () => setMapLoaded(true));
map.current.on("load", () => {
setMapLoaded(true);
addNewVectorLayer(map.current);
// Add debug controls
map.current?.addControl(new maplibregl.NavigationControl());
map.current?.addControl(
new maplibregl.ScaleControl({ maxWidth: 80, unit: 'metric' })
);
});

map.current.on("error", (e) =>
handleError(setMapError, e.error, "Map error"),
);
Expand All @@ -137,6 +223,7 @@ const initMap = async (
}
});


} catch (error) {
handleError(setMapError, error as Error, "Error initializing map");
}
Expand Down Expand Up @@ -167,7 +254,10 @@ const Map: React.FC<MapProps> = ({ activeFiles, baseLayer }) => {
tokenDataRef,
setSelectedLayer,
);

}


// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down
2 changes: 0 additions & 2 deletions frontend/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import {
Upload,
FileText,
Trash2,
Link,
ChevronDown,
ChevronRight,
} from "lucide-react";
import ConnectionsModal from "../Modals/ConnectionsModal";
import { layerIcons } from "./sidebarHandler";

type LayerGroup = {
Expand Down

0 comments on commit 9085f9d

Please sign in to comment.