forked from 0x2620/oxjs
keep example ids and titles in sync
This commit is contained in:
parent
49c30cfe38
commit
422258448e
14 changed files with 2 additions and 2 deletions
191
examples/maps/ipv4_map_of_the_internet/txt/ipv4map.py.txt
Normal file
191
examples/maps/ipv4_map_of_the_internet/txt/ipv4map.py.txt
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
# ipv4map.py - no copyright 2011 0x2620.org - public domain
|
||||
|
||||
from __future__ import division
|
||||
import Image
|
||||
import ImageDraw
|
||||
import math
|
||||
import os
|
||||
import ox
|
||||
import pygeoip
|
||||
|
||||
# fixme: pow(a, b) -> a ** b
|
||||
|
||||
geoip = pygeoip.GeoIP('../dat/GeoLiteCity.dat', pygeoip.MEMORY_CACHE)
|
||||
path = '../../../../oxjs.org/source/Ox.Geo/png/flags/'
|
||||
projection = {
|
||||
'U': [[0, 2, 3, 1], 'DUUC'], # Square 0 1 Segment U = 0 3 = 0 1 E F = D C
|
||||
'D': [[0, 1, 3, 2], 'UDDA'], # 2 3 1 2 3 2 D C U U
|
||||
'C': [[3, 2, 0, 1], 'ACCU'], # 4 7 8 B
|
||||
'A': [[3, 1, 0, 2], 'CAAD'] # 5 6 9 A
|
||||
}
|
||||
|
||||
def get_country_code_by_ip(ip):
|
||||
replace = {'A1': 'NTHH', 'A2': 'NTHH', 'AN': 'ANHH', 'AP': 'FM', 'O1': 'NTHH'}
|
||||
data = geoip.record_by_addr(ip) if not ip.startswith('0.') else None
|
||||
country_code = data['country_code'] if data and 'country_code' in data else 'NTHH'
|
||||
return replace[country_code] if country_code in replace else country_code
|
||||
|
||||
def get_flag_image(county_code, size):
|
||||
flag_size = str(int(pow(4, math.ceil(math.log(size, 2) / 2))))
|
||||
flag_image = Image.open(path + flag_size + '/' + county_code + '.png')
|
||||
if size != flag_size:
|
||||
flag_image = flag_image.resize((size, size), Image.ANTIALIAS)
|
||||
return flag_image
|
||||
|
||||
def get_ip_by_n(n):
|
||||
ip = []
|
||||
for i in range(4):
|
||||
ip.append(str(int(n / pow(256, 3 - i)) % 256))
|
||||
return '.'.join(ip)
|
||||
|
||||
def get_n_by_ip(ip):
|
||||
n = 0
|
||||
for i, v in enumerate(ip.split('.')):
|
||||
n += int(v) * pow(256, 3 - i)
|
||||
return n
|
||||
|
||||
def get_tile_by_ip(ip, z):
|
||||
n = get_n_by_ip(ip)
|
||||
last_n = n + pow(4, 16 - z) - 1
|
||||
last_ip = get_ip_by_n(last_n)
|
||||
return '../png/tiles/%s/%s-%s.png' % (ip.split('.')[0], ip, last_ip)
|
||||
|
||||
def get_xy_by_ip(ip, z, w='U'):
|
||||
x, y = 0, 0
|
||||
n = int(get_n_by_ip(ip) / pow(4, 8 - z))
|
||||
for i in range(8 + z):
|
||||
p2 = pow(2, 7 + z - i)
|
||||
p4 = pow(4, 7 + z - i)
|
||||
q = int(n / p4)
|
||||
xy = projection[w][0][q]
|
||||
x += xy % 2 * p2
|
||||
y += int(xy / 2) * p2
|
||||
n -= q * p4
|
||||
w = projection[w][1][q]
|
||||
return [x, y]
|
||||
|
||||
def render_flags():
|
||||
# renders an image of 256 flags
|
||||
image = Image.new('RGB', (1024, 1024))
|
||||
font = '../ttf/DejaVuSansMonoBold.ttf'
|
||||
countries = ox.file.read_json('../../../../oxjs.org/oxjs/source/Ox.Geo/json/Ox.Geo.json')
|
||||
countries = filter(lambda x: len(x['code']) == 2 and not x['code'] in ['UK', 'XK'], countries)
|
||||
for i, country in enumerate(sorted(countries, key=lambda x: x['code'])):
|
||||
flag = get_flag_image(country['code'], 64)
|
||||
x, y = i % 16 * 64, int(i / 16) * 64
|
||||
image.paste(flag, (x, y, x + 64, y + 64))
|
||||
ox.image.drawText(image, (x + 5, y + 5), country['code'], font, 8, (64, 64, 64))
|
||||
ox.image.drawText(image, (x + 4, y + 4), country['code'], font, 8, (192, 192, 192))
|
||||
image.save('../png/flags.png')
|
||||
|
||||
def render_map():
|
||||
# renders images of the full map
|
||||
if not os.path.exists('../png/ipv4map16.png'):
|
||||
mapfile = '../png/ipv4map16384.png'
|
||||
mapimage = Image.new('RGB', (16384, 16384))
|
||||
for a in range(0, 256, 16):
|
||||
print '%d.0.0.0' % a
|
||||
image = Image.open('../png/map/%d.0.0.0-%d.255.255.255.png' % (a, a + 15))
|
||||
x, y = map(lambda x: int(x / 4096) * 4096, get_xy_by_ip('%d.0.0.0' % a, 6))
|
||||
mapimage.paste(image.resize((4096, 4096), Image.ANTIALIAS), (x, y))
|
||||
mapimage.save(mapfile)
|
||||
for s in [4096, 1024, 16]:
|
||||
mapimage.resize((s, s), Image.ANTIALIAS).save(mapfile.replace('16384', str(s)))
|
||||
|
||||
def render_square(values, maxlen, w):
|
||||
# recursively renders a square region, given a list of country codes
|
||||
length = len(values)
|
||||
if length > 4:
|
||||
square_length = int(length / 4)
|
||||
square_values = map(lambda x: values[x * square_length:(x + 1) * square_length], range(4))
|
||||
values = []
|
||||
for i, v in enumerate(square_values):
|
||||
values.append(render_square(v, maxlen, projection[w][1][i]))
|
||||
equal = values[0] == values[1] == values[2] == values[3]
|
||||
if length < maxlen and equal:
|
||||
return values[0]
|
||||
else:
|
||||
order = projection[w][0]
|
||||
image_size = int(math.sqrt(length) * 16)
|
||||
flag_size = image_size if equal else int(image_size / 2)
|
||||
image = Image.new('RGB', (image_size, image_size))
|
||||
for i, value in enumerate([values[0]] if equal else values):
|
||||
flag = get_flag_image(value, flag_size) if isinstance(value, str) else value
|
||||
image.paste(flag, (order[i] % 2 * flag_size, int(order[i] / 2) * flag_size))
|
||||
if length == pow(4, 4):
|
||||
image.save('../png/_tmp/' + str(values) + '.png')
|
||||
return image
|
||||
|
||||
def render_tile(ip, z):
|
||||
# recursively renders the map tile for a given ip at a given zoom level
|
||||
n = get_n_by_ip(ip)
|
||||
file = get_tile_by_ip(ip, z)
|
||||
if not os.path.exists(file):
|
||||
tiles_n = map(lambda x: n + x * pow(4, 15 - z), range(4))
|
||||
tiles_ip = map(lambda x: get_ip_by_n(x), tiles_n)
|
||||
tiles = map(lambda x: render_tile(x, z + 1), tiles_ip)
|
||||
image = Image.new('RGB', (256, 256))
|
||||
x, y = map(lambda x: int(x / 256) * 256, get_xy_by_ip(ip, z))
|
||||
for i in range(4):
|
||||
x_, y_ = map(lambda x: int(x / 128) * 128, get_xy_by_ip(tiles_ip[i], z))
|
||||
image.paste(tiles[i].resize((128, 128), Image.ANTIALIAS), (x_ - x, y_ - y))
|
||||
image.save(file)
|
||||
else:
|
||||
image = Image.open(file)
|
||||
return image
|
||||
|
||||
def render_tiles():
|
||||
# renders all tiles at the maximum zoom level
|
||||
w = ''
|
||||
for v in projection['U'][1]:
|
||||
w += projection[v][1]
|
||||
file256 = '../png/ipv4map16384.png'
|
||||
for a in range(256):
|
||||
print '%d.0.0.0' % a
|
||||
if a % 16 == 0:
|
||||
values = []
|
||||
file = '../png/map/%d.0.0.0-%d.255.255.255.png' % (a, a + 15)
|
||||
if not os.path.exists(file):
|
||||
for b in range(256):
|
||||
for c in range(256):
|
||||
values.append(get_country_code_by_ip('%d.%d.%d.0' % (a, b, c)))
|
||||
if a % 16 == 15:
|
||||
image = render_square(values, len(values), w[int(a / 16)]).save(file)
|
||||
if a % 16 == 15:
|
||||
image = Image.open(file)
|
||||
for a_ in range(a - 15, a + 1):
|
||||
for b in range(256):
|
||||
file = '../png/tiles/%d/%d.%d.0.0-%d.%d.255.255.png' % (a_, a_, b, a_, b)
|
||||
if not os.path.exists(file):
|
||||
x, y = map(lambda x: int(x % 16384 / 256) * 256, get_xy_by_ip('%d.%d.0.0' % (a_, b), 8))
|
||||
dirs = os.path.split(file)[0]
|
||||
if dirs and not os.path.exists(dirs):
|
||||
os.makedirs(dirs)
|
||||
image.crop((x, y, x + 256, y + 256)).save(file)
|
||||
|
||||
def render_projection():
|
||||
# renders an image of the map projection
|
||||
image = Image.new('RGB', (1024, 1024))
|
||||
draw = ImageDraw.Draw(image)
|
||||
font = '../ttf/DejaVuSansCondensedBold.ttf'
|
||||
for i in range(256):
|
||||
x, y = map(lambda x: int(x / 64) * 64, get_xy_by_ip('%d.0.0.0' % i, 2))
|
||||
rgb = ox.getRGB((i * 360 / 256, 1, 0.5))
|
||||
draw.rectangle((x, y, x + 64, y + 64), fill=rgb)
|
||||
ox.image.drawText(image, (x + 4, y + 4), str(i), font, 8, (0, 0, 0))
|
||||
draw.rectangle((x + 30, y + 30, x + 34, y + 33), fill=0)
|
||||
if i:
|
||||
draw.line((x_ + 32, y_ + 32, x + 32, y + 32), fill=0, width=4)
|
||||
x_, y_ = x, y
|
||||
image.save('../png/projection.png')
|
||||
|
||||
if __name__ == '__main__':
|
||||
# qlmanage -t -s 16384 -o . ../../../../oxjs.org/tools/geo/svg/icons/NTHH.svg
|
||||
render_flags()
|
||||
render_projection()
|
||||
render_tiles()
|
||||
render_tile('0.0.0.0', 0)
|
||||
render_map()
|
||||
|
||||
|
||||
# http://s3.amazonaws.com/alexa-static/top-1m.csv.zip
|
||||
Loading…
Add table
Add a link
Reference in a new issue