Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for Pointcloud layers
  • Loading branch information
Sandro Santilli authored and jef-n committed May 6, 2015
1 parent 3dcb640 commit 4490948
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 22 deletions.
68 changes: 54 additions & 14 deletions src/providers/postgres/qgspostgresconn.cpp
Expand Up @@ -364,12 +364,12 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP

mLayersSupported.clear();

for ( int i = 0; i < ( hasTopology() ? 3 : 2 ); i++ )
for ( int i = sctGeometry; i <= sctPcPatch; ++i )
{
QString sql, tableName, schemaName, columnName, typeName, sridName, gtableName, dimName;
QgsPostgresGeometryColumnType columnType = sctGeometry;

if ( i == 0 )
if ( i == sctGeometry )
{
tableName = "l.f_table_name";
schemaName = "l.f_table_schema";
Expand All @@ -380,7 +380,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
gtableName = "geometry_columns";
columnType = sctGeometry;
}
else if ( i == 1 )
else if ( i == sctGeography )
{
tableName = "l.f_table_name";
schemaName = "l.f_table_schema";
Expand All @@ -391,8 +391,10 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
gtableName = "geography_columns";
columnType = sctGeography;
}
else if ( i == 2 )
else if ( i == sctTopoGeometry )
{
if ( ! hasTopology() ) continue;

schemaName = "l.schema_name";
tableName = "l.table_name";
columnName = "l.feature_column";
Expand All @@ -407,6 +409,25 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
gtableName = "topology.layer";
columnType = sctTopoGeometry;
}
else if ( i == sctPcPatch )
{
if ( ! hasPointcloud() ) continue;

tableName = "l.\"table\"";
schemaName = "l.\"schema\"";
columnName = "l.\"column\"";
typeName = "'POLYGON'";
sridName = "l.srid";
dimName = "2";
gtableName = "pointcloud_columns";
columnType = sctPcPatch;
}
else
{
QgsMessageLog::logMessage( tr( "Unsupported spatial column type %1" )
.arg( displayStringForGeomType(( QgsPostgresGeometryColumnType )i ) ) );
continue;
}

// The following query returns only tables that exist and the user has SELECT privilege on.
// Can't use regclass here because table must exist, else error occurs.
Expand Down Expand Up @@ -510,7 +531,7 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
" WHERE c.relkind IN ('v','r','m')"
" AND has_schema_privilege( n.nspname, 'usage' )"
" AND has_table_privilege( '\"' || n.nspname || '\".\"' || c.relname || '\"', 'select' )"
" AND (t.typname IN ('geometry','geography','topogeometry') OR b.typname IN ('geometry','geography','topogeometry'))";
" AND (t.typname IN ('geometry','geography','topogeometry') OR b.typname IN ('geometry','geography','topogeometry','pcpatch'))";

// user has select privilege
if ( searchPublicOnly )
Expand All @@ -522,19 +543,19 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
// skip columns of which we already derived information from the metadata tables
if ( nColumns > 0 )
{
if ( foundInTables & 1 )
if ( foundInTables & ( 1 << sctGeometry ) )
{
sql += " AND (n.nspname,c.relname,a.attname) NOT IN (SELECT f_table_schema,f_table_name,f_geometry_column FROM geometry_columns)";
}

if ( foundInTables & 2 )
if ( foundInTables & ( 1 << sctGeography ) )
{
sql += " AND (n.nspname,c.relname,a.attname) NOT IN (SELECT f_table_schema,f_table_name,f_geography_column FROM geography_columns)";
}

if ( foundInTables & 4 )
if ( foundInTables & ( 1 << sctPcPatch ) )
{
sql += " AND (n.nspname,c.relname,a.attname) NOT IN (SELECT schema_name,table_name,feature_column FROM topology.layer)";
sql += " AND (n.nspname,c.relname,a.attname) NOT IN (SELECT \"schema\",\"table\",\"column\" FROM pointcloud_columns)";
}
}

Expand Down Expand Up @@ -586,6 +607,10 @@ bool QgsPostgresConn::getTableInfo( bool searchGeometryColumnsOnly, bool searchP
{
layerProperty.geometryColType = sctTopoGeometry;
}
else if ( coltype == "pcpatch" )
{
layerProperty.geometryColType = sctPcPatch;
}
else
{
Q_ASSERT( !"Unknown geometry type" );
Expand Down Expand Up @@ -747,6 +772,16 @@ bool QgsPostgresConn::hasTopology()
return mTopologyAvailable;
}

/**
* Check to see if pointcloud is available
*/
bool QgsPostgresConn::hasPointcloud()
{
// TODO: use mPointcloudAvailable function instead
QgsPostgresResult result = PQexec( "SELECT 'pointcloud_columns'::regclass" );

This comment has been minimized.

Copy link
@nyalldawson

nyalldawson May 12, 2015

Collaborator

@strk I'm seeing a lot of errors in the PostGIS log messages window following this commit:

"Erroneous query: SELECT 'pointcloud_columns'::regclass returned 7 [ERROR: relation "pointcloud_columns" does not exist
LINE 1: SELECT 'pointcloud_columns'::regclass"

This comment has been minimized.

Copy link
@jef-n

jef-n May 12, 2015

Member

fixed in c8aa777

This comment has been minimized.

Copy link
@strk

strk May 12, 2015

Contributor

Thanks. I've cleaned it further with 4562b04 so to get no error at all

return result.PQntuples() == 1;
}

/* Functions for determining available features in postGIS */
QString QgsPostgresConn::postgisVersion()
{
Expand Down Expand Up @@ -1279,12 +1314,15 @@ void QgsPostgresConn::retrieveLayerTypes( QgsPostgresLayerProperty &layerPropert

QString query = "SELECT DISTINCT ";

bool castToGeometry = layerProperty.geometryColType == sctGeography ||
layerProperty.geometryColType == sctPcPatch;

QGis::WkbType type = layerProperty.types.value( 0, QGis::WKBUnknown );
if ( type == QGis::WKBUnknown )
{
query += QString( "upper(geometrytype(%1%2))" )
.arg( quotedIdentifier( layerProperty.geometryColName ) )
.arg( layerProperty.geometryColType == sctGeography ? "::geometry" : "" );
.arg( castToGeometry ? "::geometry" : "" );
}
else
{
Expand All @@ -1299,7 +1337,7 @@ void QgsPostgresConn::retrieveLayerTypes( QgsPostgresLayerProperty &layerPropert
query += QString( "%1(%2%3)" )
.arg( majorVersion() < 2 ? "srid" : "st_srid" )
.arg( quotedIdentifier( layerProperty.geometryColName ) )
.arg( layerProperty.geometryColType == sctGeography ? "::geometry" : "" );
.arg( castToGeometry ? "::geometry" : "" );
}
else
{
Expand All @@ -1311,7 +1349,7 @@ void QgsPostgresConn::retrieveLayerTypes( QgsPostgresLayerProperty &layerPropert
query += QString( ",%1(%2%3)" )
.arg( majorVersion() < 2 ? "ndims" : "st_ndims" )
.arg( quotedIdentifier( layerProperty.geometryColName ) )
.arg( layerProperty.geometryColType == sctGeography ? "::geometry" : "" );
.arg( castToGeometry ? "::geometry" : "" );
}

query += " FROM " + table;
Expand Down Expand Up @@ -1426,10 +1464,10 @@ QString QgsPostgresConn::postgisWkbTypeName( QGis::WkbType wkbType )
return geometryType;
}

QString QgsPostgresConn::postgisTypeFilter( QString geomCol, QGis::WkbType geomType, bool isGeography )
QString QgsPostgresConn::postgisTypeFilter( QString geomCol, QGis::WkbType geomType, bool castToGeometry )
{
geomCol = quotedIdentifier( geomCol );
if ( isGeography )
if ( castToGeometry )
geomCol += "::geometry";

switch ( geomType )
Expand Down Expand Up @@ -1601,6 +1639,8 @@ QString QgsPostgresConn::displayStringForGeomType( QgsPostgresGeometryColumnType
return tr( "Geography" );
case sctTopoGeometry:
return tr( "TopoGeometry" );
case sctPcPatch:
return tr( "PcPatch" );
}

Q_ASSERT( !"unexpected geometry column type" );
Expand Down
9 changes: 7 additions & 2 deletions src/providers/postgres/qgspostgresconn.h
Expand Up @@ -34,12 +34,14 @@ extern "C"

class QgsField;

/** Spatial column types */
enum QgsPostgresGeometryColumnType
{
sctNone,
sctGeometry,
sctGeography,
sctTopoGeometry
sctTopoGeometry,
sctPcPatch
};

enum QgsPostgresPrimaryKeyType
Expand Down Expand Up @@ -187,6 +189,9 @@ class QgsPostgresConn : public QObject
//! get status of topology capability
bool hasTopology();

//! get status of Pointcloud capability
bool hasPointcloud();

//! get status of GIST capability
bool hasGIST();

Expand Down Expand Up @@ -299,7 +304,7 @@ class QgsPostgresConn : public QObject
static int postgisWkbTypeDim( QGis::WkbType wkbType );
static void postgisWkbType( QGis::WkbType wkbType, QString &geometryType, int &dim );

static QString postgisTypeFilter( QString geomCol, QGis::WkbType wkbType, bool isGeography );
static QString postgisTypeFilter( QString geomCol, QGis::WkbType wkbType, bool castToGeometry );

static QGis::WkbType wkbTypeFromGeomType( QGis::GeometryType geomType );
static QGis::WkbType wkbTypeFromOgcWkbType( unsigned int ogcWkbType );
Expand Down
16 changes: 11 additions & 5 deletions src/providers/postgres/qgspostgresfeatureiterator.cpp
Expand Up @@ -266,15 +266,20 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
.arg( mSource->mRequestedSrid.isEmpty() ? mSource->mDetectedSrid : mSource->mRequestedSrid );
}

QString whereClause = QString( "%1 && %2" )
QString whereClause = QString( "%1%2 && %3" )
.arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
.arg( mSource->mSpatialColType == sctPcPatch ? "::geometry" : "" )
.arg( qBox );

bool castToGeometry = mSource->mSpatialColType == sctGeography ||
mSource->mSpatialColType == sctPcPatch;

if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect )
{
whereClause += QString( " AND %1(%2%3,%4)" )
.arg( mConn->majorVersion() < 2 ? "intersects" : "st_intersects" )
.arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
.arg( mSource->mSpatialColType == sctGeography ? "::geometry" : "" )
.arg( castToGeometry ? "::geometry" : "" )
.arg( qBox );
}

Expand All @@ -283,13 +288,13 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
whereClause += QString( " AND %1(%2%3)=%4" )
.arg( mConn->majorVersion() < 2 ? "srid" : "st_srid" )
.arg( QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn ) )
.arg( mSource->mSpatialColType == sctGeography ? "::geography" : "" )
.arg( castToGeometry ? "::geometry" : "" )
.arg( mSource->mRequestedSrid );
}

if ( mSource->mRequestedGeomType != QGis::WKBUnknown && mSource->mRequestedGeomType != mSource->mDetectedGeomType )
{
whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, mSource->mRequestedGeomType, mSource->mSpatialColType == sctGeography ) );
whereClause += QString( " AND %1" ).arg( QgsPostgresConn::postgisTypeFilter( mSource->mGeometryColumn, mSource->mRequestedGeomType, castToGeometry ) );
}

return whereClause;
Expand All @@ -316,7 +321,8 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )
{
QString geom = QgsPostgresConn::quotedIdentifier( mSource->mGeometryColumn );

if ( mSource->mSpatialColType == sctGeography )
if ( mSource->mSpatialColType == sctGeography ||
mSource->mSpatialColType == sctPcPatch )
geom += "::geometry";

if ( mSource->mForce2d )
Expand Down
31 changes: 30 additions & 1 deletion src/providers/postgres/qgspostgresprovider.cpp
Expand Up @@ -2513,9 +2513,10 @@ QgsRectangle QgsPostgresProvider::extent()

if ( ext.isEmpty() )
{
sql = QString( "SELECT %1(%2) FROM %3%4" )
sql = QString( "SELECT %1(%2%3) FROM %4%5" )
.arg( connectionRO()->majorVersion() < 2 ? "extent" : "st_extent" )
.arg( quotedIdentifier( mGeometryColumn ) )
.arg( mSpatialColType == sctPcPatch ? "::geometry" : "" )
.arg( mQuery )
.arg( filterWhereClause() );

Expand Down Expand Up @@ -2609,6 +2610,8 @@ bool QgsPostgresProvider::getGeometryDetails()
mSpatialColType = sctGeography;
else if ( geomColType == "topogeometry" )
mSpatialColType = sctTopoGeometry;
else if ( geomColType == "pcpatch" )
mSpatialColType = sctPcPatch;
else
mSpatialColType = sctNone;
}
Expand Down Expand Up @@ -2714,6 +2717,30 @@ bool QgsPostgresProvider::getGeometryDetails()
}
}

if ( detectedType.isEmpty() && connectionRO()->hasPointcloud() )
{
// check pointcloud columns
sql = QString( "SELECT 'POLYGON',srid FROM pointcloud_columns WHERE \"table\"=%1 AND \"column\"=%2 AND \"schema\"=%3" )
.arg( quotedValue( tableName ) )
.arg( quotedValue( geomCol ) )
.arg( quotedValue( schemaName ) );

QgsDebugMsg( QString( "Getting pointcloud column: %1" ).arg( sql ) );
result = connectionRO()->PQexec( sql, false );
QgsDebugMsg( QString( "Pointcloud column query returned %1" ).arg( result.PQntuples() ) );

if ( result.PQntuples() == 1 )
{
detectedType = result.PQgetvalue( 0, 0 );
detectedSrid = result.PQgetvalue( 0, 1 );
mSpatialColType = sctPcPatch;
}
else
{
connectionRO()->PQexecNR( "COMMIT" );
}
}

if ( mSpatialColType == sctNone )
{
sql = QString( "SELECT t.typname FROM "
Expand All @@ -2736,6 +2763,8 @@ bool QgsPostgresProvider::getGeometryDetails()
mSpatialColType = sctGeography;
else if ( geomColType == "topogeometry" )
mSpatialColType = sctTopoGeometry;
else if ( geomColType == "pcpatch" )
mSpatialColType = sctPcPatch;
}
else
{
Expand Down

0 comments on commit 4490948

Please sign in to comment.