[QGIS Commit] r8452 - trunk/qgis/src/core
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat May 17 13:54:39 EDT 2008
Author: jef
Date: 2008-05-17 13:54:39 -0400 (Sat, 17 May 2008)
New Revision: 8452
Modified:
trunk/qgis/src/core/qgslabel.cpp
trunk/qgis/src/core/qgslabel.h
Log:
some labeling cleanups (fixes #1088)
Modified: trunk/qgis/src/core/qgslabel.cpp
===================================================================
--- trunk/qgis/src/core/qgslabel.cpp 2008-05-17 12:52:44 UTC (rev 8451)
+++ trunk/qgis/src/core/qgslabel.cpp 2008-05-17 17:54:39 UTC (rev 8452)
@@ -14,7 +14,8 @@
* *
***************************************************************************/
-#include <math.h> //needed for win32 build (ts)
+#include <cmath>
+#include <limits>
#include <QString>
#include <QFont>
@@ -45,10 +46,8 @@
static const char * const ident_ =
"$Id$";
-
QgsLabel::QgsLabel( const QgsFieldMap & fields )
{
-
mField = fields;
mLabelFieldIdx.resize ( LabelFieldCount );
for ( int i = 0; i < LabelFieldCount; i++ )
@@ -459,8 +458,8 @@
{
QgsGeometry* geometry = feature.geometry();
unsigned char *geom = geometry->wkbBuffer();
+ size_t geomlen = geometry->wkbSize();
QGis::WKBTYPE wkbType = geometry->wkbType();
-
QgsPoint point;
switch (wkbType)
@@ -472,10 +471,11 @@
case QGis::WKBPolygon25D:
case QGis::WKBPolygon:
{
- labelPoint(point, geom);
+ labelPoint(point, geom, geomlen);
points.push_back(point);
}
break;
+
case QGis::WKBMultiPoint25D:
case QGis::WKBMultiPoint:
case QGis::WKBMultiLineString25D:
@@ -484,11 +484,15 @@
case QGis::WKBMultiPolygon:
// Return a position for each individual in the multi-feature
{
- int numFeatures = (int)(*(geom + 5));
- geom += 9; // now points to start of array of WKB's
- for (int i = 0; i < numFeatures; ++i)
+ assert( 1+sizeof(wkbType)+sizeof(int)<=geomlen );
+ geom += 1+sizeof(wkbType);
+ int nFeatures = *(unsigned int *)geom;
+ geom += sizeof(int);
+
+ unsigned char *feature = geom;
+ for (int i = 0; i<nFeatures && feature; ++i)
{
- geom = labelPoint(point, geom);
+ feature = labelPoint(point, feature, geom+geomlen-feature);
points.push_back(point);
}
}
@@ -498,156 +502,126 @@
}
}
-unsigned char* QgsLabel::labelPoint ( QgsPoint& point, unsigned char* geom)
+unsigned char* QgsLabel::labelPoint ( QgsPoint& point, unsigned char *geom, size_t geomlen)
{
- // Number of bytes that ints and doubles take in the WKB format.
- static const unsigned int sizeOfInt = 4;
- static const unsigned int sizeOfDouble = 8;
+ // verify that local types match sizes as WKB spec
+ assert( sizeof(int) == 4 );
+ assert( sizeof(QGis::WKBTYPE) == 4 );
+ assert( sizeof(double) == 8 );
- QGis::WKBTYPE wkbType;
- bool hasZValue = false;
- double *x, *y;
- unsigned char *ptr;
- int *nPoints;
- // Upon return from this function, this variable will contain a
- // pointer to the first byte beyond the current feature.
- unsigned char *nextFeature = geom;
+ if(geom==NULL) {
+ QgsDebugMsg("empty wkb");
+ return NULL;
+ }
- memcpy(&wkbType, (geom+1), sizeof(wkbType));
+ QGis::WKBTYPE wkbType;
+ unsigned char *geomend = geom+geomlen;
- switch (wkbType)
+ assert( geom+1+sizeof(wkbType)<=geomend );
+
+ geom++; // skip endianess
+ memcpy(&wkbType, geom, sizeof(wkbType));
+ geom += sizeof(wkbType);
+
+ int dims = 2;
+
+ switch (wkbType)
+ {
+ case QGis::WKBPoint25D:
+ case QGis::WKBPoint:
{
- case QGis::WKBPoint25D:
- case QGis::WKBPoint:
+ assert( geom+2*sizeof(double)<=geomend );
+ double *pts = (double *)geom;
+ point.set( pts[0], pts[1] );
+ geom += 2*sizeof(double);
+ }
+ break;
+
+ case QGis::WKBLineString25D:
+ dims=3;
+ case QGis::WKBLineString: // Line center
+ {
+ assert( geom+sizeof(int)<=geomend );
+ int nPoints = *(unsigned int *)geom;
+ geom += sizeof(int);
+
+ assert( geom+nPoints*sizeof(double)*dims<=geomend );
+
+ // get line center
+ double *pts = (double *)geom;
+ double tl = 0.0;
+ for (int i = 1; i < nPoints; i++)
{
- x = (double *) (geom + 5);
- y = (double *) (geom + 5 + sizeof(double));
- point.set(*x, *y);
- nextFeature += 1 + sizeOfInt + sizeOfDouble*2;
+ double dx = pts[dims*i] - pts[dims*(i-1)];
+ double dy = pts[dims*i+1] - pts[dims*(i-1)+1];
+ tl += sqrt(dx*dx + dy*dy);
}
- break;
- case QGis::WKBLineString25D:
- hasZValue = true;
- case QGis::WKBLineString: // Line center
+ tl /= 2.0;
+
+ // find line center
+ double l = 0.0;
+ for (int i=1; i < nPoints; i++)
{
- double dx, dy, tl, l;
- ptr = geom + 5;
- nPoints = (int *)ptr;
- if(hasZValue)
- {
- nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*3;
- }
- else
- {
- nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*2;
- }
- ptr = geom + 1 + 2 * sizeof(int);
+ double dx = pts[dims*i] - pts[dims*(i-1)];
+ double dy = pts[dims*i+1] - pts[dims*(i-1)+1];
+ double dl = sqrt(dx*dx + dy*dy);
- tl = 0;
- for (int i = 1; i < *nPoints; i++)
+ if ( l+dl > tl )
{
- if(hasZValue)
- {
- dx = ((double *)ptr)[3*i] - ((double *)ptr)[3*i-3];
- dy = ((double *)ptr)[3*i+1] - ((double *)ptr)[3*i-2];
- }
- else
- {
- dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
- dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
- }
- tl += sqrt(dx*dx + dy*dy);
+ double k = (tl-l)/dl;
+
+ point.set( pts[dims*(i-1)] + k * dx,
+ pts[dims*(i-1)+1] + k * dy);
+ break;
}
- tl /= 2;
- l = 0;
- for (int i = 1; i < *nPoints; i++)
- {
- double dl;
- if(hasZValue)
- {
- dx = ((double *)ptr)[3*i] - ((double *)ptr)[3*i-3];
- dy = ((double *)ptr)[3*i+1] - ((double *)ptr)[3*i-2];
- }
- else
- {
- dx = ((double *)ptr)[2*i] - ((double *)ptr)[2*i-2];
- dy = ((double *)ptr)[2*i+1] - ((double *)ptr)[2*i-1];
- }
- dl = sqrt(dx*dx + dy*dy);
+ l += dl;
+ }
- if ( l+dl > tl )
- {
- l = tl - l;
- double k = l/dl;
+ geom += nPoints*sizeof(double)*dims;
+ }
+ break;
- if(hasZValue)
- {
- point.setX ( ((double *)ptr)[3*i-3] + k * dx );
- point.setY ( ((double *)ptr)[3*i-2] + k * dy );
- }
- else
- {
- point.setX ( ((double *)ptr)[2*i-2] + k * dx );
- point.setY ( ((double *)ptr)[2*i-1] + k * dy );
- }
- break;
- }
- l += dl;
- }
- }
- break;
+ case QGis::WKBPolygon25D:
+ dims = 3;
+ case QGis::WKBPolygon: // centroid of outer ring
+ {
+ assert( geom+sizeof(int)<=geomend);
+ int nRings = *(unsigned int *)geom;
+ geom += sizeof(int);
- case QGis::WKBPolygon25D:
- hasZValue = true;
- case QGis::WKBPolygon:
+ for (int i=0; i<nRings; ++i)
{
- double sx, sy;
- ptr = geom + 1 + 2 * sizeof(int); // set pointer to the first ring
- nPoints = (int *) ptr;
- ptr += 4;
- sx = sy = 0;
- for (int i = 0; i < *nPoints-1; i++)
- {
- if(hasZValue)
- {
- sx += ((double *)ptr)[3*i];
- sy += ((double *)ptr)[3*i+1];
- }
- else
- {
- sx += ((double *)ptr)[2*i];
- sy += ((double *)ptr)[2*i+1];
- }
+ assert( geom+sizeof(int)<=geomend );
+ int nPoints = *(unsigned int *)geom;
+ geom += sizeof(int);
+
+ assert( geom+nPoints*sizeof(double)*dims<=geomend );
+
+ if( i==0 ) {
+ double sx=0.0, sy=0.0;
+ double *pts = (double*) geom;
+ for (int j=0; j<nPoints-1; j++) {
+ sx += pts[dims*j];
+ sy += pts[dims*j+1];
+ }
+ point.set( sx/(nPoints-1),
+ sy/(nPoints-1) );
}
- point.setX ( sx/(*nPoints-1) );
- point.setY ( sy/(*nPoints-1) );
- // Work out a pointer to the next feature after this one.
- int numRings = (int)(*(geom+1+sizeOfInt));
- unsigned char* nextRing = nextFeature + 1 + 2*sizeOfInt;
- for (int i = 0; i < numRings; ++i)
- {
- int numPoints = (int)(*nextRing);
- // get the start of the next ring
- if(hasZValue)
- {
- nextRing += sizeOfInt + numPoints*sizeOfDouble*3;
- }
- else
- {
- nextRing += sizeOfInt + numPoints*sizeOfDouble*2;
- }
- }
- nextFeature = nextRing;
- }
- break;
- default:
- // To get here is a bug because our caller should be filtering
- // on wkb type.
- break;
+ geom += nPoints*sizeof(double)*dims;
+ }
}
- return nextFeature;
+ break;
+
+ default:
+ // To get here is a bug because our caller should be filtering
+ // on wkb type.
+ QgsDebugMsg("unsupported wkb type");
+ return NULL;
+ }
+
+ return geom;
}
static int _elementFieldIndex(QDomElement& el)
Modified: trunk/qgis/src/core/qgslabel.h
===================================================================
--- trunk/qgis/src/core/qgslabel.h 2008-05-17 12:52:44 UTC (rev 8451)
+++ trunk/qgis/src/core/qgslabel.h 2008-05-17 17:54:39 UTC (rev 8452)
@@ -133,7 +133,7 @@
void labelPoint ( std::vector<QgsPoint>&, QgsFeature & feature );
/** Get label point for the given feature in wkb format. */
- unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb);
+ unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb, size_t wkblen);
/** Color to draw selected features */
QColor mSelectionColor;
More information about the QGIS-commit
mailing list