00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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;
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:
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:
00161 {
00162
00163 if ( type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D )
00164 {
00165 hasZValue = true;
00166 }
00167
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
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