Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgscentralpointpositionmanager.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscentralpointpositionmanager.cpp - description
3  ----------------------------------
4  begin : January 2007
5  copyright : (C) 2007 by Marco Hugentobler
6  email : marco dot hugentobler at karto dot baug dot ethz dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsgeometry.h"
20 #include "qgsoverlayobject.h"
21 #include "qgsvectoroverlay.h"
22 #include <map>
23 
25 {
26 
27 }
28 
30 {
31 
32 }
33 
34 void QgsCentralPointPositionManager::addLayer( QgsVectorLayer* vl, QList<QgsVectorOverlay*>& overlays )
35 {
36  mOverlays << overlays;
37 }
38 
40 {
41  mOverlays.clear();
42 }
43 
45 {
46  QList<QgsVectorOverlay*>::iterator overlay_it = mOverlays.begin();
47  QgsVectorOverlay* currentOverlay = 0;
48  QgsPoint currentPosition;
49 
50  for ( ; overlay_it != mOverlays.end(); ++overlay_it )
51  {
52  currentOverlay = *overlay_it;
53  if ( !currentOverlay )
54  {
55  continue;
56  }
57 
58  QMap<int, QgsOverlayObject*>* objectMap = currentOverlay->overlayObjects();
59  if ( !objectMap )
60  {
61  continue;
62  }
63 
64  QMap<int, QgsOverlayObject*>::iterator object_it = objectMap->begin();
65  for ( ; object_it != objectMap->end(); ++object_it )
66  {
67  if ( findObjectPosition( object_it.value()->geometry()->asWkb(), currentPosition ) == 0 )
68  {
69  object_it.value()->addPosition( currentPosition );
70  }
71  }
72  }
73 }
74 
75 int QgsCentralPointPositionManager::findObjectPosition( const unsigned char* wkb, QgsPoint& position ) const
76 {
77  QGis::WkbType type;
78  int currentPosition = 0; //parsing position in the wkb binary
79  double currentX, currentY;
80  bool hasZValue = false;
81 
82  currentPosition += 1;
83  memcpy( &type, &( wkb[currentPosition] ), sizeof( int ) );
84  currentPosition += sizeof( int );
85 
86  switch ( type )
87  {
90  currentPosition += ( 2 * sizeof( int ) + 1 );
91  case QGis::WKBPoint25D:
92  case QGis::WKBPoint:
93  memcpy( &currentX, &( wkb[currentPosition] ), sizeof( double ) );
94  currentPosition += sizeof( double );
95  memcpy( &currentY, &( wkb[currentPosition] ), sizeof( double ) );
96  position.setX( currentX );
97  position.setY( currentY );
98  return 0;
99 
102  {
103  int numberOfLines;
104  memcpy( &numberOfLines, &( wkb[currentPosition] ), sizeof( int ) );
105  if ( numberOfLines < 1 )
106  {
107  return 1;
108  }
109  currentPosition += ( 2 * sizeof( int ) + 1 );
110  }
112  case QGis::WKBLineString://get the middle point
113  {
114  if ( type == QGis::WKBLineString25D || type == QGis::WKBMultiLineString25D )
115  {
116  hasZValue = true;
117  }
118 
119  int numberOfPoints;
120  memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) );
121  currentPosition += sizeof( int );
122  if ( numberOfPoints < 1 )
123  {
124  return 2;
125  }
126  if ( numberOfPoints > 2 )
127  {
128  int midpoint = ( numberOfPoints - 1 ) / 2 ;
129  for ( int i = 0; i < midpoint; ++i )
130  {
131  currentPosition += 2 * sizeof( double );
132  if ( hasZValue )
133  {
134  currentPosition += sizeof( double );
135  }
136  }
137  }
138  double xPos, yPos;
139  memcpy( &xPos, &( wkb[currentPosition] ), sizeof( double ) );
140  currentPosition += sizeof( double );
141  memcpy( &yPos, &( wkb[currentPosition] ), sizeof( double ) );
142  position.setX( xPos );
143  position.setY( yPos );
144  return 0;
145  }
146 
149  {
150  int numberOfPolygons;
151  memcpy( &numberOfPolygons, &( wkb[currentPosition] ), sizeof( int ) );
152  if ( numberOfPolygons < 1 )
153  {
154  return 3;
155  }
156  currentPosition += sizeof( int );
157  currentPosition += ( 1 + sizeof( int ) );
158  }
159  case QGis::WKBPolygon25D:
160  case QGis::WKBPolygon: //calculate the centroid of the first ring
161  {
162  //2.5D or 2D type?
163  if ( type == QGis::WKBPolygon25D || type == QGis::WKBMultiPolygon25D )
164  {
165  hasZValue = true;
166  }
167  //number of rings
168  int numberOfRings;
169  memcpy( &numberOfRings, &( wkb[currentPosition] ), sizeof( int ) );
170  if ( numberOfRings < 1 )
171  {
172  return 4;
173  }
174  currentPosition += sizeof( int );
175 
176  //number of points
177  int numberOfPoints;
178  memcpy( &numberOfPoints, &( wkb[currentPosition] ), sizeof( int ) );
179  if ( numberOfPoints < 1 )
180  {
181  return 5;
182  }
183  currentPosition += sizeof( int );
184 
185  double *x = new double[numberOfPoints];
186  double *y = new double[numberOfPoints];
187 
188  for ( int i = 0; i < numberOfPoints; ++i )
189  {
190  memcpy( &( x[i] ), &( wkb[currentPosition] ), sizeof( double ) );
191  currentPosition += sizeof( double );
192  memcpy( &( y[i] ), &( wkb[currentPosition] ), sizeof( double ) );
193  currentPosition += sizeof( double );
194  if ( hasZValue )
195  {
196  currentPosition += sizeof( double );
197  }
198  }
199  double centroidX, centroidY;
200  int res = calculatePolygonCentroid( x, y, numberOfPoints, centroidX, centroidY );
201  delete [] x;
202  delete [] y;
203 
204  if ( res != 0 )
205  {
206  return 1;
207  }
208  else
209  {
210  position.setX( centroidX );
211  position.setY( centroidY );
212  return 0;
213  }
214  }
215 
216  default:
217  return 6;
218  }
219 }
220 
221 int QgsCentralPointPositionManager::calculatePolygonCentroid( double x[], double y[], int numberOfPoints, double& centroidX, double& centroidY ) const
222 {
223  register int i, j;
224  double ai, atmp = 0, xtmp = 0, ytmp = 0;
225  if ( numberOfPoints < 3 )
226  {
227  return 1;
228  }
229 
230  for ( i = numberOfPoints - 1, j = 0; j < numberOfPoints; i = j, j++ )
231  {
232  ai = x[i] * y[j] - x[j] * y[i];
233  atmp += ai;
234  xtmp += ( x[j] + x[i] ) * ai;
235  ytmp += ( y[j] + y[i] ) * ai;
236  }
237  if ( atmp == 0 )
238  {
239  return 2;
240  }
241  centroidX = xtmp / ( 3 * atmp );
242  centroidY = ytmp / ( 3 * atmp );
243  return 0;
244 }
245