[QGIS Commit] r9636 - trunk/qgis/src/core/symbology

svn_qgis at osgeo.org svn_qgis at osgeo.org
Fri Nov 14 13:44:36 EST 2008


Author: homann
Date: 2008-11-14 13:44:36 -0500 (Fri, 14 Nov 2008)
New Revision: 9636

Modified:
   trunk/qgis/src/core/symbology/qgsmarkercatalogue.cpp
   trunk/qgis/src/core/symbology/qgsmarkercatalogue.h
Log:
Applying patch from smizuno to polish hard marker position accuracy. Many thanks! Fixes #1262

Modified: trunk/qgis/src/core/symbology/qgsmarkercatalogue.cpp
===================================================================
--- trunk/qgis/src/core/symbology/qgsmarkercatalogue.cpp	2008-11-13 23:44:39 UTC (rev 9635)
+++ trunk/qgis/src/core/symbology/qgsmarkercatalogue.cpp	2008-11-14 18:44:36 UTC (rev 9636)
@@ -14,7 +14,6 @@
  *                                                                         *
  ***************************************************************************/
 #include <cmath>
-#include <iostream>
 #include <assert.h>
 
 #include <QPen>
@@ -24,7 +23,8 @@
 #include <QString>
 #include <QStringList>
 #include <QRect>
-#include <QPolygon>
+#include <QPointF>
+#include <QPolygonF>
 #include <QDir>
 #include <QPicture>
 #include <QSvgRenderer>
@@ -34,6 +34,13 @@
 #include "qgsmarkercatalogue.h"
 #include "qgslogger.h"
 
+// MSVC compiler doesn't have defined M_PI in math.h
+#ifndef M_PI
+#define M_PI          3.14159265358979323846
+#endif
+
+#define DEG2RAD(x)    ((x)*M_PI/180)
+
 //#define IMAGEDEBUG
 
 QgsMarkerCatalogue *QgsMarkerCatalogue::mMarkerCatalogue = 0;
@@ -46,10 +53,13 @@
   mList.append( "hard:circle" );
   mList.append( "hard:rectangle" );
   mList.append( "hard:diamond" );
+  mList.append( "hard:pentagon" );
   mList.append( "hard:cross" );
   mList.append( "hard:cross2" );
   mList.append( "hard:triangle" );
+  mList.append( "hard:equilateral_triangle" );
   mList.append( "hard:star" );
+  mList.append( "hard:regular_star" );
   mList.append( "hard:arrow" );
 
   // SVG
@@ -109,16 +119,20 @@
   }
 
   QImage myImage;
+  int imageSize;
   if ( fullName.left( 5 ) == "hard:" )
   {
-    myImage = QImage( size + 1, size + 1, QImage::Format_ARGB32_Premultiplied );
+    int pw = ( ( pen.width()==0 ? 1 : pen.width() ) + 1 ) / 2 * 2;	// make even (round up); handle cosmetic pen
+    imageSize = ( (int) size + pw ) / 2 * 2 + 1;	//  make image width, height odd; account for pen width
+    myImage = QImage( imageSize, imageSize, QImage::Format_ARGB32_Premultiplied );
   }
   else
   {
     // TODO Change this logic so width is size and height is same
     // proportion of scale factor as in oritignal SVG TS XXX
     //QPixmap myPixmap = QPixmap(width,height);
-    myImage = QImage( size, size, QImage::Format_ARGB32_Premultiplied );
+    imageSize = ( (int) size ) / 2 * 2 + 1;	//  make image width, height odd
+    myImage = QImage( imageSize, imageSize, QImage::Format_ARGB32_Premultiplied );
   }
 
   // starting with transparent QImage
@@ -134,7 +148,7 @@
 
   if ( fullName.left( 5 ) == "hard:" )
   {
-    hardMarker( &myPainter, fullName.mid( 5 ), size, pen, brush, qtBug );
+    hardMarker( &myPainter, imageSize, fullName.mid( 5 ), size, pen, brush, qtBug );
 #ifdef IMAGEDEBUG
     QgsDebugMsg( "*** Saving hard marker to hardMarker.png ***" );
 #ifdef QGISDEBUG
@@ -181,7 +195,7 @@
 
   if ( fullName.left( 5 ) == "hard:" )
   {
-    hardMarker( &myPainter, fullName.mid( 5 ), size, pen, brush, qtBug );
+    hardMarker( &myPainter, (int) size, fullName.mid( 5 ), size, pen, brush, qtBug );
     return myPicture;
   }
   else if ( fullName.left( 4 ) == "svg:" )
@@ -199,30 +213,30 @@
   mySVG.render( thepPainter );
 }
 
-void QgsMarkerCatalogue::hardMarker( QPainter * thepPainter, QString name, double s, QPen pen, QBrush brush, bool qtBug )
+void QgsMarkerCatalogue::hardMarker( QPainter * thepPainter, int imageSize, QString name, double s, QPen pen, QBrush brush, bool qtBug )
 {
   // Size of polygon symbols is calculated so that the boundingbox is circumscribed
   // around a circle with diameter mPointSize
 
-  double half = s / 2; // number of points from center
+#if 0
+  s = s - pen.widthF();	// to make the overall size of the symbol at the specified size
+#else
+  // the size of the base symbol is at the specified size; the outline is applied additionally
+#endif
 
+  // Circle radius, is used for other figures also, when compensating for line
+  // width is necessary.
+  double r = s / 2;	// get half the size of the figure to be rendered (the radius)
+
   QgsDebugMsg( QString( "Hard marker size %1" ).arg( s ) );
 
-  // Find out center coordinates.
-  double x_c = s / 2;
-  double y_c = x_c;
+  // Find out center coordinates of the QImage to draw on.
+  double x_c = (double) ( imageSize / 2 ) + 0.5;	// add 1/2 pixel for proper rounding when the figure's coordinates are added
+  double y_c = x_c;		// is square image
 
-  // Also width must be odd otherwise there are discrepancies visible in canvas!
-  double lw = pen.widthF();//(int)(2*floor((double)pen.widthF()/2)+1); // -> lw > 0
-  pen.setWidthF( lw );
   thepPainter->setPen( pen );
   thepPainter->setBrush( brush );
-  QRect box;
 
-  // Circle radius, is used for other figures also, when compensating for line
-  // width is necessary.
-
-  int r = ( s - 2 * lw ) / 2 - 1;
   QgsDebugMsg( QString( "Hard marker radius %1" ).arg( r ) );
 
   // If radius is 0, draw a circle, so it wont disappear.
@@ -230,80 +244,106 @@
   {
     // "A stroked ellipse has a size of rectangle.size() plus the pen width."
     // (from Qt doc)
-    // It doesn't seem like it is centered, however. Fudge...
-    // Is this a Qt bug or feature?
-    x_c -= (( lw + 5 ) / 4 );
-    y_c -= (( lw + 5 ) / 4 );
 
-    thepPainter->drawEllipse( QRectF( x_c - r, y_c - r, x_c + r, y_c + r ) );
+    thepPainter->drawEllipse( QRectF( x_c - r, y_c - r, s, s ) );	// x,y,w,h
   }
   else if ( name == "rectangle" )
   {
-    // Same fudge as for circle...
-    x_c -= (( lw + 5 ) / 4 );
-    y_c -= (( lw + 5 ) / 4 );
-
-    thepPainter->drawRect( x_c - r, y_c - r, x_c + r, y_c + r );
+    thepPainter->drawRect( QRectF( x_c - r, y_c - r, s, s ) );		// x,y,w,h
   }
   else if ( name == "diamond" )
   {
-    QPolygon pa( 4 );
-    pa.setPoint( 0, x_c - r, y_c );
-    pa.setPoint( 1, x_c, y_c + r );
-    pa.setPoint( 2, x_c + r, y_c );
-    pa.setPoint( 3, x_c, y_c - r );
+    QPolygonF pa;
+    pa << QPointF( x_c - r, y_c )
+       << QPointF( x_c, y_c + r )
+       << QPointF( x_c + r, y_c )
+       << QPointF( x_c, y_c - r );
     thepPainter->drawPolygon( pa );
   }
+  else if ( name == "pentagon" )
+  {
+    QPolygonF pa;
+    pa << QPointF( x_c + ( r * sin( DEG2RAD( 288.0 ) ) ), y_c - ( r * cos( DEG2RAD( 288.0 ) ) ) )
+       << QPointF( x_c + ( r * sin( DEG2RAD( 216.0 ) ) ), y_c - ( r * cos( DEG2RAD( 216.0 ) ) ) )
+       << QPointF( x_c + ( r * sin( DEG2RAD( 144.0 ) ) ), y_c - ( r * cos( DEG2RAD( 144.0 ) ) ) )
+       << QPointF( x_c + ( r * sin( DEG2RAD( 72.0 ) ) ), y_c - ( r * cos( DEG2RAD( 72.0 ) ) ) )
+       << QPointF( x_c, y_c - r );
+    thepPainter->drawPolygon( pa );
+  }
   else if ( name == "cross" )
   {
-    thepPainter->drawLine( x_c - half, y_c, x_c + half, y_c ); // horizontal
-    thepPainter->drawLine( x_c, y_c - half, x_c, y_c + half ); // vertical
+    thepPainter->drawLine( QPointF( x_c - r, y_c ), QPointF( x_c + r, y_c ) ); // horizontal
+    thepPainter->drawLine( QPointF( x_c, y_c - r ), QPointF( x_c, y_c + r ) ); // vertical
   }
   else if ( name == "cross2" )
   {
-    thepPainter->drawLine( x_c - half, y_c - half, x_c + half, y_c + half );
-    thepPainter->drawLine( x_c - half, y_c + half, x_c + half, y_c - half );
+    thepPainter->drawLine( QPointF( x_c - r, y_c - r ), QPointF( x_c + r, y_c + r ) );
+    thepPainter->drawLine( QPointF( x_c - r, y_c + r ), QPointF( x_c + r, y_c - r ) );
   }
   else if ( name == "triangle" )
   {
-    QPolygon pa( 3 );
-
-    pa.setPoint( 0, x_c - r, y_c + r );
-    pa.setPoint( 1, x_c + r, y_c + r );
-    pa.setPoint( 2, x_c, y_c - r );
+    QPolygonF pa;
+    pa << QPointF( x_c - r, y_c + r )
+       << QPointF( x_c + r, y_c + r )
+       << QPointF( x_c, y_c - r );
     thepPainter->drawPolygon( pa );
   }
+  else if ( name == "equilateral_triangle" )
+  {
+    QPolygonF pa;
+    pa << QPointF( x_c + ( r * sin( DEG2RAD( 240.0 ) ) ), y_c - ( r * cos( DEG2RAD( 240.0 ) ) ) )
+       << QPointF( x_c + ( r * sin( DEG2RAD( 120.0 ) ) ), y_c - ( r * cos( DEG2RAD( 120.0 ) ) ) )
+       << QPointF( x_c, y_c - r );	// 0
+    thepPainter->drawPolygon( pa );
+  }
   else if ( name == "star" )
   {
-    int oneSixth = 2 * r / 6;
+    double oneSixth = 2 * r / 6;
 
-    QPolygon pa( 10 );
-    pa.setPoint( 0, x_c, y_c - half );
-    pa.setPoint( 1, x_c - oneSixth, y_c - oneSixth );
-    pa.setPoint( 2, x_c - half, y_c - oneSixth );
-    pa.setPoint( 3, x_c - oneSixth, y_c );
-    pa.setPoint( 4, x_c - half, y_c + half );
-    pa.setPoint( 5, x_c, y_c + oneSixth );
-    pa.setPoint( 6, x_c + half, y_c + half );
-    pa.setPoint( 7, x_c + oneSixth, y_c );
-    pa.setPoint( 8, x_c + half, y_c - oneSixth );
-    pa.setPoint( 9, x_c + oneSixth, y_c - oneSixth );
+    QPolygonF pa;
+    pa << QPointF( x_c, y_c - r )
+       << QPointF( x_c - oneSixth, y_c - oneSixth )
+       << QPointF( x_c - r, y_c - oneSixth )
+       << QPointF( x_c - oneSixth, y_c )
+       << QPointF( x_c - r, y_c + r )
+       << QPointF( x_c, y_c + oneSixth )
+       << QPointF( x_c + r, y_c + r )
+       << QPointF( x_c + oneSixth, y_c )
+       << QPointF( x_c + r, y_c - oneSixth )
+       << QPointF( x_c + oneSixth, y_c - oneSixth );
     thepPainter->drawPolygon( pa );
   }
+  else if ( name == "regular_star" )
+  {
+    // control the 'fatness' of the star:  cos(72)/cos(36) gives the classic star shape
+    double inner_r = r * cos( DEG2RAD( 72.0 ) ) / cos( DEG2RAD( 36.0 ) );
 
+    QPolygonF pa;
+    pa << QPointF( x_c + ( inner_r * sin( DEG2RAD( 324.0 ) ) ), y_c - ( inner_r * cos( DEG2RAD( 324.0 ) ) ) )	// 324
+       << QPointF( x_c + ( r * sin( DEG2RAD( 288.0 ) ) ), y_c - ( r * cos( DEG2RAD( 288 ) ) ) )			// 288
+       << QPointF( x_c + ( inner_r * sin( DEG2RAD( 252.0 ) ) ), y_c - ( inner_r * cos( DEG2RAD( 252.0 ) ) ) )	// 252
+       << QPointF( x_c + ( r * sin( DEG2RAD( 216.0 ) ) ), y_c - ( r * cos( DEG2RAD( 216.0 ) ) ) )		// 216
+       << QPointF( x_c, y_c + ( inner_r ) )									// 180
+       << QPointF( x_c + ( r * sin( DEG2RAD( 144.0 ) ) ), y_c - ( r * cos( DEG2RAD( 144.0 ) ) ) )		// 144
+       << QPointF( x_c + ( inner_r * sin( DEG2RAD( 108.0 ) ) ), y_c - ( inner_r * cos( DEG2RAD( 108.0 ) ) ) )	// 108
+       << QPointF( x_c + ( r * sin( DEG2RAD( 72.0 ) ) ), y_c - ( r * cos( DEG2RAD( 72.0 ) ) ) )			//  72
+       << QPointF( x_c + ( inner_r * sin( DEG2RAD( 36.0 ) ) ), y_c - ( inner_r * cos( DEG2RAD( 36.0 ) ) ) )	//  36
+       << QPointF( x_c, y_c - r );										//   0
+    thepPainter->drawPolygon( pa );
+  }
   else if ( name == "arrow" )
   {
-    int oneEight = r / 4;
-    int quarter = r / 2;
+    double oneEight = r / 4;
+    double quarter = r / 2;
 
-    QPolygon pa( 7 );
-    pa.setPoint( 0, x_c, y_c - r );
-    pa.setPoint( 1, x_c + quarter,  y_c - quarter );
-    pa.setPoint( 2, x_c + oneEight, y_c - quarter );
-    pa.setPoint( 3, x_c + oneEight, y_c + r );
-    pa.setPoint( 4, x_c - oneEight, y_c + r );
-    pa.setPoint( 5, x_c - oneEight, y_c - quarter );
-    pa.setPoint( 6, x_c - quarter,  y_c - quarter );
+    QPolygonF pa;
+    pa << QPointF( x_c, y_c - r )
+       << QPointF( x_c + quarter,  y_c - quarter )
+       << QPointF( x_c + oneEight, y_c - quarter )
+       << QPointF( x_c + oneEight, y_c + r )
+       << QPointF( x_c - oneEight, y_c + r )
+       << QPointF( x_c - oneEight, y_c - quarter )
+       << QPointF( x_c - quarter,  y_c - quarter );
     thepPainter->drawPolygon( pa );
   }
   thepPainter->end();

Modified: trunk/qgis/src/core/symbology/qgsmarkercatalogue.h
===================================================================
--- trunk/qgis/src/core/symbology/qgsmarkercatalogue.h	2008-11-13 23:44:39 UTC (rev 9635)
+++ trunk/qgis/src/core/symbology/qgsmarkercatalogue.h	2008-11-14 18:44:36 UTC (rev 9636)
@@ -64,7 +64,7 @@
     QStringList mList;
 
     /** Hard coded */
-    void hardMarker( QPainter * thepPainter, QString name, double size, QPen pen, QBrush brush, bool qtBug = true );
+    void hardMarker( QPainter * thepPainter, int imageSize, QString name, double size, QPen pen, QBrush brush, bool qtBug = true );
 
 };
 



More information about the QGIS-commit mailing list