35 #define M_PI 3.14159265358979323846
38 #define DEG2RAD(x) ((x)*M_PI/180)
44 mEllipsoidalMode =
false;
59 delete mCoordTransform;
65 if (
this == & origDA )
77 mEllipsoidalMode = origDA.mEllipsoidalMode;
78 mEllipsoid = origDA.mEllipsoid;
79 mSemiMajor = origDA.mSemiMajor;
80 mSemiMinor = origDA.mSemiMinor;
81 mInvFlattening = origDA.mInvFlattening;
90 mEllipsoidalMode = flag;
114 QString radius, parameter2;
120 sqlite3_stmt *myPreparedStatement;
134 if ( ellipsoid.startsWith(
"PARAMETER" ) )
136 QStringList paramList = ellipsoid.split(
":" );
137 bool semiMajorOk, semiMinorOk;
138 double semiMajor = paramList[1].toDouble( & semiMajorOk );
139 double semiMinor = paramList[2].toDouble( & semiMinorOk );
140 if ( semiMajorOk && semiMinorOk )
162 QString mySql =
"select radius, parameter2 from tbl_ellipsoid where acronym='" + ellipsoid +
"'";
163 myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
165 if ( myResult == SQLITE_OK )
167 if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW )
169 radius = QString((
char * )sqlite3_column_text( myPreparedStatement, 0 ) );
170 parameter2 = QString((
char * )sqlite3_column_text( myPreparedStatement, 1 ) );
174 sqlite3_finalize( myPreparedStatement );
175 sqlite3_close( myDatabase );
178 if ( radius.isEmpty() || parameter2.isEmpty() )
180 QgsDebugMsg( QString(
"setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) );
185 if ( radius.left( 2 ) ==
"a=" )
186 mSemiMajor = radius.mid( 2 ).toDouble();
189 QgsDebugMsg( QString(
"setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) );
196 if ( parameter2.left( 2 ) ==
"b=" )
198 mSemiMinor = parameter2.mid( 2 ).toDouble();
199 mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor );
201 else if ( parameter2.left( 3 ) ==
"rf=" )
203 mInvFlattening = parameter2.mid( 3 ).toDouble();
204 mSemiMinor = mSemiMajor - ( mSemiMajor / mInvFlattening );
208 QgsDebugMsg( QString(
"setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) );
212 QgsDebugMsg( QString(
"setEllipsoid: a=%1, b=%2, 1/f=%3" ).arg( mSemiMajor ).arg( mSemiMinor ).arg( mInvFlattening ) );
216 QString proj4 =
"+proj=longlat +ellps=" + ellipsoid +
" +no_defs";
223 if ( destCRS.
srsid() == 0 )
225 QString myName = QString(
" * %1 (%2)" )
226 .arg(
QObject::tr(
"Generated CRS",
"A CRS automatically generated from layer info get this prefix for description" ) )
247 mEllipsoid = QString(
"PARAMETER:%1:%2" ).arg( semiMajor ).arg( semiMinor );
248 mSemiMajor = semiMajor;
249 mSemiMinor = semiMinor;
250 mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor );
262 const unsigned char* wkb = geometry->
asWkb();
271 double res, resTotal = 0;
275 bool hasZptr =
false;
284 QgsDebugMsg(
"returning " + QString::number( res ) );
292 for ( i = 0; i < count; i++ )
297 QgsDebugMsg(
"returning " + QString::number( resTotal ) );
305 QgsDebugMsg(
"returning " + QString::number( res ) );
313 for ( i = 0; i < count; i++ )
323 QgsDebugMsg(
"returning " + QString::number( resTotal ) );
327 QgsDebugMsg( QString(
"measure: unexpected geometry type: %1" ).arg( wkbType ) );
337 const unsigned char* wkb = geometry->
asWkb();
345 double res = 0.0, resTotal = 0.0;
349 bool hasZptr =
false;
364 QgsDebugMsg(
"returning " + QString::number( res ) );
372 for ( i = 0; i < count; i++ )
382 QgsDebugMsg(
"returning " + QString::number( resTotal ) );
386 QgsDebugMsg( QString(
"measure: unexpected geometry type: %1" ).arg( wkbType ) );
398 QList<QgsPoint> points;
401 QgsDebugMsg(
"This feature WKB has " + QString::number( nPoints ) +
" points" );
403 for (
int i = 0; i < nPoints; ++i )
409 wkbPtr +=
sizeof( double );
421 if ( points.size() < 2 )
429 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
430 p1 = mCoordTransform->
transform( points[0] );
434 for ( QList<QgsPoint>::const_iterator i = points.begin(); i != points.end(); ++i )
436 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
470 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
472 QgsDebugMsgLevel( QString(
"Ellipsoidal calculations is enabled, using ellipsoid %1" ).arg( mEllipsoid ), 4 );
477 QgsDebugMsgLevel( QString(
"New points are %1 and %2, calculating..." ).arg( pp1.
toString( 4 ) ).arg( pp2.toString( 4 ) ), 4 );
518 QList<QgsPoint> points;
528 for (
int idx = 0; idx < numRings; idx++ )
535 for (
int jdx = 0; jdx < nPoints; jdx++ )
541 wkbPtr +=
sizeof( double );
546 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
550 points.append( pnt );
553 if ( points.size() > 2 )
596 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
599 for ( QList<QgsPoint>::const_iterator i = points.begin(); i != points.end(); ++i )
601 pts.append( mCoordTransform->
transform( *i ) );
624 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
632 double dx = p2.
x() - p1.
x();
633 double dy = p2.
y() - p1.
y();
634 bearing = atan2( dx, dy );
646 double* course1,
double* course2 )
648 if ( p1.
x() == p2.
x() && p1.
y() == p2.
y() )
652 double a = mSemiMajor;
653 double b = mSemiMinor;
654 double f = 1 / mInvFlattening;
659 double L = p2_lon - p1_lon;
660 double U1 = atan(( 1 - f ) * tan( p1_lat ) );
661 double U2 = atan(( 1 - f ) * tan( p2_lat ) );
662 double sinU1 = sin( U1 ), cosU1 = cos( U1 );
663 double sinU2 = sin( U2 ), cosU2 = cos( U2 );
665 double lambdaP = 2 *
M_PI;
667 double sinLambda = 0;
668 double cosLambda = 0;
673 double cosSqAlpha = 0;
674 double cos2SigmaM = 0;
680 while ( qAbs( lambda - lambdaP ) > 1e-12 && --iterLimit > 0 )
682 sinLambda = sin( lambda );
683 cosLambda = cos( lambda );
684 tu1 = ( cosU2 * sinLambda );
685 tu2 = ( cosU1 * sinU2 - sinU1 * cosU2 * cosLambda );
686 sinSigma = sqrt( tu1 * tu1 + tu2 * tu2 );
687 cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
688 sigma = atan2( sinSigma, cosSigma );
689 alpha = asin( cosU1 * cosU2 * sinLambda / sinSigma );
690 cosSqAlpha = cos( alpha ) * cos( alpha );
691 cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
692 C = f / 16 * cosSqAlpha * ( 4 + f * ( 4 - 3 * cosSqAlpha ) );
694 lambda = L + ( 1 - C ) * f * sin( alpha ) *
695 ( sigma + C * sinSigma * ( cos2SigmaM + C * cosSigma * ( -1 + 2 * cos2SigmaM * cos2SigmaM ) ) );
698 if ( iterLimit == 0 )
701 double uSq = cosSqAlpha * ( a * a - b * b ) / ( b * b );
702 double A = 1 + uSq / 16384 * ( 4096 + uSq * ( -768 + uSq * ( 320 - 175 * uSq ) ) );
703 double B = uSq / 1024 * ( 256 + uSq * ( -128 + uSq * ( 74 - 47 * uSq ) ) );
704 double deltaSigma = B * sinSigma * ( cos2SigmaM + B / 4 * ( cosSigma * ( -1 + 2 * cos2SigmaM * cos2SigmaM ) -
705 B / 6 * cos2SigmaM * ( -3 + 4 * sinSigma * sinSigma ) * ( -3 + 4 * cos2SigmaM * cos2SigmaM ) ) );
706 double s = b * A * ( sigma - deltaSigma );
710 *course1 = atan2( tu1, tu2 );
715 *course2 = atan2( cosU1 * sinLambda, -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda ) +
M_PI;
723 return sqrt(( p2.
x() - p1.
x() ) * ( p2.
x() - p1.
x() ) + ( p2.
y() - p1.
y() ) * ( p2.
y() - p1.
y() ) );
728 if ( points.size() < 2 )
738 for ( QList<QgsPoint>::const_iterator i = points.begin(); i != points.end(); ++i )
741 if ( mEllipsoidalMode && ( mEllipsoid !=
GEO_NONE ) )
770 double QgsDistanceArea::getQ(
double x )
777 return sinx *( 1 + sinx2 *( m_QA + sinx2 *( m_QB + sinx2 * m_QC ) ) );
781 double QgsDistanceArea::getQbar(
double x )
788 return cosx *( m_QbarA + cosx2 *( m_QbarB + cosx2 *( m_QbarC + cosx2 * m_QbarD ) ) );
800 double a2 = ( mSemiMajor * mSemiMajor );
801 double e2 = 1 - ( a2 / ( mSemiMinor * mSemiMinor ) );
809 m_AE = a2 * ( 1 - e2 );
811 m_QA = ( 2.0 / 3.0 ) * e2;
812 m_QB = ( 3.0 / 5.0 ) * e4;
813 m_QC = ( 4.0 / 7.0 ) * e6;
815 m_QbarA = -1.0 - ( 2.0 / 3.0 ) * e2 - ( 3.0 / 5.0 ) * e4 - ( 4.0 / 7.0 ) * e6;
816 m_QbarB = ( 2.0 / 9.0 ) * e2 + ( 2.0 / 5.0 ) * e4 + ( 4.0 / 7.0 ) * e6;
817 m_QbarC = - ( 3.0 / 25.0 ) * e4 - ( 12.0 / 35.0 ) * e6;
818 m_QbarD = ( 4.0 / 49.0 ) * e6;
820 m_Qp = getQ( M_PI / 2 );
821 m_E = 4 * M_PI * m_Qp * m_AE;
829 double x1, y1, x2, y2, dx, dy;
834 if (( ! mEllipsoidalMode ) || ( mEllipsoid ==
GEO_NONE ) )
838 int n = points.size();
839 x2 =
DEG2RAD( points[n-1].x() );
840 y2 =
DEG2RAD( points[n-1].y() );
841 Qbar2 = getQbar( y2 );
845 for (
int i = 0; i < n; i++ )
853 Qbar2 = getQbar( y2 );
856 while ( x1 - x2 >
M_PI )
859 while ( x2 - x1 >
M_PI )
863 area += dx * ( m_Qp - getQ( y2 ) );
865 if (( dy = y2 - y1 ) != 0.0 )
866 area += dx * getQ( y2 ) - ( dx / dy ) * ( Qbar2 - Qbar1 );
868 if (( area *= m_AE ) < 0.0 )
878 if ( area > m_E / 2 )
890 size = points.size();
893 for ( i = 0; i <
size; i++ )
898 area = area + points[i].x() * points[( i+1 ) % size].y() - points[( i+1 ) % size].x() * points[i].y();
916 unitLabel = QObject::trUtf8(
" m²" );
918 else if ( qAbs( value ) > 1000000.0 )
920 unitLabel = QObject::trUtf8(
" km²" );
921 value = value / 1000000.0;
923 else if ( qAbs( value ) > 10000.0 )
926 value = value / 10000.0;
930 unitLabel = QObject::trUtf8(
" m²" );
935 if ( keepBaseUnit || qAbs( value ) == 0.0 )
939 else if ( qAbs( value ) > 1000.0 )
942 value = value / 1000;
944 else if ( qAbs( value ) < 0.01 )
947 value = value * 1000;
949 else if ( qAbs( value ) < 0.1 )
963 if ( keepBaseUnit || qAbs( value ) <= 0.5*43560.0 )
968 else if ( qAbs( value ) <= 0.5*5280.0*5280.0 )
978 value /= 5280.0 * 5280.0;
983 if ( qAbs( value ) <= 528.0 || keepBaseUnit )
985 if ( qAbs( value ) == 1.0 )
1018 if ( qAbs( value ) == 1.0 )
1028 QgsDebugMsg( QString(
"Error: not picked up map units - actual value = %1" ).arg( u ) );
1031 return QLocale::system().toString( value,
'f', decimals ) + unitLabel;
1045 QgsDebugMsg(
"We're measuring on an ellipsoid or using projections, the system is returning meters" );
1047 else if ( mEllipsoidalMode && mEllipsoid ==
GEO_NONE )
1051 QgsDebugMsg(
"We're measuing on planimetric distance/area on given CRS, measured value is in CRS units" );
1057 factorUnits *= factorUnits;
1060 measure *= factorUnits;
1062 measureUnits = displayUnits;