Quantum GIS API Documentation
1.7.4
|
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 mOverlays << overlays; 00037 } 00038 00039 void QgsCentralPointPositionManager::removeLayers() 00040 { 00041 mOverlays.clear(); 00042 } 00043 00044 void QgsCentralPointPositionManager::findObjectPositions( const QgsRenderContext& context, QGis::UnitType unitType ) 00045 { 00046 QList<QgsVectorOverlay*>::iterator overlay_it = mOverlays.begin(); 00047 QgsVectorOverlay* currentOverlay = 0; 00048 QgsPoint currentPosition; 00049 00050 for ( ; overlay_it != mOverlays.end(); ++overlay_it ) 00051 { 00052 currentOverlay = *overlay_it; 00053 if ( !currentOverlay ) 00054 { 00055 continue; 00056 } 00057 00058 QMap<int, QgsOverlayObject*>* objectMap = currentOverlay->overlayObjects(); 00059 if ( !objectMap ) 00060 { 00061 continue; 00062 } 00063 00064 QMap<int, QgsOverlayObject*>::iterator object_it = objectMap->begin(); 00065 for ( ; object_it != objectMap->end(); ++object_it ) 00066 { 00067 if ( findObjectPosition( object_it.value()->geometry()->asWkb(), currentPosition ) == 0 ) 00068 { 00069 object_it.value()->addPosition( currentPosition ); 00070 } 00071 } 00072 } 00073 } 00074 00075 int QgsCentralPointPositionManager::findObjectPosition( const unsigned char* wkb, QgsPoint& position ) const 00076 { 00077 QGis::WkbType type; 00078 int currentPosition = 0; //parsing position in the wkb binary 00079 double currentX, currentY; 00080 bool hasZValue = false; 00081 00082 currentPosition += 1; 00083 memcpy( &type, &( wkb[currentPosition] ), sizeof( int ) ); 00084 currentPosition += sizeof( int ); 00085 00086 switch ( type ) 00087 { 00088 case QGis::WKBMultiPoint: 00089 case QGis::WKBMultiPoint25D: 00090 currentPosition += ( 2 * sizeof( int ) + 1 ); 00091 case QGis::WKBPoint25D: 00092 case QGis::WKBPoint: 00093 memcpy( ¤tX, &( wkb[currentPosition] ), sizeof( double ) ); 00094 currentPosition += sizeof( double ); 00095 memcpy( ¤tY, &( wkb[currentPosition] ), sizeof( double ) ); 00096 position.setX( currentX ); 00097 position.setY( currentY ); 00098 return 0; 00099 00100 case QGis::WKBMultiLineString25D: 00101 case QGis::WKBMultiLineString: 00102 { 00103 int numberOfLines; 00104 memcpy( &numberOfLines, &( wkb[currentPosition] ), sizeof( int ) ); 00105 if ( numberOfLines < 1 ) 00106 { 00107 return 1; 00108 } 00109 currentPosition += ( 2 * sizeof( int ) + 1 ); 00110 } 00111 case QGis::WKBLineString25D: 00112 case QGis::WKBLineString://get the middle point 00113 { 00114 if ( type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString25D ) 00115 { 00116 hasZValue = true; 00117 } 00118 00119 int numberOfPoints; 00120 memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); 00121 currentPosition += sizeof( int ); 00122 if ( numberOfPoints < 1 ) 00123 { 00124 return 2; 00125 } 00126 if ( numberOfPoints > 2 ) 00127 { 00128 int midpoint = ( numberOfPoints - 1 ) / 2 ; 00129 for ( int i = 0; i < midpoint; ++i ) 00130 { 00131 currentPosition += 2 * sizeof( double ); 00132 if ( hasZValue ) 00133 { 00134 currentPosition += sizeof( double ); 00135 } 00136 } 00137 } 00138 double xPos, yPos; 00139 memcpy( &xPos, &( wkb[currentPosition] ), sizeof( double ) ); 00140 currentPosition += sizeof( double ); 00141 memcpy( &yPos, &( wkb[currentPosition] ), sizeof( double ) ); 00142 position.setX( xPos ); 00143 position.setY( yPos ); 00144 return 0; 00145 } 00146 00147 case QGis::WKBMultiPolygon25D: 00148 case QGis::WKBMultiPolygon: 00149 { 00150 int numberOfPolygons; 00151 memcpy( &numberOfPolygons, &( wkb[currentPosition] ), sizeof( int ) ); 00152 if ( numberOfPolygons < 1 ) 00153 { 00154 return 3; 00155 } 00156 currentPosition += sizeof( int ); 00157 currentPosition += ( 1 + sizeof( int ) ); 00158 } 00159 case QGis::WKBPolygon25D: 00160 case QGis::WKBPolygon: //calculate the centroid of the first ring 00161 { 00162 //2.5D or 2D type? 00163 if ( type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D ) 00164 { 00165 hasZValue = true; 00166 } 00167 //number of rings 00168 int numberOfRings; 00169 memcpy( &numberOfRings, &( wkb[currentPosition] ), sizeof( int ) ); 00170 if ( numberOfRings < 1 ) 00171 { 00172 return 4; 00173 } 00174 currentPosition += sizeof( int ); 00175 00176 //number of points 00177 int numberOfPoints; 00178 memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) ); 00179 if ( numberOfPoints < 1 ) 00180 { 00181 return 5; 00182 } 00183 currentPosition += sizeof( int ); 00184 00185 double *x = new double[numberOfPoints]; 00186 double *y = new double[numberOfPoints]; 00187 00188 for ( int i = 0; i < numberOfPoints; ++i ) 00189 { 00190 memcpy( &( x[i] ), &( wkb[currentPosition] ), sizeof( double ) ); 00191 currentPosition += sizeof( double ); 00192 memcpy( &( y[i] ), &( wkb[currentPosition] ), sizeof( double ) ); 00193 currentPosition += sizeof( double ); 00194 if ( hasZValue ) 00195 { 00196 currentPosition += sizeof( double ); 00197 } 00198 } 00199 double centroidX, centroidY; 00200 int res = calculatePolygonCentroid( x, y, numberOfPoints, centroidX, centroidY ); 00201 delete [] x; 00202 delete [] y; 00203 00204 if ( res != 0 ) 00205 { 00206 return 1; 00207 } 00208 else 00209 { 00210 position.setX( centroidX ); 00211 position.setY( centroidY ); 00212 return 0; 00213 } 00214 } 00215 00216 default: 00217 return 6; 00218 } 00219 } 00220 00221 int QgsCentralPointPositionManager::calculatePolygonCentroid( double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY ) const 00222 { 00223 register int i, j; 00224 double ai, atmp = 0, xtmp = 0, ytmp = 0; 00225 if ( numberOfPoints < 3 ) 00226 { 00227 return 1; 00228 } 00229 00230 for ( i = numberOfPoints - 1, j = 0; j < numberOfPoints; i = j, j++ ) 00231 { 00232 ai = x[i] * y[j] - x[j] * y[i]; 00233 atmp += ai; 00234 xtmp += ( x[j] + x[i] ) * ai; 00235 ytmp += ( y[j] + y[i] ) * ai; 00236 } 00237 if ( atmp == 0 ) 00238 { 00239 return 2; 00240 } 00241 centroidX = xtmp / ( 3 * atmp ); 00242 centroidY = ytmp / ( 3 * atmp ); 00243 return 0; 00244 } 00245