From 85b09885eec277ba7e0fb3cf003be781575702f6 Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Thu, 3 Apr 2025 18:04:05 +0530 Subject: [PATCH 1/2] Processing: Reproject a vector layer --- packages/base/src/commands.ts | 17 +++++++++++++++++ packages/base/src/constants.ts | 1 + .../base/src/dialogs/ProcessingFormDialog.tsx | 3 ++- packages/base/src/processing.ts | 7 +++++-- .../src/schema/processing/reproject.json | 18 ++++++++++++++++++ packages/schema/src/types.ts | 1 + python/jupytergis_lab/src/index.ts | 4 ++++ 7 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 packages/schema/src/schema/processing/reproject.json diff --git a/packages/base/src/commands.ts b/packages/base/src/commands.ts index 7dd6c1e39..0692534d4 100644 --- a/packages/base/src/commands.ts +++ b/packages/base/src/commands.ts @@ -365,6 +365,23 @@ export function addCommands( } }); + commands.addCommand(CommandIDs.reproject, { + label: trans.__('Reproject'), + isEnabled: () => selectedLayerIsOfType(['VectorLayer'], tracker), + execute: async () => { + await processSelectedLayer(tracker, formSchemaRegistry, 'Reproject', { + sqlQueryFn: (layerName, targetSRS) => `${targetSRS}`, + gdalFunction: 'ogr2ogr', + options: (sqlQuery: string) => [ + '-f', 'GeoJSON', + '-t_srs', + sqlQuery + ] + }); + } + }); + + commands.addCommand(CommandIDs.newGeoJSONEntry, { label: trans.__('New GeoJSON layer'), isEnabled: () => { diff --git a/packages/base/src/constants.ts b/packages/base/src/constants.ts index eb91c975d..ba5e3b06d 100644 --- a/packages/base/src/constants.ts +++ b/packages/base/src/constants.ts @@ -27,6 +27,7 @@ export namespace CommandIDs { // Processing commands export const buffer = 'jupytergis:buffer'; export const dissolve = 'jupytergis:dissolve'; + export const reproject = 'jupytergis:reproject'; // Sources only commands export const newRasterSource = 'jupytergis:newRasterSource'; diff --git a/packages/base/src/dialogs/ProcessingFormDialog.tsx b/packages/base/src/dialogs/ProcessingFormDialog.tsx index fab6b91e4..ba2035e52 100644 --- a/packages/base/src/dialogs/ProcessingFormDialog.tsx +++ b/packages/base/src/dialogs/ProcessingFormDialog.tsx @@ -18,7 +18,7 @@ export interface IProcessingFormDialogOptions extends IBaseFormProps { parentType: 'dialog' | 'panel' ) => void; model: IJupyterGISModel; - processingType: 'Buffer' | 'Dissolve' | 'Export'; + processingType: 'Buffer' | 'Dissolve' | 'Export' | 'Reproject'; } /** @@ -52,6 +52,7 @@ const ProcessingFormWrapper = (props: IProcessingFormWrapperProps) => { break; case 'Buffer': case 'Export': + case 'Reproject': default: FormComponent = BaseForm; } diff --git a/packages/base/src/processing.ts b/packages/base/src/processing.ts index 3e895e5ff..bbbbdfa42 100644 --- a/packages/base/src/processing.ts +++ b/packages/base/src/processing.ts @@ -89,7 +89,7 @@ export type GdalFunctions = export async function processSelectedLayer( tracker: JupyterGISTracker, formSchemaRegistry: IJGISFormSchemaRegistry, - processingType: 'Buffer' | 'Dissolve', + processingType: 'Buffer' | 'Dissolve' | 'Reproject', processingOptions: { sqlQueryFn: (layerName: string, param: any) => string; gdalFunction: GdalFunctions; @@ -148,6 +148,9 @@ export async function processSelectedLayer( case 'Dissolve': processParam = formValues.dissolveField; break; + case 'Reproject': + processParam = formValues.targetCRS; + break; default: console.error(`Unsupported processing type: ${processingType}`); return; @@ -187,7 +190,7 @@ export async function executeSQLProcessing( gdalFunction: GdalFunctions, options: string[], layerNamePrefix: string, - processingType: 'Buffer' | 'Dissolve' + processingType: 'Buffer' | 'Dissolve' | 'Reproject' ) { const geoFile = new File( [new Blob([geojsonString], { type: 'application/geo+json' })], diff --git a/packages/schema/src/schema/processing/reproject.json b/packages/schema/src/schema/processing/reproject.json new file mode 100644 index 000000000..ba8b6275d --- /dev/null +++ b/packages/schema/src/schema/processing/reproject.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "description": "Reproject", + "title": "IReproject", + "required": ["inputLayer", "targetCRS"], + "additionalProperties": false, + "properties": { + "inputLayer": { + "type": "string", + "description": "The input layer for reprojection." + }, + "targetCRS": { + "type": "string", + "default": "EPSG:4326", + "description": "The target coordinate reference system (CRS) for reprojection." + } + } + } diff --git a/packages/schema/src/types.ts b/packages/schema/src/types.ts index 412b7958e..769883189 100644 --- a/packages/schema/src/types.ts +++ b/packages/schema/src/types.ts @@ -22,6 +22,7 @@ export * from './_interface/project/layers/heatmapLayer'; // Processing export * from './_interface/processing/buffer'; export * from './_interface/processing/dissolve'; +export * from './_interface/processing/reproject'; // exportLayer export * from './_interface/export/exportGeojson'; diff --git a/python/jupytergis_lab/src/index.ts b/python/jupytergis_lab/src/index.ts index 4178bdbd3..b8f5f3edf 100644 --- a/python/jupytergis_lab/src/index.ts +++ b/python/jupytergis_lab/src/index.ts @@ -201,6 +201,10 @@ const plugin: JupyterFrontEndPlugin = { command: CommandIDs.dissolve }); + processingSubmenu.addItem({ + command: CommandIDs.reproject + }); + app.contextMenu.addItem({ type: 'submenu', selector: '.jp-gis-layerItem', From 3a27259e7a4e89281c59d9e1a91c59ce82e4cf4f Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Thu, 3 Apr 2025 18:04:33 +0530 Subject: [PATCH 2/2] lint --- packages/base/src/commands.ts | 7 +---- .../src/schema/processing/reproject.json | 30 +++++++++---------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/packages/base/src/commands.ts b/packages/base/src/commands.ts index 0692534d4..c16ed8e81 100644 --- a/packages/base/src/commands.ts +++ b/packages/base/src/commands.ts @@ -372,16 +372,11 @@ export function addCommands( await processSelectedLayer(tracker, formSchemaRegistry, 'Reproject', { sqlQueryFn: (layerName, targetSRS) => `${targetSRS}`, gdalFunction: 'ogr2ogr', - options: (sqlQuery: string) => [ - '-f', 'GeoJSON', - '-t_srs', - sqlQuery - ] + options: (sqlQuery: string) => ['-f', 'GeoJSON', '-t_srs', sqlQuery] }); } }); - commands.addCommand(CommandIDs.newGeoJSONEntry, { label: trans.__('New GeoJSON layer'), isEnabled: () => { diff --git a/packages/schema/src/schema/processing/reproject.json b/packages/schema/src/schema/processing/reproject.json index ba8b6275d..d69494f43 100644 --- a/packages/schema/src/schema/processing/reproject.json +++ b/packages/schema/src/schema/processing/reproject.json @@ -1,18 +1,18 @@ { - "type": "object", - "description": "Reproject", - "title": "IReproject", - "required": ["inputLayer", "targetCRS"], - "additionalProperties": false, - "properties": { - "inputLayer": { - "type": "string", - "description": "The input layer for reprojection." - }, - "targetCRS": { - "type": "string", - "default": "EPSG:4326", - "description": "The target coordinate reference system (CRS) for reprojection." - } + "type": "object", + "description": "Reproject", + "title": "IReproject", + "required": ["inputLayer", "targetCRS"], + "additionalProperties": false, + "properties": { + "inputLayer": { + "type": "string", + "description": "The input layer for reprojection." + }, + "targetCRS": { + "type": "string", + "default": "EPSG:4326", + "description": "The target coordinate reference system (CRS) for reprojection." } } +}