-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathcgmap__define.pro
2073 lines (1863 loc) · 94.5 KB
/
cgmap__define.pro
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
; docformat = 'rst'
;
; PURPOSE:
; Provides an easy way to set up a map projection coordinate space using GCTP map
; projections normally accessed via Map_Proj_Init.
;
;******************************************************************************************;
; ;
; Copyright (c) 2011, by Fanning Software Consulting, Inc. All rights reserved. ;
; ;
; Redistribution and use in source and binary forms, with or without ;
; modification, are permitted provided that the following conditions are met: ;
; ;
; * Redistributions of source code must retain the above copyright ;
; notice, this list of conditions and the following disclaimer. ;
; * Redistributions in binary form must reproduce the above copyright ;
; notice, this list of conditions and the following disclaimer in the ;
; documentation and/or other materials provided with the distribution. ;
; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ;
; contributors may be used to endorse or promote products derived from this ;
; software without specific prior written permission. ;
; ;
; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ;
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ;
; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ;
; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ;
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ;
; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ;
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ;
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ;
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;
;******************************************************************************************;
;
;+--------------------------------------------------------------------------
; Provides an easy way to set up a map projection coordinate space using GCTP map
; projections normally accessed via Map_Proj_Init. Allows an unlimited number of map
; overlays, and can provide a fresh map structure on demand, eliminating the problem
; of ephemerial map structures that plaqued Map_Proj_Init until IDL 8.x. This program
; is basically a wrapper for Map_Proj_Init, with additional features that make it
; superiour for working with map projections in IDL.
;
; :Categories:
; Graphics, Map Projections
;
; :File_comments:
; Only GCTP projections are allowed. If you wish to use projections normally
; set up with Map_Set, use the comparable cgMap_Set command.
;
; :Author:
; FANNING SOFTWARE CONSULTING::
; David W. Fanning
; 1645 Sheely Drive
; Fort Collins, CO 80526 USA
; Phone: 970-221-0438
; E-mail: [email protected]
; Coyote's Guide to IDL Programming: http://www.idlcoyote.com
;
; :History:
; Change History::
; Brought over to the Coyote Library from a similar routine in the Catalyst Library.
; Updated to account for the bug that creates incorrect result in UTM projections
; when using the WGS84 ellipsoid. The Wallbeck ellipsoid is substituted for the
; WGS84 ellipsoid in this instance. David W. Fanning, 7 November 2011.
; Added IS_CYLINDRICAL method to solve a problem with grid labeling and drawing
; of grid lines. 16 Dec 2011. DWF.
; Added ERASE method to erase the display. 28 Dec 2011. DWF.
; Added check for identical range values in FORWARD method. 30 Dec 2011. DWF.
; I am convinced that the map structure returned by Map_Proj_Init, when there
; is a LIMIT used in the call contains a uv_box with incorrect latitude values.
; This is important because other routines (e.g., cgMapGrid) depend on these values.
; I've created a fix wherein I fixed the uv_box latitude values to correspond
; to the LIMIT of the map projection. 6 April 2012. DWF.
; Set the default CENTER_LATITUDE and CENTER_LONGITUDE to 0.0. 9 April 2012. DWF.
; Added NOFORWARDFIX keyword to allow skipping of the "fix" in the FORWARD method,
; as sometimes this is not needed or required. 29 June 2012. DWF.
; Fixed a problem that required having to set the UTM zone in addition to the latitude
; and longitude in a UTM projection. Now using cgUTMZone to determine the proper
; zone. 8 Aug 2012. DWF.
; Added a BOUNDARY keyword to the GetProperty method. 16 Aug 2012. DWF.
; Modified to allow Hotine Oblique Mercator map projections to work correctly. 7 Sept 2012. DWF.
; Additional changes to better handle IDL 8.2 map projections. 12 Sept 2012. DWF.
; Added LATLONBOX keyword to the GetProperty method to allow me to obtain
; the map boundary in the Google Map preferred notation of [north, south, east, west]
; in degrees. 30 Oct 2012.
; I was calculating the default X and Y range incorrectly for non-UTM map projections.
; I have now gone back to my original method of using the UV_BOX of the map structure
; to do this. However, there is still a problem with the UV_BOX when the center latitude
; is not zero. I still attempt to fix this problem in the code (SetMapProjection method). 3 Jan 2012. DWF.
; I added ASPECT and ISOTROPIC keywords to allow the setting of the aspect ratio of the map. 3 Jan 2012. DWF.
; Added zone to the information returned with MapInfo method if projection is UTM. 25 April 2013. DWF.
; The map aspect was disappearing because Total(!P.Multi) can occasionally be LT 0! Fixed. 3 July 2013. DWF.
; Added Hughes ellipsoid, used at NSIDC, as index 26 or as "Hughes". 11 Sept 2013. DWF.
; Fixed a bug in the way ellipsoids were selected when using numbers to choose elliposids. All ellipsoids
; with values over 20 were affected. 18 Sept 2013. DWF.
; Added FORMAT keyword to LanLonLabels method. 27 November 2013. DWF.
; Change EASTING and NORTHING keywords to FALSE_EASTING and FALSE_NOTHING to conform to Map_Proj_Init. 29 Nov 2013. DWF.
; Forgetting to add the false_easting and false_northing values to the structure in INIT method. 29 Nov 2013. DWF.
; Added Cylindrical Equal Area to list of projections that don't allow CENTER_LATITUDE keyword. 24 Dec 2014. DWF.
; Typo in code to handle ASPECT ratio was causing aspect ratio of output to be lost. Fixed. 19 Feb 2015. DWF.
;
; :Copyright:
; Copyright (c) 2011-2013, Fanning Software Consulting, Inc.
;---------------------------------------------------------------------------
;
;+--------------------------------------------------------------------------
; The initialization method for the cgMap object.
;
; :Params:
; map_projection: in, optional, type=string/integer, default='Equirectangular'
; The name or index number of the map projection desired. Passed directly
; to Map_Proj_Init as the map projection value. Only GCTP projections are
; allowed. If you wish to use projections normally set up with Map_Set, use
; the comparable cgMap_Set command.
;
; :Keywords:
; addcmd: in, optional, type=boolean, default=0
; If this keyword is set, the object is added to the resizeable graphics
; window, cgWindow. The DRAW method of the object is called in cgWindow.
; aspect: in, optional, type=float, default=none
; Set this keyword to a floating point ratio that represents the aspect ratio
; (ysize/xsize) of the resulting map projection. Note that `Aspect` cannot be
; used when plotting with !P.MULTI. Consider using cgLayout instead for multiple
; plots.
; background: in, optional, type=string, default='white'
; The name of the background color. Used only if the map object erases
; the display when it draws its contents.
; bcolor: optional, type=string, default='opposite'
; The name of the color to draw box axes with. Requires BOX_AXES be set.
; box_axes: in, optional, type=boolean, default=0
; Set this keyword to draw a box-style grid axes around the map. Applies
; only if creating a mapGrid object.
; center_latitude: in, optional, type=float, default=0.0
; The center latitude of the map projection.
; center_longitude: in, optional, type=float, default=0.0
; The center longitude of the map projection.
; ccolor: in, optional, type=string, default='charcoal'
; The name of the drawing color for the MapContinents object if this is requested.
; color: in, optional, type=string, default='opposite'
; The name of the drawing color for the object. Passed along to the mapGrid
; and MapContinents object if these are requested.
; continents: in, optional, type=boolean, default=0
; Set this keyword if you wish to create an overlay object of continental outlines
; that will be rendered when the draw method is called.
; datum: in, optional, type=string/integer, default='Sphere'
; This keyword is being depreciated in favor of the keyword ELLIPSOID,
; corresponding to changes to Map_Proj_Init initiated in IDL 7.
; draw: in, optional, type=boolean, default=0
; Set this keyword if you wish to immediately call the DRAW method after the
; object has been completely initialized.
; ellipsoid: in, optional, type=string/integer
; Set this to the name or index number of the ellopsoid or datum you wish to use
; for the map projection. The value is passed directly to Map_Proj_Init. The
; default is a sphere for those projections that only support a sphere, otherwise
; a Clark projection is used to conform to Map_Proj_Init defaults. Added the "Hughes"
; datum, which is used at NSIDC. Use "Hughes" or index number 25.
; erase: in, optional, type=boolean, default=0
; Set this keyword if you wish to have the object erase the current graphics display
; before drawing its content in the DRAW method. The graphics display will be erased
; in the background color.
; false_easting: in, optional, type=double, default=0.0
; Set this keyword to the false easting value (in meters) to be added to each x
; coordinate for the forward transform, or subtracted from each x coordinate for
; the inverse transform.
; false_northing: in, optional, type=double, default=0.0
; Set this keyword to the false northing value (in meters) to be added to each y
; coordinate for the forward transform, or subtracted from each y coordinate for
; the inverse transform.
; fill: in, optional, type=boolean, default=0
; Set this keyword to display filled continents, if the keyword CONTINENTS is set.
; gcolor: in, optional, type=string, default='gray'
; The name of the drawing color for the MapGrid object if this is requested.
; grid: in, optional, type=boolean, default=0
; Set this keyword if you wish to create an overlay object of map grid lines
; that will be rendered when the draw method is called.
; hires: in, optional, type=boolean, default=0
; Set this keyword if you wish to use high resolution continental outlines.
; Passed to the MapContinents object if one is requested.
; isotropic: in, optional, type=boolean, default=0
; Set this keyword to set the `Aspect` keyword to a value that correctly represents
; the same map unit length in both the X and Y directions. In other words, a map
; unit measured in the X direction is the same physical length as a map unit measured
; in the Y direction.
; land_color: in, optional, type=string
; The name of the drawing color for filled continents, if the keyword CONTINENTS
; is set. Passed directly to the cgMapContinents object.
; latlon_ranges: in, optional, type=boolean, default=0
; Normally the XRANGE and YRANGE keywords are set in terms of projected meters. If
; this keyword is set, then the values of XRANGE and YRANGE are assumed to be in longitude
; and latitude values, respectively, and will be converted to projected meters prior to
; being stored in the object.
; limit: in, optional, type=FltArr(4), default=none
; The normal LIMIT keyword to Map_Proj_Init, specifying the limit of the map
; projection in terms of latitude and longitude. Normally, `Limit` is used when using
; Map_Proj_Init. Most work is done by specifying the projected XY rectangular
; coordinate system with the keywords XRANGE and YRANGE.
; lcolor: in, optional, type=string
; Set this to the name of the label color to use in labeling grid lines.
; By default, the same as COLOR, or if BOX_AXIS is set, then same as BCOLOR.
; name: in, optional, type=string, default=selected by cgContainer.
; Use this keyword to name the object. Names are often used to select objects in
; program code.
; noborder: in, optional, type=boolean, default=0
; If this keyword is set, the customary border than surrounds the map projection is
; not drawn.
; noforwardfix: in, optional, type=boolean, default=0
; There is, I believe, a bug in MAP_PROJ_FORWARD that renders longitude values
; incorrectly in projected meter space. This is evidenced by MAP_GRID not producing
; the correct longitude lines in map coordinate systems set up in projected XY meters.
; In the FORWARD method I correct for this. But, this correction is not always needed
; or wanted. This property of the object allows me to turn that correction on or off,
; as needed. Normally, the fix is provided, unless this keyword is set to 1.
; onimage: in, optional, type=boolean, default=0
; If this keyword is set, the position of the map projection in the graphics window
; is obtained from the last image displayed with cgImage. This makes it extremely
; easy to display an image and immediately set up a map projection space that will
; allow you to annotate the image using map locations.
; position: in, optional, type=FltArr(4)
; The normalized position of the map projection space in the graphics window.
; The default is [0.075, 0.075, 0.925, 0.925]
; radians: in, optional, type=boolean, default=0
; Set this keyword to indicate latitude and longitude values are in radians rather
; than degrees.
; semimajor_axis: in, optional, type=double, default=varies
; The length of the semimajor axis of the ellipsoid in meters. Normally calculated
; from the ELLIPSOID keyword values.
; semiminor_axis: in, optional, type=double, default=varies
; The length of the semiminor axis of the ellipsoid in meters. Normally calculated
; from the ELLIPSOID keyword values.
; sphere_radius: in, optional, type=double, default=varies
; The length of the ellipsoidal sphere in meters. Normally calculated from the
; ELLIPSOID keyword values.
; title: in, optional, type=string, default=""
; The title of the map projection display.
; uvalue: in, optional, type=any, default=none
; A storage space for storing any kind of IDL variable of importance to the user.
; window: in, optional, type=boolean, default=0
; If this keyword is set, the object replaces any commands in a current
; cgWindow or it opens a new cgWindow and adds itself to it.
; xrange: in, optional, type=various
; Set this keyword to the X axis range desired in the data coordinate system.
; Normally expressed in XY projected meter space, unless the LATLON_RANGES
; keyword is set. The default is mapStruct.uv_box[[0,2]].
; yrange: in, optional, type=various
; Set this keyword to the X axis range desired in the data coordinate system.
; Normally expressed in XY projected meter space, unless the LATLON_RANGES
; keyword is set. The default is mapStruct.uv_box[[1,3]].
; zone: in, optional, type=integer, default=varies
; The zone (normally in UTM projections) of the map projection. If not given and needed,
; calculated from the CENTER_LATITUDE and CENTER_LONGITUDE keyword values.
; _EXTRA: in, optional
; Other keywords accepted by the MAP_PROJ_INIT command are allowed and are passed
; directly to the MAP_PROJ_INIT program.
;
;---------------------------------------------------------------------------
FUNCTION cgMap::INIT, map_projection, $
ADDCMD=addcmd, $
ASPECT=aspect, $
BACKGROUND=background, $
BCOLOR=bcolor, $
BOX_AXES=box_axes, $
CCOLOR=ccolor, $
CENTER_LATITUDE=center_latitude, $
CENTER_LONGITUDE=center_longitude, $
COLOR=color, $
CONTINENTS=continents, $
DATUM=datum, $
DRAW=draw, $
ELLIPSOID=ellipsoid, $
ERASE=erase, $
FALSE_EASTING=easting, $
FALSE_NORTHING=northing, $
FILL=fill, $
GCOLOR=gcolor, $
GRID=grid, $
HIRES=hires, $
ISOTROPIC=isotropic, $
LAND_COLOR=land_color, $
LATLON_RANGES=latlon_ranges, $
LCOLOR=lcolor, $
LIMIT=limit, $
NAME=name, $
NOBORDER=noborder, $
NOFORWARDFIX=noForwardFix, $
ONIMAGE=onimage, $
POSITION=position, $
RADIANS=radians, $
SEMIMAJOR_AXIS=semimajor_axis, $
SEMIMINOR_AXIS=semiminor_axis, $
SPHERE_RADIUS=sphere_radius, $
TITLE=title, $
WINDOW=window, $
XRANGE=xrange, $
YRANGE=yrange, $
UVALUE=uvalue, $
ZONE=zone, $
_EXTRA=extraKeywords
Compile_Opt idl2
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /CANCEL
void = cgErrorMsg()
RETURN, 0
ENDIF
; Structures used in the object.
datumStruct = { cgMap_DATUM }
void = { cgMap_PROJECTION }
; If you specify a BACKGROUND keyword, then ERASE is set automatically.
IF N_Elements(background) NE 0 THEN BEGIN
erase = 1
ENDIF ELSE background = 'white'
erase = Keyword_Set(erase)
SetDefaultValue, center_latitude, 0.0
SetDefaultValue, center_longitude, 0.0
SetDefaultValue, color, "opposite"
SetDefaultValue, easting, 0.0
SetDefaultValue, northing, 0.0
SetDefaultValue, position, [0.075, 0.075, 0.925, 0.925]
SetDefaultValue, title, ""
; Default map projection.
IF N_Elements(map_projection) EQ 0 THEN BEGIN
this_map_projection = 'Equirectangular'
map_projection = 117
limit = [-90, -180, 90, 180]
ENDIF
projections=[ {cgMap_PROJECTION, 'UTM', 101, 0 }, $ ; GCTP 101
{cgMap_PROJECTION, 'State Plane', 102, 0 }, $ ; GCTP 102
{cgMap_PROJECTION, 'Albers Equal Area', 103, 0 }, $ ; GCTP 103
{cgMap_PROJECTION, 'Lambert Conformal Conic', 104, 0 }, $ ; GCTP 104
{cgMap_PROJECTION, 'Mercator', 105, 0 }, $ ; GCTP 105
{cgMap_PROJECTION, 'Polar Stereographic', 106, 0 }, $ ; GCTP 106
{cgMap_PROJECTION, 'Polyconic', 107, 0 }, $ ; GCTP 107
{cgMap_PROJECTION, 'Equidistant Conic A', 108, 0 }, $ ; GCTP 108
{cgMap_PROJECTION, 'Transverse Mercator', 109, 0 }, $ ; GCTP 109
{cgMap_PROJECTION, 'Stereographic', 110, 1 }, $ ; GCTP 110
{cgMap_PROJECTION, 'Lambert Azimuthal', 111, 1 }, $ ; GCTP 111
{cgMap_PROJECTION, 'Azimuthal', 112, 1 }, $ ; GCTP 112
{cgMap_PROJECTION, 'Gnomonic', 113, 1 }, $ ; GCTP 113
{cgMap_PROJECTION, 'Orthographic', 114, 1 }, $ ; GCTP 114
{cgMap_PROJECTION, 'Near Side Perspective', 115, 1 }, $ ; GCTP 115
{cgMap_PROJECTION, 'Sinusoidal', 116, 1 }, $ ; GCTP 116
{cgMap_PROJECTION, 'Equirectangular', 117, 1 }, $ ; GCTP 117
{cgMap_PROJECTION, 'Miller Cylindrical', 118, 1 }, $ ; GCTP 118
{cgMap_PROJECTION, 'Van der Grinten', 119, 1 }, $ ; GCTP 119
{cgMap_PROJECTION, 'Hotine Oblique Mercator A', 120, 0 }, $ ; GCTP 120
{cgMap_PROJECTION, 'Robinson', 121, 1 }, $ ; GCTP 121
{cgMap_PROJECTION, 'Space Oblique Mercator A', 122, 0 }, $ ; GCTP 122
{cgMap_PROJECTION, 'Alaska Conformal', 123, 0 }, $ ; GCTP 123
{cgMap_PROJECTION, 'Interrupted Goode', 124, 1 }, $ ; GCTP 124
{cgMap_PROJECTION, 'Mollweide', 125, 1 }, $ ; GCTP 125
{cgMap_PROJECTION, 'Interrupted Mollweide', 126, 1 }, $ ; GCTP 126
{cgMap_PROJECTION, 'Hammer', 127, 1 }, $ ; GCTP 127
{cgMap_PROJECTION, 'Wagner IV', 128, 1 }, $ ; GCTP 128
{cgMap_PROJECTION, 'Wagner VII', 129, 1 }, $ ; GCTP 129
{cgMap_PROJECTION, 'Integerized Sinusoidal', 131, 1 }, $ ; GCTP 131
{cgMap_PROJECTION, 'Equidistant Conic B', 208, 0 }, $ ; GCTP 208
{cgMap_PROJECTION, 'Hotine Oblique Mercator B', 220, 0 }, $ ; GCTP 220
{cgMap_PROJECTION, 'Space Oblique Mercator B', 222, 0 }] ; GCTP 222
IF Float(!Version.Release) GE 8.0 THEN BEGIN
projections = [projections, {cgMap_PROJECTION, 'Cylindrical Equal Area', 132, 0 }]
; Lambert Azimuthal now allows all ellipsoids.
index = Where(projections.name EQ 'Lambert Azimuthal', count)
IF count GT 0 THEN projections[index].sphereOnly = 0
ENDIF
; Find the map projection.
IF Size(map_projection, /TNAME) EQ 'STRING' THEN BEGIN
index = Where(StrUpCase(projections.name[*]) EQ StrUpCase(map_projection))
IF index[0] EQ -1 THEN Message, 'Cannot find map projection ' + map_projection + ' in the CGTP projection list.'
ENDIF ELSE BEGIN
index = Where(projections.index EQ map_projection, count)
IF count EQ 0 THEN Message, 'Cannot find map projection index ' + StrTrim(map_projection,2) + ' in GCTP projection list.'
ENDELSE
this_map_projection = projections[index]
IF StrUpCase(this_map_projection.name) EQ StrUpCase('Mercator') THEN BEGIN
IF N_Elements(limit) EQ 0 THEN limit = [-84.75, -180, 84.75, 180]
ENDIF
; Find the datum.
theDatums = Replicate(datumStruct, 21)
theDatums[0] = { cgMap_DATUM, 0, 'Clark 1866', 6378206.4 , 6356583.8 }
theDatums[1] = { cgMap_DATUM, 1, 'Clark 1880', 6378249.145, 6356514.86955 }
theDatums[2] = { cgMap_DATUM, 2, 'Bessel', 6377397.155, 6356078.96284 }
theDatums[3] = { cgMap_DATUM, 3, 'International 1967', 6378157.5, 6356772.2 }
theDatums[4] = { cgMap_DATUM, 4, 'International 1909', 6378388.0, 6356911.94613 }
theDatums[5] = { cgMap_DATUM, 5, 'WGS 72', 6378135.0, 6356750.519915 }
theDatums[6] = { cgMap_DATUM, 6, 'Everst', 6377276.3452 , 6356075.4133 }
theDatums[7] = { cgMap_DATUM, 7, 'WGS 66', 6378145.0 , 6356759.769356 }
theDatums[8] = { cgMap_DATUM, 8, 'GRS 1980', 6378137.0, 6356752.31414 }
theDatums[9] = { cgMap_DATUM, 9, 'Airy', 6377563.396, 6356256.91 }
theDatums[10] = { cgMap_DATUM, 10, 'Modified Everest', 6377304.063, 6356103.039 }
theDatums[11] = { cgMap_DATUM, 11, 'Modified Airy', 6377340.189, 6356034.448 }
theDatums[12] = { cgMap_DATUM, 12, 'Walbeck', 6378137.0, 6356752.314245 }
theDatums[13] = { cgMap_DATUM, 13, 'Southeast Asia', 6378155.0, 6356773.3205 }
theDatums[14] = { cgMap_DATUM, 14, 'Australian National', 6378160.0, 6356774.719 }
theDatums[15] = { cgMap_DATUM, 15, 'Krassovsky', 6378245.0, 6356863.0188 }
theDatums[16] = { cgMap_DATUM, 16, 'Hough', 6378270.0 , 6356794.343479 }
theDatums[17] = { cgMap_DATUM, 17, 'Mercury 1960', 6378166.0, 6356784.283666 }
theDatums[18] = { cgMap_DATUM, 18, 'Modified Mercury 1968', 6378150.0, 6356768.337303 }
theDatums[19] = { cgMap_DATUM, 19, 'Sphere', 6370997.0, 6370997.0 }
IF Float(!Version.Release) GE 8.0 THEN BEGIN
theDatums[20] = { cgMap_DATUM, 24, 'WGS 84', 6378137.0, 6356752.314245 }
ENDIF ELSE BEGIN
theDatums[20] = { cgMap_DATUM, 8, 'WGS 84', 6378137.0, 6356752.314245 }
ENDELSE
; Since I already have "WGS 84" in the list, and since IDL 8 introduces an ellipsoid
; with this name, I am going to use index 24 to list the more commonly used "WGS84" name.
; Add "Hughes" as index 25.
IF Float(!Version.Release) GE 8.0 THEN BEGIN
theDatums = [theDatums, $
{ cgMap_DATUM, 20, 'Clarke IGN', 6378249.2, 6356515.0 }, $
{ cgMap_DATUM, 21, 'Helmert 1906', 6378200.0, 6356818.2 }, $
{ cgMap_DATUM, 22, 'Modified Fischer 1960', 6378115.0, 6356773.3 }, $
{ cgMap_DATUM, 23, 'South American 1969', 6378160.0, 6356774.7 }, $
{ cgMap_DATUM, 24, 'WGS84', 6378137.0, 6356752.314245 }, $
{ cgMap_DATUM, 26, 'Hughes', 6378273.00, 6356889.4 } ]
ENDIF
; Need a datum?
IF (N_Elements(datum) EQ 0) && (N_Elements(ellipsoid) EQ 0) THEN BEGIN
IF this_map_projection.sphereOnly EQ 1 THEN datum = 19 ELSE datum = 0
ENDIF
IF (N_Elements(datum) EQ 0) && (N_Elements(ellipsoid) NE 0) THEN datum = ellipsoid
IF N_Elements(datum) EQ 0 THEN BEGIN
thisDatum = theDatums[19]
ENDIF ELSE BEGIN
IF Size(datum, /TNAME) EQ 'STRING' THEN BEGIN
datumIndex = Where(StrUpCase(theDatums.name) EQ StrUpCase(datum))
datumIndex = datumIndex[0]
; If you can't find one, try compressing the names.
IF datumIndex[0] EQ -1 EQ 0 THEN BEGIN
datumIndex = Where(StrCompress(StrUpCase(theDatums.name), /Remove_All) EQ $
StrCompress(StrUpCase(datum), /Remove_All), nameCount)
ENDIF
; Now if you can't find one, report it.
IF datumIndex[0] EQ -1 THEN Message, 'Cannot find datum ' + datum + ' in datum list.'
thisDatum = theDatums[datumIndex]
ENDIF ELSE BEGIN
datumIndex = Where(theDatums.index EQ datum, count)
IF count GT 0 THEN thisDatum = theDatums[datumIndex[0]] ELSE Message, 'Cannot find datum ' + StrTrim(datum,2) + ' in datum list.'
ENDELSE
IF N_Elements(thisDatum) GT 1 THEN thisDatum = thisDatum[0]
ENDELSE
; There is a bug in all versions of IDL up to IDL 8.1 apparently that
; produces the wrong result when a UTM projection is used in conjunction
; with a WGS84 datum (the most common datum used in this projection). Here
; we substitute the WALBECK datum, which is nearly identical to WGS84 are
; results in position errors of less than a meter typically.
IF ((StrUpCase((thisDatum.Name)[0]) EQ 'WGS 84') || (StrUpCase((thisDatum.Name)[0]) EQ 'WGS84')) && $
(StrUpCase((this_map_projection.Name)[0]) EQ 'UTM') && $
(Float(!version.release) LT 8.2) THEN BEGIN
Print, 'Switching UTM datum from WGS84 to WALBECK to avoid UTM projection bug.'
thisDatum = { cgMAP_DATUM, 12, 'Walbeck', 6378137.0, 6356752.314245 }
ENDIF
; Modify the radii?
IF N_Elements(sphere_radius) NE 0 THEN BEGIN
semimajor_axis = sphere_radius
semiminor_axis = sphere_radius
ENDIF
IF N_Elements(semimajor_axis) NE 0 THEN thisDatum.semimajor_axis = semimajor_axis
IF N_Elements(semiminor_axis) NE 0 THEN thisDatum.semiminor_axis = semiminor_axis
IF N_Elements(zone) EQ 0 THEN zone = cgUTMZone(center_longitude, center_latitude)
; Default MAP_PROJ_INIT keywords.
IF N_Elements(extraKeywords) NE 0 $
THEN self._cg_map_projection_keywords = Ptr_New(extraKeywords) $
ELSE self._cg_map_projection_keywords = Ptr_New(/ALLOCATE_HEAP)
; Are ISOTROPIC or ASPECT keywords used?
IF Keyword_Set(isotropic) THEN self._cg_isotropic = 1
IF N_Elements(aspect) NE 0 THEN self._cg_aspect = aspect
; Load the object.
self._cg_background = background
self._cg_center_latitude = center_latitude
self._cg_center_longitude = center_longitude
self._cg_color = color
self._cg_easting = easting
self._cg_erase = erase
self._cg_multi_position = FltArr(4)
self._cg_noborder = Keyword_Set(noborder)
self._cg_noforwardfix = Keyword_Set(noforwardfix)
self._cg_northing = northing
self._cg_onimage = Keyword_Set(onimage)
self._cg_radians = Keyword_Set(radians)
self._cg_theDatums = Ptr_New(theDatums)
self._cg_theProjections = Ptr_New(projections)
self._cg_thisDatum = thisDatum
self._cg_thisProjection = this_map_projection
self._cg_title = title
self._cg_zone = zone
self._cg_overlays = Obj_New('cgContainer')
; Do you have a limit?
IF N_Elements(limit) NE 0 $
THEN self._cg_limit = Ptr_New(Double(limit)) $
ELSE self._cg_limit = Ptr_New(/ALLOCATE_HEAP)
; Get the map structure.
mapStruct = self -> SetMapProjection()
; Do you need to set the data ranges? If so, these should be set from
; the UV_BOX of the map structure.
IF N_Elements(xrange) EQ 0 THEN BEGIN
xrange = mapStruct.uv_box[[0,2]]
latlon_ranges = 0
ENDIF
IF N_Elements(yrange) EQ 0 THEN BEGIN
yrange = mapStruct.uv_box[[1,3]]
latlon_ranges = 0
ENDIF
; Are the ranges in lat/lon space?
IF Keyword_Set(latlon_ranges) THEN BEGIN
uvcoords = self -> Forward(xrange, yrange)
xrange = Reform(uvcoords[0,*])
yrange = Reform(uvcoords[1,*])
ENDIF
; Call the SUPERCLASS object INIT method.
ok = self -> cgCOORD::INIT ($
POSITION=position, $
XRANGE=xrange, $
YRANGE=yrange, $
XLOG=0, YLOG=0, $ ; No log axis on maps!
NAME=name, $
UVALUE=uvalue)
IF ~ok THEN RETURN, 0
; Do you need overlay objects in this map?
IF N_Elements(continents) NE 0 THEN BEGIN
; Is this a continental object? If so add it, if not
; create one and add it.
IF Obj_Valid(continents) THEN BEGIN
continents -> GetProperty, NAME=continentsName
IF continentsName EQ "" THEN continentsName = 'MAPCONTINENTS'
continents -> SetProperty, NAME=continentsName
self._cg_overlays -> Add, continents
ENDIF ELSE BEGIN
continents = Obj_New('cgMapContinents', self, /COUNTRIES, $
COLOR=cccolor, NAME='MAPCONTINENTS', HIRES=Keyword_Set(hires), $
FILL=Keyword_Set(fill), LAND_COLOR=land_color)
self._cg_overlays -> Add, continents
ENDELSE
ENDIF
IF N_Elements(grid) NE 0 THEN BEGIN
; Is this a grid object? If so add it, if not
; create one and add it.
IF Obj_Valid(grid) THEN BEGIN
grid -> GetProperty, NAME=gridName
IF gridName EQ "" THEN gridName = 'MAPGRID'
grid -> SetProperty, NAME=gridName
self._cg_overlays -> Add, grid
ENDIF ELSE BEGIN
grid = Obj_New('cgMapGrid', self, COLOR=gcolor, $
NAME='MAPGRID', BOX_AXES=box_axes, BCOLOR=bcolor, LCOLOR=lcolor)
self._cg_overlays -> Add, grid
ENDELSE
ENDIF
; Need to add this command to a resizeable cgWindow?
IF Keyword_Set(window) THEN self -> AddCmd, /REPLACE
IF Keyword_Set(addcmd) THEN self -> AddCmd
; Need immediate draw?
IF Keyword_Set(draw) THEN self -> Draw
RETURN, 1
END
;+--------------------------------------------------------------------------
; Adds the object as a command (the DRAW method is called) in a cgWindow
; resizeable graphics window. If there is no current cgWindow, one is
; created.
;
; :Keywords:
; method: in, optional, type='string', default='draw'
; The object method to add to the cgWindow.
; replace: in, optional, type=boolean, default=0
; If this keyword is set, object DRAW method replaces any commands in the
; current graphics window.
;---------------------------------------------------------------------------
PRO cgMap::AddCmd, REPLACE=replace, METHOD=method
IF N_Elements(method) EQ 0 THEN method = 'DRAW'
; Which method are we adding?
currentWindow = cgQuery(/CURRENT, COUNT=wincnt)
; Do we have a window to add it to?
IF wincnt EQ 0 THEN cgWindow
; Add (or replace) the command to the window.
IF Keyword_Set(replace) $
THEN cgWindow, method, self, /Method, /ReplaceCmd $ ; Replace all commands in the window
ELSE cgWindow, method, self, /Method, /AddCmd ; Add this command to the window.
END
;+--------------------------------------------------------------------------
; Adds the an overlay object into the overlay container of the object.
; Overlay objects are drawn (by calling their DRAW methods) after the
; map coordinate space is set up in the DRAW method of the object. They
; are drawn in the order they appear in the object.
;
; :Params:
; overlayObject: required, type=object
; The object that will draw a graphic overlay in the map projection space
; created by this map object. Typically, overlay objects contain map grid
; lines (cgMapGrid object), continental outlines (cgMapContinents object), or
; other types of graphical overlays. The only requirement of an overlay
; object is that is have a DRAW method and that it draw into a map
; projection space. This may be an object array.
;
;---------------------------------------------------------------------------
PRO cgMap::AddOverlay, overLayObject
; Required parameter must be a valid object with a DRAW method.
IF N_Elements(overLayObject) EQ 0 THEN $
Message, 'A map overlay object is a required parameter.'
IF ~Obj_Valid(overLayObject) THEN Message, 'A valid overlay object is required.'
IF Float(!Version.Release) GT 6.4 THEN BEGIN
hasMethod = Call_Function('Obj_HasMethod', overLayObject, 'DRAW')
IF ~hasMethod THEN Message, 'The overlay object must have a DRAW method.'
ENDIF
; Add the object to the overlay container.
FOR j=0,N_Elements(overlayObject)-1 DO BEGIN
self._cg_overlays -> Add, overLayObject
ENDFOR
END
;+--------------------------------------------------------------------------
; Advances the map projection position to the next position of a multiple
; plot (using !P.MULTI). Does not need to be called directly, as the object
; will call this method as needed.
;
; :Keywords:
; draw: in, optional, type=boolean, default=0
; Set this keyword to immediately call the draw method after the position
; has been advanced.
;---------------------------------------------------------------------------
PRO cgMap::Advance, DRAW=draw
IF Total(!P.Multi) NE 0 THEN BEGIN
; Draw the invisible plot to get plot position.
IF Size(self._cg_background, /TNAME) EQ 'STRING' $
THEN background = cgColor(self._cg_background)$
ELSE background = self._cg_background
TVLCT, rr, gg, bb, /Get
Plot, Findgen(11), XStyle=4, YStyle=4, /NoData;, Background=background
TVLCT, rr, gg, bb
; Use position coordinates to indicate position in this set of coordinates.
; New position based on !P.MULTI position.
position = [!x.window[0], !y.window[0], !x.window[1], !y.window[1]]
self._cg_multi_position = position
ENDIF ELSE self._cg_multi_position = FltArr(4)
IF Keyword_Set(draw) THEN self -> Draw
END
;+--------------------------------------------------------------------------
; This method sets up the map projection space of the object. Also, if map
; borders or titles are required, they are drawn here. If the object contains
; any overlay objects, they are also drawn at this time.
;
; :Keywords:
; erase: in, optional, type=boolean, default=0
; Set this keyword to erase contents of the map window for one time only
; in this Draw method. It does NOT set the Erase parameter for the object.
; nographics: in, optional, type=boolean, default=0
; If this keyword is set, no graphics are drawn, but the map data coordinate
; system is set up.
;
;---------------------------------------------------------------------------
PRO cgMap::Draw, ERASE=erase, NOGRAPHICS=nographics, _EXTRA=extra
Compile_Opt idl2
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /CANCEL
void = cgErrorMsg()
RETURN
ENDIF
displayGraphics = 1 - Keyword_Set(nographics)
; If this is a graphics device, and there is no current graphics window,
; then set the erase flag.
IF (!D.Name EQ 'WIN' || !D.Name EQ 'X') && (!D.Window LT 0) && displayGraphics THEN BEGIN
erase = 1
ENDIF
; Temporary erase?
IF N_Elements(erase) NE 0 THEN erase = Keyword_Set(erase)
; If you are doing multiple plots, then you have to update
; your position.
IF Total(!P.Multi) GT 0 THEN BEGIN
self -> Advance
position = self._cg_multi_position
old_position = self._cg_position
self -> SetProperty, POSITION=position
ENDIF
; Are you putting this on an image? If so, get the position from
; the last image position in.
IF self._cg_onimage THEN BEGIN
COMMON FSC_$CGIMAGE, _cgimage_xsize, _cgimage_ysize, $
_cgimage_winxsize, _cgimage_winysize, $
_cgimage_position, _cgimage_winID, $
_cgimage_current
old_position = self._cg_position
self -> SetProperty, POSITION=_cgimage_position
ENDIF
; Did you set the isotropic keyword:
IF self._cg_isotropic THEN BEGIN
self -> GetProperty, XRANGE=xr, YRANGE=yr
self._cg_aspect = Double(Abs(yr[1]-yr[0]))/Abs(xr[1]-xr[0])
ENDIF
; Do you need an aspect ratio?
IF (self._cg_aspect NE 0.0) AND (Total(!P.MULTI) LE 0) THEN BEGIN
position = self._cg_position
trial_position = cgAspect(self._cg_aspect, POSITION=position)
trial_width = trial_position[2]-trial_position[0]
trial_height = trial_position[3]-trial_position[1]
pos_width = position[2]-position[0]
pos_height = position[3]-position[1]
; Same logic as cgImage: try to fit image width, then if you can't get the right aspect
; ratio, fit the image height instead.
fit_ratio = pos_width / trial_width
IF trial_height * fit_ratio GT pos_height THEN $
fit_ratio = pos_height / trial_height
; new width and height
trial_width *= fit_ratio
trial_height *= fit_ratio
; calculate position vector based on trial_width and trial_height
position[0] += 0.5*(pos_width - trial_width)
position[2] -= 0.5*(pos_width - trial_width)
position[1] += 0.5*(pos_height - trial_height)
position[3] -= 0.5*(pos_height - trial_height)
ENDIF ELSE position = self._cg_position
; Do you need to erase in the background color? Don't do this if you
; are just drawing the coordinate system.
IF ~Keyword_Set(nographics) THEN BEGIN
IF N_Elements(erase) EQ 0 THEN erase = self._cg_erase
p = position
IF erase THEN cgColorFill, [p[0],p[0],p[2],p[2],p[0]], NORMAL=1, $
[p[1],p[3],p[3],p[1],p[1]], COLOR=self._cg_background
ENDIF
; Draw the map data coordinate system.
mapStruct = self -> SetMapProjection()
temp_position = self._cg_position
self._cg_position = position
self -> cgCoord::Draw, _EXTRA=extra
self._cg_position = temp_position
; Draw overlays?
count = self._cg_overlays -> Count()
IF (count GT 0) && displayGraphics THEN BEGIN
; Get the overlay objects out of the overlay container.
FOR j=0,count-1 DO BEGIN
thisOverlay = self._cg_overlays -> Get(POSITION=j)
IF Obj_Valid(thisOverlay) THEN thisOverlay -> Draw
ENDFOR
ENDIF
; Draw a border around the map?
IF ~Keyword_Set(self._cg_noborder) && displayGraphics THEN BEGIN
p = position
cgPlots, [p[0],p[0],p[2],p[2],p[0]], [p[1],p[3],p[3],p[1],p[1]], $
/NORMAL, COLOR=self._cg_color
ENDIF
; Draw a title?
IF (self._cg_title NE "") && displayGraphics THEN BEGIN
p = position
px = (p[2]-p[0])/2.0 + p[0]
py = (p[3] + 0.05) < 0.975
cgText, px, py, /Normal, Alignment=0.5, self._cg_title, Charsize=cgDefCharsize()*1.25
ENDIF
; If you changed the position for some reason, put it back.
IF N_Elements(old_position) NE 0 THEN self -> SetProperty, POSITION=old_position
END
;+--------------------------------------------------------------------------
; This method erases the graphics window.
;
; :Keywords:
; color: in, optional, type=string, default='white'
; The color used in the erasing of the display.
;
;---------------------------------------------------------------------------
PRO cgMap::Erase, COLOR=color
cgErase, COLOR=color
END
;+--------------------------------------------------------------------------
; This method transforms latitude and longitude values into projected
; XY Cartesian values. This is known as the forward map transformation.
;
; :Returns:
; The projected XY coordinates are returned in a 2xN array. The first
; column contains the projected X values and the second column contains
; the projected Y values.
;
; :Params:
; lons: in, required
; The longitude values to transform. May be a scalar or an array.
; lats: in, required
; The latitude values to transform. May be a scalar or an array.
; mapStruct: in, optional, type=structure
; The map structure to use in doing the forward transformation. If
; not provided, the map structure is obtained from the object itself.
;
; :Keywords:
; noforwardfix: in, optional, type=boolean, default=0
; I may be wrong about the fix I put in when the longitude values
; are the same. If so, setting this keyword will avoid the fix.
; The default value is the default for the object.
;
;---------------------------------------------------------------------------
FUNCTION cgMap::Forward, lons, lats, mapStruct, NOFORWARDFIX=noForwardFix
Compile_Opt idl2
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /CANCEL
void = cgErrorMsg()
RETURN, -1
ENDIF
IF N_Elements(lons) EQ 0 THEN Message, 'Longitude values are required.'
IF N_Elements(lats) EQ 0 THEN Message, 'Latitude values are required.'
IF N_Elements(noforwardfix) EQ 0 $
THEN noforwardfix = self._cg_noForwardFix $
ELSE noforwardfix = Keyword_Set(noforwardfix)
; Forward map transformation.
IF N_Elements(mapStruct) EQ 0 THEN mapStruct = self->GetMapStruct()
xycoords = Map_Proj_Forward(lons, lats, MAP_STRUCTURE=mapStruct)
; Check to see if longitude range values are identical. If so, then fix. This is, I believe,
; a bug in IDL code, but I can't get the IDL support engineers to believe it.
IF ~Keyword_Set(noforwardfix) THEN BEGIN
xr = Reform(xycoords[0,*])
n = N_Elements(xr)
IF (Floats_Equal(xr[0], xr[n-1], ULP=8)) && N_Elements(xr) GT 1 THEN BEGIN
IF xr[0] GT 0 THEN xycoords[0,0] = -xr[n-1] ELSE xycoords[0,n-1] = Abs(xr[0])
ENDIF
ENDIF
RETURN, xycoords
END
;+--------------------------------------------------------------------------
; This method returns a 1 if the map projection is a cylindrical projection
; and a 0 otherwise.
;
;---------------------------------------------------------------------------
FUNCTION cgMap::Is_Cylindrical
CASE (self._cg_thisProjection).index OF
100: retval = 1 ; Geographic
105: retval = 1 ; Mercator
109: retval = 1 ; Transvere Mercator
116: retval = 1 ; Sinusoidal
117: retval = 1 ; Equirectangular
118: retval = 1 ; Miller Cylindrical
121: retval = 1 ; Robinson
125: retval = 1 ; Mollweide
126: retval = 1 ; Interrupted Mollweide
127: retval = 1 ; Hammer-Aitoff
128: retval = 1 ; Wagner IV
129: retval = 1 ; Wagner VII
132: retval = 1 ; Cylindrical Equal Area
ELSE: retval = 0
ENDCASE
RETURN, retval
END
;+--------------------------------------------------------------------------
; This method returns a map structure that is the result of calling Map_Proj_Init.
; It is important to get a fresh map structure because up until IDL 8, the map
; structure was ephemeral (http://www.idlcoyote.com/map_tips/ephemeral.php).
; Every time this function is called, a new map structure is created.
;
;---------------------------------------------------------------------------
FUNCTION cgMap::GetMapStruct
RETURN, self -> SetMapProjection()
END
;+--------------------------------------------------------------------------
; This method allows the user to get various properties of the object. In general,
; the same keywords that are used for the INIT method can be used here. Here
; are a few that are different.
;
; :Keywords:
; boundary: out, optional, type=array
; A four-element array giving the boundaries of the image in the form
; [x0,y0,x1,y1]. This is a more convenient way of expressing the range
; of the map space.
; latlonbox: out, optional, type=array
; A four-element array giving the boundaries of the map projection in the
; Google Map form of [north, south, east, west]. This is useful when you
; are creating image overlays to be added to Google Earth.
; overlays: out, optional, type=object
; Set this keyword to a named variable that will return an object
; array containing the overlay objects in the map object.
;---------------------------------------------------------------------------
PRO cgMap::GetProperty, $
BACKGROUND=background, $
BCOLOR=bcolor, $
BOUNDARY=boundary, $
CENTER_LATITUDE=center_latitude, $
CENTER_LONGITUDE=center_longitude, $
COLOR=color, $
DATUM=datum, $
DRAW=draw, $
ELLIPSOID=ellipsoid, $
ERASE=erase, $
FALSE_EASTING=easting, $
FALSE_NORTHING=northing, $
HIRES=hires, $
LATLONBOX=latlonbox, $
LIMIT=limit, $
MAP_PROJECTION=map_projection, $
NAME=name, $
NOBORDER=noborder, $
NOFORWARDFIX=noforwardfix, $
ONIMAGE=onimage, $
OVERLAYS=overlays, $
POSITION=position, $
RADIANS=radians, $
SEMIMAJOR_AXIS=semimajor_axis, $
SEMIMINOR_AXIS=semiminor_axis, $
SPHERE_RADIUS=sphere_radius, $
TITLE=title, $
XRANGE=xrange, $
YRANGE=yrange, $
UVALUE=uvalue, $
ZONE=zone, $
_REF_EXTRA=extraKeywords
Compile_Opt idl2
Catch, theError
IF theError NE 0 THEN BEGIN