14
14
* *
15
15
***************************************************************************/
16
16
17
- #include < math.h> // needed for win32 build (ts)
17
+ #include < cmath>
18
+ #include < limits>
18
19
19
20
#include < QString>
20
21
#include < QFont>
45
46
static const char * const ident_ =
46
47
" $Id$" ;
47
48
48
-
49
49
QgsLabel::QgsLabel ( const QgsFieldMap & fields )
50
50
{
51
-
52
51
mField = fields;
53
52
mLabelFieldIdx .resize ( LabelFieldCount );
54
53
for ( int i = 0 ; i < LabelFieldCount; i++ )
@@ -459,8 +458,8 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
459
458
{
460
459
QgsGeometry* geometry = feature.geometry ();
461
460
unsigned char *geom = geometry->wkbBuffer ();
461
+ size_t geomlen = geometry->wkbSize ();
462
462
QGis::WKBTYPE wkbType = geometry->wkbType ();
463
-
464
463
QgsPoint point;
465
464
466
465
switch (wkbType)
@@ -472,10 +471,11 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
472
471
case QGis::WKBPolygon25D:
473
472
case QGis::WKBPolygon:
474
473
{
475
- labelPoint (point, geom);
474
+ labelPoint (point, geom, geomlen );
476
475
points.push_back (point);
477
476
}
478
477
break ;
478
+
479
479
case QGis::WKBMultiPoint25D:
480
480
case QGis::WKBMultiPoint:
481
481
case QGis::WKBMultiLineString25D:
@@ -484,11 +484,15 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
484
484
case QGis::WKBMultiPolygon:
485
485
// Return a position for each individual in the multi-feature
486
486
{
487
- int numFeatures = (int )(*(geom + 5 ));
488
- geom += 9 ; // now points to start of array of WKB's
489
- for (int i = 0 ; i < numFeatures; ++i)
487
+ assert ( 1 +sizeof (wkbType)+sizeof (int )<=geomlen );
488
+ geom += 1 +sizeof (wkbType);
489
+ int nFeatures = *(unsigned int *)geom;
490
+ geom += sizeof (int );
491
+
492
+ unsigned char *feature = geom;
493
+ for (int i = 0 ; i<nFeatures && feature; ++i)
490
494
{
491
- geom = labelPoint (point, geom);
495
+ feature = labelPoint (point, feature, geom+geomlen-feature );
492
496
points.push_back (point);
493
497
}
494
498
}
@@ -498,156 +502,126 @@ void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature
498
502
}
499
503
}
500
504
501
- unsigned char * QgsLabel::labelPoint ( QgsPoint& point, unsigned char * geom)
505
+ unsigned char * QgsLabel::labelPoint ( QgsPoint& point, unsigned char * geom, size_t geomlen )
502
506
{
503
- // Number of bytes that ints and doubles take in the WKB format.
504
- static const unsigned int sizeOfInt = 4 ;
505
- static const unsigned int sizeOfDouble = 8 ;
507
+ // verify that local types match sizes as WKB spec
508
+ assert ( sizeof (int ) == 4 );
509
+ assert ( sizeof (QGis::WKBTYPE) == 4 );
510
+ assert ( sizeof (double ) == 8 );
511
+
512
+ if (geom==NULL ) {
513
+ QgsDebugMsg (" empty wkb" );
514
+ return NULL ;
515
+ }
516
+
517
+ QGis::WKBTYPE wkbType;
518
+ unsigned char *geomend = geom+geomlen;
506
519
507
- QGis::WKBTYPE wkbType;
508
- bool hasZValue = false ;
509
- double *x, *y;
510
- unsigned char *ptr;
511
- int *nPoints;
512
- // Upon return from this function, this variable will contain a
513
- // pointer to the first byte beyond the current feature.
514
- unsigned char *nextFeature = geom;
520
+ assert ( geom+1 +sizeof (wkbType)<=geomend );
515
521
516
- memcpy (&wkbType, (geom+1 ), sizeof (wkbType));
522
+ geom++; // skip endianess
523
+ memcpy (&wkbType, geom, sizeof (wkbType));
524
+ geom += sizeof (wkbType);
517
525
518
- switch (wkbType)
526
+ int dims = 2 ;
527
+
528
+ switch (wkbType)
529
+ {
530
+ case QGis::WKBPoint25D:
531
+ case QGis::WKBPoint:
519
532
{
520
- case QGis::WKBPoint25D:
521
- case QGis::WKBPoint:
533
+ assert ( geom+2 *sizeof (double )<=geomend );
534
+ double *pts = (double *)geom;
535
+ point.set ( pts[0 ], pts[1 ] );
536
+ geom += 2 *sizeof (double );
537
+ }
538
+ break ;
539
+
540
+ case QGis::WKBLineString25D:
541
+ dims=3 ;
542
+ case QGis::WKBLineString: // Line center
543
+ {
544
+ assert ( geom+sizeof (int )<=geomend );
545
+ int nPoints = *(unsigned int *)geom;
546
+ geom += sizeof (int );
547
+
548
+ assert ( geom+nPoints*sizeof (double )*dims<=geomend );
549
+
550
+ // get line center
551
+ double *pts = (double *)geom;
552
+ double tl = 0.0 ;
553
+ for (int i = 1 ; i < nPoints; i++)
522
554
{
523
- x = (double *) (geom + 5 );
524
- y = (double *) (geom + 5 + sizeof (double ));
525
- point.set (*x, *y);
526
- nextFeature += 1 + sizeOfInt + sizeOfDouble*2 ;
555
+ double dx = pts[dims*i] - pts[dims*(i-1 )];
556
+ double dy = pts[dims*i+1 ] - pts[dims*(i-1 )+1 ];
557
+ tl += sqrt (dx*dx + dy*dy);
527
558
}
528
- break ;
529
- case QGis::WKBLineString25D:
530
- hasZValue = true ;
531
- case QGis::WKBLineString: // Line center
559
+ tl /= 2.0 ;
560
+
561
+ // find line center
562
+ double l = 0.0 ;
563
+ for (int i=1 ; i < nPoints; i++)
532
564
{
533
- double dx, dy, tl, l;
534
- ptr = geom + 5 ;
535
- nPoints = (int *)ptr;
536
- if (hasZValue)
537
- {
538
- nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*3 ;
539
- }
540
- else
541
- {
542
- nextFeature += 1 + sizeOfInt*2 + (*nPoints)*sizeOfDouble*2 ;
543
- }
544
- ptr = geom + 1 + 2 * sizeof (int );
565
+ double dx = pts[dims*i] - pts[dims*(i-1 )];
566
+ double dy = pts[dims*i+1 ] - pts[dims*(i-1 )+1 ];
567
+ double dl = sqrt (dx*dx + dy*dy);
545
568
546
- tl = 0 ;
547
- for (int i = 1 ; i < *nPoints; i++)
569
+ if ( l+dl > tl )
548
570
{
549
- if (hasZValue)
550
- {
551
- dx = ((double *)ptr)[3 *i] - ((double *)ptr)[3 *i-3 ];
552
- dy = ((double *)ptr)[3 *i+1 ] - ((double *)ptr)[3 *i-2 ];
553
- }
554
- else
555
- {
556
- dx = ((double *)ptr)[2 *i] - ((double *)ptr)[2 *i-2 ];
557
- dy = ((double *)ptr)[2 *i+1 ] - ((double *)ptr)[2 *i-1 ];
558
- }
559
- tl += sqrt (dx*dx + dy*dy);
560
- }
561
- tl /= 2 ;
571
+ double k = (tl-l)/dl;
562
572
563
- l = 0 ;
564
- for (int i = 1 ; i < *nPoints; i++)
565
- {
566
- double dl;
567
- if (hasZValue)
568
- {
569
- dx = ((double *)ptr)[3 *i] - ((double *)ptr)[3 *i-3 ];
570
- dy = ((double *)ptr)[3 *i+1 ] - ((double *)ptr)[3 *i-2 ];
571
- }
572
- else
573
- {
574
- dx = ((double *)ptr)[2 *i] - ((double *)ptr)[2 *i-2 ];
575
- dy = ((double *)ptr)[2 *i+1 ] - ((double *)ptr)[2 *i-1 ];
576
- }
577
- dl = sqrt (dx*dx + dy*dy);
578
-
579
- if ( l+dl > tl )
580
- {
581
- l = tl - l;
582
- double k = l/dl;
583
-
584
- if (hasZValue)
585
- {
586
- point.setX ( ((double *)ptr)[3 *i-3 ] + k * dx );
587
- point.setY ( ((double *)ptr)[3 *i-2 ] + k * dy );
588
- }
589
- else
590
- {
591
- point.setX ( ((double *)ptr)[2 *i-2 ] + k * dx );
592
- point.setY ( ((double *)ptr)[2 *i-1 ] + k * dy );
593
- }
594
- break ;
595
- }
596
- l += dl;
573
+ point.set ( pts[dims*(i-1 )] + k * dx,
574
+ pts[dims*(i-1 )+1 ] + k * dy);
575
+ break ;
597
576
}
577
+
578
+ l += dl;
598
579
}
599
- break ;
600
580
601
- case QGis::WKBPolygon25D:
602
- hasZValue = true ;
603
- case QGis::WKBPolygon:
581
+ geom += nPoints*sizeof (double )*dims;
582
+ }
583
+ break ;
584
+
585
+ case QGis::WKBPolygon25D:
586
+ dims = 3 ;
587
+ case QGis::WKBPolygon: // centroid of outer ring
588
+ {
589
+ assert ( geom+sizeof (int )<=geomend);
590
+ int nRings = *(unsigned int *)geom;
591
+ geom += sizeof (int );
592
+
593
+ for (int i=0 ; i<nRings; ++i)
604
594
{
605
- double sx, sy;
606
- ptr = geom + 1 + 2 * sizeof (int ); // set pointer to the first ring
607
- nPoints = (int *) ptr;
608
- ptr += 4 ;
609
- sx = sy = 0 ;
610
- for (int i = 0 ; i < *nPoints-1 ; i++)
611
- {
612
- if (hasZValue)
613
- {
614
- sx += ((double *)ptr)[3 *i];
615
- sy += ((double *)ptr)[3 *i+1 ];
616
- }
617
- else
618
- {
619
- sx += ((double *)ptr)[2 *i];
620
- sy += ((double *)ptr)[2 *i+1 ];
621
- }
622
- }
623
- point.setX ( sx/(*nPoints-1 ) );
624
- point.setY ( sy/(*nPoints-1 ) );
625
- // Work out a pointer to the next feature after this one.
626
- int numRings = (int )(*(geom+1 +sizeOfInt));
627
- unsigned char * nextRing = nextFeature + 1 + 2 *sizeOfInt;
628
- for (int i = 0 ; i < numRings; ++i)
629
- {
630
- int numPoints = (int )(*nextRing);
631
- // get the start of the next ring
632
- if (hasZValue)
633
- {
634
- nextRing += sizeOfInt + numPoints*sizeOfDouble*3 ;
635
- }
636
- else
637
- {
638
- nextRing += sizeOfInt + numPoints*sizeOfDouble*2 ;
639
- }
595
+ assert ( geom+sizeof (int )<=geomend );
596
+ int nPoints = *(unsigned int *)geom;
597
+ geom += sizeof (int );
598
+
599
+ assert ( geom+nPoints*sizeof (double )*dims<=geomend );
600
+
601
+ if ( i==0 ) {
602
+ double sx=0.0 , sy=0.0 ;
603
+ double *pts = (double *) geom;
604
+ for (int j=0 ; j<nPoints-1 ; j++) {
605
+ sx += pts[dims*j];
606
+ sy += pts[dims*j+1 ];
607
+ }
608
+ point.set ( sx/(nPoints-1 ),
609
+ sy/(nPoints-1 ) );
640
610
}
641
- nextFeature = nextRing;
642
- }
643
- break ;
644
611
645
- default :
646
- // To get here is a bug because our caller should be filtering
647
- // on wkb type.
648
- break ;
612
+ geom += nPoints*sizeof (double )*dims;
613
+ }
649
614
}
650
- return nextFeature;
615
+ break ;
616
+
617
+ default :
618
+ // To get here is a bug because our caller should be filtering
619
+ // on wkb type.
620
+ QgsDebugMsg (" unsupported wkb type" );
621
+ return NULL ;
622
+ }
623
+
624
+ return geom;
651
625
}
652
626
653
627
static int _elementFieldIndex (QDomElement& el)
0 commit comments