Re: NCL library for creating Google Earth kml and kmz files

From: Ryan Pavlick <ryan.pavlick_at_nyahnyahspammersnyahnyah>
Date: Fri Sep 17 2010 - 06:46:07 MDT

Thanks again, Álvaro. I've incorporated your code and put the updates
online. It certainly makes the code cleaner.

For everyone else:
To see some nice examples of how others are using KML and Google Earth for
scientific visualization and public outreach, there is a nice gallery at:

http://earth.google.com/outreach/showcase.html

I've put output from the kml.ncl application examples online as well:

http://rpavlick.github.com/kmlncl/ex01.html
http://rpavlick.github.com/kmlncl/ex02.html
http://rpavlick.github.com/kmlncl/ex03.html
http://rpavlick.github.com/kmlncl/ex04.html
http://rpavlick.github.com/kmlncl/ex05.html
http://github.com/rpavlick/kmlncl

Cheers,
Ryan

On Wed, Sep 15, 2010 at 6:18 PM, "Álvaro M. Valdebenito B." <
alvaro.valdebenito@met.no> wrote:

> Thanks for the acknowledgement.
>
> I added a new procedure: kml_setline_idtag
> it handles:
> <TAG id=res@ID> or <TAG>
> it might also add single tags (if resource single_tags is found):
> <single_tag> res@single_tag </single_tag>
> and close the tag (if resource is set close_tag):
> </TAG>
>
> Cheers,
> Á.
>
>
> Ryan Pavlick wrote:
>
>> Thanks, Álvaro.
>>
>> I've added all of your recommendations to my TODO list and will
>> acknowledge you in the list of contributors.
>>
>> I've also had many problems with convert and transparency.
>>
>> For instance, I'd like to be able make the oceans or land transparent
>> in kml_plot_groundoverlay. Unfortunately, Google Earth requires that
>> the specified latitude and longitude boundaries correspond with the
>> extent of the non-transparent pixels. Which turned out to be very
>> tricky to code, so I've put it off for now.
>>
>> Cheers,
>> Ryan
>>
>> On Wed, Sep 15, 2010 at 3:54 PM, "Álvaro M. Valdebenito B."
>> <alvaro.valdebenito@met.no> wrote:
>>
>>> Dear Ryan,
>>>
>>> thanks for your efforts creating the kml/kmz library.
>>>
>>> I noticed that the labelbar prodiced by kml_add_labelbar
>>> calls to drawNDCGrid (line 757),
>>> so the labelbar.png has a the placement grid also.
>>>
>>> I would also suggest the addition of transparency to the convert call on
>>> kml_add_labelbar, but my experiment with "convert -transparent white
>>> ..." failed to produce good results.
>>>
>>> I also noticed many lines as the following:
>>> if (isatt(res,"kmlRefreshMode")) then
>>> kml_entry = "<refreshMode>"+res@kmlRefreshMode+"</refreshMode>"
>>> kml_setline(kml,kml_entry)
>>> delete(kml_entry)
>>> end if
>>> and
>>> if (isatt(res,"kmlOverlayXY")) then
>>> if (res@kmlOverlayXY)
>>> kml_entry = "<overlayXY x="+kml@quote+res@kmlOverlayXYx+kml@quote+"
>>> y="+kml@quote+res@kmlOverlayXYy+kml@quote+"
>>> xunits="+kml@quote+res@kmlOverlayXYxunits+kml@quote+"
>>> yunits="+kml@quote+res@kmlOverlayXYyunits+kml@quote+"/>"
>>> kml_setline(kml,kml_entry)
>>> delete(kml_entry)
>>> end if
>>> end if
>>>
>>> I understand that the keeping the kml output and ncl code as close as
>>> possible is a design decision. Nevertheless, I would like to suggest the
>>> introduction of two specialized procedures to remove the repetitive
>>> code, which is prone to typos, as follows:
>>>
>>> procedure
>>> kml_setline_singletag(kml:string,kml_tags[*]:string,res[1]:logical)
>>> local kml_entry, atts, i
>>> begin
>>> ; add "single tag" lines to kml file
>>>
>>> atts="kml"+str_capital(kml_tags)
>>> do i=0,dimsizes(kml_tags)-1
>>> if (isatt(res,atts(i)).and.dimsizes(res@$atts(i)$).eq.1) then
>>> kml_entry = "<"+kml_tags(i)+">"+res@$atts(i)$+"</"+kml_tags(i)+">"
>>> kml_setline(kml,kml_entry)
>>> end if
>>> end do
>>> end
>>>
>>> and
>>>
>>> undef("kml_setline_xytag")
>>> procedure kml_setline_xytag(kml:string,kml_tags[*]:string,res[1]:logical)
>>> local kml_entry, atts, i, tagsXY, attsXY, j
>>> begin
>>> ; add "XY tag" lines to kml file
>>>
>>> tagsXY=(/"x","y","xunits","yunits"/)
>>> atts="kml"+str_capital(kml_tags)
>>> do i=0,dimsizes(kml_tags)-1
>>> attsXY=atts(i)+tagsXY
>>> if (isatt(res,atts(i)).and.dimsizes(res@$atts(i)$).eq.1.and.\
>>> typeof(res@$atts(i)$).eq."logical".and.res@$atts(i)$.and.\
>>> all(isatt(res,attsXY))) then
>>> do j=0,dimsizes(attsXY)-1
>>> attsXY(j)=kml@quote+res@$attsXY(j)$+kml@quote
>>> end do
>>> kml_entry="<"+kml_tags(i)+" "+str_join(tagsXY+"="+attsXY," ")+"/>"
>>> kml_setline(kml,kml_entry)
>>> end if
>>> end do
>>> end
>>>
>>> Then, lines 101-141 will be reduced to
>>> kml_tags=(/"refreshMode","refreshInterval",
>>> "viewRefreshMode","viewRefreshTime",\
>>> "viewBoundScale","viewFormat","httpQuery"/)
>>> kml_setline_singletag(kml,kml_tags,res)
>>> delete(kml_tags)
>>>
>>> Then, lines 589-619 will be reduced to
>>> kml_tags = (/"overlayXY","screenXY","rotationXY","sizeXY"/)
>>> kml_setline_xytag(kml,kml_tags,res)
>>> delete(kml_tags)
>>>
>>> Best wishes,
>>> Álvaro.
>>>
>>> ncl-talk-request@ucar.edu wrote:
>>>
>>>> Message: 3
>>>> Date: Tue, 14 Sep 2010 00:22:44 +0200
>>>> From: Ryan Pavlick <ryan.pavlick@gmail.com>
>>>> Subject: NCL library for creating Google Earth kml and kmz
>>>> files
>>>> To: ncl-talk@ucar.edu
>>>> Message-ID:
>>>> <AANLkTi=6SEn5ZKGiFd8bNpZ6S8yyBqMyfp2-i4sTp4K9@mail.gmail.com>
>>>> Content-Type: text/plain; charset=ISO-8859-1
>>>>
>>>> NCLers,
>>>>
>>>> I am developing an NCL library for creating kml/kmz files to visualize
>>>> geographic data in Earth browsers (e.g. Google Earth).
>>>>
>>>> You can see my progress so far along with several example scripts and
>>>> output files at: http://github.com/rpavlick/kmlncl
>>>>
>>>> This is very much an alpha release. It has plenty of bugs and limited
>>>> documentation. Nor is it feature complete.
>>>>
>>>> Most KML elements are basically working though (Document, Folder,
>>>> Placemark, Point, LineString, Polygon, GroundOverlay, ScreenOverlay,
>>>> PhotoOverlay, NetworkLink, LookAt, Camera, some Style elements).
>>>>
>>>> If you find bugs or have feature ideas, just respond to this thread in
>>>> ncl-talk (I hope this is ok with the admins). There is also an issue
>>>> tracker on the github project page. Although, I make no promises
>>>> about speedy responses, this is a spare-time project.
>>>>
>>>> Cheers,
>>>> Ryan
>>>>
>>>> --
>>> Álvaro M. Valdebenito B., Dr. rer. nat. alvaro.valdebenito@met.no
>>> Air Pollution Section/Research Department Tel. +47-2296 3397
>>> Norwegian Meteorological Institute http:\\www.met.no
>>> P.O. Box 43 Blindern, 0313 Oslo, NORWAY http:\\www.emep.int/CWF
>>> _______________________________________________
>>> ncl-talk mailing list
>>> List instructions, subscriber options, unsubscribe:
>>> http://mailman.ucar.edu/mailman/listinfo/ncl-talk
>>>
>>>
>>
>>
>>
> --
> Álvaro M. Valdebenito B., Dr. rer. nat. alvaro.valdebenito@met.no
> Air Pollution Section/Research Department Tel. +47-2296 3397
> Norwegian Meteorological Institute http:\\www.met.no
> P.O. Box 43 Blindern, 0313 Oslo, NORWAY http:\\www.emep.int/CWF
>
> ; Copyright (c) 2010, Ryan Pavlick (http://github.com/rpavlick)
> ;
> ; Permission is hereby granted, free of charge, to any person obtaining a
> copy
> ; of this software and associated documentation files (the "Software"), to
> deal
> ; in the Software without restriction, including without limitation the
> rights
> ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> ; copies of the Software, and to permit persons to whom the Software is
> ; furnished to do so, subject to the following conditions:
> ;
> ; The above copyright notice and this permission notice shall be included
> in
> ; all copies or substantial portions of the Software.
> ;
> ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> OR
> ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> THE
> ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> ; THE SOFTWARE.
> ; *************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_setline")
> procedure kml_setline(kml:string,kml_entry:string)
> local kml_entry, nkml_entry
> begin
> ; add lines to kml file
>
> nkml_entry = dimsizes(kml_entry)
> if(kml@nline+nkml_entry-1.ge.dimsizes(kml))
> print("kml_setline: bad index, not setting anything.")
> return
> end if
> kml(kml@nline:kml@nline+nkml_entry-1) = kml_entry
> kml@nline = kml@nline + nkml_entry
> kml@_FillValue = ""
>
> return
> end
> ;**************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_setline_singletag")
> procedure
> kml_setline_singletag(kml:string,kml_tags[*]:string,res[1]:logical)
> local kml_entry, atts, i
> begin
> ; add multiple "single tag" lines to kml file
> ; e.g. <kml_tags> res@kml$kml_tags$ </kml_tags>
>
> atts="kml"+str_capital(kml_tags)
> do i=0,dimsizes(kml_tags)-1
> if (isatt(res,atts(i)).and.dimsizes(res@$atts(i)$).eq.1) then
> kml_entry = "<"+kml_tags(i)+">"+res@$atts(i)$+"</"+kml_tags(i)+">"
> kml_setline(kml,kml_entry)
> end if
> end do
>
> return
> end
> ;**************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_setline_xytag")
> procedure kml_setline_xytag(kml:string,kml_tags[*]:string,res[1]:logical)
> local kml_entry, atts, i, tagsXY, attsXY, j
> begin
> ; add multiple "XY tag" lines to kml file
> ; e.g. <kml_tags x="res@kml$kml_tags+"x"$" xunits="res@kml
> $kml_tags+"xunits"$"
> ; y="res@kml$kml_tags+"y"$" yunits="res@kml$kml_tags+"yunits"$"
> </>
>
> tagsXY=(/"x","y","xunits","yunits"/)
> atts="kml"+str_capital(kml_tags)
> do i=0,dimsizes(kml_tags)-1
> attsXY=atts(i)+tagsXY
> if (isatt(res,atts(i)).and.dimsizes(res@$atts(i)$).eq.1.and.\
> typeof(res@$atts(i)$).eq."logical".and.res@$atts(i)$.and.\
> all(isatt(res,attsXY))) then
> do j=0,dimsizes(attsXY)-1
> attsXY(j)=kml@quote+res@$attsXY(j)$+kml@quote
> end do
> kml_entry = "<"+kml_tags(i)+" "+str_join(tagsXY+"="+attsXY," ")+"/>"
> kml_setline(kml,kml_entry)
> end if
> end do
>
> return
> end
> ;**************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_setline_idtag")
> procedure kml_setline_idtag(kml:string,kml_tags[1]:string,res[1]:logical)
> local kml_entry, atts, i
> begin
> ; add one "id" line to kml file
> ; e.g. <kml_tags id="res@kmlID"> or <kml_tags>
> ; add multiple "single tag" lines if kml_tags@single_tags
> ; e.g. <kml_tags@single_tags> res@kml$kml_tags@single_tags$
> </kml_tags@single_tags>
> ; add one "close" line if if kml_tags@close_tag
> ; e.g. </kml_tags>
>
> if (isatt(res,"kmlID")) then
> kml_entry = "<"+kml_tags+" id="+kml@quote+res@kmlID+kml@quote+">"
> else
> kml_entry = "<"+kml_tags+">"
> end if
> kml_setline(kml,kml_entry)
>
> if (isatt(res,"single_tags")) then
> kml_setline_singletag(kml,kml_tags@single_tags,res)
> end if
>
> if (isatt(kml_tags,"close_tag").and.dimsizes(kml_tags@close_tag
> ).eq.1.and.\
> typeof(kml_tags@close_tag).eq."logical".and.kml_tags@close_tag) then
> kml_entry = "<"+kml_tags+">"
> kml_setline(kml,kml_entry)
> end if
>
> return
> end
> ;**************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_altitudeMode_attr")
> function kml_altitudeMode_attr ( kml:string, res:logical )
> local kml, kml_entry, res, altmode
> begin
>
> altmode = get_res_value_keep(res, "kmlAltitudeMode", "relativeToGround")
>
> kml_entry = "<altitudeMode>"+altmode+"</altitudeMode>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_icon_attr")
> function kml_icon_attr ( kml:string, icon:string, ires:logical )
> local kml_entry, res
> begin
>
> ; <Icon id="ID">
> ; <!-- specific to Icon -->
> ; <href>...</href> <!-- anyURI -->
> ; <gx:x>0<gx:x/> <!-- int -->
> ; <gx:y>0<gx:y/> <!-- int -->
> ; <gx:w>...<gx:w/> <!-- int -->
> ; <gx:h>...<gx:h/> <!-- int -->
> ; <refreshMode>onChange</refreshMode>
> ; <!-- kml:refreshModeEnum: onChange, onInterval, or onExpire -->
> ; <refreshInterval>4</refreshInterval> <!-- float -->
> ; <viewRefreshMode>never</viewRefreshMode>
> ; <!-- kml:viewRefreshModeEnum: never, onStop, onRequest, onRegion -->
> ; <viewRefreshTime>4</viewRefreshTime> <!-- float -->
> ; <viewBoundScale>1</viewBoundScale> <!-- float -->
> ; <viewFormat>...</viewFormat> <!-- string -->
> ; <httpQuery>...</httpQuery> <!-- string -->
> ; </Icon>
>
> kml_entry = "Icon"
> kml_entry@single_tags=(/"href","refreshMode","refreshInterval",\
>
> "viewRefreshMode","viewRefreshTime","viewBoundScale","viewFormat",\
> "httpQuery"/)
> kml_entry@close_tag=True
> res=ires
> res@kmlHref=icon
> kml_setline_idtag(kml,kml_entry,res)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_overlay_attr")
> function kml_overlay_attr ( kml:string, icon:string, res:logical )
> local kml_entry
> begin
>
> ;
> ; <!-- inherited from Overlay element -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <drawOrder>0</drawOrder> <!-- int -->
> ; <Icon>...</Icon>
>
> kml_tags=(/"color","drawOrder"/)
> kml_setline_singletag(kml,kml_tags,res)
> delete(kml_tags)
>
> kml = kml_icon_attr(kml,icon,res)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_link_attr")
> function kml_link_attr ( kml:string, href:string, ires:logical )
> local kml_entry, res
> begin
>
> ; <Link id="ID">
> ; <!-- specific to Link -->
> ; <href>...</href> <!-- string -->
> ; <refreshMode>onChange</refreshMode>
> ; <!-- refreshModeEnum: onChange, onInterval, or onExpire -->
> ; <refreshInterval>4</refreshInterval> <!-- float -->
> ; <viewRefreshMode>never</viewRefreshMode>
> ; <!-- viewRefreshModeEnum: never, onStop, onRequest, onRegion -->
> ; <viewRefreshTime>4</viewRefreshTime> <!-- float -->
> ; <viewBoundScale>1</viewBoundScale> <!-- float -->
> ;
> <viewFormat>BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]</viewFormat>
> ; <!-- string -->
> ; <httpQuery>...</httpQuery> <!-- string -->
> ; </Link>
>
>
> kml_entry = "Link"
> kml_entry@single_tags=(/"href","refreshMode","refreshInterval",\
>
> "viewRefreshMode","viewRefreshTime","viewBoundScale","viewFormat",\
> "httpQuery"/)
> kml_entry@close_tag=True
> res=ires
> res@kmlHref=href
> kml_setline_idtag(kml,kml_entry,res)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_feature_attr")
> function kml_feature_attr ( kml:string, name:string, ires:logical )
> local kml_entry, res
> begin
>
> ; <!-- abstract element; do not create -->
> ; <!-- Feature id="ID" --> <!-- Document,Folder,
> ; NetworkLink,Placemark,
> ;
> GroundOverlay,PhotoOverlay,ScreenOverlay -->
> ; <name>...</name> <!-- string -->
> ; <visibility>1</visibility> <!-- boolean -->
> ; <open>0</open> <!-- boolean -->
> ; <atom:author>...<atom:author> <!-- xmlns:atom -->
> ; <atom:link href=" "/> <!-- xmlns:atom -->
> ; <address>...</address> <!-- string -->
> ; <xal:AddressDetails>...</xal:AddressDetails> <!-- xmlns:xal -->
> ; <phoneNumber>...</phoneNumber> <!-- string -->
> ; <Snippet maxLines="2">...</Snippet> <!-- string -->
> ; <description>...</description> <!-- string -->
> ; <AbstractView>...</AbstractView> <!-- Camera or LookAt -->
> ; <TimePrimitive>...</TimePrimitive> <!-- TimeStamp or TimeSpan -->
> ; <styleUrl>...</styleUrl> <!-- anyURI -->
> ; <StyleSelector>...</StyleSelector>
> ; <Region>...</Region>
> ; <Metadata>...</Metadata> <!-- deprecated in KML 2.2 -->
> ; <ExtendedData>...</ExtendedData> <!-- new in KML 2.2 -->
> ; <-- /Feature -->
>
>
> ; inherits all Feature elements
> res=ires
> res@kmlNmame=name
> kml_entry=(/"name","visibility","open"/)
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> if (isatt(res,"kmlAtomAuthor")) then
> kml_entry = "<atom:author>"+res@kmlAtomAuthor+"</atom:author>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
>
> if (isatt(res,"kmlAtomLink")) then
> kml_entry = "<atom:link href=" + kml@quote + res@kmlAtomLink +
> kml@quote + "/>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
>
> kml_entry=(/"adderss","Snippet","description"/)
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> ;
> ; <TimeSpan id="ID">
> ; <begin>...</begin> <!-- yyyy-mm-ddThh:mm:sszzzzzz -->
> ; <end>...</end> <!-- yyyy-mm-ddThh:mm:sszzzzzz-->
> ; </TimeSpan>
>
> ; <TimeStamp id=ID>
> ; <when>...</when> <!-- kml:dateTime -->
> ; </TimeStamp>
>
> ; TODO error check here
>
> if (isatt(res,"kmlTimeSpanBegin")) then
> kml_entry = (/ \
> "<TimeSpan>", \
> "<begin>"+res@kmlTimeSpanBegin+"</begin>", \
> "<end>"+res@kmlTimeSpanEnd+"</end>", \
> "</TimeSpan>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> else
> if (isatt(res,"kmlTimeStamp")) then
> kml_entry = (/ \
> "<TimeStamp>", \
> "<when>"+res@kmlTimeStamp+"</when>", \
> "</TimeStamp>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
> end if
>
> kml_entry=(/"styleUrl"/)
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_get_vp_crop")
> function kml_get_vp_crop ( wks:graphic,plot:graphic )
> local plot, slop, crop, dc, vp, lb
> begin
>
> ; Based on thread "Re: No-frills contour plot" on ncl-talk
>
> ; find the location on the page of the normalized
> ; device coordinate space (NDC), using the workstation resources
>
> dc = new(4,float)
> getvalues wks
> "wkDeviceLowerX" : dc(0)
> "wkDeviceLowerY" : dc(1)
> "wkDeviceUpperX" : dc(2)
> "wkDeviceUpperY" : dc(3)
> end getvalues
>
> ; location of the "map" within NDC space
> ; is obtained from the plot resources
>
> vp = new(4,float)
> getvalues plot
> "vpXF" : vp(0)
> "vpYF" : vp(1)
> "vpWidthF" : vp(2)
> "vpHeightF" : vp(3)
> end getvalues
> print(vp)
>
> ; calculate the *location on the
> ; page* of the map portion of the plot:
>
> crop = new(4,float)
> crop(0) = vp(2) * (dc(2) - dc(0))
> crop(1) = vp(3) * (dc(3) - dc(1))
> crop(2) = dc(0) + vp(0) * (dc(2) - dc(0))
> crop(3) = dc(1) + (vp(1) - vp(3)) * (dc(3) - dc(1))
> crop = floor(crop)
> ; postscript page-coordinates
> ; "convert -crop 0x1+2+3"
>
> ; does not work with gsnMaximize=True
>
> return(crop)
> end
>
> ;************************************************************
> ; comments
>
> undef("kml_get_vp_latlonbox")
> function kml_get_vp_latlonbox ( plot:graphic )
> local plot, xf, yf, width, height, xNDC, yNDC, xWorld, yWorld, slop,
> LatLonBox
> begin
>
> mp = new(4,float)
> getvalues plot
> "mpMaxLonF" : mp(3)
> "mpMinLonF" : mp(2)
> "mpMaxLatF" : mp(0)
> "mpMinLatF" : mp(1)
> end getvalues
>
> LatLonBox = new(4,float)
> LatLonBox = (/ mp(0), mp(1), mp(2), mp(3) /)
>
> return(LatLonBox)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_add_groundoverlay")
> function kml_add_groundoverlay ( kml:string, name:string, icon:string,
> LatLonBox[4]:float, z[1]:float, res:logical )
> local kml, kml_entry, res, icon, name, rotation, LatLonBox
> begin
>
> ; <GroundOverlay id="ID">
>
> kml_entry = "GroundOverlay"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> ; <!-- inherits all Feature elements -->
>
> kml = kml_feature_attr(kml, name, res)
> ;
> ; <!-- inherited from Overlay element -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <drawOrder>0</drawOrder> <!-- int -->
> ; <Icon>...</Icon>
>
> kml = kml_overlay_attr(kml, icon, res)
> ;
> ; <!-- specific to GroundOverlay -->
> ; <altitude>0</altitude> <!-- double -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround or absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor or
> relativeToSeaFloor --
>
>
> kml_entry = "<altitude>"+z+"</altitude>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> ; <LatLonBox>
> ; <north>...</north> <! kml:angle90 -->
> ; <south>...</south> <! kml:angle90 -->
> ; <east>...</east> <! kml:angle180 -->
> ; <west>...</west> <! kml:angle180 -->
> ; <rotation>0</rotation> <! kml:angle180 -->
> ; </LatLonBox>
> ; <gx:LatLonQuad>
> ; <coordinates>...</coordinates> <!-- four lon,lat tuples
> -->
> ; </gx:LatLonQuad>
>
> rotation = get_res_value_keep(res,"kmlRotation",0)
>
> kml_entry = (/ \
> "<LatLonBox>", \
> " <north>"+LatLonBox(0)+"</north>", \
> " <south>"+LatLonBox(1)+"</south>", \
> " <east>"+LatLonBox(2)+"</east>", \
> " <west>"+LatLonBox(3)+"</west>", \
> " <rotation>"+rotation+"</rotation>", \
> "</LatLonBox>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
>
> ; </GroundOverlay>
> kml_entry = "</GroundOverlay>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_add_screenoverlay")
> function kml_add_screenoverlay ( kml:string, name:string, icon:string,
> res:logical )
> local kml, kml_entry, res, plot_name, plot_file, icon, name
> begin
>
> ; <ScreenOverlay id="ID">
>
> kml_entry = "ScreenOverlay"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> ; <!-- inherits all Feature elements -->
>
> kml = kml_feature_attr(kml, name, res)
> ;
> ; <!-- inherited from Overlay element -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <drawOrder>0</drawOrder> <!-- int -->
> ; <Icon>...</Icon>
>
> kml = kml_overlay_attr(kml, icon, res)
>
> ; <!-- specific to ScreenOverlay -->
> ; <overlayXY x="double" y="double" xunits="fraction" yunits="fraction"/>
> ; <!-- vec2 -->
> ; <!-- xunits and yunits can be one of: fraction, pixels, or
> insetPixels -->
> ; <screenXY x="double" y="double" xunits="fraction" yunits="fraction"/>
> ; <!-- vec2 -->
> ; <rotationXY x="double" y="double" xunits="fraction" yunits"fraction"/>
> ; <!-- vec2 -->
> ; <size x="double" y="double" xunits="fraction" yunits="fraction"/>
> ; <!-- vec2 -->
> ; <rotation>0</rotation> <!-- float -->
> ; </ScreenOverlay>
> ;
>
> ;TODO: error checking
>
> kml_entry = (/"overlayXY","screenXY","rotationXY","sizeXY"/)
> kml_setline_xytag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml_entry="rotation"
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml_entry = "</ScreenOverlay>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_open_doc")
> function kml_open_doc(filename:string, name:string,res:logical)
> local kml, kml_entry, name, maxlines,res, filename
> begin
> ; create new string array to contain kml
>
> ; <Document id="ID">
> ; <!-- inherits all Feature elements -->
> ;
> ; <!-- specific to Document -->
> ; <!-- 0 or more Schema elements -->
> ; <!-- 0 or more Feature elements -->
> ; </Document>
>
> if (isatt(res,"maxlines")) then
> maxlines = res@maxlines
> else
> maxlines = 100000
> end if
>
> kml = new((/maxlines/),"string")
> kml@_FillValue = " "
> kml@nline = 0
> kml@filename = filename
> kml@files = " "
>
> kml@quote = str_get_dq()
>
> kml_entry = (/ \
> "<?xml version=" + kml@quote + "1.0" + kml@quote + " encoding=" +
> kml@quote + "UTF-8" + kml@quote + "?>", \
> "<kml xmlns=" + kml_at_quote + "http://www.opengis.net/kml/2.2" + kml_at_quote+ ">" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml_entry = "Document"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_feature_attr(kml, name, res)
>
> return (kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_add_labelbar")
> function kml_add_labelbar (kml:string, name:string,
> wks:graphic,plot:graphic, res:logical)
> local kml, name, wks, plot, res, cmap, levels, colors, font_height, \
> labels, lbres, lbplot_name, lbplot_file, lbicon, lbwks, lbplot, \
> crop, files
> begin
>
> ;
> ; Get some resource values and use these to create a labelbar.
>
> getvalues wks
> "wkColorMap" : cmap
> end getvalues
>
> getvalues plot@contour
> "cnLevels" : levels
> "cnFillColors" : colors
> "cnInfoLabelFontHeightF" : font_height
> end getvalues
>
> labels = "" + levels ; Convert levels to a string array. This is
> ; not necessary, but it gets rid of the
> ; annoying error message about coercing
> types.
>
> lbres = True ; Set up a resource list for the
> labelbar.
> lbres@vpWidthF = 0.1
> lbres@vpHeightF = 0.8
>
> lbres@lbBoxLinesOn = False
> lbres@lbFillColors = colors
> lbres@lbMonoFillPattern = True
>
> lbres@lbOrientation = "Vertical"
> lbres@lbPerimOn = False
>
> lbres@lbLabelFontHeightF = font_height
> lbres@lbLabelAutoStride = True
>
> lbplot_name = wks@name + "_lb"
> lbplot_file = lbplot_name + ".ps"
> lbicon = lbplot_name + ".png"
>
> lbwks = gsn_open_wks("ps",lbplot_name)
> gsn_define_colormap(lbwks,cmap)
>
> lbid = gsn_create_labelbar(lbwks,dimsizes(levels)+1,labels,lbres)
>
> lbplot = create "lbplot" mapPlotClass lbwks
> ; "vpXF" : 0.0
> ; "vpYF" : 1.0
> ; "vpWidthF" : 0.8
> ; "vpHeightF" : 0.1
> "mpOutlineOn" : False
> "mpPerimOn" : False
> "mpGridAndLimbOn" : False
> "tmXBBorderOn" : False
> "tmXTBorderOn" : False
> "tmYRBorderOn" : False
> "tmYLBorderOn" : False
> "tmXBOn" : False
> "tmXTOn" : False
> "tmYROn" : False
> "tmYLOn" : False
> end create
>
> annoid = gsn_add_annotation(lbplot,lbid,False)
> draw(lbplot)
> ; drawNDCGrid(lbwks)
> frame(lbwks)
>
> crop = kml_get_vp_crop(lbwks,lbid)
>
> convert = "convert +repage -crop
> "+crop(0)+"x"+crop(1)+"+"+crop(2)+"+"+crop(3)+" "+lbplot_file+" "+lbicon
> ;convert = str_sub_str(convert,"convert","convert -transparent white")
> print(convert)
> system(convert)
>
> files = kml@files
> kml@files = files + " " + lbicon
>
> kml = kml_add_screenoverlay(kml, name, lbicon, res)
>
> return(kml)
> end
>
>
>
> ;************************************************************
> ; comments
>
> undef("kml_map_defaults")
> procedure kml_map_defaults ( res:logical )
> begin
>
> res@mpOutlineOn = False
> res@mpPerimOn = False
> res@mpGridAndLimbOn = False
> res@tmXBBorderOn = False
> res@tmXTBorderOn = False
> res@tmYRBorderOn = False
> res@tmYLBorderOn = False
> res@tmXBOn = False
> res@tmXTOn = False
> res@tmYROn = False
> res@tmYLOn = False
> res@gsnMaximize = False
> res@gsnDraw = False
> res@gsnFrame = False
>
> end ;kml_map_defaults
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_close_doc")
> function kml_close_doc ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = "</Document>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml_entry = "</kml>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_write")
> procedure kml_write ( kml:string )
> local kml, kml_file
> begin
>
> kml_file = kml@filename+".kml"
> asciiwrite(kml_file,kml(0:kml@nline))
>
> end ;kml_write
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_make_kmz")
> procedure kml_make_kmz ( kml:string )
> local kml, kml_file, kmz_file
> begin
>
> kml_file = kml@filename+".kml"
> kmz_file = kml@filename+".kmz"
> system("zip " + kmz_file + " " + kml_file + " " + kml@files)
>
> end
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_open_folder")
> function kml_open_folder ( kml:string, name:string, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <Folder id="ID">
> ; <!-- inherits all Feature elements -->
> ;
> ; <!-- specific to Folder -->
> ; <!-- 0 or more Feature elements -->
> ; </Folder>
>
> kml_entry = "Folder"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_feature_attr(kml, name, res)
>
> return(kml)
> end ;kml_open_folder
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_close_folder")
> function kml_close_folder ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = "</Folder>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> undef("kml_add_networklink")
> function kml_add_networklink ( kml:string, name:string, link:string,
> res:logical )
> local kml, kml_entry, res
> begin
>
> ; <NetworkLink id="ID">
> ; <!-- inherits all Feature elements --><name>...</name>
> <!-- string -->
> ;
> ; <!-- specific to NetworkLink -->
> ; <refreshVisibility>0</refreshVisibility> <!-- boolean -->
> ; <flyToView>0</flyToView> <!-- boolean -->
> ; <Link>...</Link>
> ; </NetworkLink>
>
> kml_entry = "NetworkLink"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_feature_attr(kml, name, res)
>
> kml_entry=(/"refreshVisibility","flyToView"/)
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_link_attr(kml, link, res)
>
> kml_entry = "</NetworkLink>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_open_style")
> function kml_open_style ( kml:string, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <Style id="ID">
> ; <!-- extends StyleSelector -->
> ;
> ; <!-- specific to Style -->
> ; <IconStyle>...</IconStyle>
> ; <LabelStyle>...</LabelStyle>
> ; <LineStyle>...</LineStyle>
> ; <PolyStyle>...</PolyStyle>
> ; <BalloonStyle>...</BalloonStyle>
> ; <ListStyle>...</ListStyle>
> ; </Style>
>
> kml_entry = "Style"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_open_stylemap")
> function kml_open_stylemap ( kml:string, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <StyleMap id="ID">
> ; <!-- extends StyleSelector -->
> ; <!-- elements specific to StyleMap -->
> ; <Pair id="ID">
> ; <key>normal</key> <!-- kml:styleStateEnum: normal or
> highlight -->
> ; <styleUrl>...</styleUrl>
> ; </Pair>
> ; </StyleMap>
>
> kml_entry = "StyleMap"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_polystyle")
> function kml_add_polystyle ( kml:string, res:logical )
> local kml_entry
> begin
>
> ; <PolyStyle id="ID">
> ; <!-- inherited from ColorStyle -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <colorMode>normal</colorMode> <!-- kml:colorModeEnum: normal or
> random -->
> ;
> ; <!-- specific to PolyStyle -->
> ; <fill>1</fill> <!-- boolean -->
> ; <outline>1</outline> <!-- boolean -->
> ; </PolyStyle>
>
> kml_entry = "PolyStyle"
> kml_entry@single_tags=(/"color","colorMode","fill","outline"/)
> kml_entry@close_tag=True
> kml_setline_idtag(kml,kml_entry,res)
>
> return(kml)
> end ;kml_add_polystyle
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_iconstyle")
> function kml_add_iconstyle ( kml:string, icon:string, res:logical )
> local kml_entry
> begin
>
> ; <IconStyle id="ID">
> ; <!-- inherited from ColorStyle -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <colorMode>normal</colorMode> <!-- kml:colorModeEnum:normal or
> random -->
> ;
> ; <!-- specific to IconStyle -->
> ; <scale>1</scale> <!-- float -->
> ; <heading>0</heading> <!-- float -->
> ; <Icon>
> ; <href>...</href>
> ; </Icon>
> ; <hotSpot x="0.5" y="0.5"
> ; xunits="fraction" yunits="fraction"/> <!-- kml:vec2 -->
> ; </IconStyle>
>
> kml_entry = "IconStyle"
> kml_entry@single_tags=(/"color","colorMode","scale","heading"/)
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_icon_attr(kml, icon, res)
>
> if (isatt(res,"kmlHotSpot")) then
> if (res@kmlHotSpot)
> kml_entry = "<overlayXY x="+kml@quote+res@kmlHotSpotx+kml@quote+"
> y="+kml@quote+res@kmlHotSpoty+kml@quote+" xunits="+kml@quote
> +res@kmlHotSpotxunits+kml@quote+" yunits="+kml@quote+res@kmlHotSpotyunits
> +kml@quote+"/>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
> end if
>
> kml_entry = "</IconStyle>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_add_iconstyle
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_linestyle")
> function kml_add_linestyle ( kml:string, res:logical )
> local kml_entry
> begin
>
> ; <LineStyle id="ID">
> ; <!-- inherited from ColorStyle -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <colorMode>normal</colorMode> <!-- colorModeEnum: normal or
> random -->
> ;
> ; <!-- specific to LineStyle -->
> ; <width>1</width> <!-- float -->
> ; </LineStyle>
>
> kml_entry = "LineStyle"
> kml_entry@single_tags=(/"color","colorMode","width"/)
> kml_entry@close_tag=True
> kml_setline_idtag(kml,kml_entry,res)
>
> return(kml)
> end ;kml_add_linestyle
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_ballonstyle")
> function kml_add_ballonstyle ( kml:string, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <BalloonStyle id="ID">
> ; <!-- specific to BalloonStyle -->
> ; <bgColor>ffffffff</bgColor> <!-- kml:color -->
> ; <textColor>ff000000</textColor> <!-- kml:color -->
> ; <text>...</text> <!-- string -->
> ; <displayMode>default</displayMode> <!-- kml:displayModeEnum -->
> ; </BalloonStyle>
>
> kml_entry = "BalloonStyle"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> if (isatt(res,"kmlBGColor")) then
> kml_entry = "<bgColor>"+res@kmlBGColor+"</bgColor>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
>
> kml_entry=(/"textColor","text","displayMode"/)
> kml_setline_singletag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml_entry = "</BalloonStyle>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_add_ballonstyle
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_liststyle")
> function kml_add_liststyle ( kml:string, href:string, ires:logical )
> local kml_entry, res
> begin
>
> ; <ListStyle id="ID">
> ; <!-- specific to ListStyle -->
> ; <listItemType>check</listItemType> <!-- kml:listItemTypeEnum:check,
> ;
> checkOffOnly,checkHideChildren,
> ; radioFolder -->
> ; <bgColor>ffffffff</bgColor> <!-- kml:color -->
> ; <ItemIcon> <!-- 0 or more ItemIcon elements
> -->
> ; <state>open</state>
> ; <!-- kml:itemIconModeEnum:open, closed, error, fetching0,
> fetching1, or fetching2 -->
> ; <href>...</href> <!-- anyURI -->
> ; </ItemIcon>
> ; </ListStyle>
>
> res=ires
> kml_entry = "ListStyle"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> if (isatt(res,"kmlBGColor")) then
> kml_entry = "<bgColor>"+res@kmlBGColor+"</bgColor>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
>
> if (isatt(res,"kmlItemIcon").and.res@kmlItemIcon) then
> kml_entry = "<ItemIcon>"
> kml_entry@single_tags=(/"state","href"/)
> kml_entry@close_tag=True
> delete(res@ID)
> res@kmlHref=href
> kml_setline_idtag(kml,kml_entry,res)
> end if
>
> kml_entry = "</ListStyle>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_add_liststyle
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_close_stylemap")
> function kml_close_stylemap ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = "</StyleMap>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_close_style")
> function kml_close_style ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = "</Style>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
>
> ; features
>
> ;************************************************************
> ; comments
>
> undef("kml_add_lookat")
> function kml_add_lookat ( kml:string, x[1]:float, y[1]:float, z[1]:float,
> range[1]:float, res:logical )
> local kml, kml_entry, res, heading, tilt, roll, range, x, y, z
> begin
>
> ; <LookAt id="ID">
> ; <!-- inherited from AbstractView element -->
> ; <TimePrimitive>...</TimePrimitive> <!-- gx:TimeSpan or gx:TimeStamp
> -->
> ;
> ; <!-- specific to LookAt -->
> ; <longitude>0</longitude> <!-- kml:angle180 -->
> ; <latitude>0</latitude> <!-- kml:angle90 -->
> ; <altitude>0</altitude> <!-- double -->
> ; <heading>0</heading> <!-- kml:angle360 -->
> ; <tilt>0</tilt> <!-- kml:anglepos90 -->
> ; <range></range> <!-- double -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!--kml:altitudeModeEnum:clampToGround, relativeToGround,
> absolute -->
> ; <!-- or, gx:altitudeMode can be substituted: clampToSeaFloor,
> relativeToSeaFloor -->
> ;
> ; </LookAt>
>
> kml_entry = "LookAt"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> ;
> ; <TimeSpan id="ID">
> ; <begin>...</begin> <!-- yyyy-mm-ddThh:mm:sszzzzzz -->
> ; <end>...</end> <!-- yyyy-mm-ddThh:mm:sszzzzzz-->
> ; </TimeSpan>
>
> ; <TimeStamp id=ID>
> ; <when>...</when> <!-- kml:dateTime -->
> ; </TimeStamp>
>
> ; TODO error check here
>
> if (isatt(res,"kmlTimeSpanBegin")) then
> kml_entry = (/ \
> "<TimeSpan>", \
> "<begin>"+res@kmlTimeSpanBegin+"</begin>", \
> "<end>"+res@kmlTimeSpanEnd+"</end>", \
> "</TimeSpan>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> else
> if (isatt(res,"kmlTimeStamp")) then
> kml_entry = (/ \
> "<TimeStamp>", \
> "<when>"+res@kmlTimeStamp+"</when>", \
> "</TimeStamp>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
> end if
>
> heading = get_res_value_keep(res,"kmlHeading",0)
> tilt = get_res_value_keep(res,"kmlTilt",0)
>
> kml_entry = (/ \
> " <longitude>"+x+"</longitude>", \
> " <latitude>"+y+"</latitude>", \
> " <altitude>"+z+"</altitude>", \
> " <heading>"+heading+"</heading>", \
> " <tilt>"+tilt+"</tilt>", \
> " <range>"+range+"</range>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> kml_entry = "</LookAt>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
>
> return(kml)
> end ;kml_add_lookat
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_camera")
> function kml_add_camera ( kml:string, x[1]:float, y[1]:float, z[1]:float,
> res:logical )
> local kml, kml_entry, res
> begin
>
> ; <Camera id="ID">
> ; <!-- inherited from AbstractView element -->
> ; <TimePrimitive>...</TimePrimitive> <!-- gx:TimeSpan or gx:TimeStamp
> -->
> ;
> ; <!-- specific to Camera -->
> ; <longitude>0</longitude> <!-- kml:angle180 -->
> ; <latitude>0</latitude> <!-- kml:angle90 -->
> ; <altitude>0</altitude> <!-- double -->
> ; <heading>0</heading> <!-- kml:angle360 -->
> ; <tilt>0</tilt> <!-- kml:anglepos180 -->
> ; <roll>0</roll> <!-- kml:angle180 -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: relativeToGround, clampToGround, or
> absolute -->
> ; <!-- or, gx:altitudeMode can be substituted: clampToSeaFloor,
> relativeToSeaFloor -->
> ; </Camera>
>
> kml_entry = "Camera"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> ;
> ; <TimeSpan id="ID">
> ; <begin>...</begin> <!-- yyyy-mm-ddThh:mm:sszzzzzz -->
> ; <end>...</end> <!-- yyyy-mm-ddThh:mm:sszzzzzz-->
> ; </TimeSpan>
>
> ; <TimeStamp id=ID>
> ; <when>...</when> <!-- kml:dateTime -->
> ; </TimeStamp>
>
> ; TODO error check here
>
> if (isatt(res,"kmlTimeSpanBegin")) then
> kml_entry = (/ \
> "<TimeSpan>", \
> "<begin>"+res@kmlTimeSpanBegin+"</begin>", \
> "<end>"+res@kmlTimeSpanEnd+"</end>", \
> "</TimeSpan>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> else
> if (isatt(res,"kmlTimeStamp")) then
> kml_entry = (/ \
> "<TimeStamp>", \
> "<when>"+res@kmlTimeStamp+"</when>", \
> "</TimeStamp>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
> end if
>
> heading = get_res_value_keep(res,"kmlHeading",0)
> tilt = get_res_value_keep(res,"kmlTilt",0)
> roll = get_res_value_keep(res,"kmlRoll",0)
>
> kml_entry = (/ \
> " <longitude>"+x+"</longitude>", \
> " <latitude>"+y+"</latitude>", \
> " <altitude>"+z+"</altitude>", \
> " <heading>"+heading+"</heading>", \
> " <tilt>"+tilt+"</tilt>", \
> " <roll>"+roll+"</roll>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> kml_entry = "</Camera>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_add_camera
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_region")
> function kml_add_region ( kml:string, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <Region id="ID">
> ; <LatLonAltBox>
> ; <north></north> <!-- required;
> kml:angle90 -->
> ; <south></south> <!-- required;
> kml:angle90 -->
> ; <east></east> <!-- required;
> kml:angle180 -->
> ; <west></west> <!-- required;
> kml:angle180 -->
> ; <minAltitude>0</minAltitude> <!-- float -->
> ; <maxAltitude>0</maxAltitude> <!-- float -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or
> absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; </LatLonAltBox>
> ; <Lod>
> ; <minLodPixels>0</minLodPixels> <!-- float -->
> ; <maxLodPixels>-1</maxLodPixels> <!-- float -->
> ; <minFadeExtent>0</minFadeExtent> <!-- float -->
> ; <maxFadeExtent>0</maxFadeExtent> <!-- float -->
> ; </Lod>
> ; </Region>
>
> return(kml)
> end ;kml_add_region
> ; *****************************************************************
>
>
>
> ;************************************************************
> ; comments
>
> undef("kml_open_placemark")
> function kml_open_placemark ( kml:string, name:string, res:logical )
> local kml_entry
> begin
>
> ; <Placemark id="ID">
> ; <!-- inherits all Feature elements -->
>
> ;
> ; <!-- specific to Placemark element -->
> ; <MultiGeometry>...</MultiGeometry>
> ; </Placemark>
>
> kml_entry = "Placemark"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_feature_attr(kml, name, res)
>
> ; specific to Placemark
> kml_entry = "<MultiGeometry>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_open_placemark
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_add_point")
> function kml_add_point( kml:string, x[1]:float, y[1]:float, z[1]:float,
> res:logical )
> local kml_entry
> begin
> ; add point element to kml
> ; contained by placemark or multigeometry
>
> ; <Point id="ID">
> ; <!-- specific to Point -->
> ; <extrude>0</extrude> <!-- boolean -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or
> absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
> ; </Point>
>
> kml_entry = "Point"
> kml_entry@single_tags=(/"extrude"/)
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> kml_entry = "<coordinates>"+x+","+y+","+z+"</coordinates>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml_entry = "</Point>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return (kml)
> end ;kml_add_point
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_linestring")
> function kml_add_linestring ( kml:string, x[*]:numeric, y[*]:numeric,
> z[*]:numeric, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <LineString id="ID">
> ; <!-- specific to LineString -->
> ; <extrude>0</extrude> <!-- boolean -->
> ; <tessellate>0</tessellate> <!-- boolean -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or
> absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
> ; </LineString>
>
> ; TODO: error check dimension sizes
>
> kml_entry = "LineString"
> kml_entry@single_tags=(/"extrude","tessellate"/)
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> kml_entry = "<coordinates>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> nx = dimsizes(x)
> ny = dimsizes(y)
> nz = dimsizes(z)
>
> if ((nx .ne. ny) .or. (nx .ne. nz)) then
> print("kml_add_linestring: Fatal: dimensions of x, y, and z must be
> equal.")
> return
> end if
>
> do i = 0, nx-1
> kml_entry = x(i) + "," + y(i) + "," + z(i)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end do
>
> kml_entry = "</coordinates>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml_entry = "</LineString>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
>
> return(kml)
> end ;kml_add_linestring
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_open_polygon")
> function kml_open_polygon ( kml:string, res:logical )
> local kml_entry
> begin
>
> ; <Polygon id="ID">
> ; <!-- specific to Polygon -->
> ; <extrude>0</extrude> <!-- boolean -->
> ; <tessellate>0</tessellate> <!-- boolean -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or
> absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; <outerBoundaryIs>
> ; <LinearRing>
> ; <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
> ; </LinearRing>
> ; </outerBoundaryIs>
> ; <innerBoundaryIs>
> ; <LinearRing>
> ; <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
> ; </LinearRing>
> ; </innerBoundaryIs>
> ; </Polygon>
>
> ; TODO: error check dimension sizes
>
> kml_entry = "Polygon"
> kml_entry@single_tags=(/"extrude","tessellate"/)
> kml_setline_idtag(kml,kml_entry,res)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> return(kml)
> end ;kml_open_polygon
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_polygon_outer")
> function kml_add_polygon_outer ( kml:string, x[*]:numeric, y[*]:numeric,
> z[*]:numeric, res:logical )
> local kml, kml_entry, res, x, y, z, npoints
> begin
>
> ; 1 contained in Polygon element
>
> kml_entry = (/ \
> "<outerBoundaryIs>", \
> " <LinearRing>", \
> " <coordinates>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> nx = dimsizes(x)
> ny = dimsizes(y)
> nz = dimsizes(z)
>
> if ((nx .ne. ny) .or. (nx .ne. nz)) then
> print("kml_polygon_outer: Fatal: dimensions of x, y, and z must be
> equal.")
> return
> end if
>
> do i = 0, nx-1
> kml_entry = " " + x(i) + "," + y(i) + "," + z(i)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end do
>
> kml_entry = (/ \
> " </coordinates>", \
> " </LinearRing>", \
> "</outerBoundaryIs>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end ;kml_add_polygon_outer
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_polygon_inner")
> function kml_add_polygon_inner ( kml:string, x[*]:numeric, y[*]:numeric,
> z[*]:numeric, res:logical )
> local kml, kml_entry, res, x, y, z, npoints
> begin
>
> ; 0 or more contained in Polygon element
>
> kml_entry = (/ \
> "<innerBoundaryIs>", \
> " <LinearRing>", \
> " <coordinates>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
>
>
> nx = dimsizes(x)
> ny = dimsizes(y)
> nz = dimsizes(z)
>
> if ((nx .ne. ny) .or. (nx .ne. nz)) then
> print("kml_polygon_inner: Fatal: dimensions of x, y, and z must be
> equal.")
> return
> end if
>
> do i = 0, nx-1
> kml_entry = " " + x(i) + "," + y(i) + "," + z(i)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end do
>
> kml_entry = (/ \
> " </coordinates>", \
> " </LinearRing>", \
> "</innerBoundaryIs>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_close_polygon")
> function kml_close_polygon ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = "</Polygon>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
> ;************************************************************
> ; comments
>
> undef("kml_close_placemark")
> function kml_close_placemark ( kml:string )
> local kml, kml_entry
> begin
>
> kml_entry = (/ \
> " </MultiGeometry>", \
> "</Placemark>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
>
> ;************************************************************
> ; comments
>
> undef("kml_plot_groundoverlay")
> function kml_plot_groundoverlay ( kml:string, name:string,
> wks:graphic,plot:graphic, z[1]:float, res:logical )
> local kml, kml_entry, res, plot_name, plot_file, icon, crop, name
> begin
>
> plot_name = wks@name
> plot_file = plot_name+".ps"
> icon = plot_name+".png"
>
> draw(plot)
> frame(wks)
>
> LatLonBox = kml_get_vp_latlonbox(plot)
> crop = kml_get_vp_crop(wks,plot)
>
> convert = "convert +repage -crop
> "+crop(0)+"x"+crop(1)+"+"+crop(2)+"+"+crop(3)+" "+plot_file+" "+icon
> print(convert)
> system(convert)
>
> files = kml@files
> kml@files = files + " " + icon
>
> kml = kml_add_groundoverlay(kml, name, icon, LatLonBox, z, res)
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_plot_screenoverlay")
> function kml_plot_screenoverlay ( kml:string, name:string,
> wks:graphic,plot:graphic, res:logical )
> local kml, kml_entry, res, plot_name, plot_file, icon, lbcrop, name
> begin
>
>
> plot_name = wks@name
> plot_file = plot_name+".ps"
> icon = plot_name+"_lb.png"
>
> crop = kml_get_vp_crop(wks,plot)
>
> convert = "convert +repage -crop
> "+crop(0)+"x"+crop(1)+"+"+crop(2)+"+"+crop(3)+" "+plot_file+" "+icon
> print(convert)
> system(convert)
>
> files = kml@files
> kml@files = files + " " + icon
>
> kml = kml_add_screenoverlay(kml, name, icon, res)
>
> return(kml)
> end
> ; *****************************************************************
>
>
>
>
>
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_model")
> function kml_add_model ( kml:string, name:string, link:string, x[1]:float,
> y[1]:float, z[1]:float, res:logical )
> local kml, kml_entry, res, heading, tilt, roll, scalex, scaley, scalez
> begin
>
> ; <Model id="ID">
> ; <!-- specific to Model -->
> ; <altitudeMode>clampToGround</altitudeMode>
> ; <!-- kml:altitudeModeEnum: clampToGround,relativeToGround,or
> absolute -->
> ; <!-- or, substitute gx:altitudeMode: clampToSeaFloor,
> relativeToSeaFloor -->
> ; <Location>
> ; <longitude></longitude> <!-- kml:angle180 -->
> ; <latitude></latitude> <!-- kml:angle90 -->
> ; <altitude>0</altitude> <!-- double -->
> ; </Location>
> ; <Orientation>
> ; <heading>0</heading> <!-- kml:angle360 -->
> ; <tilt>0</tilt> <!-- kml:angle360 -->
> ; <roll>0</roll> <!-- kml:angle360 -->
> ; </Orientation>
> ; <Scale>
> ; <x>1</x> <!-- double -->
> ; <y>1</y> <!-- double -->
> ; <z>1</z> <!-- double -->
> ; </Scale>
> ; <Link>...</Link>
> ; <ResourceMap>
> ; <Alias>
> ; <targetHref>...</targetHref> <!-- anyURI -->
> ; <sourceHref>...</sourceHref> <!-- anyURI -->
> ; </Alias>
> ; </ResourceMap>
> ; </Model>
>
> kml_entry = "Model"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml = kml_altitudeMode_attr(kml,res)
>
> kml_entry = (/ \
> "<Location>", \
> " <longitude>"+x+"</longitude>", \
> " <latitude>"+y+"</latitude>", \
> " <altitude>"+z+"</altitude>", \
> "</Location>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> heading = get_res_value_keep(res,"kmlHeading",0)
> tilt = get_res_value_keep(res,"kmlTilt",0)
> roll = get_res_value_keep(res,"kmlRoll",0)
>
> kml_entry = (/ \
> "<Orientation>", \
> " <heading>"+heading+"</heading>", \
> " <tilt>"+tilt+"</tilt>", \
> " <roll>"+roll+"</roll>", \
> "</Orientation>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> scalex = get_res_value_keep(res,"kmlScaleX",1)
> scaley = get_res_value_keep(res,"kmlScaleY",1)
> scalez = get_res_value_keep(res,"kmlScaleZ",1)
>
> kml_entry = (/ \
> "<Scale>", \
> " <x>"+scalex+"</x>", \
> " <y>"+scaley+"</y>", \
> " <z>"+scalez+"</z>", \
> "</Scale>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml = kml_link_attr(kml, link, res)
>
> if (isatt(res,"kmlTargetHref") .and. isatt(res,"kmlSourceHref")) then
>
> ntarget = dimsizes(res@kmlTargetHref)
> nsource = dimsizes(res@kmlSourceHref)
>
> if ((ntarget .ne. nsource) ) then
> print("kml_add_model: Fatal: dimensions of resources kmlTargetHref and
> kmlSourceHref must be equal.")
> return
> end if
>
> kml_entry = "<ResourceMap>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> do i = 0, ntarget-1
> kml_entry = (/ \
> "<Alias>", \
> " <targetHref>"+res@kmlTargetHref(i)+"</targetHref>", \
> " <sourceHref>"+res@kmlSourceHref(i)+"</sourceHref>", \
> "</Alias>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end do
>
> kml_entry = "</ResourceMap>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> end if
>
> kml_entry = "</Model>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
> ;************************************************************
> ; comments
>
> undef("kml_add_stylepair")
> function kml_add_stylepair ( kml:string, key:string, styleurl:string)
> local kml, kml_entry, target, source
> begin
>
> ; contained by <StyleMap>
> ; <Pair id="ID">
> ; <key>normal</key> <!-- kml:styleStateEnum: normal or
> highlight -->
> ; <styleUrl>...</styleUrl> or <Style>...</Style>
> ; </Pair>
>
> kml_entry = "Pair"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> kml_entry = (/ \
> " <key>"+key+"</key>", \
> " <styleUrl>"+styleurl+"</styleUrl>", \
> "</Pair>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; *****************************************************************
>
>
>
> ;************************************************************
> ; comments
>
> undef("kml_add_photooverlay")
> function kml_add_photooverlay ( kml:string, name:string, icon:string,
> x[1]:float, y[1]:float, z[1]:float, res:logical )
> local kml, kml_entry, res
> begin
>
> ; <PhotoOverlay id="ID">
>
> kml_entry = "PhotoOverlay"
> kml_setline_idtag(kml,kml_entry,res)
> delete(kml_entry)
>
> ; <!-- inherits all Feature elements -->
>
> kml = kml_feature_attr(kml, name, res)
> ;
> ; <!-- inherited from Overlay element -->
> ; <color>ffffffff</color> <!-- kml:color -->
> ; <drawOrder>0</drawOrder> <!-- int -->
> ; <Icon>...</Icon>
>
> kml = kml_overlay_attr(kml, icon, res)
>
> ; <!-- specific to PhotoOverlay -->
> ; <rotation>0</rotation> <!-- kml:angle180 -->
> ; <ViewVolume>
> ; <leftFov>0</leftFov> <!-- kml:angle180 -->
> ; <rightFov>0</rightFov> <!-- kml:angle180 -->
> ; <bottomFov>0</bottomFov> <!-- kml:angle90 -->
> ; <topFov>0</topFov> <!-- kml:angle90 -->
> ; <near>0</near> <!-- double -->
> ; </ViewVolume>
>
> rotation = get_res_value_keep(res,"kmlRotation",0)
> leftfov = get_res_value_keep(res,"kmlLeftFov" ,0)
> rightfov = get_res_value_keep(res,"kmlRightFov" ,0)
> bottomfov = get_res_value_keep(res,"kmlBottomFov" ,0)
> topfov = get_res_value_keep(res,"kmlTopFov" ,0)
> near = get_res_value_keep(res,"kmlNear" ,0)
>
> kml_entry = (/ \
> "<rotation>"+rotation+"</rotation>", \
> "<ViewVolume>", \
> " <leftFov>"+leftfov+"</leftFov>", \
> " <rightFov>"+rightfov+"</rightFov>", \
> " <bottomFov>"+bottomfov+"</bottomFov>", \
> " <topFov>"+topfov+"</topFov>", \
> " <near>"+near+"</near>", \
> "</ViewVolume>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> ; <ImagePyramid>
> ; <tileSize>256</tileSize> <!-- int -->
> ; <maxWidth>...</maxWidth> <!-- int -->
> ; <maxHeight>...</maxHeight> <!-- int -->
> ; <gridOrigin>lowerLeft</gridOrigin> <!-- lowerLeft or
> upperLeft-->
> ; </ImagePyramid>
>
> if (isatt(res,"kmlImagePyramid")) then
> if (res@kmlImagePyramid) then
>
> tilesize = get_res_value_keep(res,"kmlTileSize",256)
> gridorigin = get_res_value_keep(res,"kmlGridOrigin" ,"lowerLeft")
>
> kml_entry = (/ \
> "<ImagePyramid>", \
> " <tileSize>"+tilesize+"</tileSize>", \
> " <maxWidth>"+res@kmlMaxWidth+"</maxWidth>", \
> " <maxHeight>"+res@kmlMaxHeight+"</maxHeight>", \
> " <gridOrigin>"+gridorigin+"</gridOrigin>", \
> "</ImagePyramid>" \
> /)
> kml_setline(kml,kml_entry)
> delete(kml_entry)
> end if
> end if
>
> ; <Point>
> ; <coordinates>...</coordinates> <!-- lon,lat[,alt] -->
> ; </Point>
> ; <shape>rectangle</shape> <!-- kml:shape -->
> ; </PhotoOverlay>
>
> kml = kml_add_point(kml, x, y, z, 0)
> shape = get_res_value_keep(res,"kmlShape","rectangle")
>
> kml_entry = "<shape>"+shape+"</shape>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> kml_entry = "</PhotoOverlay>"
> kml_setline(kml,kml_entry)
> delete(kml_entry)
>
> return(kml)
> end
> ; ***************************************************************** -->
>
>

-- 
------------------------------------------
Ryan Pavlick
Doctoral Student
Biospheric Theory and Modellling Group
Max Planck Institute for Biogeochemistry
mail: P.O. Box 10 01 64, D-07701 Jena, Germany
email: rpavlick@bgc-jena.mpg.de
phone: +49.36.41.57.6262
web: http://gaia.mpg.de
------------------------------------------

_______________________________________________
ncl-talk mailing list
List instructions, subscriber options, unsubscribe:
http://mailman.ucar.edu/mailman/listinfo/ncl-talk
Received on Fri Sep 17 06:46:43 2010

This archive was generated by hypermail 2.1.8 : Wed Oct 06 2010 - 09:53:35 MDT