42 #define M_PI 3.14159265358979323846 45 #define DEG2RAD(x) ((x)*M_PI/180) 51 mEllipsoidalMode =
false;
60 : mCoordTransform( nullptr )
67 delete mCoordTransform;
73 if (
this == & origDA )
85 mEllipsoidalMode = origDA.mEllipsoidalMode;
86 mEllipsoid = origDA.mEllipsoid;
87 mSemiMajor = origDA.mSemiMajor;
88 mSemiMinor = origDA.mSemiMinor;
89 mInvFlattening = origDA.mInvFlattening;
93 delete mCoordTransform;
99 mEllipsoidalMode = flag;
104 return mEllipsoidalMode && mEllipsoid !=
GEO_NONE;
132 sqlite3_stmt *myPreparedStatement;
149 bool semiMajorOk, semiMinorOk;
150 double semiMajor = paramList[1].toDouble( & semiMajorOk );
151 double semiMinor = paramList[2].toDouble( & semiMinorOk );
152 if ( semiMajorOk && semiMinorOk )
174 QString mySql =
"select radius, parameter2 from tbl_ellipsoid where acronym='" + ellipsoid +
'\'';
175 myResult = sqlite3_prepare( myDatabase, mySql.
toUtf8(), mySql.
toUtf8().
length(), &myPreparedStatement, &myTail );
177 if ( myResult == SQLITE_OK )
179 if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
181 radius =
QString( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 0 ) ) );
182 parameter2 =
QString( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 1 ) ) );
186 sqlite3_finalize( myPreparedStatement );
187 sqlite3_close( myDatabase );
192 QgsDebugMsg(
QString(
"setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) );
197 if ( radius.
left( 2 ) ==
"a=" )
201 QgsDebugMsg(
QString(
"setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) );
208 if ( parameter2.
left( 2 ) ==
"b=" )
211 mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor );
213 else if ( parameter2.
left( 3 ) ==
"rf=" )
216 mSemiMinor = mSemiMajor - ( mSemiMajor / mInvFlattening );
220 QgsDebugMsg(
QString(
"setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) );
224 QgsDebugMsg(
QString(
"setEllipsoid: a=%1, b=%2, 1/f=%3" ).arg( mSemiMajor ).arg( mSemiMinor ).arg( mInvFlattening ) );
228 QString proj4 =
"+proj=longlat +ellps=" + ellipsoid +
" +no_defs";
234 if ( destCRS.
srsid() == 0 )
237 .
arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ),
259 mEllipsoid =
QString(
"PARAMETER:%1:%2" ).
arg( semiMajor ).
arg( semiMinor );
260 mSemiMajor = semiMajor;
261 mSemiMinor = semiMinor;
262 mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor );
277 if ( geomDimension <= 0 )
282 MeasureType measureType = type;
283 if ( measureType == Default )
285 measureType = ( geomDimension == 1 ? Length : Area );
288 if ( !mEllipsoidalMode || mEllipsoid ==
GEO_NONE )
291 if ( measureType == Length )
297 return geomV2->
area();
314 if ( measureType == Length )
365 return measure( geomV2, Area );
374 return measure( geomV2, Length );
383 if ( !geomV2 || geomV2->
dimension() < 2 )
388 if ( !mEllipsoidalMode || mEllipsoid ==
GEO_NONE )
406 surfaces.
append( static_cast<const QgsSurfaceV2*>( multiSurf->
geometryN( i ) ) );
412 for ( ; surfaceIt != surfaces.
constEnd(); ++surfaceIt )
423 length +=
measure( outerRing );
426 for (
int i = 0; i < nInnerRings; ++i )
444 curve->
points( linePointsV2 );
451 if ( points.
size() < 2 )
459 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
460 p1 = mCoordTransform->
transform( points[0] );
466 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
507 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
576 for (
int idx = 0; idx < numRings; idx++ )
583 for (
int jdx = 0; jdx < nPoints; jdx++ )
589 wkbPtr +=
sizeof( double );
594 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
601 if ( points.
size() > 2 )
647 curve->
points( linePointsV2 );
658 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
686 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
694 double dx = p2.
x() - p1.
x();
695 double dy = p2.
y() - p1.
y();
696 bearing = atan2( dx, dy );
708 double* course1,
double* course2 )
const 714 double a = mSemiMajor;
715 double b = mSemiMinor;
716 double f = 1 / mInvFlattening;
721 double L = p2_lon - p1_lon;
722 double U1 = atan(( 1 - f ) * tan( p1_lat ) );
723 double U2 = atan(( 1 - f ) * tan( p2_lat ) );
724 double sinU1 = sin( U1 ), cosU1 = cos( U1 );
725 double sinU2 = sin( U2 ), cosU2 = cos( U2 );
727 double lambdaP = 2 *
M_PI;
729 double sinLambda = 0;
730 double cosLambda = 0;
735 double cosSqAlpha = 0;
736 double cos2SigmaM = 0;
742 while ( qAbs( lambda - lambdaP ) > 1e-12 && --iterLimit > 0 )
744 sinLambda = sin( lambda );
745 cosLambda = cos( lambda );
746 tu1 = ( cosU2 * sinLambda );
747 tu2 = ( cosU1 * sinU2 - sinU1 * cosU2 * cosLambda );
748 sinSigma = sqrt( tu1 * tu1 + tu2 * tu2 );
749 cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
750 sigma = atan2( sinSigma, cosSigma );
751 alpha = asin( cosU1 * cosU2 * sinLambda / sinSigma );
752 cosSqAlpha = cos( alpha ) * cos( alpha );
753 cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
754 C = f / 16 * cosSqAlpha * ( 4 + f * ( 4 - 3 * cosSqAlpha ) );
756 lambda = L + ( 1 - C ) * f * sin( alpha ) *
757 ( sigma + C * sinSigma * ( cos2SigmaM + C * cosSigma * ( -1 + 2 * cos2SigmaM * cos2SigmaM ) ) );
760 if ( iterLimit == 0 )
763 double uSq = cosSqAlpha * ( a * a - b * b ) / ( b * b );
764 double A = 1 + uSq / 16384 * ( 4096 + uSq * ( -768 + uSq * ( 320 - 175 * uSq ) ) );
765 double B = uSq / 1024 * ( 256 + uSq * ( -128 + uSq * ( 74 - 47 * uSq ) ) );
766 double deltaSigma = B * sinSigma * ( cos2SigmaM + B / 4 * ( cosSigma * ( -1 + 2 * cos2SigmaM * cos2SigmaM ) -
767 B / 6 * cos2SigmaM * ( -3 + 4 * sinSigma * sinSigma ) * ( -3 + 4 * cos2SigmaM * cos2SigmaM ) ) );
768 double s = b * A * ( sigma - deltaSigma );
772 *course1 = atan2( tu1, tu2 );
777 *course2 = atan2( cosU1 * sinLambda, -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda ) +
M_PI;
785 return sqrt(( p2.
x() - p1.
x() ) * ( p2.
x() - p1.
x() ) + ( p2.
y() - p1.
y() ) * ( p2.
y() - p1.
y() ) );
790 if ( points.
size() < 2 )
803 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
832 double QgsDistanceArea::getQ(
double x )
const 839 return sinx *( 1 + sinx2 *( m_QA + sinx2 *( m_QB + sinx2 * m_QC ) ) );
843 double QgsDistanceArea::getQbar(
double x )
const 850 return cosx *( m_QbarA + cosx2 *( m_QbarB + cosx2 *( m_QbarC + cosx2 * m_QbarD ) ) );
862 double a2 = ( mSemiMajor * mSemiMajor );
863 double e2 = 1 - ( a2 / ( mSemiMinor * mSemiMinor ) );
871 m_AE = a2 * ( 1 - e2 );
873 m_QA = ( 2.0 / 3.0 ) * e2;
874 m_QB = ( 3.0 / 5.0 ) * e4;
875 m_QC = ( 4.0 / 7.0 ) * e6;
877 m_QbarA = -1.0 - ( 2.0 / 3.0 ) * e2 - ( 3.0 / 5.0 ) * e4 - ( 4.0 / 7.0 ) * e6;
878 m_QbarB = ( 2.0 / 9.0 ) * e2 + ( 2.0 / 5.0 ) * e4 + ( 4.0 / 7.0 ) * e6;
879 m_QbarC = - ( 3.0 / 25.0 ) * e4 - ( 12.0 / 35.0 ) * e6;
880 m_QbarD = ( 4.0 / 49.0 ) * e6;
882 m_Qp = getQ( M_PI / 2 );
883 m_E = 4 * M_PI * m_Qp * m_AE;
900 double x1, y1, x2, y2, dx, dy;
907 const double thresh = 1e-6;
910 if (( ! mEllipsoidalMode ) || ( mEllipsoid ==
GEO_NONE ) )
914 int n = points.
size();
915 x2 =
DEG2RAD( points[n-1].x() );
916 y2 =
DEG2RAD( points[n-1].y() );
917 Qbar2 = getQbar( y2 );
921 for (
int i = 0; i < n; i++ )
929 Qbar2 = getQbar( y2 );
932 while ( x1 - x2 >
M_PI )
935 while ( x2 - x1 >
M_PI )
940 if ( qAbs( dy ) > thresh )
943 area += dx * ( m_Qp - ( Qbar2 - Qbar1 ) / dy );
955 area += dx * ( m_Qp - getQ( ( y1 + y2 ) / 2.0 ) );
962 if (( area *= m_AE ) < 0.0 )
972 if ( area > m_E / 2 )
984 size = points.
size();
987 for ( i = 0; i < size; i++ )
992 area = area + points[i].x() * points[( i+1 ) % size].y() - points[( i+1 ) % size].x() * points[i].y();
1012 else if ( qAbs( value ) > 1000000.0 )
1015 value = value / 1000000.0;
1017 else if ( qAbs( value ) > 10000.0 )
1020 value = value / 10000.0;
1029 if ( keepBaseUnit || qAbs( value ) == 0.0 )
1033 else if ( qAbs( value ) > 1000.0 )
1036 value = value / 1000;
1038 else if ( qAbs( value ) < 0.01 )
1041 value = value * 1000;
1043 else if ( qAbs( value ) < 0.1 )
1046 value = value * 100;
1057 if ( keepBaseUnit || qAbs( value ) <= 0.5*43560.0 )
1062 else if ( qAbs( value ) <= 0.5*5280.0*5280.0 )
1072 value /= 5280.0 * 5280.0;
1077 if ( qAbs( value ) <= 528.0 || keepBaseUnit )
1079 if ( qAbs( value ) == 1.0 )
1112 if ( qAbs( value ) == 1.0 )
1122 QgsDebugMsg(
QString(
"Error: not picked up map units - actual value = %1" ).arg( u ) );
1126 return QString(
"%L1%2" ).
arg( value, 0,
'f', decimals ).
arg( unitLabel );
1136 if ( keepBaseUnit || qAbs( distance ) == 0.0 )
1140 else if ( qAbs( distance ) > 1000.0 )
1143 distance = distance / 1000;
1145 else if ( qAbs( distance ) < 0.01 )
1148 distance = distance * 1000;
1150 else if ( qAbs( distance ) < 0.1 )
1153 distance = distance * 100;
1162 if ( keepBaseUnit || qAbs( distance ) >= 1.0 )
1169 distance = distance * 1000;
1174 if ( qAbs( distance ) <= 5280.0 || keepBaseUnit )
1186 if ( qAbs( distance ) <= 1760.0 || keepBaseUnit )
1198 if ( qAbs( distance ) >= 1.0 || keepBaseUnit )
1215 if ( qAbs( distance ) == 1.0 )
1225 QgsDebugMsg(
QString(
"Error: not picked up map units - actual value = %1" ).arg( unit ) );
1229 return QString(
"%L1%2" ).
arg( distance, 0,
'f', decimals ).
arg( unitLabel );
1364 return QString(
"%L1%2" ).
arg( area, 0,
'f', decimals ).
arg( unitLabel );
1378 QgsDebugMsg(
"We're measuring on an ellipsoid or using projections, the system is returning meters" );
1380 else if ( mEllipsoidalMode && mEllipsoid ==
GEO_NONE )
1384 QgsDebugMsg(
"We're measuing on planimetric distance/area on given CRS, measured value is in CRS units" );
1390 factorUnits *= factorUnits;
1393 measure *= factorUnits;
1395 measureUnits = displayUnits;
1404 double result = length * factorUnits;
1418 double result = area * factorUnits;
const QgsCurveV2 * exteriorRing() const
double convertLengthMeasurement(double length, QGis::UnitType toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
int numGeometries() const
Returns the number of geometries within the collection.
QgsCoordinateReferenceSystem crsByOgcWmsCrs(const QString &ogcCrs) const
Returns the CRS from a given OGC WMS-format Coordinate Reference System string.
virtual QgsPolygonV2 * surfaceToPolygon() const =0
const QgsCurveV2 * interiorRing(int i) const
~QgsDistanceArea()
Destructor.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
void computeAreaInit()
precalculates some values (must be called always when changing ellipsoid)
QString toProj4() const
Returns a Proj4 string representation of this CRS.
Abstract base class for all geometries.
A geometry is the spatial representation of a feature.
bool setEllipsoid(const QString &ellipsoid)
Sets ellipsoid by its acronym.
double convertAreaMeasurement(double area, QgsUnitTypes::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
double toDouble(bool *ok) const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
QString trUtf8(const char *sourceText, const char *disambiguation, int n)
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
QgsCoordinateReferenceSystem crsBySrsId(long srsId) const
Returns the CRS from a specified QGIS SRS ID.
double y() const
Get the y value of the point.
bool willUseEllipsoid() const
Returns whether calculations will use the ellipsoid.
static QString toString(QGis::UnitType unit)
Returns a translated string representing a distance unit.
QString number(int n, int base)
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
void append(const T &value)
QGis::UnitType lengthUnits() const
Returns the units of distance for length calculations made by this object.
#define QgsDebugMsgLevel(str, level)
Line string geometry type, with support for z-dimension and m-values.
QGis::UnitType mapUnits() const
Returns the units for the projection used by the CRS.
double bearing(const QgsPoint &p1, const QgsPoint &p2) const
compute bearing - in radians
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
const long GEOCRS_ID
Magic number for a geographic coord sys in QGIS srs.db tbl_srs.srs_id.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
Multi surface geometry collection.
double measureLine(const QList< QgsPoint > &points) const
Measures the length of a line with multiple segments.
double computePolygonFlatArea(const QList< QgsPoint > &points) const
double measurePolygon(const QList< QgsPoint > &points) const
measures polygon area
bool saveAsUserCRS(const QString &name)
Save the proj4-string as a custom CRS.
A class to represent a point.
QString toString() const
String representation of the point (x,y)
static double fromUnitToUnitFactor(QGis::UnitType fromUnit, QGis::UnitType toUnit)
Returns the conversion factor between the specified distance units.
double computePolygonArea(const QList< QgsPoint > &points) const
calculates area of polygon on ellipsoid algorithm has been taken from GRASS: gis/area_poly1.c
virtual double perimeter() const
Returns the perimeter of the geometry.
double measureArea(const QgsGeometry *geometry) const
Measures the area of a geometry.
QgsDistanceArea & operator=(const QgsDistanceArea &origDA)
Assignment operator.
static Q_DECL_DEPRECATED QString textUnit(double value, int decimals, QGis::UnitType u, bool isArea, bool keepBaseUnit=false)
Returns a measurement formatted as a friendly string.
double computeDistanceFlat(const QgsPoint &p1, const QgsPoint &p2) const
uses flat / planimetric / Euclidean distance
General purpose distance and area calculator.
double measurePerimeter(const QgsGeometry *geometry) const
Measures the perimeter of a polygon geometry.
QgsUnitTypes::AreaUnit areaUnits() const
Returns the units of area for areal calculations made by this object.
QString ellipsoid() const
Returns ellipsoid's acronym.
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
QString mid(int position, int n) const
QgsCoordinateReferenceSystem crsByProj4(const QString &proj4) const
Returns the CRS from a proj4 style formatted string.
double computeDistanceBearing(const QgsPoint &p1, const QgsPoint &p2, double *course1=nullptr, double *course2=nullptr) const
calculates distance from two points on ellipsoid based on inverse Vincenty's formulae ...
QgsPolygonV2 * surfaceToPolygon() const override
void convertMeasurement(double &measure, QGis::UnitType &measureUnits, QGis::UnitType displayUnits, bool isArea) const
Helper for conversion between physical units.
static AreaUnit distanceToAreaUnit(QGis::UnitType distanceUnit)
Converts a distance unit to its corresponding area unit, eg meters to square meters.
void setSourceAuthId(const QString &authid)
sets source spatial reference system by authid
Class for storing a coordinate reference system (CRS)
virtual int dimension() const =0
Returns the inherent dimension of the geometry.
virtual QgsLineStringV2 * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
virtual double length() const
Returns the length of the geometry.
static QString formatArea(double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit=false)
Returns an area formatted as a friendly string.
UnitType
Map units that qgis supports.
QString left(int n) const
double measureLength(const QgsGeometry *geometry) const
Measures the length of a geometry.
static QString srsDbFilePath()
Returns the path to the srs.db file.
static QString formatDistance(double distance, int decimals, QGis::UnitType unit, bool keepBaseUnit=false)
Returns an distance formatted as a friendly string.
Custom exception class for Coordinate Reference System related exceptions.
QgsWKBTypes::Type readHeader() const
Q_DECL_DEPRECATED double measure(const QgsGeometry *geometry) const
General measurement (line distance or polygon area)
const_iterator constEnd() const
const_iterator constBegin() const
long srsid() const
Returns the SrsId, if available.
Abstract base class for curved geometry type.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QgsDistanceArea()
Constructor.
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
virtual void points(QgsPointSequenceV2 &pt) const =0
Returns a list of points within the curve.
static void convertPointList(const QList< QgsPoint > &input, QgsPointSequenceV2 &output)
Upgrades a point list from QgsPoint to QgsPointV2.
virtual double area() const
Returns the area of the geometry.
double x() const
Get the x value of the point.
void setEllipsoidalMode(bool flag)
Sets whether coordinates must be projected to ellipsoid before measuring.
double computeDistance(const QList< QgsPoint > &points) const
calculate distance with given coordinates (does not do a transform anymore)
int numInteriorRings() const
QByteArray toUtf8() const