]> marstr Code Repo - orthographic/commitdiff
Milestone commit - switch to mostly in-memory management, and functioning multi-proce...
authorMarcus Str. <marcus@marstr.online>
Sat, 16 Nov 2024 14:20:00 +0000 (15:20 +0100)
committerMarcus Str. <marcus@marstr.online>
Sat, 16 Nov 2024 14:20:00 +0000 (15:20 +0100)
defines.py
layergen.py
maskgen.py
og.py
orthographic.py
photogen.py
repoinfo
xp_normalmap.py

index e9553caacc69ce463afbd74d79615a4657aad29a..dea842cb9d0ed7a2c56d2a15c384167bb8425887 100644 (file)
@@ -148,7 +148,6 @@ mstr_ortho_layers = [
     ("highway", "tertiary", 20),\r
     ("highway", "unclassified", 17),\r
     ("highway", "living_street", 12),\r
-    ("waterway", "river", 10),\r
     ("waterway", "stream", 2),\r
     ("amenity", "parking", "amenity", "parking"),\r
     ("amenity", "school", "amenity", "school"),\r
@@ -162,12 +161,8 @@ mstr_ortho_layers = [
     ("natural", "sand", "natural", "sand"),\r
     ("natural", "desert", "natural", "desert"),\r
     # Z-Order 3\r
-    ("natural", "water", "natural", "water"),\r
     ("natural", "bay", "natural", "beach"),\r
     ("natural", "beach", "natural", "beach"),\r
-    ("water", "lake", "natural", "water"),\r
-    ("water", "pond", "natural", "water"),\r
-    ("water", "river", "natural", "water"),\r
     ("leisure", "swimming_pool", "natural", "water"),\r
     ("highway", "pedestrian", 4),\r
     # Z-Order 4\r
@@ -195,6 +190,11 @@ mstr_ortho_layers = [
     ("building", "public", "building", "public"),\r
     ("building", "commercial", "building", "commercial"),\r
     ("building", "yes", "building", "common"),\r
+    ("water", "lake", "natural", "water"),\r
+    ("water", "pond", "natural", "water"),\r
+    ("water", "river", "natural", "water"),\r
+    ("natural", "water", "natural", "water"),\r
+    ("waterway", "river", 10),\r
     ("place", "sea", "natural", "sea"),\r
     ("place", "ocean", "natural", "sea")\r
 ]\r
@@ -229,10 +229,10 @@ mstr_mask_blur = [
     ("landuse", "farmland", 10),\r
     ("landuse", "farmyard", 10),\r
     # Z-Order 2\r
-    ("landuse", "forest", 8),\r
-    ("leisure", "nature_reserve", 8),\r
-    ("natural", "wood", 8),\r
-    ("natural", "tree_row", 8),\r
+    ("landuse", "forest", 10),\r
+    ("leisure", "nature_reserve", 10),\r
+    ("natural", "wood", 10),\r
+    ("natural", "tree_row", 10),\r
     ("landuse", "military", 15),\r
     # Z-Order 3\r
     ("natural", "bare_rock", 25),\r
index 6c02f9b1d846124703e7dfa5d36d12023e25b503..21520ce04b44a1557bebc0341fb8e7449dcde27b 100644 (file)
@@ -114,27 +114,63 @@ class mstr_layergen:
         return layer_final\r
 \r
 \r
+    # Find the source to use pre-determined in phase one\r
+    def findLayerSource(self):\r
+        # The source number\r
+        src = -1\r
+\r
+        # The already existing source data\r
+        srcfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(self._lng_number)\r
+\r
+        # Let's open the file and find our entry\r
+        with open(srcfile) as file:\r
+            for line in file:\r
+                linedata = line.split(" ")\r
+                if linedata[2] == self._tag and linedata[3] == self._value:\r
+                    src = int(linedata[4])\r
+                    break\r
+        \r
+        # Should we encounter a -1 at this point, we can choose something\r
+        # It means it touches no border as it was not found in the file\r
+        if src == -1:\r
+            root_folder = mstr_datafolder + "textures/"\r
+            for s in mstr_ortho_layers:\r
+                if s[0] == self._tag and s[1] == self._value:\r
+                    fld_main = len(s)-2\r
+                    fld_sub  = len(s)-1\r
+                    root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]\r
+            \r
+            brd = glob.glob(root_folder + "/brd/b*.png")\r
+            src = randrange(1, len(brd)+1)\r
+\r
+        return src\r
+\r
+\r
+\r
     # This generates the layer from the defined mask\r
-    def genlayer(self):\r
+    def genlayer(self, mask, xml):\r
 \r
         mstr_msg("layergen", "Layer to be generated: " + str(self._latitude) + "-" + str(self._lat_number) + ":" + str(self._longitude) + "-" + str(self._lng_number) + " -- tag: " + self._tag + " - value: " + self._value )\r
 \r
         # Before we generate the layer, let's check for airports in this chunk\r
         mstr_msg("layergen", "Checking for airport/s with ICAO code")\r
-        osmxml = mstr_osmxml(0,0)\r
-        icao = osmxml.find_icao_codes(mstr_datafolder + "_cache/tile.xml")\r
-        mstr_msg("layergen", "Found " + str(len(icao)) + " airport/s")\r
+        \r
+        icao = None\r
+        if xml != None:\r
+            icao = xml.find_icao_codes()\r
+            mstr_msg("layergen", "Found " + str(len(icao)) + " airport/s")\r
         # Runway surface, if any other than concrete/asphalt\r
         rw_surface = ""\r
         # If we find an airport, make a note ...\r
-        if len(icao) >= 1:\r
-            #for i in icao:\r
-                # ... but only, if this airport is not already noted\r
-                #iccheck = self._tiledb.perform_query("SELECT * FROM airports WHERE icao='" + i +"';")\r
-                #if len(iccheck) == 0:\r
-                    #self._tiledb.insert_icao(i, self._lat_number, self._lng_number, self._latitude, self._longitude)\r
-                #    mstr_msg("layergen", "Airport/s noted in data file")\r
-            rw_surface = osmxml.find_runway_surface(mstr_datafolder + "_cache/tile.xml")\r
+        if icao != None:\r
+            if len(icao) >= 1 and self._is_completion == False:\r
+                #for i in icao:\r
+                    # ... but only, if this airport is not already noted\r
+                    #iccheck = self._tiledb.perform_query("SELECT * FROM airports WHERE icao='" + i +"';")\r
+                    #if len(iccheck) == 0:\r
+                        #self._tiledb.insert_icao(i, self._lat_number, self._lng_number, self._latitude, self._longitude)\r
+                    #    mstr_msg("layergen", "Airport/s noted in data file")\r
+                rw_surface = xml.find_runway_surface()\r
 \r
         # The image for the layer itself\r
         layer = Image.new("RGBA", (self._imgsize, self._imgsize))\r
@@ -153,176 +189,7 @@ class mstr_layergen:
                     root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]\r
 \r
             # Determine which sources to use.\r
-            # First, we need to check for adjacent tile information. We then either\r
-            # need to use the source of any adjacent tile, or we can choose freely.\r
-            src = -1\r
-            \r
-            # Find our adjacent tiles\r
-            adjtiles = findAdjacentTilesTo(self._lat_number, self._lng_number)\r
-\r
-            mstr_msg("layergen", "Performing adjacency check")\r
-            # Walk through each tile and see what we can find in relation to this\r
-            # tile in the center\r
-            # Since we already know the order in adjtiles, we can do this real easy\r
-            if self._is_completion == False:\r
-                at = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[0][0], adjtiles[0][1], self._tag, self._value) # Top\r
-                ar = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[1][0], adjtiles[1][1], self._tag, self._value) # Right\r
-                ab = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[2][0], adjtiles[2][1], self._tag, self._value) # Bottom\r
-                al = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[3][0], adjtiles[3][1], self._tag, self._value) # Left\r
-                #at = self._tiledb.get_adjacency_for_source(adjtiles[0][0], adjtiles[0][1], self._tag, self._value) # Top\r
-                #ar = self._tiledb.get_adjacency_for_source(adjtiles[1][0], adjtiles[1][1], self._tag, self._value) # Right\r
-                #ab = self._tiledb.get_adjacency_for_source(adjtiles[2][0], adjtiles[2][1], self._tag, self._value) # Bottom\r
-                #al = self._tiledb.get_adjacency_for_source(adjtiles[3][0], adjtiles[3][1], self._tag, self._value) # Left\r
-            if self._is_completion == True:\r
-                at = self._tileinfo.get_adjacency_for_completion(adjtiles[0][0], adjtiles[0][1]) # Top\r
-                ar = self._tileinfo.get_adjacency_for_completion(adjtiles[1][0], adjtiles[1][1]) # Right\r
-                ab = self._tileinfo.get_adjacency_for_completion(adjtiles[2][0], adjtiles[2][1]) # Bottom\r
-                al = self._tileinfo.get_adjacency_for_completion(adjtiles[3][0], adjtiles[3][1]) # Left\r
-                #at = self._tiledb.get_adjacency_for_completion(adjtiles[0][0], adjtiles[0][1]) # Top\r
-                #ar = self._tiledb.get_adjacency_for_completion(adjtiles[1][0], adjtiles[1][1]) # Right\r
-                #ab = self._tiledb.get_adjacency_for_completion(adjtiles[2][0], adjtiles[2][1]) # Bottom\r
-                #al = self._tiledb.get_adjacency_for_completion(adjtiles[3][0], adjtiles[3][1]) # Left\r
-\r
-                if len(at) == 4:\r
-                    self._tag   = at[0]\r
-                    self._value = at[1]\r
-                if len(ar) == 4:\r
-                    self._tag   = ar[0]\r
-                    self._value = ar[1]\r
-                if len(ab) == 4:\r
-                    self._tag   = ab[0]\r
-                    self._value = ab[1]\r
-                if len(al) == 4:\r
-                    self._tag   = al[0]\r
-                    self._value = al[1]\r
-\r
-                root_folder = mstr_datafolder + "textures/"\r
-                for s in mstr_ortho_layers:\r
-                    if s[0] == self._tag and s[1] == self._value:\r
-                        fld_main = len(s)-2\r
-                        fld_sub  = len(s)-1\r
-                        root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]\r
-\r
-            # We are south to the top tile.\r
-            if len(at) == 2 and src == -1:\r
-                if "b" in at[1]: src = at[0]\r
-            # We are west to the right tile.\r
-            if len(ar) == 2 and src == -1:\r
-                if "l" in ar[1]: src = ar[0]\r
-            # We are north to the bottom tile.\r
-            if len(ab) == 2 and src == -1:\r
-                if "t" in ab[1]: src = ab[0]\r
-            # We are east to the left tile.\r
-            if len(al) == 2 and src == -1:\r
-                if "r" in al[1]: src = al[0]\r
-\r
-            # Should we be at the border of the degree for latitude and longitude, we need to perform\r
-            # additional checks\r
-            is_deg_brd_t = False\r
-            is_deg_brd_r = False\r
-            is_deg_brd_b = False\r
-            is_deg_brd_l = False\r
-            if self._lat_number == 1: is_deg_brd_b = True\r
-            if self._lat_number == self._maxlat: is_deg_brd_t = True\r
-            if self._lng_number == 1: is_deg_brd_l = True\r
-            if self._lng_number == self._maxlng: is_deg_brd_r = True\r
-\r
-            # Adjacent latitude and longitude tiles\r
-            deg_tiles = []\r
-            deg_tiles.append( ( self._latitude+1, self._longitude ) ) # Top\r
-            deg_tiles.append( ( self._latitude, self._longitude+1 ) ) # Right\r
-            deg_tiles.append( ( self._latitude-1, self._longitude ) ) # Bottom\r
-            deg_tiles.append( ( self._latitude, self._longitude-1 ) ) # Left\r
-\r
-            # Perform degree border checks\r
-            # - and make sure we do not run into errors - this drove me crazy in testing\r
-            atd = []\r
-            ard = []\r
-            abd = []\r
-            ald = []\r
-            if is_deg_brd_t == True:\r
-                if self._is_completion == False:\r
-                    atd = self._tileinfo.get_adjacency_for_tag_and_value_in_lat_lng(deg_tiles[0][0], deg_tiles[0][1], self._tag, self._value, 1, self._lng_number, "b") # Top\r
-                    #atd = self._tiledb.get_adjacency_for_source_in_lat_lng(deg_tiles[0][0], deg_tiles[0][1], 1, self._lng_number, self._tag, self._value) # Top\r
-                if self._is_completion == True:\r
-                    atd = self._tileinfo.get_completion_in_lat_lng(deg_tiles[0][0], deg_tiles[0][1], 1, self._lng_number, "b")\r
-                    #atd = self._tiledb.get_adjacency_for_completion_in_lat_lng(deg_tiles[0][0], deg_tiles[0][1], 1, self._lng_number) # Top\r
-            \r
-            if is_deg_brd_r == True:\r
-                if self._is_completion == False:\r
-                    ard = self._tileinfo.get_adjacency_for_tag_and_value_in_lat_lng(deg_tiles[1][0], deg_tiles[1][1], self._tag, self._value, self._lat_number, 1, "l") # Right\r
-                    #ard = self._tiledb.get_adjacency_for_source_in_lat_lng(deg_tiles[1][0], deg_tiles[1][1], self._lat_number, 1, self._tag, self._value) # Right\r
-                if self._is_completion == True:\r
-                    ard = self._tileinfo.get_completion_in_lat_lng(deg_tiles[1][0], deg_tiles[1][1], self._lat_number, 1, "l")\r
-                    #ard = self._tiledb.get_adjacency_for_completion_in_lat_lng(deg_tiles[1][0], deg_tiles[1][1], self._lat_number, 1) # Right\r
-            \r
-            if is_deg_brd_b == True:\r
-                #maxlatlng = self._tiledb.get_highest_latlong_from_tile(self._latitude-1, self._longitude)\r
-                if self._is_completion == False:\r
-                    abd = self._tileinfo.get_adjacency_for_tag_and_value_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._tag, self._value, self._lat_number, self._lng_number, "t")\r
-                    #abd = self._tiledb.get_adjacency_for_source_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], maxlatlng[0], self._lng_number, self._tag, self._value) # Bottom\r
-                if self._is_completion == True:\r
-                    abd = self._tileinfo.get_completion_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._lat_number, self._lng_number, "t")\r
-                    #abd = self._tiledb.get_adjacency_for_completion_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], maxlatlng[0], self._lng_number) # Bottom\r
-            \r
-            if is_deg_brd_l == True:\r
-                #maxlatlng = self._tiledb.get_highest_latlong_from_tile(self._latitude, self._longitude-1)\r
-                if self._is_completion == False:\r
-                    ald = self._tileinfo.get_adjacency_for_tag_and_value_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._tag, self._value, self._lat_number, self._lng_number, "r")\r
-                    #ald = self._tiledb.get_adjacency_for_source_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._lat_number, maxlatlng[1], self._tag, self._value) # Left\r
-                if self._is_completion == True:\r
-                    ald = self._tileinfo.get_completion_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._lat_number, self._lng_number, "r")\r
-                    #ald = self._tiledb.get_adjacency_for_completion_in_lat_lng(deg_tiles[2][0], deg_tiles[2][1], self._lat_number, maxlatlng[1]) # Left\r
-\r
-            if (is_deg_brd_t == True or is_deg_brd_r == True or is_deg_brd_b == True or is_deg_brd_l == True):\r
-                if src == -1 and self._is_completion == True:\r
-                    if len(atd) == 4:\r
-                        self._tag   = atd[0]\r
-                        self._value = atd[1]\r
-                    if len(ard) == 4:\r
-                        self._tag   = ard[0]\r
-                        self._value = ard[1]\r
-                    if len(abd) == 4:\r
-                        self._tag   = abd[0]\r
-                        self._value = abd[1]\r
-                    if len(ald) == 4:\r
-                        self._tag   = ald[0]\r
-                        self._value = ald[1]\r
-\r
-                    root_folder = mstr_datafolder + "textures/"\r
-                    for s in mstr_ortho_layers:\r
-                        if s[0] == self._tag and s[1] == self._value:\r
-                            fld_main = len(s)-2\r
-                            fld_sub  = len(s)-1\r
-                            root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]\r
-\r
-\r
-            # Should we get here and one of the degree border checks turns out true,\r
-            # we need to make sure that we select the source we found. This should\r
-            # enable seamless tiling... around the entire planet\r
-            if is_deg_brd_t == True and len(at) == 0 and src == -1:\r
-                if len(atd) == 2:\r
-                    if "b" in atd[3]: src = int(atd[2])\r
-            if is_deg_brd_r == True and len(ar) == 0 and src == -1:\r
-                if len(ard) == 2:\r
-                    if "l" in ard[3]: src = int(ard[2])\r
-            if is_deg_brd_b == True and len(ab) == 0 and src == -1:\r
-                if len(abd) == 2:\r
-                    if "t" in abd[3]: src = int(abd[2])\r
-            if is_deg_brd_l == True and len(al) == 0 and src == -1:\r
-                if len(ald) == 2:\r
-                    if "r" in ald[3]: src = int(ald[2])\r
-            \r
-            mstr_msg("layergen", "Adjacency check completed")\r
-\r
-            brd = glob.glob(root_folder + "/brd/b*.png")\r
-\r
-            # If the adjacency check returned nothing (src is still -1),\r
-            # then pick something\r
-            if src == -1:\r
-                if len(brd) == 1: src=1\r
-                if len(brd) >= 2:\r
-                    src = randrange(1, len(brd)+1)\r
+            src = self.findLayerSource()\r
             \r
             ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")\r
             \r
@@ -333,25 +200,27 @@ class mstr_layergen:
                 ptc_src.append(Image.open(p))\r
             mstr_msg("layergen", "Layer sources selected")\r
 \r
+            """\r
             # OK! Load the mask\r
             if self._is_completion == False:\r
-                osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
+                mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
             if self._is_completion == True:\r
-                osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion.png" )\r
+                mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion.png" )\r
+            """\r
             \r
             # Generate an edge mask from the original\r
-            osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)\r
+            osm_edge = mask.filter(ImageFilter.FIND_EDGES)\r
             osm_edge = osm_edge.filter(ImageFilter.MaxFilter)\r
             mstr_msg("layergen", "Edge mask generated")\r
 \r
             # This adds some natural looking shapes to these types of features\r
             if self._value == "forest" or self._value == "nature_reserve":\r
                 epx = osm_edge.load()\r
-                imgd = ImageDraw.Draw(osm_mask)\r
+                imgd = ImageDraw.Draw(mask)\r
 \r
-                # Walk through a grid of 200x200 - on the edge image\r
-                for y in range(0, osm_mask.height, int(osm_mask.height/200)):\r
-                    for x in range(0, osm_mask.width, int(osm_mask.width/200)):\r
+                # Walk through a grid of 100x100 - on the edge image\r
+                for y in range(0, mask.height, int(mask.height/100)):\r
+                    for x in range(0, mask.width, int(mask.width/100)):\r
                         px = epx[x,y]\r
                         if px[3] == 255:\r
                             rx = randrange(24,60)\r
@@ -363,7 +232,7 @@ class mstr_layergen:
                             psy = randrange(y-11, y+11)\r
                             \r
                             # Do some magic - but not on edges\r
-                            if x > 0 and x < osm_mask.width and y > 0 and y < osm_mask.height:\r
+                            if x > 0 and x < mask.width and y > 0 and y < mask.height:\r
                                 if f != 5:\r
                                     imgd.ellipse((psx-int(rx/2), psy-int(ry/2), psx+rx, psy+ry), fill="black")\r
                                 if f == 3 or f == 7:\r
@@ -372,14 +241,14 @@ class mstr_layergen:
 \r
             # We need to change the image in certain conditions\r
             if self._value == "hedge" and self._tag == "barrier":\r
-                osm_mask = osm_edge\r
+                mask = osm_edge\r
 \r
             # From here on in we will need to perform some adjustments on the masks, depending\r
             # on what they are.\r
             for i in mstr_mask_blur:\r
                 if i[0] == self._tag and i[1] == self._value:\r
                     if self._tag != "place" and (self._value != "sea" or self._value != "ocean"): \r
-                        osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
+                        mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
                         break\r
             \r
             # Begin producing a largely random image\r
@@ -414,7 +283,7 @@ class mstr_layergen:
                         ly = randrange( self._imgsize - img.height )\r
                         layer.alpha_composite( img, (lx, ly) )\r
                 if self._is_completion == True:\r
-                    mp = osm_mask.load()\r
+                    mp = mask.load()\r
                     edn = self.xplane_latlng_folder(self.find_earthnavdata_number())\r
                     idx = 0\r
                     for r in mstr_completion_colors:\r
@@ -483,7 +352,7 @@ class mstr_layergen:
             # Generate the layer from the mask.\r
             layer_comp = Image.new("RGBA", (self._imgsize, self._imgsize))\r
             layer_pix = layer.load()\r
-            mask_pix = osm_mask.load()\r
+            mask_pix = mask.load()\r
             layer_comp_pix = layer_comp.load()\r
             for y in range(self._imgsize):\r
                 for x in range(self._imgsize):\r
@@ -505,9 +374,10 @@ class mstr_layergen:
             # Here we want to make sure that the generated image fits well with others, so\r
             # let's do that.\r
             mstr_msg("layergen", "Generating adjacent fades")\r
-            self.generate_adjacent_fades()\r
+            adjfade = self.generate_adjacent_fades(mask)\r
 \r
             # Determine if there are any fades, and if so, fade those in first before we save the layer\r
+            """\r
             fade_fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value\r
             if os.path.isfile(fade_fn + "_fade_top.png") == True:\r
                 fade = Image.open(fade_fn + "_fade_top.png")\r
@@ -521,6 +391,9 @@ class mstr_layergen:
             if os.path.isfile(fade_fn + "_fade_left.png") == True:\r
                 fade = Image.open(fade_fn + "_fade_left.png")\r
                 layer_comp.alpha_composite(fade)\r
+            """\r
+\r
+            layer_comp.alpha_composite(adjfade)\r
             mstr_msg("layergen", "Adjacent fading completed")\r
 \r
 \r
@@ -551,10 +424,10 @@ class mstr_layergen:
                                 layer_comp_pix[x,y] = (lpix[0], lpix[1], lpix[2], 255-rpix[3])\r
 \r
             # Store layer\r
-            if self._is_completion == False:\r
-                layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
-            if self._is_completion == True:\r
-                layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion_layer.png" )\r
+            #if self._is_completion == False:\r
+            #    layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
+            #if self._is_completion == True:\r
+            #   layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion_layer.png" )\r
             #layer_final.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
             mstr_msg("layergen", "Layer image finalized and saved.")\r
 \r
@@ -570,7 +443,7 @@ class mstr_layergen:
                             break\r
                     if nm == True:\r
                         nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)\r
-                        nrm.build_normalmap()\r
+                        nrm.build_normalmap(layer_comp)\r
 \r
 \r
             # Let's try our hand at pseudo shadows\r
@@ -581,7 +454,7 @@ class mstr_layergen:
                         if self._tag == sh[0] and self._value == sh[1]:\r
                             mstr_msg("layergen", "Generating shadow for layer")\r
                             shadow_pix = shadow.load()\r
-                            mask_pix = osm_mask.load()\r
+                            mask_pix = mask.load()\r
                             shf = 1\r
                             while shf < mstr_shadow_shift:\r
                                 for y in range(self._imgsize):\r
@@ -602,73 +475,12 @@ class mstr_layergen:
 \r
                             shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1.5))\r
 \r
-                            shadow.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_shadow.png")\r
+                            #shadow.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_shadow.png")\r
+                            shadow.alpha_composite(layer_comp)\r
+                            layer_comp = shadow\r
                             mstr_msg("layergen", "Shadow layer completed")\r
 \r
 \r
-\r
-            # Check if pixels touch the borders of the image, and if so -\r
-            # make a not of that in the database.\r
-            at=False\r
-            ar=False\r
-            ab=False\r
-            al=False\r
-            layer_pix = layer_comp.load() # <- Just to be safe\r
-\r
-            # Top scan\r
-            for i in range(0, self._imgsize-1):\r
-                p = layer_pix[i,0]\r
-                if p[3] > 0:\r
-                    at=True\r
-                    break\r
-           \r
-            # Right scan\r
-            for i in range(0, self._imgsize-1):\r
-                p = layer_pix[self._imgsize-1,i]\r
-                if p[3] > 0:\r
-                    ar=True\r
-                    break\r
-            \r
-            # Bottom scan\r
-            for i in range(0, self._imgsize-1):\r
-                p = layer_pix[i,self._imgsize-1]\r
-                if p[3] > 0:\r
-                    ab=True\r
-                    break\r
-            \r
-            # Left scan\r
-            for i in range(0, self._imgsize-1):\r
-                p = layer_pix[1,i]\r
-                if p[3] > 0:\r
-                    al=True\r
-                    break\r
-            \r
-            # Construct DB String\r
-            adjstr = ""\r
-            if at==True: adjstr = adjstr + "t"\r
-            if ar==True: adjstr = adjstr + "r"\r
-            if ab==True: adjstr = adjstr + "b"\r
-            if al==True: adjstr = adjstr + "l"\r
-\r
-            # Store into DB - but only if there is something to store\r
-            if adjstr != "":\r
-                if self._is_completion == False:\r
-                    r = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number, self._lng_number, self._tag, self._value)\r
-                    #r = self._tiledb.get_adjacency_for_source(self._lat_number, self._lng_number, self._tag, self._value)\r
-                    if len(r) == 0:\r
-                        self._tileinfo.add_adjacency_data(self._lat_number, self._lng_number, self._tag, self._value, src, adjstr)\r
-                        mstr_msg("layergen", "Adjacency info stored in database")\r
-\r
-                if self._is_completion == True:\r
-                    r = self._tileinfo.get_adjacency_for_completion(self._lat_number, self._lng_number)\r
-                    #r = self._tiledb.get_adjacency_for_completion(self._lat_number, self._lng_number)\r
-                    if len(r) == 0:\r
-                        self._tileinfo.add_completion_data(self._lat_number, self._lng_number, self._tag, self._value, src, adjstr)\r
-                        mstr_msg("layergen", "Adjacency info for completion stored in database")\r
-\r
-                #self._tiledb.commit_query()\r
-                #self._tiledb.close_db()\r
-\r
             # Create a water mask we need to remove from the DDS later\r
             if (self._tag == "natural" and self._value == "water") or (self._tag == "water" and self._value == "lake") or (self._tag == "water" and self._value == "pond") or (self._tag == "water" and self._value == "river") or (self._tag == "leisure" and self._value == "swimming_pool"):\r
                 mstr_msg("layergen", "Generating inland water mask")\r
@@ -681,8 +493,12 @@ class mstr_layergen:
                         if l[3] > 65:\r
                             b = 255 - l[3]\r
                             inl_pix[x,y] = (255,0,255,255)\r
-                inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")\r
+                #inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")\r
+                layer_comp = inl_mask\r
                 mstr_msg("layergen", "Inland water mask generated and saved")\r
+\r
+            # Return the completed image\r
+            return layer_comp\r
         \r
 \r
         # ---------------------------------------------------------------------------------------\r
@@ -694,10 +510,10 @@ class mstr_layergen:
         if self._isline == True or self._tag == "building":\r
 \r
             # We will need the mask in question\r
-            osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
+            #mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
 \r
             # Generate an edge mask from the original\r
-            osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)\r
+            osm_edge = mask.filter(ImageFilter.FIND_EDGES)\r
             osm_edge = osm_edge.filter(ImageFilter.MaxFilter)\r
             mstr_msg("layergen", "Edge mask generated")\r
 \r
@@ -706,7 +522,7 @@ class mstr_layergen:
             if self._tag != "building":\r
                 for i in mstr_mask_blur:\r
                     if i[0] == self._tag and i[1] == self._value:\r
-                        osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
+                        mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
                         break\r
             \r
             \r
@@ -715,7 +531,7 @@ class mstr_layergen:
             # This time we have no source material - instead we will fill the\r
             # mask with a color that is appropriate for this street type.\r
             layer_comp = Image.new("RGBA", (self._imgsize, self._imgsize))\r
-            mask_pix = osm_mask.load()\r
+            mask_pix = mask.load()\r
             edge_pix = osm_edge.load()\r
             layer_comp_pix = layer_comp.load()\r
 \r
@@ -812,10 +628,21 @@ class mstr_layergen:
 \r
             # We will do some super magic here to let houses look more realistic\r
             if self._tag == "building":\r
+                \r
+                details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+                tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+                trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+                roof_details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+                shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+\r
+                if mstr_shadow_enabled == True:\r
+                    fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_building-" + self._value + "_layer_shadow.png"\r
+                    if os.path.isfile(fn):\r
+                        shadow = Image.open(fn)\r
+\r
                 vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]\r
                 if self._value in vls:\r
                     # Generate a new image\r
-                    details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                     details_pix = details.load()\r
                     layer_pix = layer_comp.load()\r
                     for y in range(self._imgsize):\r
@@ -836,7 +663,6 @@ class mstr_layergen:
                                     details_pix[shf_x2, shf_y2] = (187-d2, 179-d2, 176-d2, aa)\r
 \r
                     # Image for roof details\r
-                    roof_details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                     roof_det_pix = roof_details.load()\r
                     for y in range(self._imgsize):\r
                         for x in range(self._imgsize):\r
@@ -851,15 +677,14 @@ class mstr_layergen:
                                     a = randrange(1, 151)\r
                                     nc = (mstr_building_detail_colors[0][0]-d, mstr_building_detail_colors[0][1]-d, mstr_building_detail_colors[0][2]-d, a)\r
                                     roof_det_pix[x,y] = nc\r
-                    layer_comp.alpha_composite(roof_details)\r
 \r
 \r
                     # Let's see how it works with this method\r
-                    details.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_details.png")\r
+                    #details.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_details.png")\r
+                    #layer_comp.alpha_composite(details)\r
 \r
                     # Add some random trees\r
                     div = int(self._imgsize/200)\r
-                    trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                     for y in range(0, self._imgsize, div):\r
                         for x in range(0, self._imgsize, div):\r
                             if x > 0 and x < self._imgsize and y > 0 and y < self._imgsize:\r
@@ -885,9 +710,9 @@ class mstr_layergen:
                                                 if shf_x > self._imgsize - tree.width: shf_x = self._imgsize - tree.width - 1\r
                                                 if shf_y > self._imgsize - tree.height: shf_y = self._imgsize - tree.height - 1\r
                                                 trees.alpha_composite(tree, (shf_x, shf_y))\r
-\r
+                    \r
+                    \r
                     if mstr_shadow_enabled == True:\r
-                        tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                         tree_pix = trees.load()\r
                         shadow_pix = tree_shadow.load()\r
                         for y in range(self._imgsize):\r
@@ -902,18 +727,34 @@ class mstr_layergen:
                         tree_shadow.alpha_composite(trees)\r
 \r
                         # Save this separately, so that we can blur buildings, but not the trees\r
-                        fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_building_trees.png"\r
-\r
-                        if os.path.isfile(fn) == True:\r
-                            extrees = Image.open(fn)\r
-                            extrees.alpha_composite(tree_shadow)\r
-                            extrees.save(fn)\r
-                        else:\r
-                            tree_shadow.save(fn)\r
-\r
-                        #layer_comp.alpha_composite(tree_shadow)\r
-                        #tree_shadow.alpha_composite(layer_comp)\r
-                        #layer_comp = tree_shadow\r
+                        #fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_building_trees.png"\r
+\r
+                        #if os.path.isfile(fn) == True:\r
+                        #    extrees = Image.open(fn)\r
+                        #    extrees.alpha_composite(tree_shadow)\r
+                        #    extrees.save(fn)\r
+                        #else:\r
+                        #    tree_shadow.save(fn)\r
+\r
+                # Let's try this one on for size\r
+                bld_comp = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+                details = details.filter(ImageFilter.GaussianBlur(radius=1))\r
+                bld_comp.alpha_composite(details)\r
+                bld_comp.alpha_composite(tree_shadow)\r
+                bld_comp.alpha_composite(trees)\r
+                shd_p  = shadow.load()\r
+                for y in range(self._imgsize):\r
+                    for x in range(self._imgsize):\r
+                        c = shd_p[x,y]\r
+                        if c[3] > 0:\r
+                            s = (0,0,0,120-(randrange(0,21)))\r
+                            shd_p[x,y] = s\r
+                shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1))\r
+                bld_comp.alpha_composite(shadow)\r
+                layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1.1))\r
+                bld_comp.alpha_composite(layer_comp)\r
+                layer_comp = bld_comp\r
+                layer_comp.alpha_composite(roof_details)\r
 \r
             mstr_msg("layergen", "Layer image generated")\r
 \r
@@ -922,7 +763,7 @@ class mstr_layergen:
                     \r
                 # Some funnies with shadows\r
                 if self._tag == "building" and (self._value == "detached" or self._value == "semidetached_house" or self._value == "apartments" or self._value == "civic" or self._value == "house" or self._value == "terrace"):\r
-                    mask_pix = osm_mask.load()\r
+                    mask_pix = mask.load()\r
                     roofshadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                     roofpix = roofshadow.load()\r
                     # Generate a pseudo shifted roof shadow\r
@@ -937,7 +778,7 @@ class mstr_layergen:
 \r
                     # Now apply the shift where necessary\r
                     roofpix = roofshadow.load()\r
-                    mask_pix = osm_mask.load()\r
+                    mask_pix = mask.load()\r
                     layer_comp_pix = layer_comp.load()\r
                     for y in range(self._imgsize):\r
                         for x in range(self._imgsize):\r
@@ -1014,7 +855,7 @@ class mstr_layergen:
             # Highways and runways of any kind get some special treatment\r
             if (self._tag == "highway" and self._value == "motorway") or (self._tag == "highway" and self._value == "primary") or (self._tag == "highway" and self._value == "secondary") or (self._tag == "highway" and self._value == "tertiary") or (self._tag == "aeroway" and self._value == "runway"):\r
                 # We will now add some white lines for coolness\r
-                osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)\r
+                osm_edge = mask.filter(ImageFilter.FIND_EDGES)\r
                 mask_pix = osm_edge.load()\r
                 layer_comp_pix = layer_comp.load()\r
                 for y in range(self._imgsize):\r
@@ -1026,7 +867,7 @@ class mstr_layergen:
                             layer_comp_pix[x, y] = ( w,w,w,a[3] )\r
 \r
             if self._tag == "highway" and self._value == "residential":\r
-                osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)\r
+                osm_edge = mask.filter(ImageFilter.FIND_EDGES)\r
                 mask_pix = osm_edge.load()\r
                 layer_comp_pix = layer_comp.load()\r
                 for y in range(self._imgsize):\r
@@ -1052,7 +893,7 @@ class mstr_layergen:
                         if l[3] > 65:\r
                             b = 255 - l[3]\r
                             inl_pix[x,y] = (255,0,255,255)\r
-                inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")\r
+                #inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")\r
                 mstr_msg("layergen", "Inland water mask generated and saved")\r
 \r
             \r
@@ -1062,7 +903,7 @@ class mstr_layergen:
 \r
 \r
             # Store layer\r
-            layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
+            #layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
             mstr_msg("layergen", "Layer image finalized and saved.")\r
 \r
 \r
@@ -1077,13 +918,17 @@ class mstr_layergen:
                             break\r
                     if nm == True:\r
                         nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)\r
-                        nrm.build_normalmap()\r
+                        nrm.build_normalmap(layer_comp)\r
+\r
+\r
+            # Return image\r
+            return layer_comp\r
 \r
 \r
     # Should we find more than one source, the first one found will take precedence.\r
     # For the others, we will need to generate fading images, so that the final layer \r
     # image works with other tiles\r
-    def generate_adjacent_fades(self):\r
+    def generate_adjacent_fades(self, mask):\r
         adj_sources = self.find_all_adjacent_sources()\r
         precedence = -1\r
 \r
@@ -1105,11 +950,11 @@ class mstr_layergen:
 \r
         # Generate required images\r
         # Basically a shortened version of the main layergen call\r
+        adj_image = Image.new("RGBA", (self._imgsize, self._imgsize))\r
         for s in range(0, 4):\r
             if adj_sources[s] != precedence and adj_sources[s] != -1:\r
                 src = adj_sources[s]\r
 \r
-                adj_image = Image.new("RGBA", (self._imgsize, self._imgsize))\r
                 adj_pix = adj_image.load()\r
 \r
                 # Root folder\r
@@ -1122,15 +967,15 @@ class mstr_layergen:
                 for p in ptc:\r
                     ptc_src.append(Image.open(p))\r
 \r
-                osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
+                #mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )\r
                 #lyr_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
 \r
                 for i in mstr_mask_blur:\r
                     if i[0] == self._tag and i[1] == self._value:\r
                         if self._tag != "place" and (self._value != "sea" or self._value != "ocean"): \r
-                            osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
+                            mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
                             break\r
-                mask_pix = osm_mask.load()\r
+                mask_pix = mask.load()\r
             \r
                 # Begin producing a largely random image\r
                 samples = 250   # <- We need this in a moment\r
@@ -1167,7 +1012,7 @@ class mstr_layergen:
                                 adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
                             else:\r
                                 adj_pix[x,y] = (0,0,0,0)\r
-                    adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_top.png")\r
+                    #adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_top.png")\r
                 \r
                 if s == 1:\r
                     for y in range(self._imgsize):\r
@@ -1178,7 +1023,7 @@ class mstr_layergen:
                                 adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
                             else:\r
                                 adj_pix[x,y] = (0,0,0,0)\r
-                    adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_right.png")\r
+                    #adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_right.png")\r
                 \r
                 if s == 2:\r
                     for y in range(self._imgsize):\r
@@ -1189,7 +1034,7 @@ class mstr_layergen:
                                 adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
                             else:\r
                                 adj_pix[x,y] = (0,0,0,0)\r
-                    adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_bottom.png")\r
+                    #adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_bottom.png")\r
 \r
                 if s == 3:\r
                     for y in range(self._imgsize):\r
@@ -1200,7 +1045,11 @@ class mstr_layergen:
                                 adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
                             else:\r
                                 adj_pix[x,y] = (0,0,0,0)\r
-                    adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_left.png")\r
+                    #adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_left.png")\r
+\r
+        # Return the image\r
+        return adj_image\r
+\r
 \r
 \r
     def find_all_adjacent_sources(self):\r
index d60f866d54749d32507fbfba6ccae5ff3718556e..519e8110898acf2f0c0be259b36681715a6e3345 100644 (file)
@@ -205,12 +205,10 @@ class mstr_maskgen:
                             break\r
                     imgd.line(pts, fill="#000000", width=mstr_ortho_layers[idx][2], joint="curve")\r
         \r
-        # Save image\r
-        if is_prep == False:\r
-            mask_img.save(mstr_datafolder + "_cache/" + fstr + "_" + self._tag + "-" + self._value + ".png")\r
         if is_prep == True:\r
             return mask_img\r
 \r
+\r
         # If this is a building, we need to render the shadow here, as we only know the height\r
         # of the building in this loop.\r
         if mstr_shadow_enabled == True and is_prep == False:\r
@@ -265,3 +263,6 @@ class mstr_maskgen:
 \r
         # Inform\r
         mstr_msg("maskgen", "Mask built.")\r
+\r
+        # Return the image\r
+        return mask_img\r
diff --git a/og.py b/og.py
index 57a95f4606330ab6fbe9ee9eb0d30cd26fd57575..01f7d2496303d3e85855d18ca4b13d2cc7855d07 100644 (file)
--- a/og.py
+++ b/og.py
@@ -49,7 +49,12 @@ if cli == True:
 \r
     # Create the class and init values\r
     og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd(), prep)\r
-    og._buildTile()\r
+\r
+    if prep == True:\r
+        og._prepareTile()\r
+\r
+    if prep == False:\r
+        og._generateOrthos_mt(int(sys.argv[3]))\r
 \r
 \r
 # Only if we find enough arguments, proceed.\r
index 9cccd68fc875f2fc9cad22dd93de72fce48cae75..f316ac6b2b86d524dfad0caa4e297d998179758f 100644 (file)
@@ -13,6 +13,8 @@
 import math\r
 import os\r
 import glob\r
+import threading\r
+from multiprocessing import Process\r
 from defines import *\r
 from log import *\r
 from osmxml import *\r
@@ -147,8 +149,140 @@ class mstr_orthographic:
                 top_lat = cur_tile_y\r
 \r
 \r
-    # Builds and processes the tile with everything required, in one call.\r
-    def _buildTile(self):\r
+    # Start the multi-threaded build of all orthos\r
+    # amtsmt = AmountSimultaneous - so how many orthos you want to\r
+    # generate at the same time. You may need to fine tune this value\r
+    # so that you don't overload your machine.\r
+    def _generateOrthos_mt(self, amtsmt):\r
+        # Need to know maximum values first\r
+        bb_lat = self._lat\r
+        bb_lng = self._long\r
+        bb_lat_edge = self._lat+self._vstep\r
+        bb_lng_edge = self._long+mstr_zl_18\r
+        mlat = 1\r
+        mlng = 1\r
+        while bb_lat < self._lat + 1:\r
+            bb_lat = bb_lat + self._vstep\r
+            mlat = mlat+1\r
+        while bb_lng < self._long + 1:\r
+            bb_lng = bb_lng + mstr_zl_18\r
+            mlng = mlng+1\r
+        mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))\r
+        maxlatlng = [ mlat, mlng ]\r
+\r
+        procs = []\r
+        for p in range(1, amtsmt+1):\r
+            proc = Process(target=self._buildOrtho, args=[1, p, amtsmt])\r
+            procs.append(proc)\r
+            proc.start()\r
+        mstr_msg("orthographic", "Ortho threads started")\r
+\r
+\r
+    # Starts a threading loop to build orthos, with the defined starting point in\r
+    # the lat-lng grid. You will also need to provide the horizontal stepping so\r
+    # that the thread keeps running.\r
+    def _buildOrtho(self, v, h, step):\r
+\r
+        # Starting point\r
+        grid_lat = v\r
+        grid_lng = h\r
+\r
+        # The tile is constructed of many smaller parts. We walk through the\r
+        # smallest possible, from which the bigger ones are later built.\r
+        bb_lat = self._lat\r
+        bb_lng = self._long\r
+        bb_lat_edge = self._lat+self._vstep\r
+        bb_lng_edge = self._long+mstr_zl_18\r
+\r
+        # We need to know the highest possible latitude and longitude tile numbers,\r
+        # in case we render at the edge\r
+        mlat = 1\r
+        mlng = 1\r
+        while bb_lat < self._lat + 1:\r
+            bb_lat = bb_lat + self._vstep\r
+            mlat = mlat+1\r
+        while bb_lng < self._long + 1:\r
+            bb_lng = bb_lng + mstr_zl_18\r
+            mlng = mlng+1\r
+        mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))\r
+        maxlatlng = [ mlat, mlng ]\r
+\r
+        while grid_lat <= maxlatlng[0]:\r
+            # Reset these two\r
+            bb_lat = self._lat + ((grid_lat-1)*self._vstep)\r
+            bb_lng = self._long + ((grid_lng-1)*mstr_zl_18)\r
+            bb_lat_edge = self._lat + ((grid_lat-1)*self._vstep) + self._vstep\r
+            bb_lng_edge = self._long + ((grid_lng-1)*mstr_zl_18) + mstr_zl_18\r
+\r
+            osmxml = mstr_osmxml()\r
+            osmxml.adjust_bbox(bb_lat, bb_lng, bb_lat_edge, bb_lng_edge)\r
+            osmxml.acquire_osm(grid_lat, grid_lng)\r
+\r
+            # Let the user know\r
+            mstr_msg("orthographic", "Generating orthophoto " + str(grid_lat) + "-" + str(grid_lng))\r
+\r
+            # Get the data\r
+            #osmxml.acquire_osm(cur_tile_y, cur_tile_x) # <- This acquires current OSM info\r
+            #mstr_msg("orthographic", "Acquired current OSM info from marstr.online repository")\r
+\r
+            # Check for work to be done\r
+            layers = self.determineLayerWork(osmxml)\r
+\r
+            # We need to walk through the array of layers,\r
+            # in their z-order.\r
+            # For each layer, we will generate the mask, the layer image\r
+            # itself, and finally, compose the ortho photo.\r
+            mstr_msg("orthographic", "Beginning generation of layers")\r
+\r
+            # In here we store the layers\r
+            photolayers = []\r
+\r
+            # The masks are handed to layergen in sequence. The layers are then\r
+            # in turn handed to photogen.\r
+\r
+            curlyr = 1\r
+            for layer in layers:\r
+                # Let the user know\r
+                mstr_msg("orthographic", "Processing layer " + str(curlyr) + " of " + str(len(layers)))\r
+\r
+                # Generate the mask\r
+                mg = mstr_maskgen( [self._lat, grid_lat, self._long, grid_lng], self._vstep, layer[0], layer[1], layer[2])\r
+                if layer[0] == "building":\r
+                    mg.set_tile_width(self._findWidthOfLongitude(bb_lat))\r
+                    mg.set_latlng_numbers(self._lat, grid_lat, self._long, grid_lng)\r
+                mask = mg._build_mask(osmxml)\r
+                \r
+                # Generate the layer\r
+                lg = mstr_layergen(layer[0], layer[1], self._lat, grid_lat, self._long, grid_lng, layer[2])\r
+                lg.set_max_latlng_tile(maxlatlng)\r
+                lg.set_latlng_folder(self._latlngfld)\r
+                #lg.open_db()\r
+                lg.open_tile_info()\r
+                photolayers.append(lg.genlayer(mask, osmxml))\r
+                curlyr = curlyr+1\r
+            mstr_msg("orthographic", "All layers created")\r
+\r
+            # We should have all layers now.\r
+            # Snap a photo with our satellite :)\r
+            mstr_msg("orthographic", "Generating ortho photo")\r
+            pg = mstr_photogen(self._lat, self._long, grid_lat, grid_lng,  maxlatlng[0], maxlatlng[1])\r
+            pg.genphoto(photolayers)\r
+            mstr_msg("orthographic", " -- Ortho photo generated -- ")\r
+            print("")\r
+            print("")\r
+\r
+            # Perform adjustment of grid position\r
+            n_lng = grid_lng + step\r
+            if n_lng > maxlatlng[1]:\r
+                np = n_lng - maxlatlng[1]\r
+                grid_lng = np\r
+                grid_lat = grid_lat+1\r
+            else:\r
+                grid_lng = n_lng\r
+\r
+\r
+    # Prepares the entire tile\r
+    def _prepareTile(self):\r
         mstr_msg("orthographic", "Beginning construction of tile")\r
 \r
         # We need to know which platform we are on\r
@@ -239,194 +373,52 @@ class mstr_orthographic:
         # Previously, I downloaded all XML files in one go - but to ease the\r
         # stress on OSM servers and my server, we will do acquire the data\r
         # only for the current processed part of the tile.\r
-        if self._prep == True:\r
-            for lat_grid in range(1, maxlatlng[0]+1):\r
-                for lng_grid in range(1, maxlatlng[1]+1):\r
-                    # Adjust bounding box\r
-                    osmxml = mstr_osmxml()\r
-                    osmxml.adjust_bbox(bb_lat, bb_lng, bb_lat_edge, bb_lng_edge)\r
-                    osmxml.acquire_osm(lat_grid, lng_grid)\r
-                    mstr_msg("orthographic", "Adjusted bounding box for XML object")\r
-\r
-                    # Check for work to be done\r
-                    layers = self.determineLayerWork(osmxml)\r
-\r
-                    curlyr = 1\r
-                    for layer in layers:\r
-                        if layer[2] == False and layer[0] != "building":\r
-                            # Let the user know\r
-                            mstr_msg("orthographic", "Processing layer " + str(curlyr) + " of " + str(len(layers)))\r
-\r
-                            # Generate the mask\r
-                            mg = mstr_maskgen( [self._lat, cur_tile_y, self._long, cur_tile_x], self._vstep, layer[0], layer[1], layer[2])\r
-                            mask = mg._build_mask(osmxml, is_prep=True) # We need an object here\r
-\r
-                            tp = mstr_tileprep(self._lat, self._long, lat_grid, lng_grid, layer[0], layer[1], mask, False)\r
-                            tp._prepareTile()\r
-\r
-                        curlyr = curlyr+1\r
-\r
-                    # Adjust longitude coordinates\r
-                    cur_tile_x = cur_tile_x+1\r
-                    bb_lng = bb_lng + mstr_zl_18\r
-                    bb_lng_edge = bb_lng_edge + mstr_zl_18\r
-                    mstr_msg("orthographic", "Adjustment of longitude performed")\r
-                    # Adjust peak longitude tile number\r
-                    if cur_tile_x > top_lng:\r
-                        top_lng = cur_tile_x\r
-\r
-                # Adjust latitude and all other values when we get here\r
-                cur_tile_y = cur_tile_y+1\r
-                cur_tile_x = 1\r
-                bb_lng = self._long\r
-                bb_lng_edge = self._long + mstr_zl_18\r
-                bb_lat = bb_lat + self._vstep\r
-                bb_lat_edge = bb_lat_edge + self._vstep\r
-                mstr_msg("orthographic", "Adjustment of latitude performed")\r
-                # Adjust peak latitude number\r
-                if cur_tile_y > top_lat:\r
-                    top_lat = cur_tile_y\r
-\r
-        # Need to differentiate\r
-        if self._prep == False:\r
-            # The tile is constructed of many smaller parts. We walk through the\r
-            # smallest possible, from which the bigger ones are later built.\r
-            bb_lat = self._lat\r
-            bb_lng = self._long\r
-            bb_lat_edge = self._lat+self._vstep\r
-            bb_lng_edge = self._long+mstr_zl_18\r
-            cur_tile_x = 1\r
-            cur_tile_y = 1\r
-            osmxml = mstr_osmxml(0,0)\r
-\r
-            # Previously, I downloaded all XML files in one go - but to ease the\r
-            # stress on OSM servers and my server, we will do acquire the data\r
-            # only for the current processed part of the tile.\r
-            for lat_grid in range(1, maxlatlng[0]+1):\r
-                for lng_grid in range(1, maxlatlng[1]+1):\r
-                    # Adjust bounding box\r
-                    osmxml.adjust_bbox(bb_lat, bb_lng, bb_lat_edge, bb_lng_edge)\r
-                    mstr_msg("orthographic", "Adjusted bounding box for XML object")\r
+        for lat_grid in range(1, maxlatlng[0]+1):\r
+            for lng_grid in range(1, maxlatlng[1]+1):\r
+                # Adjust bounding box\r
+                osmxml = mstr_osmxml()\r
+                osmxml.adjust_bbox(bb_lat, bb_lng, bb_lat_edge, bb_lng_edge)\r
+                osmxml.acquire_osm(lat_grid, lng_grid)\r
+                mstr_msg("orthographic", "Adjusted bounding box for XML object")\r
 \r
-                    # Determine what to do... maybe work was interrupted\r
-                    if os.path.isfile(mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(cur_tile_y) + "_" + str(cur_tile_x) + ".dds") == False:\r
+                # Check for work to be done\r
+                layers = self.determineLayerWork(osmxml)\r
 \r
+                curlyr = 1\r
+                for layer in layers:\r
+                    if layer[2] == False and layer[0] != "building":\r
                         # Let the user know\r
-                        mstr_msg("orthographic", "Generating missing orthophoto " + str(cur_tile_y) + "-" + str(cur_tile_x))\r
-\r
-                        # Get the data\r
-                        #osmxml.acquire_osm(cur_tile_y, cur_tile_x) # <- This acquires current OSM info\r
-                        #mstr_msg("orthographic", "Acquired current OSM info from marstr.online repository")\r
-\r
-                        # Check for work to be done\r
-                        layers = self.determineLayerWork()\r
-\r
-                        # We need to walk through the array of layers,\r
-                        # in their z-order.\r
-                        # For each layer, we will generate the mask, the layer image\r
-                        # itself, and finally, compose the ortho photo.\r
-                        mstr_msg("orthographic", "Beginning generation of layers")\r
-\r
-                        curlyr = 1\r
-                        for layer in layers:\r
-                            # Let the user know\r
-                            mstr_msg("orthographic", "Processing layer " + str(curlyr) + " of " + str(len(layers)))\r
-\r
-                            # Generate the mask\r
-                            mg = mstr_maskgen( [self._lat, cur_tile_y, self._long, cur_tile_x], self._vstep, layer[0], layer[1], layer[2])\r
-                            if layer[0] == "building":\r
-                                mg.set_tile_width(self._findWidthOfLongitude(bb_lat))\r
-                                mg.set_latlng_numbers(self._lat, lat_grid, self._long, lng_grid)\r
-                            mg._build_mask()\r
-                            \r
-                            # Generate the layer\r
-                            lg = mstr_layergen(layer[0], layer[1], self._lat, cur_tile_y, self._long, cur_tile_x, layer[2])\r
-                            lg.set_max_latlng_tile(maxlatlng)\r
-                            lg.set_latlng_folder(self._latlngfld)\r
-                            #lg.open_db()\r
-                            lg.open_tile_info()\r
-                            lg.genlayer()\r
-                            curlyr = curlyr+1\r
-                        mstr_msg("orthographic", "All layers created")\r
-\r
-                        # We should have all layers now.\r
-                        # Snap a photo with our satellite :)\r
-                        mstr_msg("orthographic", "Generating ortho photo")\r
-                        pg = mstr_photogen(self._lat, self._long, cur_tile_y, cur_tile_x,  maxlatlng[0], maxlatlng[1])\r
-                        pg.genphoto()\r
-                        mstr_msg("orthographic", " -- Ortho photo generated -- ")\r
-                        print("")\r
-                        print("")\r
-\r
-                    # Adjust longitude coordinates\r
-                    cur_tile_x = cur_tile_x+1\r
-                    bb_lng = bb_lng + mstr_zl_18\r
-                    bb_lng_edge = bb_lng_edge + mstr_zl_18\r
-                    mstr_msg("orthographic", "Adjustment of longitude performed")\r
-                    # Adjust peak longitude tile number\r
-                    if cur_tile_x > top_lng:\r
-                        top_lng = cur_tile_x\r
-\r
-                    # Clear out cache\r
-                    """\r
-                    if mstr_clear_cache == True:\r
-                        ch = glob.glob(mstr_datafolder + "_cache/*")\r
-                        for f in ch:\r
-                            if os_platform == "nt":\r
-                                if self._isFileAccessibleWin(f) == True:\r
-                                    os.remove(f)\r
-                            if os_platform == "posix":\r
-                                if self._isFileAccessiblePosix(f) == True:\r
-                                    os.remove(f)\r
-                        mstr_msg("orthographic", "Cleared cache")\r
-                    """\r
-                \r
+                        mstr_msg("orthographic", "Processing layer " + str(curlyr) + " of " + str(len(layers)))\r
 \r
-                # Adjust latitude and all other values when we get here\r
-                cur_tile_y = cur_tile_y+1\r
-                cur_tile_x = 1\r
-                bb_lng = self._long\r
-                bb_lng_edge = self._long + mstr_zl_18\r
-                bb_lat = bb_lat + self._vstep\r
-                bb_lat_edge = bb_lat_edge + self._vstep\r
-                mstr_msg("orthographic", "Adjustment of latitude performed")\r
-                # Adjust peak latitude number\r
-                if cur_tile_y > top_lat:\r
-                    top_lat = cur_tile_y\r
-            \r
-            mstr_msg("orthographic", "Generation of all tiles completed!")\r
-\r
-\r
-            # Complete scenery\r
-            if mstr_xp_genscenery == True:\r
-                scn = mstr_xp_scenery(self._lat, self._long, mlat, mlng, self._vstep, self._latlngfld)\r
-                scn.acquire_elevation_data()\r
-                scn.acquire_xes_data()\r
-                scn.build_mesh_script()\r
-                scn.build_mesh()\r
-                scn.build_ter_files()\r
-                mstr_msg("orthographic", "[X-Plane] Mesh built, and scenery completed")\r
-            \r
-            mstr_msg("orthographic", "Final step completed.")\r
-            mstr_msg("orthographic", "Tile data in: " + self._output + "z_orthographic/" + self._latlngfld)\r
-            print("")\r
-            mstr_msg("orthographic", "Thanks for using Orthographic! -- Best, Marcus")\r
-            print("")\r
+                        # Generate the mask\r
+                        mg = mstr_maskgen( [self._lat, cur_tile_y, self._long, cur_tile_x], self._vstep, layer[0], layer[1], layer[2])\r
+                        mask = mg._build_mask(osmxml, is_prep=True) # We need an object here\r
 \r
-            # Let's leave this out for the moment\r
-            """\r
-            mstr_msg("orthographic", "Generating ZL16 tiles and keeping airport tiles")\r
-            tg = mstr_tilegen(self._lat, self._lng, self._vstep, top_lat, top_lng)\r
-            tg.genTiles()\r
-            mstr_msg("orthographic", "Final step completed.")\r
-            print("")\r
-            mstr_msg("orthographic", "Tile data in: " + mstr_datafolder + "/Tiles/" + str(self._lat) + "_" + self._lng)\r
-            print("")\r
-            print("")\r
-            mstr_msg("orthographic", "Thanks for using Orthographic! -- Best, Marcus")\r
-            print("")\r
-            """\r
+                        tp = mstr_tileprep(self._lat, self._long, lat_grid, lng_grid, layer[0], layer[1], mask, False)\r
+                        tp._prepareTile()\r
+\r
+                    curlyr = curlyr+1\r
 \r
+                # Adjust longitude coordinates\r
+                cur_tile_x = cur_tile_x+1\r
+                bb_lng = bb_lng + mstr_zl_18\r
+                bb_lng_edge = bb_lng_edge + mstr_zl_18\r
+                mstr_msg("orthographic", "Adjustment of longitude performed")\r
+                # Adjust peak longitude tile number\r
+                if cur_tile_x > top_lng:\r
+                    top_lng = cur_tile_x\r
+\r
+            # Adjust latitude and all other values when we get here\r
+            cur_tile_y = cur_tile_y+1\r
+            cur_tile_x = 1\r
+            bb_lng = self._long\r
+            bb_lng_edge = self._long + mstr_zl_18\r
+            bb_lat = bb_lat + self._vstep\r
+            bb_lat_edge = bb_lat_edge + self._vstep\r
+            mstr_msg("orthographic", "Adjustment of latitude performed")\r
+            # Adjust peak latitude number\r
+            if cur_tile_y > top_lat:\r
+                top_lat = cur_tile_y\r
 \r
 \r
 \r
index 033bef0cbe23b84e5c450c3c97beb95887837fc0..3aad51d536a8d211fc7bec733530852dcbfb645c 100644 (file)
@@ -4,6 +4,7 @@ from PIL import Image, ImageFilter, ImageEnhance
 from defines import *\r
 from layergen import *\r
 from log import *\r
+from functions import *\r
 \r
 # -------------------------------------------------------------------\r
 # ORTHOGRAPHIC\r
@@ -38,13 +39,14 @@ class mstr_photogen:
 \r
     \r
     # This puts it all together. Bonus: AND saves it.\r
-    def genphoto(self):\r
+    def genphoto(self, layers):\r
         # Template for the file name which is always the same\r
-        root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"\r
+        #root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"\r
 \r
         # First, we walk through all layers and blend them on top of each other, in order\r
         mstr_msg("photogen", "Merging layers")\r
 \r
+        """\r
         # Note if we added building shadows\r
         bldg_shadow_added = False\r
 \r
@@ -86,8 +88,11 @@ class mstr_photogen:
         #bldg_final.alpha_composite(bldg_shadow)\r
         bldg_final.alpha_composite(tree_main)\r
         bldg_final.alpha_composite(bldg_main)\r
+        """\r
 \r
-        for l in mstr_ortho_layers:\r
+        for l in layers:\r
+            self._tile.alpha_composite(l)\r
+            """\r
             if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):\r
                 # Need to divert in case we have shadows\r
                 if mstr_shadow_enabled == True:\r
@@ -117,9 +122,10 @@ class mstr_photogen:
                         layer = layer.filter(ImageFilter.GaussianBlur(radius=0.2))\r
                     # Converge the layer with this image\r
                     self._tile.alpha_composite(layer)\r
+            """\r
 \r
         # Drop the buildings on top\r
-        self._tile.alpha_composite(bldg_final)\r
+        #self._tile.alpha_composite(bldg_final)\r
 \r
 \r
         # When we have run through this loop, we will end up with a sandwiched\r
@@ -136,29 +142,68 @@ class mstr_photogen:
         # If this check comes back as true, we need to perform\r
         # aforementioned fix:\r
         if emptyspace == True:\r
-            # Choose a suitable layer type\r
-            tag   = "landuse"\r
-            value = "meadow"\r
 \r
             mstr_msg("photogen", "Patching empty space")\r
-            self.buildCompletionMask()\r
+            mask = self.buildCompletionMask()\r
+\r
+            # Load the mask\r
+            mask_px = mask.load()\r
 \r
-            # Generate the layer as if it were part of the OSM data\r
-            lg = mstr_layergen(tag, value, self._lat, self._ty, self._lng, self._tx, False, is_completion=True)\r
-            lg.set_max_latlng_tile(self._maxlatlng)\r
-            lg.set_latlng_folder(self._latlngfld)\r
-            #lg.open_db()\r
-            lg.open_tile_info()\r
-            lg.genlayer()\r
+            cmpl = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+            cmp_px = cmpl.load()\r
 \r
-            # Load the image\r
-            completion = Image.open(root_filename + "tile-completion_layer.png")\r
+            edn = self.find_earthnavdata_number()\r
+            edns = self.latlng_folder(edn)\r
+            idx = 0\r
+            for r in mstr_completion_colors:\r
+                if r[0] == edns:\r
+                    break\r
+                else:\r
+                    idx = idx+1\r
+            \r
+            for y in range(self._imgsize):\r
+                for x in range(self._imgsize):\r
+                    p = mask_px[x,y]\r
+                    if p[3] > 0:\r
+                        cidx = randrange(0, len(mstr_completion_colors[idx][1])-1)\r
+                        clr = mstr_completion_colors[idx][1][cidx]\r
+                        cmp_px[x,y] = (clr[0], clr[1], clr[2], 255)\r
+\r
+            # Some features\r
+            patches = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")\r
+\r
+            # Pick an amount of features to add\r
+            patch_amt = randrange(1, 7)\r
+\r
+            # Add those somewhere\r
+            for p in range(1, patch_amt+1):\r
+                # Load some patch\r
+                ptc = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(randrange(1, len(patches)+1)) + ".png")\r
+                # Rotate it\r
+                ptc = ptc.rotate(randrange(0, 360), expand=True)\r
+                # Adjust alpha on this image\r
+                ptc_p = ptc.load()\r
+                for y in range(ptc.height):\r
+                    for x in range(ptc.width):\r
+                        c = ptc_p[x,y]\r
+                        if c[3] > 0:\r
+                            na = c[3] - 160\r
+                            if na < 0: na = 0\r
+                            nc = (c[0], c[1], c[2], na)\r
+                            ptc_p[x,y] = nc\r
+\r
+                # Find a location INSIDE the image!\r
+                px = randrange(1, randrange(self._imgsize - ptc.width - 1))\r
+                py = randrange(1, randrange(self._imgsize - ptc.height - 1))\r
+\r
+                # Add it to the completion image\r
+                cmpl.alpha_composite(ptc)\r
 \r
             # Merge the images\r
-            completion.alpha_composite(self._tile)\r
+            cmpl.alpha_composite(self._tile)\r
 \r
             # Make this the real one\r
-            self._tile = completion\r
+            self._tile = cmpl\r
 \r
 \r
         # There may be some tiles that have a larger sea or even an ocean in them - these need to be\r
@@ -262,8 +307,9 @@ class mstr_photogen:
         # We do not apply any blur or other effects here - we only want the\r
         # exact pixel positions.\r
 \r
-        mask.save( mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_tile-completion.png" )\r
+        #mask.save( mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_tile-completion.png" )\r
         mstr_msg("photogen", "Generated and saved empty space mask")\r
+        return mask\r
 \r
 \r
     # Construct a folder name for latitude and longitude\r
@@ -281,3 +327,13 @@ class mstr_photogen:
         if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])\r
 \r
         return fstr\r
+\r
+\r
+    # Find the next "by-ten" numbers for the current latitude and longitude\r
+    def find_earthnavdata_number(self):\r
+        earthnavdata = []\r
+        lat = abs(int(self._lat / 10) * 10)\r
+        lng = abs(int(self._lng / 10) * 10)\r
+        earthnavdata.append(lat)\r
+        earthnavdata.append(lng)\r
+        return earthnavdata
\ No newline at end of file
index d0e4842cc12a0ce26656cb095306bd3cadc55552..5c7559fbd7576c54ed2b14e3c8abec25815b7068 100644 (file)
--- a/repoinfo
+++ b/repoinfo
@@ -6,6 +6,16 @@ While tools like Ortho4XP or AutoOrtho can provide next-level realism into X-Pla
 \r
 Currently, zoom level 18 is implemented.\r
 \r
+\r
+Orthographic | Real World\r
+\r
+[img]comp_1_1.jpg[/img]\r
+\r
+[img]comp_2_11.jpg[/img]\r
+\r
+[img]comp_2_23.jpg[/img]\r
+\r
+\r
 [section]Wait, just what are ortho photos?[/section]\r
 \r
 Aerial photos taken with a satellite, of varying resolution, altitude, and detail. When you switch to satellite in Google or Bing Maps - what you see is a collage of ortho photos, depending on how close or far away you are zoomed in.\r
@@ -70,8 +80,7 @@ Apart from that I am aware that the code is most likely not the best and can be
 [section]Requirements[/section]\r
 \r
 - Current Python version (3.10 and up)\r
-- Python modules: Pillow (formerly PIL), wand, numpy\r
-- SQLite must be available to Python. On Windows it is by default, you may need to install the sqlite3 developer libraries on your distribution, then compile Python to automatically avail of this built-in module. On my Endeavour OS install, SQLite was already built-in to the Python package.\r
+- Python modules: Pillow (formerly PIL), requests, numpy\r
 \r
 \r
 [section]Configuration[/section]\r
@@ -82,11 +91,7 @@ You will find various configuration options, each of which is documented what it
 \r
 In this file you can also define how large you want the final products to be - you can choose between 4k resolution (2048px) or 16k resolution (4096). The choice you make here should be based on 1) how much detail you want, and 2) how much VRAM your GPU has. The larger a texture, the more VRAM is needed, and the more processing is required by the GPU. I personally go with 2048, as I have a RTX2060, so my VRAM is limited. When at altitudes of 10,000 feet and above, you will most definitely not notice the difference between 4096 and 2048.\r
 \r
-NOTE! 4096 not yet implemented, but planned.\r
-\r
-Change the mstr_photores variable to 4096 if you want the maximum possible.\r
-\r
-Just a note: 4096 also uses 4x more hard drive space. 4k uses about 2MB per image, where as 16k uses about 8-10MB per image. This may not seem much for one image, but keep in mind we are talking about quite a considerable number of images. To get an idea - if you have it, look into any folder of an Ortho4XP tile in your X-Plane folder, and check the size of the "textures" folder.\r
+NOTE! 4096 not yet implemented.\r
 \r
 Also in defines.py, you will find the single layers, along with their corresponding mask blurring values. It is my strong recommendation NOT to change these values, as I have taken a lot of time to fine-tune these values.\r
 \r
@@ -95,33 +100,36 @@ Also in defines.py, you will find the single layers, along with their correspond
 \r
 Very simple.\r
 \r
-[codebox]python og.py LATITUDE LONGITUDE[/codebox]\r
+First step: \r
+[codebox]python og.py LATITUDE LONGITUDE true[/codebox]\r
 \r
 So for example\r
 \r
-[codebox]python main.py 51 7[codebox]\r
+[codebox]python main.py 51 7 true[codebox]\r
 \r
-This does everything for you.\r
+This will generate a complete dataset containing which sources to use in which quadrant of the image grid.\r
 \r
-ATTENTION! This process will take a considerable amount of time due to the work being involved. Please keep this in mind, especially if you seek to do this for an entire country.\r
+Then:\r
 \r
-I am considering hosting the finished tiles on my server, so that you only need to download the finished photos / tile packs.\r
+[codebox]python og.py LATITUDE LONGITUDE NUMBER_OF_SIMULTANEOUS_IMAGES_TO_PRODUCE[/codebox]\r
 \r
+So for example\r
 \r
-[section]Examples[/section]\r
+[codebox]python main.py 51 7 32[codebox]\r
 \r
-Dortmund, Germany\r
+This will generate 32 "orthos" at once. Which number you can use highly depends on the performance of your hardware.\r
 \r
-[REAL WORLD]\r
+This does everything for you.\r
 \r
-[RESULT]\r
+ATTENTION! This process will take a considerable amount of time due to the work being involved. Please keep this in mind, especially if you seek to do this for an entire country.\r
 \r
+For X-Plane scenery, you will need to do this once step 2 is done:\r
 \r
-Leverkusen, Germany\r
+[codebox]python main.py 51 7 xpscenery[codebox]\r
 \r
-[REAL WORLD]\r
+This will generate the terrain mesh and associate the textures with the mesh.\r
 \r
-[RESULT]\r
+I am considering hosting the finished tiles on my server, so that you only need to download the finished photos / tile packs.\r
 \r
 \r
 [section]Improving the code[/section]\r
index 059aa8d815f7a0f7788f8f3fb0795e3afec5f4f3..8a0551b6f423c7ab76b49415db95bf743ce9b1f7 100644 (file)
@@ -86,6 +86,10 @@ class mstr_xp_normalmap:
         mstr_msg("xp_normalmap", "[X-Plane] Beginning normal map generation")\r
         # No specularity, no reflectivity - but standard color\r
         # Blue (reflectivity) and alpha (specularity) need to be 1 - but can be adjusted as needed\r
+\r
+        # Resize original\r
+        image = image.resize((int(mstr_photores/4), int(mstr_photores/4)), Image.Resampling.BILINEAR)\r
+\r
         nmp = Image.new("RGBA", (image.width, image.height), (128,128,1,1))\r
         org = image.load()\r
         nmp_pix = nmp.load()\r
@@ -137,13 +141,13 @@ class mstr_xp_normalmap:
     \r
 \r
     # The funnction to call. Blends with the existing map, or creates a new one\r
-    def build_normalmap(self):\r
+    def build_normalmap(self, layer):\r
         mstr_msg("xp_normalmap", "[X-Plane] Building normal map")\r
         # The layer image\r
-        lyr = self.load_layer()\r
+        #lyr = self.load_layer()\r
 \r
         # Make the normal map for the layer\r
-        nrm = self.generate_normal_map_for_layer(lyr)\r
+        nrm = self.generate_normal_map_for_layer(layer)\r
 \r
         # Normal map final file name\r
         nrmfln = mstr_datafolder + "z_orthographic/normals/" + self._latlngfld + "/" + str(self._tv) + "_" + str(self._th) + ".png"\r