2024-08-27 20:54:22 +02:00
# -------------------------------------------------------------------
# ORTHOGRAPHIC
# Your personal aerial satellite. Always on. At any altitude.*
# Developed by MarStrMind
2024-08-27 21:55:25 +02:00
# License: Open Software License 3.0
2024-08-27 20:54:22 +02:00
# Up to date version always on marstr.online
# -------------------------------------------------------------------
# maskgen.py
# The class that generates a mask of the layer it was asked to do.
# This mask will then be used to generate a photo layer, which in
# turn is then used to construct the final photo. It can be argued
# that this part of the code is the most crucial one, as the other
# classes involved rely on what this code is doing, and by extension,
# generating.
#
# The PNG generated will be used in this progression:
# - Generate mask from OSM (here)
# - Generate colored photo layer from this mask, for example for
# landuse: forest
# - Compile actual satellite aerial
# -------------------------------------------------------------------
import math
from osmxml import *
from defines import *
from log import *
from PIL import Image , ImageFilter , ImageDraw , ImagePath
2024-08-29 22:46:49 +02:00
from random import randrange
import random
2024-08-27 20:54:22 +02:00
class mstr_maskgen :
# Initializes the class with some required variables
# Much of this code is adjusted to work within a class.
def __init__ ( self , box , vstep , tag , value , isline , subtag = None , subvalue = None ) :
self . _box = box
self . _tag = tag
self . _subtag = subtag
self . _subvalue = subvalue
self . _value = value
self . _vstep = vstep
self . _scale = 1 / math . cos ( math . radians ( self . _box [ 0 ] ) )
self . _isline = isline
2024-09-02 08:03:45 +02:00
#mstr_msg("maskgen", "Intialized mask gen.")
2024-08-27 20:54:22 +02:00
# Projects a point into the canvas of the mask.
# Final projection depends on positive or negative latitude or longitude.
def project_pixel ( self , pnt , edge ) :
pdiff = edge - pnt
byT = pdiff * 1000
divisor = byT / 16
return divisor
# Extract lat/lng from custom extracted nodes block
def latlong_from_id ( self , id , nds ) :
latlng = [ ]
for i in nds :
if i [ 0 ] == id :
#latlng.append((float(i[1]), float(i[2])))
latlng . append ( float ( i [ 1 ] ) )
latlng . append ( float ( i [ 2 ] ) )
break
return latlng
# Builds the required mask
def _build_mask ( self ) :
# Generate empty image
imgsize = 0
if mstr_photores == 2048 : imgsize = 3000
if mstr_photores == 4096 : imgsize = 6000
mask_img = Image . new ( " RGBA " , ( imgsize , imgsize ) )
2024-09-03 20:49:35 +02:00
tilexml = mstr_datafolder + " _cache/tile.xml "
2024-08-27 20:54:22 +02:00
xml = mstr_osmxml ( 0 , 0 )
fstr = str ( self . _box [ 0 ] ) + " - " + str ( self . _box [ 1 ] ) + " _ " + str ( self . _box [ 2 ] ) + " - " + str ( self . _box [ 3 ] )
nds = xml . acquire_nodes ( tilexml )
way = xml . acquire_waypoint_data ( tilexml )
rls = xml . acquire_relations ( tilexml )
2024-09-02 08:03:45 +02:00
mstr_msg ( " maskgen " , " Building mask for " + str ( self . _box [ 0 ] ) + " - " + str ( self . _box [ 1 ] ) + " , " + str ( self . _box [ 2 ] ) + " - " + str ( self . _box [ 3 ] ) + " , for " + self . _tag + " : " + self . _value )
2024-08-27 20:54:22 +02:00
frs = [ ]
# Calculate actual bounding box
bbox = [ ]
# Latitude
bbox . append ( self . _box [ 0 ] + ( ( self . _box [ 1 ] - 1 ) * self . _vstep ) )
bbox . append ( self . _box [ 0 ] + ( ( self . _box [ 1 ] - 1 ) * self . _vstep ) + self . _vstep )
# Longitude
bbox . append ( self . _box [ 2 ] + ( ( self . _box [ 3 ] - 1 ) * mstr_zl_18 ) )
bbox . append ( self . _box [ 2 ] + ( ( self . _box [ 3 ] - 1 ) * mstr_zl_18 ) + mstr_zl_18 )
# Generate mask for ONE tag only
if self . _subtag == None :
for w in way :
if w [ 2 ] == self . _tag and w [ 3 ] == self . _value :
nd = [ ]
for d in way :
if d [ 0 ] == w [ 0 ] :
nd . append ( d [ 1 ] )
frs . append ( nd )
# Scout through relations as these also make up map data
for r in rls :
if self . _tag in r [ 1 ] and self . _value in r [ 1 ] :
nd = [ ]
for w in way :
if int ( w [ 0 ] ) == int ( r [ 0 ] ) :
nd . append ( w [ 1 ] )
frs . append ( nd )
# Generate mask for one tag, PLUS a subtag. This is mostly used for admin areas
if self . _subtag != None :
nd = [ ]
wids = [ ]
for w in way :
if w [ 2 ] == self . _tag and w [ 3 ] == self . _value :
wids . append ( w [ 0 ] )
for w in wids :
for wp in way :
if wp [ 0 ] == w and wp [ 2 ] == self . _subtag and wp [ 3 ] in self . _subvalue :
for d in way :
if d [ 0 ] == wp [ 0 ] and d [ 1 ] != " NULL " :
nd . append ( d [ 1 ] )
frs . append ( nd )
# Project all pixels
for f in frs :
pts = [ ]
for a in f :
latlng = self . latlong_from_id ( a , nds )
if len ( latlng ) == 2 :
# For some reason, sometimes the array is empty. Make sure we have two data points.
if len ( latlng ) == 2 :
# Project the pixel, and add to the polygon shape.
p_lat = self . project_pixel ( latlng [ 0 ] , bbox [ 1 ] )
p_lng = self . project_pixel ( latlng [ 1 ] , bbox [ 3 ] )
pixlat = 0
pixlng = 0
pr = 0
if mstr_photores == 2048 : pr = 3000
if mstr_photores == 4096 : pr = 6000
# Draw pixels in direction according to latitude and longitude positions -
# Latitude:
if self . _box [ 0 ] > 0 :
pixlat = int ( ( imgsize * self . _scale ) * p_lat )
if self . _box [ 0 ] < 0 :
pixlat = pr - ( int ( ( imgsize * self . _scale ) * p_lat ) )
# Longitude:
if self . _box [ 2 ] > 0 :
pixlng = int ( imgsize - ( imgsize * p_lng ) )
if self . _box [ 2 ] < 0 :
pixlng = pr - ( int ( imgsize - ( imgsize * p_lng ) ) )
pts . append ( ( pixlng , pixlat ) )
# Corel Draw!
imgd = ImageDraw . Draw ( mask_img )
# Draw polygons for everything except those three tags
if self . _isline == False :
if len ( pts ) > = 3 :
imgd . polygon ( pts , fill = " #000000 " )
# For road specific items, draw lines instead
if self . _isline == True :
if len ( pts ) > = 2 : # Only need two points to form a line
idx = 0
for i in range ( len ( mstr_ortho_layers ) ) :
if mstr_ortho_layers [ i ] [ 0 ] == self . _tag and mstr_ortho_layers [ i ] [ 1 ] == self . _value :
idx = i
break
2024-08-29 22:46:49 +02:00
imgd . line ( pts , fill = " #000000 " , width = mstr_ortho_layers [ idx ] [ 2 ] , joint = " curve " )
2024-08-27 20:54:22 +02:00
# Save image
2024-09-03 20:49:35 +02:00
mask_img . save ( mstr_datafolder + " _cache/ " + fstr + " _ " + self . _tag + " - " + self . _value + " .png " )
2024-08-27 20:54:22 +02:00
# Inform
2024-09-02 08:03:45 +02:00
mstr_msg ( " maskgen " , " Mask built. " )
2024-09-02 15:15:16 +02:00
2024-09-03 15:57:58 +02:00