Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 38 additions & 26 deletions packages/base/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,46 +322,58 @@ export function addCommands(
label: trans.__('Buffer'),
isEnabled: () => selectedLayerIsOfType(['VectorLayer'], tracker),
execute: async () => {
await processSelectedLayer(tracker, formSchemaRegistry, 'Buffer', {
sqlQueryFn: (layerName, bufferDistance) => `
await processSelectedLayer(
tracker,
formSchemaRegistry,
'Buffer',
{
sqlQueryFn: (layerName, bufferDistance) => `
SELECT ST_Union(ST_Buffer(geometry, ${bufferDistance})) AS geometry, *
FROM "${layerName}"
`,
gdalFunction: 'ogr2ogr',
options: (sqlQuery: string) => [
'-f',
'GeoJSON',
'-dialect',
'SQLITE',
'-sql',
sqlQuery,
'output.geojson'
]
});
gdalFunction: 'ogr2ogr',
options: (sqlQuery: string) => [
'-f',
'GeoJSON',
'-dialect',
'SQLITE',
'-sql',
sqlQuery,
'output.geojson'
]
},
app
);
}
});

commands.addCommand(CommandIDs.dissolve, {
label: trans.__('Dissolve'),
isEnabled: () => selectedLayerIsOfType(['VectorLayer'], tracker),
execute: async () => {
await processSelectedLayer(tracker, formSchemaRegistry, 'Dissolve', {
sqlQueryFn: (layerName, dissolveField) => `
await processSelectedLayer(
tracker,
formSchemaRegistry,
'Dissolve',
{
sqlQueryFn: (layerName, dissolveField) => `
SELECT ST_Union(geometry) AS geometry, ${dissolveField}
FROM "${layerName}"
GROUP BY ${dissolveField}
`,
gdalFunction: 'ogr2ogr',
options: (sqlQuery: string) => [
'-f',
'GeoJSON',
'-dialect',
'SQLITE',
'-sql',
sqlQuery,
'output.geojson'
]
});
gdalFunction: 'ogr2ogr',
options: (sqlQuery: string) => [
'-f',
'GeoJSON',
'-dialect',
'SQLITE',
'-sql',
sqlQuery,
'output.geojson'
]
},
app
);
}
});

Expand Down
2 changes: 0 additions & 2 deletions packages/base/src/dialogs/ProcessingFormDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ export class ProcessingFormDialog extends Dialog<IDict> {

// Modify schema to include layer options and layer name field
if (options.schema) {
console.log(options.schema.properties?.inputLayer);

if (options.schema.properties?.inputLayer) {
options.schema.properties.inputLayer.enum = layerOptions.map(
option => option.value
Expand Down
91 changes: 66 additions & 25 deletions packages/base/src/processing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { JupyterGISTracker } from './types';
import { UUID } from '@lumino/coreutils';
import { ProcessingFormDialog } from './dialogs/ProcessingFormDialog';
import { getGeoJSONDataFromLayerSource } from './tools';
import { JupyterFrontEnd } from '@jupyterlab/application';

/**
* Get the currently selected layer from the shared model. Returns null if there is no selection or multiple layer is selected.
Expand Down Expand Up @@ -94,7 +95,8 @@ export async function processSelectedLayer(
sqlQueryFn: (layerName: string, param: any) => string;
gdalFunction: GdalFunctions;
options: (sqlQuery: string) => string[];
}
},
app: JupyterFrontEnd
) {
const selected = getSingleSelectedLayer(tracker);
if (!selected || !tracker.currentWidget) {
Expand Down Expand Up @@ -153,6 +155,8 @@ export async function processSelectedLayer(
return;
}

const embedOutputLayer = formValues.embedOutputLayer;

const fileBlob = new Blob([geojsonString], {
type: 'application/geo+json'
});
Expand All @@ -174,27 +178,28 @@ export async function processSelectedLayer(
processingOptions.gdalFunction,
fullOptions,
formValues.outputLayerName,
processingType
processingType,
embedOutputLayer,
tracker,
app
);
}

/**
* Execute SQL processing on the layer
*/
export async function executeSQLProcessing(
model: IJupyterGISModel,
geojsonString: string,
gdalFunction: GdalFunctions,
options: string[],
layerNamePrefix: string,
processingType: 'Buffer' | 'Dissolve'
processingType: 'Buffer' | 'Dissolve',
embedOutputLayer: boolean,
tracker: JupyterGISTracker,
app: JupyterFrontEnd
) {
const geoFile = new File(
[new Blob([geojsonString], { type: 'application/geo+json' })],
'data.geojson',
{
type: 'application/geo+json'
}
{ type: 'application/geo+json' }
);

const Gdal = await getGdal();
Expand All @@ -210,23 +215,59 @@ export async function executeSQLProcessing(
const processedGeoJSONString = new TextDecoder().decode(processedBytes);
Gdal.close(dataset);

const processedGeoJSON = JSON.parse(processedGeoJSONString);
if (!embedOutputLayer) {
// Save the output as a file
const jgisFilePath = tracker.currentWidget?.model.filePath;
const jgisDir = jgisFilePath
? jgisFilePath.substring(0, jgisFilePath.lastIndexOf('/'))
: '';

// Store in shared model
const newSourceId = UUID.uuid4();
const sourceModel: IJGISSource = {
type: 'GeoJSONSource',
name: `${layerNamePrefix} ${processingType.charAt(0).toUpperCase() + processingType.slice(1)}`,
parameters: { data: processedGeoJSON }
};
const outputFileName = `${layerNamePrefix}_${processingType}.json`;
const savePath = jgisDir ? `${jgisDir}/${outputFileName}` : outputFileName;

const layerModel: IJGISLayer = {
type: 'VectorLayer',
parameters: { source: newSourceId },
visible: true,
name: `${layerNamePrefix} ${processingType.charAt(0).toUpperCase() + processingType.slice(1)}`
};
await app.serviceManager.contents.save(savePath, {
type: 'file',
format: 'text',
content: processedGeoJSONString
});

const newSourceId = UUID.uuid4();
const sourceModel: IJGISSource = {
type: 'GeoJSONSource',
name: outputFileName,
parameters: {
path: outputFileName
}
};

const layerModel: IJGISLayer = {
type: 'VectorLayer',
parameters: { source: newSourceId },
visible: true,
name: outputFileName
};

model.sharedModel.addSource(newSourceId, sourceModel);
model.addLayer(UUID.uuid4(), layerModel);
model.sharedModel.addSource(newSourceId, sourceModel);
model.addLayer(UUID.uuid4(), layerModel);
} else {
// Embed the output directly into the model
const processedGeoJSON = JSON.parse(processedGeoJSONString);
const newSourceId = UUID.uuid4();

const sourceModel: IJGISSource = {
type: 'GeoJSONSource',
name: `${layerNamePrefix} ${processingType.charAt(0).toUpperCase() + processingType.slice(1)}`,
parameters: { data: processedGeoJSON }
};

const layerModel: IJGISLayer = {
type: 'VectorLayer',
parameters: { source: newSourceId },
visible: true,
name: `${layerNamePrefix} ${processingType.charAt(0).toUpperCase() + processingType.slice(1)}`
};

model.sharedModel.addSource(newSourceId, sourceModel);
model.addLayer(UUID.uuid4(), layerModel);
}
}
5 changes: 5 additions & 0 deletions packages/schema/src/schema/processing/buffer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
"type": "number",
"default": 10,
"description": "The distance used for buffering the geometry (in projection units)."
},
"embedOutputLayer": {
"type": "boolean",
"title": "Embed output buffered layer in file",
"default": true
}
}
}
5 changes: 5 additions & 0 deletions packages/schema/src/schema/processing/dissolve.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
"dissolveField": {
"type": "string",
"description": "The field based on which geometries will be dissolved."
},
"embedOutputLayer": {
"type": "boolean",
"title": "Embed output dissolved layer in file",
"default": true
}
}
}
Loading