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