mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Merge branch 'master' into sirs_db_manager
This commit is contained in:
commit
a80f3d01ee
@ -65,7 +65,7 @@ COPY .docker/qgis_resources/supervisor/supervisor.xvfb.conf /etc/supervisor/supe
|
||||
# - deb installed
|
||||
# - built from git
|
||||
# needed to find PyQt wrapper provided by QGIS
|
||||
ENV PYTHONPATH=/usr/share/qgis/python/:/usr/lib/python3/dist-packages/qgis:/usr/share/qgis/python/qgis
|
||||
ENV PYTHONPATH=/usr/share/qgis/python/:/usr/share/qgis/python/plugins:/usr/lib/python3/dist-packages/qgis:/usr/share/qgis/python/qgis
|
||||
|
||||
|
||||
WORKDIR /
|
||||
|
@ -32,6 +32,7 @@ matrix:
|
||||
# QGIS TESTS ON BIONIC
|
||||
##########################################################
|
||||
- os: linux
|
||||
name: building and testing on linux
|
||||
if: type != cron
|
||||
services: docker
|
||||
env:
|
||||
@ -44,6 +45,7 @@ matrix:
|
||||
# CODE LAYOUT
|
||||
##########################################################
|
||||
- os: linux
|
||||
name: code layout
|
||||
if: type != cron
|
||||
env:
|
||||
- TRAVIS_CONFIG=code_layout
|
||||
@ -93,6 +95,7 @@ matrix:
|
||||
# BIONIC DOCKER BUILD ON CRON OR TAG
|
||||
##########################################################
|
||||
- os: linux
|
||||
name: bionic docker build
|
||||
if: repo = qgis/QGIS AND (tag IS PRESENT OR type = cron)
|
||||
services: docker
|
||||
env:
|
||||
@ -105,6 +108,7 @@ matrix:
|
||||
# COSMIC DOCKER BUILD ON CRON OR TAG
|
||||
##########################################################
|
||||
- os: linux
|
||||
name: cosmic docker build
|
||||
if: repo = qgis/QGIS AND (tag IS PRESENT OR type = cron)
|
||||
services: docker
|
||||
env:
|
||||
|
@ -94,6 +94,7 @@ IF(WITH_APIDOC)
|
||||
${CMAKE_SOURCE_DIR}/src/gui/raster
|
||||
${CMAKE_SOURCE_DIR}/src/gui/symbology
|
||||
${CMAKE_SOURCE_DIR}/src/analysis
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/mesh
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/interpolation
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/network
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/processing
|
||||
|
@ -31,7 +31,7 @@
|
||||
<tr><td align="center"><img src="qrc:/images/flags/vi.svg" height="20"></td><td>Vietnamese</td><td><div title="finished:12244 unfinished:57 untranslated:6734" class="bartodo"><div class="bardone" style="width:64px">64.5</div></div></td><td>Phùng Văn Doanh, Bùi Hữu Mạnh, Nguyễn Văn Thanh, Nguyễn Hữu Phúc, Cao Minh Tu</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/ky.svg" height="20"></td><td>Kirghiz</td><td><div title="finished:11363 unfinished:53 untranslated:7619" class="bartodo"><div class="bardone" style="width:59px">59.8</div></div></td><td>Stéphane Henriod, Azamat Karypov, Salaidin Kamaldinov, Akylbek Chymyrov, Chinara Saparova, Almaz Abdiev, Nurlan Tokbaev, Tatygul Urmambetova, Adilet Bekturov, Nursultan Ismailov, Nurlan Zhusupov</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/ca.svg" height="20"></td><td>Catalan</td><td><div title="finished:11258 unfinished:51 untranslated:7726" class="bartodo"><div class="bardone" style="width:59px">59.3</div></div></td><td>Albert F, Pau Reguant Ridó, Xavier Roijals</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/zh.svg" height="20"></td><td>Chinese traditional</td><td><div title="finished:10778 unfinished:151 untranslated:8106" class="bartodo"><div class="bardone" style="width:57px">57.0</div></div></td><td>Calvin Ngei, Zhang Jun, Richard Xie, Dennis Raylin Chen</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/zh-Hant.svg" height="20"></td><td>Chinese traditional</td><td><div title="finished:10778 unfinished:151 untranslated:8106" class="bartodo"><div class="bardone" style="width:57px">57.0</div></div></td><td>Calvin Ngei, Zhang Jun, Richard Xie, Dennis Raylin Chen</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/hi.svg" height="20"></td><td>Hindi</td><td><div title="finished:9409 unfinished:75 untranslated:9551" class="bartodo"><div class="bardone" style="width:49px">49.6</div></div></td><td>Harish Kumar Solanki</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/sl.svg" height="20"></td><td>Slovenian</td><td><div title="finished:9233 unfinished:85 untranslated:9717" class="bartodo"><div class="bardone" style="width:48px">48.7</div></div></td><td>Jože Detečnik, Dejan Gregor, Jaka Kranjc</td></tr>
|
||||
<tr><td align="center"><img src="qrc:/images/flags/tr.svg" height="20"></td><td>Turkish</td><td><div title="finished:8972 unfinished:62 untranslated:10001" class="bartodo"><div class="bardone" style="width:47px">47.3</div></div></td><td>Osman Yalçın YILMAZ, Omur Saygin</td></tr>
|
||||
|
@ -61,7 +61,6 @@ Moved Classes {#qgis_api_break_3_0_moved_classes}
|
||||
-------------
|
||||
|
||||
<table>
|
||||
<caption id="moved_classes">Moved classes</caption>
|
||||
<tr><th>class<th>Module 2.X<th>Module 3.x
|
||||
<tr><td>QgsMapLayerModel<td>gui<td>core
|
||||
<tr><td>QgsMapLayerProxyModel<td>gui<td>core
|
||||
@ -72,7 +71,6 @@ Renamed Classes {#qgis_api_break_3_0_renamed_classes}
|
||||
---------------
|
||||
|
||||
<table>
|
||||
<caption id="renamed_classes">Renamed classes</caption>
|
||||
<tr><th>API 2.x<th>API 3.X
|
||||
<tr><td>QgisGui<td>QgsGuiUtils
|
||||
<tr><td>QgsAbstractGeometryV2<td>QgsAbstractGeometry
|
||||
@ -230,15 +228,21 @@ Renamed Classes {#qgis_api_break_3_0_renamed_classes}
|
||||
<tr><td>vertexData<td>QgsInterpolatorVertexData
|
||||
</table>
|
||||
|
||||
|
||||
Renamed Enum Values {#qgis_api_break_3_0_renamed_enum_values}
|
||||
-------------------
|
||||
|
||||
<table>
|
||||
<caption id="renamed_enum_values">Renamed enum values</caption>
|
||||
<tr><th>class</th><th>API 2.x<th>API 3.X
|
||||
<tr><td>QgsLayerTreeModelLegendNode<td>SymbolV2LegacyRuleKeyRole<td>SymbolLegacyRuleKeyRole
|
||||
<tr><td>QgsVectorLayer<td>EditorWidgetV2<td>EditorWidget
|
||||
</table>
|
||||
|
||||
|
||||
Renamed Methods {#qgis_api_break_3_0_renamed_methods}
|
||||
---------------
|
||||
|
||||
<table>
|
||||
<caption id="renamed_methods">Renamed method names</caption>
|
||||
<tr><th>class</th><th>API 2.x<th>API 3.X
|
||||
<tr><td>QgsAnnotation<td>mapPositionFixed<td>hasFixedMapPosition
|
||||
<tr><td>QgsApplication<td>defaultStyleV2Path<td>defaultStylePath
|
||||
@ -2430,6 +2434,7 @@ displayExpression instead. For the map tip use mapTipTemplate() instead.
|
||||
- select() replaced by selectByRect()
|
||||
- selectedFeaturesIds() replaced by selectedFeatureIds()
|
||||
- selectedFeaturesIterator() was replaced by getSelectedFeatures()
|
||||
- setDisplayField() has been removed, and its functionality split between setMapTipTemplate() and setDisplayExpression()
|
||||
- setSelectedFeatures() replaced by selectByIds()
|
||||
- applyNamedStyle() replaced by importNamedStyle()
|
||||
- isReadOnly() use readOnly()
|
||||
|
88
external/mdal/api/mdal.h
vendored
88
external/mdal/api/mdal.h
vendored
@ -55,6 +55,7 @@ enum MDAL_Status
|
||||
Err_IncompatibleDataset,
|
||||
Err_IncompatibleDatasetGroup,
|
||||
Err_MissingDriver,
|
||||
Err_MissingDriverCapability,
|
||||
// Warnings
|
||||
Warn_UnsupportedElement,
|
||||
Warn_InvalidElements,
|
||||
@ -101,6 +102,9 @@ MDAL_EXPORT DriverH MDAL_driverFromName( const char *name );
|
||||
*/
|
||||
MDAL_EXPORT bool MDAL_DR_meshLoadCapability( DriverH driver );
|
||||
|
||||
//! Returns whether driver has capability to write/edit dataset (groups)
|
||||
MDAL_EXPORT bool MDAL_DR_writeDatasetsCapability( DriverH driver );
|
||||
|
||||
/**
|
||||
* Returns name of MDAL driver
|
||||
* not thread-safe and valid only till next call
|
||||
@ -163,6 +167,37 @@ MDAL_EXPORT int MDAL_M_datasetGroupCount( MeshH mesh );
|
||||
//! Returns dataset group handle
|
||||
MDAL_EXPORT DatasetGroupH MDAL_M_datasetGroup( MeshH mesh, int index );
|
||||
|
||||
/**
|
||||
* Adds empty (new) dataset group to the mesh
|
||||
* This increases dataset group count MDAL_M_datasetGroupCount() by 1
|
||||
*
|
||||
* The Dataset Group is opened in edit mode.
|
||||
* To persist dataset group, call MDAL_G_closeEditMode();
|
||||
*
|
||||
* It is not possible to read and write to the same group
|
||||
* at the same time. Finalize edits before reading.
|
||||
*
|
||||
* \param mesh mesh handle
|
||||
* \param driver the driver to use for storing the data
|
||||
* \param name dataset group name
|
||||
* \param isOnVertices whether data is defined on vertices
|
||||
* \param hasScalarData whether data is scalar (false = vector data)
|
||||
* \param datasetGroupFile file to store the new dataset group
|
||||
* \returns empty pointer if not possible to create group, otherwise handle to new group
|
||||
*/
|
||||
MDAL_EXPORT DatasetGroupH MDAL_M_addDatasetGroup( MeshH mesh,
|
||||
const char *name,
|
||||
bool isOnVertices,
|
||||
bool hasScalarData,
|
||||
DriverH driver,
|
||||
const char *datasetGroupFile );
|
||||
|
||||
/**
|
||||
* Returns name of MDAL driver
|
||||
* not thread-safe and valid only till next call
|
||||
*/
|
||||
MDAL_EXPORT const char *MDAL_M_driverName( MeshH mesh );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// MESH VERTICES
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -247,12 +282,24 @@ MDAL_EXPORT const char *MDAL_G_metadataKey( DatasetGroupH group, int index );
|
||||
*/
|
||||
MDAL_EXPORT const char *MDAL_G_metadataValue( DatasetGroupH group, int index );
|
||||
|
||||
/**
|
||||
* Adds new metadata to the group
|
||||
* Group must be in edit mode MDAL_G_isInEditMode()
|
||||
*/
|
||||
MDAL_EXPORT void MDAL_G_setMetadata( DatasetGroupH group, const char *key, const char *val );
|
||||
|
||||
/**
|
||||
* Returns dataset group name
|
||||
* not thread-safe and valid only till next call
|
||||
*/
|
||||
MDAL_EXPORT const char *MDAL_G_name( DatasetGroupH group );
|
||||
|
||||
/**
|
||||
* Returns name of MDAL driver
|
||||
* not thread-safe and valid only till next call
|
||||
*/
|
||||
MDAL_EXPORT const char *MDAL_G_driverName( DatasetGroupH group );
|
||||
|
||||
//! Whether dataset has scalar data associated
|
||||
MDAL_EXPORT bool MDAL_G_hasScalarData( DatasetGroupH group );
|
||||
|
||||
@ -260,11 +307,48 @@ MDAL_EXPORT bool MDAL_G_hasScalarData( DatasetGroupH group );
|
||||
MDAL_EXPORT bool MDAL_G_isOnVertices( DatasetGroupH group );
|
||||
|
||||
/**
|
||||
* Returns the min and max values of the group
|
||||
* Returns the minimum and maximum values of the group
|
||||
* Returns NaN on error
|
||||
*/
|
||||
MDAL_EXPORT void MDAL_G_minimumMaximum( DatasetGroupH group, double *min, double *max );
|
||||
|
||||
/**
|
||||
* Adds empty (new) dataset to the group
|
||||
* This increases dataset group count MDAL_G_datasetCount() by 1
|
||||
*
|
||||
* The dataset is opened in edit mode.
|
||||
* To persist dataset, call MDAL_G_closeEditMode() on parent group
|
||||
*
|
||||
* Minimum and maximum dataset values are automatically calculated
|
||||
*
|
||||
* \param group parent group handle
|
||||
* \param time time for dataset
|
||||
* \param values For scalar data on vertices, the size must be vertex count
|
||||
* For scalar data on faces, the size must be faces count
|
||||
* For vector data on vertices, the size must be vertex count * 2 (x1, y1, x2, y2, ..., xN, yN)
|
||||
* For vector data on faces, the size must be faces count * 2 (x1, y1, x2, y2, ..., xN, yN)
|
||||
* \param active if null pointer, all faces are active. Otherwise size must be equal to face count.
|
||||
* \returns empty pointer if not possible to create dataset (e.g. group opened in read mode), otherwise handle to new dataset
|
||||
*/
|
||||
MDAL_EXPORT DatasetH MDAL_G_addDataset( DatasetGroupH group,
|
||||
double time,
|
||||
const double *values,
|
||||
const int *active
|
||||
);
|
||||
|
||||
//! Returns whether dataset group is in edit mode
|
||||
MDAL_EXPORT bool MDAL_G_isInEditMode( DatasetGroupH group );
|
||||
|
||||
/**
|
||||
* Close edit mode for group and all its datasets.
|
||||
* This may effectively write the data to the files and/or
|
||||
* reopen the file in read-only mode
|
||||
*
|
||||
* When closed, minimum and maximum dataset group values are automatically calculated
|
||||
*/
|
||||
MDAL_EXPORT void MDAL_G_closeEditMode( DatasetGroupH group );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// DATASETS
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -307,7 +391,7 @@ enum MDAL_DataType
|
||||
MDAL_EXPORT int MDAL_D_data( DatasetH dataset, int indexStart, int count, MDAL_DataType dataType, void *buffer );
|
||||
|
||||
/**
|
||||
* Returns the min and max values of the dataset
|
||||
* Returns the minimum and maximum values of the dataset
|
||||
* Returns NaN on error
|
||||
*/
|
||||
MDAL_EXPORT void MDAL_D_minimumMaximum( DatasetH dataset, double *min, double *max );
|
||||
|
13
external/mdal/frmts/mdal_2dm.cpp
vendored
13
external/mdal/frmts/mdal_2dm.cpp
vendored
@ -17,13 +17,20 @@
|
||||
#include "mdal.h"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
#define DRIVER_NAME "2DM"
|
||||
|
||||
MDAL::Mesh2dm::Mesh2dm( size_t verticesCount,
|
||||
size_t facesCount,
|
||||
size_t faceVerticesMaximumCount,
|
||||
MDAL::BBox extent,
|
||||
const std::string &uri,
|
||||
const std::map<size_t, size_t> vertexIDtoIndex )
|
||||
: MemoryMesh( verticesCount, facesCount, faceVerticesMaximumCount, extent, uri )
|
||||
: MemoryMesh( DRIVER_NAME,
|
||||
verticesCount,
|
||||
facesCount,
|
||||
faceVerticesMaximumCount,
|
||||
extent,
|
||||
uri )
|
||||
, mVertexIDtoIndex( vertexIDtoIndex )
|
||||
{
|
||||
}
|
||||
@ -58,10 +65,10 @@ size_t MDAL::Mesh2dm::vertexIndex( size_t vertexID ) const
|
||||
|
||||
|
||||
MDAL::Driver2dm::Driver2dm():
|
||||
Driver( "2DM",
|
||||
Driver( DRIVER_NAME,
|
||||
"2DM Mesh File",
|
||||
"*.2dm",
|
||||
DriverType::CanReadMeshAndDatasets
|
||||
Capability::ReadMesh
|
||||
)
|
||||
{
|
||||
}
|
||||
|
3
external/mdal/frmts/mdal_3di.cpp
vendored
3
external/mdal/frmts/mdal_3di.cpp
vendored
@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
#include "mdal_3di.hpp"
|
||||
#include <netcdf.h>
|
||||
#include <assert.h>
|
||||
|
||||
MDAL::Driver3Di::Driver3Di()
|
||||
: DriverCF(
|
||||
@ -126,6 +128,7 @@ void MDAL::Driver3Di::addBedElevation( MDAL::Mesh *mesh )
|
||||
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mesh,
|
||||
mesh->uri(),
|
||||
"Bed Elevation"
|
||||
|
351
external/mdal/frmts/mdal_ascii_dat.cpp
vendored
351
external/mdal/frmts/mdal_ascii_dat.cpp
vendored
@ -27,7 +27,7 @@ MDAL::DriverAsciiDat::DriverAsciiDat( ):
|
||||
Driver( "ASCII_DAT",
|
||||
"DAT",
|
||||
"*.dat",
|
||||
DriverType::CanReadOnlyDatasets
|
||||
Capability::ReadDatasets
|
||||
)
|
||||
{
|
||||
}
|
||||
@ -49,15 +49,203 @@ bool MDAL::DriverAsciiDat::canRead( const std::string &uri )
|
||||
}
|
||||
line = trim( line );
|
||||
|
||||
if ( line != "DATASET" &&
|
||||
line != "SCALAR" &&
|
||||
line != "VECTOR" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return canReadNewFormat( line ) || canReadOldFormat( line );
|
||||
}
|
||||
|
||||
bool MDAL::DriverAsciiDat::canReadOldFormat( const std::string &line ) const
|
||||
{
|
||||
return MDAL::contains( line, "SCALAR" ) ||
|
||||
MDAL::contains( line, "VECTOR" ) ||
|
||||
MDAL::contains( line, "TS" );
|
||||
}
|
||||
|
||||
bool MDAL::DriverAsciiDat::canReadNewFormat( const std::string &line ) const
|
||||
{
|
||||
return line == "DATASET";
|
||||
}
|
||||
|
||||
|
||||
void MDAL::DriverAsciiDat::loadOldFormat( std::ifstream &in,
|
||||
Mesh *mesh,
|
||||
MDAL_Status *status ) const
|
||||
{
|
||||
std::shared_ptr<DatasetGroup> group; // DAT outputs data
|
||||
std::string groupName( MDAL::baseName( mDatFile ) );
|
||||
std::string line;
|
||||
std::getline( in, line );
|
||||
|
||||
// Read the first line
|
||||
bool isVector = MDAL::contains( line, "VECTOR" );
|
||||
group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mesh,
|
||||
mDatFile,
|
||||
groupName
|
||||
);
|
||||
group->setIsScalar( !isVector );
|
||||
group->setIsOnVertices( true );
|
||||
|
||||
do
|
||||
{
|
||||
// Replace tabs by spaces,
|
||||
// since basement v.2.8 uses tabs instead of spaces (e.g. 'TS 0\t0.0')
|
||||
line = replace( line, "\t", " " );
|
||||
|
||||
// Trim string for cases when file has inconsistent new line symbols
|
||||
line = MDAL::trim( line );
|
||||
|
||||
// Split to tokens
|
||||
std::vector<std::string> items = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
if ( items.size() < 1 )
|
||||
continue; // empty line?? let's skip it
|
||||
|
||||
std::string cardType = items[0];
|
||||
if ( cardType == "ND" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileNodeCount = toSizeT( items[1] );
|
||||
if ( mesh->verticesCount() != fileNodeCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( cardType == "SCALAR" || cardType == "VECTOR" )
|
||||
{
|
||||
// just ignore - we know the type from earlier...
|
||||
}
|
||||
else if ( cardType == "TS" && items.size() >= 2 )
|
||||
{
|
||||
double t = toDouble( items[ 1 ] );
|
||||
readVertexTimestep( mesh, group, t, isVector, false, in );
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream str;
|
||||
str << " Unknown card:" << line;
|
||||
debug( str.str() );
|
||||
}
|
||||
}
|
||||
while ( std::getline( in, line ) );
|
||||
|
||||
if ( !group || group->datasets.size() == 0 )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
group->setStatistics( MDAL::calculateStatistics( group ) );
|
||||
mesh->datasetGroups.push_back( group );
|
||||
group.reset();
|
||||
}
|
||||
|
||||
void MDAL::DriverAsciiDat::loadNewFormat( std::ifstream &in,
|
||||
Mesh *mesh,
|
||||
MDAL_Status *status ) const
|
||||
{
|
||||
bool isVector = false;
|
||||
std::shared_ptr<DatasetGroup> group; // DAT outputs data
|
||||
std::string groupName( MDAL::baseName( mDatFile ) );
|
||||
std::string line;
|
||||
|
||||
// see if it contains face-centered results - supported by BASEMENT
|
||||
bool faceCentered = false;
|
||||
if ( contains( groupName, "_els_" ) )
|
||||
faceCentered = true;
|
||||
|
||||
if ( group )
|
||||
group->setIsOnVertices( !faceCentered );
|
||||
|
||||
while ( std::getline( in, line ) )
|
||||
{
|
||||
// Replace tabs by spaces,
|
||||
// since basement v.2.8 uses tabs instead of spaces (e.g. 'TS 0\t0.0')
|
||||
line = replace( line, "\t", " " );
|
||||
|
||||
// Trim string for cases when file has inconsistent new line symbols
|
||||
line = MDAL::trim( line );
|
||||
|
||||
// Split to tokens
|
||||
std::vector<std::string> items = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
if ( items.size() < 1 )
|
||||
continue; // empty line?? let's skip it
|
||||
|
||||
std::string cardType = items[0];
|
||||
if ( cardType == "ND" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileNodeCount = toSizeT( items[1] );
|
||||
if ( mesh->verticesCount() != fileNodeCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( cardType == "NC" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileElemCount = toSizeT( items[1] );
|
||||
if ( mesh->facesCount() != fileElemCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( cardType == "OBJTYPE" )
|
||||
{
|
||||
if ( items[1] != "mesh2d" && items[1] != "\"mesh2d\"" )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
else if ( cardType == "BEGSCL" || cardType == "BEGVEC" )
|
||||
{
|
||||
if ( group )
|
||||
{
|
||||
debug( "New dataset while previous one is still active!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
isVector = cardType == "BEGVEC";
|
||||
|
||||
group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mesh,
|
||||
mDatFile,
|
||||
groupName
|
||||
);
|
||||
group->setIsScalar( !isVector );
|
||||
group->setIsOnVertices( !faceCentered );
|
||||
}
|
||||
else if ( cardType == "ENDDS" )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
debug( "ENDDS card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
group->setStatistics( MDAL::calculateStatistics( group ) );
|
||||
mesh->datasetGroups.push_back( group );
|
||||
group.reset();
|
||||
}
|
||||
else if ( cardType == "NAME" && items.size() >= 2 )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
debug( "NAME card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
|
||||
size_t quoteIdx1 = line.find( '\"' );
|
||||
size_t quoteIdx2 = line.find( '\"', quoteIdx1 + 1 );
|
||||
if ( quoteIdx1 != std::string::npos && quoteIdx2 != std::string::npos )
|
||||
group->setName( line.substr( quoteIdx1 + 1, quoteIdx2 - quoteIdx1 - 1 ) );
|
||||
}
|
||||
else if ( cardType == "TS" && items.size() >= 3 )
|
||||
{
|
||||
double t = toDouble( items[2] );
|
||||
|
||||
if ( faceCentered )
|
||||
{
|
||||
readFaceTimestep( mesh, group, t, isVector, in );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hasStatus = ( toBool( items[1] ) );
|
||||
readVertexTimestep( mesh, group, t, isVector, hasStatus, in );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream str;
|
||||
str << " Unknown card:" << line;
|
||||
debug( str.str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The DAT format contains "datasets" and each dataset has N-outputs. One output
|
||||
@ -85,145 +273,18 @@ void MDAL::DriverAsciiDat::load( const std::string &datFile, MDAL::Mesh *mesh, M
|
||||
return;
|
||||
}
|
||||
line = trim( line );
|
||||
|
||||
// http://www.xmswiki.com/xms/SMS:ASCII_Dataset_Files_*.dat
|
||||
// Apart from the format specified above, there is an older supported format used in BASEMENT (and SMS?)
|
||||
// which is simpler (has only one dataset in one file, no status flags etc)
|
||||
bool oldFormat;
|
||||
bool isVector = false;
|
||||
|
||||
std::shared_ptr<DatasetGroup> group; // DAT outputs data
|
||||
std::string name( MDAL::baseName( mDatFile ) );
|
||||
|
||||
if ( line == "DATASET" )
|
||||
oldFormat = false;
|
||||
else if ( line == "SCALAR" || line == "VECTOR" )
|
||||
if ( canReadNewFormat( line ) )
|
||||
{
|
||||
oldFormat = true;
|
||||
isVector = ( line == "VECTOR" );
|
||||
|
||||
group = std::make_shared< DatasetGroup >(
|
||||
mesh,
|
||||
mDatFile,
|
||||
name
|
||||
);
|
||||
group->setIsScalar( !isVector );
|
||||
// we do not need to parse first line again
|
||||
loadNewFormat( in, mesh, status );
|
||||
}
|
||||
else
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
// see if it contains face-centered results - supported by BASEMENT
|
||||
bool faceCentered = false;
|
||||
if ( !oldFormat && contains( name, "_els_" ) )
|
||||
faceCentered = true;
|
||||
|
||||
if ( group )
|
||||
group->setIsOnVertices( !faceCentered );
|
||||
|
||||
while ( std::getline( in, line ) )
|
||||
{
|
||||
// Replace tabs by spaces,
|
||||
// since basement v.2.8 uses tabs instead of spaces (e.g. 'TS 0\t0.0')
|
||||
line = replace( line, "\t", " " );
|
||||
|
||||
std::vector<std::string> items = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||
if ( items.size() < 1 )
|
||||
continue; // empty line?? let's skip it
|
||||
|
||||
std::string cardType = items[0];
|
||||
if ( cardType == "ND" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileNodeCount = toSizeT( items[1] );
|
||||
if ( mesh->verticesCount() != fileNodeCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "NC" && items.size() >= 2 )
|
||||
{
|
||||
size_t fileElemCount = toSizeT( items[1] );
|
||||
if ( mesh->facesCount() != fileElemCount )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "OBJTYPE" )
|
||||
{
|
||||
if ( items[1] != "mesh2d" && items[1] != "\"mesh2d\"" )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
else if ( !oldFormat && ( cardType == "BEGSCL" || cardType == "BEGVEC" ) )
|
||||
{
|
||||
if ( group )
|
||||
{
|
||||
debug( "New dataset while previous one is still active!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
isVector = cardType == "BEGVEC";
|
||||
|
||||
group = std::make_shared< DatasetGroup >(
|
||||
mesh,
|
||||
mDatFile,
|
||||
name
|
||||
);
|
||||
group->setIsScalar( !isVector );
|
||||
group->setIsOnVertices( !faceCentered );
|
||||
}
|
||||
else if ( !oldFormat && cardType == "ENDDS" )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
debug( "ENDDS card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
group->setStatistics( MDAL::calculateStatistics( group ) );
|
||||
mesh->datasetGroups.push_back( group );
|
||||
group.reset();
|
||||
}
|
||||
else if ( !oldFormat && cardType == "NAME" && items.size() >= 2 )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
debug( "NAME card for no active dataset!" );
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
}
|
||||
|
||||
size_t quoteIdx1 = line.find( '\"' );
|
||||
size_t quoteIdx2 = line.find( '\"', quoteIdx1 + 1 );
|
||||
if ( quoteIdx1 != std::string::npos && quoteIdx2 != std::string::npos )
|
||||
group->setName( line.substr( quoteIdx1 + 1, quoteIdx2 - quoteIdx1 - 1 ) );
|
||||
}
|
||||
else if ( oldFormat && ( cardType == "SCALAR" || cardType == "VECTOR" ) )
|
||||
{
|
||||
// just ignore - we know the type from earlier...
|
||||
}
|
||||
else if ( cardType == "TS" && items.size() >= ( oldFormat ? 2 : 3 ) )
|
||||
{
|
||||
double t = toDouble( items[oldFormat ? 1 : 2] );
|
||||
|
||||
if ( faceCentered )
|
||||
{
|
||||
readFaceTimestep( mesh, group, t, isVector, in );
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hasStatus = ( oldFormat ? false : toBool( items[1] ) );
|
||||
readVertexTimestep( mesh, group, t, isVector, hasStatus, in );
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream str;
|
||||
str << " Unknown card:" << line;
|
||||
debug( str.str() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( oldFormat )
|
||||
{
|
||||
if ( !group || group->datasets.size() == 0 )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
group->setStatistics( MDAL::calculateStatistics( group ) );
|
||||
mesh->datasetGroups.push_back( group );
|
||||
group.reset();
|
||||
// we need to parse first line again to see
|
||||
// scalar/vector flag or timestep flag
|
||||
in.clear();
|
||||
in.seekg( 0 );
|
||||
loadOldFormat( in, mesh, status );
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,7 +294,7 @@ void MDAL::DriverAsciiDat::readVertexTimestep(
|
||||
double t,
|
||||
bool isVector,
|
||||
bool hasStatus,
|
||||
std::ifstream &stream )
|
||||
std::ifstream &stream ) const
|
||||
{
|
||||
assert( group );
|
||||
size_t faceCount = mesh->facesCount();
|
||||
@ -299,7 +360,7 @@ void MDAL::DriverAsciiDat::readFaceTimestep(
|
||||
std::shared_ptr<DatasetGroup> group,
|
||||
double t,
|
||||
bool isVector,
|
||||
std::ifstream &stream )
|
||||
std::ifstream &stream ) const
|
||||
{
|
||||
assert( group );
|
||||
|
||||
|
34
external/mdal/frmts/mdal_ascii_dat.hpp
vendored
34
external/mdal/frmts/mdal_ascii_dat.hpp
vendored
@ -20,6 +20,29 @@
|
||||
namespace MDAL
|
||||
{
|
||||
|
||||
/**
|
||||
* ASCII Dat format is used by various solvers and the output
|
||||
* from various solvers can have slightly different header.
|
||||
* The format is used by TUFLOW, BASEMENT and HYDRO_AS-2D solvers.
|
||||
*
|
||||
* The most frequent form is based on official SMS documentation
|
||||
* https://www.xmswiki.com/wiki/SMS:ASCII_Dataset_Files_*.dat
|
||||
* The official format only supports data defined on vertices,
|
||||
* both scalar vector. The new format is recognized by keyword
|
||||
* "DATASET" on the first line of the file.
|
||||
*
|
||||
* BASEMENT solver also stores data defined on faces. To recognize
|
||||
* such dataset, the dataset name contains "_els_" substring
|
||||
* (e.g. depth_els_1.dat)
|
||||
*
|
||||
* In one file, there is always one dataset group stored.
|
||||
*
|
||||
* Sometime the "older" datasets may have some part of the
|
||||
* header missing, e.g. the file starts with SCALAR or VECTOR or TS
|
||||
* keyword. The older format does not have "active" flags for faces
|
||||
* and does not recognize most of the keywords. Old format data
|
||||
* are always defined on vertices
|
||||
*/
|
||||
class DriverAsciiDat: public Driver
|
||||
{
|
||||
public:
|
||||
@ -30,22 +53,27 @@ namespace MDAL
|
||||
bool canRead( const std::string &uri ) override;
|
||||
void load( const std::string &datFile, Mesh *mesh, MDAL_Status *status ) override;
|
||||
|
||||
|
||||
private:
|
||||
bool canReadOldFormat( const std::string &line ) const;
|
||||
bool canReadNewFormat( const std::string &line ) const;
|
||||
|
||||
void loadOldFormat( std::ifstream &in, Mesh *mesh, MDAL_Status *status ) const;
|
||||
void loadNewFormat( std::ifstream &in, Mesh *mesh, MDAL_Status *status ) const;
|
||||
|
||||
void readVertexTimestep(
|
||||
const Mesh *mesh,
|
||||
std::shared_ptr<DatasetGroup> group,
|
||||
double t,
|
||||
bool isVector,
|
||||
bool hasStatus,
|
||||
std::ifstream &stream );
|
||||
std::ifstream &stream ) const;
|
||||
|
||||
void readFaceTimestep(
|
||||
const Mesh *mesh,
|
||||
std::shared_ptr<DatasetGroup> group,
|
||||
double t,
|
||||
bool isVector,
|
||||
std::ifstream &stream );
|
||||
std::ifstream &stream ) const;
|
||||
|
||||
std::string mDatFile;
|
||||
};
|
||||
|
133
external/mdal/frmts/mdal_binary_dat.cpp
vendored
133
external/mdal/frmts/mdal_binary_dat.cpp
vendored
@ -75,7 +75,7 @@ MDAL::DriverBinaryDat::DriverBinaryDat():
|
||||
Driver( "BINARY_DAT",
|
||||
"Binary DAT",
|
||||
"*.dat",
|
||||
DriverType::CanReadOnlyDatasets
|
||||
Capability::ReadDatasets | Capability::WriteDatasets
|
||||
)
|
||||
{
|
||||
}
|
||||
@ -141,7 +141,7 @@ void MDAL::DriverBinaryDat::load( const std::string &datFile, MDAL::Mesh *mesh,
|
||||
int objid;
|
||||
int numdata;
|
||||
int numcells;
|
||||
char name[40];
|
||||
char groupName[40];
|
||||
char istat;
|
||||
float time;
|
||||
|
||||
@ -152,6 +152,7 @@ void MDAL::DriverBinaryDat::load( const std::string &datFile, MDAL::Mesh *mesh,
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mesh,
|
||||
mDatFile
|
||||
); // DAT datasets
|
||||
@ -160,6 +161,7 @@ void MDAL::DriverBinaryDat::load( const std::string &datFile, MDAL::Mesh *mesh,
|
||||
// in TUFLOW results there could be also a special timestep (99999) with maximums
|
||||
// we will put it into a separate dataset
|
||||
std::shared_ptr<DatasetGroup> groupMax = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mesh,
|
||||
mDatFile
|
||||
);
|
||||
@ -235,11 +237,11 @@ void MDAL::DriverBinaryDat::load( const std::string &datFile, MDAL::Mesh *mesh,
|
||||
|
||||
case CT_NAME:
|
||||
// Name
|
||||
if ( read( in, reinterpret_cast< char * >( &name ), 40 ) )
|
||||
if ( read( in, reinterpret_cast< char * >( &groupName ), 40 ) )
|
||||
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat );
|
||||
if ( name[39] != 0 )
|
||||
name[39] = 0;
|
||||
group->setName( trim( std::string( name ) ) );
|
||||
if ( groupName[39] != 0 )
|
||||
groupName[39] = 0;
|
||||
group->setName( trim( std::string( groupName ) ) );
|
||||
groupMax->setName( group->name() + "/Maximums" );
|
||||
break;
|
||||
|
||||
@ -340,3 +342,122 @@ bool MDAL::DriverBinaryDat::readVertexTimestep( const MDAL::Mesh *mesh,
|
||||
}
|
||||
return false; //OK
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////
|
||||
// WRITE
|
||||
// ////////////////////////////////////////////
|
||||
|
||||
static bool writeRawData( std::ofstream &out, const char *s, int n )
|
||||
{
|
||||
out.write( s, n );
|
||||
if ( !out )
|
||||
return true; //error
|
||||
else
|
||||
return false; //OK
|
||||
}
|
||||
|
||||
bool MDAL::DriverBinaryDat::persist( MDAL::DatasetGroup *group )
|
||||
{
|
||||
std::ofstream out( group->uri(), std::ofstream::out | std::ofstream::binary );
|
||||
|
||||
// implementation based on information from:
|
||||
// http://www.xmswiki.com/wiki/SMS:Binary_Dataset_Files_*.dat
|
||||
if ( !out )
|
||||
return true; // Couldn't open the file
|
||||
|
||||
const Mesh *mesh = group->mesh();
|
||||
size_t nodeCount = mesh->verticesCount();
|
||||
size_t elemCount = mesh->facesCount();
|
||||
|
||||
if ( !group->isOnVertices() )
|
||||
{
|
||||
// Element outputs not supported in the format
|
||||
return true;
|
||||
}
|
||||
|
||||
// version card
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_VERSION ), 4 );
|
||||
|
||||
// objecttype
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_OBJTYPE ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_2D_MESHES ), 4 );
|
||||
|
||||
// float size
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_SFLT ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_FLOAT_SIZE ), 4 );
|
||||
|
||||
// Flag size
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_SFLG ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CF_FLAG_SIZE ), 4 );
|
||||
|
||||
// Dataset Group Type
|
||||
if ( group->isScalar() )
|
||||
{
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_BEGSCL ), 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_BEGVEC ), 4 );
|
||||
}
|
||||
|
||||
// Object id (ignored)
|
||||
int ignored_val = 1;
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_OBJID ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &ignored_val ), 4 );
|
||||
|
||||
// Num nodes
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_NUMDATA ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &nodeCount ), 4 );
|
||||
|
||||
// Num cells
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_NUMCELLS ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &elemCount ), 4 );
|
||||
|
||||
// Name
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_NAME ), 4 );
|
||||
writeRawData( out, MDAL::leftJustified( group->name(), 39 ).c_str(), 40 );
|
||||
|
||||
// Time steps
|
||||
int istat = 1; // include if elements are active
|
||||
|
||||
for ( size_t time_index = 0; time_index < group->datasets.size(); ++ time_index )
|
||||
{
|
||||
const std::shared_ptr<MDAL::MemoryDataset> dataset = std::dynamic_pointer_cast<MDAL::MemoryDataset>( group->datasets[time_index] );
|
||||
|
||||
writeRawData( out, reinterpret_cast< const char * >( &CT_TS ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &istat ), 1 );
|
||||
float ftime = static_cast<float>( dataset->time() );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &ftime ), 4 );
|
||||
|
||||
if ( istat )
|
||||
{
|
||||
// Write status flags
|
||||
for ( size_t i = 0; i < elemCount; i++ )
|
||||
{
|
||||
bool active = static_cast<bool>( dataset->active()[i] );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &active ), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < nodeCount; i++ )
|
||||
{
|
||||
// Read values flags
|
||||
if ( !group->isScalar() )
|
||||
{
|
||||
float x = static_cast<float>( dataset->values()[2 * i] );
|
||||
float y = static_cast<float>( dataset->values()[2 * i + 1 ] );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &x ), 4 );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &y ), 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
float val = static_cast<float>( dataset->values()[i] );
|
||||
writeRawData( out, reinterpret_cast< const char * >( &val ), 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( writeRawData( out, reinterpret_cast< const char * >( &CT_ENDDS ), 4 ) ) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
1
external/mdal/frmts/mdal_binary_dat.hpp
vendored
1
external/mdal/frmts/mdal_binary_dat.hpp
vendored
@ -29,6 +29,7 @@ namespace MDAL
|
||||
|
||||
bool canRead( const std::string &uri ) override;
|
||||
void load( const std::string &datFile, Mesh *mesh, MDAL_Status *status ) override;
|
||||
bool persist( DatasetGroup *group ) override;
|
||||
|
||||
private:
|
||||
bool readVertexTimestep( const Mesh *mesh,
|
||||
|
11
external/mdal/frmts/mdal_cf.cpp
vendored
11
external/mdal/frmts/mdal_cf.cpp
vendored
@ -5,14 +5,15 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <netcdf.h>
|
||||
#include "math.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mdal_data_model.hpp"
|
||||
#include "mdal_cf.hpp"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
#include "math.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CF_THROW_ERR throw MDAL_Status::Err_UnknownFormat
|
||||
|
||||
MDAL::cfdataset_info_map MDAL::DriverCF::parseDatasetGroupInfo()
|
||||
@ -182,6 +183,7 @@ void MDAL::DriverCF::addDatasetGroups( MDAL::Mesh *mesh, const std::vector<doubl
|
||||
const CFDatasetGroupInfo dsi = it.second;
|
||||
// Create a dataset group
|
||||
std::shared_ptr<MDAL::DatasetGroup> group = std::make_shared<MDAL::DatasetGroup>(
|
||||
name(),
|
||||
mesh,
|
||||
mFileName,
|
||||
dsi.name
|
||||
@ -245,7 +247,7 @@ void MDAL::DriverCF::parseTime( std::vector<double> × )
|
||||
MDAL::DriverCF::DriverCF( const std::string &name,
|
||||
const std::string &longName,
|
||||
const std::string &filters ):
|
||||
Driver( name, longName, filters, DriverType::CanReadMeshAndDatasets )
|
||||
Driver( name, longName, filters, Capability::ReadMesh )
|
||||
{
|
||||
}
|
||||
|
||||
@ -327,6 +329,7 @@ std::unique_ptr< MDAL::Mesh > MDAL::DriverCF::load( const std::string &fileName,
|
||||
populateFacesAndVertices( vertices, faces );
|
||||
std::unique_ptr< MemoryMesh > mesh(
|
||||
new MemoryMesh(
|
||||
name(),
|
||||
vertices.size(),
|
||||
faces.size(),
|
||||
mDimensions.MaxVerticesInFace,
|
||||
|
41
external/mdal/frmts/mdal_driver.cpp
vendored
41
external/mdal/frmts/mdal_driver.cpp
vendored
@ -3,17 +3,19 @@
|
||||
Copyright (C) 2018 Lutra Consulting Ltd.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "mdal_driver.hpp"
|
||||
#include "mdal_utils.hpp"
|
||||
#include "mdal_memory_data_model.hpp"
|
||||
|
||||
MDAL::Driver::Driver( const std::string &name,
|
||||
const std::string &longName,
|
||||
const std::string &filters,
|
||||
DriverType type )
|
||||
int capabilityFlags )
|
||||
: mName( name )
|
||||
, mLongName( longName )
|
||||
, mFilters( filters )
|
||||
, mType( type )
|
||||
, mCapabilityFlags( capabilityFlags )
|
||||
{
|
||||
|
||||
}
|
||||
@ -35,9 +37,9 @@ std::string MDAL::Driver::filters() const
|
||||
return mFilters;
|
||||
}
|
||||
|
||||
MDAL::DriverType MDAL::Driver::type() const
|
||||
bool MDAL::Driver::hasCapability( MDAL::Capability capability ) const
|
||||
{
|
||||
return mType;
|
||||
return capability == ( mCapabilityFlags & capability );
|
||||
}
|
||||
|
||||
std::unique_ptr< MDAL::Mesh > MDAL::Driver::load( const std::string &uri, MDAL_Status *status )
|
||||
@ -54,3 +56,34 @@ void MDAL::Driver::load( const std::string &uri, Mesh *mesh, MDAL_Status *status
|
||||
MDAL_UNUSED( status );
|
||||
return;
|
||||
}
|
||||
|
||||
void MDAL::Driver::createDatasetGroup( MDAL::Mesh *mesh, const std::string &groupName, bool isOnVertices, bool hasScalarData, const std::string &datasetGroupFile )
|
||||
{
|
||||
std::shared_ptr<MDAL::DatasetGroup> grp(
|
||||
new MDAL::DatasetGroup( name(),
|
||||
mesh,
|
||||
datasetGroupFile )
|
||||
);
|
||||
grp->setName( groupName );
|
||||
grp->setIsOnVertices( isOnVertices );
|
||||
grp->setIsScalar( hasScalarData );
|
||||
grp->startEditing();
|
||||
mesh->datasetGroups.push_back( grp );
|
||||
}
|
||||
|
||||
void MDAL::Driver::createDataset( MDAL::DatasetGroup *group, double time, const double *values, const int *active )
|
||||
{
|
||||
std::shared_ptr<MDAL::MemoryDataset> dataset = std::make_shared< MemoryDataset >( group );
|
||||
dataset->setTime( time );
|
||||
memcpy( dataset->values(), values, sizeof( double ) * dataset->valuesCount() );
|
||||
if ( active && dataset->active() )
|
||||
memcpy( dataset->active(), active, sizeof( int ) * dataset->mesh()->facesCount() );
|
||||
dataset->setStatistics( MDAL::calculateStatistics( dataset ) );
|
||||
group->datasets.push_back( dataset );
|
||||
}
|
||||
|
||||
bool MDAL::Driver::persist( MDAL::DatasetGroup *group )
|
||||
{
|
||||
MDAL_UNUSED( group );
|
||||
return true; // failure
|
||||
}
|
||||
|
32
external/mdal/frmts/mdal_driver.hpp
vendored
32
external/mdal/frmts/mdal_driver.hpp
vendored
@ -12,10 +12,12 @@
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
enum DriverType
|
||||
enum Capability
|
||||
{
|
||||
CanReadMeshAndDatasets,
|
||||
CanReadOnlyDatasets
|
||||
None = 0,
|
||||
ReadMesh = 1 << 0, //! Can read mesh and all datasets stored in the mesh file
|
||||
ReadDatasets = 1 << 1, //! Can read only datasets (groups) from existing mesh
|
||||
WriteDatasets = 1 << 2, //! Can write datasets (groups)
|
||||
};
|
||||
|
||||
class Driver
|
||||
@ -24,7 +26,7 @@ namespace MDAL
|
||||
Driver( const std::string &name,
|
||||
const std::string &longName,
|
||||
const std::string &filters,
|
||||
DriverType type
|
||||
int capabilityFlags
|
||||
);
|
||||
virtual ~Driver();
|
||||
|
||||
@ -33,7 +35,7 @@ namespace MDAL
|
||||
std::string name() const;
|
||||
std::string longName() const;
|
||||
std::string filters() const;
|
||||
DriverType type() const;
|
||||
bool hasCapability( Capability capability ) const;
|
||||
|
||||
virtual bool canRead( const std::string &uri ) = 0;
|
||||
|
||||
@ -42,11 +44,29 @@ namespace MDAL
|
||||
// loads datasets
|
||||
virtual void load( const std::string &uri, Mesh *mesh, MDAL_Status *status );
|
||||
|
||||
// create new dataset group
|
||||
virtual void createDatasetGroup(
|
||||
Mesh *mesh,
|
||||
const std::string &groupName,
|
||||
bool isOnVertices,
|
||||
bool hasScalarData,
|
||||
const std::string &datasetGroupFile );
|
||||
|
||||
// create new dataset from array
|
||||
virtual void createDataset( DatasetGroup *group,
|
||||
double time,
|
||||
const double *values,
|
||||
const int *active );
|
||||
|
||||
// persist to the file
|
||||
// returns true on error, false on success
|
||||
virtual bool persist( DatasetGroup *group );
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
std::string mLongName;
|
||||
std::string mFilters;
|
||||
DriverType mType;
|
||||
int mCapabilityFlags;
|
||||
};
|
||||
|
||||
} // namespace MDAL
|
||||
|
12
external/mdal/frmts/mdal_flo2d.cpp
vendored
12
external/mdal/frmts/mdal_flo2d.cpp
vendored
@ -73,13 +73,14 @@ static double getDouble( const std::string &val )
|
||||
void MDAL::DriverFlo2D::addStaticDataset(
|
||||
bool isOnVertices,
|
||||
std::vector<double> &vals,
|
||||
const std::string &name,
|
||||
const std::string &groupName,
|
||||
const std::string &datFileName )
|
||||
{
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
datFileName,
|
||||
name
|
||||
groupName
|
||||
);
|
||||
group->setIsOnVertices( isOnVertices );
|
||||
group->setIsScalar( true );
|
||||
@ -186,6 +187,7 @@ void MDAL::DriverFlo2D::parseTIMDEPFile( const std::string &datFileName, const s
|
||||
size_t face_idx = 0;
|
||||
|
||||
std::shared_ptr<DatasetGroup> depthDsGroup = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
datFileName,
|
||||
"Depth"
|
||||
@ -195,6 +197,7 @@ void MDAL::DriverFlo2D::parseTIMDEPFile( const std::string &datFileName, const s
|
||||
|
||||
|
||||
std::shared_ptr<DatasetGroup> waterLevelDsGroup = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
datFileName,
|
||||
"Water Level"
|
||||
@ -203,6 +206,7 @@ void MDAL::DriverFlo2D::parseTIMDEPFile( const std::string &datFileName, const s
|
||||
waterLevelDsGroup->setIsScalar( true );
|
||||
|
||||
std::shared_ptr<DatasetGroup> flowDsGroup = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
datFileName,
|
||||
"Velocity"
|
||||
@ -486,6 +490,7 @@ void MDAL::DriverFlo2D::createMesh( const std::vector<CellCenter> &cells, double
|
||||
|
||||
mMesh.reset(
|
||||
new MemoryMesh(
|
||||
name(),
|
||||
vertices.size(),
|
||||
faces.size(),
|
||||
4, //maximum quads
|
||||
@ -567,6 +572,7 @@ bool MDAL::DriverFlo2D::parseHDF5Datasets( const std::string &datFileName )
|
||||
|
||||
// Create dataset now
|
||||
std::shared_ptr<DatasetGroup> ds = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
datFileName,
|
||||
grpName
|
||||
@ -630,7 +636,7 @@ MDAL::DriverFlo2D::DriverFlo2D()
|
||||
"FLO2D",
|
||||
"Flo2D",
|
||||
"*.nc",
|
||||
DriverType::CanReadMeshAndDatasets )
|
||||
Capability::ReadMesh )
|
||||
{
|
||||
|
||||
}
|
||||
|
2
external/mdal/frmts/mdal_flo2d.hpp
vendored
2
external/mdal/frmts/mdal_flo2d.hpp
vendored
@ -47,7 +47,7 @@ namespace MDAL
|
||||
void parseTIMDEPFile( const std::string &datFileName, const std::vector<double> &elevations );
|
||||
void parseFPLAINFile( std::vector<double> &elevations, const std::string &datFileName, std::vector<CellCenter> &cells );
|
||||
void parseCADPTSFile( const std::string &datFileName, std::vector<CellCenter> &cells );
|
||||
void addStaticDataset( bool isOnVertices, std::vector<double> &vals, const std::string &name, const std::string &datFileName );
|
||||
void addStaticDataset( bool isOnVertices, std::vector<double> &vals, const std::string &groupName, const std::string &datFileName );
|
||||
static MDAL::Vertex createVertex( size_t position, double half_cell_size, const CellCenter &cell );
|
||||
static double calcCellSize( const std::vector<CellCenter> &cells );
|
||||
};
|
||||
|
71
external/mdal/frmts/mdal_gdal.cpp
vendored
71
external/mdal/frmts/mdal_gdal.cpp
vendored
@ -259,6 +259,60 @@ void MDAL::DriverGdal::parseRasterBands( const MDAL::GdalDataset *cfGDALDataset
|
||||
}
|
||||
}
|
||||
|
||||
void MDAL::DriverGdal::fixRasterBands()
|
||||
{
|
||||
// go through all bands and find out if both x and y dataset are valid
|
||||
// if such pair if found, make the group scalar by removal of null band pointer
|
||||
// this can happen is parseBandInfo() returns false-positive in vector detection
|
||||
for ( data_hash::iterator band = mBands.begin(); band != mBands.end(); band++ )
|
||||
{
|
||||
if ( band->second.empty() )
|
||||
continue;
|
||||
|
||||
// scalars are always ok
|
||||
bool is_scalar = ( band->second.begin()->second.size() == 1 );
|
||||
if ( is_scalar )
|
||||
continue;
|
||||
|
||||
// check if we have some null bands
|
||||
int needs_fix = false;
|
||||
for ( timestep_map::const_iterator time_step = band->second.begin(); time_step != band->second.end(); time_step++ )
|
||||
{
|
||||
std::vector<GDALRasterBandH> raster_bands = time_step->second;
|
||||
|
||||
if ( !raster_bands[0] )
|
||||
{
|
||||
needs_fix = true;
|
||||
break;
|
||||
}
|
||||
if ( !raster_bands[1] )
|
||||
{
|
||||
needs_fix = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// convert this vector to scalar
|
||||
if ( needs_fix )
|
||||
{
|
||||
for ( timestep_map::iterator time_step = band->second.begin(); time_step != band->second.end(); time_step++ )
|
||||
{
|
||||
std::vector<GDALRasterBandH> &raster_bands = time_step->second;
|
||||
|
||||
if ( !raster_bands[0] )
|
||||
{
|
||||
raster_bands[0] = raster_bands[1];
|
||||
}
|
||||
// get rid of y-coord
|
||||
raster_bands.resize( 1 );
|
||||
|
||||
// not we should have only 1 band and valid
|
||||
assert( raster_bands[0] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MDAL::DriverGdal::addDataToOutput( GDALRasterBandH raster_band, std::shared_ptr<MemoryDataset> tos, bool is_vector, bool is_x )
|
||||
{
|
||||
assert( raster_band );
|
||||
@ -335,9 +389,10 @@ void MDAL::DriverGdal::activateFaces( std::shared_ptr<MemoryDataset> tos )
|
||||
Face elem = mMesh->faces.at( idx );
|
||||
for ( size_t i = 0; i < 4; ++i )
|
||||
{
|
||||
const size_t vertexIndex = elem[i];
|
||||
if ( isScalar )
|
||||
{
|
||||
double val = values[elem[i]];
|
||||
double val = values[vertexIndex];
|
||||
if ( std::isnan( val ) )
|
||||
{
|
||||
active[idx] = 0; //NOT ACTIVE
|
||||
@ -346,8 +401,8 @@ void MDAL::DriverGdal::activateFaces( std::shared_ptr<MemoryDataset> tos )
|
||||
}
|
||||
else
|
||||
{
|
||||
double x = values[elem[2 * i]];
|
||||
double y = values[elem[2 * i + 1]];
|
||||
double x = values[2 * vertexIndex];
|
||||
double y = values[2 * vertexIndex + 1];
|
||||
if ( std::isnan( x ) || std::isnan( y ) )
|
||||
{
|
||||
active[idx] = 0; //NOT ACTIVE
|
||||
@ -367,6 +422,7 @@ void MDAL::DriverGdal::addDatasetGroups()
|
||||
continue;
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
mFileName,
|
||||
band->first
|
||||
@ -405,6 +461,7 @@ void MDAL::DriverGdal::createMesh()
|
||||
initFaces( vertices, faces, is_longitude_shifted );
|
||||
|
||||
mMesh.reset( new MemoryMesh(
|
||||
name(),
|
||||
vertices.size(),
|
||||
faces.size(),
|
||||
4, //maximum quads
|
||||
@ -483,7 +540,7 @@ MDAL::DriverGdal::DriverGdal( const std::string &name,
|
||||
const std::string &description,
|
||||
const std::string &filter,
|
||||
const std::string &gdalDriverName ):
|
||||
Driver( name, description, filter, DriverType::CanReadMeshAndDatasets ),
|
||||
Driver( name, description, filter, Capability::ReadMesh ),
|
||||
mGdalDriverName( gdalDriverName ),
|
||||
mPafScanline( nullptr )
|
||||
{}
|
||||
@ -549,6 +606,12 @@ std::unique_ptr<MDAL::Mesh> MDAL::DriverGdal::load( const std::string &fileName,
|
||||
}
|
||||
}
|
||||
|
||||
// Fix consistency of groups
|
||||
// It can happen that we thought that the
|
||||
// group is vector based on name, but it could be just coicidence
|
||||
// or clash in naming
|
||||
fixRasterBands();
|
||||
|
||||
// Create MDAL datasets
|
||||
addDatasetGroups();
|
||||
}
|
||||
|
1
external/mdal/frmts/mdal_gdal.hpp
vendored
1
external/mdal/frmts/mdal_gdal.hpp
vendored
@ -94,6 +94,7 @@ namespace MDAL
|
||||
void addDatasetGroups();
|
||||
void createMesh();
|
||||
void parseRasterBands( const GdalDataset *cfGDALDataset );
|
||||
void fixRasterBands();
|
||||
|
||||
std::string mFileName;
|
||||
const std::string mGdalDriverName; /* GDAL driver name */
|
||||
|
117
external/mdal/frmts/mdal_hec2d.cpp
vendored
117
external/mdal/frmts/mdal_hec2d.cpp
vendored
@ -119,6 +119,7 @@ void MDAL::DriverHec2D::readFaceOutput( const HdfFile &hdfFile,
|
||||
double eps = std::numeric_limits<double>::min();
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
mFileName,
|
||||
datasetName
|
||||
@ -163,7 +164,7 @@ void MDAL::DriverHec2D::readFaceOutput( const HdfFile &hdfFile,
|
||||
{
|
||||
for ( size_t c = 0; c < 2; ++c )
|
||||
{
|
||||
size_t cell_idx = face2Cells[2 * i + c] + areaElemStartIndex[nArea];
|
||||
size_t cell_idx = static_cast<size_t>( face2Cells[2 * i + c] ) + areaElemStartIndex[nArea];
|
||||
// Take just maximum
|
||||
if ( std::isnan( values[cell_idx] ) || values[cell_idx] < val )
|
||||
{
|
||||
@ -216,6 +217,7 @@ std::shared_ptr<MDAL::MemoryDataset> MDAL::DriverHec2D::readElemOutput( const Hd
|
||||
double eps = std::numeric_limits<double>::min();
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
name(),
|
||||
mMesh.get(),
|
||||
mFileName,
|
||||
datasetName
|
||||
@ -354,7 +356,7 @@ void MDAL::DriverHec2D::readElemResults(
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<std::string> read2DFlowAreasNames( HdfGroup gGeom2DFlowAreas )
|
||||
std::vector<std::string> MDAL::DriverHec2D::read2DFlowAreasNamesOld( HdfGroup gGeom2DFlowAreas ) const
|
||||
{
|
||||
HdfDataset dsNames = openHdfDataset( gGeom2DFlowAreas, "Names" );
|
||||
std::vector<std::string> names = dsNames.readArrayString();
|
||||
@ -365,6 +367,85 @@ std::vector<std::string> read2DFlowAreasNames( HdfGroup gGeom2DFlowAreas )
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
For 5.0.5+ format
|
||||
|
||||
DATATYPE H5T_COMPOUND {
|
||||
H5T_STRING {
|
||||
STRSIZE 16;
|
||||
STRPAD H5T_STR_NULLTERM;
|
||||
CSET H5T_CSET_ASCII;
|
||||
CTYPE H5T_C_S1;
|
||||
} "Name";
|
||||
H5T_IEEE_F32LE "Mann";
|
||||
H5T_IEEE_F32LE "Cell Vol Tol";
|
||||
H5T_IEEE_F32LE "Cell Min Area Fraction";
|
||||
H5T_IEEE_F32LE "Face Profile Tol";
|
||||
H5T_IEEE_F32LE "Face Area Tol";
|
||||
H5T_IEEE_F32LE "Face Conv Ratio";
|
||||
H5T_IEEE_F32LE "Laminar Depth";
|
||||
H5T_IEEE_F32LE "Spacing dx";
|
||||
H5T_IEEE_F32LE "Spacing dy";
|
||||
H5T_IEEE_F32LE "Shift dx";
|
||||
H5T_IEEE_F32LE "Shift dy";
|
||||
H5T_STD_I32LE "Cell Count";
|
||||
}
|
||||
*/
|
||||
typedef struct FlowAreasAttribute505
|
||||
{
|
||||
char name[HDF_MAX_NAME];
|
||||
float mann;
|
||||
float cellVolTol;
|
||||
float cellMinAreaFraction;
|
||||
float faceProfileTol;
|
||||
float faceAreaTol;
|
||||
float faceConvRatio;
|
||||
float laminarDepth;
|
||||
float spacingDx;
|
||||
float spacingDy;
|
||||
float shifyDx;
|
||||
float shifyDy;
|
||||
int cellCount;
|
||||
} FlowAreasAttribute505;
|
||||
|
||||
|
||||
std::vector<std::string> MDAL::DriverHec2D::read2DFlowAreasNames505( HdfGroup gGeom2DFlowAreas ) const
|
||||
{
|
||||
HdfDataset dsAttributes = openHdfDataset( gGeom2DFlowAreas, "Attributes" );
|
||||
hid_t attributeHID = H5Tcreate( H5T_COMPOUND, sizeof( FlowAreasAttribute505 ) );
|
||||
hid_t stringHID = H5Tcopy( H5T_C_S1 );
|
||||
H5Tset_size( stringHID, HDF_MAX_NAME );
|
||||
H5Tinsert( attributeHID, "Name", HOFFSET( FlowAreasAttribute505, name ), stringHID );
|
||||
H5Tinsert( attributeHID, "Mann", HOFFSET( FlowAreasAttribute505, mann ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Cell Vol Tol", HOFFSET( FlowAreasAttribute505, cellVolTol ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Cell Min Area Fraction", HOFFSET( FlowAreasAttribute505, cellMinAreaFraction ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Face Profile Tol", HOFFSET( FlowAreasAttribute505, faceProfileTol ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Face Area Tol", HOFFSET( FlowAreasAttribute505, faceAreaTol ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Face Conv Ratio", HOFFSET( FlowAreasAttribute505, faceConvRatio ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Laminar Depth", HOFFSET( FlowAreasAttribute505, laminarDepth ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Spacing dx", HOFFSET( FlowAreasAttribute505, spacingDx ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Spacing dy", HOFFSET( FlowAreasAttribute505, spacingDy ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Shift dx", HOFFSET( FlowAreasAttribute505, shifyDx ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Shift dy", HOFFSET( FlowAreasAttribute505, shifyDy ), H5T_NATIVE_FLOAT );
|
||||
H5Tinsert( attributeHID, "Cell Count", HOFFSET( FlowAreasAttribute505, cellCount ), H5T_NATIVE_INT );
|
||||
std::vector<FlowAreasAttribute505> attributes = dsAttributes.readArray<FlowAreasAttribute505>( attributeHID );
|
||||
H5Tclose( attributeHID );
|
||||
H5Tclose( stringHID );
|
||||
std::vector<std::string> names;
|
||||
if ( attributes.empty() )
|
||||
{
|
||||
throw MDAL_Status::Err_InvalidData;
|
||||
}
|
||||
|
||||
for ( const auto &attr : attributes )
|
||||
{
|
||||
std::string dat = std::string( attr.name );
|
||||
names.push_back( MDAL::trim( dat ) );
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
void MDAL::DriverHec2D::setProjection( HdfFile hdfFile )
|
||||
{
|
||||
try
|
||||
@ -441,6 +522,7 @@ void MDAL::DriverHec2D::parseMesh(
|
||||
|
||||
mMesh.reset(
|
||||
new MemoryMesh(
|
||||
name(),
|
||||
vertices.size(),
|
||||
faces.size(),
|
||||
maxVerticesInFace,
|
||||
@ -456,7 +538,7 @@ MDAL::DriverHec2D::DriverHec2D()
|
||||
: Driver( "HEC2D",
|
||||
"HEC-RAS 2D",
|
||||
"*.hdf",
|
||||
DriverType::CanReadMeshAndDatasets )
|
||||
Capability::ReadMesh )
|
||||
{
|
||||
}
|
||||
|
||||
@ -471,16 +553,22 @@ bool MDAL::DriverHec2D::canRead( const std::string &uri )
|
||||
{
|
||||
HdfFile hdfFile = openHdfFile( uri );
|
||||
std::string fileType = openHdfAttribute( hdfFile, "File Type" );
|
||||
if ( fileType != "HEC-RAS Results" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return canReadOldFormat( fileType ) || canReadFormat505( fileType );
|
||||
}
|
||||
catch ( MDAL_Status )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MDAL::DriverHec2D::canReadOldFormat( const std::string &fileType ) const
|
||||
{
|
||||
return fileType == "HEC-RAS Results";
|
||||
}
|
||||
|
||||
bool MDAL::DriverHec2D::canReadFormat505( const std::string &fileType ) const
|
||||
{
|
||||
return fileType == "HEC-RAS Geometry";
|
||||
}
|
||||
|
||||
std::unique_ptr<MDAL::Mesh> MDAL::DriverHec2D::load( const std::string &resultsFile, MDAL_Status *status )
|
||||
@ -495,15 +583,17 @@ std::unique_ptr<MDAL::Mesh> MDAL::DriverHec2D::load( const std::string &resultsF
|
||||
|
||||
// Verify it is correct file
|
||||
std::string fileType = openHdfAttribute( hdfFile, "File Type" );
|
||||
if ( fileType != "HEC-RAS Results" )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
bool oldFormat = canReadOldFormat( fileType );
|
||||
|
||||
HdfGroup gGeom = openHdfGroup( hdfFile, "Geometry" );
|
||||
HdfGroup gGeom2DFlowAreas = openHdfGroup( gGeom, "2D Flow Areas" );
|
||||
|
||||
std::vector<std::string> flowAreaNames = read2DFlowAreasNames( gGeom2DFlowAreas );
|
||||
std::vector<std::string> flowAreaNames;
|
||||
if ( oldFormat )
|
||||
flowAreaNames = read2DFlowAreasNamesOld( gGeom2DFlowAreas );
|
||||
else
|
||||
flowAreaNames = read2DFlowAreasNames505( gGeom2DFlowAreas );
|
||||
|
||||
std::vector<size_t> areaElemStartIndex( flowAreaNames.size() + 1 );
|
||||
|
||||
parseMesh( gGeom2DFlowAreas, areaElemStartIndex, flowAreaNames );
|
||||
@ -517,6 +607,7 @@ std::unique_ptr<MDAL::Mesh> MDAL::DriverHec2D::load( const std::string &resultsF
|
||||
|
||||
// Face centered Values
|
||||
readFaceResults( hdfFile, areaElemStartIndex, flowAreaNames );
|
||||
|
||||
}
|
||||
catch ( MDAL_Status error )
|
||||
{
|
||||
|
26
external/mdal/frmts/mdal_hec2d.hpp
vendored
26
external/mdal/frmts/mdal_hec2d.hpp
vendored
@ -16,6 +16,17 @@
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
/**
|
||||
* HEC-RAS 2D format.
|
||||
*
|
||||
* This is a HDF5-based format to store mesh and datasets
|
||||
* in a single file. The format supports meshes is multiple
|
||||
* (disconnected) areas.
|
||||
*
|
||||
* There is a small change in the format in HEC-RAS 5.0.5+, where
|
||||
* - Header File Type is different (HEC-RAS Results vs HEC-RAS Geometry)
|
||||
* - Names or areas are stored in different place (names array vs attributes array)
|
||||
*/
|
||||
class DriverHec2D: public Driver
|
||||
{
|
||||
public:
|
||||
@ -30,6 +41,15 @@ namespace MDAL
|
||||
std::unique_ptr< MDAL::MemoryMesh > mMesh;
|
||||
std::string mFileName;
|
||||
|
||||
// Pre 5.0.5 format
|
||||
bool canReadOldFormat( const std::string &fileType ) const;
|
||||
std::vector<std::string> read2DFlowAreasNamesOld( HdfGroup gGeom2DFlowAreas ) const;
|
||||
|
||||
// 5.0.5 + format
|
||||
bool canReadFormat505( const std::string &fileType ) const;
|
||||
std::vector<std::string> read2DFlowAreasNames505( HdfGroup gGeom2DFlowAreas ) const;
|
||||
|
||||
// Common functions
|
||||
void readFaceOutput( const HdfFile &hdfFile,
|
||||
const HdfGroup &rootGroup,
|
||||
const std::vector<size_t> &areaElemStartIndex,
|
||||
@ -37,9 +57,11 @@ namespace MDAL
|
||||
const std::string rawDatasetName,
|
||||
const std::string datasetName,
|
||||
const std::vector<float> × );
|
||||
|
||||
void readFaceResults( const HdfFile &hdfFile,
|
||||
const std::vector<size_t> &areaElemStartIndex,
|
||||
const std::vector<std::string> &flowAreaNames );
|
||||
|
||||
std::shared_ptr<MDAL::MemoryDataset> readElemOutput(
|
||||
const HdfGroup &rootGroup,
|
||||
const std::vector<size_t> &areaElemStartIndex,
|
||||
@ -48,14 +70,18 @@ namespace MDAL
|
||||
const std::string datasetName,
|
||||
const std::vector<float> ×,
|
||||
std::shared_ptr<MDAL::MemoryDataset> bed_elevation );
|
||||
|
||||
std::shared_ptr<MDAL::MemoryDataset> readBedElevation(
|
||||
const HdfGroup &gGeom2DFlowAreas,
|
||||
const std::vector<size_t> &areaElemStartIndex,
|
||||
const std::vector<std::string> &flowAreaNames );
|
||||
|
||||
void setProjection( HdfFile hdfFile );
|
||||
|
||||
void parseMesh( HdfGroup gGeom2DFlowAreas,
|
||||
std::vector<size_t> &areaElemStartIndex,
|
||||
const std::vector<std::string> &flowAreaNames );
|
||||
|
||||
void readElemResults(
|
||||
const HdfFile &hdfFile,
|
||||
std::shared_ptr<MDAL::MemoryDataset> bed_elevation,
|
||||
|
206
external/mdal/frmts/mdal_netcdf.cpp
vendored
Normal file
206
external/mdal/frmts/mdal_netcdf.cpp
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||
Copyright (C) 2019 Peter Petrik (zilolv at gmail dot com)
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#include <netcdf.h>
|
||||
#include "mdal_netcdf.hpp"
|
||||
#include "mdal.h"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
NetCDFFile::NetCDFFile(): mNcid( 0 ) {}
|
||||
|
||||
NetCDFFile::~NetCDFFile()
|
||||
{
|
||||
if ( mNcid != 0 ) nc_close( mNcid );
|
||||
}
|
||||
|
||||
int NetCDFFile::handle() const
|
||||
{
|
||||
return mNcid;
|
||||
}
|
||||
|
||||
void NetCDFFile::openFile( const std::string &fileName )
|
||||
{
|
||||
int res = nc_open( fileName.c_str(), NC_NOWRITE, &mNcid );
|
||||
if ( res != NC_NOERR )
|
||||
{
|
||||
MDAL::debug( nc_strerror( res ) );
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
}
|
||||
|
||||
bool NetCDFFile::hasVariable( const std::string &name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
int varid;
|
||||
return ( nc_inq_varid( mNcid, name.c_str(), &varid ) == NC_NOERR );
|
||||
}
|
||||
|
||||
std::vector<int> NetCDFFile::readIntArr( const std::string &name, size_t dim ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
std::vector<int> arr_val( dim );
|
||||
if ( nc_get_var_int( mNcid, arr_id, arr_val.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return arr_val;
|
||||
}
|
||||
|
||||
std::vector<double> NetCDFFile::readDoubleArr( const std::string &name, size_t dim ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
std::vector<double> arr_val( dim );
|
||||
if ( nc_get_var_double( mNcid, arr_id, arr_val.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return arr_val;
|
||||
}
|
||||
|
||||
bool NetCDFFile::hasArr( const std::string &name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
return nc_inq_varid( mNcid, name.c_str(), &arr_id ) == NC_NOERR;
|
||||
}
|
||||
|
||||
std::vector<std::string> NetCDFFile::readArrNames() const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
std::vector<std::string> res;
|
||||
int nvars;
|
||||
if ( nc_inq_varids( mNcid, &nvars, nullptr ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
std::vector<int> varids( static_cast<size_t>( nvars ) );
|
||||
if ( nc_inq_varids( mNcid, &nvars, varids.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < static_cast<size_t>( nvars ); ++i )
|
||||
{
|
||||
std::vector<char> cname( NC_MAX_NAME + 1 );
|
||||
if ( nc_inq_varname( mNcid, varids[i], cname.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
res.push_back( cname.data() );
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int NetCDFFile::getAttrInt( const std::string &name, const std::string &attr_name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
int val;
|
||||
if ( nc_get_att_int( mNcid, arr_id, attr_name.c_str(), &val ) )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
std::string NetCDFFile::getAttrStr( const std::string &name, const std::string &attr_name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) ) throw MDAL_Status::Err_UnknownFormat;
|
||||
return getAttrStr( attr_name, arr_id );
|
||||
}
|
||||
|
||||
std::string NetCDFFile::getAttrStr( const std::string &name, int varid ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
size_t attlen = 0;
|
||||
|
||||
if ( nc_inq_attlen( mNcid, varid, name.c_str(), &attlen ) )
|
||||
{
|
||||
// attribute is missing
|
||||
return std::string();
|
||||
}
|
||||
|
||||
char *string_attr;
|
||||
string_attr = ( char * ) malloc( attlen + 1 );
|
||||
|
||||
if ( nc_get_att_text( mNcid, varid, name.c_str(), string_attr ) ) throw MDAL_Status::Err_UnknownFormat;
|
||||
string_attr[attlen] = '\0';
|
||||
|
||||
std::string res( string_attr );
|
||||
free( string_attr );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
double NetCDFFile::getFillValue( int varid ) const
|
||||
{
|
||||
return getAttrDouble( varid, "_FillValue" );
|
||||
}
|
||||
|
||||
double NetCDFFile::getAttrDouble( int varid, const std::string &attr_name ) const
|
||||
{
|
||||
double res;
|
||||
if ( nc_get_att_double( mNcid, varid, attr_name.c_str(), &res ) )
|
||||
res = std::numeric_limits<double>::quiet_NaN(); // not present/set
|
||||
return res;
|
||||
}
|
||||
|
||||
int NetCDFFile::getVarId( const std::string &name )
|
||||
{
|
||||
int ncid_val;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &ncid_val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
return ncid_val;
|
||||
}
|
||||
|
||||
void NetCDFFile::getDimension( const std::string &name, size_t *val, int *ncid_val ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
if ( nc_inq_dimid( mNcid, name.c_str(), ncid_val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
if ( nc_inq_dimlen( mNcid, *ncid_val, val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
void NetCDFFile::getDimensionOptional( const std::string &name, size_t *val, int *ncid_val ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
try
|
||||
{
|
||||
getDimension( name, val, ncid_val );
|
||||
}
|
||||
catch ( MDAL_Status )
|
||||
{
|
||||
*ncid_val = -1;
|
||||
*val = 0;
|
||||
}
|
||||
}
|
175
external/mdal/frmts/mdal_netcdf.hpp
vendored
175
external/mdal/frmts/mdal_netcdf.hpp
vendored
@ -8,168 +8,35 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#include <netcdf.h>
|
||||
#include "mdal_utils.hpp"
|
||||
#include "mdal.h"
|
||||
|
||||
//! C++ Wrapper around netcdf C library
|
||||
class NetCDFFile
|
||||
{
|
||||
public:
|
||||
NetCDFFile(): mNcid( 0 ) {}
|
||||
~NetCDFFile()
|
||||
{
|
||||
if ( mNcid != 0 ) nc_close( mNcid );
|
||||
}
|
||||
//! Create file with invalid handle
|
||||
NetCDFFile();
|
||||
//! Closes the file
|
||||
~NetCDFFile();
|
||||
|
||||
int handle() const
|
||||
{
|
||||
return mNcid;
|
||||
}
|
||||
int handle() const;
|
||||
void openFile( const std::string &fileName );
|
||||
bool hasVariable( const std::string &name ) const;
|
||||
|
||||
void openFile( const std::string &fileName )
|
||||
{
|
||||
int res = nc_open( fileName.c_str(), NC_NOWRITE, &mNcid );
|
||||
if ( res != NC_NOERR )
|
||||
{
|
||||
MDAL::debug( nc_strerror( res ) );
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
}
|
||||
std::vector<int> readIntArr( const std::string &name, size_t dim ) const;
|
||||
std::vector<double> readDoubleArr( const std::string &name, size_t dim ) const;
|
||||
bool hasArr( const std::string &name ) const;
|
||||
std::vector<std::string> readArrNames() const;
|
||||
|
||||
bool hasVariable( const std::string &name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
int varid;
|
||||
return ( nc_inq_varid( mNcid, name.c_str(), &varid ) == NC_NOERR );
|
||||
}
|
||||
|
||||
std::vector<int> readIntArr( const std::string &name, size_t dim ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
std::vector<int> arr_val( dim );
|
||||
if ( nc_get_var_int( mNcid, arr_id, arr_val.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return arr_val;
|
||||
}
|
||||
|
||||
|
||||
std::vector<double> readDoubleArr( const std::string &name, size_t dim ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
std::vector<double> arr_val( dim );
|
||||
if ( nc_get_var_double( mNcid, arr_id, arr_val.data() ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return arr_val;
|
||||
}
|
||||
|
||||
|
||||
int getAttrInt( const std::string &name, const std::string &attr_name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) != NC_NOERR )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
int val;
|
||||
if ( nc_get_att_int( mNcid, arr_id, attr_name.c_str(), &val ) )
|
||||
{
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
std::string getAttrStr( const std::string &name, const std::string &attr_name ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
int arr_id;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &arr_id ) ) throw MDAL_Status::Err_UnknownFormat;
|
||||
return getAttrStr( attr_name, arr_id );
|
||||
}
|
||||
|
||||
std::string getAttrStr( const std::string &name, int varid ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
size_t attlen = 0;
|
||||
|
||||
if ( nc_inq_attlen( mNcid, varid, name.c_str(), &attlen ) )
|
||||
{
|
||||
// attribute is missing
|
||||
return std::string();
|
||||
}
|
||||
|
||||
char *string_attr;
|
||||
string_attr = ( char * ) malloc( attlen + 1 );
|
||||
|
||||
if ( nc_get_att_text( mNcid, varid, name.c_str(), string_attr ) ) throw MDAL_Status::Err_UnknownFormat;
|
||||
string_attr[attlen] = '\0';
|
||||
|
||||
std::string res( string_attr );
|
||||
free( string_attr );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
double getFillValue( int varid ) const
|
||||
{
|
||||
double fill;
|
||||
if ( nc_get_att_double( mNcid, varid, "_FillValue", &fill ) )
|
||||
fill = std::numeric_limits<double>::quiet_NaN(); // not present/set
|
||||
return fill;
|
||||
}
|
||||
|
||||
int getVarId( const std::string &name )
|
||||
{
|
||||
int ncid_val;
|
||||
if ( nc_inq_varid( mNcid, name.c_str(), &ncid_val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
return ncid_val;
|
||||
}
|
||||
|
||||
void getDimension( const std::string &name, size_t *val, int *ncid_val ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
if ( nc_inq_dimid( mNcid, name.c_str(), ncid_val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
if ( nc_inq_dimlen( mNcid, *ncid_val, val ) != NC_NOERR ) throw MDAL_Status::Err_UnknownFormat;
|
||||
}
|
||||
|
||||
void getDimensionOptional( const std::string &name, size_t *val, int *ncid_val ) const
|
||||
{
|
||||
assert( mNcid != 0 );
|
||||
|
||||
try
|
||||
{
|
||||
getDimension( name, val, ncid_val );
|
||||
}
|
||||
catch ( MDAL_Status )
|
||||
{
|
||||
*ncid_val = -1;
|
||||
*val = 0;
|
||||
}
|
||||
}
|
||||
int getAttrInt( const std::string &name, const std::string &attr_name ) const;
|
||||
double getAttrDouble( int varid, const std::string &attr_name ) const;
|
||||
std::string getAttrStr( const std::string &name, const std::string &attr_name ) const;
|
||||
std::string getAttrStr( const std::string &name, int varid ) const;
|
||||
double getFillValue( int varid ) const;
|
||||
int getVarId( const std::string &name );
|
||||
void getDimension( const std::string &name, size_t *val, int *ncid_val ) const;
|
||||
void getDimensionOptional( const std::string &name, size_t *val, int *ncid_val ) const;
|
||||
private:
|
||||
int mNcid;
|
||||
|
||||
int mNcid; // C handle to the file
|
||||
};
|
||||
|
||||
#endif // MDAL_NETCDF_HPP
|
||||
|
766
external/mdal/frmts/mdal_sww.cpp
vendored
766
external/mdal/frmts/mdal_sww.cpp
vendored
@ -7,20 +7,17 @@
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <netcdf.h>
|
||||
#include <set>
|
||||
|
||||
#include "mdal_netcdf.hpp"
|
||||
#include "mdal_sww.hpp"
|
||||
|
||||
// threshold for determining whether an element is active (wet)
|
||||
// the format does not explicitly store that information so we
|
||||
// determine that when loading data
|
||||
#define DEPTH_THRESHOLD 0.0001 // in meters
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
MDAL::DriverSWW::DriverSWW()
|
||||
: Driver( "SWW",
|
||||
"AnuGA",
|
||||
"*.sww",
|
||||
DriverType::CanReadMeshAndDatasets )
|
||||
Capability::ReadMesh )
|
||||
{
|
||||
}
|
||||
|
||||
@ -29,345 +26,442 @@ MDAL::DriverSWW *MDAL::DriverSWW::create()
|
||||
return new DriverSWW();
|
||||
}
|
||||
|
||||
bool MDAL::DriverSWW::canRead( const std::string &uri )
|
||||
size_t MDAL::DriverSWW::getVertexCount( const NetCDFFile &ncFile ) const
|
||||
{
|
||||
int ncid;
|
||||
int res;
|
||||
|
||||
// open
|
||||
res = nc_open( uri.c_str(), NC_NOWRITE, &ncid );
|
||||
if ( res != NC_NOERR )
|
||||
{
|
||||
MDAL::debug( nc_strerror( res ) );
|
||||
nc_close( ncid );
|
||||
return false;
|
||||
}
|
||||
|
||||
// get dimensions
|
||||
int nVolumesId, nVerticesId, nPointsId, nTimestepsId;
|
||||
if ( nc_inq_dimid( ncid, "number_of_volumes", &nVolumesId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_vertices", &nVerticesId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_points", &nPointsId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_timesteps", &nTimestepsId ) != NC_NOERR )
|
||||
{
|
||||
nc_close( ncid );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
int nPointsId;
|
||||
size_t res;
|
||||
ncFile.getDimension( "number_of_points", &res, &nPointsId );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<MDAL::Mesh> MDAL::DriverSWW::load( const std::string &resultsFile,
|
||||
MDAL_Status *status )
|
||||
bool MDAL::DriverSWW::canRead( const std::string &uri )
|
||||
{
|
||||
NetCDFFile ncFile;
|
||||
|
||||
try
|
||||
{
|
||||
ncFile.openFile( uri );
|
||||
getVertexCount( ncFile );
|
||||
}
|
||||
catch ( MDAL_Status )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<double> MDAL::DriverSWW::readZCoords( const NetCDFFile &ncFile ) const
|
||||
{
|
||||
size_t nPoints = getVertexCount( ncFile );
|
||||
|
||||
std::vector<double> pz;
|
||||
// newer sww files does have elevation array that is time-dependent
|
||||
if ( ncFile.hasArr( "z" ) )
|
||||
{
|
||||
pz = ncFile.readDoubleArr( "z", nPoints );
|
||||
}
|
||||
else if ( ncFile.hasArr( "elevation" ) )
|
||||
{
|
||||
int zDims = 0;
|
||||
int zid;
|
||||
if ( nc_inq_varid( ncFile.handle(), "elevation", &zid ) == NC_NOERR &&
|
||||
nc_inq_varndims( ncFile.handle(), zid, &zDims ) == NC_NOERR )
|
||||
{
|
||||
if ( zDims == 1 )
|
||||
{
|
||||
// just one elevation for all times, treat as z coord
|
||||
pz = ncFile.readDoubleArr( "elevation", nPoints );
|
||||
}
|
||||
else
|
||||
{
|
||||
pz.resize( nPoints );
|
||||
// fetching "elevation" data for the first timestep,
|
||||
// and threat it as z coord
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = 0; // t = 0
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
nc_get_vars_double( ncFile.handle(), zid, start, count, stride, pz.data() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pz;
|
||||
}
|
||||
|
||||
void MDAL::DriverSWW::addBedElevation( const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×
|
||||
) const
|
||||
{
|
||||
if ( ncFile.hasArr( "elevation" ) )
|
||||
{
|
||||
std::shared_ptr<MDAL::DatasetGroup> grp = readScalarGroup( ncFile,
|
||||
mesh,
|
||||
times,
|
||||
"Bed Elevation",
|
||||
"elevation" );
|
||||
mesh->datasetGroups.push_back( grp );
|
||||
}
|
||||
else
|
||||
{
|
||||
MDAL::addBedElevationDatasetGroup( mesh, mesh->vertices );
|
||||
}
|
||||
}
|
||||
|
||||
MDAL::Vertices MDAL::DriverSWW::readVertices( const NetCDFFile &ncFile ) const
|
||||
{
|
||||
size_t nPoints = getVertexCount( ncFile );
|
||||
|
||||
// load mesh data
|
||||
std::vector<double> px = ncFile.readDoubleArr( "x", nPoints );
|
||||
std::vector<double> py = ncFile.readDoubleArr( "y", nPoints );
|
||||
std::vector<double> pz = readZCoords( ncFile );
|
||||
|
||||
// we may need to apply a shift to the X,Y coordinates
|
||||
double xLLcorner = ncFile.getAttrDouble( NC_GLOBAL, "xllcorner" );
|
||||
double yLLcorner = ncFile.getAttrDouble( NC_GLOBAL, "yllcorner" );
|
||||
|
||||
MDAL::Vertices vertices( nPoints );
|
||||
Vertex *vertexPtr = vertices.data();
|
||||
for ( size_t i = 0; i < nPoints; ++i, ++vertexPtr )
|
||||
{
|
||||
vertexPtr->x = px[i] + xLLcorner ;
|
||||
vertexPtr->y = py[i] + yLLcorner ;
|
||||
if ( !pz.empty() ) // missing both "z" and "elevation"
|
||||
vertexPtr->z = pz[i];
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
MDAL::Faces MDAL::DriverSWW::readFaces( const NetCDFFile &ncFile ) const
|
||||
{
|
||||
// get dimensions
|
||||
int nVolumesId, nVerticesId;
|
||||
size_t nVolumes, nVertices;
|
||||
ncFile.getDimension( "number_of_volumes", &nVolumes, &nVolumesId );
|
||||
ncFile.getDimension( "number_of_vertices", &nVertices, &nVerticesId );
|
||||
if ( nVertices != 3 )
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
|
||||
std::vector<int> pvolumes = ncFile.readIntArr( "volumes", nVertices * nVolumes );
|
||||
|
||||
MDAL::Faces faces( nVolumes );
|
||||
for ( size_t i = 0; i < nVolumes; ++i )
|
||||
{
|
||||
faces[i].resize( 3 );
|
||||
faces[i][0] = static_cast<size_t>( pvolumes[3 * i + 0] );
|
||||
faces[i][1] = static_cast<size_t>( pvolumes[3 * i + 1] );
|
||||
faces[i][2] = static_cast<size_t>( pvolumes[3 * i + 2] );
|
||||
}
|
||||
return faces;
|
||||
}
|
||||
|
||||
std::vector<double> MDAL::DriverSWW::readTimes( const NetCDFFile &ncFile ) const
|
||||
{
|
||||
size_t nTimesteps;
|
||||
int nTimestepsId;
|
||||
ncFile.getDimension( "number_of_timesteps", &nTimesteps, &nTimestepsId );
|
||||
std::vector<double> times = ncFile.readDoubleArr( "time", nTimesteps );
|
||||
return times;
|
||||
}
|
||||
|
||||
void MDAL::DriverSWW::readDatasetGroups(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×
|
||||
) const
|
||||
{
|
||||
std::set<std::string> parsedVariableNames; // already parsed arrays somewhere else
|
||||
parsedVariableNames.insert( "x" );
|
||||
parsedVariableNames.insert( "y" );
|
||||
parsedVariableNames.insert( "z" );
|
||||
parsedVariableNames.insert( "volumes" );
|
||||
parsedVariableNames.insert( "time" );
|
||||
|
||||
std::vector<std::string> names = ncFile.readArrNames();
|
||||
std::set<std::string> namesSet( names.begin(), names.end() );
|
||||
|
||||
// Add bed elevation group
|
||||
parsedVariableNames.insert( "elevations" );
|
||||
addBedElevation( ncFile, mesh, times );
|
||||
|
||||
for ( const std::string &name : names )
|
||||
{
|
||||
// skip already parsed variables
|
||||
if ( parsedVariableNames.find( name ) == parsedVariableNames.cend() )
|
||||
{
|
||||
std::string xName, yName, groupName( name );
|
||||
bool isVector = parseGroupName( groupName, xName, yName );
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> grp;
|
||||
if ( isVector && ncFile.hasArr( xName ) && ncFile.hasArr( yName ) )
|
||||
{
|
||||
// vector dataset group
|
||||
grp = readVectorGroup(
|
||||
ncFile,
|
||||
mesh,
|
||||
times,
|
||||
groupName,
|
||||
xName,
|
||||
yName );
|
||||
parsedVariableNames.insert( xName );
|
||||
parsedVariableNames.insert( yName );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// scalar dataset group
|
||||
grp = readScalarGroup(
|
||||
ncFile,
|
||||
mesh,
|
||||
times,
|
||||
groupName,
|
||||
name );
|
||||
parsedVariableNames.insert( name );
|
||||
}
|
||||
if ( grp )
|
||||
mesh->datasetGroups.push_back( grp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MDAL::DriverSWW::parseGroupName( std::string &groupName,
|
||||
std::string &xName,
|
||||
std::string &yName ) const
|
||||
{
|
||||
bool isVector = false;
|
||||
std::string baseName( groupName );
|
||||
|
||||
// X and Y variables
|
||||
if ( groupName.size() > 1 )
|
||||
{
|
||||
if ( MDAL::startsWith( groupName, "x" ) )
|
||||
{
|
||||
baseName = groupName.substr( 1, groupName.size() - 1 );
|
||||
xName = groupName;
|
||||
yName = "y" + baseName;
|
||||
isVector = true;
|
||||
}
|
||||
else if ( MDAL::startsWith( groupName, "y" ) )
|
||||
{
|
||||
baseName = groupName.substr( 1, groupName.size() - 1 );
|
||||
xName = "x" + baseName;
|
||||
yName = groupName;
|
||||
isVector = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Maximums
|
||||
groupName = baseName;
|
||||
if ( MDAL::endsWith( baseName, "_range" ) )
|
||||
{
|
||||
groupName = groupName.substr( 0, baseName.size() - 6 ) + "/Maximums";
|
||||
}
|
||||
|
||||
return isVector;
|
||||
}
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverSWW::readScalarGroup(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×,
|
||||
const std::string groupName,
|
||||
const std::string arrName
|
||||
) const
|
||||
{
|
||||
size_t nPoints = getVertexCount( ncFile );
|
||||
std::shared_ptr<MDAL::DatasetGroup> mds;
|
||||
|
||||
int varxid;
|
||||
if ( nc_inq_varid( ncFile.handle(), arrName.c_str(), &varxid ) == NC_NOERR )
|
||||
{
|
||||
mds = std::make_shared<MDAL::DatasetGroup> (
|
||||
name(),
|
||||
mesh,
|
||||
mFileName,
|
||||
groupName );
|
||||
mds->setIsOnVertices( true );
|
||||
mds->setIsScalar( true );
|
||||
|
||||
int zDimsX = 0;
|
||||
if ( nc_inq_varndims( ncFile.handle(), varxid, &zDimsX ) != NC_NOERR )
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
|
||||
if ( zDimsX == 1 )
|
||||
{
|
||||
// TIME INDEPENDENT
|
||||
std::shared_ptr<MDAL::MemoryDataset> o = std::make_shared<MDAL::MemoryDataset>( mds.get() );
|
||||
o->setTime( 0.0 );
|
||||
double *values = o->values();
|
||||
std::vector<double> valuesX = ncFile.readDoubleArr( arrName, nPoints );
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
values[i] = valuesX[i];
|
||||
}
|
||||
o->setStatistics( MDAL::calculateStatistics( o ) );
|
||||
mds->datasets.push_back( o );
|
||||
}
|
||||
else
|
||||
{
|
||||
// TIME DEPENDENT
|
||||
for ( size_t t = 0; t < times.size(); ++t )
|
||||
{
|
||||
std::shared_ptr<MDAL::MemoryDataset> mto = std::make_shared<MDAL::MemoryDataset>( mds.get() );
|
||||
mto->setTime( static_cast<double>( times[t] ) / 3600. );
|
||||
double *values = mto->values();
|
||||
|
||||
// fetching data for one timestep
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = t;
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
nc_get_vars_double( ncFile.handle(), varxid, start, count, stride, values );
|
||||
mto->setStatistics( MDAL::calculateStatistics( mto ) );
|
||||
mds->datasets.push_back( mto );
|
||||
}
|
||||
}
|
||||
mds->setStatistics( MDAL::calculateStatistics( mds ) );
|
||||
}
|
||||
|
||||
return mds;
|
||||
}
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverSWW::readVectorGroup(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×,
|
||||
const std::string groupName,
|
||||
const std::string arrXName,
|
||||
const std::string arrYName
|
||||
) const
|
||||
{
|
||||
size_t nPoints = getVertexCount( ncFile );
|
||||
std::shared_ptr<MDAL::DatasetGroup> mds;
|
||||
|
||||
int varxid, varyid;
|
||||
if ( nc_inq_varid( ncFile.handle(), arrXName.c_str(), &varxid ) == NC_NOERR &&
|
||||
nc_inq_varid( ncFile.handle(), arrYName.c_str(), &varyid ) == NC_NOERR )
|
||||
{
|
||||
mds = std::make_shared<MDAL::DatasetGroup> (
|
||||
name(),
|
||||
mesh,
|
||||
mFileName,
|
||||
groupName );
|
||||
mds->setIsOnVertices( true );
|
||||
mds->setIsScalar( false );
|
||||
|
||||
int zDimsX = 0;
|
||||
int zDimsY = 0;
|
||||
if ( nc_inq_varndims( ncFile.handle(), varxid, &zDimsX ) != NC_NOERR )
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
|
||||
if ( nc_inq_varndims( ncFile.handle(), varyid, &zDimsY ) != NC_NOERR )
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
|
||||
if ( zDimsX != zDimsY )
|
||||
throw MDAL_Status::Err_UnknownFormat;
|
||||
|
||||
std::vector<double> valuesX( nPoints ), valuesY( nPoints );
|
||||
|
||||
if ( zDimsX == 1 )
|
||||
{
|
||||
// TIME INDEPENDENT
|
||||
std::shared_ptr<MDAL::MemoryDataset> o = std::make_shared<MDAL::MemoryDataset>( mds.get() );
|
||||
o->setTime( 0.0 );
|
||||
double *values = o->values();
|
||||
std::vector<double> valuesX = ncFile.readDoubleArr( arrXName, nPoints );
|
||||
std::vector<double> valuesY = ncFile.readDoubleArr( arrYName, nPoints );
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
values[2 * i] = valuesX[i];
|
||||
values[2 * i + 1] = valuesY[i];
|
||||
}
|
||||
o->setStatistics( MDAL::calculateStatistics( o ) );
|
||||
mds->datasets.push_back( o );
|
||||
}
|
||||
else
|
||||
{
|
||||
// TIME DEPENDENT
|
||||
for ( size_t t = 0; t < times.size(); ++t )
|
||||
{
|
||||
std::shared_ptr<MDAL::MemoryDataset> mto = std::make_shared<MDAL::MemoryDataset>( mds.get() );
|
||||
mto->setTime( static_cast<double>( times[t] ) / 3600. );
|
||||
double *values = mto->values();
|
||||
|
||||
// fetching data for one timestep
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = t;
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
nc_get_vars_double( ncFile.handle(), varxid, start, count, stride, valuesX.data() );
|
||||
nc_get_vars_double( ncFile.handle(), varyid, start, count, stride, valuesY.data() );
|
||||
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
values[2 * i] = static_cast<double>( valuesX[i] );
|
||||
values[2 * i + 1] = static_cast<double>( valuesY[i] );
|
||||
}
|
||||
|
||||
mto->setStatistics( MDAL::calculateStatistics( mto ) );
|
||||
mds->datasets.push_back( mto );
|
||||
}
|
||||
}
|
||||
mds->setStatistics( MDAL::calculateStatistics( mds ) );
|
||||
}
|
||||
|
||||
return mds;
|
||||
}
|
||||
|
||||
std::unique_ptr<MDAL::Mesh> MDAL::DriverSWW::load(
|
||||
const std::string &resultsFile,
|
||||
MDAL_Status *status )
|
||||
{
|
||||
mFileName = resultsFile;
|
||||
if ( status ) *status = MDAL_Status::None;
|
||||
|
||||
int ncid;
|
||||
int res;
|
||||
NetCDFFile ncFile;
|
||||
|
||||
res = nc_open( mFileName.c_str(), NC_NOWRITE, &ncid );
|
||||
if ( res != NC_NOERR )
|
||||
try
|
||||
{
|
||||
MDAL::debug( nc_strerror( res ) );
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
// Open file for reading
|
||||
ncFile.openFile( mFileName );
|
||||
|
||||
// Read mesh
|
||||
MDAL::Vertices vertices = readVertices( ncFile );
|
||||
MDAL::Faces faces = readFaces( ncFile );
|
||||
std::unique_ptr< MDAL::MemoryMesh > mesh(
|
||||
new MemoryMesh(
|
||||
name(),
|
||||
vertices.size(),
|
||||
faces.size(),
|
||||
3, // triangles
|
||||
computeExtent( vertices ),
|
||||
mFileName
|
||||
)
|
||||
);
|
||||
mesh->faces = faces;
|
||||
mesh->vertices = vertices;
|
||||
|
||||
// Read times
|
||||
std::vector<double> times = readTimes( ncFile );
|
||||
|
||||
// Create a dataset(s)
|
||||
readDatasetGroups( ncFile, mesh.get(), times );
|
||||
|
||||
// Success!
|
||||
return std::unique_ptr<Mesh>( mesh.release() );
|
||||
}
|
||||
catch ( MDAL_Status err )
|
||||
{
|
||||
if ( status ) *status = err;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
// get dimensions
|
||||
int nVolumesId, nVerticesId, nPointsId, nTimestepsId;
|
||||
size_t nVolumes, nVertices, nPoints, nTimesteps;
|
||||
if ( nc_inq_dimid( ncid, "number_of_volumes", &nVolumesId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_vertices", &nVerticesId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_points", &nPointsId ) != NC_NOERR ||
|
||||
nc_inq_dimid( ncid, "number_of_timesteps", &nTimestepsId ) != NC_NOERR )
|
||||
{
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
if ( nc_inq_dimlen( ncid, nVolumesId, &nVolumes ) != NC_NOERR ||
|
||||
nc_inq_dimlen( ncid, nVerticesId, &nVertices ) != NC_NOERR ||
|
||||
nc_inq_dimlen( ncid, nPointsId, &nPoints ) != NC_NOERR ||
|
||||
nc_inq_dimlen( ncid, nTimestepsId, &nTimesteps ) != NC_NOERR )
|
||||
{
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
if ( nVertices != 3 )
|
||||
{
|
||||
MDAL::debug( "Expecting triangular elements!" );
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
int xid, yid, zid, volumesid, timeid, stageid;
|
||||
if ( nc_inq_varid( ncid, "x", &xid ) != NC_NOERR ||
|
||||
nc_inq_varid( ncid, "y", &yid ) != NC_NOERR ||
|
||||
nc_inq_varid( ncid, "volumes", &volumesid ) != NC_NOERR ||
|
||||
nc_inq_varid( ncid, "time", &timeid ) != NC_NOERR ||
|
||||
nc_inq_varid( ncid, "stage", &stageid ) != NC_NOERR )
|
||||
{
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
// load mesh data
|
||||
std::vector<float> px( nPoints ), py( nPoints ), pz( nPoints );
|
||||
std::vector<int> pvolumes( nVertices * nVolumes );
|
||||
if ( nc_get_var_float( ncid, xid, px.data() ) != NC_NOERR ||
|
||||
nc_get_var_float( ncid, yid, py.data() ) != NC_NOERR ||
|
||||
nc_get_var_int( ncid, volumesid, pvolumes.data() ) != NC_NOERR )
|
||||
{
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
// we may need to apply a shift to the X,Y coordinates
|
||||
float xLLcorner = 0, yLLcorner = 0;
|
||||
nc_get_att_float( ncid, NC_GLOBAL, "xllcorner", &xLLcorner );
|
||||
nc_get_att_float( ncid, NC_GLOBAL, "yllcorner", &yLLcorner );
|
||||
|
||||
MDAL::Vertices nodes( nPoints );
|
||||
Vertex *nodesPtr = nodes.data();
|
||||
for ( size_t i = 0; i < nPoints; ++i, ++nodesPtr )
|
||||
{
|
||||
nodesPtr->x = static_cast<double>( px[i] + xLLcorner );
|
||||
nodesPtr->y = static_cast<double>( py[i] + yLLcorner );
|
||||
}
|
||||
|
||||
std::vector<float> times( nTimesteps );
|
||||
nc_get_var_float( ncid, timeid, times.data() );
|
||||
|
||||
int zDims = 0;
|
||||
if ( nc_inq_varid( ncid, "z", &zid ) == NC_NOERR &&
|
||||
nc_get_var_float( ncid, zid, pz.data() ) == NC_NOERR )
|
||||
{
|
||||
// older SWW format: elevation is constant over time
|
||||
|
||||
zDims = 1;
|
||||
}
|
||||
else if ( nc_inq_varid( ncid, "elevation", &zid ) == NC_NOERR &&
|
||||
nc_inq_varndims( ncid, zid, &zDims ) == NC_NOERR &&
|
||||
( ( zDims == 1 && nc_get_var_float( ncid, zid, pz.data() ) == NC_NOERR ) || zDims == 2 ) )
|
||||
{
|
||||
// we're good
|
||||
}
|
||||
else
|
||||
{
|
||||
// neither "z" nor "elevation" are present -> something is going wrong
|
||||
nc_close( ncid );
|
||||
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
|
||||
return std::unique_ptr< MDAL::Mesh >();
|
||||
}
|
||||
|
||||
MDAL::Faces elements( nVolumes );
|
||||
for ( size_t i = 0; i < nVolumes; ++i )
|
||||
{
|
||||
elements[i].resize( 3 );
|
||||
elements[i][0] = static_cast<size_t>( pvolumes[3 * i + 0] );
|
||||
elements[i][1] = static_cast<size_t>( pvolumes[3 * i + 1] );
|
||||
elements[i][2] = static_cast<size_t>( pvolumes[3 * i + 2] );
|
||||
}
|
||||
std::unique_ptr< MDAL::MemoryMesh > mesh(
|
||||
new MemoryMesh(
|
||||
nodes.size(),
|
||||
elements.size(),
|
||||
3, // triangles
|
||||
computeExtent( nodes ),
|
||||
mFileName
|
||||
)
|
||||
);
|
||||
mesh->faces = elements;
|
||||
mesh->vertices = nodes;
|
||||
|
||||
// Create a dataset for the bed elevation
|
||||
std::shared_ptr<MDAL::DatasetGroup> bedDs = std::make_shared<MDAL::DatasetGroup> (
|
||||
mesh.get(),
|
||||
mFileName,
|
||||
"Bed Elevation" );
|
||||
bedDs->setIsOnVertices( true );
|
||||
bedDs->setIsScalar( true );
|
||||
|
||||
// read bed elevations
|
||||
std::vector<std::shared_ptr<MDAL::MemoryDataset>> elevationOutputs;
|
||||
if ( zDims == 1 )
|
||||
{
|
||||
// either "z" or "elevation" with 1 dimension
|
||||
std::shared_ptr<MDAL::MemoryDataset> o = std::make_shared<MDAL::MemoryDataset>( bedDs.get() );
|
||||
o->setTime( 0.0 );
|
||||
double *values = o->values();
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
double z = static_cast<double>( pz[i] );
|
||||
values[i] = z;
|
||||
mesh->vertices[i].z = z;
|
||||
}
|
||||
o->setStatistics( MDAL::calculateStatistics( o ) );
|
||||
bedDs->datasets.push_back( o );
|
||||
elevationOutputs.push_back( o );
|
||||
}
|
||||
else if ( zDims == 2 )
|
||||
{
|
||||
// newer SWW format: elevation may change over time
|
||||
for ( size_t t = 0; t < nTimesteps; ++t )
|
||||
{
|
||||
std::shared_ptr<MDAL::MemoryDataset> toe = std::make_shared<MDAL::MemoryDataset>( bedDs.get() );
|
||||
toe->setTime( static_cast<double>( times[t] ) / 3600. );
|
||||
double *elev = toe->values();
|
||||
|
||||
// fetching "elevation" data for one timestep
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = t;
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
std::vector<float> buffer( nPoints );
|
||||
nc_get_vars_float( ncid, zid, start, count, stride, buffer.data() );
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
double val = static_cast<double>( buffer[i] );
|
||||
elev[i] = val;
|
||||
}
|
||||
|
||||
toe->setStatistics( MDAL::calculateStatistics( toe ) );
|
||||
bedDs->datasets.push_back( toe );
|
||||
elevationOutputs.push_back( toe );
|
||||
}
|
||||
}
|
||||
|
||||
bedDs->setStatistics( MDAL::calculateStatistics( bedDs ) );
|
||||
mesh->datasetGroups.push_back( bedDs );
|
||||
|
||||
// load results
|
||||
std::shared_ptr<MDAL::DatasetGroup> dss = std::make_shared<MDAL::DatasetGroup> (
|
||||
mesh.get(),
|
||||
mFileName,
|
||||
"Stage" );
|
||||
dss->setIsOnVertices( true );
|
||||
dss->setIsScalar( true );
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> dsd = std::make_shared<MDAL::DatasetGroup> (
|
||||
mesh.get(),
|
||||
mFileName,
|
||||
"Depth" );
|
||||
dsd->setIsOnVertices( true );
|
||||
dsd->setIsScalar( true );
|
||||
|
||||
for ( size_t t = 0; t < nTimesteps; ++t )
|
||||
{
|
||||
const std::shared_ptr<MDAL::MemoryDataset> elevO = elevationOutputs.size() > 1 ? elevationOutputs[t] : elevationOutputs[0];
|
||||
const double *elev = elevO->constValues();
|
||||
|
||||
std::shared_ptr<MDAL::MemoryDataset> tos = std::make_shared<MDAL::MemoryDataset>( dss.get() );
|
||||
tos->setTime( static_cast<double>( times[t] ) / 3600. );
|
||||
double *values = tos->values();
|
||||
|
||||
// fetching "stage" data for one timestep
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = t;
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
std::vector<float> buffer( nPoints );
|
||||
nc_get_vars_float( ncid, stageid, start, count, stride, buffer.data() );
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
double val = static_cast<double>( buffer[i] );
|
||||
values[i] = val;
|
||||
}
|
||||
|
||||
// derived data: depth = stage - elevation
|
||||
std::shared_ptr<MDAL::MemoryDataset> tod = std::make_shared<MDAL::MemoryDataset>( dsd.get() );
|
||||
tod->setTime( tos->time() );
|
||||
double *depths = tod->values();
|
||||
int *activeTos = tos->active();
|
||||
int *activeTod = tod->active();
|
||||
|
||||
for ( size_t j = 0; j < nPoints; ++j )
|
||||
depths[j] = values[j] - elev[j];
|
||||
|
||||
// determine which elements are active (wet)
|
||||
for ( size_t elemidx = 0; elemidx < nVolumes; ++elemidx )
|
||||
{
|
||||
const Face &elem = mesh->faces[elemidx];
|
||||
double v0 = depths[elem[0]];
|
||||
double v1 = depths[elem[1]];
|
||||
double v2 = depths[elem[2]];
|
||||
activeTos[elemidx] = v0 > DEPTH_THRESHOLD && v1 > DEPTH_THRESHOLD && v2 > DEPTH_THRESHOLD;
|
||||
activeTod[elemidx] = activeTos[elemidx];
|
||||
}
|
||||
|
||||
tos->setStatistics( MDAL::calculateStatistics( tos ) );
|
||||
dss->datasets.push_back( tos );
|
||||
|
||||
tod->setStatistics( MDAL::calculateStatistics( tod ) );
|
||||
dsd->datasets.push_back( tod );
|
||||
}
|
||||
|
||||
dss->setStatistics( MDAL::calculateStatistics( dss ) );
|
||||
mesh->datasetGroups.push_back( dss );
|
||||
|
||||
dsd->setStatistics( MDAL::calculateStatistics( dsd ) );
|
||||
mesh->datasetGroups.push_back( dsd );
|
||||
|
||||
|
||||
int momentumxid, momentumyid;
|
||||
if ( nc_inq_varid( ncid, "xmomentum", &momentumxid ) == NC_NOERR &&
|
||||
nc_inq_varid( ncid, "ymomentum", &momentumyid ) == NC_NOERR )
|
||||
{
|
||||
std::shared_ptr<MDAL::DatasetGroup> mds = std::make_shared<MDAL::DatasetGroup> (
|
||||
mesh.get(),
|
||||
mFileName,
|
||||
"Momentum" );
|
||||
mds->setIsOnVertices( true );
|
||||
mds->setIsScalar( false );
|
||||
|
||||
std::vector<float> valuesX( nPoints ), valuesY( nPoints );
|
||||
for ( size_t t = 0; t < nTimesteps; ++t )
|
||||
{
|
||||
std::shared_ptr<MDAL::MemoryDataset> mto = std::make_shared<MDAL::MemoryDataset>( mds.get() );
|
||||
mto->setTime( static_cast<double>( times[t] ) / 3600. );
|
||||
double *values = mto->values();
|
||||
|
||||
std::shared_ptr<MDAL::MemoryDataset> mto0 = std::static_pointer_cast<MDAL::MemoryDataset>( dsd->datasets[t] );
|
||||
memcpy( mto->active(), mto0->active(), mesh->facesCount() * sizeof( int ) );
|
||||
|
||||
// fetching "stage" data for one timestep
|
||||
size_t start[2], count[2];
|
||||
const ptrdiff_t stride[2] = {1, 1};
|
||||
start[0] = t;
|
||||
start[1] = 0;
|
||||
count[0] = 1;
|
||||
count[1] = nPoints;
|
||||
nc_get_vars_float( ncid, momentumxid, start, count, stride, valuesX.data() );
|
||||
nc_get_vars_float( ncid, momentumyid, start, count, stride, valuesY.data() );
|
||||
|
||||
for ( size_t i = 0; i < nPoints; ++i )
|
||||
{
|
||||
values[2 * i] = static_cast<double>( valuesX[i] );
|
||||
values[2 * i + 1] = static_cast<double>( valuesY[i] );
|
||||
}
|
||||
|
||||
mto->setStatistics( MDAL::calculateStatistics( mto ) );
|
||||
mds->datasets.push_back( mto );
|
||||
}
|
||||
|
||||
|
||||
mds->setStatistics( MDAL::calculateStatistics( mds ) );
|
||||
mesh->datasetGroups.push_back( mds );
|
||||
}
|
||||
|
||||
nc_close( ncid );
|
||||
|
||||
return std::unique_ptr<Mesh>( mesh.release() );
|
||||
}
|
||||
|
55
external/mdal/frmts/mdal_sww.hpp
vendored
55
external/mdal/frmts/mdal_sww.hpp
vendored
@ -7,15 +7,32 @@
|
||||
#define MDAL_SWW_HPP
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include "mdal_data_model.hpp"
|
||||
#include "mdal_memory_data_model.hpp"
|
||||
#include "mdal.h"
|
||||
#include "mdal_driver.hpp"
|
||||
#include "mdal_netcdf.hpp"
|
||||
|
||||
namespace MDAL
|
||||
{
|
||||
// AnuGA format with extension .SWW
|
||||
/**
|
||||
* AnuGA format with extension .SWW
|
||||
*
|
||||
* The format is based on NetCDF storage
|
||||
*
|
||||
* Bed Elevation can be static (== one bed elevation for all timesteps, stored
|
||||
* in "z" variable or "elevation" variable)
|
||||
* or dynamic (each timestep has its own elevation data, stored in "elevation"
|
||||
* variable with multiple dimensions)
|
||||
*
|
||||
* Vector data are recognized by prefix "x" and "y" in the name
|
||||
* Maximums data are recognized by suffix "_range" in the name
|
||||
*/
|
||||
class DriverSWW: public Driver
|
||||
{
|
||||
public:
|
||||
@ -25,7 +42,43 @@ namespace MDAL
|
||||
|
||||
std::unique_ptr< Mesh > load( const std::string &resultsFile, MDAL_Status *status ) override;
|
||||
bool canRead( const std::string &uri ) override;
|
||||
|
||||
private:
|
||||
size_t getVertexCount( const NetCDFFile &ncFile ) const;
|
||||
std::vector<double> readZCoords( const NetCDFFile &ncFile ) const;
|
||||
MDAL::Vertices readVertices( const NetCDFFile &ncFile ) const;
|
||||
MDAL::Faces readFaces( const NetCDFFile &ncFile ) const;
|
||||
std::vector<double> readTimes( const NetCDFFile &ncFile ) const;
|
||||
/**
|
||||
* Finds all variables (arrays) in netcdf file and base on the name add it as
|
||||
* vector or scalar dataset group
|
||||
*/
|
||||
void readDatasetGroups( const NetCDFFile &ncFile, MDAL::MemoryMesh *mesh, const std::vector<double> × ) const;
|
||||
bool parseGroupName( std::string &groupName, std::string &xName, std::string &yName ) const;
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> readScalarGroup(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×,
|
||||
const std::string variableBaseName,
|
||||
const std::string arrName
|
||||
) const;
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> readVectorGroup(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×,
|
||||
const std::string variableBaseName,
|
||||
const std::string arrXName,
|
||||
const std::string arrYName
|
||||
) const;
|
||||
|
||||
void addBedElevation(
|
||||
const NetCDFFile &ncFile,
|
||||
MDAL::MemoryMesh *mesh,
|
||||
const std::vector<double> ×
|
||||
) const;
|
||||
|
||||
std::string mFileName;
|
||||
};
|
||||
} // namespace MDAL
|
||||
|
71
external/mdal/frmts/mdal_xmdf.cpp
vendored
71
external/mdal/frmts/mdal_xmdf.cpp
vendored
@ -89,7 +89,7 @@ MDAL::DriverXmdf::DriverXmdf()
|
||||
: Driver( "XMDF",
|
||||
"TUFLOW XMDF",
|
||||
"*.xmdf",
|
||||
DriverType::CanReadOnlyDatasets )
|
||||
Capability::ReadDatasets )
|
||||
{
|
||||
}
|
||||
|
||||
@ -139,6 +139,7 @@ void MDAL::DriverXmdf::load( const std::string &datFile, MDAL::Mesh *mesh, MDAL
|
||||
|
||||
size_t vertexCount = mesh->verticesCount();
|
||||
size_t faceCount = mesh->facesCount();
|
||||
|
||||
std::vector<std::string> rootGroups = file.groups();
|
||||
if ( rootGroups.size() != 1 )
|
||||
{
|
||||
@ -147,44 +148,21 @@ void MDAL::DriverXmdf::load( const std::string &datFile, MDAL::Mesh *mesh, MDAL
|
||||
return;
|
||||
}
|
||||
HdfGroup gMesh = file.group( rootGroups[0] );
|
||||
|
||||
// TODO: read Times group (e.g. time of peak velocity)
|
||||
|
||||
DatasetGroups groups; // DAT outputs data
|
||||
|
||||
if ( gMesh.pathExists( "Temporal" ) )
|
||||
for ( const std::string &groupName : gMesh.groups() )
|
||||
{
|
||||
HdfGroup gTemporal = gMesh.group( "Temporal" );
|
||||
if ( gTemporal.isValid() )
|
||||
HdfGroup gGroup = gMesh.group( groupName );
|
||||
if ( gGroup.isValid() )
|
||||
{
|
||||
addDatasetGroupsFromXmdfGroup( groups, gTemporal, vertexCount, faceCount );
|
||||
}
|
||||
}
|
||||
|
||||
if ( gMesh.pathExists( "Temporal" ) )
|
||||
{
|
||||
HdfGroup gMaximums = gMesh.group( "Maximums" );
|
||||
if ( gMaximums.isValid() )
|
||||
{
|
||||
for ( const std::string &name : gMaximums.groups() )
|
||||
if ( groupName == "Maximums" )
|
||||
{
|
||||
HdfGroup g = gMaximums.group( name );
|
||||
std::shared_ptr<MDAL::DatasetGroup> maxGroup = readXmdfGroupAsDatasetGroup( g, name + "/Maximums", vertexCount, faceCount );
|
||||
if ( !maxGroup || maxGroup->datasets.size() != 1 )
|
||||
MDAL::debug( "Maximum dataset should have just one timestep!" );
|
||||
else
|
||||
groups.push_back( maxGroup );
|
||||
addDatasetGroupsFromXmdfGroup( groups, gGroup, "/Maximums", vertexCount, faceCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
addDatasetGroupsFromXmdfGroup( groups, gGroup, "", vertexCount, faceCount );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// res_to_res.exe (TUFLOW utiity tool)
|
||||
if ( gMesh.pathExists( "Difference" ) )
|
||||
{
|
||||
HdfGroup gDifference = gMesh.group( "Difference" );
|
||||
if ( gDifference.isValid() )
|
||||
{
|
||||
addDatasetGroupsFromXmdfGroup( groups, gDifference, vertexCount, faceCount );
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,20 +173,26 @@ void MDAL::DriverXmdf::load( const std::string &datFile, MDAL::Mesh *mesh, MDAL
|
||||
);
|
||||
}
|
||||
|
||||
void MDAL::DriverXmdf::addDatasetGroupsFromXmdfGroup( DatasetGroups &groups, const HdfGroup &rootGroup, size_t vertexCount, size_t faceCount )
|
||||
void MDAL::DriverXmdf::addDatasetGroupsFromXmdfGroup( DatasetGroups &groups,
|
||||
const HdfGroup &rootGroup,
|
||||
const std::string &nameSuffix,
|
||||
size_t vertexCount,
|
||||
size_t faceCount )
|
||||
{
|
||||
for ( const std::string &name : rootGroup.groups() )
|
||||
for ( const std::string &groupName : rootGroup.groups() )
|
||||
{
|
||||
HdfGroup g = rootGroup.group( name );
|
||||
std::shared_ptr<DatasetGroup> ds = readXmdfGroupAsDatasetGroup( g, name, vertexCount, faceCount );
|
||||
HdfGroup g = rootGroup.group( groupName );
|
||||
std::shared_ptr<DatasetGroup> ds = readXmdfGroupAsDatasetGroup( g, groupName + nameSuffix, vertexCount, faceCount );
|
||||
if ( ds && ds->datasets.size() > 0 )
|
||||
{
|
||||
groups.push_back( ds );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGroup(
|
||||
const HdfGroup &rootGroup, const std::string &name, size_t vertexCount, size_t faceCount )
|
||||
const HdfGroup &rootGroup, const std::string &groupName, size_t vertexCount, size_t faceCount )
|
||||
{
|
||||
std::shared_ptr<DatasetGroup> group;
|
||||
std::vector<std::string> gDataNames = rootGroup.datasets();
|
||||
@ -218,7 +202,7 @@ std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGrou
|
||||
!MDAL::contains( gDataNames, "Mins" ) ||
|
||||
!MDAL::contains( gDataNames, "Maxs" ) )
|
||||
{
|
||||
MDAL::debug( "ignoring dataset " + name + " - not having required arrays" );
|
||||
MDAL::debug( "ignoring dataset " + groupName + " - not having required arrays" );
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -241,7 +225,7 @@ std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGrou
|
||||
dimMaxs.size() != 1
|
||||
)
|
||||
{
|
||||
MDAL::debug( "ignoring dataset " + name + " - arrays not having correct dimension counts" );
|
||||
MDAL::debug( "ignoring dataset " + groupName + " - arrays not having correct dimension counts" );
|
||||
return group;
|
||||
}
|
||||
hsize_t nTimeSteps = dimTimes[0];
|
||||
@ -251,12 +235,12 @@ std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGrou
|
||||
dimMins[0] != nTimeSteps ||
|
||||
dimMaxs[0] != nTimeSteps )
|
||||
{
|
||||
MDAL::debug( "ignoring dataset " + name + " - arrays not having correct dimension sizes" );
|
||||
MDAL::debug( "ignoring dataset " + groupName + " - arrays not having correct dimension sizes" );
|
||||
return group;
|
||||
}
|
||||
if ( dimValues[1] != vertexCount || dimActive[1] != faceCount )
|
||||
{
|
||||
MDAL::debug( "ignoring dataset " + name + " - not aligned with the used mesh" );
|
||||
MDAL::debug( "ignoring dataset " + groupName + " - not aligned with the used mesh" );
|
||||
return group;
|
||||
}
|
||||
|
||||
@ -266,9 +250,10 @@ std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverXmdf::readXmdfGroupAsDatasetGrou
|
||||
|
||||
// all fine, set group and return
|
||||
group = std::make_shared<MDAL::DatasetGroup>(
|
||||
name(),
|
||||
mMesh,
|
||||
mDatFile,
|
||||
name
|
||||
groupName
|
||||
);
|
||||
group->setIsScalar( !isVector );
|
||||
group->setIsOnVertices( true );
|
||||
|
23
external/mdal/frmts/mdal_xmdf.hpp
vendored
23
external/mdal/frmts/mdal_xmdf.hpp
vendored
@ -58,6 +58,26 @@ namespace MDAL
|
||||
class DriverXmdf: public Driver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Driver for XMDF Files
|
||||
*
|
||||
* Structure of the TUFLOW file. Groups are optional since it depends
|
||||
* on tools which groups are created.
|
||||
* - root
|
||||
* - Temporal
|
||||
* - Depth
|
||||
* - Velocity
|
||||
* - ..
|
||||
* - Maximums
|
||||
* - Depth
|
||||
* - Velocity
|
||||
* - ..
|
||||
* - Difference (res_to_res.exe TUFLOW utility tool)
|
||||
* - ..
|
||||
* - Times (e.g. time of peak velocity)
|
||||
* - ..
|
||||
* - ...
|
||||
*/
|
||||
DriverXmdf();
|
||||
~DriverXmdf( ) override = default;
|
||||
DriverXmdf *create() override;
|
||||
@ -70,13 +90,14 @@ namespace MDAL
|
||||
std::string mDatFile;
|
||||
std::shared_ptr<MDAL::DatasetGroup> readXmdfGroupAsDatasetGroup(
|
||||
const HdfGroup &rootGroup,
|
||||
const std::string &name,
|
||||
const std::string &groupName,
|
||||
size_t vertexCount,
|
||||
size_t faceCount );
|
||||
|
||||
void addDatasetGroupsFromXmdfGroup(
|
||||
DatasetGroups &groups,
|
||||
const HdfGroup &rootGroup,
|
||||
const std::string &nameSuffix,
|
||||
size_t vertexCount,
|
||||
size_t faceCount );
|
||||
};
|
||||
|
220
external/mdal/mdal.cpp
vendored
220
external/mdal/mdal.cpp
vendored
@ -12,6 +12,7 @@
|
||||
#include "mdal.h"
|
||||
#include "mdal_driver_manager.hpp"
|
||||
#include "mdal_data_model.hpp"
|
||||
#include "mdal_utils.hpp"
|
||||
|
||||
#define NODATA std::numeric_limits<double>::quiet_NaN()
|
||||
|
||||
@ -21,7 +22,7 @@ static MDAL_Status sLastStatus;
|
||||
|
||||
const char *MDAL_Version()
|
||||
{
|
||||
return "0.1.2";
|
||||
return "0.1.4";
|
||||
}
|
||||
|
||||
MDAL_Status MDAL_LastStatus()
|
||||
@ -50,6 +51,12 @@ int MDAL_driverCount()
|
||||
|
||||
DriverH MDAL_driverFromIndex( int index )
|
||||
{
|
||||
if ( index < 0 )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriver;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t idx = static_cast<size_t>( index );
|
||||
std::shared_ptr<MDAL::Driver> driver = MDAL::DriverManager::instance().driver( idx );
|
||||
return static_cast<DriverH>( driver.get() );
|
||||
@ -71,7 +78,18 @@ bool MDAL_DR_meshLoadCapability( DriverH driver )
|
||||
}
|
||||
|
||||
MDAL::Driver *d = static_cast< MDAL::Driver * >( driver );
|
||||
return d->type() == MDAL::DriverType::CanReadMeshAndDatasets;
|
||||
return d->hasCapability( MDAL::Capability::ReadMesh );
|
||||
}
|
||||
|
||||
bool MDAL_DR_writeDatasetsCapability( DriverH driver )
|
||||
{
|
||||
if ( !driver )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriver;
|
||||
return false;
|
||||
}
|
||||
MDAL::Driver *d = static_cast< MDAL::Driver * >( driver );
|
||||
return d->hasCapability( MDAL::Capability::WriteDatasets );
|
||||
}
|
||||
|
||||
const char *MDAL_DR_longName( DriverH driver )
|
||||
@ -262,6 +280,72 @@ DatasetGroupH MDAL_M_datasetGroup( MeshH mesh, int index )
|
||||
return static_cast< DatasetH >( m->datasetGroups[i].get() );
|
||||
}
|
||||
|
||||
DatasetGroupH MDAL_M_addDatasetGroup(
|
||||
MeshH mesh,
|
||||
const char *name,
|
||||
bool isOnVertices,
|
||||
bool hasScalarData,
|
||||
DriverH driver,
|
||||
const char *datasetGroupFile )
|
||||
{
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( !name )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( !datasetGroupFile )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( !driver )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriver;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
MDAL::Driver *dr = static_cast< MDAL::Driver * >( driver );
|
||||
|
||||
if ( !dr->hasCapability( MDAL::Capability::WriteDatasets ) )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriverCapability;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t index = m->datasetGroups.size();
|
||||
dr->createDatasetGroup( m,
|
||||
name,
|
||||
isOnVertices,
|
||||
hasScalarData,
|
||||
datasetGroupFile
|
||||
);
|
||||
if ( index < m->datasetGroups.size() ) // we have new dataset group
|
||||
return static_cast< DatasetGroupH >( m->datasetGroups[ index ].get() );
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *MDAL_M_driverName( MeshH mesh )
|
||||
{
|
||||
if ( !mesh )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleMesh;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MDAL::Mesh *m = static_cast< MDAL::Mesh * >( mesh );
|
||||
return _return_str( m->driverName() );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// MESH VERTICES
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -506,6 +590,138 @@ void MDAL_G_minimumMaximum( DatasetGroupH group, double *min, double *max )
|
||||
*max = stats.maximum;
|
||||
}
|
||||
|
||||
DatasetH MDAL_G_addDataset( DatasetGroupH group, double time, const double *values, const int *active )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( !values )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
|
||||
if ( !g->isInEditMode() )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string driverName = g->driverName();
|
||||
std::shared_ptr<MDAL::Driver> dr = MDAL::DriverManager::instance().driver( driverName );
|
||||
if ( !dr )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriver;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( !dr->hasCapability( MDAL::Capability::WriteDatasets ) )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriverCapability;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const size_t index = g->datasets.size();
|
||||
dr->createDataset( g,
|
||||
time,
|
||||
values,
|
||||
active
|
||||
);
|
||||
if ( index < g->datasets.size() ) // we have new dataset
|
||||
return static_cast< DatasetGroupH >( g->datasets[ index ].get() );
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MDAL_G_isInEditMode( DatasetGroupH group )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return true;
|
||||
}
|
||||
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
|
||||
return g->isInEditMode();
|
||||
}
|
||||
|
||||
void MDAL_G_closeEditMode( DatasetGroupH group )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return;
|
||||
}
|
||||
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
|
||||
|
||||
if ( !g->isInEditMode() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g->setStatistics( MDAL::calculateStatistics( g ) );
|
||||
g->stopEditing();
|
||||
|
||||
const std::string driverName = g->driverName();
|
||||
std::shared_ptr<MDAL::Driver> dr = MDAL::DriverManager::instance().driver( driverName );
|
||||
if ( !dr )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriver;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !dr->hasCapability( MDAL::Capability::WriteDatasets ) )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_MissingDriverCapability;
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = dr->persist( g );
|
||||
if ( error )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MDAL_G_setMetadata( DatasetGroupH group, const char *key, const char *val )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
}
|
||||
|
||||
if ( !key )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !val )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_InvalidData;
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string k( key );
|
||||
const std::string v( val );
|
||||
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
|
||||
g->setMetadata( k, v );
|
||||
}
|
||||
|
||||
const char *MDAL_G_driverName( DatasetGroupH group )
|
||||
{
|
||||
if ( !group )
|
||||
{
|
||||
sLastStatus = MDAL_Status::Err_IncompatibleDataset;
|
||||
return EMPTY_STR;
|
||||
}
|
||||
MDAL::DatasetGroup *g = static_cast< MDAL::DatasetGroup * >( group );
|
||||
return _return_str( g->driverName() );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
/// DATASETS
|
||||
|
54
external/mdal/mdal_data_model.cpp
vendored
54
external/mdal/mdal_data_model.cpp
vendored
@ -17,6 +17,11 @@ MDAL::Dataset::Dataset( MDAL::DatasetGroup *parent )
|
||||
assert( mParent );
|
||||
}
|
||||
|
||||
std::string MDAL::Dataset::driverName() const
|
||||
{
|
||||
return group()->driverName();
|
||||
}
|
||||
|
||||
size_t MDAL::Dataset::valuesCount() const
|
||||
{
|
||||
if ( group()->isOnVertices() )
|
||||
@ -69,20 +74,30 @@ void MDAL::Dataset::setIsValid( bool isValid )
|
||||
mIsValid = isValid;
|
||||
}
|
||||
|
||||
MDAL::DatasetGroup::DatasetGroup( MDAL::Mesh *parent,
|
||||
MDAL::DatasetGroup::DatasetGroup( const std::string &driverName,
|
||||
MDAL::Mesh *parent,
|
||||
const std::string &uri,
|
||||
const std::string &name )
|
||||
: mParent( parent )
|
||||
: mDriverName( driverName )
|
||||
, mParent( parent )
|
||||
, mUri( uri )
|
||||
{
|
||||
assert( mParent );
|
||||
setName( name );
|
||||
}
|
||||
|
||||
std::string MDAL::DatasetGroup::driverName() const
|
||||
{
|
||||
return mDriverName;
|
||||
}
|
||||
|
||||
MDAL::DatasetGroup::~DatasetGroup() = default;
|
||||
|
||||
MDAL::DatasetGroup::DatasetGroup( MDAL::Mesh *parent, const std::string &uri )
|
||||
: mParent( parent )
|
||||
MDAL::DatasetGroup::DatasetGroup( const std::string &driverName,
|
||||
MDAL::Mesh *parent,
|
||||
const std::string &uri )
|
||||
: mDriverName( driverName )
|
||||
, mParent( parent )
|
||||
, mUri( uri )
|
||||
{
|
||||
assert( mParent );
|
||||
@ -145,6 +160,21 @@ MDAL::Mesh *MDAL::DatasetGroup::mesh() const
|
||||
return mParent;
|
||||
}
|
||||
|
||||
bool MDAL::DatasetGroup::isInEditMode() const
|
||||
{
|
||||
return mInEditMode;
|
||||
}
|
||||
|
||||
void MDAL::DatasetGroup::startEditing()
|
||||
{
|
||||
mInEditMode = true;
|
||||
}
|
||||
|
||||
void MDAL::DatasetGroup::stopEditing()
|
||||
{
|
||||
mInEditMode = false;
|
||||
}
|
||||
|
||||
bool MDAL::DatasetGroup::isOnVertices() const
|
||||
{
|
||||
return mIsOnVertices;
|
||||
@ -171,8 +201,15 @@ void MDAL::DatasetGroup::setIsScalar( bool isScalar )
|
||||
mIsScalar = isScalar;
|
||||
}
|
||||
|
||||
MDAL::Mesh::Mesh( size_t verticesCount, size_t facesCount, size_t faceVerticesMaximumCount, MDAL::BBox extent, const std::string &uri )
|
||||
: mVerticesCount( verticesCount )
|
||||
MDAL::Mesh::Mesh(
|
||||
const std::string &driverName,
|
||||
size_t verticesCount,
|
||||
size_t facesCount,
|
||||
size_t faceVerticesMaximumCount,
|
||||
MDAL::BBox extent,
|
||||
const std::string &uri )
|
||||
: mDriverName( driverName )
|
||||
, mVerticesCount( verticesCount )
|
||||
, mFacesCount( facesCount )
|
||||
, mFaceVerticesMaximumCount( faceVerticesMaximumCount )
|
||||
, mExtent( extent )
|
||||
@ -180,6 +217,11 @@ MDAL::Mesh::Mesh( size_t verticesCount, size_t facesCount, size_t faceVerticesMa
|
||||
{
|
||||
}
|
||||
|
||||
std::string MDAL::Mesh::driverName() const
|
||||
{
|
||||
return mDriverName;
|
||||
}
|
||||
|
||||
MDAL::Mesh::~Mesh() = default;
|
||||
|
||||
void MDAL::Mesh::setSourceCrs( const std::string &str )
|
||||
|
26
external/mdal/mdal_data_model.hpp
vendored
26
external/mdal/mdal_data_model.hpp
vendored
@ -44,6 +44,8 @@ namespace MDAL
|
||||
Dataset( DatasetGroup *parent );
|
||||
virtual ~Dataset();
|
||||
|
||||
std::string driverName() const;
|
||||
|
||||
size_t valuesCount() const;
|
||||
virtual size_t scalarData( size_t indexStart, size_t count, double *buffer ) = 0;
|
||||
virtual size_t vectorData( size_t indexStart, size_t count, double *buffer ) = 0;
|
||||
@ -73,15 +75,20 @@ namespace MDAL
|
||||
class DatasetGroup
|
||||
{
|
||||
public:
|
||||
DatasetGroup( Mesh *parent,
|
||||
const std::string &uri );
|
||||
DatasetGroup( const std::string &driverName,
|
||||
Mesh *parent,
|
||||
const std::string &uri
|
||||
);
|
||||
|
||||
DatasetGroup( Mesh *parent,
|
||||
DatasetGroup( const std::string &driverName,
|
||||
Mesh *parent,
|
||||
const std::string &uri,
|
||||
const std::string &name );
|
||||
|
||||
~DatasetGroup();
|
||||
|
||||
std::string driverName() const;
|
||||
|
||||
std::string getMetadata( const std::string &key );
|
||||
void setMetadata( const std::string &key, const std::string &val );
|
||||
|
||||
@ -104,7 +111,14 @@ namespace MDAL
|
||||
|
||||
Mesh *mesh() const;
|
||||
|
||||
bool isInEditMode() const;
|
||||
void startEditing();
|
||||
void stopEditing();
|
||||
|
||||
private:
|
||||
bool mInEditMode = false;
|
||||
|
||||
const std::string mDriverName;
|
||||
Mesh *mParent = nullptr;
|
||||
bool mIsScalar = true;
|
||||
bool mIsOnVertices = true;
|
||||
@ -136,13 +150,16 @@ namespace MDAL
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
Mesh( size_t verticesCount,
|
||||
Mesh( const std::string &driverName,
|
||||
size_t verticesCount,
|
||||
size_t facesCount,
|
||||
size_t faceVerticesMaximumCount,
|
||||
BBox extent,
|
||||
const std::string &uri );
|
||||
virtual ~Mesh();
|
||||
|
||||
std::string driverName() const;
|
||||
|
||||
void setSourceCrs( const std::string &str );
|
||||
void setSourceCrsFromWKT( const std::string &wkt );
|
||||
void setSourceCrsFromEPSG( int code );
|
||||
@ -165,6 +182,7 @@ namespace MDAL
|
||||
size_t faceVerticesMaximumCount() const;
|
||||
|
||||
private:
|
||||
const std::string mDriverName;
|
||||
size_t mVerticesCount = 0;
|
||||
size_t mFacesCount = 0;
|
||||
size_t mFaceVerticesMaximumCount = 0; //typically 3 or 4, sometimes up to 9
|
||||
|
6
external/mdal/mdal_driver_manager.cpp
vendored
6
external/mdal/mdal_driver_manager.cpp
vendored
@ -41,7 +41,7 @@ std::unique_ptr<MDAL::Mesh> MDAL::DriverManager::load( const std::string &meshFi
|
||||
|
||||
for ( const auto &driver : mDrivers )
|
||||
{
|
||||
if ( ( driver->type() == DriverType::CanReadMeshAndDatasets ) &&
|
||||
if ( ( driver->hasCapability( Capability::ReadMesh ) ) &&
|
||||
driver->canRead( meshFile ) )
|
||||
{
|
||||
std::unique_ptr<Driver> drv( driver->create() );
|
||||
@ -73,7 +73,7 @@ void MDAL::DriverManager::loadDatasets( Mesh *mesh, const std::string &datasetFi
|
||||
|
||||
for ( const auto &driver : mDrivers )
|
||||
{
|
||||
if ( ( driver->type() == DriverType::CanReadOnlyDatasets ) &&
|
||||
if ( driver->hasCapability( Capability::ReadDatasets ) &&
|
||||
driver->canRead( datasetFile ) )
|
||||
{
|
||||
std::unique_ptr<Driver> drv( driver->create() );
|
||||
@ -93,7 +93,7 @@ size_t MDAL::DriverManager::driversCount() const
|
||||
|
||||
std::shared_ptr<MDAL::Driver> MDAL::DriverManager::driver( size_t index ) const
|
||||
{
|
||||
if ( mDrivers.size() < index )
|
||||
if ( mDrivers.size() <= index )
|
||||
{
|
||||
return std::shared_ptr<MDAL::Driver>();
|
||||
}
|
||||
|
14
external/mdal/mdal_memory_data_model.cpp
vendored
14
external/mdal/mdal_memory_data_model.cpp
vendored
@ -91,8 +91,18 @@ size_t MDAL::MemoryDataset::vectorData( size_t indexStart, size_t count, double
|
||||
return copyValues;
|
||||
}
|
||||
|
||||
MDAL::MemoryMesh::MemoryMesh( size_t verticesCount, size_t facesCount, size_t faceVerticesMaximumCount, MDAL::BBox extent, const std::string &uri )
|
||||
: MDAL::Mesh( verticesCount, facesCount, faceVerticesMaximumCount, extent, uri )
|
||||
MDAL::MemoryMesh::MemoryMesh( const std::string &driverName,
|
||||
size_t verticesCount,
|
||||
size_t facesCount,
|
||||
size_t faceVerticesMaximumCount,
|
||||
MDAL::BBox extent,
|
||||
const std::string &uri )
|
||||
: MDAL::Mesh( driverName,
|
||||
verticesCount,
|
||||
facesCount,
|
||||
faceVerticesMaximumCount,
|
||||
extent,
|
||||
uri )
|
||||
{
|
||||
}
|
||||
|
||||
|
3
external/mdal/mdal_memory_data_model.hpp
vendored
3
external/mdal/mdal_memory_data_model.hpp
vendored
@ -78,7 +78,8 @@ namespace MDAL
|
||||
class MemoryMesh: public Mesh
|
||||
{
|
||||
public:
|
||||
MemoryMesh( size_t verticesCount,
|
||||
MemoryMesh( const std::string &driverName,
|
||||
size_t verticesCount,
|
||||
size_t facesCount,
|
||||
size_t faceVerticesMaximumCount,
|
||||
BBox extent,
|
||||
|
48
external/mdal/mdal_utils.cpp
vendored
48
external/mdal/mdal_utils.cpp
vendored
@ -24,6 +24,9 @@ bool MDAL::fileExists( const std::string &filename )
|
||||
|
||||
bool MDAL::startsWith( const std::string &str, const std::string &substr, ContainsBehaviour behaviour )
|
||||
{
|
||||
if ( str.size() < substr.size() )
|
||||
return false;
|
||||
|
||||
if ( behaviour == ContainsBehaviour::CaseSensitive )
|
||||
return str.rfind( substr, 0 ) == 0;
|
||||
else
|
||||
@ -32,6 +35,9 @@ bool MDAL::startsWith( const std::string &str, const std::string &substr, Contai
|
||||
|
||||
bool MDAL::endsWith( const std::string &str, const std::string &substr, ContainsBehaviour behaviour )
|
||||
{
|
||||
if ( str.size() < substr.size() )
|
||||
return false;
|
||||
|
||||
if ( behaviour == ContainsBehaviour::CaseSensitive )
|
||||
return str.rfind( substr ) == ( str.size() - substr.size() );
|
||||
else
|
||||
@ -182,6 +188,21 @@ std::string MDAL::join( const std::vector<std::string> parts, const std::string
|
||||
return res.str();
|
||||
}
|
||||
|
||||
std::string MDAL::leftJustified( const std::string &str, size_t width, char fill )
|
||||
{
|
||||
std::string ret( str );
|
||||
if ( ret.size() > width )
|
||||
{
|
||||
ret = ret.substr( 0, width );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ret + std::string( width - ret.size(), fill );
|
||||
}
|
||||
assert( ret.size() == width );
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string MDAL::toLower( const std::string &std )
|
||||
{
|
||||
std::string res( std );
|
||||
@ -222,11 +243,22 @@ std::string MDAL::replace( const std::string &str, const std::string &substr, co
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string MDAL::removeLastChar( const std::string &str )
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
std::string MDAL::trim( const std::string &s, const std::string &delimiters )
|
||||
{
|
||||
std::string ret( str );
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
return ltrim( rtrim( s, delimiters ), delimiters );
|
||||
}
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
std::string MDAL::ltrim( const std::string &s, const std::string &delimiters )
|
||||
{
|
||||
return s.substr( s.find_first_not_of( delimiters ) );
|
||||
}
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
std::string MDAL::rtrim( const std::string &s, const std::string &delimiters )
|
||||
{
|
||||
return s.substr( 0, s.find_last_not_of( delimiters ) + 1 );
|
||||
}
|
||||
|
||||
MDAL::BBox MDAL::computeExtent( const MDAL::Vertices &vertices )
|
||||
@ -348,7 +380,12 @@ MDAL::Statistics _calculateStatistics( const std::vector<double> &values, size_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
MDAL::Statistics MDAL::calculateStatistics( std::shared_ptr<DatasetGroup> grp )
|
||||
MDAL::Statistics MDAL::calculateStatistics( std::shared_ptr<MDAL::DatasetGroup> grp )
|
||||
{
|
||||
return calculateStatistics( grp.get() );
|
||||
}
|
||||
|
||||
MDAL::Statistics MDAL::calculateStatistics( DatasetGroup *grp )
|
||||
{
|
||||
Statistics ret;
|
||||
if ( !grp )
|
||||
@ -416,6 +453,7 @@ void MDAL::addBedElevationDatasetGroup( MDAL::Mesh *mesh, const Vertices &vertic
|
||||
return;
|
||||
|
||||
std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >(
|
||||
mesh->driverName(),
|
||||
mesh,
|
||||
mesh->uri(),
|
||||
"Bed Elevation"
|
||||
|
31
external/mdal/mdal_utils.hpp
vendored
31
external/mdal/mdal_utils.hpp
vendored
@ -47,7 +47,8 @@ namespace MDAL
|
||||
bool contains( const std::string &str, const std::string &substr, ContainsBehaviour behaviour = CaseSensitive );
|
||||
bool contains( const std::vector<std::string> &list, const std::string &str );
|
||||
std::string replace( const std::string &str, const std::string &substr, const std::string &replacestr, ContainsBehaviour behaviour = CaseSensitive );
|
||||
std::string removeLastChar( const std::string &str );
|
||||
//! left justify and truncate, resulting string will always have width chars
|
||||
std::string leftJustified( const std::string &str, size_t width, char fill = ' ' );
|
||||
|
||||
std::string toLower( const std::string &std );
|
||||
|
||||
@ -66,29 +67,20 @@ namespace MDAL
|
||||
std::vector<std::string> split( const std::string &str, const std::string &delimiter, SplitBehaviour behaviour );
|
||||
std::string join( const std::vector<std::string> parts, const std::string &delimiter );
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string rtrim(
|
||||
//! Right trim
|
||||
std::string rtrim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return s.substr( 0, s.find_last_not_of( delimiters ) + 1 );
|
||||
}
|
||||
const std::string &delimiters = " \f\n\r\t\v" );
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string ltrim(
|
||||
//! Left trim
|
||||
std::string ltrim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return s.substr( s.find_first_not_of( delimiters ) );
|
||||
}
|
||||
const std::string &delimiters = " \f\n\r\t\v" );
|
||||
|
||||
// http://www.cplusplus.com/faq/sequences/strings/trim/
|
||||
inline std::string trim(
|
||||
//! Right and left trim
|
||||
std::string trim(
|
||||
const std::string &s,
|
||||
const std::string &delimiters = " \f\n\r\t\v" )
|
||||
{
|
||||
return ltrim( rtrim( s, delimiters ), delimiters );
|
||||
}
|
||||
const std::string &delimiters = " \f\n\r\t\v" );
|
||||
|
||||
// extent
|
||||
BBox computeExtent( const Vertices &vertices );
|
||||
@ -102,6 +94,7 @@ namespace MDAL
|
||||
|
||||
//! Calculates statistics for dataset group
|
||||
Statistics calculateStatistics( std::shared_ptr<DatasetGroup> grp );
|
||||
Statistics calculateStatistics( DatasetGroup *grp );
|
||||
|
||||
//! Calculates statistics for dataset
|
||||
Statistics calculateStatistics( std::shared_ptr<Dataset> dataset );
|
||||
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 30 20">
|
||||
<defs>
|
||||
<path id="s" d="M0,-1 0.587785,0.809017 -0.951057,-0.309017H0.951057L-0.587785,0.809017z" fill="#ffde00"/>
|
||||
</defs>
|
||||
<rect width="30" height="20" fill="#de2910"/>
|
||||
<use xlink:href="#s" transform="translate(5,5) scale(3)"/>
|
||||
<use xlink:href="#s" transform="translate(10,2) rotate(23.036243)"/>
|
||||
<use xlink:href="#s" transform="translate(12,4) rotate(45.869898)"/>
|
||||
<use xlink:href="#s" transform="translate(12,7) rotate(69.945396)"/>
|
||||
<use xlink:href="#s" transform="translate(10,9) rotate(20.659808)"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 688 B |
@ -63,7 +63,6 @@
|
||||
<file>flags/sr.svg</file>
|
||||
<file>flags/te.svg</file>
|
||||
<file>flags/tl.svg</file>
|
||||
<file>flags/zh.svg</file>
|
||||
<file>flags/zh-Hans.svg</file>
|
||||
<file>flags/zh-Hant.svg</file>
|
||||
<file>flags/ky.svg</file>
|
||||
@ -379,6 +378,7 @@
|
||||
<file>themes/default/mActionShowPinnedLabels.svg</file>
|
||||
<file>themes/default/mActionShowPluginManager.svg</file>
|
||||
<file>themes/default/mActionShowRasterCalculator.png</file>
|
||||
<file>themes/default/mActionShowMeshCalculator.svg</file>
|
||||
<file>themes/default/mActionShowSelectedLayers.svg</file>
|
||||
<file>themes/default/mActionSimplify.svg</file>
|
||||
<file>themes/default/mActionSplitFeatures.svg</file>
|
||||
@ -742,6 +742,8 @@
|
||||
<file>themes/default/mIconFolder24.svg</file>
|
||||
<file>themes/default/mActionNewFolder.svg</file>
|
||||
<file>themes/default/mIconFieldBool.svg</file>
|
||||
<file>themes/default/mIconDataDefineColor.svg</file>
|
||||
<file>themes/default/mIconDataDefineColorOn.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images/tips">
|
||||
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
||||
|
1
images/themes/default/mActionShowMeshCalculator.svg
Executable file
1
images/themes/default/mActionShowMeshCalculator.svg
Executable file
@ -0,0 +1 @@
|
||||
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="a" x1="16.1" x2="10.9" y1="13" y2="9.09" gradientTransform="matrix(.476 0 0 .518 .336 -3.21)" gradientUnits="userSpaceOnUse"><stop stop-color="#aec7e2" offset="0"/><stop stop-color="#eee" offset="1"/></linearGradient><linearGradient id="b" x1="4.53" x2="4.46" y1="22.4" y2="25.1" gradientTransform="matrix(.719 0 0 2.45 .0312 -52.3)" gradientUnits="userSpaceOnUse"><stop stop-color="#eee" offset="0"/><stop stop-color="#aec7e2" offset="1"/></linearGradient></defs><path d="m4.5 9h1.5v2h-1.5z" fill="#cfcfcf"/><path d="m1 1v10h2.5v-10z" fill="url(#b)"/><path d="m4.5 1v7h5.5v-7z" fill="url(#a)"/><path d="m7 8.5h15" fill="none" stroke="#5b5b5c"/><path d="m7 13.5h15" fill="none" stroke="#5b5b5c"/><path d="m7 18.5h15" fill="none" stroke="#5b5b5c"/><circle cx="13" cy="8.5" r="1.5" fill="#f7aeae" fill-opacity=".996" fill-rule="evenodd" overflow="visible" stroke="#a20404"/><path d="m22.5 7.01v15" fill="none" stroke="#5b5b5c" stroke-linecap="round"/><path d="m6.5 7.01v15" fill="none" stroke="#5b5b5c" stroke-linecap="round"/><circle cx="15" cy="13.5" r="1.5" fill="#c5f7c5" fill-rule="evenodd" overflow="visible" stroke="#619361"/><circle cx="11" cy="13.5" r="1.5" fill="#c5f7c5" fill-rule="evenodd" overflow="visible" stroke="#619361"/><circle cx="11" cy="18.5" r="1.5" fill="#c2e0f4" fill-rule="evenodd" overflow="visible" stroke="#3f5e71"/><circle cx="15" cy="18.5" r="1.5" fill="#c2e0f4" fill-rule="evenodd" overflow="visible" stroke="#3f5e71"/><circle cx="19" cy="18.5" r="1.5" fill="#c2e0f4" fill-rule="evenodd" overflow="visible" stroke="#3f5e71"/><rect x="5" y="22" width="19" height="2" rx="0" ry="0" fill="#5b5b5c" stroke-width="0" style="paint-order:stroke markers fill"/><circle cx="19" cy="8.5" r="1.5" fill="#f7aeae" fill-opacity=".996" fill-rule="evenodd" overflow="visible" stroke="#a20404"/><path d="m10.5 8v-7.5h-10v11h5.5" fill="none" stroke="#2b3b4d"/><path d="m4 11v-10" stroke="#2b3b4d"/><path d="m1 8.5h5" stroke="#2b3b4d"/><path d="m4 8.5 6.5-8" stroke="#2b3b4d"/></svg>
|
After Width: | Height: | Size: 2.1 KiB |
1
images/themes/default/mIconDataDefineColor.svg
Normal file
1
images/themes/default/mIconDataDefineColor.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="4 4 24 24" width="24"><path d="M9.5 19.892c0 .836-.284 1.193-.631.792l-3.771-4.351a1.15 1.15 0 0 1 0-1.459l3.771-4.359c.347-.402.631-.045.631.792z" fill="#939598" stroke="#4f5052"/><path d="M9.341 8.199v15.156h12.514V8.199z" fill="none"/><path d="M9.5 8.5v15h12v-15z" fill="#fff" fill-opacity=".703" stroke="#878984" stroke-linecap="round" stroke-linejoin="round"/><path d="M12.954 11.868c-1.483 1.602-1.146-.264-.257-.906.921-.666 1.438-.649 1.431-.446-.008.238-.707.848-1.174 1.352zm-.498 5.16c-1.485 1.601-1.23.119-.34-.52.92-.663 1.437-.646 1.43-.443-.008.238-.626.462-1.09.963zm6.517 1.789c-1.432 1.598-1.322.08-.402-.509.702-.449.909-.06.402.509z" fill="#fff" opacity=".5"/><path d="M18.5 18v1.605c0 2.474-6 2.525-6-.18v-2.397c-.054-1.277.458-2.528 3-2.528v2c-.645.02-.995.748-1 1.212v.436c0 1.852 2 1.56 2 .185V18" fill="none" stroke="#2c2c2c" stroke-opacity=".706"/><path d="M13.5 14v-1.605c0-2.474 6-2.525 6 .18v2.397c.054 1.277-.458 2.528-3 2.528v-2c.645-.02.995-.748 1-1.212v-.436c0-1.852-2-1.56-2-.185V14" fill="none" stroke="#2c2c2c" stroke-opacity=".706"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
images/themes/default/mIconDataDefineColorOn.svg
Normal file
1
images/themes/default/mIconDataDefineColorOn.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="4 4 24 24" width="24"><path d="M9.5 19.892c0 .836-.284 1.193-.631.792l-3.771-4.351a1.15 1.15 0 0 1 0-1.459l3.771-4.359c.347-.402.631-.045.631.792z" fill="#939598" stroke="#4f5052"/><path d="M9.341 8.199v15.156h12.514V8.199z" fill="#fff"/><path d="M9.5 8.5v15h12v-15z" fill="#fbf091" stroke="#c4a000" stroke-linecap="round" stroke-linejoin="round"/><path d="M18.5 18v1.605c0 2.474-6 2.525-6-.18v-2.397c-.054-1.277.458-2.528 3-2.528v2c-.645.02-.995.748-1 1.212v.436c0 1.852 2 1.56 2 .185V18" fill="none" stroke="#2c2c2c" stroke-opacity=".706"/><path d="M13.5 14v-1.605c0-2.474 6-2.525 6 .18v2.397c.054 1.277-.458 2.528-3 2.528v-2c.645-.02.995-.748 1-1.212v-.436c0-1.852-2-1.56-2-.185V14" fill="none" stroke="#2c2c2c" stroke-opacity=".706"/></svg>
|
After Width: | Height: | Size: 805 B |
@ -43,8 +43,8 @@ call "%PF86%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %VCARCH%
|
||||
path %path%;%PF86%\Microsoft Visual Studio 14.0\VC\bin
|
||||
|
||||
set GRASS7=
|
||||
if exist %OSGEO4W_ROOT%\bin\grass72.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass72.bat
|
||||
if exist %OSGEO4W_ROOT%\bin\grass74.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass74.bat
|
||||
if exist %OSGEO4W_ROOT%\bin\grass76.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass76.bat
|
||||
if "%GRASS7%"=="" (echo GRASS7 not found & goto error)
|
||||
for /f "usebackq tokens=1" %%a in (`%GRASS7% --config path`) do set GRASS_PREFIX=%%a
|
||||
|
||||
|
@ -64,8 +64,8 @@ set CMAKE_OPT=^
|
||||
|
||||
:cmake
|
||||
set GRASS7=
|
||||
if exist %OSGEO4W_ROOT%\bin\grass72.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass72.bat
|
||||
if exist %OSGEO4W_ROOT%\bin\grass74.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass74.bat
|
||||
if exist %OSGEO4W_ROOT%\bin\grass76.bat set GRASS7=%OSGEO4W_ROOT%\bin\grass76.bat
|
||||
if "%GRASS7%"=="" (echo GRASS7 not found & goto error)
|
||||
|
||||
for /f "usebackq tokens=1" %%a in (`%GRASS7% --config path`) do set GRASS7_PATH=%%a
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Include auto-generated SIP files
|
||||
%Include auto_generated/qgs3dtypes.sip
|
||||
%Include auto_generated/qgsphongmaterialsettings.sip
|
||||
%Include auto_generated/qgsrulebased3drenderer.sip
|
||||
%Include auto_generated/qgsvectorlayer3drenderer.sip
|
||||
%Include auto_generated/symbols/qgsabstract3dsymbol.sip
|
||||
%Include auto_generated/symbols/qgsline3dsymbol.sip
|
||||
|
280
python/3d/auto_generated/qgsrulebased3drenderer.sip.in
Normal file
280
python/3d/auto_generated/qgsrulebased3drenderer.sip.in
Normal file
@ -0,0 +1,280 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/3d/qgsrulebased3drenderer.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsRuleBased3DRendererMetadata : Qgs3DRendererAbstractMetadata
|
||||
{
|
||||
%Docstring
|
||||
Metadata for rule-based 3D renderer to allow creation of its instances from XML
|
||||
|
||||
.. warning::
|
||||
|
||||
This is not considered stable API, and may change in future QGIS releases. It is
|
||||
exposed to the Python bindings as a tech preview only.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsrulebased3drenderer.h"
|
||||
%End
|
||||
public:
|
||||
QgsRuleBased3DRendererMetadata();
|
||||
|
||||
virtual QgsAbstract3DRenderer *createRenderer( QDomElement &elem, const QgsReadWriteContext &context ) /Factory/;
|
||||
|
||||
%Docstring
|
||||
Creates an instance of a 3D renderer based on a DOM element with renderer configuration
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
class QgsRuleBased3DRenderer : QgsAbstract3DRenderer
|
||||
{
|
||||
%Docstring
|
||||
Rule-based 3D renderer.
|
||||
|
||||
Similar to rule-based 2D renderer and rule-based labeling, it allows specification of rules for 3D symbols.
|
||||
|
||||
.. warning::
|
||||
|
||||
This is not considered stable API, and may change in future QGIS releases. It is
|
||||
exposed to the Python bindings as a tech preview only.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsrulebased3drenderer.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
typedef QList<QgsRuleBased3DRenderer::Rule *> RuleList;
|
||||
typedef QMap<const QgsRuleBased3DRenderer::Rule *, QgsFeature3DHandler *> RuleToHandlerMap;
|
||||
|
||||
class Rule
|
||||
{
|
||||
%Docstring
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsrulebased3drenderer.h"
|
||||
%End
|
||||
public:
|
||||
Rule( QgsAbstract3DSymbol *symbol /Transfer/, const QString &filterExp = QString(), const QString &description = QString(), bool elseRule = false );
|
||||
%Docstring
|
||||
takes ownership of symbol, symbol may be None
|
||||
%End
|
||||
~Rule();
|
||||
|
||||
|
||||
enum RegisterResult
|
||||
{
|
||||
Filtered,
|
||||
Inactive,
|
||||
Registered
|
||||
};
|
||||
|
||||
QgsAbstract3DSymbol *symbol() const;
|
||||
%Docstring
|
||||
Gets the labeling settings. May return a null pointer.
|
||||
%End
|
||||
|
||||
QString filterExpression() const;
|
||||
%Docstring
|
||||
A filter that will check if this rule applies
|
||||
|
||||
:return: An expression
|
||||
%End
|
||||
|
||||
QString description() const;
|
||||
%Docstring
|
||||
A human readable description for this rule
|
||||
|
||||
:return: Description
|
||||
%End
|
||||
|
||||
bool active() const;
|
||||
%Docstring
|
||||
Returns if this rule is active
|
||||
|
||||
:return: True if the rule is active
|
||||
%End
|
||||
|
||||
bool isElse() const;
|
||||
%Docstring
|
||||
Check if this rule is an ELSE rule
|
||||
|
||||
:return: True if this rule is an else rule
|
||||
%End
|
||||
|
||||
QString ruleKey() const;
|
||||
%Docstring
|
||||
Unique rule identifier (for identification of rule within labeling, used as provider ID)
|
||||
%End
|
||||
|
||||
void setSymbol( QgsAbstract3DSymbol *symbol /Transfer/ );
|
||||
%Docstring
|
||||
Sets new symbol (or NULL). Deletes old symbol if any.
|
||||
%End
|
||||
|
||||
void setFilterExpression( const QString &filterExp );
|
||||
%Docstring
|
||||
Set the expression used to check if a given feature shall be rendered with this rule
|
||||
|
||||
:param filterExp: An expression
|
||||
%End
|
||||
|
||||
void setDescription( const QString &description );
|
||||
%Docstring
|
||||
Set a human readable description for this rule
|
||||
|
||||
:param description: Description
|
||||
%End
|
||||
|
||||
void setActive( bool state );
|
||||
%Docstring
|
||||
Sets if this rule is active
|
||||
|
||||
:param state: Determines if the rule should be activated or deactivated
|
||||
%End
|
||||
|
||||
void setIsElse( bool iselse );
|
||||
%Docstring
|
||||
Sets if this rule is an ELSE rule
|
||||
|
||||
:param iselse: If true, this rule is an ELSE rule
|
||||
%End
|
||||
|
||||
void setRuleKey( const QString &key );
|
||||
%Docstring
|
||||
Override the assigned rule key (should be used just internally by rule-based renderer)
|
||||
%End
|
||||
|
||||
|
||||
const QgsRuleBased3DRenderer::RuleList &children() const;
|
||||
%Docstring
|
||||
Returns all children rules of this rule
|
||||
|
||||
:return: A list of rules
|
||||
%End
|
||||
|
||||
|
||||
QgsRuleBased3DRenderer::RuleList descendants() const;
|
||||
%Docstring
|
||||
Returns all children, grand-children, grand-grand-children, grand-gra... you get it
|
||||
|
||||
:return: A list of descendant rules
|
||||
%End
|
||||
|
||||
|
||||
QgsRuleBased3DRenderer::Rule *parent();
|
||||
%Docstring
|
||||
The parent rule
|
||||
|
||||
:return: Parent rule
|
||||
%End
|
||||
|
||||
void appendChild( QgsRuleBased3DRenderer::Rule *rule /Transfer/ );
|
||||
%Docstring
|
||||
add child rule, take ownership, sets this as parent
|
||||
%End
|
||||
|
||||
void insertChild( int i, QgsRuleBased3DRenderer::Rule *rule /Transfer/ );
|
||||
%Docstring
|
||||
add child rule, take ownership, sets this as parent
|
||||
%End
|
||||
|
||||
void removeChildAt( int i );
|
||||
%Docstring
|
||||
delete child rule
|
||||
%End
|
||||
|
||||
const QgsRuleBased3DRenderer::Rule *findRuleByKey( const QString &key ) const;
|
||||
%Docstring
|
||||
Try to find a rule given its unique key
|
||||
%End
|
||||
|
||||
|
||||
QgsRuleBased3DRenderer::Rule *clone() const /Factory/;
|
||||
%Docstring
|
||||
clone this rule, return new instance
|
||||
%End
|
||||
|
||||
|
||||
static QgsRuleBased3DRenderer::Rule *create( const QDomElement &ruleElem, const QgsReadWriteContext &context ) /Factory/;
|
||||
%Docstring
|
||||
Create a rule from an XML definition
|
||||
|
||||
:param ruleElem: The XML rule element
|
||||
:param context: reading context
|
||||
|
||||
:return: A new rule
|
||||
%End
|
||||
|
||||
QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
store labeling info to XML element
|
||||
%End
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
Rule( const QgsRuleBased3DRenderer::Rule &rh );
|
||||
};
|
||||
|
||||
|
||||
QgsRuleBased3DRenderer( QgsRuleBased3DRenderer::Rule *root /Transfer/ );
|
||||
%Docstring
|
||||
Construct renderer with the given root rule (takes ownership)
|
||||
%End
|
||||
~QgsRuleBased3DRenderer();
|
||||
|
||||
void setLayer( QgsVectorLayer *layer );
|
||||
%Docstring
|
||||
Sets vector layer associated with the renderer
|
||||
%End
|
||||
QgsVectorLayer *layer() const;
|
||||
%Docstring
|
||||
Returns vector layer associated with the renderer
|
||||
%End
|
||||
|
||||
QgsRuleBased3DRenderer::Rule *rootRule();
|
||||
%Docstring
|
||||
Returns pointer to the root rule
|
||||
%End
|
||||
|
||||
virtual QString type() const;
|
||||
virtual QgsRuleBased3DRenderer *clone() const /Factory/;
|
||||
|
||||
|
||||
virtual void writeXml( QDomElement &elem, const QgsReadWriteContext &context ) const;
|
||||
|
||||
virtual void readXml( const QDomElement &elem, const QgsReadWriteContext &context );
|
||||
|
||||
virtual void resolveReferences( const QgsProject &project );
|
||||
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/3d/qgsrulebased3drenderer.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -274,6 +274,7 @@ INCLUDE_DIRECTORIES(BEFORE
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/processing
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/vector
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/vector/geometry_checker
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/mesh
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/raster
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/network
|
||||
${CMAKE_SOURCE_DIR}/src/analysis/interpolation
|
||||
@ -281,6 +282,7 @@ INCLUDE_DIRECTORIES(BEFORE
|
||||
|
||||
${CMAKE_BINARY_DIR}/src/analysis/processing
|
||||
${CMAKE_BINARY_DIR}/src/analysis/vector
|
||||
${CMAKE_BINARY_DIR}/src/analysis/mesh
|
||||
${CMAKE_BINARY_DIR}/src/analysis/raster
|
||||
${CMAKE_BINARY_DIR}/src/analysis/network
|
||||
${CMAKE_BINARY_DIR}/src/analysis/interpolation
|
||||
|
@ -14,6 +14,7 @@
|
||||
%Include auto_generated/raster/qgsrastermatrix.sip
|
||||
%Include auto_generated/raster/qgsrastercalcnode.sip
|
||||
%Include auto_generated/raster/qgstotalcurvaturefilter.sip
|
||||
%Include auto_generated/mesh/qgsmeshcalculator.sip
|
||||
%Include auto_generated/vector/qgsgeometrysnapper.sip
|
||||
%Include auto_generated/vector/qgsgeometrysnappersinglesource.sip
|
||||
%Include auto_generated/vector/qgszonalstatistics.sip
|
||||
|
109
python/analysis/auto_generated/mesh/qgsmeshcalculator.sip.in
Normal file
109
python/analysis/auto_generated/mesh/qgsmeshcalculator.sip.in
Normal file
@ -0,0 +1,109 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/analysis/mesh/qgsmeshcalculator.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsMeshCalculator
|
||||
{
|
||||
%Docstring
|
||||
Performs mesh layer calculations.
|
||||
|
||||
Mesh calculator can do various mathematical operations
|
||||
between dataset groups from a single mesh layer.
|
||||
Resulting dataset group is added to the mesh layer.
|
||||
Result can be filtered by extent or a vector layer mask
|
||||
spatially and by selection of times.
|
||||
|
||||
Note: only dataset groups defined on vertices are
|
||||
implemented and supported
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsmeshcalculator.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
enum Result
|
||||
{
|
||||
Success,
|
||||
Canceled,
|
||||
CreateOutputError,
|
||||
InputLayerError,
|
||||
ParserError,
|
||||
InvalidDatasets,
|
||||
EvaluateError,
|
||||
MemoryError,
|
||||
};
|
||||
|
||||
QgsMeshCalculator( const QString &formulaString,
|
||||
const QString &outputFile,
|
||||
const QgsRectangle &outputExtent,
|
||||
double startTime,
|
||||
double endTime,
|
||||
QgsMeshLayer *layer );
|
||||
%Docstring
|
||||
Creates calculator with bounding box (rectangular) mask
|
||||
|
||||
:param formulaString: formula/expression to evaluate. Consists of dataset group names, operators and numbers
|
||||
:param outputFile: file to store the resulting dataset group data
|
||||
:param outputExtent: spatial filter defined by rectangle
|
||||
: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
|
||||
%End
|
||||
|
||||
QgsMeshCalculator( const QString &formulaString,
|
||||
const QString &outputFile,
|
||||
const QgsGeometry &outputMask,
|
||||
double startTime,
|
||||
double endTime,
|
||||
QgsMeshLayer *layer );
|
||||
%Docstring
|
||||
Creates calculator with geometry mask
|
||||
|
||||
:param formulaString: formula/expression to evaluate. Consists of dataset group names, operators and numbers
|
||||
:param outputFile: file to store the resulting dataset group data
|
||||
:param outputMask: spatial filter defined by geometry
|
||||
: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
|
||||
%End
|
||||
|
||||
Result processCalculation( QgsFeedback *feedback = 0 );
|
||||
%Docstring
|
||||
Starts the calculation, writes new dataset group to file and adds it to the mesh layer
|
||||
|
||||
:param feedback: The optional feedback argument for progress reporting and cancelation support
|
||||
|
||||
:return: QgsMeshCalculator.Success in case of success
|
||||
%End
|
||||
|
||||
static Result expression_valid( const QString &formulaString, QgsMeshLayer *layer );
|
||||
%Docstring
|
||||
Returns whether formula is valid for particular mesh layer
|
||||
|
||||
:param formulaString: formula/expression to evaluate. Consists of dataset group names, operators and numbers
|
||||
:param layer: mesh layer with dataset groups references in formulaString
|
||||
|
||||
:return: QgsMeshCalculator.Success in case of success
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/analysis/mesh/qgsmeshcalculator.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -148,6 +148,7 @@ class Editor(QsciScintilla):
|
||||
|
||||
self.SendScintilla(self.SCI_SETADDITIONALSELECTIONTYPING, 1)
|
||||
self.SendScintilla(self.SCI_SETMULTIPASTE, 1)
|
||||
self.SendScintilla(self.SCI_SETVIRTUALSPACEOPTIONS, self.SCVS_RECTANGULARSELECTION)
|
||||
|
||||
# self.setWrapMode(QsciScintilla.WrapCharacter)
|
||||
self.setWhitespaceVisibility(QsciScintilla.WsVisibleAfterIndent)
|
||||
|
@ -37,6 +37,7 @@ from .additions.qgsgeometry import _geometryNonZero, mapping_geometry
|
||||
from .additions.qgssettings import _qgssettings_enum_value, _qgssettings_set_enum_value, _qgssettings_flag_value
|
||||
from .additions.qgstaskwrapper import QgsTaskWrapper
|
||||
from .additions.readwritecontextentercategory import ReadWriteContextEnterCategory
|
||||
from .additions.validitycheck import check
|
||||
|
||||
# Injections into classes
|
||||
QgsFeature.__geo_interface__ = property(mapping_feature)
|
||||
|
95
python/core/additions/validitycheck.py
Normal file
95
python/core/additions/validitycheck.py
Normal file
@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
validitycheck.py
|
||||
---------------------
|
||||
Date : January 2019
|
||||
Copyright : (C) 2019 by Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************
|
||||
"""
|
||||
from qgis._core import (
|
||||
QgsAbstractValidityCheck,
|
||||
QgsApplication)
|
||||
|
||||
|
||||
class CheckFactory:
|
||||
"""
|
||||
Constructs QgsAbstractValidityChecks using a decorator.
|
||||
|
||||
To use, Python based checks should use the decorator syntax:
|
||||
|
||||
.. highlight:: python
|
||||
.. code-block:: python
|
||||
@check.register(type=QgsAbstractValidityCheck.TypeLayoutCheck)
|
||||
def my_layout_check(context, feedback):
|
||||
results = ...
|
||||
return results
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# unfortunately /Transfer/ annotation isn't working correct on validityCheckRegistry().addCheck(),
|
||||
# so we manually need to store a reference to all checks we register
|
||||
self.checks = []
|
||||
|
||||
def register(self, type, *args, **kwargs):
|
||||
"""
|
||||
Implements a decorator for registering Python based checks.
|
||||
|
||||
:param type: check type, e.g. QgsAbstractValidityCheck.TypeLayoutCheck
|
||||
"""
|
||||
|
||||
def dec(f):
|
||||
check = CheckWrapper(check_type=type, check_func=f)
|
||||
self.checks.append(check)
|
||||
QgsApplication.validityCheckRegistry().addCheck(check)
|
||||
|
||||
return dec
|
||||
|
||||
|
||||
class CheckWrapper(QgsAbstractValidityCheck):
|
||||
"""
|
||||
Wrapper object used to create new validity checks from @check.
|
||||
"""
|
||||
|
||||
def __init__(self, check_type, check_func):
|
||||
"""
|
||||
Initializer for CheckWrapper.
|
||||
|
||||
:param check_type: check type, e.g. QgsAbstractValidityCheck.TypeLayoutCheck
|
||||
:param check_func: test function, should return a list of QgsValidityCheckResult results
|
||||
"""
|
||||
super().__init__()
|
||||
self._check_type = check_type
|
||||
self._results = []
|
||||
self._check_func = check_func
|
||||
|
||||
def create(self):
|
||||
return CheckWrapper(check_type=self._check_type, check_func=self._check_func)
|
||||
|
||||
def id(self):
|
||||
return self._check_func.__name__
|
||||
|
||||
def checkType(self):
|
||||
return self._check_type
|
||||
|
||||
def prepareCheck(self, context, feedback):
|
||||
self._results = self._check_func(context, feedback)
|
||||
if self._results is None:
|
||||
self._results = []
|
||||
return True
|
||||
|
||||
def runCheck(self, context, feedback):
|
||||
return self._results
|
||||
|
||||
|
||||
check = CheckFactory()
|
2
python/core/auto_additions/qgsmaplayermodel.py
Normal file
2
python/core/auto_additions/qgsmaplayermodel.py
Normal file
@ -0,0 +1,2 @@
|
||||
# The following has been generated automatically from src/core/qgsmaplayermodel.h
|
||||
QgsMapLayerModel.ItemDataRole.baseClass = QgsMapLayerModel
|
@ -188,6 +188,31 @@ Note that this method is 2D only and does not consider the z-value of the circle
|
||||
.. seealso:: :py:func:`tangentToPoint`
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
int innerTangents( const QgsCircle &other,
|
||||
QgsPointXY &line1P1 /Out/, QgsPointXY &line1P2 /Out/,
|
||||
QgsPointXY &line2P1 /Out/, QgsPointXY &line2P2 /Out/ ) const;
|
||||
%Docstring
|
||||
Calculates the inner tangent points between this circle
|
||||
and an ``other`` circle.
|
||||
|
||||
The inner tangent points correspond to the points at which the two lines
|
||||
which are drawn so that they are tangential to both circles but on
|
||||
different sides, touching the circles and crossing each other.
|
||||
|
||||
The first tangent line is described by the points
|
||||
stored in ``line1P1`` and ``line1P2``,
|
||||
and the second line is described by the points stored in ``line2P1``
|
||||
and ``line2P2``.
|
||||
|
||||
Returns the number of tangents (either 0 or 2).
|
||||
|
||||
Note that this method is 2D only and does not consider the z-value of the circle.
|
||||
|
||||
.. seealso:: :py:func:`tangentToPoint`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
virtual double area() const;
|
||||
|
@ -1515,22 +1515,96 @@ will be raised.
|
||||
}
|
||||
%End
|
||||
|
||||
QgsMultiPointXY asMultiPoint() const;
|
||||
|
||||
SIP_PYOBJECT asMultiPoint() const /TypeHint="QgsMultiPointXY"/;
|
||||
%Docstring
|
||||
Returns contents of the geometry as a multi point
|
||||
if wkbType is WKBMultiPoint, otherwise an empty list
|
||||
Returns the contents of the geometry as a multi-point.
|
||||
|
||||
Any z or m values present in the geometry will be discarded.
|
||||
|
||||
This method works only with multi-point geometry types. If the geometry
|
||||
is not a multi-point type, a TypeError will be raised. If the geometry is null, a ValueError
|
||||
will be raised.
|
||||
%End
|
||||
%MethodCode
|
||||
const QgsWkbTypes::Type type = sipCpp->wkbType();
|
||||
if ( sipCpp->isNull() )
|
||||
{
|
||||
PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::PointGeometry || !QgsWkbTypes::isMultiType( type ) )
|
||||
{
|
||||
PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const sipMappedType *qvector_type = sipFindMappedType( "QVector< QgsPointXY >" );
|
||||
sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
|
||||
}
|
||||
%End
|
||||
|
||||
QgsMultiPolylineXY asMultiPolyline() const;
|
||||
|
||||
SIP_PYOBJECT asMultiPolyline() const /TypeHint="QgsMultiPolylineXY"/;
|
||||
%Docstring
|
||||
Returns contents of the geometry as a multi linestring
|
||||
if wkbType is WKBMultiLineString, otherwise an empty list
|
||||
Returns the contents of the geometry as a multi-linestring.
|
||||
|
||||
Any z or m values present in the geometry will be discarded. If the geometry is a curved line type
|
||||
(such as a MultiCurve), it will be automatically segmentized.
|
||||
|
||||
This method works only with multi-linestring (or multi-curve) geometry types. If the geometry
|
||||
is not a multi-linestring type, a TypeError will be raised. If the geometry is null, a ValueError
|
||||
will be raised.
|
||||
%End
|
||||
%MethodCode
|
||||
const QgsWkbTypes::Type type = sipCpp->wkbType();
|
||||
if ( sipCpp->isNull() )
|
||||
{
|
||||
PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::LineGeometry || !QgsWkbTypes::isMultiType( type ) )
|
||||
{
|
||||
PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multilinestring. Only multi linestring or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const sipMappedType *qvector_type = sipFindMappedType( "QVector<QVector<QgsPointXY>>" );
|
||||
sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
|
||||
}
|
||||
%End
|
||||
|
||||
QgsMultiPolygonXY asMultiPolygon() const;
|
||||
|
||||
SIP_PYOBJECT asMultiPolygon() const /TypeHint="QgsMultiPolygonXY"/;
|
||||
%Docstring
|
||||
Returns contents of the geometry as a multi polygon
|
||||
if wkbType is WKBMultiPolygon, otherwise an empty list
|
||||
Returns the contents of the geometry as a multi-polygon.
|
||||
|
||||
Any z or m values present in the geometry will be discarded. If the geometry is a curved polygon type
|
||||
(such as a MultiSurface), it will be automatically segmentized.
|
||||
|
||||
This method works only with multi-polygon (or multi-curve polygon) geometry types. If the geometry
|
||||
is not a multi-polygon type, a TypeError will be raised. If the geometry is null, a ValueError
|
||||
will be raised.
|
||||
%End
|
||||
%MethodCode
|
||||
const QgsWkbTypes::Type type = sipCpp->wkbType();
|
||||
if ( sipCpp->isNull() )
|
||||
{
|
||||
PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::PolygonGeometry || !QgsWkbTypes::isMultiType( type ) )
|
||||
{
|
||||
PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipolygon. Only multi polygon or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
const sipMappedType *qvector_type = sipFindMappedType( "QVector<QVector<QVector<QgsPointXY>>>" );
|
||||
sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
|
||||
}
|
||||
%End
|
||||
|
||||
QVector<QgsGeometry> asGeometryCollection() const;
|
||||
|
@ -202,6 +202,29 @@ and ``line2P2``.
|
||||
Returns the number of tangents (either 0 or 2).
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
static int circleCircleInnerTangents(
|
||||
const QgsPointXY ¢er1, double radius1, const QgsPointXY ¢er2, double radius2,
|
||||
QgsPointXY &line1P1 /Out/, QgsPointXY &line1P2 /Out/,
|
||||
QgsPointXY &line2P1 /Out/, QgsPointXY &line2P2 /Out/ );
|
||||
%Docstring
|
||||
Calculates the inner tangent points for two circles, centered at \a
|
||||
center1 and ``center2`` and with radii of ``radius1`` and ``radius2``
|
||||
respectively.
|
||||
|
||||
The inner tangent points correspond to the points at which the two lines
|
||||
which are drawn so that they are tangential to both circles and are
|
||||
crossing each other.
|
||||
|
||||
The first tangent line is described by the points
|
||||
stored in ``line1P1`` and ``line1P2``,
|
||||
and the second line is described by the points stored in ``line2P1``
|
||||
and ``line2P2``.
|
||||
|
||||
Returns the number of tangents (either 0 or 2).
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
static QgsPoint projectPointOnSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 );
|
||||
|
201
python/core/auto_generated/geometry/qgsquadrilateral.sip.in
Normal file
201
python/core/auto_generated/geometry/qgsquadrilateral.sip.in
Normal file
@ -0,0 +1,201 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/geometry/qgsquadrilateral.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsQuadrilateral
|
||||
{
|
||||
%Docstring
|
||||
Quadrilateral geometry type.
|
||||
A quadrilateral is a polygon with four edges (or sides) and four vertices or corners.
|
||||
This class allows the creation of simple quadrilateral (which does not self-intersect).
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsquadrilateral.h"
|
||||
%End
|
||||
public:
|
||||
QgsQuadrilateral();
|
||||
|
||||
QgsQuadrilateral( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, const QgsPoint &p4 );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral from four :py:class:`QgsPoint`.
|
||||
|
||||
:param p1: first point
|
||||
:param p2: second point
|
||||
:param p3: third point
|
||||
:param p4: fourth point
|
||||
|
||||
.. seealso:: :py:func:`setPoints`
|
||||
%End
|
||||
|
||||
explicit QgsQuadrilateral( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3, const QgsPointXY &p4 );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral from four :py:class:`QgsPointXY`.
|
||||
|
||||
:param p1: first point
|
||||
:param p2: second point
|
||||
:param p3: third point
|
||||
:param p4: fourth point
|
||||
|
||||
.. seealso:: :py:func:`setPoints`
|
||||
%End
|
||||
|
||||
|
||||
enum ConstructionOption
|
||||
{
|
||||
Distance,
|
||||
Projected,
|
||||
};
|
||||
|
||||
static QgsQuadrilateral rectangleFrom3Points( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, ConstructionOption mode );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral as a Rectangle from 3 points.
|
||||
In the case where one of the points is of type PointZ. The other points
|
||||
will also be of type Z, even if they are of type Point. In addition,
|
||||
the z used will be the one of the first point with a Z.
|
||||
This ensures consistency in point types and the ability to export to a
|
||||
Polygon or LineString.
|
||||
|
||||
:param p1: first point
|
||||
:param p2: second point
|
||||
:param p3: third point
|
||||
:param mode: Construction mode to construct the rectangle from 3 points
|
||||
|
||||
.. seealso:: ConstructionOption
|
||||
%End
|
||||
|
||||
static QgsQuadrilateral rectangleFromExtent( const QgsPoint &p1, const QgsPoint &p2 );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral as a rectangle from an extent, defined by
|
||||
two opposite corner points.
|
||||
Z is taken from point ``p1``.
|
||||
|
||||
:param p1: first point
|
||||
:param p2: second point
|
||||
%End
|
||||
|
||||
|
||||
static QgsQuadrilateral squareFromDiagonal( const QgsPoint &p1, const QgsPoint &p2 );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral as a square from a diagonal.
|
||||
Z is taken from point ``p1``.
|
||||
|
||||
:param p1: first point
|
||||
:param p2: second point
|
||||
%End
|
||||
|
||||
static QgsQuadrilateral rectangleFromCenterPoint( const QgsPoint ¢er, const QgsPoint &point );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral as a rectangle from center point ``center``
|
||||
and another point ``point``.
|
||||
Z is taken from ``center`` point.
|
||||
|
||||
:param center: center point
|
||||
:param point: corner point
|
||||
%End
|
||||
|
||||
static QgsQuadrilateral fromRectangle( const QgsRectangle &rectangle );
|
||||
%Docstring
|
||||
Construct a QgsQuadrilateral as a rectangle from a :py:class:`QgsRectangle`.
|
||||
|
||||
:param rectangle: rectangle
|
||||
%End
|
||||
|
||||
|
||||
bool equals( const QgsQuadrilateral &other, double epsilon = 4 * DBL_EPSILON ) const;
|
||||
%Docstring
|
||||
Compares two QgsQuadrilateral, allowing specification of the maximum allowable difference between points.
|
||||
|
||||
:param other: the QgsQuadrilateral to compare
|
||||
:param epsilon: the maximum difference allowed / tolerance
|
||||
%End
|
||||
bool operator==( const QgsQuadrilateral &other ) const;
|
||||
bool operator!=( const QgsQuadrilateral &other ) const;
|
||||
|
||||
bool isValid() const;
|
||||
%Docstring
|
||||
Convenient method to determine if a QgsQuadrilateral is valid.
|
||||
A QgsQuadrilateral must be simple (not self-intersecting) and
|
||||
cannot have collinear points.
|
||||
%End
|
||||
|
||||
enum Point
|
||||
{
|
||||
Point1,
|
||||
Point2,
|
||||
Point3,
|
||||
Point4,
|
||||
};
|
||||
|
||||
bool setPoint( const QgsPoint &newPoint, Point index );
|
||||
%Docstring
|
||||
Sets the point ``newPoint`` at the ``index``.
|
||||
Returns false if the QgsQuadrilateral is not valid.
|
||||
|
||||
.. seealso:: Point
|
||||
%End
|
||||
|
||||
bool setPoints( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &p3, const QgsPoint &p4 );
|
||||
%Docstring
|
||||
Set all points
|
||||
Returns false if the QgsQuadrilateral is not valid:
|
||||
- The points do not have the same type
|
||||
- The quadrilateral would have auto intersections
|
||||
- The quadrilateral has double points
|
||||
- The quadrilateral has collinear points
|
||||
%End
|
||||
|
||||
QgsPointSequence points() const;
|
||||
%Docstring
|
||||
Returns a list including the vertices of the quadrilateral.
|
||||
%End
|
||||
|
||||
QgsPolygon *toPolygon( bool force2D = false ) const /Factory/;
|
||||
%Docstring
|
||||
Returns the quadrilateral as a new polygon. Ownership is transferred to the caller.
|
||||
%End
|
||||
|
||||
QgsLineString *toLineString( bool force2D = false ) const /Factory/;
|
||||
%Docstring
|
||||
Returns the quadrilateral as a new linestring. Ownership is transferred to the caller.
|
||||
%End
|
||||
|
||||
QString toString( int pointPrecision = 17 ) const;
|
||||
%Docstring
|
||||
Returns a string representation of the quadrilateral.
|
||||
Members will be truncated to the specified precision.
|
||||
%End
|
||||
|
||||
double area() const;
|
||||
%Docstring
|
||||
Returns the area of the quadrilateral, or 0 if the quadrilateral is empty.
|
||||
%End
|
||||
|
||||
double perimeter() const;
|
||||
%Docstring
|
||||
Returns the perimeter of the quadrilateral, or 0 if the quadrilateral is empty.
|
||||
%End
|
||||
SIP_PYOBJECT __repr__();
|
||||
%MethodCode
|
||||
QString str = QStringLiteral( "<QgsQuadrilateral: %1>" ).arg( sipCpp->toString() );
|
||||
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
|
||||
%End
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/geometry/qgsquadrilateral.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -76,6 +76,7 @@ Default implementation does nothing. *
|
||||
|
||||
struct ItemContext
|
||||
{
|
||||
QgsRenderContext *context;
|
||||
QPainter *painter;
|
||||
QPointF point;
|
||||
double labelXOffset;
|
||||
|
@ -488,6 +488,9 @@ Returns the legend's renderer settings object.
|
||||
virtual void finalizeRestoreFromXml();
|
||||
|
||||
|
||||
virtual QgsExpressionContext createExpressionContext() const;
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -198,6 +198,8 @@ Sets the objects's property collection, used for data defined overrides.
|
||||
:param collection: property collection. Existing properties will be replaced.
|
||||
|
||||
.. seealso:: :py:func:`dataDefinedProperties`
|
||||
|
||||
.. seealso:: DataDefinedProperty
|
||||
%End
|
||||
|
||||
|
||||
|
@ -509,6 +509,30 @@ V3 ---- V4 ---- V6-----V8
|
||||
%Docstring
|
||||
Returns whether the faces are active for particular dataset
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
virtual bool persistDatasetGroup( const QString &path,
|
||||
const QgsMeshDatasetGroupMetadata &meta,
|
||||
const QVector<QgsMeshDataBlock> &datasetValues,
|
||||
const QVector<QgsMeshDataBlock> &datasetActive,
|
||||
const QVector<double> ×
|
||||
) = 0;
|
||||
%Docstring
|
||||
Creates a new dataset group from a data and
|
||||
persists it into a destination path
|
||||
|
||||
On success, the mesh's dataset group count is changed
|
||||
|
||||
:param path: destination path of the stored file
|
||||
:param meta: new group's metadata
|
||||
:param datasetValues: scalar/vector values for all datasets and all faces/vertices in the group
|
||||
:param datasetActive: active flag values for all datasets in the group. Empty array represents can be used
|
||||
when all faces are active
|
||||
:param times: times in hours for all datasets in the group
|
||||
|
||||
:return: true on failure, false on success
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
};
|
||||
|
@ -130,6 +130,8 @@ Returns the provider type for this layer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
QgsMeshRendererSettings rendererSettings() const;
|
||||
%Docstring
|
||||
Returns renderer settings
|
||||
|
@ -0,0 +1,59 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/mesh/qgsmeshlayerinterpolator.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%ModuleHeaderCode
|
||||
#include "qgsmeshlayerinterpolator.h"
|
||||
%End
|
||||
|
||||
|
||||
|
||||
|
||||
namespace QgsMeshUtils
|
||||
{
|
||||
|
||||
QgsRasterBlock *exportRasterBlock(
|
||||
const QgsMeshLayer &layer,
|
||||
const QgsMeshDatasetIndex &datasetIndex,
|
||||
const QgsCoordinateReferenceSystem &destinationCrs,
|
||||
const QgsCoordinateTransformContext &transformContext,
|
||||
double mapUnitsPerPixel,
|
||||
const QgsRectangle &extent,
|
||||
QgsRasterBlockFeedback *feedback = 0
|
||||
) /Factory/;
|
||||
%Docstring
|
||||
Exports mesh layer's dataset values as raster block
|
||||
|
||||
The function always fetches native mesh and dataset data
|
||||
from data provider and calculates triangular mesh
|
||||
|
||||
:param layer: mesh layer
|
||||
:param datasetIndex: index from layer defining group and dataset (time) to export
|
||||
:param destinationCrs: destination/map CRS. Used to create triangular mesh from native mesh
|
||||
:param transformContext: Transform context to transform layer CRS to destination CRS
|
||||
:param mapUnitsPerPixel: map units per pixel for block
|
||||
:param extent: extent of block in destination CRS
|
||||
:param feedback: optional raster feedback object for cancelation/preview
|
||||
|
||||
:return: raster block with Float.64 values. None on error
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/mesh/qgsmeshlayerinterpolator.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -133,6 +133,9 @@ Returns a double ``number``, rounded (as close as possible) to the specified num
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
double qgsPermissiveToDouble( QString string, bool &ok );
|
||||
%Docstring
|
||||
Converts a string to a double in a permissive way, e.g., allowing for incorrect
|
||||
|
@ -330,6 +330,8 @@ Sets the diagram's property collection, used for data defined overrides.
|
||||
|
||||
.. seealso:: :py:func:`dataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
@ -384,17 +384,17 @@ The ``interval`` parameter gives the maximum distance between points on the comp
|
||||
This argument is always specified in meters. A shorter distance results in a denser line,
|
||||
at the cost of extra computing time.
|
||||
|
||||
If the geodesic line crosses the international date line and ``breakLine`` is true, then
|
||||
the line will be split into two parts, broken at the date line. In this case the function
|
||||
will return two lines, corresponding to the portions at either side of the date line.
|
||||
If the geodesic line crosses the antimeridian (+/- 180 degrees longitude) and ``breakLine`` is true, then
|
||||
the line will be split into two parts, broken at the antimeridian. In this case the function
|
||||
will return two lines, corresponding to the portions at either side of the antimeridian.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
double latitudeGeodesicCrossesDateLine( const QgsPointXY &p1, const QgsPointXY &p2, double &fractionAlongLine /Out/ ) const;
|
||||
double latitudeGeodesicCrossesAntimeridian( const QgsPointXY &p1, const QgsPointXY &p2, double &fractionAlongLine /Out/ ) const;
|
||||
%Docstring
|
||||
Calculates the latitude at which the geodesic line joining ``p1`` and ``p2`` crosses
|
||||
the international date line (longitude +/- 180 degrees).
|
||||
the antimeridian (longitude +/- 180 degrees).
|
||||
|
||||
The ellipsoid settings defined on this QgsDistanceArea object will be used during the calculations.
|
||||
|
||||
@ -404,8 +404,37 @@ will also be in this same CRS.
|
||||
:param p1: Starting point, in ellipsoidCrs()
|
||||
:param p2: Ending point, in ellipsoidCrs()
|
||||
|
||||
:return: - the latitude at which the geodesic crosses the date line
|
||||
- fractionAlongLine: will be set to the fraction along the geodesic line joining ``p1`` to ``p2`` at which the date line crossing occurs.
|
||||
:return: - the latitude at which the geodesic crosses the antimeridian
|
||||
- fractionAlongLine: will be set to the fraction along the geodesic line joining ``p1`` to ``p2`` at which the antimeridian crossing occurs.
|
||||
|
||||
.. seealso:: :py:func:`splitGeometryAtAntimeridian`
|
||||
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
QgsGeometry splitGeometryAtAntimeridian( const QgsGeometry &geometry ) const;
|
||||
%Docstring
|
||||
Splits a (Multi)LineString ``geometry`` at the antimeridian (longitude +/- 180 degrees).
|
||||
The returned geometry will always be a multi-part geometry.
|
||||
|
||||
Whenever line segments in the input geometry cross the antimeridian, they will be
|
||||
split into two segments, with the latitude of the breakpoint being determined using a geodesic
|
||||
line connecting the points either side of this segment.
|
||||
|
||||
The ellipsoid settings defined on this QgsDistanceArea object will be used during the calculations.
|
||||
|
||||
``geometry`` must be in the sourceCrs() of this QgsDistanceArea object. The returned geometry
|
||||
will also be in this same CRS.
|
||||
|
||||
If ``geometry`` contains M or Z values, these will be linearly interpolated for the new vertices
|
||||
created at the antimeridian.
|
||||
|
||||
.. note::
|
||||
|
||||
Non-(Multi)LineString geometries will be returned unchanged.
|
||||
|
||||
.. seealso:: :py:func:`latitudeGeodesicCrossesAntimeridian`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
@ -341,6 +341,24 @@ Convenience function for setting a fields for the scope. Any existing
|
||||
fields set by the scope will be overwritten.
|
||||
|
||||
:param fields: fields for scope
|
||||
%End
|
||||
|
||||
void readXml( const QDomElement &element, const QgsReadWriteContext &context );
|
||||
%Docstring
|
||||
Reads scope variables from an XML element.
|
||||
|
||||
.. seealso:: :py:func:`writeXml`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
bool writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const;
|
||||
%Docstring
|
||||
Writes scope variables to an XML ``element``.
|
||||
|
||||
.. seealso:: :py:func:`readXml`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
};
|
||||
|
@ -34,7 +34,7 @@ Constructor for QgsLegendRenderer. The ownership of the legend model is not chan
|
||||
and the model must exist for the lifetime of this renderer.
|
||||
%End
|
||||
|
||||
QSizeF minimumSize();
|
||||
QSizeF minimumSize( QgsRenderContext *renderContext = 0 );
|
||||
%Docstring
|
||||
Runs the layout algorithm and returns the minimum size required for the legend.
|
||||
|
||||
|
@ -198,6 +198,17 @@ The ``scale`` value indicates the scale denominator, e.g. 1000.0 for a 1:1000 ma
|
||||
void setDpi( int dpi );
|
||||
|
||||
|
||||
|
||||
QStringList evaluateItemText( const QString &text, const QgsExpressionContext &context ) const;
|
||||
%Docstring
|
||||
Returns the actual text to render for a legend item, split into separate lines.
|
||||
|
||||
The expression ``context`` argument is used to correctly evaluated expressions contained
|
||||
within legend item text.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
QStringList splitStringForWrapping( const QString &stringToSplt ) const;
|
||||
%Docstring
|
||||
Splits a string using the wrap char taking into account handling empty
|
||||
|
@ -10,6 +10,51 @@
|
||||
|
||||
|
||||
|
||||
class QgsNetworkRequestParameters
|
||||
{
|
||||
%Docstring
|
||||
Encapsulates parameters and properties of a network request.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsnetworkaccessmanager.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsNetworkRequestParameters();
|
||||
%Docstring
|
||||
Default constructor.
|
||||
%End
|
||||
|
||||
QgsNetworkRequestParameters( QNetworkAccessManager::Operation operation,
|
||||
const QNetworkRequest &request );
|
||||
%Docstring
|
||||
Constructor for QgsNetworkRequestParameters, with the specified network
|
||||
``operation`` and original ``request``.
|
||||
%End
|
||||
|
||||
QNetworkAccessManager::Operation operation() const;
|
||||
%Docstring
|
||||
Returns the request operation, e.g. GET or POST.
|
||||
%End
|
||||
|
||||
QNetworkRequest request() const;
|
||||
%Docstring
|
||||
Returns the network request.
|
||||
|
||||
This is the original network request sent to :py:class:`QgsNetworkAccessManager`, but with QGIS specific
|
||||
configuration options such as proxy handling and SSL exceptions applied.
|
||||
%End
|
||||
|
||||
QString originatingThreadId() const;
|
||||
%Docstring
|
||||
Returns a string identifying the thread which the request originated from.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
class QgsNetworkAccessManager : QNetworkAccessManager
|
||||
{
|
||||
%Docstring
|
||||
@ -111,6 +156,18 @@ Returns whether the system proxy should be used
|
||||
|
||||
signals:
|
||||
void requestAboutToBeCreated( QNetworkAccessManager::Operation, const QNetworkRequest &, QIODevice * );
|
||||
|
||||
void requestAboutToBeCreated( QgsNetworkRequestParameters request );
|
||||
%Docstring
|
||||
Emitted when a network request is about to be created.
|
||||
|
||||
This signal is propagated to the main thread QgsNetworkAccessManager instance, so it is necessary
|
||||
only to connect to the main thread's signal in order to receive notifications about requests
|
||||
created in any thread.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
void requestCreated( QNetworkReply * );
|
||||
void requestTimedOut( QNetworkReply * );
|
||||
|
||||
|
@ -432,6 +432,8 @@ Sets the label's property collection, used for data defined overrides.
|
||||
|
||||
.. seealso:: :py:func:`dataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
@ -1003,6 +1003,15 @@ in the project. The removeMapLayer(), removeMapLayers() calls do not block remov
|
||||
.. deprecated:: since QGIS 3.4 use QgsMapLayer.setFlags() instead
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
void setProjectColors( const QgsNamedColorList &colors );
|
||||
%Docstring
|
||||
Sets the ``colors`` for the project's color scheme (see QgsProjectColorScheme).
|
||||
|
||||
.. seealso:: :py:func:`projectColorsChanged`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
void generateTsFile( const QString &locale );
|
||||
@ -1230,6 +1239,15 @@ Emitted when the project's metadata is changed.
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
void projectColorsChanged();
|
||||
%Docstring
|
||||
Emitted whenever the project's color scheme has been changed.
|
||||
|
||||
.. seealso:: :py:func:`setProjectColors`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
|
||||
void layersWillBeRemoved( const QStringList &layerIds );
|
||||
%Docstring
|
||||
|
@ -311,6 +311,13 @@ Returns true if preparation was successful.
|
||||
%Docstring
|
||||
Returns the set of any fields referenced by the property for a specified
|
||||
expression context.
|
||||
%End
|
||||
|
||||
bool isProjectColor() const;
|
||||
%Docstring
|
||||
Returns true if the property is set to a linked project color.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
QVariant value( const QgsExpressionContext &context, const QVariant &defaultValue = QVariant(), bool *ok /Out/ = 0 ) const;
|
||||
|
@ -309,6 +309,21 @@ A grouped map of multiple QgsProperty objects, each referenced by a integer key
|
||||
Properties within a collection are referenced by an integer key. This is done to avoid the cost of
|
||||
string creation and comparisons which would be required by a string key. The intended use case is that
|
||||
a context specific enum is cast to int and used for the key value.
|
||||
Examples of such enums are :
|
||||
|
||||
.. seealso:: :py:func:`QgsLayoutObject.DataDefinedProperty`
|
||||
|
||||
.. seealso:: :py:func:`QgsSymbolLayer.Property`
|
||||
|
||||
.. seealso:: :py:func:`QgsPalLabeling.Property`
|
||||
|
||||
.. seealso:: :py:func:`QgsAbstract3DSymbol.Property`
|
||||
|
||||
.. seealso:: :py:func:`QgsDiagramLayerSettings.Property`
|
||||
|
||||
.. seealso:: :py:func:`QgsPalLayerSettings.Property`
|
||||
|
||||
.. seealso:: :py:func:`QgsWidgetWrapper.Property`
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
@ -119,6 +119,19 @@ Will throw a QgsException if called on a vector with length of 0.
|
||||
|
||||
bool operator!=( QgsVector other ) const;
|
||||
|
||||
|
||||
QString toString( int precision = 17 ) const;
|
||||
%Docstring
|
||||
Returns a string representation of the vector.
|
||||
Members will be truncated to the specified ``precision``.
|
||||
%End
|
||||
|
||||
SIP_PYOBJECT __repr__();
|
||||
%MethodCode
|
||||
QString str = QStringLiteral( "<QgsVector: %1>" ).arg( sipCpp->toString() );
|
||||
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -89,7 +89,27 @@ Returns the length of the vector
|
||||
Normalizes the current vector in place.
|
||||
%End
|
||||
|
||||
double distance( const QgsVector3D &other ) const;
|
||||
%Docstring
|
||||
Returns the distance with the ``other`` :py:class:`QgsVector3`
|
||||
%End
|
||||
|
||||
static QgsVector3D perpendicularPoint( const QgsVector3D &v1, const QgsVector3D &v2, const QgsVector3D &vp );
|
||||
%Docstring
|
||||
Returns the perpendicular point of vector ``vp`` from [``v1`` - ``v2``]
|
||||
%End
|
||||
|
||||
QString toString( int precision = 17 ) const;
|
||||
%Docstring
|
||||
Returns a string representation of the 3D vector.
|
||||
Members will be truncated to the specified ``precision``.
|
||||
%End
|
||||
|
||||
SIP_PYOBJECT __repr__();
|
||||
%MethodCode
|
||||
QString str = QStringLiteral( "<QgsVector3D: %1>" ).arg( sipCpp->toString() );
|
||||
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
|
||||
%End
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -153,20 +153,26 @@ returned value is undefined.
|
||||
:param row: row index
|
||||
:param column: column index
|
||||
|
||||
:return: value *
|
||||
:return: value
|
||||
|
||||
.. seealso:: :py:func:`valueAndNoData`
|
||||
%End
|
||||
|
||||
|
||||
double value( qgssize index ) const;
|
||||
%Docstring
|
||||
Read a single value if type of block is numeric. If type is color,
|
||||
Reads a single value if type of block is numeric. If type is color,
|
||||
returned value is undefined.
|
||||
|
||||
:param index: data matrix index (long type in Python)
|
||||
|
||||
:return: value *
|
||||
:return: value
|
||||
|
||||
.. seealso:: :py:func:`valueAndNoData`
|
||||
%End
|
||||
|
||||
|
||||
|
||||
QRgb color( int row, int column ) const;
|
||||
%Docstring
|
||||
Read a single color
|
||||
@ -188,12 +194,14 @@ Read a single value
|
||||
|
||||
bool isNoData( int row, int column ) const;
|
||||
%Docstring
|
||||
Check if value at position is no data
|
||||
Checks if value at position is no data
|
||||
|
||||
:param row: row index
|
||||
:param column: column index
|
||||
|
||||
:return: true if value is no data *
|
||||
:return: true if value is no data
|
||||
|
||||
.. seealso:: :py:func:`valueAndNoData`
|
||||
%End
|
||||
|
||||
bool isNoData( qgssize row, qgssize column ) const;
|
||||
@ -203,7 +211,9 @@ Check if value at position is no data
|
||||
:param row: row index
|
||||
:param column: column index
|
||||
|
||||
:return: true if value is no data *
|
||||
:return: true if value is no data
|
||||
|
||||
.. seealso:: :py:func:`valueAndNoData`
|
||||
%End
|
||||
|
||||
bool isNoData( qgssize index ) const;
|
||||
@ -212,7 +222,9 @@ Check if value at position is no data
|
||||
|
||||
:param index: data matrix index (long type in Python)
|
||||
|
||||
:return: true if value is no data *
|
||||
:return: true if value is no data
|
||||
|
||||
.. seealso:: :py:func:`valueAndNoData`
|
||||
%End
|
||||
|
||||
bool setValue( int row, int column, double value );
|
||||
@ -441,6 +453,7 @@ Returns the height (number of rows) of the raster block.
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
@ -33,6 +33,28 @@ Start reading of raster band. Raster data can then be retrieved by calling readN
|
||||
:param nRows: number of rows
|
||||
:param extent: area to read
|
||||
:param feedback: optional raster feedback object for cancelation/preview. Added in QGIS 3.0.
|
||||
%End
|
||||
|
||||
bool next( int bandNumber, int &columns /Out/, int &rows /Out/, int &topLeftColumn /Out/, int &topLeftRow /Out/, QgsRectangle &blockExtent /Out/ );
|
||||
%Docstring
|
||||
Fetches details of the next part of the raster data. This method does NOT actually fetch the raster
|
||||
data itself, rather it calculates and iterates over the details of the raster alone.
|
||||
|
||||
It's useful for iterating over several layers using a target "reference" layer. E.g. summing
|
||||
the pixels in n rasters whilst aligning the result to a reference layer which is not being summed.
|
||||
|
||||
Note that calling this method also advances the iterator, just like calling readNextRasterPart().
|
||||
|
||||
:param bandNumber: band to read
|
||||
:param rows: number of rows on output device
|
||||
:param topLeftColumn: top left column
|
||||
:param topLeftRow: top left row
|
||||
:param blockExtent: exact extent of returned raster block
|
||||
|
||||
:return: - false if the last part was already returned
|
||||
- columns: number of columns on output device
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
bool readNextRasterPart( int bandNumber,
|
||||
|
@ -43,6 +43,8 @@ Create a new QgsArrowSymbolLayer
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
double arrowWidth() const;
|
||||
%Docstring
|
||||
|
@ -734,6 +734,8 @@ Returns the stroke width map unit scale.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -1563,6 +1565,8 @@ Returns the map unit scale for the pattern's line offset.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -1727,6 +1731,8 @@ Returns the units for the vertical displacement between rows in the pattern.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
virtual void setColor( const QColor &c );
|
||||
|
||||
virtual QColor color() const;
|
||||
@ -1798,6 +1804,8 @@ class QgsCentroidFillSymbolLayer : QgsFillSymbolLayer
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
void setPointOnSurface( bool pointOnSurface );
|
||||
bool pointOnSurface() const;
|
||||
|
@ -70,6 +70,8 @@ Gets the expression to generate this geometry.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
virtual bool isCompatibleWithSymbol( QgsSymbol *symbol ) const;
|
||||
|
||||
|
@ -378,6 +378,8 @@ Returns the units for the interval between markers.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
virtual void setDataDefinedProperty( QgsSymbolLayer::Property key, const QgsProperty &property );
|
||||
|
||||
|
@ -505,6 +505,8 @@ Creates a new QgsFilledMarkerSymbolLayer.
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
virtual void setColor( const QColor &c );
|
||||
|
||||
virtual QColor color() const;
|
||||
|
@ -459,6 +459,16 @@ Exports the style as a XML file
|
||||
bool importXml( const QString &filename );
|
||||
%Docstring
|
||||
Imports the symbols and colorramps into the default style database from the given XML file
|
||||
%End
|
||||
|
||||
static bool isXmlStyleFile( const QString &path );
|
||||
%Docstring
|
||||
Tests if the file at ``path`` is a QGIS style XML file.
|
||||
|
||||
This method samples only the first line in the file, so is safe to call on
|
||||
large xml files.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
@ -300,6 +300,8 @@ will be overwritten.
|
||||
|
||||
.. seealso:: :py:func:`dataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
@ -386,6 +388,8 @@ Returns a reference to the symbol layer's property collection, used for data def
|
||||
|
||||
.. seealso:: :py:func:`setDataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
@ -399,6 +403,13 @@ Sets the symbol layer's property collection, used for data defined overrides.
|
||||
.. seealso:: :py:func:`properties`
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
%Docstring
|
||||
Returns true if the symbol layer (or any of its sub-symbols) contains data defined properties.
|
||||
|
||||
.. versionadded:: 3.4.5
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
@ -74,6 +74,8 @@ A symbol layer class for displaying displacement arrows based on point layer att
|
||||
|
||||
virtual QSet<QString> usedAttributes( const QgsRenderContext &context ) const;
|
||||
|
||||
virtual bool hasDataDefinedProperties() const;
|
||||
|
||||
|
||||
void setXAttribute( const QString &attribute );
|
||||
QString xAttribute() const;
|
||||
|
@ -41,8 +41,7 @@ result will be communicated to users, but not prevent them from proceeding.
|
||||
|
||||
};
|
||||
|
||||
|
||||
class QgsAbstractValidityCheck : QObject
|
||||
class QgsAbstractValidityCheck
|
||||
{
|
||||
%Docstring
|
||||
Abstract base class for individual validity checks.
|
||||
@ -77,6 +76,8 @@ Checks must be registered in the application's :py:class:`QgsValidityCheckRegist
|
||||
TypeUserCheck,
|
||||
};
|
||||
|
||||
virtual ~QgsAbstractValidityCheck();
|
||||
|
||||
virtual QgsAbstractValidityCheck *create() const = 0 /Factory/;
|
||||
%Docstring
|
||||
Creates a new instance of the check and returns it.
|
||||
@ -126,9 +127,6 @@ The ``context`` argument gives the wider in which the check is being run.
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
@ -236,6 +236,7 @@
|
||||
%Include auto_generated/raster/qgssinglebandgrayrenderer.sip
|
||||
%Include auto_generated/raster/qgssinglebandpseudocolorrenderer.sip
|
||||
%Include auto_generated/raster/qgshillshaderenderer.sip
|
||||
%Include auto_generated/mesh/qgsmeshlayerinterpolator.sip
|
||||
%Include auto_generated/mesh/qgsmeshrenderersettings.sip
|
||||
%Include auto_generated/scalebar/qgsdoubleboxscalebarrenderer.sip
|
||||
%Include auto_generated/scalebar/qgsnumericscalebarrenderer.sip
|
||||
@ -288,6 +289,7 @@
|
||||
%Include auto_generated/geometry/qgsmultipolygon.sip
|
||||
%Include auto_generated/geometry/qgsmultisurface.sip
|
||||
%Include auto_generated/geometry/qgspolygon.sip
|
||||
%Include auto_generated/geometry/qgsquadrilateral.sip
|
||||
%Include auto_generated/geometry/qgsrectangle.sip
|
||||
%Include auto_generated/geometry/qgsreferencedgeometry.sip
|
||||
%Include auto_generated/geometry/qgsregularpolygon.sip
|
||||
|
@ -144,6 +144,8 @@ Returns a reference to the editor widget's property collection, used for data de
|
||||
|
||||
.. seealso:: :py:func:`setDataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
@ -155,6 +157,8 @@ Sets the editor widget's property collection, used for data defined overrides.
|
||||
|
||||
.. seealso:: :py:func:`dataDefinedProperties`
|
||||
|
||||
.. seealso:: Property
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
@ -303,6 +303,42 @@ that are shown in the button's drop-down menu.
|
||||
swatch grids are hidden from the button's drop-down menu.
|
||||
|
||||
.. seealso:: :py:func:`setColorSchemeRegistry`
|
||||
%End
|
||||
|
||||
void linkToProjectColor( const QString &name );
|
||||
%Docstring
|
||||
Sets the button to link to an existing project color, by color ``name``.
|
||||
|
||||
This changes the behavior of the button to a "linked" mode. Specifically,
|
||||
the button will show the linked color and respond to changes in the project
|
||||
color scheme by refreshing the displayed color automatically. Additionally,
|
||||
the button's menu will show items specific to linked color mode, including
|
||||
an option to "unlink" from the project color.
|
||||
|
||||
.. seealso:: :py:func:`linkedProjectColorName`
|
||||
|
||||
.. seealso:: :py:func:`unlink`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
QString linkedProjectColorName() const;
|
||||
%Docstring
|
||||
Returns the linked project color name, if set.
|
||||
|
||||
.. seealso:: :py:func:`linkToProjectColor`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
static QPixmap createMenuIcon( const QColor &color, bool showChecks = true );
|
||||
%Docstring
|
||||
Creates an icon for displaying a ``color`` in a drop-down menu.
|
||||
|
||||
If ``showChecks`` set to true, then a checkboard pattern will be shown behind
|
||||
semi-transparent colors.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
public slots:
|
||||
@ -380,6 +416,17 @@ Sets color to null.
|
||||
.. seealso:: :py:func:`setToNoColor`
|
||||
|
||||
.. versionadded:: 2.16
|
||||
%End
|
||||
|
||||
void unlink();
|
||||
%Docstring
|
||||
Unlinks the button from a project color.
|
||||
|
||||
.. seealso:: :py:func:`unlinked`
|
||||
|
||||
.. seealso:: :py:func:`linkToProjectColor`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
signals:
|
||||
@ -401,6 +448,18 @@ Emitted when the button is clicked, if the button's behavior is set to SignalOnl
|
||||
.. seealso:: :py:func:`setBehavior`
|
||||
|
||||
.. seealso:: :py:func:`behavior`
|
||||
%End
|
||||
|
||||
void unlinked();
|
||||
%Docstring
|
||||
Emitted when the color is unlinked, e.g. when it was previously set to link
|
||||
to a project color and is now no longer linked.
|
||||
|
||||
.. seealso:: :py:func:`unlink`
|
||||
|
||||
.. seealso:: :py:func:`linkToProjectColor`
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
@ -39,6 +39,8 @@ Logs a ``message`` to the viewer.
|
||||
|
||||
virtual void reject();
|
||||
|
||||
virtual bool eventFilter( QObject *obj, QEvent *ev );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -31,13 +31,14 @@ for added panels.
|
||||
:param parent:
|
||||
%End
|
||||
|
||||
void setMainPanel( QgsPanelWidget *panel );
|
||||
void setMainPanel( QgsPanelWidget *panel /Transfer/ );
|
||||
%Docstring
|
||||
Adds the main panel widget to the stack and selects it for the user
|
||||
The main widget can not be closed and only the showPanel signal is attached
|
||||
Sets the main ``panel`` widget for the stack and selects it for the user.
|
||||
|
||||
The main widget cannot be closed and only the showPanel signal is attached
|
||||
to handle children widget opening panels.
|
||||
|
||||
:param panel: The panel to set as the first widget in the stack.
|
||||
Ownership of ``panel`` is transferred to the stack.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -59,7 +60,7 @@ and doesn't display a back button.
|
||||
.. seealso:: :py:func:`setMainPanel`
|
||||
%End
|
||||
|
||||
QgsPanelWidget *takeMainPanel();
|
||||
QgsPanelWidget *takeMainPanel() /TransferBack/;
|
||||
%Docstring
|
||||
Removes the main panel widget from the stack and transfers ownsership to the
|
||||
caller.
|
||||
|
@ -40,7 +40,6 @@ Constructor for QgsPropertyOverrideButton.
|
||||
:param layer: associated vector layer
|
||||
%End
|
||||
|
||||
|
||||
void init( int propertyKey,
|
||||
const QgsProperty &property,
|
||||
const QgsPropertiesDefinition &definitions,
|
||||
@ -195,6 +194,17 @@ Register a sibling ``widget`` (line edit, text edit) that will receive the prope
|
||||
%Docstring
|
||||
Register an expression context generator class that will be used to retrieve
|
||||
an expression context for the button when required.
|
||||
%End
|
||||
|
||||
void registerLinkedWidget( QWidget *widget );
|
||||
%Docstring
|
||||
Registers a ``widget`` which is linked to this button. The meaning of linked widgets
|
||||
depends on the property type, and the type of linked widget.
|
||||
|
||||
For color properties, linking a QgsColorButton allows the color button to correctly
|
||||
reflect the status of the property when it's set to follow a project color.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
void updateFieldLists();
|
||||
@ -212,6 +222,12 @@ Updates list of fields.
|
||||
Set whether the current property override definition is to be used
|
||||
%End
|
||||
|
||||
|
||||
|
||||
void aboutToShowMenu();
|
||||
void menuActionTriggered( QAction *action );
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
void changed();
|
||||
@ -235,7 +251,6 @@ Emitted when creating a new auxiliary field
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsStyleManagerDialog : QDialog
|
||||
{
|
||||
%Docstring
|
||||
@ -22,7 +23,8 @@ A dialog allowing users to customize and populate a QgsStyle.
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsStyleManagerDialog( QgsStyle *style, QWidget *parent /TransferThis/ = 0, Qt::WindowFlags flags = Qt::WindowFlags() );
|
||||
QgsStyleManagerDialog( QgsStyle *style, QWidget *parent /TransferThis/ = 0, Qt::WindowFlags flags = Qt::WindowFlags(),
|
||||
bool readOnly = false );
|
||||
%Docstring
|
||||
Constructor for QgsStyleManagerDialog, with the specified ``parent`` widget and window ``flags``.
|
||||
|
||||
@ -35,10 +37,36 @@ The ``style`` object must last for the lifetime of the dialog.
|
||||
QString RampType = QString() );
|
||||
%Docstring
|
||||
Opens the add color ramp dialog, returning the new color ramp's name if the ramp has been added.
|
||||
%End
|
||||
|
||||
void setFavoritesGroupVisible( bool show );
|
||||
%Docstring
|
||||
Sets whether the favorites group should be shown. The default is to show the group.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
void setSmartGroupsVisible( bool show );
|
||||
%Docstring
|
||||
Sets whether smart groups should be shown. The default is to show the groups.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
void setBaseStyleName( const QString &name );
|
||||
%Docstring
|
||||
Sets the base ``name`` for the style, which is used by the dialog to reflect the
|
||||
original style/XML file name.
|
||||
|
||||
``name`` should be stripped of any extensions and folder information, e.g. "transport_styles",
|
||||
not "d:/stuff/transport_styles.xml".
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
void activate();
|
||||
%Docstring
|
||||
Raises, unminimizes and activates this window
|
||||
@ -47,69 +75,132 @@ Raises, unminimizes and activates this window
|
||||
%End
|
||||
|
||||
void addItem();
|
||||
%Docstring
|
||||
Triggers the dialog for adding a new item, based on the currently
|
||||
selected item type tab.
|
||||
%End
|
||||
|
||||
void editItem();
|
||||
%Docstring
|
||||
Triggers the dialog for editing the current item.
|
||||
%End
|
||||
|
||||
void removeItem();
|
||||
%Docstring
|
||||
Removes the current selected item.
|
||||
%End
|
||||
|
||||
void exportItemsSVG();
|
||||
%Docstring
|
||||
Triggers the dialog to export selected items as SVG files.
|
||||
|
||||
.. seealso:: :py:func:`exportItemsPNG`
|
||||
|
||||
.. seealso:: :py:func:`exportSelectedItemsImages`
|
||||
%End
|
||||
|
||||
void exportItemsPNG();
|
||||
%Docstring
|
||||
Triggers the dialog to export selected items as PNG files.
|
||||
|
||||
.. seealso:: :py:func:`exportItemsSVG`
|
||||
|
||||
.. seealso:: :py:func:`exportSelectedItemsImages`
|
||||
%End
|
||||
|
||||
void exportSelectedItemsImages( const QString &dir, const QString &format, QSize size );
|
||||
%Docstring
|
||||
Triggers the dialog to export selected items as images of the specified ``format`` and ``size``.
|
||||
|
||||
.. seealso:: :py:func:`exportItemsSVG`
|
||||
|
||||
.. seealso:: :py:func:`exportItemsPNG`
|
||||
%End
|
||||
|
||||
void exportItems();
|
||||
%Docstring
|
||||
Triggers the dialog to export items.
|
||||
|
||||
.. seealso:: :py:func:`importItems`
|
||||
%End
|
||||
|
||||
void importItems();
|
||||
%Docstring
|
||||
Triggers the dialog to import items.
|
||||
|
||||
.. seealso:: :py:func:`exportItems`
|
||||
%End
|
||||
|
||||
void populateList();
|
||||
%Docstring
|
||||
adds symbols of some type to list
|
||||
Refreshes the list of items.
|
||||
%End
|
||||
|
||||
void onFinished();
|
||||
%Docstring
|
||||
called when the dialog is going to be closed
|
||||
Called when the dialog is going to be closed.
|
||||
%End
|
||||
|
||||
void onClose();
|
||||
%Docstring
|
||||
Close the dialog
|
||||
Closes the dialog
|
||||
%End
|
||||
|
||||
void showHelp();
|
||||
%Docstring
|
||||
Open the associated help
|
||||
Opens the associated help
|
||||
%End
|
||||
|
||||
void itemChanged( QStandardItem *item );
|
||||
void itemChanged( QStandardItem *item ) /Deprecated/;
|
||||
%Docstring
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void groupChanged( const QModelIndex & );
|
||||
void groupRenamed( QStandardItem * );
|
||||
%Docstring
|
||||
Trigerred when the current group (or tag) is changed.
|
||||
%End
|
||||
|
||||
void groupRenamed( QStandardItem *item );
|
||||
%Docstring
|
||||
Triggered when a group ``item`` is renamed.
|
||||
%End
|
||||
|
||||
int addTag();
|
||||
%Docstring
|
||||
add a tag
|
||||
Triggers the dialog to add a new tag.
|
||||
%End
|
||||
|
||||
int addSmartgroup();
|
||||
%Docstring
|
||||
add a smartgroup
|
||||
Triggers the dialog to add a new smart group.
|
||||
%End
|
||||
|
||||
void removeGroup();
|
||||
%Docstring
|
||||
remove a tag or smartgroup
|
||||
Removes the selected tag or smartgroup.
|
||||
%End
|
||||
|
||||
void tagSymbolsAction();
|
||||
%Docstring
|
||||
carry out symbol tagging using check boxes
|
||||
Toggles the interactive item tagging mode.
|
||||
%End
|
||||
|
||||
void editSmartgroupAction();
|
||||
%Docstring
|
||||
edit the selected smart group
|
||||
Triggers the dialog for editing the selected smart group.
|
||||
%End
|
||||
|
||||
void regrouped( QStandardItem * );
|
||||
void regrouped( QStandardItem * ) /Deprecated/;
|
||||
%Docstring
|
||||
symbol changed from one group
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void filterSymbols( const QString & );
|
||||
void filterSymbols( const QString &filter );
|
||||
%Docstring
|
||||
filter the symbols based on input search term
|
||||
Sets the ``filter`` string to filter symbols by.
|
||||
%End
|
||||
|
||||
void symbolSelected( const QModelIndex & );
|
||||
@ -153,28 +244,36 @@ Remove all tags from selected symbols
|
||||
|
||||
protected:
|
||||
|
||||
void populateTypes();
|
||||
void populateTypes() /Deprecated/;
|
||||
%Docstring
|
||||
populate combo box with known style items (symbols, color ramps)
|
||||
Populate combo box with known style items (symbols, color ramps).
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void populateGroups();
|
||||
%Docstring
|
||||
populate the groups
|
||||
%End
|
||||
void setSymbolsChecked( const QStringList & );
|
||||
|
||||
void setSymbolsChecked( const QStringList & ) /Deprecated/;
|
||||
%Docstring
|
||||
to set symbols checked when in editing mode
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void populateSymbols( const QStringList &symbolNames, bool checkable = false );
|
||||
void populateSymbols( const QStringList &symbolNames, bool checkable = false ) /Deprecated/;
|
||||
%Docstring
|
||||
populate list view with symbols of the current type with the given names
|
||||
Populates the list view with symbols of the current type with the given names.
|
||||
|
||||
.. deprecated:: No longer required in QGIS 3.6, as the model is updated live. Has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void populateColorRamps( const QStringList &colorRamps, bool checkable = false );
|
||||
void populateColorRamps( const QStringList &colorRamps, bool checkable = false ) /Deprecated/;
|
||||
%Docstring
|
||||
populate list view with color ramps
|
||||
Populates the list view with color ramps of the current type with the given names.
|
||||
|
||||
.. deprecated:: No longer required in QGIS 3.6, as the model is updated live. Has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
int currentItemType();
|
||||
@ -192,8 +291,17 @@ add a new color ramp to style
|
||||
bool editSymbol();
|
||||
bool editColorRamp();
|
||||
|
||||
bool removeSymbol();
|
||||
bool removeColorRamp();
|
||||
bool removeSymbol() /Deprecated/;
|
||||
%Docstring
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
bool removeColorRamp() /Deprecated/;
|
||||
%Docstring
|
||||
|
||||
.. deprecated:: in QGIS 3.6 - has no effect and will be removed in QGIS 4.0
|
||||
%End
|
||||
|
||||
void enableSymbolInputs( bool );
|
||||
%Docstring
|
||||
|
@ -465,6 +465,8 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
self._execute(c, sql)
|
||||
self._commit()
|
||||
|
||||
return True
|
||||
|
||||
def emptyTable(self, table):
|
||||
""" delete all rows from table """
|
||||
if self.isRasterTable(table):
|
||||
@ -494,6 +496,7 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
self._execute(c, sql)
|
||||
|
||||
self._commit()
|
||||
return True
|
||||
|
||||
def moveTable(self, table, new_table, new_schema=None):
|
||||
return self.renameTable(table, new_table)
|
||||
@ -571,7 +574,16 @@ class SpatiaLiteDBConnector(DBConnector):
|
||||
def addTableColumn(self, table, field_def):
|
||||
""" add a column to table """
|
||||
sql = u"ALTER TABLE %s ADD %s" % (self.quoteId(table), field_def)
|
||||
self._execute_and_commit(sql)
|
||||
self._execute(None, sql)
|
||||
|
||||
sql = u"SELECT InvalidateLayerStatistics(%s)" % (self.quoteId(table))
|
||||
self._execute(None, sql)
|
||||
|
||||
sql = u"SELECT UpdateLayerStatistics(%s)" % (self.quoteId(table))
|
||||
self._execute(None, sql)
|
||||
|
||||
self._commit()
|
||||
return True
|
||||
|
||||
def deleteTableColumn(self, table, column):
|
||||
""" delete column from a table """
|
||||
|
@ -39,6 +39,7 @@ from qgis.core import (QgsProcessingAlgorithm,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterRasterDestination,
|
||||
QgsProcessingParameterCrs,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessingOutputLayerDefinition,
|
||||
QgsProcessingUtils)
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
@ -57,6 +58,7 @@ class buildvrt(GdalAlgorithm):
|
||||
ADD_ALPHA = 'ADD_ALPHA'
|
||||
ASSIGN_CRS = 'ASSIGN_CRS'
|
||||
RESAMPLING = 'RESAMPLING'
|
||||
SRC_NODATA = 'SRC_NODATA'
|
||||
|
||||
RESOLUTION_OPTIONS = ['average', 'highest', 'lowest']
|
||||
RESAMPLING_OPTIONS = ['nearest', 'bilinear', 'cubic', 'cubicspline', 'lanczos', 'average', 'mode']
|
||||
@ -82,38 +84,45 @@ class buildvrt(GdalAlgorithm):
|
||||
return 'vrt'
|
||||
|
||||
self.addParameter(QgsProcessingParameterMultipleLayers(self.INPUT,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Input layers'),
|
||||
self.tr('Input layers'),
|
||||
QgsProcessing.TypeRaster))
|
||||
self.addParameter(QgsProcessingParameterEnum(self.RESOLUTION,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Resolution'),
|
||||
self.tr('Resolution'),
|
||||
options=self.RESOLUTION_OPTIONS,
|
||||
defaultValue=0))
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.SEPARATE,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Place each input file into a separate band'),
|
||||
self.tr('Place each input file into a separate band'),
|
||||
defaultValue=True))
|
||||
self.addParameter(QgsProcessingParameterBoolean(self.PROJ_DIFFERENCE,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Allow projection difference'),
|
||||
self.tr('Allow projection difference'),
|
||||
defaultValue=False))
|
||||
|
||||
add_alpha_param = QgsProcessingParameterBoolean(self.ADD_ALPHA,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Add alpha mask band to VRT when source raster has none'),
|
||||
self.tr('Add alpha mask band to VRT when source raster has none'),
|
||||
defaultValue=False)
|
||||
add_alpha_param.setFlags(add_alpha_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(add_alpha_param)
|
||||
|
||||
assign_crs = QgsProcessingParameterCrs(self.ASSIGN_CRS,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Override projection for the output file'),
|
||||
self.tr('Override projection for the output file'),
|
||||
defaultValue=None, optional=True)
|
||||
assign_crs.setFlags(assign_crs.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(assign_crs)
|
||||
|
||||
resampling = QgsProcessingParameterEnum(self.RESAMPLING,
|
||||
QCoreApplication.translate("ParameterVrtDestination", 'Resampling algorithm'),
|
||||
self.tr('Resampling algorithm'),
|
||||
options=self.RESAMPLING_OPTIONS,
|
||||
defaultValue=0)
|
||||
resampling.setFlags(resampling.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(resampling)
|
||||
|
||||
src_nodata_param = QgsProcessingParameterString(self.SRC_NODATA,
|
||||
self.tr('Nodata value(s) for input bands (space separated)'),
|
||||
defaultValue=None,
|
||||
optional=True)
|
||||
src_nodata_param.setFlags(src_nodata_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(src_nodata_param)
|
||||
|
||||
self.addParameter(ParameterVrtDestination(self.OUTPUT, QCoreApplication.translate("ParameterVrtDestination", 'Virtual')))
|
||||
|
||||
def name(self):
|
||||
@ -151,6 +160,10 @@ class buildvrt(GdalAlgorithm):
|
||||
arguments.append('-r')
|
||||
arguments.append(self.RESAMPLING_OPTIONS[self.parameterAsEnum(parameters, self.RESAMPLING, context)])
|
||||
|
||||
if self.SRC_NODATA in parameters and parameters[self.SRC_NODATA] not in (None, ''):
|
||||
nodata = self.parameterAsString(parameters, self.SRC_NODATA, context)
|
||||
arguments.append('-srcnodata "{}"'.format(nodata))
|
||||
|
||||
# Always write input files to a text file in case there are many of them and the
|
||||
# length of the command will be longer then allowed in command prompt
|
||||
list_file = GdalUtils.writeLayerParameterToTextFile(filename='buildvrtInputFiles.txt', alg=self, parameters=parameters, parameter_name=self.INPUT, context=context, executing=executing, quote=False)
|
||||
|
@ -127,7 +127,6 @@ class rasterize(GdalAlgorithm):
|
||||
init_param = QgsProcessingParameterNumber(self.INIT,
|
||||
self.tr('Pre-initialize the output image with value'),
|
||||
type=QgsProcessingParameterNumber.Double,
|
||||
defaultValue=0.0,
|
||||
optional=True)
|
||||
init_param.setFlags(init_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(init_param)
|
||||
@ -181,8 +180,8 @@ class rasterize(GdalAlgorithm):
|
||||
arguments.append(self.parameterAsDouble(parameters, self.WIDTH, context))
|
||||
arguments.append(self.parameterAsDouble(parameters, self.HEIGHT, context))
|
||||
|
||||
initValue = self.parameterAsDouble(parameters, self.INIT, context)
|
||||
if initValue:
|
||||
if self.INIT in parameters and parameters[self.INIT] is not None:
|
||||
initValue = self.parameterAsDouble(parameters, self.INIT, context)
|
||||
arguments.append('-init')
|
||||
arguments.append(initValue)
|
||||
|
||||
|
@ -38,6 +38,7 @@ from qgis.core import (QgsRasterFileWriter,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsProcessingParameterBoolean,
|
||||
QgsProcessingParameterExtent,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessingParameterRasterDestination,
|
||||
QgsProcessingUtils)
|
||||
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
|
||||
@ -59,6 +60,7 @@ class warp(GdalAlgorithm):
|
||||
TARGET_EXTENT = 'TARGET_EXTENT'
|
||||
TARGET_EXTENT_CRS = 'TARGET_EXTENT_CRS'
|
||||
MULTITHREADING = 'MULTITHREADING'
|
||||
EXTRA = 'EXTRA'
|
||||
OUTPUT = 'OUTPUT'
|
||||
|
||||
TYPES = ['Use input layer data type', 'Byte', 'Int16', 'UInt16', 'UInt32', 'Int32', 'Float32', 'Float64', 'CInt16', 'CInt32', 'CFloat32', 'CFloat64']
|
||||
@ -139,6 +141,13 @@ class warp(GdalAlgorithm):
|
||||
multithreading_param.setFlags(multithreading_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(multithreading_param)
|
||||
|
||||
extra_param = QgsProcessingParameterBoolean(self.EXTRA,
|
||||
self.tr('Additional command-line parameters'),
|
||||
defaultValue=None,
|
||||
optional=True)
|
||||
extra_param.setFlags(extra_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
|
||||
self.addParameter(extra_param)
|
||||
|
||||
self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT,
|
||||
self.tr('Reprojected')))
|
||||
|
||||
@ -228,6 +237,10 @@ class warp(GdalAlgorithm):
|
||||
if options:
|
||||
arguments.extend(GdalUtils.parseCreationOptions(options))
|
||||
|
||||
if self.EXTRA in parameters and parameters[self.EXTRA] not in (None, ''):
|
||||
extra = self.parameterAsString(parameters, self.EXTRA, context)
|
||||
arguments.append(extra)
|
||||
|
||||
arguments.append(inLayer.source())
|
||||
arguments.append(out)
|
||||
|
||||
|
@ -132,8 +132,8 @@ class Grass7Utils:
|
||||
Find GRASS binary path on the operating system.
|
||||
Sets global variable Grass7Utils.command
|
||||
"""
|
||||
cmdList = ["grass74", "grass72", "grass71", "grass70", "grass",
|
||||
"grass74.sh", "grass72.sh", "grass71.sh", "grass70.sh", "grass.sh"]
|
||||
cmdList = ["grass76", "grass74", "grass72", "grass70", "grass",
|
||||
"grass76.sh", "grass74.sh", "grass72.sh", "grass70.sh", "grass.sh"]
|
||||
|
||||
def searchFolder(folder):
|
||||
"""
|
||||
@ -544,7 +544,7 @@ class Grass7Utils:
|
||||
return 'https://grass.osgeo.org/grass{}/manuals/'.format(version)
|
||||
else:
|
||||
# GRASS not available!
|
||||
return 'https://grass.osgeo.org/grass72/manuals/'
|
||||
return 'https://grass.osgeo.org/grass76/manuals/'
|
||||
|
||||
@staticmethod
|
||||
def getSupportedOutputRasterExtensions():
|
||||
|
@ -84,18 +84,13 @@ qgis:createconstantrasterlayer: >
|
||||
Given an input raster layer and a value, this algorithm generates a new layer with the same extent and cell size as the input one, and all cells with the specified value.
|
||||
|
||||
qgis:creategridlines: >
|
||||
This algorithm creates a line vector layer with a grid covering a given extent.
|
||||
This algorithm creates a vector layer with a grid covering a given extent. Elements in the grid can be points, lines or polygons.
|
||||
|
||||
The size of each element in the grid is defined using a horizontal and vertical spacing.
|
||||
The size and/or placement of each element in the grid is defined using a horizontal and vertical spacing.
|
||||
|
||||
The CRS of the output layer must be defined. The grid extent and the spacing values must be expressed in the coordinates and units of this CRS.
|
||||
|
||||
qgis:creategridpolygon: >
|
||||
This algorithm creates a polygon vector layer with a grid covering a given extent. The grid shape can be rectangles, diamond or hexagons.
|
||||
|
||||
The size of each element in the grid is defined using a horizontal and vertical spacing.
|
||||
|
||||
The CRS of the output layer must be defined. The grid extent and the spacing values must be expressed in the coordinates and units of this CRS.
|
||||
The top-left point (minX, maxY) is used as the reference point. That means that, at that point, an element is guaranteed to be placed. Unless the width and height of the selected extent is a multiple of the selected spacing, that is not true for the other points that define that extent.
|
||||
|
||||
qgis:createpointsalonglines: >
|
||||
This algorithm creates a points layer, with points distributed along the lines of an input vector layer. the distance between points (measured along the line) is defined as a parameter.
|
||||
|
@ -1,77 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
***************************************************************************
|
||||
DensifyGeometriesInterval.py by Anita Graser, Dec 2012
|
||||
based on DensifyGeometries.py
|
||||
---------------------
|
||||
Date : October 2012
|
||||
Copyright : (C) 2012 by Victor Olaya
|
||||
Email : volayaf at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************
|
||||
"""
|
||||
|
||||
__author__ = 'Anita Graser'
|
||||
__date__ = 'Dec 2012'
|
||||
__copyright__ = '(C) 2012, Anita Graser'
|
||||
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
from qgis.core import (QgsProcessingParameterDistance,
|
||||
QgsProcessing)
|
||||
|
||||
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
|
||||
|
||||
|
||||
class DensifyGeometriesInterval(QgisFeatureBasedAlgorithm):
|
||||
|
||||
INTERVAL = 'INTERVAL'
|
||||
|
||||
def tags(self):
|
||||
return self.tr('add,vertex,vertices,points,nodes').split(',')
|
||||
|
||||
def group(self):
|
||||
return self.tr('Vector geometry')
|
||||
|
||||
def groupId(self):
|
||||
return 'vectorgeometry'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.interval = None
|
||||
|
||||
def initParameters(self, config=None):
|
||||
self.addParameter(QgsProcessingParameterDistance(self.INTERVAL,
|
||||
self.tr('Interval between vertices to add'),
|
||||
1, 'INPUT', False, 0, 10000000))
|
||||
|
||||
def name(self):
|
||||
return 'densifygeometriesgivenaninterval'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Densify by interval')
|
||||
|
||||
def outputName(self):
|
||||
return self.tr('Densified')
|
||||
|
||||
def inputLayerTypes(self):
|
||||
return [QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPolygon]
|
||||
|
||||
def prepareAlgorithm(self, parameters, context, feedback):
|
||||
self.interval = self.parameterAsDouble(parameters, self.INTERVAL, context)
|
||||
return True
|
||||
|
||||
def processFeature(self, feature, context, feedback):
|
||||
if feature.hasGeometry():
|
||||
new_geometry = feature.geometry().densifyByDistance(float(self.interval))
|
||||
feature.setGeometry(new_geometry)
|
||||
return [feature]
|
@ -129,7 +129,7 @@ class IdwInterpolation(QgisAlgorithm):
|
||||
|
||||
layerData = []
|
||||
layers = []
|
||||
for row in interpolationData.split(';'):
|
||||
for row in interpolationData.split('::|::'):
|
||||
v = row.split('::~::')
|
||||
data = QgsInterpolator.LayerData()
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user