Chapter Nine: Theme Mapping and Analysis
Theme Mapping and Analysis
Thematic mapping is a powerful way to analyze and visualize your data. You give graphic form to your data so that you can see it on a map. Patterns and trends that are almost impossible to detect in lists of data reveal themselves clearly when you use thematic shading to display data on a map.
With MapXtreme, you can create applications with thematic maps.
What Is Thematic Mapping?
Thematic mapping is the process of shading your map according to a particular theme. The theme is usually some piece or pieces of your data. You thematically shade a map using data from a layer. The most commonly known example of a thematic map is a weather map. When you see red, you know it is hot (high number of degrees); where you see blue, it is cold (low number of degrees).
Themes represent your data with shades of color, fill patterns, or symbols. There are many, many uses for thematic maps to display your data. You create different thematic maps by assigning these colors, patterns, or symbols to map objects according to specific values in your data.
Thematic mapping allows you to visualize and highlight trends in data that would be difficult to see through tabular data. Using the methods in the ThemeList and the Theme Interface, you can create and define your own thematic shading.
MapXtreme Java Edition has three types of thematic maps:
All layers that have thematic maps use the ThemeList collection, the Theme interface, and the Rendition object. Each specific theme type will use other objects to create the appropriate map. They are explained in detail later in this chapter.
General Objects for Themes
The ThemeList collection is accessible from the Layer object and contains Theme objects. These Theme objects, which are built from information in the tables for the layer, make up your thematic map. Each theme can contain a different type of thematic shading. The ThemeList collection has methods used to perform operations such as adding and removing Theme object(s) from the collection.
The ThemeList allows several thematic shades to exist for one layer. It is important to keep the themes ordered correctly so that they display on the map. For example, if you had two themes that both changed the fill color of objects, one would obscure the other when the map is rendered. The last theme added to the list has precedence. The ThemeList works well for certain situations. For example, if you had a map of the world and wanted to shade the countries by population and also by literacy rate, the ThemeList allows this. You could first create a theme to shade by population using a different fill color for the regions and add that to the ThemeList. You could then create a theme to shade by literacy using a different edge color for the regions and add that to the ThemeList.
ThemeList objects are used even if you only have one theme.
Theme is an interface. The methods of this interface allow you to retrieve the column which the theme is based on and the theme's descriptive name. If either the column or the name do not exist for a particular theme, a null value will be returned.
The Rendition object is used throughout MapXtreme. It gives all of the style characteristics to features. When creating thematic maps, you will use Renditions to specify the appearance of the objects.
An IDSelectionTheme can be used to change the Rendition of all Features in a FeatureSet. This type of theme is commonly used to highlight a group of objects returned from a search method. For example, if you had performed a searchWithinRadius on a layer of points, you may want to display the points of the returned FeatureSet as bright red circles. To accomplish this, you would have to loop through the FeatureSet, get the PrimaryKey for each Feature, and add the Feature and a specified rendition to the Theme.
Features are included in the theme via the add method, which takes a PrimaryKey and a Rendition. The PrimaryKey is an object that can uniquely identify a record in the table. The Rendition object will be the Rendition used to display the features on the map.
The following code is an example of an IDSelectionTheme:
IDSelectionTheme mySelectTheme = new IDSelectionTheme("myTheme");
// Assume myLayer is a Layer object.
// Assume fs is a FeatureSet returned from a search such
// as searchWithinRadius.
// Assume that rend is a previously created Rendition object.
myFeature = fs.getNextFeature();
while (myFeature != null)
pkey = myFeature.getPrimaryKey();
myFeature = fs.getNextFeature();
// Next, add the selection to the ThemeList
The IDSelectionTheme is used for shading features from a search. If you want to shade a layer by several values, use the RangedTheme object.
An OverrideTheme can be used to change the rendition of an entire layer. For example, if you wanted the world table to display with a red fill pattern and green edge color, you would use an OverrideTheme.
To make an OverrideTheme for a layer, you only need to pass a Rendition object in its constructor.
// Assume myLayer is a Layer object.
// Assume myRend is a Rendition object.
OverrideTheme myOTheme = new OverrideTheme(myRend,"My Theme");
A RangedTheme is a more complex type of thematic map. When you create a ranged thematic map, all rows are grouped into ranges and each assigned a rendition for its corresponding range. For example, you have a table of weather stations for your television viewing area, and you want to shade the locations according to their reported snowfall amounts.
With the Ranged map feature, MapXtreme groups the snowfall amounts into ranges. For instance all weather stations that received between zero and five inches of snowfall in the past month are grouped into one range. Stations receiving between five and 10 inches are in a separate range. Sites that received between 10 and 15 inches are in a third range, while those stations reporting greater than 15 inch snowfall amounts are in a fourth range. Each range is referred to as a Bin. Each Bin has an upper-bound cut-off value.
All records in the table are assigned to a range and then assigned a rendition based on that range. For instance the weather stations reporting the 15 plus inches of snow are shaded red. The other ranges are shaded in lighter shades of red with the last range in gray (default colors). When you display the map, the colors make it readily apparent which locations received the most and least snow accumulation.
MapXtreme includes several utility objects that help create a RangedTheme.
The ColumnStatistics interface is returned when you use the fetchColumnStatistics method of the Layer object. The ColumnStatistics object contains information on the minimum, maximum, mean, and standard deviation of the values in a column. When you use the fetchColumnStatistics method, you pass the column on which you want the map shaded. You will not need to use the methods of the ColumnStatistics object directly to create a RangedTheme. Once the object has been retrieved, it is then used in the Bucketer object to create a vector of breakpoints.
The Bucketer class is responsible for calculating the breakpoints for the Bins in a RangedTheme. For example, you may have a series of region objects representing oil fields. You may want to shade the regions by the oil yield for each field. Shade each region according to a certain range, such as green for over 500 barrels a day, white for 200-500, and orange for less than 200. Each of these ranges is represented by a Bin.
The Bucketer calculates the breakpoints using the computeDistribution methods. These methods all return a vector of breakpoints. All of the computeDistribution methods pass the number of ranges and a ColumnStatistics object. You may also pass a Distribution Type and a RoundOff object.
DISTRIBUTION_TYPE_EQUAL_COUNT has the same number of records in each range. If you want the Bucketer to group 100 records into 4 ranges using equal count, it computes the ranges so that approximately 25 records fall into each range, depending on the rounding factor you set.
When using equal count (or any other range method), it's important to watch out for any extreme data values that might affect your thematic map (in statistics, these values are referred to as outliers). For example, if you shade according to equal count with this database:
Ben and Miguel are grouped in the same range (since they have the two lowest values). This may not produce the results you want since the value for Ben is so much lower than any of the other values.
DISTRIBUTION_TYPE_EQUAL_RANGES divides records across ranges of equal size. For example, you have a field in your table with data values ranging from 1 to 100. You want to create a thematic map with four equal size ranges. The Bucketer produces ranges 1-25, 26-50, 51-75, and 76-100.
Keep in mind that the Bucketer may create ranges with no data records, depending on the distribution of your data. For example, if you shade the following database according to Equal Ranges:
The Bucketer creates four ranges (1-25, 26-50, 51-75, and 76-100). Notice, however, that only two of those ranges (1-25 and 76-100) actually contain records.
DISTRIBUTION_TYPE_STANDARD_DEVIATION breaks at the middle range of the mean of your values, and the ranges above and below the middle range are one standard deviation above or below the mean.
The RoundOff object is use to create clean breakpoints for ranges. For example, if you were shading a map with values that ranged from 101 to 397, the range breaks would be cleaner if the range was 100 to 400. RoundOff can round down the lower end of your range down, and round up the higher end of your range.
An important part of creating a useful thematic map is to represent the values with renditions that gradually go from one value to another. The example above discussed shading snowfall amounts. One end of the values was represented with red, and the next range was a lighter red, and so forth. The spread method of the LinearRenditionSpreader will return a vector of Renditions that spread the style from one given rendition to another for the number of elements given. The number of elements should match the number of ranges passed to the Bucketer object. For example, if you passed a rendition that was a red fill, a rendition that was a white fill, and the number five, the LinearRenditionSpreader would create a vector of five renditions with the red fill at the beginning, the white fill at the end, and an even spread of fill types in between.
Creating a RangedTheme
The following example demonstrates the code for creating a RangedTheme:
Rendition yellow=new Rendition(), red=new Rendition();
lyr = m_map.getLayers().getLayer("States.tab");
colName = "Pop_1990";
colStats = lyr.fetchColumnStatistics(colName);
// Set number of breaks for data
// Compute the distribution of data with 5 breaks and
// Equal Ranges
rBreaks = Bucketer.computeDistribution
// Set up a red and a yellow rendition and then
// spread the colors
rends = LinearRenditionSpreader.spread
(numBreaks+1, yellow, red);
// Create Theme object
rTheme = new RangedTheme
(colName, rBreaks, rends, "States by Pop_1990");
// Get ThemeList class object
// Add theme to Layers themeList
catch (Exception e)