Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgscentralpointpositionmanager.cpp - description 00003 ---------------------------------- 00004 begin : January 2007 00005 copyright : (C) 2007 by Marco Hugentobler 00006 email : marco dot hugentobler at karto dot baug dot ethz dot ch 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "qgscentralpointpositionmanager.h" 00019 #include "qgsgeometry.h" 00020 #include "qgsoverlayobject.h" 00021 #include "qgsvectoroverlay.h" 00022 #include <map> 00023 00024 QgsCentralPointPositionManager::QgsCentralPointPositionManager() 00025 { 00026 00027 } 00028 00029 QgsCentralPointPositionManager::~QgsCentralPointPositionManager() 00030 { 00031 00032 } 00033 00034 void QgsCentralPointPositionManager::addLayer( QgsVectorLayer* vl, QList<QgsVectorOverlay*>& overlays ) 00035 { 00036 Q_UNUSED( vl ); 00037 mOverlays << overlays; 00038 } 00039 00040 void QgsCentralPointPositionManager::removeLayers() 00041 { 00042 mOverlays.clear(); 00043 } 00044 00045 void QgsCentralPointPositionManager::findObjectPositions( const QgsRenderContext& context, QGis::UnitType unitType ) 00046 { 00047 Q_UNUSED( context ); 00048 Q_UNUSED( unitType ); 00049 QList<QgsVectorOverlay*>::iterator overlay_it = mOverlays.begin(); 00050 QgsVectorOverlay* currentOverlay = 0; 00051 QgsPoint currentPosition; 00052 00053 for ( ; overlay_it != mOverlays.end(); ++overlay_it ) 00054 { 00055 currentOverlay = *overlay_it; 00056 if ( !currentOverlay ) 00057 { 00058 continue; 00059 } 00060 00061 QMap<QgsFeatureId, QgsOverlayObject*>* objectMap = currentOverlay->overlayObjects(); 00062 if ( !objectMap ) 00063 { 00064 continue; 00065 } 00066 00067 QMap<QgsFeatureId, QgsOverlayObject*>::iterator object_it = objectMap->begin(); 00068 for ( ; object_it != objectMap->end(); ++object_it ) 00069 { 00070 if ( findObjectPosition( object_it.value()->geometry()->asWkb(), currentPosition ) == 0 ) 00071 { 00072 object_it.value()->addPosition( currentPosition ); 00073 } 00074 } 00075 } 00076 } 00077 00078 int QgsCentralPointPositionManager::findObjectPosition( const unsigned char* wkb, QgsPoint& position ) const 00079 { 00080 QGis::WkbType type; 00081 int currentPosition = 0; //parsing position in the wkb binary 00082 double currentX, currentY; 00083 bool hasZValue = false; 00084 00085 currentPosition += 1; 00086 memcpy( &type, &( wkb[currentPosition] ), sizeof( int ) ); 00087 currentPosition += sizeof( int ); 00088 00089 switch ( type ) 00090 { 00091 case QGis::WKBMultiPoint: 00092 case QGis::WKBMultiPoint25D: 00093 currentPosition += ( 2 * sizeof( int ) + 1 ); 00094 case QGis::WKBPoint25D: 00095 case QGis::WKBPoint: 00096 memcpy( ¤tX, &( wkb[currentPosition] ), sizeof( double ) ); 00097 currentPosition += sizeof( double ); 00098 memcpy( ¤tY, &( wkb[currentPosition] ), sizeof( double ) ); 00099 position.setX( currentX ); 00100 position.setY( currentY ); 00101 return 0; 00102 00103 case QGis::WKBMultiLineString25D: 00104 case QGis::WKBMultiLineString: 00105 { 00106 int numberOfLines; 00107 memcpy( &numberOfLines, &( wkb[currentPosition] ), sizeof( int ) ); 00108 if ( numberOfLines < 1 ) 00109 { 00110 return 1; 00111 } 00112 currentPosition += ( 2 * sizeof( int ) + 1 ); 00113 } 00114 case QGis::WKBLineString25D: 00115 case QGis::WKBLineString://get the middle point 00116 { 00117 if ( type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString25D ) 00118 { 00119 hasZValue = true; 00120 } 00121 00122 int numberOfPoints; 00123 memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); 00124 currentPosition += sizeof( int ); 00125 if ( numberOfPoints < 1 ) 00126 { 00127 return 2; 00128 } 00129 if ( numberOfPoints > 2 ) 00130 { 00131 int midpoint = ( numberOfPoints - 1 ) / 2 ; 00132 for ( int i = 0; i < midpoint; ++i ) 00133 { 00134 currentPosition += 2 * sizeof( double ); 00135 if ( hasZValue ) 00136 { 00137 currentPosition += sizeof( double ); 00138 } 00139 } 00140 } 00141 double xPos, yPos; 00142 memcpy( &xPos, &( wkb[currentPosition] ), sizeof( double ) ); 00143 currentPosition += sizeof( double ); 00144 memcpy( &yPos, &( wkb[currentPosition] ), sizeof( double ) ); 00145 position.setX( xPos ); 00146 position.setY( yPos ); 00147 return 0; 00148 } 00149 00150 case QGis::WKBMultiPolygon25D: 00151 case QGis::WKBMultiPolygon: 00152 { 00153 int numberOfPolygons; 00154 memcpy( &numberOfPolygons, &( wkb[currentPosition] ), sizeof( int ) ); 00155 if ( numberOfPolygons < 1 ) 00156 { 00157 return 3; 00158 } 00159 currentPosition += sizeof( int ); 00160 currentPosition += ( 1 + sizeof( int ) ); 00161 } 00162 case QGis::WKBPolygon25D: 00163 case QGis::WKBPolygon: //calculate the centroid of the first ring 00164 { 00165 //2.5D or 2D type? 00166 if ( type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D ) 00167 { 00168 hasZValue = true; 00169 } 00170 //number of rings 00171 int numberOfRings; 00172 memcpy( &numberOfRings, &( wkb[currentPosition] ), sizeof( int ) ); 00173 if ( numberOfRings < 1 ) 00174 { 00175 return 4; 00176 } 00177 currentPosition += sizeof( int ); 00178 00179 //number of points 00180 int numberOfPoints; 00181 memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); 00182 if ( numberOfPoints < 1 ) 00183 { 00184 return 5; 00185 } 00186 currentPosition += sizeof( int ); 00187 00188 double *x = new double[numberOfPoints]; 00189 double *y = new double[numberOfPoints]; 00190 00191 for ( int i = 0; i < numberOfPoints; ++i ) 00192 { 00193 memcpy( &( x[i] ), &( wkb[currentPosition] ), sizeof( double ) ); 00194 currentPosition += sizeof( double ); 00195 memcpy( &( y[i] ), &( wkb[currentPosition] ), sizeof( double ) ); 00196 currentPosition += sizeof( double ); 00197 if ( hasZValue ) 00198 { 00199 currentPosition += sizeof( double ); 00200 } 00201 } 00202 double centroidX, centroidY; 00203 int res = calculatePolygonCentroid( x, y, numberOfPoints, centroidX, centroidY ); 00204 delete [] x; 00205 delete [] y; 00206 00207 if ( res != 0 ) 00208 { 00209 return 1; 00210 } 00211 else 00212 { 00213 position.setX( centroidX ); 00214 position.setY( centroidY ); 00215 return 0; 00216 } 00217 } 00218 00219 default: 00220 return 6; 00221 } 00222 } 00223 00224 int QgsCentralPointPositionManager::calculatePolygonCentroid( double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY ) const 00225 { 00226 register int i, j; 00227 double ai, atmp = 0, xtmp = 0, ytmp = 0; 00228 if ( numberOfPoints < 3 ) 00229 { 00230 return 1; 00231 } 00232 00233 for ( i = numberOfPoints - 1, j = 0; j < numberOfPoints; i = j, j++ ) 00234 { 00235 ai = x[i] * y[j] - x[j] * y[i]; 00236 atmp += ai; 00237 xtmp += ( x[j] + x[i] ) * ai; 00238 ytmp += ( y[j] + y[i] ) * ai; 00239 } 00240 if ( atmp == 0 ) 00241 { 00242 return 2; 00243 } 00244 centroidX = xtmp / ( 3 * atmp ); 00245 centroidY = ytmp / ( 3 * atmp ); 00246 return 0; 00247 } 00248