[QGIS-trac] Re: [Quantum GIS] #3222: Fast, easy and beautiful on the fly rule-based rendering of OSM maps

Quantum GIS qgis at qgis.org
Wed Dec 22 20:11:39 EST 2010


#3222: Fast, easy and beautiful on the fly rule-based rendering of OSM maps
------------------------------------------------+---------------------------
   Reporter:  mayeulk                           |              Owner:  mayeulk      
       Type:  enhancement                       |             Status:  new          
   Priority:  major: does not work as expected  |          Milestone:  Version 1.7.0
  Component:  Symbology                         |            Version:               
   Keywords:                                    |   Platform_version:               
   Platform:  All                               |           Must_fix:  No           
Status_info:  0                                 |  
------------------------------------------------+---------------------------

Comment(by mayeulk):

 I have made extensive additions to many parts of the code to support some
 useful features to render map with complex symbology grammar. Still, I
 have problems with the symbol levels. I would like to enable symbol levels
 when several rules are matched. It would be useful when a feature
 (specially highways) should be represented with a combination of symbols.
 For instance, a road can be on a bridge, under a tunnel [with transparent
 tunnel symbol], in construction, bordered with trees, etc.
 In many cases, it is possible to simply combine the symbols, e.g. one
 symbol for the road itself and another one for the bridge "around" it. It
 would be possible to use only one rule for all highways (except motorways
 if shown with wider symbol).
 If we have 30 types of ways and 5 types of additional symbols (bridge,
 etc), we could then do this with only 30+5=35 rules instead of 30*5=150.
 (Imagine if you add 10 scale-based rules: you got 1500 combinations!!).

 For the implementation, I modified the symbolForFeature function (code
 below) in src/core/symbology-ng/qgsrulebasedrendererv2.cpp

 Here is what I'm trying to do:
 For the first matched rule for a given feature, the code makes a copy of
 the rule's symbol. If other rules are matched, it merges the layers of the
 additional matched rule with the symbol(s) of previously matched rule(s).
 It also merges the information on symbol levels.

 Tests on rendering on small areas (with features matched by 2 rules) works
 partially:
  * the symbols are correctly merged. A new symbol is created and
 displayed, based on the symbology and levels of the matching rules  8-)
  * However, it modifies the symbol associated with the first matched rule
 and shown in the style sheet (if you open the layer properties, you see
 that the symbol has been permanently modified): the 1st matched rule is
 now represented by  a combination of the 2 original symbols. This change
 is saved permanently in the Layer Properties. Similarly for symbol levels.
 8-(
  * it crashes very often 8-(

 Below is the related draft code. I'm sure there are several incorrect
 thinks here. Anyone could help?
 Thanks!
 Mayuel

 {{{
 QgsSymbolV2* QgsRuleBasedRendererV2::symbolForFeature( QgsFeature& feature
 )
 {
 //    return mCurrentSymbol;
 //    QgsSymbolV2* mergedSymbols = QgsSymbolV2::defaultSymbol( QGis::Line
 ); // tmp test
    QgsSymbolV2* mergedSymbols; //FIXME is this correct?
     int nSym = 0; // Number of symbols for a given feature

   for ( QList<Rule*>::iterator it = mCurrentRules.begin(); it !=
 mCurrentRules.end(); ++it )
   {
     Rule* rule = *it;

     if ( rule->isFilterOK( mCurrentFields, feature ) )
         {
              if (nSym == 0){
                 ++nSym;
                 QgsDebugMsg( "@@@@@@@@@@@@@@@@@@@@@@@@@@ ");
                 QgsDebugMsg( "@@ 1st symbol to be merged:" +
 rule->dump());
                 mergedSymbols = rule->symbol(); //FIXME is this correct?
 is it why the symbol in the rule itself get modified?
             }
             else
             {
                 QgsDebugMsg( "@@ ADDING  ADDITIONAL SYMBOL FOR GIVEN
 FEATURE");
                   QgsSymbolV2* tmpSymbol = rule->symbol();
 //                tmpSymbol = rule->symbol();
                 QgsDebugMsg( "num layers tmpSymbol:" + QString::number(
 tmpSymbol->symbolLayerCount() ) );
                 QgsDebugMsg( "tmpSymbol Rule:" + rule->dump());
                 QgsDebugMsg( "tmpSymbol Pass0 :" + QString::number(
 tmpSymbol->symbolLayer( 0 )->renderingPass() ) );

                 // Merge layers of additional matched rule with symbol(s)
 of previously matched rules
                 QgsSymbolLayerV2*  sl = tmpSymbol->symbolLayer( 0 );

                 QgsDebugMsg( "Highest symbol level : " + QString::number
 ((mergedSymbols->symbolLayer( (mergedSymbols->symbolLayerCount()) -1
 ))->renderingPass()));

                 // insert symbol matching additional rule only if its
 first layer is strictly above the last layer of the already merged symbol:
                 // this is partly to avoid part of the catastrophic
 consequences of the bug with insertSymbolLayer a few lines below
                 // and might be changed when this bug is fixed
                if(rule->symbol()->symbolLayer( 0 )->renderingPass() <=
 ((mergedSymbols->symbolLayer( (mergedSymbols->symbolLayerCount()) -1
 ))->renderingPass()) ) {QgsDebugMsg("Break"); break;}

                QgsDebugMsg(   QString::number(rule->symbol()->symbolLayer(
 0 )->renderingPass()));
                 mergedSymbols->insertSymbolLayer(
 (mergedSymbols->symbolLayerCount()) , sl ); // probably buggy: modifies
 the symbol styles as well!!
 //
 (mergedSymbols->symbolLayer(1))->setRenderingPass(sl->renderingPass() );
                  (mergedSymbols->symbolLayer(1))->setRenderingPass(
 rule->symbol()->symbolLayer( 0 )->renderingPass() );
                 QgsDebugMsg( "mergedSymbols layer: " + QString::number(1)
 + "  Pass: "   +
 QString::number(mergedSymbols->symbolLayer(1)->renderingPass())   );

 // For testing, currently only one layer is added. Adding several layers
 could be done with some code more or less like:
 //                for( int slid = 0 ; slid < tmpSymbol->symbolLayerCount()
 ; ++slid ){
 //                    QgsSymbolLayerV2*  sl = tmpSymbol->symbolLayer( slid
 );
 //                    mergedSymbols->insertSymbolLayer( slid, sl );
 //
 (mergedSymbols->symbolLayer(slid))->setRenderingPass(sl->renderingPass()
 );
 //                    QgsDebugMsg( "mergedSymbols layer: " +
 QString::number(slid) + "  Pass: "   +
 //
 QString::number(mergedSymbols->symbolLayer(slid)->renderingPass())   );
 //                }


             }
     //        return rule->symbol(); //work with levels but takes only
 first rule
          }
   }
     QgsDebugMsg( "num layers mergedSymbols:" + QString::number(
 mergedSymbols->symbolLayerCount() ) );
     QgsDebugMsg( " mergedSymbols Pass layer0:"+
 QString::number(mergedSymbols->symbolLayer( 0 )->renderingPass() ));
     QgsDebugMsg( "@ @ @ @ @ @ return mergedSymbols");
     return mergedSymbols;
 }
 }}}

-- 
Ticket URL: <http://trac.osgeo.org/qgis/ticket/3222#comment:7>
Quantum GIS <http://qgis.org>
Quantum GIS is an Open Source GIS viewer/editor supporting OGR, PostGIS, and GRASS formats


More information about the QGIS-trac mailing list