Skip to content
Permalink
Browse files

Virtual dataset groups for mesh layer (#37605)

[FEATURE] Introduces mesh virtual datasets

With the mesh calculator the user can choose to create those "virtual" dataset groups that will be added to the layer. Then, for these dataset groups, values are not stored in memory but each dataset is calculated when needed whit the formula entered in the mesh calculator.

Those virtual dataset groups are saved with the project.

If needed, the user can remove them or can persist them on files to make them persistent.

Co-authored-by: Étienne Trimaille <gustrimaille@yahoo.fr>
  • Loading branch information
vcloarec and Gustry committed Jul 23, 2020
1 parent 282d5f9 commit de68f83cc3f57ef646478d25dcf24d44cd76615a
Showing with 2,018 additions and 655 deletions.
  1. +1 −1 CMakeLists.txt
  2. +5 −0 external/mdal/api/mdal.h
  3. +13 −1 external/mdal/mdal.cpp
  4. +31 −0 external/mdal/mdal_datetime.cpp
  5. +3 −0 external/mdal/mdal_datetime.hpp
  6. +0 −1 python/analysis/analysis_auto.sip
  7. +17 −12 python/{analysis → core}/auto_generated/mesh/qgsmeshcalculator.sip.in
  8. +243 −19 python/core/auto_generated/mesh/qgsmeshdataset.sip.in
  9. +31 −4 python/core/auto_generated/mesh/qgsmeshlayer.sip.in
  10. +1 −0 python/core/core_auto.sip
  11. +0 −9 src/analysis/CMakeLists.txt
  12. +78 −59 src/app/mesh/qgsmeshcalculatordialog.cpp
  13. +1 −0 src/app/mesh/qgsmeshcalculatordialog.h
  14. +177 −51 src/app/mesh/qgsmeshdatasetgrouptreeview.cpp
  15. +27 −16 src/app/mesh/qgsmeshdatasetgrouptreeview.h
  16. +0 −1 src/app/mesh/qgsmeshdatasetgrouptreewidget.cpp
  17. +1 −1 src/app/mesh/qgsmeshstaticdatasetwidget.h
  18. +1 −11 src/app/qgisapp.cpp
  19. +11 −1 src/core/CMakeLists.txt
  20. 0 src/{analysis → core}/mesh/qgsmeshcalclexer.ll
  21. +44 −0 src/{analysis → core}/mesh/qgsmeshcalcnode.cpp
  22. +9 −3 src/{analysis → core}/mesh/qgsmeshcalcnode.h
  23. 0 src/{analysis → core}/mesh/qgsmeshcalcparser.yy
  24. +39 −13 src/{analysis → core}/mesh/qgsmeshcalculator.cpp
  25. +19 −14 src/{analysis → core}/mesh/qgsmeshcalculator.h
  26. +164 −110 src/{analysis → core}/mesh/qgsmeshcalcutils.cpp
  27. +26 −6 src/{analysis → core}/mesh/qgsmeshcalcutils.h
  28. +201 −26 src/core/mesh/qgsmeshdataset.cpp
  29. +275 −210 src/core/mesh/qgsmeshdataset.h
  30. +127 −40 src/core/mesh/qgsmeshdatasetgroupstore.cpp
  31. +21 −6 src/core/mesh/qgsmeshdatasetgroupstore.h
  32. +20 −8 src/core/mesh/qgsmeshlayer.cpp
  33. +26 −5 src/core/mesh/qgsmeshlayer.h
  34. +176 −0 src/core/mesh/qgsmeshvirtualdatasetgroup.cpp
  35. +80 −0 src/core/mesh/qgsmeshvirtualdatasetgroup.h
  36. +1 −1 src/core/providers/meshmemory/qgsmeshmemorydataprovider.cpp
  37. +1 −0 src/core/qgsapplication.cpp
  38. +9 −0 src/providers/mdal/qgsmdalprovider.cpp
  39. +22 −22 src/ui/mesh/qgsmeshcalculatordialogbase.ui
  40. +3 −3 src/ui/mesh/qgsmeshdatasetgrouptreewidgetbase.ui
  41. +1 −1 src/ui/mesh/qgsmeshlayerpropertiesbase.ui
  42. +113 −0 tests/src/analysis/testqgsmeshcalculator.cpp
@@ -571,7 +571,7 @@ IF (PEDANTIC)
# ADD_DEFINITIONS( -fstrict-aliasing -Wstrict-aliasing=1 -Wredundant-decls )

IF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-overloaded-virtual -Wimplicit-fallthrough")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-overloaded-virtual -Wimplicit-fallthrough")
ENDIF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")

# add any extra CXXFLAGS flags set by user. can be -D CXX_EXTRA_FLAGS or environment variable
@@ -533,6 +533,11 @@ MDAL_EXPORT void MDAL_G_closeEditMode( MDAL_DatasetGroupH group );
*/
MDAL_EXPORT const char *MDAL_G_referenceTime( MDAL_DatasetGroupH group );

/**
* Sets reference time for dataset group expressed in date with ISO8601 format
*/
MDAL_EXPORT void MDAL_G_setReferenceTime( MDAL_DatasetGroupH group, const char *referenceTimeISO8601 );

/**
* Returns whether the dataset group is temporal, i.e. has time-related datasets
*
@@ -21,7 +21,7 @@ static const char *EMPTY_STR = "";

const char *MDAL_Version()
{
return "0.6.90";
return "0.6.91";
}

MDAL_Status MDAL_LastStatus()
@@ -874,6 +874,18 @@ const char *MDAL_G_referenceTime( MDAL_DatasetGroupH group )
return _return_str( g->referenceTime().toStandardCalendarISO8601() );
}

void MDAL_G_setReferenceTime( MDAL_DatasetGroupH group, const char *referenceTimeISO8601 )
{
if ( !group )
{
MDAL::Log::error( MDAL_Status::Err_IncompatibleDataset, "Dataset Group is not valid (null)" );
return;
}
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
const std::string datetime( referenceTimeISO8601 );
g->setReferenceTime( MDAL::DateTime( datetime ) );
}

void MDAL_G_setMetadata( MDAL_DatasetGroupH group, const char *key, const char *val )
{
if ( !group )
@@ -49,6 +49,37 @@ MDAL::DateTime::DateTime( double value, Epoch epoch ): mValid( true )
}
}

MDAL::DateTime::DateTime( const std::string &fromISO8601 )
{
std::vector<std::string> splitedDateTime = split( fromISO8601, 'T' );

if ( splitedDateTime.size() != 2 )
return;
//parse date
std::vector<std::string> splitedDate = split( splitedDateTime.at( 0 ), '-' );
if ( splitedDate.size() != 3 )
return;

//parse time
splitedDateTime[1] = replace( splitedDateTime.at( 1 ), "Z", "", ContainsBehaviour::CaseInsensitive );
std::vector<std::string> splitedTime = split( splitedDateTime.at( 1 ), ':' );
if ( splitedTime.size() < 2 || splitedTime.size() > 3 )
return;

DateTimeValues dateTimeValues;
dateTimeValues.year = toInt( splitedDate[0] );
dateTimeValues.month = toInt( splitedDate[1] );
dateTimeValues.day = toInt( splitedDate[2] );
dateTimeValues.hours = toInt( splitedTime[0] );
dateTimeValues.minutes = toInt( splitedTime[1] );
if ( splitedTime.size() == 3 )
dateTimeValues.seconds = toDouble( splitedTime[2] );
else
dateTimeValues.seconds = 0.0;

setWithGregorianCalendarDate( dateTimeValues );
}

std::string MDAL::DateTime::toStandardCalendarISO8601() const
{
if ( mValid )
@@ -67,6 +67,9 @@ namespace MDAL
//! Constructor with Julian day or Unix Epoch
DateTime( double value, Epoch epoch );

//! Constructor with ISO 8601 string
DateTime( const std::string &fromISO8601 );

//! Returns a string with the date/time expressed in Greogrian proleptic calendar with ISO8601 format (local time zone)
//! Do not support negative year
std::string toStandardCalendarISO8601() const;
@@ -4,7 +4,6 @@
%Include auto_generated/interpolation/qgsidwinterpolator.sip
%Include auto_generated/interpolation/qgsinterpolator.sip
%Include auto_generated/interpolation/qgstininterpolator.sip
%Include auto_generated/mesh/qgsmeshcalculator.sip
%Include auto_generated/mesh/qgsmeshcontours.sip
%Include auto_generated/network/qgsgraph.sip
%Include auto_generated/network/qgsgraphanalyzer.sip
@@ -1,7 +1,7 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/analysis/mesh/qgsmeshcalculator.h *
* src/core/mesh/qgsmeshcalculator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -131,16 +131,19 @@ Creates calculator with geometry mask

QgsMeshCalculator( const QString &formulaString,
const QString &outputGroupName,
double startTime,
double endTime,
const QgsRectangle &outputExtent,
QgsMeshLayer *layer );
const QgsMeshDatasetGroup::Type &destination,
QgsMeshLayer *layer,
double startTime,
double endTime );
%Docstring
Creates calculator with bounding box (rectangular) mask, store the result in the memory
Creates calculator with bounding box (rectangular) mask, store the result in ``destination`` (must be on memory or virtual),
see QgsMeshCalculator.Destination

:param formulaString: formula/expression to evaluate. Consists of dataset group names, operators and numbers
:param outputGroupName: output group name
:param outputExtent: spatial filter defined by rectangle
:param destination: destination of the calculation (memory or virtual)
:param startTime: time filter defining the starting dataset
:param endTime: time filter defining the ending dataset
:param layer: mesh layer with dataset groups references in formulaString
@@ -150,27 +153,29 @@ Creates calculator with bounding box (rectangular) mask, store the result in the

QgsMeshCalculator( const QString &formulaString,
const QString &outputGroupName,
double startTime,
double endTime,
const QgsGeometry &outputMask,
QgsMeshLayer *layer );
const QgsMeshDatasetGroup::Type &destination,
QgsMeshLayer *layer,
double startTime,
double endTime );
%Docstring
Creates calculator with with geometry mask, store the result in the memory
Creates calculator with with geometry mask, store the result in ``destination`` (must be on memory or virtual),
see QgsMeshCalculator.Destination

:param formulaString: formula/expression to evaluate. Consists of dataset group names, operators and numbers
:param outputGroupName: output group name
:param outputMask: spatial filter defined by geometry
:param destination: destination of the calculation (memory or virtual)
:param startTime: time filter defining the starting dataset
:param endTime: time filter defining the ending dataset
:param layer: mesh layer with dataset groups references in formulaString

.. versionadded:: 3.16
%End


Result processCalculation( QgsFeedback *feedback = 0 );
%Docstring
Starts the calculation, writes new dataset group to file and adds it to the mesh layer
Starts the calculation, creates new dataset group and adds it to the mesh layer

:param feedback: The optional feedback argument for progress reporting and cancellation support

@@ -211,7 +216,7 @@ Returns whether formula is valid for particular mesh layer
/************************************************************************
* This file has been generated automatically from *
* *
* src/analysis/mesh/qgsmeshcalculator.h *
* src/core/mesh/qgsmeshcalculator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

0 comments on commit de68f83

Please sign in to comment.
You can’t perform that action at this time.