From an ESRI shapefile of world countries I have created, in R,
library(sf)
world <- st_read("World_Countries__Generalized_.shp", stringsAsFactors=FALSE)
cs<-c("af", "al", "dz", "as", "ad", "ao", "ai", "aq", "ag", "ar", "am", "aw", "au", "at", "az", "pt", "bs", "bh", "bd", "bb", "by", "be", "bz", "bj", "bm", "bt", "bo", "bq", "ba", "bw", "bv", "br", "io", "vg", "bn", "bg", "bf", "bi", "cv", "kh", "cm", "ca", "es", "ky", "cf", "td", "cl", "cn", "cx", "cc", "co", "km", "cg", "cd", "ck", "cr", "ci", "hr", "cu", "cw", "cy", "cz", "dk", "dj", "dm", "do", "ec", "eg", "sv", "gq", "er", "ee", "sz", "et", "fk", "fo", "fj", "fi", "fr", "gf", "pf", "tf", "ga", "gm", "ge", "de", "gh", "gi", "tf", "gr", "gl", "gd", "gp", "gu", "gt", "gg", "gn", "gw", "gy", "ht", "hm", "hn", "hu", "is", "in", "id", "ir", "iq", "ie", "im", "il", "it", "jm", "jp", "je", "jo", "tf", "kz", "ke", "ki", "kw", "kg", "la", "lv", "lb", "ls", "lr", "ly", "li", "lt", "lu", "mg", "pt", "mw", "my", "mv", "ml", "mt", "mh", "mq", "mr", "mu", "yt", "mx", "fm", "md", "mc", "mn", "me", "ms", "ma", "mz", "mm", "na", "nr", "np", "nl", "nc", "nz", "ni", "ne", "ng", "nu", "nf", "kp", "mk", "mp", "no", "om", "pk", "pw", "ps", "pa", "pg", "py", "pe", "ph", "pn", "pl", "pt", "pr", "qa", "re", "ro", "ru", "rw", "bq", "bl", "bq", "sh", "kn", "lc", "mf", "pm", "vc", "ws", "sm", "st", "sa", "sn", "rs", "sc", "sl", "sg", "sx", "sk", "si", "sb", "so", "za", "gs", "kr", "ss", "es", "lk", "sd", "sr", "sj", "se", "ch", "sy", "tj", "tz", "th", "tl", "tg", "tk", "to", "tt", "tn", "tr", "tm", "tc", "tv", "ug", "ua", "ae", "gb", "us", "um", "uy", "vi", "uz", "vu", "va", "ve", "vn", "wf", "ye", "zm", "zw")
for(i in 1:length(cs)){
dput(world$geometry[[i]],file=paste0(cs[i],".R"))
}
no<-source("no.R")$value
cat(print(no),file = "no.txt")
files isocode.txt (i.e. no.txt for Norway) containing strings
"MULTIPOLYGON (((X1 Y1, X2 Y2, ...), ((XX1 YY1, ...) ))"
and I want to turn them into
"no={Polyline((radius; X1°; X2°), ...),Polyline((radius; XX1°;YY1°), ...)}"
for use in geogebra to draw on the sphere x^2+y^2+z^2=radius^2. Say with radius=5.
My work: for proof of concept I used some horribly slow emacs lisp keyboard macros.
I don't really know common lisp, but I heard it is good for these kinds of problems.
Edit
Edit 2
I've gotten a bit more ambitious and want to write to the geogebra.xml in the world.ggb directly (it's just a .zip of some files; this being one of them). For each line of world2.txt it should have an entry of the form
<command name="PolyLine">
<input [my output goes here]\>
<output a0="aq[the iso code for antarctica]"/>
</command>
<element type="polyline3d" label="aq">
<lineStyle thickness="1" type="0" typeHidden="1" opacity="178"/>
<show object="true" label="false" ev="4"/>
<objColor r="0" g="0" b="0" alpha="0.0"/>
<layer val="0"/>
<labelMode val="0"/>
</element>
where world2.txt just keeps lines of these MULTIPOLYGONs.
There a few problems with my implementation, it only handles the first polygon in the list, and it feels a bit hacky. Also the list of names (iso codes) in the order of the lines in the file should go in there.
(ql:quickload "split-sequence")
(ql:quickload "parse-number")
(defun extract-lon (str)
(let ((m (search " " str)))
(parse-number:parse-real-number (subseq str 0 m))))
(defun extract-lat (str)
(let ((m (search " " str))
(l (length str)))
(parse-number:parse-real-number (subseq str (1+ m) l))))
(with-open-file (in "c:/Users/nmajo/Downloads/World_Countries_(Generalized)/world2.txt" :direction :input)
(loop for text = (read-line in nil) while text do
(loop for string in (split-sequence:split-sequence #\, (if (search "))," text) (subseq text (+ (search "(((" text) 3) (search "))," text)) (subseq text (+ (search "(((" text) 3) (search ")))" text))))
while string
for a from 0
do (format t "a~d=\"(5; ~f°; ~f°)\" " a (extract-lon (string-left-trim " " string)) (extract-lat (string-left-trim " " string))))))
