10
10
from xml .dom import minidom , Node
11
11
12
12
# symbol map
13
- qgisSymbols = {'hard:circle' : 'CIRCLE' }
13
+ qgisSymbols = {'hard:circle' : 'CIRCLE' ,
14
+ 'hard:triangle' : 'TRIANGLE' }
15
+
14
16
class Qgis2Map :
15
17
def __init__ (self , projectFile , mapFile ):
16
18
self .project = projectFile
@@ -28,54 +30,69 @@ def __init__(self, projectFile, mapFile):
28
30
self .template = ''
29
31
self .header = ''
30
32
self .footer = ''
33
+ self .symbolQueue = {}
31
34
32
-
33
- # Set the options collected from the GUI
34
- def setOptions (self , units , image , mapname , width , height , minscale , maxscale , template , header , footer ):
35
+ # Set the options collected from the GUI
36
+ def setOptions (self , units , image , mapname , width , height , template , header , footer ):
35
37
self .units = units
36
38
self .imageType = image
37
39
self .mapName = mapname
38
40
self .width = width
39
41
self .height = height
40
- self .minScale = minscale
41
- self .maxScale = maxscale
42
+ # self.minScale = minscale
43
+ # self.maxScale = maxscale
42
44
self .template = template
43
45
self .header = header
44
46
self .footer = footer
45
- #
46
- ## All real work happens here by calling methods to write the
47
- ## various sections of the map file
47
+ print units , image , mapname , width , height , template , header , footer
48
+
49
+ ## All real work happens here by calling methods to write the
50
+ ## various sections of the map file
48
51
def writeMapFile (self ):
49
52
# open the output file
50
53
self .outFile = open (self .mapFile , 'w' )
51
54
# write the general map and web settings
55
+ print " --- python : map section "
52
56
self .writeMapSection ()
57
+ print " --- python : map section done"
53
58
# write the projection section
59
+ print " --- python : proj section "
54
60
self .writeProjectionSection ()
61
+ print " --- python : proj section done"
55
62
# write the output format section
63
+ print " --- python : outputformat section "
56
64
self .writeOutputFormat ()
65
+ print " --- python : outputformat section done"
57
66
# write the legend section
67
+ print " --- python : legend section"
58
68
self .writeLegendSection ()
59
- # write the symbol defs section
60
- self .writeSymbolSection ()
69
+ print " --- python : legend section done"
61
70
62
71
# write the WEB section
72
+ print " --- python : web section "
63
73
self .writeWebSection ()
74
+ print " --- python : web section done"
64
75
65
76
# write the LAYER sections
77
+ print " --- python : layer section "
66
78
self .writeMapLayers ()
79
+ print " --- python : layer section done"
80
+
81
+ # write the symbol defs section
82
+ # must happen after layers so we can build a symbol queue
83
+ print " --- python : symbol section "
84
+ self .writeSymbolSection ()
85
+ print " --- python : symbol section done"
67
86
68
87
# END and close the map file
69
88
self .outFile .write ("END" )
70
89
self .outFile .close ()
71
90
72
91
ret = "Writing the map file using " + self .project + " " + self .mapFile
73
92
return ret
74
- #, self.mapFile, self.project
75
93
76
- # Write the general parts of the map section
94
+ # Write the general parts of the map section
77
95
def writeMapSection (self ):
78
- print "Writing header\n "
79
96
self .outFile .write ("# Map file created from QGIS project file " + self .project + "\n " )
80
97
self .outFile .write ("# Edit this file to customize for your map interface\n " )
81
98
self .outFile .write ("MAP\n " )
@@ -99,22 +116,22 @@ def writeMapSection(self):
99
116
self .outFile .write (ymax [0 ].childNodes [0 ].nodeValue .encode ())
100
117
self .outFile .write ("\n " )
101
118
102
- # Write the OUTPUTFORMAT section
119
+ # Write the OUTPUTFORMAT section
103
120
def writeOutputFormat (self ):
104
121
self .outFile .write (" # Background color for the map canvas -- change as desired\n " )
105
122
self .outFile .write (" IMAGECOLOR 192 192 192\n " )
106
123
self .outFile .write (" IMAGEQUALITY 95\n " )
107
124
self .outFile .write (" IMAGETYPE " + self .imageType + "\n " )
108
- # self.outFile.write(" OUTPUTFORMAT\n")
109
- # self.outFile.write(" NAME " + self.imageType + "\n")
110
- # self.outFile.write(" DRIVER 'GD/" + self.imageType.upper() + "'\n")
111
- # self.outFile.write(" MIMETYPE 'image/" + self.imageType.lower() + "'\n")
112
- # self.outFile.write(" IMAGEMODE PC256\n")
113
- # self.outFile.write(" EXTENSION '" + self.imageType.lower() + "'\n")
114
- # self.outFile.write(" END\n")
125
+ self .outFile .write (" OUTPUTFORMAT\n " )
126
+ self .outFile .write (" NAME " + self .imageType + "\n " )
127
+ self .outFile .write (" DRIVER 'GD/" + self .imageType .upper () + "'\n " )
128
+ self .outFile .write (" MIMETYPE 'image/" + self .imageType .lower () + "'\n " )
129
+ self .outFile .write (" IMAGEMODE PC256\n " )
130
+ self .outFile .write (" EXTENSION '" + self .imageType .lower () + "'\n " )
131
+ self .outFile .write (" END\n " )
115
132
116
133
117
- # Write Projection section
134
+ # Write Projection section
118
135
def writeProjectionSection (self ):
119
136
# Need to get the destination srs from one of the map layers since
120
137
# the project file doesn't contain the epsg id or proj4 text for
@@ -123,13 +140,14 @@ def writeProjectionSection(self):
123
140
self .outFile .write (" PROJECTION\n " )
124
141
125
142
# Get the proj4 text from the first map layer's destination SRS
126
- proj4Text = self .qgs .getElementsByTagName ("destinationsrs" )[0 ].getElementsByTagName ("proj4" )[0 ].childNodes [0 ].nodeValue .encode ()
143
+ destsrs = self .qgs .getElementsByTagName ("destinationsrs" )[0 ]
144
+ proj4Text = destsrs .getElementsByTagName ("proj4" )[0 ].childNodes [0 ].nodeValue .encode ()
127
145
# the proj4 text string needs to be reformatted to make mapserver happy
128
146
self .outFile .write (self .formatProj4 (proj4Text ))
129
147
130
- self .outFile .write (" END\n " )
148
+ self .outFile .write (" END\n \n " )
131
149
132
- # Write the LEGEND section
150
+ # Write the LEGEND section
133
151
def writeLegendSection (self ):
134
152
self .outFile .write (" # Legend\n " )
135
153
self .outFile .write (" LEGEND\n " )
@@ -141,22 +159,15 @@ def writeLegendSection(self):
141
159
self .outFile .write (" SIZE MEDIUM\n " )
142
160
self .outFile .write (" COLOR 0 0 89\n " )
143
161
self .outFile .write (" END\n " )
144
- self .outFile .write (" END\n \n " )
162
+ self .outFile .write (" END\n \n " )
145
163
146
- # Write the symbol definitions
164
+ # Write the symbol definitions
147
165
def writeSymbolSection (self ):
148
- self .outFile .write (" #Circle symbol\n " );
149
- self .outFile .write (" SYMBOL\n " );
150
- self .outFile .write (" NAME 'CIRCLE'\n " );
151
- self .outFile .write (" TYPE ellipse\n " );
152
- self .outFile .write (" FILLED true\n " );
153
- self .outFile .write (" POINTS\n " );
154
- self .outFile .write (" 1 1\n " );
155
- self .outFile .write (" END\n " );
156
- self .outFile .write (" END\n \n " );
157
-
158
-
159
- # Write the WEB section of the map file
166
+ for symbol in self .symbolQueue .keys ():
167
+ self .outFile .write ( self .symbolQueue [symbol ] )
168
+ self .outFile .write ( "\n " )
169
+
170
+ # Write the WEB section of the map file
160
171
def writeWebSection (self ):
161
172
self .outFile .write (" # Web interface definition. Only the template parameter\n " )
162
173
self .outFile .write (" # is required to display a map. See MapServer documentation\n " )
@@ -215,7 +226,7 @@ def parsePostgisConnection( self, dataString ):
215
226
return pg
216
227
217
228
218
- # Write the map layers
229
+ # Write the map layers
219
230
def writeMapLayers (self ):
220
231
# get the list of maplayer nodes
221
232
maplayers = self .qgs .getElementsByTagName ("maplayer" )
@@ -255,45 +266,54 @@ def writeMapLayers(self):
255
266
# it's a postgis layer
256
267
pg = self .parsePostgisConnection (dataString )
257
268
self .outFile .write (" CONNECTIONTYPE postgis\n " )
258
- self .outFile .write (" CONNECTION 'host=" + pg ['host' ] + " dbname=" + pg ['dbname' ] + " password=" + pg ['password' ] + " user=" + pg ['user' ] + "'\n " )
269
+ self .outFile .write (" CONNECTION 'host=" + pg ['host' ] + " dbname=" + pg ['dbname' ]
270
+ + " password=" + pg ['password' ] + " user=" + pg ['user' ] + "'\n " )
259
271
self .outFile .write (" DATA '" + pg ['geom' ] + " FROM " + pg ['table' ] + "'\n " )
272
+
260
273
elif providerString == 'wms' and lyr .getAttribute ("type" ).encode ().upper () == 'RASTER' :
261
274
# it's a WMS layer
262
275
self .outFile .write (" CONNECTIONTYPE WMS\n " )
263
276
self .outFile .write (" CONNECTION '" + dataString + "'\n " )
264
277
rasterProp = lyr .getElementsByTagName ("rasterproperties" )[0 ]
265
-
266
- # TODO loop thru wmsSubLayers
267
- # wmsSubLayers = rasterProp.getElementsByTagName('wmsSublayer')
268
- layername = rasterProp .getElementsByTagName ('wmsSublayer' )[0 ].getElementsByTagName ('name' )[0 ].childNodes [0 ].nodeValue .encode ()
269
- try :
270
- style = rasterProp .getElementsByTagName ('wmsSublayer' )[0 ].getElementsByTagName ('style' )[0 ].childNodes [0 ].nodeValue .encode ()
271
- except :
272
- style = ''
273
-
278
+ # loop thru wmsSubLayers
279
+ wmsSubLayers = rasterProp .getElementsByTagName ('wmsSublayer' )
280
+ wmsNames = []
281
+ wmsStyles = []
282
+ for wmsLayer in wmsSubLayers :
283
+ wmsNames .append ( wmsLayer .getElementsByTagName ('name' )[0 ].childNodes [0 ].nodeValue .encode () )
284
+ try :
285
+ wmsStyles .append ( wmsLayer .getElementsByTagName ('style' )[0 ].childNodes [0 ].nodeValue .encode () )
286
+ except :
287
+ wmsStyles .append ( '' )
274
288
# Create necesssary wms metadata
275
289
format = rasterProp .getElementsByTagName ('wmsFormat' )[0 ].childNodes [0 ].nodeValue .encode ()
276
- srs = lyr .getElementsByTagName ('coordinatetransform' )[0 ].getElementsByTagName ('sourcesrs' )[0 ].getElementsByTagName ('spatialrefsys' )[0 ]
290
+ ct = lyr .getElementsByTagName ('coordinatetransform' )[0 ]
291
+ srs = ct .getElementsByTagName ('sourcesrs' )[0 ].getElementsByTagName ('spatialrefsys' )[0 ]
277
292
epsg = srs .getElementsByTagName ('epsg' )[0 ].childNodes [0 ].nodeValue .encode ()
278
293
self .outFile .write (" METADATA\n " )
279
- self .outFile .write (" 'wms_name' '" + layername + "'\n " )
294
+ self .outFile .write (" 'wms_name' '" + ',' . join ( wmsNames ) + "'\n " )
280
295
self .outFile .write (" 'wms_server_version' '1.1.1'\n " )
281
296
self .outFile .write (" 'wms_srs' 'EPSG:4326 EPSG:" + epsg + "'\n " )
282
297
self .outFile .write (" 'wms_format' '" + format + "'\n " )
283
- self .outFile .write (" 'wms_style' '" + style + "'\n " )
298
+ self .outFile .write (" 'wms_style' '" + ',' . join ( wmsStyles ) + "'\n " )
284
299
self .outFile .write (" END\n " )
300
+
285
301
else :
286
302
# its a standard ogr, gdal or grass layer
287
303
self .outFile .write (" DATA '" + dataString + "'\n " )
288
304
289
305
# WMS settings for all layers
290
306
self .outFile .write (" METADATA\n " )
291
- self .outFile .write (" 'wms_title' '" + lyr .getElementsByTagName ("layername" )[0 ].childNodes [0 ].nodeValue .encode () + "'\n " )
307
+ self .outFile .write (" 'wms_title' '"
308
+ + lyr .getElementsByTagName ("layername" )[0 ].childNodes [0 ].nodeValue .encode () + "'\n " )
292
309
self .outFile .write (" END\n " )
293
310
294
311
self .outFile .write (" STATUS DEFAULT\n " )
295
- opacity = int ( 100.0 * float (lyr .getElementsByTagName ("transparencyLevelInt" )[0 ].childNodes [0 ].nodeValue .encode ()) / 255.0 )
312
+
313
+ opacity = int ( 100.0 *
314
+ float (lyr .getElementsByTagName ("transparencyLevelInt" )[0 ].childNodes [0 ].nodeValue .encode ()) / 255.0 )
296
315
self .outFile .write (" TRANSPARENCY " + str (opacity ) + "\n " )
316
+
297
317
self .outFile .write (" PROJECTION\n " )
298
318
proj4Text = lyr .getElementsByTagName ("proj4" )[0 ].childNodes [0 ].nodeValue .encode ()
299
319
self .outFile .write (self .formatProj4 (proj4Text ))
@@ -335,66 +355,55 @@ def writeMapLayers(self):
335
355
# end of LAYER
336
356
self .outFile .write (" END\n \n " )
337
357
358
+
338
359
# Simple renderer ouput
339
360
# We need the layer node and symbol node
340
361
def simpleRenderer (self , layerNode , symbolNode ):
341
- # symbology depends on the feature type and the .qgs file
342
- # contains the same markup for a layer regardless of type
343
- # so we infer a symbol type based on the geometry
344
- geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
345
- if geometry == 'POLYGON' :
346
- symbol = '0'
347
- elif geometry == 'LINE' :
348
- symbol = '0'
349
- elif geometry == 'POINT' :
350
- symbolName = qgisSymbols [symbolNode .getElementsByTagName ('pointsymbol' )[0 ].childNodes [0 ].nodeValue .encode ()]
351
- # make sure it's single quoted
352
- symbol = "'" + symbolName + "'"
353
-
354
- self .outFile .write (" CLASS\n " )
362
+ # get the layers geometry type
363
+ geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
355
364
356
- self .outFile .write (" NAME "
357
- + lyr .getElementsByTagName ("layername" )[0 ].childNodes [0 ].nodeValue .encode ()
358
- + " \n " )
365
+ self .outFile .write (" CLASS\n " )
359
366
360
- # use the point symbol map to lookup the mapserver symbol type
361
- self .outFile .write (" SYMBOL " + symbol + " \n " )
362
- self .outFile .write (" SIZE "
363
- + symbolNode .getElementsByTagName ('pointsize' )[0 ].childNodes [0 ].nodeValue .encode ()
364
- + " \n " )
367
+ self .outFile .write (" NAME "
368
+ + layerNode .getElementsByTagName ("layername" )[0 ].childNodes [0 ].nodeValue .encode ()
369
+ + " \n " )
365
370
366
- # outline color
367
- outlineNode = symbolNode .getElementsByTagName ('outlinecolor' )[0 ]
368
- self .outFile .write (" OUTLINECOLOR "
369
- + outlineNode .getAttribute ('red' ) + ' '
370
- + outlineNode .getAttribute ('green' ) + ' '
371
- + outlineNode .getAttribute ('blue' )
372
- + "\n " )
373
- # color
374
- colorNode = symbolNode .getElementsByTagName ('fillcolor' )[0 ]
375
- self .outFile .write (" COLOR "
376
- + colorNode .getAttribute ('red' ) + ' '
377
- + colorNode .getAttribute ('green' ) + ' '
378
- + colorNode .getAttribute ('blue' )
379
- + "\n " )
371
+ self .outFile .write (" STYLE\n " )
372
+ # use the point symbol map to lookup the mapserver symbol type
373
+ symbol = self .msSymbol ( geometry , symbolNode )
374
+ self .outFile .write (" SYMBOL " + symbol + " \n " )
375
+ self .outFile .write (" SIZE "
376
+ + symbolNode .getElementsByTagName ('pointsize' )[0 ].childNodes [0 ].nodeValue .encode ()
377
+ + " \n " )
380
378
381
- # label
382
- # currently a very basic bitmap font
383
- # need to extend for font, size, color, buffer, alignment, etc
384
- labelNode = layerNode .getElementsByTagName ('labelattributes' )[0 ]
385
- labelField = labelNode .getElementsByTagName ('label' )[0 ].getAttribute ('field' ).encode ()
386
- if labelField != '' and labelField is not None :
387
- self .outFile .write (" LABEL \n " );
388
- self .outFile .write (" SIZE medium\n " );
389
- self .outFile .write (" COLOR 0 0 0 \n " );
390
- self .outFile .write (" END \n " );
379
+ # outline color
380
+ outlineNode = symbolNode .getElementsByTagName ('outlinecolor' )[0 ]
381
+ self .outFile .write (" OUTLINECOLOR "
382
+ + outlineNode .getAttribute ('red' ) + ' '
383
+ + outlineNode .getAttribute ('green' ) + ' '
384
+ + outlineNode .getAttribute ('blue' )
385
+ + "\n " )
386
+ # color
387
+ colorNode = symbolNode .getElementsByTagName ('fillcolor' )[0 ]
388
+ self .outFile .write (" COLOR "
389
+ + colorNode .getAttribute ('red' ) + ' '
390
+ + colorNode .getAttribute ('green' ) + ' '
391
+ + colorNode .getAttribute ('blue' )
392
+ + "\n " )
391
393
392
- # end of CLASS
393
- self .outFile .write (" END\n " )
394
+ self .outFile .write (" END\n " )
395
+
396
+ self .outFile .write ( self .msLabel ( layerNode ) )
397
+
398
+ # end of CLASS
399
+ self .outFile .write (" END\n " )
394
400
395
401
396
- # Graduated symbol renderer output
402
+ # Graduated symbol renderer output
397
403
def graduatedRenderer (self , layerNode , symbolNode ):
404
+ # get the layers geometry type
405
+ geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
406
+
398
407
# get the renderer field for building up the classes
399
408
classField = layerNode .getElementsByTagName ('classificationattribute' )[0 ].childNodes [0 ].nodeValue .encode ()
400
409
# write the render item
@@ -415,91 +424,81 @@ def graduatedRenderer(self, layerNode, symbolNode):
415
424
except :
416
425
self .outFile .write (" NAME '" + lower + " < " + classField + " < " + upper + "'\n " )
417
426
418
- self .outFile .write (" EXPRESSION ( ([" + classField + "] >= " + lower + ") AND ([" + classField + "] <= " + upper + ") )\n " )
427
+ self .outFile .write (" EXPRESSION ( ([" + classField + "] >= " + lower
428
+ + ") AND ([" + classField + "] <= " + upper + ") )\n " )
419
429
420
- # contains the same markup for a layer regardless of type
421
- # so we infer a symbol type based on the geometry
422
- geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
423
- if geometry == 'POLYGON' :
424
- symbol = '0'
425
- elif geometry == 'LINE' :
426
- symbol = '0'
427
- elif geometry == 'POINT' :
428
- symbolName = qgisSymbols [symbolNode .getElementsByTagName ('pointsymbol' )[0 ].childNodes [0 ].nodeValue .encode ()]
429
- # make sure it's single quoted
430
- symbol = "'" + symbolName + "'"
431
- self .outFile .write (" SYMBOL " + symbol + "\n " )
430
+ self .outFile .write (" STYLE\n " )
431
+ symbol = self .msSymbol ( geometry , symbolNode )
432
+ self .outFile .write (" SYMBOL " + symbol + "\n " )
432
433
433
434
# Symbol size
434
435
if geometry == 'POINT' or geometry == 'LINE' :
435
- self .outFile .write (" SIZE "
436
+ self .outFile .write (" SIZE "
436
437
+ cls .getElementsByTagName ('pointsize' )[0 ].childNodes [0 ].nodeValue .encode ()
437
438
+ " \n " )
438
439
439
440
# outline color
440
441
outlineNode = cls .getElementsByTagName ('outlinecolor' )[0 ]
441
- self .outFile .write (" OUTLINECOLOR "
442
+ self .outFile .write (" OUTLINECOLOR "
442
443
+ outlineNode .getAttribute ('red' ) + ' '
443
444
+ outlineNode .getAttribute ('green' ) + ' '
444
445
+ outlineNode .getAttribute ('blue' )
445
446
+ "\n " )
446
447
# color
447
448
colorNode = cls .getElementsByTagName ('fillcolor' )[0 ]
448
- self .outFile .write (" COLOR "
449
+ self .outFile .write (" COLOR "
449
450
+ colorNode .getAttribute ('red' ) + ' '
450
451
+ colorNode .getAttribute ('green' ) + ' '
451
452
+ colorNode .getAttribute ('blue' )
452
453
+ "\n " )
453
454
455
+ self .outFile .write (" END\n " )
456
+
454
457
# label
455
- # currently a very basic bitmap font
456
- # need to extend for font, size, color, buffer, alignment, etc
457
- labelNode = layerNode .getElementsByTagName ('labelattributes' )[0 ]
458
- labelField = labelNode .getElementsByTagName ('label' )[0 ].getAttribute ('field' ).encode ()
459
- if labelField != '' and labelField is not None :
460
- self .outFile .write (" LABEL \n " );
461
- self .outFile .write (" SIZE medium\n " );
462
- self .outFile .write (" COLOR 0 0 0 \n " );
463
- self .outFile .write (" END \n " );
458
+ self .outFile .write ( self .msLabel ( layerNode ) )
464
459
465
460
# end of CLASS
466
461
self .outFile .write (" END\n " )
467
462
468
- # Continuous symbol renderer output
463
+ # Continuous symbol renderer output
469
464
def continuousRenderer (self , layerNode , symbolNode ):
465
+ # get the layers geometry type
466
+ geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
467
+
470
468
# get the renderer field for building up the classes
471
469
classField = layerNode .getElementsByTagName ('classificationattribute' )[0 ].childNodes [0 ].nodeValue .encode ()
472
470
473
471
# write the rendering info for each class
474
472
self .outFile .write (" CLASS\n " )
475
-
476
- lower = symbolNode .getElementsByTagName ('lowestsymbol' )[0 ].getElementsByTagName ('symbol' )[0 ]
477
- upper = symbolNode .getElementsByTagName ('highestsymbol' )[0 ].getElementsByTagName ('symbol' )[0 ]
478
473
479
474
# Class name irrelevant for color ramps since mapserver can't render their legend
480
475
#self.outFile.write(" NAME '" + classField + "'\n")
481
476
482
477
# color
478
+ lower = symbolNode .getElementsByTagName ('lowestsymbol' )[0 ].getElementsByTagName ('symbol' )[0 ]
479
+ upper = symbolNode .getElementsByTagName ('highestsymbol' )[0 ].getElementsByTagName ('symbol' )[0 ]
483
480
lowerColor = lower .getElementsByTagName ('fillcolor' )[0 ]
484
481
upperColor = upper .getElementsByTagName ('fillcolor' )[0 ]
485
482
486
483
# outline color
487
484
outlineNode = lower .getElementsByTagName ('outlinecolor' )[0 ]
488
485
489
486
self .outFile .write (" STYLE\n " )
487
+
488
+ # The first and last color of the ramp ( r g b r g b )
490
489
self .outFile .write (" COLORRANGE "
491
490
+ lowerColor .getAttribute ('red' ) + " "
492
491
+ lowerColor .getAttribute ('green' ) + " "
493
492
+ lowerColor .getAttribute ('blue' ) + " "
494
493
+ upperColor .getAttribute ('red' ) + " "
495
494
+ upperColor .getAttribute ('green' ) + " "
496
495
+ upperColor .getAttribute ('blue' ) + "\n " )
497
- # QGIS project file is a bit unclear...
498
- # lower.lowervalue <-> upper.lowervalue
499
- # upper.LOWER value .. hmm ...
496
+
497
+ # The range of values over which to ramp the colors
500
498
self .outFile .write (" DATARANGE "
501
499
+ lower .getElementsByTagName ('lowervalue' )[0 ].childNodes [0 ].nodeValue .encode () + ' '
502
500
+ upper .getElementsByTagName ('lowervalue' )[0 ].childNodes [0 ].nodeValue .encode () + '\n ' )
501
+
503
502
self .outFile .write (" RANGEITEM '" + classField + "'\n " )
504
503
self .outFile .write (" END\n " )
505
504
@@ -511,24 +510,20 @@ def continuousRenderer(self, layerNode, symbolNode):
511
510
self .outFile .write (" END\n " )
512
511
513
512
# label
514
- # currently a very basic bitmap font
515
- # need to extend for font, size, color, buffer, alignment, etc
516
- labelNode = layerNode .getElementsByTagName ('labelattributes' )[0 ]
517
- labelField = labelNode .getElementsByTagName ('label' )[0 ].getAttribute ('field' ).encode ()
518
- if labelField != '' and labelField is not None :
519
- self .outFile .write (" LABEL \n " );
520
- self .outFile .write (" SIZE medium\n " );
521
- self .outFile .write (" COLOR 0 0 0 \n " );
522
- self .outFile .write (" END \n " );
513
+ self .outFile .write ( self .msLabel ( layerNode ))
523
514
524
515
# end of CLASS
525
516
self .outFile .write (" END\n " )
526
517
527
518
528
- # Unique value renderer output
519
+ # Unique value renderer output
529
520
def uniqueRenderer (self , layerNode , symbolNode ):
530
521
# get the renderer field for building up the classes
531
522
classField = layerNode .getElementsByTagName ('classificationattribute' )[0 ].childNodes [0 ].nodeValue .encode ()
523
+
524
+ # get the layers geometry type
525
+ geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
526
+
532
527
# write the render item
533
528
self .outFile .write (" CLASSITEM '" + classField + "'\n " )
534
529
@@ -548,55 +543,42 @@ def uniqueRenderer(self, layerNode, symbolNode):
548
543
549
544
self .outFile .write (" EXPRESSION '" + lower + "' \n " )
550
545
551
- # contains the same markup for a layer regardless of type
552
- # so we infer a symbol type based on the geometry
553
- geometry = layerNode .getAttribute ("geometry" ).encode ().upper ()
554
- if geometry == 'POLYGON' :
555
- symbol = '0'
556
- elif geometry == 'LINE' :
557
- symbol = '0'
558
- elif geometry == 'POINT' :
559
- symbolName = qgisSymbols [symbolNode .getElementsByTagName ('pointsymbol' )[0 ].childNodes [0 ].nodeValue .encode ()]
560
- # make sure it's single quoted
561
- symbol = "'" + symbolName + "'"
562
- self .outFile .write (" SYMBOL " + symbol + "\n " )
546
+ # Get the symbol name
547
+ symbol = self .msSymbol ( geometry , symbolNode )
548
+
549
+ self .outFile .write (" STYLE\n " )
550
+ self .outFile .write (" SYMBOL " + symbol + "\n " )
563
551
564
552
# Symbol size
565
553
if geometry == 'POINT' or geometry == 'LINE' :
566
- self .outFile .write (" SIZE "
554
+ self .outFile .write (" SIZE "
567
555
+ cls .getElementsByTagName ('pointsize' )[0 ].childNodes [0 ].nodeValue .encode ()
568
556
+ " \n " )
569
557
570
558
# outline color
571
559
outlineNode = cls .getElementsByTagName ('outlinecolor' )[0 ]
572
- self .outFile .write (" OUTLINECOLOR "
560
+ self .outFile .write (" OUTLINECOLOR "
573
561
+ outlineNode .getAttribute ('red' ) + ' '
574
562
+ outlineNode .getAttribute ('green' ) + ' '
575
563
+ outlineNode .getAttribute ('blue' )
576
564
+ "\n " )
565
+
577
566
# color
578
567
colorNode = cls .getElementsByTagName ('fillcolor' )[0 ]
579
- self .outFile .write (" COLOR "
568
+ self .outFile .write (" COLOR "
580
569
+ colorNode .getAttribute ('red' ) + ' '
581
570
+ colorNode .getAttribute ('green' ) + ' '
582
571
+ colorNode .getAttribute ('blue' )
583
572
+ "\n " )
573
+ self .outFile .write (" END\n " )
584
574
585
575
# label
586
- # currently a very basic bitmap font
587
- # need to extend for font, size, color, buffer, alignment, etc
588
- labelNode = layerNode .getElementsByTagName ('labelattributes' )[0 ]
589
- labelField = labelNode .getElementsByTagName ('label' )[0 ].getAttribute ('field' ).encode ()
590
- if labelField != '' and labelField is not None :
591
- self .outFile .write (" LABEL \n " );
592
- self .outFile .write (" SIZE medium\n " );
593
- self .outFile .write (" COLOR 0 0 0 \n " );
594
- self .outFile .write (" END \n " );
595
-
576
+ self .outFile .write ( self .msLabel ( layerNode ))
577
+
596
578
# end of CLASS
597
579
self .outFile .write (" END\n " )
598
580
599
- # Utility method to format a proj4 text string into mapserver format
581
+ # Utility method to format a proj4 text string into mapserver format
600
582
def formatProj4 (self , proj4text ):
601
583
parms = proj4text .split (" " )
602
584
ret = ""
@@ -605,3 +587,80 @@ def formatProj4(self, proj4text):
605
587
ret = ret + " '" + p + "'\n "
606
588
return ret
607
589
590
+ # Determines the symbol name and adds it to the symbol queue
591
+ def msSymbol (self , geometry , symbolNode ):
592
+ # contains the same markup for a layer regardless of type
593
+ # so we infer a symbol type based on the geometry
594
+ symbolName = ''
595
+ symbol = '0'
596
+
597
+ if geometry == 'POLYGON' :
598
+ symbol = '0'
599
+ elif geometry == 'LINE' :
600
+ symbol = '0'
601
+ elif geometry == 'POINT' :
602
+ try :
603
+ symbolName = qgisSymbols [symbolNode .getElementsByTagName ('pointsymbol' )[0 ].childNodes [0 ].nodeValue .encode ()]
604
+ except :
605
+ symbolName = "CIRCLE"
606
+ # make sure it's single quoted
607
+ symbol = "'" + symbolName + "'"
608
+
609
+ if symbolName == 'CIRCLE' :
610
+ self .symbolQueue ['CIRCLE' ] = """
611
+ #Circle symbol
612
+ SYMBOL
613
+ NAME 'CIRCLE'
614
+ TYPE ellipse
615
+ FILLED true
616
+ POINTS
617
+ 1 1
618
+ END
619
+ END """
620
+
621
+ if symbolName == 'TRIANGLE' :
622
+ self .symbolQueue ['TRIANGLE' ] = """
623
+ SYMBOL
624
+ NAME "TRIANGLE"
625
+ TYPE vector
626
+ FILLED true
627
+ POINTS
628
+ 0 1
629
+ .5 0
630
+ 1 1
631
+ 0 1
632
+ END
633
+ END """
634
+
635
+ return symbol
636
+
637
+ # Label block creation
638
+ # TODO field-based parameters, alignment, truetype fonts, sizes
639
+ def msLabel (self , layerNode ):
640
+ # currently a very basic bitmap font
641
+ labelNode = layerNode .getElementsByTagName ('labelattributes' )[0 ]
642
+ labelField = labelNode .getElementsByTagName ('label' )[0 ].getAttribute ('field' ).encode ()
643
+ if labelField != '' and labelField is not None :
644
+ labelBlock = " LABEL \n "
645
+
646
+ labelBlock += " SIZE medium\n "
647
+ labelBlock += " COLOR 0 0 0 \n "
648
+
649
+ # Include label angle if specified
650
+ # Note that angles only work for truetype fonts which aren't supported yet
651
+ angle = labelNode .getElementsByTagName ('angle' )[0 ].getAttribute ('value' ).encode ()
652
+ labelBlock += " ANGLE " + angle + "\n "
653
+
654
+ # Include label buffer if specified
655
+ # Note that the buffer has different meaning in qgis vs mapserver
656
+ # mapserver just adds blank space around the label while
657
+ # qgis uses a fill color around the label
658
+ # Note that buffer only works for truetype fonts which aren't supported yet
659
+ buffer = labelNode .getElementsByTagName ('buffersize' )[0 ].getAttribute ('value' ).encode ()
660
+ labelBlock += " BUFFER " + buffer + "\n "
661
+
662
+ labelBlock += " END \n "
663
+ return labelBlock
664
+ else :
665
+ return ''
666
+
0 commit comments