Refactor and optimise certain QgsWKBTypes functions

Given how frequently these functions are called throughout QGIS,
it makes sense for them to be written in a way that makes it easy
for the compiler to optimise them/inline them.
This commit is contained in:
Nyall Dawson 2016-01-24 20:24:29 +11:00
parent ba530a0f1c
commit ac033cfc9d
2 changed files with 637 additions and 229 deletions

View File

@ -29,42 +29,6 @@ QMap<QgsWKBTypes::Type, QgsWKBTypes::wkbEntry>* QgsWKBTypes::entries()
return &entries;
}
QgsWKBTypes::Type QgsWKBTypes::singleType( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() || it.key() == Unknown )
{
return Unknown;
}
return ( it->mSingleType );
}
QgsWKBTypes::Type QgsWKBTypes::multiType( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() || it.key() == Unknown )
{
return Unknown;
}
return it->mMultiType;
}
QgsWKBTypes::Type QgsWKBTypes::flatType( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() || it.key() == Unknown )
{
return Unknown;
}
return it->mFlatType;
}
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.
* See details in QEP #17
****************************************************************************/
QgsWKBTypes::Type QgsWKBTypes::parseType( const QString &wktStr )
{
QString typestr = wktStr.left( wktStr.indexOf( '(' ) ).simplified().remove( ' ' );
@ -79,82 +43,6 @@ QgsWKBTypes::Type QgsWKBTypes::parseType( const QString &wktStr )
return Unknown;
}
bool QgsWKBTypes::isSingleType( Type type )
{
return ( type != Unknown && !isMultiType( type ) );
}
bool QgsWKBTypes::isMultiType( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() )
{
return Unknown;
}
return it->mIsMultiType;
}
bool QgsWKBTypes::isCurvedType( QgsWKBTypes::Type type )
{
switch ( flatType( type ) )
{
case CircularString:
case CompoundCurve:
case CurvePolygon:
case MultiCurve:
case MultiSurface:
return true;
default:
return false;
}
return false;
}
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.
* See details in QEP #17
****************************************************************************/
int QgsWKBTypes::wkbDimensions( Type type )
{
GeometryType gtype = geometryType( type );
switch ( gtype )
{
case LineGeometry:
return 1;
case PolygonGeometry:
return 2;
default: //point, no geometry, unknown geometry
return 0;
}
}
int QgsWKBTypes::coordDimensions( QgsWKBTypes::Type type )
{
if ( type == Unknown || type == NoGeometry )
return 0;
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() )
{
return 0;
}
return 2 + it->mHasZ + it->mHasM;
}
QgsWKBTypes::GeometryType QgsWKBTypes::geometryType( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() )
{
return UnknownGeometry;
}
return it->mGeometryType;
}
QString QgsWKBTypes::displayString( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
@ -165,107 +53,6 @@ QString QgsWKBTypes::displayString( Type type )
return it->mName;
}
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.
* See details in QEP #17
****************************************************************************/
bool QgsWKBTypes::hasZ( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() )
{
return false;
}
return it->mHasZ;
}
bool QgsWKBTypes::hasM( Type type )
{
QMap< Type, wkbEntry >::const_iterator it = entries()->constFind( type );
if ( it == entries()->constEnd() )
{
return false;
}
return it->mHasM;
}
QgsWKBTypes::Type QgsWKBTypes::addZ( QgsWKBTypes::Type type )
{
if ( hasZ( type ) )
return type;
else if ( type == Unknown )
return Unknown;
else if ( type == NoGeometry )
return NoGeometry;
//upgrade with z dimension
Type flat = flatType( type );
if ( hasM( type ) )
return static_cast< QgsWKBTypes::Type >( flat + 3000 );
else
return static_cast< QgsWKBTypes::Type >( flat + 1000 );
}
QgsWKBTypes::Type QgsWKBTypes::addM( QgsWKBTypes::Type type )
{
if ( hasM( type ) )
return type;
else if ( type == Unknown )
return Unknown;
else if ( type == NoGeometry )
return NoGeometry;
else if ( type == Point25D ||
type == LineString25D ||
type == Polygon25D ||
type == MultiPoint25D ||
type == MultiLineString25D ||
type == MultiPolygon25D )
return type; //can't add M dimension to these types
//upgrade with m dimension
Type flat = flatType( type );
if ( hasZ( type ) )
return static_cast< QgsWKBTypes::Type >( flat + 3000 );
else
return static_cast< QgsWKBTypes::Type >( flat + 2000 );
}
QgsWKBTypes::Type QgsWKBTypes::dropZ( QgsWKBTypes::Type type )
{
if ( !hasZ( type ) )
return type;
QgsWKBTypes::Type returnType = flatType( type );
if ( hasM( type ) )
returnType = addM( returnType );
return returnType;
}
QgsWKBTypes::Type QgsWKBTypes::dropM( QgsWKBTypes::Type type )
{
if ( !hasM( type ) )
return type;
QgsWKBTypes::Type returnType = flatType( type );
if ( hasZ( type ) )
returnType = addZ( returnType );
return returnType;
}
QgsWKBTypes::Type QgsWKBTypes::to25D( QgsWKBTypes::Type type )
{
QgsWKBTypes::Type flat = flatType( type );
if ( flat >= Point && flat <= MultiPolygon )
return static_cast< QgsWKBTypes::Type >( flat + 0x80000000 );
else if ( type == QgsWKBTypes::NoGeometry )
return QgsWKBTypes::NoGeometry;
else
return Unknown;
}
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
* full unit tests.

View File

@ -111,21 +111,349 @@ class CORE_EXPORT QgsWKBTypes
* @see multiType()
* @see flatType()
*/
static Type singleType( Type type );
static Type singleType( Type type )
{
switch ( type )
{
case Unknown:
case GeometryCollection:
case GeometryCollectionZ:
case GeometryCollectionM:
case GeometryCollectionZM:
return Unknown;
case Point:
case MultiPoint:
return Point;
case PointZ:
case MultiPointZ:
return PointZ;
case PointM:
case MultiPointM:
return PointM;
case PointZM:
case MultiPointZM:
return PointZM;
case LineString:
case MultiLineString:
return LineString;
case LineStringZ:
case MultiLineStringZ:
return LineStringZ;
case LineStringM:
case MultiLineStringM:
return LineStringM;
case LineStringZM:
case MultiLineStringZM:
return LineStringZM;
case Polygon:
case MultiPolygon:
return Polygon;
case PolygonZ:
case MultiPolygonZ:
return PolygonZ;
case PolygonM:
case MultiPolygonM:
return PolygonM;
case PolygonZM:
case MultiPolygonZM:
return PolygonZM;
case CircularString:
return CircularString;
case CircularStringZ:
return CircularStringZ;
case CircularStringM:
return CircularStringM;
case CircularStringZM:
return CircularStringZM;
case CompoundCurve:
case MultiCurve:
return CompoundCurve;
case CompoundCurveZ:
case MultiCurveZ:
return CompoundCurveZ;
case CompoundCurveM:
case MultiCurveM:
return CompoundCurveM;
case CompoundCurveZM:
case MultiCurveZM:
return CompoundCurveZM;
case CurvePolygon:
case MultiSurface:
return CurvePolygon;
case CurvePolygonZ:
case MultiSurfaceZ:
return CurvePolygonZ;
case CurvePolygonM:
case MultiSurfaceM:
return CurvePolygonM;
case CurvePolygonZM:
case MultiSurfaceZM:
return CurvePolygonZM;
case NoGeometry:
return NoGeometry;
case Point25D:
case MultiPoint25D:
return Point25D;
case LineString25D:
case MultiLineString25D:
return LineString25D;
case Polygon25D:
case MultiPolygon25D:
return Polygon25D;
}
return Unknown;
}
/** Returns the multi type for a WKB type. Eg, for Polygon WKB types the multi type would be MultiPolygon.
* @see isMultiType()
* @see singleType()
* @see flatType()
*/
static Type multiType( Type type );
static Type multiType( Type type )
{
switch ( type )
{
case Unknown:
return Unknown;
case GeometryCollection:
return GeometryCollection;
case GeometryCollectionZ:
return GeometryCollectionZ;
case GeometryCollectionM:
return GeometryCollectionM;
case GeometryCollectionZM:
return GeometryCollectionZM;
case Point:
case MultiPoint:
return MultiPoint;
case PointZ:
case MultiPointZ:
return MultiPointZ;
case PointM:
case MultiPointM:
return MultiPointM;
case PointZM:
case MultiPointZM:
return MultiPointZM;
case LineString:
case MultiLineString:
return MultiLineString;
case LineStringZ:
case MultiLineStringZ:
return MultiLineStringZ;
case LineStringM:
case MultiLineStringM:
return MultiLineStringM;
case LineStringZM:
case MultiLineStringZM:
return MultiLineStringZM;
case Polygon:
case MultiPolygon:
return MultiPolygon;
case PolygonZ:
case MultiPolygonZ:
return MultiPolygonZ;
case PolygonM:
case MultiPolygonM:
return MultiPolygonM;
case PolygonZM:
case MultiPolygonZM:
return MultiPolygonZM;
case CompoundCurve:
case CircularString:
case MultiCurve:
return MultiCurve;
case CompoundCurveZ:
case CircularStringZ:
case MultiCurveZ:
return MultiCurveZ;
case CompoundCurveM:
case CircularStringM:
case MultiCurveM:
return MultiCurveM;
case CompoundCurveZM:
case CircularStringZM:
case MultiCurveZM:
return MultiCurveZM;
case CurvePolygon:
case MultiSurface:
return MultiSurface;
case CurvePolygonZ:
case MultiSurfaceZ:
return MultiSurfaceZ;
case CurvePolygonM:
case MultiSurfaceM:
return MultiSurfaceM;
case CurvePolygonZM:
case MultiSurfaceZM:
return MultiSurfaceZM;
case NoGeometry:
return NoGeometry;
case Point25D:
case MultiPoint25D:
return MultiPoint25D;
case LineString25D:
case MultiLineString25D:
return MultiLineString25D;
case Polygon25D:
case MultiPolygon25D:
return MultiPolygon25D;
}
return Unknown;
}
/** Returns the flat type for a WKB type. This is the WKB type minus any Z or M dimensions.
* Eg, for PolygonZM WKB types the single type would be Polygon.
* @see singleType()
* @see multiType()
*/
static Type flatType( Type type );
static Type flatType( Type type )
{
switch ( type )
{
case Unknown:
return Unknown;
case Point:
case PointZ:
case PointM:
case PointZM:
case Point25D:
return Point;
case LineString:
case LineStringZ:
case LineStringM:
case LineStringZM:
case LineString25D:
return LineString;
case Polygon:
case PolygonZ:
case PolygonM:
case PolygonZM:
case Polygon25D:
return Polygon;
case MultiPoint:
case MultiPointZ:
case MultiPointM:
case MultiPointZM:
case MultiPoint25D:
return MultiPoint;
case MultiLineString:
case MultiLineStringZ:
case MultiLineStringM:
case MultiLineStringZM:
case MultiLineString25D:
return MultiLineString;
case MultiPolygon:
case MultiPolygonZ:
case MultiPolygonM:
case MultiPolygonZM:
case MultiPolygon25D:
return MultiPolygon;
case GeometryCollection:
case GeometryCollectionZ:
case GeometryCollectionM:
case GeometryCollectionZM:
return GeometryCollection;
case CircularString:
case CircularStringZ:
case CircularStringM:
case CircularStringZM:
return CircularString;
case CompoundCurve:
case CompoundCurveZ:
case CompoundCurveM:
case CompoundCurveZM:
return CompoundCurve;
case MultiCurve:
case MultiCurveZ:
case MultiCurveM:
case MultiCurveZM:
return MultiCurve;
case CurvePolygon:
case CurvePolygonZ:
case CurvePolygonM:
case CurvePolygonZM:
return CurvePolygon;
case MultiSurface:
case MultiSurfaceZ:
case MultiSurfaceM:
case MultiSurfaceZM:
return MultiSurface;
case NoGeometry:
return NoGeometry;
}
return Unknown;
}
/** Attempts to extract the WKB type from a WKT string.
* @param wktStr a valid WKT string
@ -136,18 +464,78 @@ class CORE_EXPORT QgsWKBTypes
* @see isMultiType()
* @see singleType()
*/
static bool isSingleType( Type type );
static bool isSingleType( Type type )
{
return ( type != Unknown && !isMultiType( type ) );
}
/** Returns true if the WKB type is a multi type.
* @see isSingleType()
* @see multiType()
*/
static bool isMultiType( Type type );
static bool isMultiType( Type type )
{
switch ( type )
{
case Unknown:
case Point:
case LineString:
case Polygon:
case CircularString:
case CompoundCurve:
case CurvePolygon:
case NoGeometry:
case PointZ:
case LineStringZ:
case PolygonZ:
case CircularStringZ:
case CompoundCurveZ:
case CurvePolygonZ:
case PointM:
case LineStringM:
case PolygonM:
case CircularStringM:
case CompoundCurveM:
case CurvePolygonM:
case PointZM:
case LineStringZM:
case PolygonZM:
case CircularStringZM:
case CompoundCurveZM:
case CurvePolygonZM:
case Point25D:
case LineString25D:
case Polygon25D:
return false;
default:
return true;
}
return false;
}
/** Returns true if the WKB type is a curved type or can contain curved geometries.
* @note added in QGIS 2.14
*/
static bool isCurvedType( Type type );
static bool isCurvedType( Type type )
{
switch ( flatType( type ) )
{
case CircularString:
case CompoundCurve:
case CurvePolygon:
case MultiCurve:
case MultiSurface:
return true;
default:
return false;
}
return false;
}
/** Returns the inherent dimension of the geometry type as an integer. Returned value will
* always be less than or equal to the coordinate dimension.
@ -155,7 +543,19 @@ class CORE_EXPORT QgsWKBTypes
* Invalid geometry types will return a dimension of 0.
* @see coordDimensions()
*/
static int wkbDimensions( Type type );
static int wkbDimensions( Type type )
{
GeometryType gtype = geometryType( type );
switch ( gtype )
{
case LineGeometry:
return 1;
case PolygonGeometry:
return 2;
default: //point, no geometry, unknown geometry
return 0;
}
}
/** Returns the coordinate dimension of the geometry type as an integer. Returned value will
* be between 2-4, depending on whether the geometry type contains the Z or M dimensions.
@ -163,12 +563,90 @@ class CORE_EXPORT QgsWKBTypes
* @note added in QGIS 2.14
* @see wkbDimensions()
*/
static int coordDimensions( Type type );
static int coordDimensions( Type type )
{
if ( type == Unknown || type == NoGeometry )
return 0;
return 2 + hasZ( type ) + hasM( type );
}
/** Returns the geometry type for a WKB type, eg both MultiPolygon and CurvePolygon would have a
* PolygonGeometry geometry type.
*/
static GeometryType geometryType( Type type );
static GeometryType geometryType( Type type )
{
switch ( type )
{
case Unknown:
case GeometryCollection:
case GeometryCollectionZ:
case GeometryCollectionM:
case GeometryCollectionZM:
return UnknownGeometry;
case Point:
case MultiPoint:
case PointZ:
case MultiPointZ:
case PointM:
case MultiPointM:
case PointZM:
case MultiPointZM:
case Point25D:
case MultiPoint25D:
return PointGeometry;
case LineString:
case MultiLineString:
case LineStringZ:
case MultiLineStringZ:
case LineStringM:
case MultiLineStringM:
case LineStringZM:
case MultiLineStringZM:
case LineString25D:
case MultiLineString25D:
case CircularString:
case CompoundCurve:
case MultiCurve:
case CircularStringZ:
case CompoundCurveZ:
case MultiCurveZ:
case CircularStringM:
case CompoundCurveM:
case MultiCurveM:
case CircularStringZM:
case CompoundCurveZM:
case MultiCurveZM:
return LineGeometry;
case Polygon:
case MultiPolygon:
case PolygonZ:
case MultiPolygonZ:
case PolygonM:
case MultiPolygonM:
case PolygonZM:
case MultiPolygonZM:
case Polygon25D:
case MultiPolygon25D:
case CurvePolygon:
case MultiSurface:
case CurvePolygonZ:
case MultiSurfaceZ:
case CurvePolygonM:
case MultiSurfaceM:
case CurvePolygonZM:
case MultiSurfaceZM:
return PolygonGeometry;
case NoGeometry:
return NullGeometry;
}
return UnknownGeometry;
}
/** Returns a display string type for a WKB type, eg the geometry name used in WKT geometry representations.
*/
@ -179,14 +657,91 @@ class CORE_EXPORT QgsWKBTypes
* @see addZ()
* @see hasM()
*/
static bool hasZ( Type type );
static bool hasZ( Type type )
{
switch ( type )
{
case PointZ:
case LineStringZ:
case PolygonZ:
case MultiPointZ:
case MultiLineStringZ:
case MultiPolygonZ:
case GeometryCollectionZ:
case CircularStringZ:
case CompoundCurveZ:
case CurvePolygonZ:
case MultiCurveZ:
case MultiSurfaceZ:
case PointZM:
case LineStringZM:
case PolygonZM:
case MultiPointZM:
case MultiLineStringZM:
case MultiPolygonZM:
case GeometryCollectionZM:
case CircularStringZM:
case CompoundCurveZM:
case CurvePolygonZM:
case MultiCurveZM:
case MultiSurfaceZM:
case Point25D:
case LineString25D:
case Polygon25D:
case MultiPoint25D:
case MultiLineString25D:
case MultiPolygon25D:
return true;
default:
return false;
}
return false;
}
/** Tests whether a WKB type contains m values.
* @returns true if type has m values
* @see addM()
* @see hasZ()
*/
static bool hasM( Type type );
static bool hasM( Type type )
{
switch ( type )
{
case PointM:
case LineStringM:
case PolygonM:
case MultiPointM:
case MultiLineStringM:
case MultiPolygonM:
case GeometryCollectionM:
case CircularStringM:
case CompoundCurveM:
case CurvePolygonM:
case MultiCurveM:
case MultiSurfaceM:
case PointZM:
case LineStringZM:
case PolygonZM:
case MultiPointZM:
case MultiLineStringZM:
case MultiPolygonZM:
case GeometryCollectionZM:
case CircularStringZM:
case CompoundCurveZM:
case CurvePolygonZM:
case MultiCurveZM:
case MultiSurfaceZM:
return true;
default:
return false;
}
return false;
}
/** Adds the z dimension to a WKB type and returns the new type
* @param type original type
@ -195,7 +750,22 @@ class CORE_EXPORT QgsWKBTypes
* @see dropZ()
* @see hasZ()
*/
static Type addZ( Type type );
static Type addZ( Type type )
{
if ( hasZ( type ) )
return type;
else if ( type == Unknown )
return Unknown;
else if ( type == NoGeometry )
return NoGeometry;
//upgrade with z dimension
Type flat = flatType( type );
if ( hasM( type ) )
return static_cast< QgsWKBTypes::Type >( flat + 3000 );
else
return static_cast< QgsWKBTypes::Type >( flat + 1000 );
}
/** Adds the m dimension to a WKB type and returns the new type
* @param type original type
@ -204,7 +774,29 @@ class CORE_EXPORT QgsWKBTypes
* @see dropM()
* @see hasM()
*/
static Type addM( Type type );
static Type addM( Type type )
{
if ( hasM( type ) )
return type;
else if ( type == Unknown )
return Unknown;
else if ( type == NoGeometry )
return NoGeometry;
else if ( type == Point25D ||
type == LineString25D ||
type == Polygon25D ||
type == MultiPoint25D ||
type == MultiLineString25D ||
type == MultiPolygon25D )
return type; //can't add M dimension to these types
//upgrade with m dimension
Type flat = flatType( type );
if ( hasZ( type ) )
return static_cast< QgsWKBTypes::Type >( flat + 3000 );
else
return static_cast< QgsWKBTypes::Type >( flat + 2000 );
}
/** Drops the z dimension (if present) for a WKB type and returns the new type.
* @param type original type
@ -212,7 +804,16 @@ class CORE_EXPORT QgsWKBTypes
* @see dropM()
* @see addZ()
*/
static Type dropZ( Type type );
static Type dropZ( Type type )
{
if ( !hasZ( type ) )
return type;
QgsWKBTypes::Type returnType = flatType( type );
if ( hasM( type ) )
returnType = addM( returnType );
return returnType;
}
/** Drops the m dimension (if present) for a WKB type and returns the new type.
* @param type original type
@ -220,14 +821,34 @@ class CORE_EXPORT QgsWKBTypes
* @see dropZ()
* @see addM()
*/
static Type dropM( Type type );
static Type dropM( Type type )
{
if ( !hasM( type ) )
return type;
QgsWKBTypes::Type returnType = flatType( type );
if ( hasZ( type ) )
returnType = addZ( returnType );
return returnType;
}
/**
* Will convert the 25D version of the flat type if supported or Unknown if not supported.
* @param type The type to convert
* @return the 25D version of the type or Unknown
*/
static Type to25D( Type type );
static Type to25D( Type type )
{
QgsWKBTypes::Type flat = flatType( type );
if ( flat >= Point && flat <= MultiPolygon )
return static_cast< QgsWKBTypes::Type >( flat + 0x80000000 );
else if ( type == QgsWKBTypes::NoGeometry )
return QgsWKBTypes::NoGeometry;
else
return Unknown;
}
private:
struct wkbEntry