[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