1 //      Illustrates backdrop plotting of world, US maps.
2 //      Contributed by Wesley Ebisuzaki.
3 //
4 
5 #include "plcdemos.h"
6 
7 void map_transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data );
8 void mapform19( PLINT n, PLFLT *x, PLFLT *y );
9 PLFLT normalize_longitude( PLFLT lon );
10 void geolocation_labeler( PLINT axis, PLFLT value, char *label, PLINT length, PLPointer data );
11 
12 void
13 map_transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer PL_UNUSED( data ) )
14 {
15     PLFLT radius;
16 
17     radius = 90.0 - y;
18     *xt    = radius * cos( x * M_PI / 180.0 );
19     *yt    = radius * sin( x * M_PI / 180.0 );
20 }
21 
22 //--------------------------------------------------------------------------
23 // mapform19
24 //
25 // Defines specific coordinate transformation for example 19.
26 // Not to be confused with mapform in src/plmap.c.
27 // x[], y[] are the coordinates to be plotted.
28 //--------------------------------------------------------------------------
29 
30 void
31 mapform19( PLINT n, PLFLT *x, PLFLT *y )
32 {
33     int   i;
34     PLFLT xp, yp;
35     for ( i = 0; i < n; i++ )
36     {
37         map_transform( x[i], y[i], &xp, &yp, NULL );
38         x[i] = xp;
39         y[i] = yp;
40     }
41 }
42 
43 // "Normalize" longitude values so that they always fall between -180.0 and
44 // 180.0
45 PLFLT
46 normalize_longitude( PLFLT lon )
47 {
48     PLFLT times;
49     if ( lon >= -180.0 && lon <= 180.0 )
50     {
51         return ( lon );
52     }
53     else
54     {
55         times = floor( ( fabs( lon ) + 180.0 ) / 360.0 );
56         if ( lon < 0.0 )
57         {
58             return ( lon + 360.0 * times );
59         }
60         else
61         {
62             return ( lon - 360.0 * times );
63         }
64     }
65 }
66 
67 // A custom axis labeling function for longitudes and latitudes.
68 void
69 geolocation_labeler( PLINT axis, PLFLT value, char *label, PLINT length, PLPointer PL_UNUSED( data ) )
70 {
71     PLCHAR_VECTOR direction_label = NULL;
72     PLFLT         label_val       = 0.0;
73 
74     if ( axis == PL_Y_AXIS )
75     {
76         label_val = value;
77         if ( label_val > 0.0 )
78         {
79             direction_label = " N";
80         }
81         else if ( label_val < 0.0 )
82         {
83             direction_label = " S";
84         }
85         else
86         {
87             direction_label = "Eq";
88         }
89     }
90     else if ( axis == PL_X_AXIS )
91     {
92         label_val = normalize_longitude( value );
93         if ( label_val > 0.0 )
94         {
95             direction_label = " E";
96         }
97         else if ( label_val < 0.0 )
98         {
99             direction_label = " W";
100         }
101         else
102         {
103             direction_label = "";
104         }
105     }
106     if ( axis == PL_Y_AXIS && value == 0.0 )
107     {
108         // A special case for the equator
109         snprintf( label, (size_t) length, "%s", direction_label );
110     }
111     else
112     {
113         snprintf( label, (size_t) length, "%.0f%s", fabs( label_val ), direction_label );
114     }
115 }
116 
117 //--------------------------------------------------------------------------
118 // main
119 //
120 // Shows two views of the world map.
121 //--------------------------------------------------------------------------
122 
123 int
124 main( int argc, char **argv )
125 {
126     PLFLT       minx, maxx, miny, maxy;
127     PLFLT       x, y;
128     //variables for the shapelib example
129     const PLINT nbeachareas    = 2;
130     const PLINT beachareas[]   = { 23, 24 };
131     const PLINT nwoodlandareas = 94;
132     PLINT       woodlandareas[94];
133     const PLINT nshingleareas  = 22;
134     const PLINT shingleareas[] = { 0, 1, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 217, 2424, 2425, 2426, 2427, 2428, 2491, 2577 };
135     const PLINT ncragareas     = 2024;
136     PLINT       cragareas[2024];
137     const PLINT majorroads[] = { 33, 48, 71, 83, 89, 90, 101, 102, 111 };
138     int         i;
139 
140 // Parse and process command line arguments
141 
142     (void) plparseopts( &argc, argv, PL_PARSE_FULL );
143 
144 // Longitude (x) and latitude (y)
145 
146     miny = -70;
147     maxy = 80;
148 
149     plinit();
150 
151 // Cartesian plots
152 // Most of world
153 
154     minx = -170;
155     maxx = minx + 360;
156 
157     // Setup a custom latitude and longitude-based scaling function.
158     plslabelfunc( geolocation_labeler, NULL );
159 
160     plcol0( 1 );
161     plenv( minx, maxx, miny, maxy, 1, 70 );
162     plmap( NULL, "usaglobe", minx, maxx, miny, maxy );
163 
164 // The Americas
165 
166     minx = 190;
167     maxx = 340;
168 
169     plcol0( 1 );
170     plenv( minx, maxx, miny, maxy, 1, 70 );
171     plmap( NULL, "usaglobe", minx, maxx, miny, maxy );
172 
173     // Clear the labeling function
174     plslabelfunc( NULL, NULL );
175 
176 // Polar, Northern hemisphere
177 
178     minx = 0;
179     maxx = 360;
180 
181     plenv( -75., 75., -75., 75., 1, -1 );
182     plmap( mapform19, "globe", minx, maxx, miny, maxy );
183 
184     pllsty( 2 );
185     plmeridians( mapform19, 10.0, 10.0, 0.0, 360.0, -10.0, 80.0 );
186 
187 // Polar, Northern hemisphere, this time with a PLplot-wide transform
188 
189     minx = 0;
190     maxx = 360;
191 
192     plstransform( map_transform, NULL );
193 
194     pllsty( 1 );
195     plenv( -75., 75., -75., 75., 1, -1 );
196     // No need to set the map transform here as the global transform will be
197     // used.
198     plmap( NULL, "globe", minx, maxx, miny, maxy );
199 
200     pllsty( 2 );
201     plmeridians( NULL, 10.0, 10.0, 0.0, 360.0, -10.0, 80.0 );
202 
203     // Show Baltimore, MD on the map
204     plcol0( 2 );
205     plssym( 0.0, 2.0 );
206     x = -76.6125;
207     y = 39.2902778;
208     plpoin( 1, &x, &y, 18 );
209     plssym( 0.0, 1.0 );
210     plptex( -76.6125, 43.0, 0.0, 0.0, 0.0, "Baltimore, MD" );
211 
212     // For C, this is how the global transform is cleared
213     plstransform( NULL, NULL );
214 
215     // An example using shapefiles. The shapefiles used are from Ordnance Survey, UK.
216     // These were chosen because they provide shapefiles for small grid boxes which
217     // are easilly manageable for this demo.
218 
219     pllsty( 1 );
220 
221 
222     minx = 240570;
223     maxx = 621109;
224     miny = 87822;
225     maxy = 722770;
226     plscol0( 0, 255, 255, 255 );
227     plscol0( 1, 0, 0, 0 );
228     plscol0( 2, 150, 150, 150 );
229     plscol0( 3, 0, 50, 200 );
230     plscol0( 4, 50, 50, 50 );
231     plscol0( 5, 150, 0, 0 );
232     plscol0( 6, 100, 100, 255 );
233 
234 
235     minx = 265000;
236     maxx = 270000;
237     miny = 145000;
238     maxy = 150000;
239     plscol0( 0, 255, 255, 255 ); //white
240     plscol0( 1, 0, 0, 0 );       //black
241     plscol0( 2, 255, 200, 0 );   //yelow for sand
242     plscol0( 3, 60, 230, 60 );   // green for woodland
243     plscol0( 4, 210, 120, 60 );  //brown for contours
244     plscol0( 5, 150, 0, 0 );     //red for major roads
245     plscol0( 6, 180, 180, 255 ); //pale blue for water
246     plscol0( 7, 100, 100, 100 ); //pale grey for shingle or boulders
247     plscol0( 8, 100, 100, 100 ); //dark grey for custom polygons - generally crags
248 
249 
250     plcol0( 1 );
251     plenv( minx, maxx, miny, maxy, 1, -1 );
252     pllab( "", "", "Martinhoe CP, Exmoor National Park, UK (shapelib only)" );
253 
254 
255     //Beach
256     plcol0( 2 );
257     plmapfill( NULL, "ss/ss64ne_Landform_Area", minx, maxx, miny, maxy, beachareas, nbeachareas );
258 
259     //woodland
260     plcol0( 3 );
261     for ( i = 0; i < nwoodlandareas; ++i )
262         woodlandareas[i] = i + 218;
263     plmapfill( NULL, "ss/ss64ne_Landform_Area", minx, maxx, miny, maxy, (PLINT_VECTOR) woodlandareas, nwoodlandareas );
264 
265     //shingle or boulders
266     plcol0( 7 );
267     plmapfill( NULL, "ss/ss64ne_Landform_Area", minx, maxx, miny, maxy, shingleareas, nshingleareas );
268 
269     //crags
270     plcol0( 8 );
271     for ( i = 0; i < ncragareas; ++i )
272         cragareas[i] = i + 325;
273     plmapfill( NULL, "ss/ss64ne_Landform_Area", minx, maxx, miny, maxy, (PLINT_VECTOR) cragareas, ncragareas );
274 
275     //draw contours, we need to separate contours from high/low coastline
276     //draw_contours(pls, "ss/SS64_line", 433, 20, 4, 3, minx, maxx, miny, maxy );
277     plcol0( 4 );
278     plmapline( NULL, "ss/ss64ne_Height_Contours", minx, maxx, miny, maxy, NULL, 0 );
279 
280     //draw the sea and surface water
281     plwidth( 0.0 );
282     plcol0( 6 );
283     plmapfill( NULL, "ss/ss64ne_Water_Area", minx, maxx, miny, maxy, NULL, 0 );
284     plwidth( 2.0 );
285     plmapline( NULL, "ss/ss64ne_Water_Line", minx, maxx, miny, maxy, NULL, 0 );
286 
287     //draw the roads, first with black and then thinner with colour to give an
288     //an outlined appearance
289     plwidth( 5.0 );
290     plcol0( 1 );
291     plmapline( NULL, "ss/ss64ne_Road_Centreline", minx, maxx, miny, maxy, NULL, 0 );
292     plwidth( 3.0 );
293     plcol0( 0 );
294     plmapline( NULL, "ss/ss64ne_Road_Centreline", minx, maxx, miny, maxy, NULL, 0 );
295     plcol0( 5 );
296     plmapline( NULL, "ss/ss64ne_Road_Centreline", minx, maxx, miny, maxy, majorroads, 9 );
297 
298     //draw buildings
299     plwidth( 1.0 );
300     plcol0( 1 );
301     plmapfill( NULL, "ss/ss64ne_Building_Area", minx, maxx, miny, maxy, NULL, 0 );
302 
303     //labels
304     plsfci( 0x80000100 );
305     plschr( 0, 0.8 );
306     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "MARTINHOE CP", minx, maxx, miny, maxy, 202 );
307     plschr( 0, 0.7 );
308     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Heale\nDown", minx, maxx, miny, maxy, 13 );
309     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "South\nDown", minx, maxx, miny, maxy, 34 );
310     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Martinhoe\nCommon", minx, maxx, miny, maxy, 42 );
311     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Woody Bay", minx, maxx, miny, maxy, 211 );
312     plschr( 0, 0.6 );
313     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Mill Wood", minx, maxx, miny, maxy, 16 );
314     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Heale Wood", minx, maxx, miny, maxy, 17 );
315     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 1.0, "Bodley", minx, maxx, miny, maxy, 31 );
316     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.0, "Martinhoe", minx, maxx, miny, maxy, 37 );
317     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Woolhanger\nCommon", minx, maxx, miny, maxy, 60 );
318     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "West Ilkerton\nCommon", minx, maxx, miny, maxy, 61 );
319     plmaptex( NULL, "ss/ss64ne_General_Text", 1.0, 0.0, 0.5, "Caffyns\nHeanton\nDown", minx, maxx, miny, maxy, 62 );
320 
321     plend();
322     exit( 0 );
323 }
324