// Write KML file for mapping lat/lon // stored in a Stata data set -- 2011.09.20 // Bug fix: writeKMLFile used to rely on explicit // variable names. No longer -- 2011.11.19 // 2 improvements -- 2012.12.27 // -- place names and descriptions are now optional. // if missing, the place category will be filled into // both the name and the description slot. // -- place category can be numeric now. // Gabi Huiber -- ghuiber@gmail.com program writekml version 9.0 syntax, filename(string) plcategory(varname) [plname(varname string) pldesc(varname string)] local keepthese longitude latitude `plcategory' `plname' `pldesc' confirm numeric variable longitude confirm numeric variable latitude quietly { preserve tempfile keeps keep `keepthese' compress save "`keeps'", replace count local obs=r(N) levelsof `plcategory', local(kinds) capture confirm numeric variable `plcategory' if _rc==0 { local chex foreach k in `kinds' { local chex `chex' `plcategory'`k' } local kinds `chex' } local kinds: list clean kinds restore } local checkname=length("`plname'") local checkdesc=length("`pldesc'") local myargs obs(`obs') filename(`filename') plcategory(`plcategory') if `checkname'>0 { local myargs `myargs' plname(`plname') } if `checkdesc'>0 { local myargs `myargs' pldesc(`pldesc') } writeKMLFile `kinds', `myargs' end // write kml file. this is a wrapper that // relies on components defined below. capture prog drop writeKMLFile program writeKMLFile version 9.0 syntax namelist(min=1), obs(integer) filename(string) plcategory(varname) [plname(varname string) pldesc(varname string)] local kinds `namelist' local kindct: list sizeof kinds local colors red green blue ltblue yellow orange pink purple local colorct: list sizeof colors if `colorct'<`kindct' { di as err "Not enough colors." exit } forvalues i=1/`kindct' { local kindname: word `i' of `kinds' local `kindname': word `i' of `colors' // so, e.g. "local academic green" } local checkname=length("`plname'") local checkdesc=length("`pldesc'") local checkncat=0 capture confirm numeric variable `plcategory' if _rc==0 { local checkncat=1 } // now write out the KML file // -- header first writeKMLHeader `filename' // -- then a style corresponding to each kind of object foreach kindname in `kinds' { writeKMLStyle ``kindname'' `filename' } // -- then a place marker for each valid observation in the address file forvalues i=1/`obs' { local kind=`plcategory' in `i' if `checkncat'==1 { local kind `plcategory'`kind' } local lat =latitude in `i' local lon =longitude in `i' local myargs color(``kind'') lon(`lon') lat(`lat') if `checkname'>0 { local name=`plname' in `i' local myargs `myargs' name(`name') } else { local myargs `myargs' name(`kind') } if `checkdesc'>0 { local desc=`pldesc' in `i' local myargs `myargs' desc(`desc') } else { local myargs `myargs' desc(`kind') } writeKMLPlacemark, kmlfile(`filename') `myargs' } // -- and finally the footer writeKMLFooter `filename' di "`filename' written to `c(pwd)'" end // set locals capture prog drop setKMLLocals program setKMLLocals, rclass version 9.0 return local lilpaddles "http://www.google.com/intl/en_us/mapfiles/ms/micons/" return local bigpaddles "http://maps.google.com/mapfiles/kml/paddle/" end // write style corresponding to a paddle color, // which in turn corresponds to a given kind of mapped // object (e.g. coffee shop, gas station) as defined // in the writeKMLFile wrapper. capture prog drop writeKMLStyle program writeKMLStyle version 9.0 args color filename setKMLLocals local path `r(lilpaddles)' tempname fwrite local writeto `filename' file open `fwrite' using `writeto', write append file write `fwrite' `"`kml_header'"' _n file write `fwrite' `"`kml_open'"' _n file write `fwrite' "`doc_open'" _n local styleid " _n file close `fwrite' end // write a place mark, corresponding to a given style. see // color mapping in writeKMLFile and header of writeKMLStyle capture prog drop writeKMLPlacemark program writeKMLPlacemark version 9.0 syntax, kmlfile(string) color(string) lon(real) lat(real) name(string) desc(string) local checkname=length("`plname'") local checkdesc=length("`pldesc'") local styletag #`color' local nametag `name' local desctag `desc' local coordinates `lon',`lat',0 tempname fwrite local writeto `kmlfile' file open `fwrite' using `writeto', write append file write `fwrite' _tab "" _n file write `fwrite' _tab "`macval(nametag)'" _n file write `fwrite' _tab "`macval(desctag)'" _n file write `fwrite' _tab _tab "`macval(styletag)'" _n file write `fwrite' _tab _tab "" _n file write `fwrite' _tab _tab _tab "`macval(coordinates)'" _n file write `fwrite' _tab _tab "" _n file write `fwrite' _tab "" _n file close `fwrite' end // write kml file header capture prog drop writeKMLHeader program writeKMLHeader version 9.0 local 0 `"using `0'"' syntax using/ tempname fwrite local writeto `using' file open `fwrite' using `writeto', write replace local kml_header local kml_open local doc_open file write `fwrite' `"`kml_header'"' _n file write `fwrite' `"`kml_open'"' _n file write `fwrite' "`doc_open'" _n file close `fwrite' end // write kml file footer capture prog drop writeKMLFooter program writeKMLFooter version 9.0 local 0 `"using `0'"' syntax using/ tempname fwrite local writeto `using' file open `fwrite' using `writeto', write append file write `fwrite' "" _n file write `fwrite' "" _n file close `fwrite' end