@@ -14,7 +14,6 @@ email : blazek@itc.it
14
14
* *
15
15
***************************************************************************/
16
16
#include < cmath>
17
- #include < iostream>
18
17
#include < assert.h>
19
18
20
19
#include < QPen>
@@ -24,7 +23,8 @@ email : blazek@itc.it
24
23
#include < QString>
25
24
#include < QStringList>
26
25
#include < QRect>
27
- #include < QPolygon>
26
+ #include < QPointF>
27
+ #include < QPolygonF>
28
28
#include < QDir>
29
29
#include < QPicture>
30
30
#include < QSvgRenderer>
@@ -34,6 +34,13 @@ email : blazek@itc.it
34
34
#include " qgsmarkercatalogue.h"
35
35
#include " qgslogger.h"
36
36
37
+ // MSVC compiler doesn't have defined M_PI in math.h
38
+ #ifndef M_PI
39
+ #define M_PI 3.14159265358979323846
40
+ #endif
41
+
42
+ #define DEG2RAD (x ) ((x)*M_PI/180 )
43
+
37
44
// #define IMAGEDEBUG
38
45
39
46
QgsMarkerCatalogue *QgsMarkerCatalogue::mMarkerCatalogue = 0 ;
@@ -46,10 +53,13 @@ QgsMarkerCatalogue::QgsMarkerCatalogue()
46
53
mList .append ( " hard:circle" );
47
54
mList .append ( " hard:rectangle" );
48
55
mList .append ( " hard:diamond" );
56
+ mList .append ( " hard:pentagon" );
49
57
mList .append ( " hard:cross" );
50
58
mList .append ( " hard:cross2" );
51
59
mList .append ( " hard:triangle" );
60
+ mList .append ( " hard:equilateral_triangle" );
52
61
mList .append ( " hard:star" );
62
+ mList .append ( " hard:regular_star" );
53
63
mList .append ( " hard:arrow" );
54
64
55
65
// SVG
@@ -109,16 +119,20 @@ QImage QgsMarkerCatalogue::imageMarker( QString fullName, double size, QPen pen,
109
119
}
110
120
111
121
QImage myImage;
122
+ int imageSize;
112
123
if ( fullName.left ( 5 ) == " hard:" )
113
124
{
114
- myImage = QImage ( size + 1 , size + 1 , QImage::Format_ARGB32_Premultiplied );
125
+ int pw = ( ( pen.width ()==0 ? 1 : pen.width () ) + 1 ) / 2 * 2 ; // make even (round up); handle cosmetic pen
126
+ imageSize = ( (int ) size + pw ) / 2 * 2 + 1 ; // make image width, height odd; account for pen width
127
+ myImage = QImage ( imageSize, imageSize, QImage::Format_ARGB32_Premultiplied );
115
128
}
116
129
else
117
130
{
118
131
// TODO Change this logic so width is size and height is same
119
132
// proportion of scale factor as in oritignal SVG TS XXX
120
133
// QPixmap myPixmap = QPixmap(width,height);
121
- myImage = QImage ( size, size, QImage::Format_ARGB32_Premultiplied );
134
+ imageSize = ( (int ) size ) / 2 * 2 + 1 ; // make image width, height odd
135
+ myImage = QImage ( imageSize, imageSize, QImage::Format_ARGB32_Premultiplied );
122
136
}
123
137
124
138
// starting with transparent QImage
@@ -134,7 +148,7 @@ QImage QgsMarkerCatalogue::imageMarker( QString fullName, double size, QPen pen,
134
148
135
149
if ( fullName.left ( 5 ) == " hard:" )
136
150
{
137
- hardMarker ( &myPainter, fullName.mid ( 5 ), size, pen, brush, qtBug );
151
+ hardMarker ( &myPainter, imageSize, fullName.mid ( 5 ), size, pen, brush, qtBug );
138
152
#ifdef IMAGEDEBUG
139
153
QgsDebugMsg ( " *** Saving hard marker to hardMarker.png ***" );
140
154
#ifdef QGISDEBUG
@@ -181,7 +195,7 @@ QPicture QgsMarkerCatalogue::pictureMarker( QString fullName, double size, QPen
181
195
182
196
if ( fullName.left ( 5 ) == " hard:" )
183
197
{
184
- hardMarker ( &myPainter, fullName.mid ( 5 ), size, pen, brush, qtBug );
198
+ hardMarker ( &myPainter, ( int ) size, fullName.mid ( 5 ), size, pen, brush, qtBug );
185
199
return myPicture;
186
200
}
187
201
else if ( fullName.left ( 4 ) == " svg:" )
@@ -199,111 +213,137 @@ void QgsMarkerCatalogue::svgMarker( QPainter * thepPainter, QString fileName, do
199
213
mySVG.render ( thepPainter );
200
214
}
201
215
202
- void QgsMarkerCatalogue::hardMarker ( QPainter * thepPainter, QString name, double s, QPen pen, QBrush brush, bool qtBug )
216
+ void QgsMarkerCatalogue::hardMarker ( QPainter * thepPainter, int imageSize, QString name, double s, QPen pen, QBrush brush, bool qtBug )
203
217
{
204
218
// Size of polygon symbols is calculated so that the boundingbox is circumscribed
205
219
// around a circle with diameter mPointSize
206
220
207
- double half = s / 2 ; // number of points from center
221
+ #if 0
222
+ s = s - pen.widthF(); // to make the overall size of the symbol at the specified size
223
+ #else
224
+ // the size of the base symbol is at the specified size; the outline is applied additionally
225
+ #endif
226
+
227
+ // Circle radius, is used for other figures also, when compensating for line
228
+ // width is necessary.
229
+ double r = s / 2 ; // get half the size of the figure to be rendered (the radius)
208
230
209
231
QgsDebugMsg ( QString ( " Hard marker size %1" ).arg ( s ) );
210
232
211
- // Find out center coordinates.
212
- double x_c = s / 2 ;
213
- double y_c = x_c;
233
+ // Find out center coordinates of the QImage to draw on .
234
+ double x_c = ( double ) ( imageSize / 2 ) + 0.5 ; // add 1/2 pixel for proper rounding when the figure's coordinates are added
235
+ double y_c = x_c; // is square image
214
236
215
- // Also width must be odd otherwise there are discrepancies visible in canvas!
216
- double lw = pen.widthF ();// (int)(2*floor((double)pen.widthF()/2)+1); // -> lw > 0
217
- pen.setWidthF ( lw );
218
237
thepPainter->setPen ( pen );
219
238
thepPainter->setBrush ( brush );
220
- QRect box;
221
239
222
- // Circle radius, is used for other figures also, when compensating for line
223
- // width is necessary.
224
-
225
- int r = ( s - 2 * lw ) / 2 - 1 ;
226
240
QgsDebugMsg ( QString ( " Hard marker radius %1" ).arg ( r ) );
227
241
228
242
// If radius is 0, draw a circle, so it wont disappear.
229
243
if ( name == " circle" || r < 1 )
230
244
{
231
245
// "A stroked ellipse has a size of rectangle.size() plus the pen width."
232
246
// (from Qt doc)
233
- // It doesn't seem like it is centered, however. Fudge...
234
- // Is this a Qt bug or feature?
235
- x_c -= (( lw + 5 ) / 4 );
236
- y_c -= (( lw + 5 ) / 4 );
237
247
238
- thepPainter->drawEllipse ( QRectF ( x_c - r, y_c - r, x_c + r, y_c + r ) );
248
+ thepPainter->drawEllipse ( QRectF ( x_c - r, y_c - r, s, s ) ); // x,y,w,h
239
249
}
240
250
else if ( name == " rectangle" )
241
251
{
242
- // Same fudge as for circle...
243
- x_c -= (( lw + 5 ) / 4 );
244
- y_c -= (( lw + 5 ) / 4 );
245
-
246
- thepPainter->drawRect ( x_c - r, y_c - r, x_c + r, y_c + r );
252
+ thepPainter->drawRect ( QRectF ( x_c - r, y_c - r, s, s ) ); // x,y,w,h
247
253
}
248
254
else if ( name == " diamond" )
249
255
{
250
- QPolygon pa ( 4 );
251
- pa.setPoint ( 0 , x_c - r, y_c );
252
- pa.setPoint ( 1 , x_c, y_c + r );
253
- pa.setPoint ( 2 , x_c + r, y_c );
254
- pa.setPoint ( 3 , x_c, y_c - r );
256
+ QPolygonF pa;
257
+ pa << QPointF ( x_c - r, y_c )
258
+ << QPointF ( x_c, y_c + r )
259
+ << QPointF ( x_c + r, y_c )
260
+ << QPointF ( x_c, y_c - r );
261
+ thepPainter->drawPolygon ( pa );
262
+ }
263
+ else if ( name == " pentagon" )
264
+ {
265
+ QPolygonF pa;
266
+ pa << QPointF ( x_c + ( r * sin ( DEG2RAD ( 288.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 288.0 ) ) ) )
267
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 216.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 216.0 ) ) ) )
268
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 144.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 144.0 ) ) ) )
269
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 72.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 72.0 ) ) ) )
270
+ << QPointF ( x_c, y_c - r );
255
271
thepPainter->drawPolygon ( pa );
256
272
}
257
273
else if ( name == " cross" )
258
274
{
259
- thepPainter->drawLine ( x_c - half , y_c, x_c + half , y_c ); // horizontal
260
- thepPainter->drawLine ( x_c, y_c - half, x_c, y_c + half ); // vertical
275
+ thepPainter->drawLine ( QPointF ( x_c - r , y_c ), QPointF ( x_c + r , y_c ) ); // horizontal
276
+ thepPainter->drawLine ( QPointF ( x_c, y_c - r ), QPointF ( x_c, y_c + r ) ); // vertical
261
277
}
262
278
else if ( name == " cross2" )
263
279
{
264
- thepPainter->drawLine ( x_c - half , y_c - half, x_c + half , y_c + half );
265
- thepPainter->drawLine ( x_c - half , y_c + half, x_c + half , y_c - half );
280
+ thepPainter->drawLine ( QPointF ( x_c - r , y_c - r ), QPointF ( x_c + r , y_c + r ) );
281
+ thepPainter->drawLine ( QPointF ( x_c - r , y_c + r ), QPointF ( x_c + r , y_c - r ) );
266
282
}
267
283
else if ( name == " triangle" )
268
284
{
269
- QPolygon pa ( 3 );
270
-
271
- pa.setPoint ( 0 , x_c - r, y_c + r );
272
- pa.setPoint ( 1 , x_c + r, y_c + r );
273
- pa.setPoint ( 2 , x_c, y_c - r );
285
+ QPolygonF pa;
286
+ pa << QPointF ( x_c - r, y_c + r )
287
+ << QPointF ( x_c + r, y_c + r )
288
+ << QPointF ( x_c, y_c - r );
289
+ thepPainter->drawPolygon ( pa );
290
+ }
291
+ else if ( name == " equilateral_triangle" )
292
+ {
293
+ QPolygonF pa;
294
+ pa << QPointF ( x_c + ( r * sin ( DEG2RAD ( 240.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 240.0 ) ) ) )
295
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 120.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 120.0 ) ) ) )
296
+ << QPointF ( x_c, y_c - r ); // 0
274
297
thepPainter->drawPolygon ( pa );
275
298
}
276
299
else if ( name == " star" )
277
300
{
278
- int oneSixth = 2 * r / 6 ;
279
-
280
- QPolygon pa ( 10 );
281
- pa.setPoint ( 0 , x_c, y_c - half );
282
- pa.setPoint ( 1 , x_c - oneSixth, y_c - oneSixth );
283
- pa.setPoint ( 2 , x_c - half, y_c - oneSixth );
284
- pa.setPoint ( 3 , x_c - oneSixth, y_c );
285
- pa.setPoint ( 4 , x_c - half, y_c + half );
286
- pa.setPoint ( 5 , x_c, y_c + oneSixth );
287
- pa.setPoint ( 6 , x_c + half, y_c + half );
288
- pa.setPoint ( 7 , x_c + oneSixth, y_c );
289
- pa.setPoint ( 8 , x_c + half, y_c - oneSixth );
290
- pa.setPoint ( 9 , x_c + oneSixth, y_c - oneSixth );
301
+ double oneSixth = 2 * r / 6 ;
302
+
303
+ QPolygonF pa;
304
+ pa << QPointF ( x_c, y_c - r )
305
+ << QPointF ( x_c - oneSixth, y_c - oneSixth )
306
+ << QPointF ( x_c - r, y_c - oneSixth )
307
+ << QPointF ( x_c - oneSixth, y_c )
308
+ << QPointF ( x_c - r, y_c + r )
309
+ << QPointF ( x_c, y_c + oneSixth )
310
+ << QPointF ( x_c + r, y_c + r )
311
+ << QPointF ( x_c + oneSixth, y_c )
312
+ << QPointF ( x_c + r, y_c - oneSixth )
313
+ << QPointF ( x_c + oneSixth, y_c - oneSixth );
314
+ thepPainter->drawPolygon ( pa );
315
+ }
316
+ else if ( name == " regular_star" )
317
+ {
318
+ // control the 'fatness' of the star: cos(72)/cos(36) gives the classic star shape
319
+ double inner_r = r * cos ( DEG2RAD ( 72.0 ) ) / cos ( DEG2RAD ( 36.0 ) );
320
+
321
+ QPolygonF pa;
322
+ pa << QPointF ( x_c + ( inner_r * sin ( DEG2RAD ( 324.0 ) ) ), y_c - ( inner_r * cos ( DEG2RAD ( 324.0 ) ) ) ) // 324
323
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 288.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 288 ) ) ) ) // 288
324
+ << QPointF ( x_c + ( inner_r * sin ( DEG2RAD ( 252.0 ) ) ), y_c - ( inner_r * cos ( DEG2RAD ( 252.0 ) ) ) ) // 252
325
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 216.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 216.0 ) ) ) ) // 216
326
+ << QPointF ( x_c, y_c + ( inner_r ) ) // 180
327
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 144.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 144.0 ) ) ) ) // 144
328
+ << QPointF ( x_c + ( inner_r * sin ( DEG2RAD ( 108.0 ) ) ), y_c - ( inner_r * cos ( DEG2RAD ( 108.0 ) ) ) ) // 108
329
+ << QPointF ( x_c + ( r * sin ( DEG2RAD ( 72.0 ) ) ), y_c - ( r * cos ( DEG2RAD ( 72.0 ) ) ) ) // 72
330
+ << QPointF ( x_c + ( inner_r * sin ( DEG2RAD ( 36.0 ) ) ), y_c - ( inner_r * cos ( DEG2RAD ( 36.0 ) ) ) ) // 36
331
+ << QPointF ( x_c, y_c - r ); // 0
291
332
thepPainter->drawPolygon ( pa );
292
333
}
293
-
294
334
else if ( name == " arrow" )
295
335
{
296
- int oneEight = r / 4 ;
297
- int quarter = r / 2 ;
298
-
299
- QPolygon pa ( 7 ) ;
300
- pa. setPoint ( 0 , x_c, y_c - r );
301
- pa. setPoint ( 1 , x_c + quarter, y_c - quarter );
302
- pa. setPoint ( 2 , x_c + oneEight, y_c - quarter );
303
- pa. setPoint ( 3 , x_c + oneEight, y_c + r );
304
- pa. setPoint ( 4 , x_c - oneEight, y_c + r );
305
- pa. setPoint ( 5 , x_c - oneEight, y_c - quarter );
306
- pa. setPoint ( 6 , x_c - quarter, y_c - quarter );
336
+ double oneEight = r / 4 ;
337
+ double quarter = r / 2 ;
338
+
339
+ QPolygonF pa;
340
+ pa << QPointF ( x_c, y_c - r )
341
+ << QPointF ( x_c + quarter, y_c - quarter )
342
+ << QPointF ( x_c + oneEight, y_c - quarter )
343
+ << QPointF ( x_c + oneEight, y_c + r )
344
+ << QPointF ( x_c - oneEight, y_c + r )
345
+ << QPointF ( x_c - oneEight, y_c - quarter )
346
+ << QPointF ( x_c - quarter, y_c - quarter );
307
347
thepPainter->drawPolygon ( pa );
308
348
}
309
349
thepPainter->end ();
0 commit comments