Quantum GIS API Documentation  1.7.4
src/core/qgscentralpointpositionmanager.cpp
Go to the documentation of this file.
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( &currentX, &( wkb[currentPosition] ), sizeof( double ) );
00094       currentPosition += sizeof( double );
00095       memcpy( &currentY, &( 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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines