[mapguide-internals] RFC 60 questions about ComputeUsedColors

Walt Welton-Lair walt.welton-lair at autodesk.com
Thu Mar 26 11:01:00 EDT 2009


Regarding color expressions, I see now that only one pass through the would be needed.  Basically during stylization you would need to build up a list of colors used during rendering.  Of course this still has a performance impact associated with it, but it doesn't seem as bad.

Theming involves setting up a collection of rules, each with a filter condition and its own style.  As long as you're iterating over the rules you will capture any theming.

For composite styles, you can get a few examples by running the server rendering unit tests (from the command line use "mgserver test renderingservice").  As long as you build the Server solution all the data files should be there.  Look at the TestCase_SymbologyXYZ test cases in TestRenderingService.

Walt


-----Original Message-----
From: mapguide-internals-bounces at lists.osgeo.org [mailto:mapguide-internals-bounces at lists.osgeo.org] On Behalf Of UV
Sent: Tuesday, March 24, 2009 9:55 PM
To: MapGuide Internals Mail List
Subject: Re: [mapguide-internals] RFC 60 questions about ComputeUsedColors

Thanks Walt for having a look.

I hope this is not opening a can of worms as the use case for our client 
is already sufficiently implemented ;-)

1) And yes you are right I only read text string colors so far...... 
thats what I could extract from the XML schemas....
However, the code is collecting simply a unique list of strings here.... 
which leaves us a lot of room to do other things with them!
The strings are translated into colors only in the rendering service 
before they are passed to the AGG renderer.

BTW, I did not  manage to find more detailed information on the theming 
bit so far ..... I suppose, however,  that in the long run the
color collecting code needs to be deeper integrated into the 
mapping/rendering code which uses the theming capabilities.
In the moment I am lacking sufficient documentation and samples to see a 
way how to get there.

2) Currently the code is evaluating Area/Line/Point Rules and collects 
colors from the corresponding xxxSymbolization classes.
    This seemed sufficient for our use case as only the areas are really 
affected.
    Also I did not manage to follow the symbol definitions and 
compositeTypeStyles to the actual definition of colors in my samples.....
    If I get a few use cases and examples of how this is used and what 
else need to be done to retrieve those colors I am happy to add that for 
completeness.
(I believe in this case the code should be merged further with the 
rendering/mapping code doing that lookup already to avoid unnecessary 
overhead in calling the resource service)

    The color collection is done  in the 
VectorLayerDefinition.::ComputeUsedColors and this code is called from 
the StylizeLayers right after stylization....
    As I do not really understanding all details here that was the place 
seeming logical... :) 

3) I included the relevant code bits here and I will be posting a patch 
later today after cleaning up and synching with the repository.
    If there will be votes to add more StylizationTypes to the color 
extraction thats fine with me....
    I will require some support in forms of examples and test cases = 
maps to do so. 
    Also the following up of ResourceIds which I believe will be 
essential to do the SymbolDefintions need more considerations
    In the current approach the simple rescanning of the in memory layer 
defs seems performant enough to just plug it into the Stylize Layer code 
as is.


Cheers,
UV

Walt Welton-Lair wrote:
> Hi UV,
>
> I like the change you've made in your RFC about not storing user stored palettes.  It simplifies things significantly.
>
> The updated RFC suggests adding a new ComputeUsedColors method to VectorLayerDefinition.  Just to be sure I understand, the purpose of the method is to iterate through the layer definition data model and build a list of all colors reference by the styles?  If so, I have a couple of questions:
>
> 1/ How will the new method work with colors which are set to expressions?  While not a very common use case - color variation is generally done via theming - MapGuide does support it.  Getting that use case to fully work with your RFC seems like it would require two passes through the features - one pass to evaluate the color expression(s) against all the features which want to be rendered, and the second pass to do the actual rendering using the updated tile palette.  I'm not suggesting we actually do this, but I think it needs to be pointed out as a limitation with your updated approach.
>
> 2/ With the new enhanced stylization (RFC 14) the layer definition can reference symbol definitions (in addition to inlining them).  The symbols, of course, define colors which need to be accounted for.  Accessing referenced symbol definitions requires the resource service - we need to get the symbol definition resource from the service.  The MdfModel project (where VectorLayerDefinition is stored) does not have access (nor want access) to the resource service.  So if you want to properly support the new enhanced stylization with your RFC (you should) then we'll probably have to move this ComputeUsedColors method somewhere else.  There's a method - MgMappingUtil::ComputeStylizationOffset - which does something analogous to ComputeUsedColors, so possibly we can add ComputeUsedColors to MgMappingUtil.
>   
I added the call just a few lines below the call to the  
MgMappingUtil::ComputeStylizationOffset           right after the 
stylization    

#line 565
                   if (NULL != fdoReader.p)
                    {
                        // stylize into output format
                        dr->StartLayer(&layerInfo, &fcinfo);
                        ds->StylizeVectorLayer(vl, dr, rsReader, 
xformer, scale, NULL, NULL);
                        dr->EndLayer();
                        
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                        // COLORPALETTE CODE from UV for Ticket #813
                        // add the colors from this scaleRange and 
vectorlayer to the map colors
                        // (overrideFilters == NULL could tells us
                        // that we have been called for rendering a map 
and not for selection)
                        {
                            // the map object owns the color list so get 
a pointer from there
                            PSTRCOLORLIST pStringColorPalette = 
map->GetColorPalette();
                            PSTRCOLORLIST vLayerColors = 
vl->ComputeUsedColors(scaleRange);
                            if (!vLayerColors->empty())
                            {
                                assert (pStringColorPalette);
                                // add the vectorLayer's Colors to the 
map's color list
                                STRCOLORLIST::iterator it = 
vLayerColors->begin();
                                for(; it != vLayerColors->end(); it++)
                                {    // uppercase the colorcodes 
(FFABDEFF) and filter empty strings
                                    if (*it == L"") continue;
                                    STRING upc = *it;
                                    std::transform( upc.begin(), 
upc.end(), upc.begin(), towupper);
                                    pStringColorPalette->push_back(upc);
                                }
                                assert (pStringColorPalette == 
map->GetColorPalette());  /// make sure this is the same palette
                                // the property setter canonicalizes the 
palette
                                map->SetColorPalette(pStringColorPalette);
                            }
                            #ifdef _DEBUG
                            
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
StylizeLayers::Palette->size(): %d\n", pStringColorPalette->size());
                            #endif
                        }
                        
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                    }
                }


Here is the Compute UsedColors method

//-------------------------------------------------------------------------
// PURPOSE: Accessor method for the base colors defined in this Layer and scaleRange.
// RETURNS: A pointer to the list of colors of the collected colors (maybe empty but not null)
//-------------------------------------------------------------------------
PSTRCOLORLIST VectorLayerDefinition::ComputeUsedColors(VectorScaleRange* scaleRange)
{
	PSTRCOLORLIST foundColors = new STRCOLORLIST(); // always create
	// iterate through the featuretypecollection
	FeatureTypeStyleCollection* pftsColl = scaleRange->GetFeatureTypeStyles();
	int ftsccount = pftsColl->GetCount();
	for (int j=0; j< ftsccount; j++)
	{
		FeatureTypeStyle* pfts = pftsColl->GetAt(j);

		// iterate through the rulecollection
		RuleCollection* ruleColl = pfts->GetRules();
		int rccount = ruleColl->GetCount();
		for (int k=0; k < rccount; k++)
		{
			Rule* rule = ruleColl->GetAt(k);

			// get the label which will be the key in the color map
			const MdfString& label = rule->GetLegendLabel();

			// do the casting to access the relevant members
			// this is bad style (instead of virtual functions in each subclass)
			// but we save touching too many different files
			AreaRule* paRule = dynamic_cast<AreaRule*>(rule);
			LineRule* plRule = dynamic_cast<LineRule*>(rule);
			PointRule* ppRule = dynamic_cast<PointRule*>(rule);
			//CompositeRule* pcRule = dynamic_cast<CompositeRule*>(rule);  // no colors in there

			// AreaRule Symbolization.....
			if (paRule != NULL)
			{
				AreaSymbolization2D* pasym = paRule->GetSymbolization();
				if (pasym->GetFill() != NULL) {
					foundColors->push_back(pasym->GetFill()->GetForegroundColor());
					foundColors->push_back(pasym->GetFill()->GetBackgroundColor());
				}
				if (pasym->GetEdge() != NULL) 
					foundColors->push_back(pasym->GetEdge()->GetColor());
			}

			// LineRule Symbolization.....
			if (plRule != NULL)
			{
				LineSymbolizationCollection* plsymcol = plRule->GetSymbolizations();
				// iterate through the linesymbolizations
				int lsccount = plsymcol->GetCount();
				for (int l=0; l < lsccount; l++)
				{
					LineSymbolization2D* plsym = plsymcol->GetAt(l);
					if (plsym->GetStroke() != NULL)
						foundColors->push_back(plsym->GetStroke()->GetColor());
				}
			}
			// PointRule Symbolization.....
			if (ppRule != NULL)
			{
				PointSymbolization2D* ppsym = ppRule->GetSymbolization();
				if (ppsym)
				{
					Symbol *sym   = ppsym->GetSymbol();
					MdfModel::BlockSymbol* blockSymbol = dynamic_cast<MdfModel::BlockSymbol*>(sym);
					MdfModel::FontSymbol* fontSymbol = dynamic_cast<MdfModel::FontSymbol*>(sym);
					MdfModel::MarkSymbol* markSymbol = dynamic_cast<MdfModel::MarkSymbol*>(sym);
					MdfModel::TextSymbol* textSymbol = dynamic_cast<MdfModel::TextSymbol*>(sym);
					MdfModel::W2DSymbol* w2dSymbol = dynamic_cast<MdfModel::W2DSymbol*>(sym);
					if (blockSymbol != NULL)
					{
						foundColors->push_back(blockSymbol->GetBlockColor());
						foundColors->push_back(blockSymbol->GetLayerColor());
					}
					if (fontSymbol != NULL)
					{
						foundColors->push_back(fontSymbol->GetForegroundColor());
					}
					if (markSymbol != NULL)
					{
						if (markSymbol->GetEdge() != NULL)
							foundColors->push_back(markSymbol->GetEdge()->GetColor());
						if (markSymbol->GetFill() != NULL) {
							foundColors->push_back(markSymbol->GetFill()->GetForegroundColor());
							foundColors->push_back(markSymbol->GetFill()->GetBackgroundColor());
						}
					}
					if (textSymbol != NULL)
					{
						foundColors->push_back(textSymbol->GetForegroundColor());
						foundColors->push_back(textSymbol->GetBackgroundColor());
					}
					if (w2dSymbol != NULL)
					{
						foundColors->push_back(w2dSymbol->GetFillColor());
						foundColors->push_back(w2dSymbol->GetLineColor());
						foundColors->push_back(w2dSymbol->GetTextColor());
					}
				} // if pointSymbolization
			} // end pointRule

		} // for GetRules
	} // for GetFeatureTypeStyles
	#ifdef _DEBUG
	printf("|||||||||||||||||||||||||||||||||||||||||||||||VectorLayerDefinition %s found %d colors\n",
			this->GetFeatureName(), foundColors->size());
	#endif

	return foundColors;
}


> Walt
>
>  W       E         @__   __o
>    A   T   R   @___    _ \<,_
>      L           @_   (*)/ (*)
>
>
> _______________________________________________
> mapguide-internals mailing list
> mapguide-internals at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/mapguide-internals
>
>   

_______________________________________________
mapguide-internals mailing list
mapguide-internals at lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/mapguide-internals


More information about the mapguide-internals mailing list