/
ms-rfc-6.txt
228 lines (166 loc) · 6.93 KB
/
ms-rfc-6.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
.. _rfc6:
===============================================================
MS RFC 6: Color Range Mapping of Continuous Feature Values
===============================================================
:Date: 2005/09/27
:Author: Bill Binko
:Contact: bill at binko.net
:Status: Proposed
Description: This proposal addresses the need to be able to easily
map continuous feature values to a continuous range of colors. This RFC is
the result of (and my interpretation of) the discussion that
surrounded Bug #1305.
A preliminary patch has already been applied to MapServer 4.6+ (before
the RFC process was in place), however, there is little consensus on the
format being used and there is no support for proper display of
legends for classes using ColorRanges.
Background
~~~~~~~~~~
This work started as a patch that I created to be able to quickly
visualize data with a large range of values. In particular, I was
wishing to map property values, and various ratios that could take on
a large range of values. To me, the natural way to do this was to set
a max value, a min value and what colors those mapped to. The patch I
wrote had MapServer do a linear interpolation of the value for each
feature on to that color range.
The initial syntax for this feature simply added 5 new keywords to the
STYLE block and looked as follows:
::
STYLE
COLOR 60 60 60
MINCOLOR 0 0 0
MAXCOLOR 255 255 0
MINVALUE 0.0
MAXVALUE 300000.0
GRADIENTITEM "sale_price"
END
After some discussion, the term Gradient was shown to be problematic.
Also, the number of new keywords seemed high. After some discussion,
the syntax was changed to this format:
::
STYLE
COLORRANGE 0 0 0 255 255 0 # black to yellow
DATARANGE 0.0 100.0
RANGEITEM "foobar"
END
While this is still just a set of keywords under a Style, it seemed
simpler and is now working in the MapServer 4.6 branch.
Current Syntax Problems
~~~~~~~~~~~~~~~~~~~~~~~
Several people pointed out that the current syntax could be improved
by:
1) Moving the new keywords into a block
2) Adding a METHOD keyword with the type of interpolation used
('linear' being the first defined type, 'logarithmic' being a
potential second type, etc.
3) Adding an INTERVALS keyword that would limit the number of colors
actually used by rounding values before interopolation.
4) Moving all of the keywords out of the Style block.
5) Allowing the ColorRange to be defined separately so that it can be reused
Proposed New Syntax
~~~~~~~~~~~~~~~~~~~
To meet the above needs, I propose the following new Block Syntax:
::
COLORRANGE
RANGEITEM 'itemname' #required
MINCOLOR 0 0 0 #optional - default = Black
MAXCOLOR 255 255 0 #optional -default = White
MINVALUE 0.0 #optional - default = 0
MAXVALUE 100.0 #optional - default = 1
INTERVALS 10 #optional - default = 0 (unlimited)
METHOD LINEAR #optional - default = 'LINEAR'
END
I propose that this block lives at the CLASS level. My reasons for
putting it at the CLASS, rather than the LAYER (or above) level are as
follows:
1) CLASS is the lowest level that can define a Legend entry (by using
a named class)
2) Allows multiple COLORANGES to be applied to a single layer
(i.e. Red->Yellow and Yellow->Green to make a contiguous
Reg->Yellow->Green).
3) Allows "out of bounds" values to be highlighted separately (with a
different CLASS).
(If we wish to provide this capability on the OUTLINECOLOR, then I
would suggest we create a OUTLINECOLORRANGE block with identical format.)
Note: I am (and have always been) flexible on all of the keyword names
and formats here. However, given the discussion that's gone on around
(and around) this, I thought I'd put a straw man up and start here.
Proposed Legend Format
~~~~~~~~~~~~~~~~~~~~~~
I have posted a mockup of how I believe legends should look at
https://github.com/mapserver/mapserver/issues/324
The format only changes the height of the legend (which is already
dynamic) so it should not have major layout implications.
(Nit-picking about how tall the colorbar should be can be worked out
during implementation.)
I have not started the legend support, and would like some help in
this area. However, I do believe it is straightforward, and I will do
it on my own if there are no volunteers.
MapScript Issues
~~~~~~~~~~~~~~~~
As Sean Gillies mentioned in the discussion, this should be
encapsulated in MapScript as a class. While I disagree with his
putting it on the LAYER (see above), the rest of his suggestions all
seem right in line.
I Propose a class named ColorRamp with the following read/write attributes:
::
Color minColor
Color maxColor
double minValue
double maxValue
String rangeItem
String method
int intervals
and two methods
::
Color findColor(double value)
double findValue(Color color)
ColorRamps can be obtained through an appropriate constructor or
through a new (read/write) attribute on the ClassObj object:
::
ColorRange colorRange
Note: I will need help in adding these to MapScript as I do not have
the SWIG experience to do it well.
Files affected
~~~~~~~~~~~~~~
I will update this list as the RFC evolves, but right now, these are
what I see:
- mapfile.h => Change Keywords
- maplexer.l => Change Keywords
- mapfile.c => process new Keywords
- mapscript/swiginc/\*.i => various interface modifications to fit the
above requirements
- maplegend.c => Add new Legend support
- mapdraw.c => update existing ColorRange code to use new keywords &
add intervals and LOGARITHMIC method
Backwards compatibility issues
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Right now, certain code _requires_ that there is a COLOR attribute set
on any layer that is going to be displayed. Either this will need to
be changed, or we will have to decide what that means if both a COLOR
and a COLORRANGE are defined. One option is to use the COLOR for any
values that are outside of the range.
Multiple Mapping Methods
~~~~~~~~~~~~~~~~~~~~~~~~
The system will allow new color mapping methods to be added with as little
effort as possible. If a new color mapping method uses only the keywords
defined by this RFC, it should be a simple as:
1) Implement a function with the signature
::
int mappingFn(colorRangeObj\* range, shapeObj\* shape, colorObj \*color)
This function should use the shape and range parameters to determine the
shapes color, and modify the color parameter accordingly.
2) Choose a unique method name ('linear', 'logarithmic', 'discrete')
modify the method msMapColorRamp() to call its method when its method name
is found on a ColorRange definition.
.. note::
Whether the msMapColorRamp() method uses if/then logic or dispatches
by function pointer can be determined later. For now, I believe the
simplest approach would be to move all of the mapping logic + all current
methods into a mapColorRange.c file.
Bug ID
~~~~~~
Currently this is being tracked by https://github.com/mapserver/mapserver/issues/1305
Voting history
~~~~~~~~~~~~~~
None