MapWindow 4 - Plugins : MapWindow Discussion Forum
How, in the new MapWindow (4.8) can I most simply grayscale shade shapes depending on some calculated value for each shape. Transferring to the excellent MapWindow 4.8 the coloring in my plugin now doesn't function. If there’s no easy-to-follow documentation yet coul
Changing Shape Color
Posted by: danofweaver ()
Date: July 01, 2011 04:20AM

How, in the new MapWindow (4.8) can I most simply grayscale shade shapes depending on some calculated value for each shape.

Transferring to the excellent MapWindow 4.8 the coloring in my plugin now doesn't function.

If there’s no easy-to-follow documentation yet could you possibly answer the below example with some VB.net code:

Example...

Part A
I have 10 shapes (0 to 9) in shapefile sf. Their values (stored in field 5 if that is relevant) are:
.25
.5
.75
.2
.3
.4
.5
.6
.7
.8

Part B
For the same ten shapes I make a calculation and now have new values which don't require storage so
are not stored in a column of the MapWindow table but DO require a visualisation ie white=minimum value, black = maximum value.
The minimum value resulting from the calculation is 1.1 and the maximum 9.4

Q: How do I most easily shade shapes where minimum = white and maximum = black?

I used to do something like this...

For x = 0 To oMW.Layers(oMW.Layers.CurrentLayer).Shapes.NumShapes - 1

theGrescaleShadeColor= calculateShadeColour(x)
oMW.Layers(0).Shapes(x).ShapeFillColor = theGrescaleShadeColor

Next

GENERAL USAGE CASE...
I have 150 shapes (counties) with medical measures.
Measure 1 (a correlation measure) has values between -1 and 1.
Measure 2 has values between 0 and 1.
Measure 3 is a dynamic (user dictated) value based on some calculation involving various shapes.


I've started this thread as it's easier to find for future searchers but it's partly a continuation of these threads...

[www.mapwindow.org]
[www.mapwindow.org]

Is this as complex as creating a bunch of schemes and categories? If so is there a simple tutorial on doing this?

Any help gratefully received, full example code most helpful...

ps- The new MapWindow really rocks my world- I'm really happy that the project is moving forward so strongly and providing a framework that organisations without access to huge funding streams can realistically use and build on. Congratulations all.

--
[danofweaver.googlepages.com] | danofweaver@googlemail.com | +44 (0)791 3985890

Options: ReplyQuote
Re: Changing Shape Color
Posted by: Chris George ()
Date: July 03, 2011 08:59AM

It took me a while to work out how to do something similar, so I hope the code below is useful. It is in C# rather than VB, but it should be readable.

First I would set categories for a shapefile manually (right click in the legend entry and use Properties for the best interface). Then save the project and look in the .mwprj file for how categories are structured. It is strange that the ranges seem only to be stored as strings, which apparently means you have to parse them to decide which category a value would be in.

In my plugin users are asked to decide on a colour scheme and number of categories themselves. You seem to decide for them that it will be white to black, so you also need to decide a number of categories. The function SetCategories below assumes a set of categories existing already, so it knows how many there will be and what the colour is for each, using the input set. It then changes the categories based on an input minimum and maximum value. To save having to parse values later to colour the shapefile in the MapWindow view it also creates a list of "rangeIndex" values. rangeIndex is just a struct containing a start, finish, and category index, so a list of them makes a simple lookup table to find the category index for a particular value. "displayVar" is the name of the attribute being used to colour the shapefile.

		/// <summary>
		/// Set categories in a range of min to max
		/// and return list of ranges with corresponding category indexes
		/// </summary>
		/// <param name="cs"></param>
		/// <param name="min"></param>
		/// <param name="max"></param>
		List<rangeIndex> SetCategories(MapWinGIS.ShapefileCategories cs, double min, double max)
		{
			// Increase spread to avoid rounding errors losing min and max values
			// (gives black regions in display)
			min = 0.95 * min;
			max = 1.05 * max;
			int numBreaks = cs.Count;
			// avoid dividing by zero
			if (numBreaks == 0) return null;
			double range = max - min;
			double step = range / numBreaks;
			double next = min;
			rangeIndexes = new List<mwSWATResults.rangeIndex>();
			for (int i = 0; i < numBreaks; i++)
			{
				MapWinGIS.ShapefileCategory cat = cs.get_Item(i);
				double startVal = next;
				next += step;
				double endVal = next;
				string varId = displayVar.Trim();
				cat.Name = startVal.ToString("G3") + " - " + endVal.ToString("G3");
				cat.Expression = 
					"[" + varId + "] >= " + startVal.ToString("G6") +
					" AND [" + varId + "] < " + endVal.ToString("G6");
				rangeIndex ri = new mwSWATResults.rangeIndex(startVal, endVal, i);
				rangeIndexes.Add(ri);
				cs.set_Item(i, cat);
			}
			return rangeIndexes;
		}
	


Here is the bit of code that colours the shapefile. First it uses SetCategories to make the categories and the lookup table. Then it assigns the new categories to the shapefile sf in layer resultsLayer. Then it opens the corresponding dbf file, and for each shape s it reads the value for the attribute whose index is in displayFieldIndex, looks up the category index in the lookup table (GetCategory), and sets the shape category. Finally it redraws the OCX. map (of type AxMapWinGIS.AxMap) is mw.GetOCX, where mw is the MapWindow.Interfaces.IMapWin object passed to a plugin by its Initialize method.

			string resultsTable = Path.ChangeExtension(resultsShapefile, "dbf");
			results = new MapWinGIS.TableClass();
			rangeIndexes = SetCategories(resultsCategories, minmin, maxmax);
			MapWinGIS.ShapefileClass sf = (MapWinGIS.ShapefileClass) resultsLayer.GetObject();
			sf.Categories = resultsCategories;
			// repaint
			results.Open(resultsTable, null);
			for (int s = 0; s < numRows; s++)
			{
				double val = Convert.ToDouble(results.get_CellValue(displayFieldIndex, s), CultureInfo.InvariantCulture);
				int index = GetCategoryIndex(val, rangeIndexes);
				sf.set_ShapeCategory(s, index);
			}
			results.Close();
			map.Redraw();
	

Hope I haven't forgotten to explain anything.

Chris

Options: ReplyQuote
Re: Changing Shape Color
Posted by: Sergei ()
Date: July 04, 2011 07:29AM

Chris,

1. You shouldn't call: cs.set_Item(i, cat);

cs.get_Item(i) provides a reference to the category (not a copy of it). set_Item should be used only if you've created new Category.

2. In your code you duplicate functionality that already implemented in MapWinGIS. I suppose the same effect can be achieved by automatic generation of categories with ctEqualIntervals classification. See sample here:
[mapwingis.codeplex.com]

Shapefile.Categories.Generate(FieldIndex, classification, number_of_classes); 
Shapefile.Categories.ApplyExpressions();

Even if you need your own implementation of GenerateCategories (in your case it's SetCategories function), then why to apply categories manually when expression are already specified for them? It's simply enough to call:

Shapefile.Categories.ApplyExpressions();

MapWinGIS has build-in expression parser and will set categories for particular shapes.

3. Shapefile.set_ShapeCategory should be called only in case it's impossible to specify expression for category. For example, a user chooses shapes randomly on the map and wants them to be coloured in the same way. In all the rest cases - use expressions.

4. In your code you apply categories for values in some range [min, max]. In case it doesn't encompass all the values in the given field - ShapefileCategories.Generate won't be able to provide the same classification for you. I can add overloaded method:

ShapefileCategories.Generate2(long FieldIndex, VARIANT minValue,  VARIANT maxValue, tkClassificationType ClassificationType, long numClasses, VARIANT_BOOL* retVal);

Let me know in case it's needed (better at mapwingis.codeplex.com)

Regards,
Sergei



Edited 1 time(s). Last edit at 07/04/2011 09:16AM by Sergei.

Options: ReplyQuote
Re: Changing Shape Color
Posted by: Sergei ()
Date: July 04, 2011 09:17AM

I've added the new method ShapefileCategories.AddRange. Example is here:
[mapwingis.codeplex.com]

Options: ReplyQuote
Re: Changing Shape Color
Posted by: Chris George ()
Date: July 04, 2011 11:44AM

Many thanks, Sergei. I was operating on a cycle of guess and experiment. In particular, although the function ApplyExpressions is available it is difficult to use without a grammar of valid expressions being documented.

Anyway, your efforts are much appreciated. I'll try out your suggestions soon.

Chris

Options: ReplyQuote
Re: Changing Shape Color
Posted by: danofweaver ()
Date: July 05, 2011 05:16AM

Thanks ever so much for that Chris and thanks for your detailed response Sergei.
I feel all examples for this so far (in all threads referred to) are intimidatingly complex for MapWindow plugin learners.

I’m discouraged at the apparent difficulty to complete a task which was previously so simple. I’m also surprised that backward compatibility seems not to exist. Is there any documentation or straightforward notes for coloring specified shape indices a specific color?

Why does something like this now not function?
oMW.Layers(0).Shapes(x).ShapeFillColor = color.blue

The shapes’ color in my case is a result of a dynamic calculation so a field index is not available unless I change the program structure significantly- I may later do this but would like the choice. I would have thought a few lines of code should do this as has been the case previously.

I have years coding experience and am finding getting a simple solution to this a real struggle - one of the great barriers in education to getting people excited by GIS coding is the seemingly impenetrable nature of programming tasks and lack of simple examples and explanations - how would this task be completed by the the new GIS programmers to whom I am recommending MapWindow? Please look at the complexity of the examples now in this thread and in the threads referred to.

I don’t want to sound ungrateful, Sergei; I’m certain that the changes to the symbology are incredibly powerful and it’s fantastic that this high level coding of an OS product is going ahead. I want the basic functionality to be accessible and to be able to use the new MapWindow for all its improvements.

Can anyone complete my example question (see top of thread) in a few lines of code or explain with examples an alternative but straightforward way of looking at problems like these?

Warm regards,
Dan

Options: ReplyQuote
Re: Changing Shape Color
Posted by: pmeems ()
Date: July 14, 2011 02:56AM

I've just created a small test script that is adding random point shapes and gives them a random color.
Hopefully it makes it a bit more clear:
[svn.mapwindow.org]

--
Paul

--
Don't forget to read the new documentation: www.mapwindow.org/documentation/mapwingis4.8
Join us Google+: MapWindow GIS Google+ Community
Join the MapWindow Group on LinkedIn! LinkedIn - MapWindow Group

Download the latest beta installer at:
tinyurl.com/mwMonthly 32-Bit
tinyurl.com/mwMonthlyx64 64-Bit
Follow me on Twitter MapWindow_nl to read when a new installer is published.

---
Paul Meems
The Netherlands
[www.bontepaarden.nl]
Release manager, configuration manager and
forum moderator of MapWindow GIS

Owner of MapWindow.nl - Support for
Dutch speaking users: www.mapwindow.nl

*******
Everything I say or write is my personal opinion and
not the opinion of the company I work for.
*******
View my profile on LinkedIn

Options: ReplyQuote
Re: Changing Shape Color
Posted by: Sabin21 ()
Date: September 29, 2011 09:05AM

It seems that the new method for generating Feature Symbols in MapWindow using Categories has left old properties dangling. It was extremely convenient to be able to read/write Symbol information for each Shape. I have plugins that used this feature, which will no longer work in MapWindow 4.8.x.

I was coding some experiments in cycling through the Categories and comparing them to each Shape’s attribute value so that I could directly relate each Shape to its assigned symbol set.

This has become rather time consuming, so I started to wonder if my efforts would be better served by getting this into MapWindow itself.

Would it be possible to associate symbol information to each Shape as it is being created and applied by the Categories object? Where is this sorting occurring in the code?

As it is, the Shapes collection from the Layers object has properties that don’t do anything. I would like to replace this with properties that do.

Any thoughts?

Tim Beermann

Options: ReplyQuote


Sorry, only registered users may post in this forum.





Banner Exchange




GISCP.com




Send us your banner logo (160x120) for the space above, and add this MapWindow banner ad to your site:

Just paste this text in your page: