From cdb0b57768a7c7bc93b84d5fb051eb0d613573e3 Mon Sep 17 00:00:00 2001 From: Joseph Camp Date: Fri, 11 Sep 2020 18:28:18 +0000 Subject: [PATCH] Improve multiple crop zone support Amends handling of the 'crop' render option such that when multiple crop zones are specified, one CroppedRegionSet with many crop zones is used rather than many CroppedRegionSets each with one crop zone. This resolves issues where crop zones within the same render could clobber each others tiles if close enough and could be rendered with a different number of zoom levels. --- overviewer.py | 17 ++++---------- overviewer_core/world.py | 50 ++++++++++++++++++---------------------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/overviewer.py b/overviewer.py index e29c66071..dfc350118 100755 --- a/overviewer.py +++ b/overviewer.py @@ -531,20 +531,12 @@ def set_renderchecks(checkname, num): # If a crop is requested, wrap the regionset here if "crop" in render: - rsets = [] - for zone in render['crop']: - rsets.append(world.CroppedRegionSet(rset, *zone)) - else: - rsets = [rset] + rset = world.CroppedRegionSet(rset, render['crop']) # If this is to be a rotated regionset, wrap it in a RotatedRegionSet # object if (render['northdirection'] > 0): - newrsets = [] - for r in rsets: - r = world.RotatedRegionSet(r, render['northdirection']) - newrsets.append(r) - rsets = newrsets + rset = world.RotatedRegionSet(rset, render['northdirection']) ############################### # Do the final prep and create the TileSet object @@ -560,9 +552,8 @@ def set_renderchecks(checkname, num): "dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom", "showlocationmarker", "minzoom", "center"]) tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this - for rset in rsets: - tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir) - tilesets.append(tset) + tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir) + tilesets.append(tset) # If none of the requested dimenstions exist, tilesets will be empty if not tilesets: diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 8cb621337..8dbc4d746 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -2034,42 +2034,38 @@ def iterate_newer_chunks(self, filemtime): yield x,z,mtime class CroppedRegionSet(RegionSetWrapper): - def __init__(self, rsetobj, xmin, zmin, xmax, zmax): + def __init__(self, rsetobj, cropzones): super(CroppedRegionSet, self).__init__(rsetobj) - self.xmin = xmin//16 - self.xmax = xmax//16 - self.zmin = zmin//16 - self.zmax = zmax//16 - - def get_chunk(self,x,z): - if ( - self.xmin <= x <= self.xmax and - self.zmin <= z <= self.zmax - ): - return super(CroppedRegionSet, self).get_chunk(x,z) + newcropzones = [] + for cz in cropzones: + # Crop zone format: (xmin, zmin, xmax, zmax) + newcropzones.append(tuple([x // 16 for x in cz])) + self.cropzones = newcropzones + + def chunk_in_cropzone(self, x, z): + # Determines if chunk at (x, z) is within one of the defined crop zones + for cz in self.cropzones: + if cz[0] <= x <= cz[2] and cz[1] <= z <= cz[3]: + return True + return False + + def get_chunk(self, x, z): + if self.chunk_in_cropzone(x, z): + return super(CroppedRegionSet, self).get_chunk(x, z) else: raise ChunkDoesntExist("This chunk is out of the requested bounds") def iterate_chunks(self): - return ((x,z,mtime) for (x,z,mtime) in super(CroppedRegionSet,self).iterate_chunks() - if - self.xmin <= x <= self.xmax and - self.zmin <= z <= self.zmax - ) + return ((x, z, mtime) for (x, z ,mtime) in super(CroppedRegionSet,self).iterate_chunks() + if self.chunk_in_cropzone(x, z)) def iterate_newer_chunks(self, filemtime): - return ((x,z,mtime) for (x,z,mtime) in super(CroppedRegionSet,self).iterate_newer_chunks(filemtime) - if - self.xmin <= x <= self.xmax and - self.zmin <= z <= self.zmax - ) + return ((x, z, mtime) for (x, z, mtime) in super(CroppedRegionSet,self).iterate_newer_chunks(filemtime) + if self.chunk_in_cropzone(x, z)) def get_chunk_mtime(self,x,z): - if ( - self.xmin <= x <= self.xmax and - self.zmin <= z <= self.zmax - ): - return super(CroppedRegionSet, self).get_chunk_mtime(x,z) + if self.chunk_in_cropzone(x, z): + return super(CroppedRegionSet, self).get_chunk_mtime(x, z) else: return None