77f4fa2000-12-02Martin Nilsson /* * Map of the Earth. */ #define ERR(msg) throw(({ msg+"\n", backtrace() })) mapping(string:string) aliases = ([ "usa":"United States of America", "us":"United States of America", "russia":"Russian Federation", "united kingdom":"England", "uk":"England", "vietnam":"Viet Nam" ]); mapping(string:string) domain_to_country =
b206932005-02-22Anders Johansson  ([
85040b2005-03-11Anders Johansson  "ac":"ascension island", "ad":"andorra", "ae":"united arab emirates",
77f4fa2000-12-02Martin Nilsson  "af":"afghanistan",
85040b2005-03-11Anders Johansson  "ag":"antigua and barbuda", "ai":"anguilla",
77f4fa2000-12-02Martin Nilsson  "al":"albania",
85040b2005-03-11Anders Johansson  "am":"armenia", "an":"netherlands antilles",
77f4fa2000-12-02Martin Nilsson  "ao":"angola",
85040b2005-03-11Anders Johansson  "aq":"antarctica",
77f4fa2000-12-02Martin Nilsson  "ar":"argentina",
85040b2005-03-11Anders Johansson  "as":"american samoa",
77f4fa2000-12-02Martin Nilsson  "at":"austria",
85040b2005-03-11Anders Johansson  "au":"australia", "aw":"aruba", "ax":"åland islands",
77f4fa2000-12-02Martin Nilsson  "az":"azerbaijan",
85040b2005-03-11Anders Johansson  "ba":"bosnia and herzegovina", "bb":"barbados",
77f4fa2000-12-02Martin Nilsson  "bd":"bangladesh", "be":"belgium",
85040b2005-03-11Anders Johansson  "bf":"burkina faso", "bg":"bulgaria", "bh":"bahrain", "bi":"burundi",
77f4fa2000-12-02Martin Nilsson  "bj":"benin", "bm":"bermuda",
85040b2005-03-11Anders Johansson  "bn":"brunei darussalam",
77f4fa2000-12-02Martin Nilsson  "bo":"bolivia", "br":"brazil",
85040b2005-03-11Anders Johansson  "bs":"bahamas", "bt":"bhutan", "bu":"burma", "bv":"bouvet island", "bw":"botswana", "by":"belarus", "bz":"belize",
77f4fa2000-12-02Martin Nilsson  "ca":"canada",
85040b2005-03-11Anders Johansson  "cc":"cocos (keeling) islands", "cd":"congo, the democratic republic of the",
77f4fa2000-12-02Martin Nilsson  "cf":"central african republic",
85040b2005-03-11Anders Johansson  "cg":"congo", "ch":"switzerland", "ci":"côte d'ivoire", "ck":"cook islands",
77f4fa2000-12-02Martin Nilsson  "cl":"chile",
85040b2005-03-11Anders Johansson  "cm":"cameroon",
77f4fa2000-12-02Martin Nilsson  "cn":"china", "co":"colombia", "cr":"costa rica",
85040b2005-03-11Anders Johansson  "cs":"serbia and montenegro",
77f4fa2000-12-02Martin Nilsson  "cu":"cuba",
85040b2005-03-11Anders Johansson  "cv":"cape verde", "cx":"christmas island",
77f4fa2000-12-02Martin Nilsson  "cy":"cyprus",
aa300a2001-10-16Honza Petrous  "cz":"czech republic",
85040b2005-03-11Anders Johansson  "de":"germany", "dj":"djibouti",
77f4fa2000-12-02Martin Nilsson  "dk":"denmark",
85040b2005-03-11Anders Johansson  "dm":"dominica",
77f4fa2000-12-02Martin Nilsson  "do":"dominican republic",
85040b2005-03-11Anders Johansson  "dz":"algeria", "ec":"ecuador",
77f4fa2000-12-02Martin Nilsson  "ee":"estonia",
85040b2005-03-11Anders Johansson  "eg":"egypt", "eh":"western sahara", "er":"eritrea", "es":"spain",
77f4fa2000-12-02Martin Nilsson  "et":"ethiopia", "fi":"finland",
85040b2005-03-11Anders Johansson  "fj":"fiji", "fk":"falkland islands (malvinas)", "fm":"micronesia, federal state of", "fo":"faroe islands",
77f4fa2000-12-02Martin Nilsson  "fr":"france", "fx":"france", "ga":"gabon",
85040b2005-03-11Anders Johansson  "gb":"england", "gd":"grenada",
77f4fa2000-12-02Martin Nilsson  "ge":"georgia",
85040b2005-03-11Anders Johansson  "gf":"french guiana", "gg":"guernsey",
77f4fa2000-12-02Martin Nilsson  "gh":"ghana",
85040b2005-03-11Anders Johansson  "gi":"gibraltar",
77f4fa2000-12-02Martin Nilsson  "gl":"greenland",
85040b2005-03-11Anders Johansson  "gm":"gambia",
77f4fa2000-12-02Martin Nilsson  "gn":"guinea",
85040b2005-03-11Anders Johansson  "gp":"guadeloupe", "gq":"equatorial guinea", "gr":"greece", "gs":"south georgia and the south sandwich islands", "gt":"guatemala", "gu":"guam",
77f4fa2000-12-02Martin Nilsson  "gw":"guinea-bissau", "gy":"guyana",
85040b2005-03-11Anders Johansson  "hk":"hong kong", "hm":"heard and mcdonald islands", "hn":"honduras", "hr":"croatia", "ht":"haiti",
77f4fa2000-12-02Martin Nilsson  "hu":"hungary",
85040b2005-03-11Anders Johansson  "id":"indonesia",
77f4fa2000-12-02Martin Nilsson  "ie":"ireland", "il":"israel",
85040b2005-03-11Anders Johansson  "im":"isle of man", "in":"india", "io":"british indian ocean territory", "iq":"iraq", "ir":"iran", "is":"iceland",
77f4fa2000-12-02Martin Nilsson  "it":"italy",
85040b2005-03-11Anders Johansson  "je":"jersey",
77f4fa2000-12-02Martin Nilsson  "jm":"jamaica", "jo":"jordan",
85040b2005-03-11Anders Johansson  "jp":"japan",
77f4fa2000-12-02Martin Nilsson  "ke":"kenya",
85040b2005-03-11Anders Johansson  "kg":"kyrgyzstan", "kh":"cambodia", "ki":"kiribati", "km":"comoros", "kn":"saint kitts and nevis", "kp":"north korea", "kr":"south korea",
77f4fa2000-12-02Martin Nilsson  "kw":"kuwait",
85040b2005-03-11Anders Johansson  "ky":"cayman islands", "kz":"kazakhstan",
77f4fa2000-12-02Martin Nilsson  "la":"laos", "lb":"lebanon",
85040b2005-03-11Anders Johansson  "lc":"saint lucia", "li":"liechtenstein", "lk":"sri lanka",
77f4fa2000-12-02Martin Nilsson  "lr":"liberia",
85040b2005-03-11Anders Johansson  "ls":"lesotho",
77f4fa2000-12-02Martin Nilsson  "lt":"lithuania",
85040b2005-03-11Anders Johansson  "lu":"luxembourg", "lv":"latvia", "ly":"libya", "ma":"morocco", "mc":"monaco", "md":"moldova",
77f4fa2000-12-02Martin Nilsson  "mg":"madagascar",
85040b2005-03-11Anders Johansson  "mh":"marshall islands", "mk":"macedonia, the former yugoslav republic of",
77f4fa2000-12-02Martin Nilsson  "ml":"mali",
85040b2005-03-11Anders Johansson  "mm":"myanmar", "mn":"mongolia", "mo":"macao", "mp":"northern mariana islands", "mq":"martinique",
77f4fa2000-12-02Martin Nilsson  "mr":"mauritania",
85040b2005-03-11Anders Johansson  "ms":"montserrat", "mt":"malta", "mu":"mauritius", "mv":"maldives", "mw":"malawi",
77f4fa2000-12-02Martin Nilsson  "mx":"mexico",
85040b2005-03-11Anders Johansson  "my":"malaysia",
77f4fa2000-12-02Martin Nilsson  "mz":"mozambique", "na":"namibia",
85040b2005-03-11Anders Johansson  "nc":"new caledonia",
77f4fa2000-12-02Martin Nilsson  "ne":"niger",
85040b2005-03-11Anders Johansson  "nf":"norfolk island",
77f4fa2000-12-02Martin Nilsson  "ng":"nigeria",
85040b2005-03-11Anders Johansson  "ni":"nicaragua", "nl":"netherlands",
77f4fa2000-12-02Martin Nilsson  "no":"norway",
85040b2005-03-11Anders Johansson  "np":"nepal", "nr":"nauru", "nu":"niue", "nz":"new zealand",
77f4fa2000-12-02Martin Nilsson  "om":"oman", "pa":"panama", "pe":"peru",
85040b2005-03-11Anders Johansson  "pf":"french polynesia", "pg":"papua new guinea",
77f4fa2000-12-02Martin Nilsson  "ph":"philippines",
85040b2005-03-11Anders Johansson  "pk":"pakistan",
77f4fa2000-12-02Martin Nilsson  "pl":"poland",
85040b2005-03-11Anders Johansson  "pm":"saint pierre and miquelon", "pn":"pitcairn island", "pr":"puerto rico", "ps":"palestinian territory, occupied",
77f4fa2000-12-02Martin Nilsson  "pt":"portugal",
85040b2005-03-11Anders Johansson  "pw":"palau", "py":"paraguay",
77f4fa2000-12-02Martin Nilsson  "qa":"qatar",
85040b2005-03-11Anders Johansson  "re":"reunion island",
77f4fa2000-12-02Martin Nilsson  "ro":"romania",
85040b2005-03-11Anders Johansson  "ru":"russian federation",
77f4fa2000-12-02Martin Nilsson  "rw":"rwanda", "sa":"saudi arabia",
85040b2005-03-11Anders Johansson  "sb":"solomon islands", "sc":"seychelles", "sd":"sudan", "se":"sweden",
b206932005-02-22Anders Johansson  "sg":"singapore",
85040b2005-03-11Anders Johansson  "sh":"saint helena", "si":"slovenia", "sj":"svalbard and jan mayen islands",
aa300a2001-10-16Honza Petrous  "sk":"slovakia",
77f4fa2000-12-02Martin Nilsson  "sl":"sierra leone",
85040b2005-03-11Anders Johansson  "sm":"san marino", "sn":"senegal",
77f4fa2000-12-02Martin Nilsson  "so":"somalia", "sr":"suriname",
85040b2005-03-11Anders Johansson  "st":"sao tome and principe", "su":"russian federation", "sv":"el salvador",
77f4fa2000-12-02Martin Nilsson  "sy":"syria",
85040b2005-03-11Anders Johansson  "sz":"swaziland", "tc":"turks and caicos islands", "td":"chad", "tf":"french southern territories",
77f4fa2000-12-02Martin Nilsson  "tg":"togo",
85040b2005-03-11Anders Johansson  "th":"thailand", "tj":"tajikistan", "tk":"tokelau", "tl":"timor-leste", "tm":"turkmenistan",
77f4fa2000-12-02Martin Nilsson  "tn":"tunisia",
85040b2005-03-11Anders Johansson  "to":"tonga", "tp":"east timor",
77f4fa2000-12-02Martin Nilsson  "tr":"turkey",
85040b2005-03-11Anders Johansson  "tt":"trinidad and tobago", "tv":"tuvalu", "tw":"taiwan", "tz":"tanzania",
77f4fa2000-12-02Martin Nilsson  "ua":"ukraine",
85040b2005-03-11Anders Johansson  "ug":"uganda", "uk":"england", "um":"united states minor outlying islands",
77f4fa2000-12-02Martin Nilsson  "us":"united states of america",
85040b2005-03-11Anders Johansson  "uy":"uruguay",
77f4fa2000-12-02Martin Nilsson  "uz":"uzbekistan",
85040b2005-03-11Anders Johansson  "va":"italy", "vc":"saint vincent and the grenadines",
77f4fa2000-12-02Martin Nilsson  "ve":"venezuela",
85040b2005-03-11Anders Johansson  "vg":"virgin islands, british", "vi":"virgin islands, u.s.",
77f4fa2000-12-02Martin Nilsson  "vn":"viet nam",
85040b2005-03-11Anders Johansson  "vu":"vanuatu", "wf":"wallis and futuna islands", "ws":"western samoa",
77f4fa2000-12-02Martin Nilsson  "ye":"yemen",
85040b2005-03-11Anders Johansson  "yt":"mayotte",
77f4fa2000-12-02Martin Nilsson  "yu":"yugoslavia",
85040b2005-03-11Anders Johansson  "za":"south africa",
77f4fa2000-12-02Martin Nilsson  "zm":"zambia",
85040b2005-03-11Anders Johansson  "zr":"zaire",
77f4fa2000-12-02Martin Nilsson  "zw":"zimbabwe",
85040b2005-03-11Anders Johansson  "com":"united states of america", "net":"united states of america", "org":"united states of america", "edu":"united states of america", "gov":"united states of america", "mil":"united states of america", "nato":"united states of america",
77f4fa2000-12-02Martin Nilsson  ]); class Legend { static private string state_color_scheme = "white-to-red"; static private mapping color_schemes = ([ "white-to-red": ([ 0:({ 0xff,0xff,0xff }), 1:({ 0xe0,0xc0,0x80 }), 2:({ 0xe0,0x80,0x40 }), 3:({ 0xd0,0x40,0x00 }), 4:({ 0x80,0x00,0x00 }) ]), "white-to-green": ([ 0:({ 0xff,0xff,0xff }), 1:({ 0xe0,0xe0,0x80 }), 2:({ 0x80,0xe0,0x40 }), 3:({ 0x40,0xd0,0x00 }), 4:({ 0x00,0x80,0x00 }) ]), "white-to-purpur": ([ 0:({ 0xff,0xff,0xff }), 1:({ 0xe0,0xc0,0xe0 }), 2:({ 0xe0,0x80,0xe0 }), 3:({ 0xd0,0x40,0xd0 }), 4:({ 0x80,0x00,0x80 }) ]) ]); object scheme(string color_scheme) { state_color_scheme = color_scheme; return this_object(); } array(string) schemes() { return sort(indices(color_schemes)); } array(int) color_blend(float x, array(int) c1, array(int) c2) { array(int) c = allocate(3); for(int i = 0; i < 3; i++) c[i] = (int) ((1.0-x)*c1[i] + x*c2[i]); return c; } array(int) color_scale(float x, string|void color_scheme) { if(x < 0.0 | x > 1.0) ERR(sprintf("Value of the scale (%f).", x)); color_scheme = color_scheme || state_color_scheme; if(x == 0 || x == 0.0) return color_schemes[color_scheme][0]; float adj = (float)sizeof(color_schemes[color_scheme])-2.01; int i = (int)(x*adj); return color_blend(x*adj-(float)i, color_schemes[color_scheme][i+1], color_schemes[color_scheme][i+2]); } string float_to_eng(float x) { array(string) suffix = ({ "a", "f", "p", "n", "u", "m", "", "k", "M", "G", "T", "P", "E" }); float y = floor(log(x)/log(1000.0)); if((0.1 <= x && x <= 1.0) || y < -6.0 || 6.0 < y) y = 0.0; return sprintf("%g%s", x/exp(y*log(1000.0)), suffix[(int)y+6])-" "; } object image(int fixed_width, int fixed_height, mapping|void opt) { opt = opt || ([]); for(int i = 0; i < sizeof(opt->titles||({})); i++) if(floatp(opt->titles[i]) || intp(opt->titles[i])) opt->titles[i] = float_to_eng((float)opt->titles[i]); opt->color_scheme = opt->color_scheme || state_color_scheme; opt->border = opt->border || 20; opt->title = opt->title || ""; opt->title_color = opt->title_color || ({ 0xff,0xff,0xff }); opt->background_color = opt->background_color || ({ 0x10,0x10,0x40 }); opt->titles = ({ "1" })+ (opt->titles || ({ "" })); object font = opt->font; // Image.font("default"); int nom = font->height(); int title_h = nom*sizeof(opt->title/"\n")+nom/2; int bar_h = 6*nom; int width = max(font->text_extents(@opt->title/"\n")[0], font->text_extents(@opt->titles)[0] + nom+nom/2); int height = title_h + bar_h + 2*nom + nom; object img = Image.image(width, height+100, @opt->background_color); img->paste_alpha_color(font->write(@(opt->title/"\n")), @opt->title_color, 0, 0); for(int i = 0; i < bar_h; i++) img->line(0, title_h+i, nom, title_h+i, @color_scale(1.0 - i/(float)(bar_h), opt->color_scheme)); img->box(0, title_h+bar_h+nom/2, nom, title_h+bar_h+nom/2+(int)(nom*0.8), @color_scale(0, opt->color_scheme)); img->paste_alpha_color(font->write("0")->scale(0.8), @opt->title_color, nom+nom/2, title_h+bar_h+nom/2); for(int i = 0; i < sizeof(opt->titles); i++) { int y = title_h + ((bar_h-1)*i)/((sizeof(opt->titles)-1)||1); img->paste_alpha_color(font->write(reverse(opt->titles)[i])->scale(0.8), @opt->title_color, nom+nom/2, y-(int) (0.8*nom/2)); } img = img->autocrop()->setcolor(@opt->background_color); img = img->copy(-opt->border, -opt->border, img->xsize()+opt->border-1, img->ysize()+opt->border-1); return img->scale(min(min(fixed_width/(float)img->xsize(), 1.0), min(fixed_height/(float)img->ysize(), 1.0))); } } static private mapping map_of_the_earth =
b11af32000-12-02Martin Nilsson  decode_value(Stdio.read_bytes("etc/maps/worldmap"));
77f4fa2000-12-02Martin Nilsson  class Earth { static string state_region; static string state_country; // Aliases. mapping(string:array(string)) country_name_aliases = ([ "United States of America":({ "USA", "US" }), "Russian Federation":({ "Russia" }), "England":({ "United Kingdom", "UK" }), "Viet Nam":({ "Vietnam" }), ]); // Official names. mapping(string:string) official_country_names = ([ "Iran":"Iran (Islamic Republic of)", "England":"United Kingdom of Great Britain and Northern Ireland", "Tanzania":"United Republic of Tanzania", "Libya":"Libyan Arab Jamahiriya", "North Korea":"Democratic People's Republic of Korea", "Syria":"Syrian Arab Republic", "Laos":"Lao People's Democratic Republic", "South Korea":"Republic of Korea" ]); object region(string new_region) { return object_program(this_object())(new_region, state_country); } array(string) regions() { return sort(({ "World", "Europe", "Asia", "Africa", "Arab States", "North America", "South America", "Oceania" })); } object country(string new_country) { return object_program(this_object())(state_region, new_country); } static private string capitalize_country(string s) { return Array.map(s/" ", lambda(string w) { switch(w) { case "of": case "and": return w; default: return capitalize(w); } })*" "; } array(string) countries() { return sort(Array.map(indices(map_of_the_earth), capitalize_country)); } mixed polygons() { if(state_country) return map_of_the_earth[state_country]; } static private array(float) transform(float x, float y, mapping opt) { y = 1.0-y; switch(lower_case(opt->region||state_region||"")) { case "europe": x = (x-0.33)*3.0; y = (y-0.05)*3.0; break; case "africa": x = (x-0.20)*1.5; y = (y-0.25)*1.5; break; case "arab states": x = (x-0.46)*3.0; y = (y-0.20)*3.0; break; case "north america": x = (x-0.00)*2.0; y = (y-0.05)*2.0; break; case "south america": x = (x-0.00)*1.5; y = (y-0.40)*1.5; break;
f917e42001-10-15Anders Johansson  case "asia":
77f4fa2000-12-02Martin Nilsson  x = (x-0.57)*2.0; y = (y-0.17)*2.0; break; case "oceania": x = (x-0.63)*2.0; y = (y-0.47)*2.0; break; default: } return ({ x, y }); } object image(int width, int height, mapping|void opt) { opt = opt || ([]); opt->color_sea = opt->color_sea || ({ 0x10,0x10,0x40 }); opt->color_fu = opt->color_fu || lambda() { return ({ 0xff,0xff,0xff }); }; Image.image map = Image.image(width, height, @opt->color_sea); foreach(indices(map_of_the_earth), string cntry) { map->setcolor(@opt->color_fu(cntry, @(opt->fu_args||({})))); foreach(map_of_the_earth[cntry], array(float) original_vertices) { array(float) vertices = copy_value(original_vertices); for(int v = 0; v < sizeof(vertices); v += 2) { array(float) a = transform(vertices[v+0], vertices[v+1], opt); vertices[v+0] = a[0]*width; vertices[v+1] = a[1]*height; } map->polyfill(vertices); } } // Add markers if(opt->markers) foreach(opt->markers, mapping marker) { int x1 = marker->x - marker->size/2; int x2 = marker->x + marker->size/2; int y1 = marker->y - marker->size/2; int y2 = marker->y + marker->size/2; switch(marker->style) { case "box": map->box(x1, y1, x2, y2, @marker->color); case "diamond": default: map->setcolor(@marker->color); map->polyfill( ({ x1, marker->y, marker->x, y1, x2, marker->y, marker->x, y2 }) ); } } // Apply borders. if(opt->border) map = Image.image(map->xsize()+2*opt->border, map->ysize()+2*opt->border, @opt->color_sea)->paste(map, opt->border, opt->border); return map; } void create(void|string _state_region, void|string _state_country) { state_region = _state_region; state_country = _state_country; } }