Example #1
0
    def test_points_pbf(self):
        '''
        Create 3 points (2 on west, 1 on east hemisphere) and retrieve as pbf.
        2 points should be returned in western hemisphere and 1 on eastern at zoom level 1
        (clip on)
        '''
        
        self.defineGeometry('POINT')

        point_sf = Point(-122.42, 37.78)
        point_berlin = Point(13.41, 52.52)
        point_lima = Point(-77.03, 12.04)

        self.insertTestRow(point_sf.wkt, 'San Francisco')
        self.insertTestRow(point_berlin.wkt, 'Berlin')
        self.insertTestRow(point_lima.wkt, 'Lima')

        ########
        # northwest quadrant should return San Francisco and Lima

        tile_mimetype, tile_content = utils.request(self.config_file_content, "vectile_test", "pbf", 0, 0, 1)
        pbf_result = mapbox_vector_tile.decode(tile_content)


        self.assertTrue(tile_mimetype.endswith('/x-protobuf'))
        self.assertIn('vectile_test', pbf_result)
        layer_result = pbf_result['vectile_test']
        self.assertEqual(len(layer_result['features']), 2)

        extent = tile_bounds_mercator(0, 0, 1)

        cities = []

        # Make sure that the right cities have been returned and that the geometries match

        for feature in layer_result['features']:
            if feature['properties']['name'] == 'San Francisco':
                cities.append(feature['properties']['name'])
                self.assertTrue(point_sf.almost_equals(decoded_pbf_asshape(feature, extent), decimal=1))

            elif feature['properties']['name'] == 'Lima':
                cities.append(feature['properties']['name'])
                self.assertTrue(point_lima.almost_equals(decoded_pbf_asshape(feature, extent), decimal=1))

        self.assertTrue('San Francisco' in cities)
        self.assertTrue('Lima' in cities)

        ##########
        # northeast quadrant should return Berlin

        tile_mimetype, tile_content = utils.request(self.config_file_content, "vectile_test", "pbf", 0, 1, 1)
        pbf_result = mapbox_vector_tile.decode(tile_content)

        self.assertTrue(tile_mimetype.endswith('/x-protobuf'))
        self.assertIn('vectile_test', pbf_result)
        layer_result = pbf_result['vectile_test']
        self.assertEqual(len(layer_result['features']), 1)
        self.assertTrue('Berlin' in layer_result['features'][0]['properties']['name'])
Example #2
0
    def test_points_pbf(self):
        """
        Create 3 points (2 on west, 1 on east hemisphere) and retrieve as pbf.
        2 points should be returned in western hemisphere and 1 on eastern at zoom level 1
        (clip on)
        """

        self.defineGeometry("POINT")

        point_sf = Point(-122.42, 37.78)
        point_berlin = Point(13.41, 52.52)
        point_lima = Point(-77.03, 12.04)

        self.insertTestRow(point_sf.wkt, "San Francisco")
        self.insertTestRow(point_berlin.wkt, "Berlin")
        self.insertTestRow(point_lima.wkt, "Lima")

        ########
        # northwest quadrant should return San Francisco and Lima

        tile_mimetype, tile_content = utils.request(self.config_file_content, "vectile_test", "pbf", 0, 0, 1)
        pbf_result = mapbox_vector_tile.decode(tile_content)

        self.assertTrue(tile_mimetype.endswith("/x-protobuf"))
        self.assertIn("vectile_test", pbf_result)
        layer_result = pbf_result["vectile_test"]
        self.assertEqual(len(layer_result["features"]), 2)

        extent = tile_bounds_mercator(0, 0, 1)

        cities = []

        # Make sure that the right cities have been returned and that the geometries match

        for feature in layer_result["features"]:
            if feature["properties"]["name"] == "San Francisco":
                cities.append(feature["properties"]["name"])
                self.assertTrue(point_sf.almost_equals(decoded_pbf_asshape(feature, extent), decimal=1))

            elif feature["properties"]["name"] == "Lima":
                cities.append(feature["properties"]["name"])
                self.assertTrue(point_lima.almost_equals(decoded_pbf_asshape(feature, extent), decimal=1))

        self.assertTrue("San Francisco" in cities)
        self.assertTrue("Lima" in cities)

        ##########
        # northeast quadrant should return Berlin

        tile_mimetype, tile_content = utils.request(self.config_file_content, "vectile_test", "pbf", 0, 1, 1)
        pbf_result = mapbox_vector_tile.decode(tile_content)

        self.assertTrue(tile_mimetype.endswith("/x-protobuf"))
        self.assertIn("vectile_test", pbf_result)
        layer_result = pbf_result["vectile_test"]
        self.assertEqual(len(layer_result["features"]), 1)
        self.assertTrue("Berlin" in layer_result["features"][0]["properties"]["name"])
Example #3
0
 def assertRoundTrip(self, input_geometry, expected_geometry, name=None,
                     properties=None, id=None, expected_len=1,
                     expected_properties=None):
     if input_geometry is None:
         input_geometry = self.feature_geometry
     if name is None:
         name = self.layer_name
     if properties is None:
         properties = self.feature_properties
     if expected_properties is None:
         expected_properties = properties
     source = [{
         "name": name,
         "features": [{
             "geometry": input_geometry,
             "properties": properties
         }]
     }]
     if id:
         source[0]['features'][0]['id'] = id
     encoded = encode(source)
     decoded = decode(encoded)
     self.assertIn(name, decoded)
     layer = decoded[name]
     features = layer['features']
     self.assertEqual(expected_len, len(features))
     self.assertEqual(features[0]['properties'], expected_properties)
     self.assertEqual(features[0]['geometry'], expected_geometry)
     if id:
         self.assertEqual(features[0]['id'], id)
Example #4
0
    def test_make_valid_can_return_multipolygon(self):
        from mapbox_vector_tile import encode
        from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
        import shapely.wkt
        import os.path

        test_dir = os.path.dirname(os.path.realpath(__file__))
        file_name = 'error_nested_multipolygon.wkt'

        with open(os.path.join(test_dir, file_name)) as fh:
            shape = wkt.loads(fh.read())

        features = [dict(geometry=shape, properties={})]
        pbf = encode({'name': 'foo', 'features': features},
                     quantize_bounds=(-10018754.1713946, 11271098.44281893,
                                      -8766409.899970269, 12523442.714243261),
                     on_invalid_geometry=on_invalid_geometry_make_valid)
        result = decode(pbf)
        features = result['foo']['features']
        self.assertEqual(1, len(features))
        geom = features[0]['geometry']
        self.assertEquals(geom['type'], 'MultiPolygon')
        multipolygon = shapely.geometry.shape(geom)
        self.assertTrue(multipolygon.is_valid)

        area = 0
        for p in multipolygon.geoms:
            self.assertTrue(p.is_valid)
            area += p.area
        self.assertEquals(4339852.5, area)
Example #5
0
 def test_decoder(self):
     if PY3:
         vector_tile = b'\x1aI\n\x05water\x12\x1a\x08\x01\x12\x06\x00\x00\x01\x01\x02\x02\x18\x03"\x0c\t\x00\x80@\x1a\x00\x01\x02\x00\x00\x02\x0f\x1a\x03foo\x1a\x03baz\x1a\x03uid"\x05\n\x03bar"\x05\n\x03foo"\x02 {(\x80 x\x02'  # noqa
     else:
         vector_tile = '\x1aI\n\x05water\x12\x1a\x08\x01\x12\x06\x00\x00\x01\x01\x02\x02\x18\x03"\x0c\t\x00\x80@\x1a\x00\x01\x02\x00\x00\x02\x0f\x1a\x03foo\x1a\x03baz\x1a\x03uid"\x05\n\x03bar"\x05\n\x03foo"\x02 {(\x80 x\x02'  # noqa
     self.assertEqual(mapbox_vector_tile.decode(vector_tile), {
         'water': {
             'version': 2,
             'extent': 4096,
             'features': [{
                 'geometry': {
                     'type': 'Polygon',
                     'coordinates': [
                         [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]
                     ]
                 },
                 'properties': {
                     'foo': 'bar',
                     'baz': 'foo',
                     'uid': 123
                 },
                 'id': 1,
                 'type': 3
             }],
         },
     })
Example #6
0
    def test_bowtie_self_crossing(self):
        from mapbox_vector_tile import encode
        from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
        import shapely.geometry
        import shapely.wkt
        bowtie = ('POLYGON ((0 0, 2 2, 2 0, 0 2, 0 0))')
        shape = shapely.wkt.loads(bowtie)
        self.assertFalse(shape.is_valid)
        feature = dict(geometry=shape, properties={})
        source = dict(name='layername', features=[feature])
        pbf = encode(source,
                     on_invalid_geometry=on_invalid_geometry_make_valid)
        result = decode(pbf)
        self.assertEqual(1, len(result['layername']['features']))
        valid_geometries = result['layername']['features'][0]['geometry']
        multipolygon = shapely.geometry.shape(valid_geometries)
        self.assertEqual(multipolygon.geom_type, 'MultiPolygon')
        self.assertTrue(multipolygon.is_valid)

        total_area = 0
        for p in multipolygon.geoms:
            self.assertEqual(p.geom_type, 'Polygon')
            self.assertTrue(p.is_valid)
            self.assertGreater(p.area, 0)
            total_area += p.area
        self.assertEquals(2, total_area)
Example #7
0
    def test_make_valid_self_crossing(self):
        from mapbox_vector_tile import encode
        from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
        import shapely.geometry
        import shapely.wkt
        geometry = 'POLYGON ((10 10, 20 10, 20 20, 15 15, 15 5, 10 10))'
        shape = shapely.wkt.loads(geometry)
        self.assertFalse(shape.is_valid)
        feature = dict(geometry=shape, properties={})
        source = dict(name='layername', features=[feature])
        pbf = encode(source,
                     on_invalid_geometry=on_invalid_geometry_make_valid)
        result = decode(pbf)
        self.assertEqual(1, len(result['layername']['features']))
        valid_geometries = result['layername']['features'][0]['geometry']
        geom_type = result['layername']['features'][0]['type']
        self.assertEqual(3, geom_type)  # 3 means POLYGON
        self.assertEqual(valid_geometries['type'], 'MultiPolygon')
        multipolygon = shapely.geometry.shape(valid_geometries)
        self.assertTrue(multipolygon.is_valid)

        total_area = 0
        for p in multipolygon.geoms:
            self.assertTrue(p.is_valid)
            self.assertGreater(p.area, 0)
            total_area += p.area

        self.assertEquals(50, total_area)
        self.assertEquals(50, multipolygon.area)
Example #8
0
def copy_dir(root_src_dir, root_dst_dir):
    """ Copy vector tiles from source to destination directory with overlap handling"""

    for src_dir, dirs, files in os.walk(root_src_dir):
        dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)

        if not os.path.exists(dst_dir):
            os.makedirs(dst_dir)
        for file_ in files:
            src_file = os.path.join(src_dir, file_)
            dst_file = os.path.join(dst_dir, file_)
            if os.path.exists(dst_file):                
                # If we have .pbf's that clash, we want to merge them 
                # together and write them to the new directory as dst_dir

                if file_ == "metadata.json":
                    os.remove(dst_file)
                else:
                    print "\n Merging tiles to... " + dst_file

                    with open(src_file, 'rb') as f:
                        data = f.read()
                    decoded_data1 = mapbox_vector_tile.decode(data)

                    with open(dst_file, 'rb') as f:
                        data = f.read()
                    decoded_data2 = mapbox_vector_tile.decode(data)
                    
                    for k, v in decoded_data2.items():
                        if k in decoded_data1:
                            decoded_data1[k]["features"] += decoded_data2[k]["features"]
                        else:
                            decoded_data1[k] = decoded_data2[k]                       

                    listofdict = []
                    for k, v in decoded_data1.items():
                        dic = {
                            'name': k,
                            'features': decoded_data1[k]["features"]
                        }
                        listofdict.append(dic)

                    encoded_data = mapbox_vector_tile.encode(listofdict)
                    with open(dst_file, 'w') as f:
                        f.write(encoded_data)
            else:                
                shutil.copy(src_file, dst_dir)
Example #9
0
    def parse_data(self, x, y, zoom, data):
        self.x = x
        self.y = y
        self.zoom = zoom

        tile = mapbox_vector_tile.decode(data)
        self.extent = tile["osm"]["extent"]
        for feature in tile["osm"]["features"]:
            self._handle_feature(feature)
Example #10
0
    def test_retrieve_valid_tiles(self):
        point = sample_point()
        url = mvt_url(0, 0, 0)

        res = self.client.get(url)

        decoded_data = mapbox_vector_tile.decode(res.content)

        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertIsNotNone(decoded_data)
Example #11
0
 def _decode_binary_tile_data(self, data):
     try:
         # The offset of 32 signals to the zlib header that the gzip header is expected but skipped.
         file_content = zlib.decompress(data, 32 + zlib.MAX_WBITS)
         decoded_data = mapbox_vector_tile.decode(file_content)
     except:
         print "decoding data with mapbox_vector_tile failed", sys.exc_info(
         )
         return
     return decoded_data
Example #12
0
    def getTile(self, zoom_level, tile_col, tile_row):
        import mapbox_vector_tile

        con = sqlite3.connect(self.source.resolve())
        tile_data = con.execute('''
       SELECT tile_data FROM tiles
           WHERE zoom_level = ?
             AND tile_column = ?
             AND tile_row = ?''', (zoom_level, tile_col, tile_row)).fetchone()[0]

        return mapbox_vector_tile.decode(gzip.decompress(tile_data))
    def test_encode_multipolygon(self):
        geometry = 'MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)))'
        expected_result = '\x1a9\n\x05water\x12\x0e\x18\x03"\n\tP\xb0?\x12\'\t2\x1e\x0f\x12\x1b\x18\x03"\x17\t(\xba?"\x13\n\x00((\n\x1e\x1d\x0f\t\x1d\x00\x12\x13\n\x00\x13\x0f(\x80 x\x02'
        result = mapbox_vector_tile.encode([
            dict(name='water',
                 features=[dict(geometry=geometry, properties={})])])
        self.assertEqual(expected_result, result)

        decoded = mapbox_vector_tile.decode(result)
        features = decoded['water']
        self.assertEqual(2, len(features))
Example #14
0
    def test_merge_tile_directories_with_overlap(self):

        config_path_1 = "/tiler-data/test-data/configs/mergeOverlap1.tiler.json"
        self.assertTrue(os.path.isfile(config_path_1))
        tiles_from_config(config_path_1)
        output_path_1 = "/tiler-data/tiles/test_merge_overlap_1"
        self.assertTrue(os.path.isdir(output_path_1))

        config_path_2 = "/tiler-data/test-data/configs/mergeOverlap2.tiler.json"
        self.assertTrue(os.path.isfile(config_path_2))
        tiles_from_config(config_path_2)
        output_path_2 = "/tiler-data/tiles/test_merge_overlap_2"
        self.assertTrue(os.path.isdir(output_path_2))

        out_dir = "/tiler-data/tiles/merge-test-overlap/"
        merge_tile_directories(output_path_1, output_path_2, out_dir)

        with open("/tiler-data/tiles/merge-test-overlap/2/0/1.pbf", 'rb') as f:
            data = f.read()
        overlap_merge = mapbox_vector_tile.decode(data)

        with open("/tiler-data/tiles/test_merge_overlap_1/2/0/1.pbf",
                  'rb') as f:
            data = f.read()
        overlap_1 = mapbox_vector_tile.decode(data)

        with open("/tiler-data/tiles/test_merge_overlap_2/2/0/1.pbf",
                  'rb') as f:
            data = f.read()
        overlap_2 = mapbox_vector_tile.decode(data)

        self.assertTrue(os.path.isdir(out_dir))
        self.assertTrue(get_num_pbfs(out_dir) > 0)
        self.assertTrue(
            str(overlap_merge).find("Pizazz")
            and str(overlap_1).find("Pizazz"))
        self.assertEqual(str(overlap_2).find("Pizazz"), -1)
        self.assertTrue(
            str(overlap_merge).find("Hungry")
            and str(overlap_2).find("Hungry"))
        self.assertEqual(str(overlap_1).find("Hungry"), -1)
 def test_encode_feature_with_id(self):
     geometry = 'POINT(1 1)'
     expected_result = '\x1a\x18\n\x05water\x12\n\x08*\x18\x01"\x04\t\x02\xfe?(\x80 x\x02'
     result = mapbox_vector_tile.encode([
         dict(name='water',
              features=[dict(geometry=geometry, properties={}, id=42)])])
     self.assertEqual(expected_result, result)
     decoded = mapbox_vector_tile.decode(result)
     features = decoded['water']
     self.assertEqual(1, len(features))
     feature = features[0]
     self.assertEqual(42, feature['id'])
Example #16
0
 def test_too_small_linestring(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
     import shapely.wkt
     shape = shapely.wkt.loads(
         'LINESTRING(-71.160281 42.258729,-71.160837 42.259113,-71.161144 42.25932)')  # noqa
     features = [dict(geometry=shape, properties={})]
     pbf = encode({'name': 'foo', 'features': features},
                  on_invalid_geometry=on_invalid_geometry_make_valid)
     result = decode(pbf)
     features = result['foo']['features']
     self.assertEqual(0, len(features))
 def test_invalid_geometry_ignore(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_ignore
     import shapely.wkt
     geometry = 'POLYGON ((10 10, 20 10, 20 20, 15 15, 15 5, 10 10))'
     shape = shapely.wkt.loads(geometry)
     self.assertFalse(shape.is_valid)
     feature = dict(geometry=shape, properties={})
     source = dict(name='layername', features=[feature])
     pbf = encode(source, on_invalid_geometry=on_invalid_geometry_ignore)
     result = decode(pbf)
     self.assertEqual(0, len(result['layername']['features']))
Example #18
0
 def test_too_small_geometry(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
     import shapely.wkt
     shape = shapely.wkt.loads(
         'LINESTRING (3065.656210384849 3629.831662879646, 3066.458953567231 3629.725941289478)')  # noqa
     features = [dict(geometry=shape, properties={})]
     pbf = encode({'name': 'foo', 'features': features},
                  on_invalid_geometry=on_invalid_geometry_make_valid)
     result = decode(pbf)
     features = result['foo']['features']
     self.assertEqual(0, len(features))
Example #19
0
 def test_quantize_makes_mutlipolygon_invalid(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
     import shapely.wkt
     shape = shapely.wkt.loads('MULTIPOLYGON (((656510.8206577231 5674684.979891453, 656511.16 5674685.9, 656514.1758819892 5674684.979891453, 656510.8206577231 5674684.979891453)), ((657115.9120547654 5674684.979891453, 657118.85 5674690, 657118.0689111941 5674684.979891453, 657115.9120547654 5674684.979891453)))')  # noqa
     quantize_bounds = (645740.0149532147, 5674684.979891453, 665307.8941942193, 5694252.8591324575)  # noqa
     features = [dict(geometry=shape, properties={})]
     pbf = encode({'name': 'foo', 'features': features},
                  quantize_bounds=quantize_bounds,
                  on_invalid_geometry=on_invalid_geometry_make_valid)
     result = decode(pbf)
     features = result['foo']['features']
     self.assertEqual(1, len(features))
    def test_quantize_and_y_coord_down(self):
        from mapbox_vector_tile import decode
        from mapbox_vector_tile import encode
        props = dict(foo='bar')
        shape = 'POINT(30 30)'
        feature = dict(geometry=shape, properties=props)
        features = [feature]
        source = dict(name='layername', features=features)
        bounds = 0.0, 0.0, 50.0, 50.0
        pbf = encode(source, quantize_bounds=bounds, y_coord_down=True)

        result_decode_no_flip = decode(pbf, y_coord_down=True)
        act_feature = result_decode_no_flip['layername']['features'][0]
        act_geom = act_feature['geometry']
        exp_geom = [[2458, 2458]]
        self.assertEqual(exp_geom, act_geom)

        result_decode_flip = decode(pbf)
        act_feature = result_decode_flip['layername']['features'][0]
        act_geom = act_feature['geometry']
        exp_geom = [[2458, 1638]]
        self.assertEqual(exp_geom, act_geom)
Example #21
0
    def mapper(self, x, y, zoom, data):
        if data is None:
            return 0

        tile = mapbox_vector_tile.decode(data)

        count = 0
        if tile.get('buildings'):
            count += len(tile['buildings'])
        if tile.get('roads'):
            count += len(tile['roads'])

        return count
 def test_y_coord_down(self):
     from mapbox_vector_tile import decode
     from mapbox_vector_tile import encode
     props = dict(foo='bar')
     shape = 'POINT(10 10)'
     feature = dict(geometry=shape, properties=props)
     features = [feature]
     source = dict(name='layername', features=features)
     pbf = encode(source, y_coord_down=True)
     result = decode(pbf, y_coord_down=True)
     act_feature = result['layername']['features'][0]
     act_geom = act_feature['geometry']
     exp_geom = [[10, 10]]
     self.assertEqual(exp_geom, act_geom)
	def test_decoder(self):
		vector_tile = '\x1aI\n\x05water\x12\x1a\x08\x01\x12\x06\x00\x00\x01\x01\x02\x02\x18\x03"\x0c\t\x00\x80@\x1a\x00\x01\x02\x00\x00\x02\x0f\x1a\x03foo\x1a\x03baz\x1a\x03uid"\x05\n\x03bar"\x05\n\x03foo"\x02 {(\x80 x\x02'
		self.assertEqual(mapbox_vector_tile.decode(vector_tile), 
				{
					'water': [{
						'geometry': [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]], 
						'properties': {
							'foo': 'bar', 
							'baz': 'foo', 
							'uid': 123
						}, 
						'id': 1
					}]
				}
			)
Example #24
0
 def test_quantize(self):
     from mapbox_vector_tile import decode
     from mapbox_vector_tile import encode
     props = dict(foo='bar')
     shape = 'POINT(15 15)'
     feature = dict(geometry=shape, properties=props)
     features = [feature]
     source = dict(name='layername', features=features)
     bounds = 10.0, 10.0, 20.0, 20.0
     pbf = encode(source, quantize_bounds=bounds)
     result = decode(pbf)
     act_feature = result['layername']['features'][0]
     act_geom = act_feature['geometry']
     exp_geom = {'type': 'Point', 'coordinates': [2048, 2048]}
     self.assertEqual(exp_geom, act_geom)
 def test_custom_extent(self):
     from mapbox_vector_tile import decode
     from mapbox_vector_tile import encode
     props = dict(foo='bar')
     shape = 'POINT(10 10)'
     feature = dict(geometry=shape, properties=props)
     features = [feature]
     source = dict(name='layername', features=features)
     bounds = 0.0, 0.0, 10.0, 10.0
     pbf = encode(source, quantize_bounds=bounds, extents=50)
     result = decode(pbf)
     act_feature = result['layername']['features'][0]
     act_geom = act_feature['geometry']
     exp_geom = [[50, 50]]
     self.assertEqual(exp_geom, act_geom)
Example #26
0
    def test_MVT_MRF_generation(self):
        # Process config file
        test_artifact_path = os.path.join(self.main_artifact_path, 'mvt_mrf')
        config = self.parse_vector_config(self.mrf_test_config, test_artifact_path)
        
        # Run vectorgen
        os.chdir(test_artifact_path)
        if os.path.isfile("../../tilematrixsets.xml") == False: # Check for tilematrixsets.xml
            if os.path.isfile("/etc/onearth/config/conf/tilematrixsets.xml"):
                os.symlink("/etc/onearth/config/conf/tilematrixsets.xml", test_artifact_path+"/tilematrixsets.xml")
            else:
                self.fail("Cannot find tilematrixsets.xml. Aborting test.")
        else:
            os.symlink("../../tilematrixsets.xml", test_artifact_path+"/tilematrixsets.xml")
        cmd = 'oe_vectorgen -c ' + self.mrf_test_config
        run_command(cmd, ignore_warnings=True)

        # Get index of first, second-to-last, and last tile in MRF
        with open(os.path.join(config['output_dir'], config['prefix'] + '.idx'), 'rb') as idx:
            first_byte = idx.read(16)
            idx.seek(-32, 2)
            penultimate_byte = idx.read(16)
            last_byte = idx.read(16)
        top_tile_feature_count = 0
        for byte in (first_byte, penultimate_byte, last_byte):
            tile_buffer = StringIO.StringIO()
            offset = struct.unpack('>q', byte[0:8])[0]
            size = struct.unpack('>q', byte[8:16])[0]
            with open(os.path.join(config['output_dir'], config['prefix'] + '.pvt'), 'rb') as pvt:
                pvt.seek(offset)
                tile_buffer.write(pvt.read(size))
            tile_buffer.seek(0)
            # Check to see if extracted files are valid zip files and valid MVT tiles
            try:
                unzipped_tile = gzip.GzipFile(fileobj=tile_buffer)
                tile_data = unzipped_tile.read()
            except IOError:
                self.fail("Invalid tile found in MRF -- can't be unzipped.")
            try:
                tile = mapbox_vector_tile.decode(tile_data)
            except:
                self.fail("Can't decode MVT tile -- bad protobuffer or wrong MVT structure")
            # Check the top 2 tiles to see if they have any features (they should)
            if byte != first_byte:
                top_tile_feature_count += len(tile[tile.keys()[0]]['features'])
        self.assertTrue(top_tile_feature_count, "Top two files contain no features -- MRF likely was not created correctly.")
    def test_custom_rounding_function(self):
        from mapbox_vector_tile import decode
        from mapbox_vector_tile import encode
        props = dict(foo='bar')
        shape = 'POINT(10 10)'
        feature = dict(geometry=shape, properties=props)
        features = [feature]
        source = dict(name='layername', features=features)
        bounds = 0.0, 0.0, 10.0, 10.0
        # A really bad, custom "rounding" function
        pbf = encode(source, quantize_bounds=bounds, round_fn=lambda x: 5)
        result = decode(pbf)

        act_feature = result['layername']['features'][0]
        act_geom = act_feature['geometry']
        exp_geom = [[5, 5]]
        self.assertEqual(exp_geom, act_geom)
Example #28
0
 def test_flipped_geometry_produces_multipolygon(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
     import shapely.wkt
     shape = shapely.wkt.loads('POLYGON ((3449 1939, 3476 1967, 3473 1996, 3483 2027, 3542 2119, 3538 2160, 3563 2233, 3602 2255, 3639 2326, 3629 2388, 3573 2455, 3594 2493, 3558 2533, 3573 2549, 3518 2572, 3502 2592, 3505 2607, 3513 2614, 3535 2616, 3537 2610, 3535 2602, 3537 2599, 3548 2607, 3551 2636, 3528 2634, 3537 2668, 3549 2670, 3528 2711, 3550 2667, 3532 2635, 3550 2641, 3553 2613, 3549 2602, 3540 2596, 3512 2610, 3506 2589, 3576 2552, 3576 2543, 3563 2535, 3596 2506, 3597 2494, 3587 2469, 3589 2451, 3636 2385, 3644 2326, 3605 2251, 3566 2230, 3547 2122, 3482 2014, 3479 1966, 3455 1944, 3458 1910, 3449 1902, 3449 1939))')  # noqa
     features = [dict(geometry=shape, properties={})]
     pbf = encode({'name': 'foo', 'features': features},
                  on_invalid_geometry=on_invalid_geometry_make_valid)
     result = decode(pbf)
     features = result['foo']['features']
     self.assertEqual(1, len(features))
     geom = shapely.geometry.shape(features[0]['geometry'])
     self.assertEqual(features[0]['geometry']['type'], 'MultiPolygon')
     self.assertEqual(geom.geom_type, 'MultiPolygon')
     self.assertTrue(geom.is_valid)
     for poly in geom.geoms:
         self.assertTrue(poly.is_valid)
    def test_nondefault_extent(self):
        if PY3:
            vector_tile = b'\x1aK\n\x05water\x12\x1c\x08\x01\x12\x06\x00\x00\x01\x01\x02\x02\x18\x02"\x0e\t\x80}\xd0\x12\x12\xbf>\xd86\xbf>\xd86\x1a\x03foo\x1a\x03baz\x1a\x03uid"\x05\n\x03bar"\x05\n\x03foo"\x02 {(\x80@x\x02'  # noqa
        else:
            vector_tile = '\x1aK\n\x05water\x12\x1c\x08\x01\x12\x06\x00\x00\x01\x01\x02\x02\x18\x02"\x0e\t\x80}\xd0\x12\x12\xbf>\xd86\xbf>\xd86\x1a\x03foo\x1a\x03baz\x1a\x03uid"\x05\n\x03bar"\x05\n\x03foo"\x02 {(\x80@x\x02'  # noqa

        self.assertEqual(mapbox_vector_tile.decode(vector_tile), {
            'water': {
                'version': 2,
                'extent': 8192,
                'features': [{
                    'geometry': [[8000, 7000], [4000, 3500], [0, 0]],
                    'id': 1,
                    'properties': {'baz': 'foo', 'foo': 'bar', 'uid': 123},
                    'type': 2
                }],
            }
        })
 def test_validate_generates_rounding_error(self):
     from mapbox_vector_tile import encode
     from mapbox_vector_tile.encoder import on_invalid_geometry_make_valid
     import shapely.geometry
     import shapely.wkt
     bowtie = ('POLYGON((0 0, 1 1, 0 1, 1 0, 0 0))')
     shape = shapely.wkt.loads(bowtie)
     self.assertFalse(shape.is_valid)
     feature = dict(geometry=shape, properties={})
     source = dict(name='layername', features=[feature])
     pbf = encode(source,
                  on_invalid_geometry=on_invalid_geometry_make_valid)
     result = decode(pbf)
     features = result['layername']['features']
     self.assertEqual(1, len(features))
     shape = shapely.geometry.Polygon(features[0]['geometry'][0])
     self.assertTrue(shape.is_valid)
     self.assertGreater(shape.area, 0)
Example #31
0
    def test_polygon_pbf(self):
        '''
        Create a polygon to cover the world and make sure it is "similar" (clip on) (pbf)
        '''
        self.defineGeometry('POLYGON')

        geom = Polygon([(-180, -85.05),
                        (180, -85.05),
                        (180, 85.05),
                        (-180, 85.05),
                        (-180, -85.05)])

        self.insertTestRow(geom.wkt)

        tile_mimetype, tile_content = utils.request(self.config_file_content, "vectile_test", "pbf", 0, 0, 0)
        self.assertTrue(tile_mimetype.endswith('/x-protobuf'))
        pbf_result = mapbox_vector_tile.decode(tile_content)
        layer_result = pbf_result['vectile_test']

        extent = tile_bounds_mercator(0, 0, 0)

        result_geom = decoded_pbf_asshape(layer_result['features'][0], extent)
        expected_geom = Polygon([(-180, -85.05), (180, -85.05), (180, 85.05), (-180, 85.05), (-180, -85.05)])

        # What is going on here is a bit unorthodox, but let me explain. The clipping
        # code inside TileStache relies on GEOS Intersection alongside some TileStache code
        # that creates a clipping geometry based on the tile perimeter. The tile perimeter
        # is made out of 17 (x,y) coordinates and not a box. Hence, the GEOS::Intersection
        # os that perimeter with the geometry of the vector we get back from the data provider
        # can end with extra vertices. Although it is the right shape, we cannot do a straight
        # comparisson because the expected geometry and the returned geometry *may* have extra
        # vertices. Simplify() will not do much because the distance of the vertices can clearly
        # be bigger than the tolerance. 
        #
        # To add to this, because of double precision, the vertices may not be exact.
        # An optional way to find out if two shapes are close enough, is to buffer the two features
        # by just a little bit and then subtract each other like so:
        #
        #             geometry1.difference(geometry2) == empty set?
        #             geometry2.difference(geometry1) == empty set?
        # 
        # If both geometries are empty, then they are similar. Hence what you see below
        self.assertTrue(result_geom.difference(expected_geom.buffer(0.01)).is_empty)
        self.assertTrue(expected_geom.difference(result_geom.buffer(0.01)).is_empty)
 def test_vector_tile_endpoint_pbf(self):
     # Get url for a tile.
     self.url = reverse('vectortiles-list', kwargs={'aggregationlayer': self.agglayer.id, 'z': 11, 'x': 552, 'y': 859, 'frmt': 'pbf'})
     # Setup request with fromula that will multiply the rasterlayer by itself
     response = self.client.get(self.url)
     self.assertEqual(response.status_code, 200)
     result = mapbox_vector_tile.decode(response.content)
     self.assertEqual(
         'St Petersburg',
         result['My Aggregation Layer']['features'][0]['properties']['name'],
     )
     self.assertEqual(
         'Coverall',
         result['My Aggregation Layer']['features'][1]['properties']['name'],
     )
     self.assertEqual(
         [3267, 3986],
         result['My Aggregation Layer']['features'][0]['geometry']['coordinates'][0][0][0],
     )
Example #33
0
 def test_encode_multiple_values_test(self):
     geometry = 'POINT(0 0)'
     properties1 = dict(foo='bar', baz='bar')
     properties2 = dict(quux='morx', baz='bar')
     name = 'foo'
     feature1 = dict(geometry=geometry, properties=properties1)
     feature2 = dict(geometry=geometry, properties=properties2)
     source = [{
         "name": name,
         "features": [feature1, feature2]
     }]
     encoded = encode(source)
     decoded = decode(encoded)
     self.assertIn(name, decoded)
     layer = decoded[name]
     features = layer['features']
     self.assertEqual(2, len(features))
     self.assertEqual(features[0]['properties'], properties1)
     self.assertEqual(features[1]['properties'], properties2)
Example #34
0
def check_valid_mvt(file, warn_if_empty=False):
    tile_buffer = StringIO.StringIO()
    tile_buffer.write(file.read())
    tile_buffer.seek(0)
    try:
        unzipped_tile = gzip.GzipFile(fileobj=tile_buffer)
        tile_data = unzipped_tile.read()
    except IOError:
        return False
    try:
        tile = mapbox_vector_tile.decode(tile_data)
    except:
        return False
    if warn_if_empty:
        try:
            num_features = len(tile[tile.keys()[0]]['features'])
        except IndexError:
            return False
    return True
 def test_decode_polygon_no_cmd_seg_end(self):
     # the binary here was generated without including the
     # CMD_SEG_END after the polygon parts
     # this tests that the decoder can detect that a new
     # CMD_MOVE_TO implicitly closes the previous polygon
     if PY3:
         vector_tile = b'\x1a+\n\x05water\x12\x1d\x18\x03"\x19\t\x00\x80@"\x08\x00\x00\x07\x07\x00\x00\x08\t\x02\x01"\x00\x03\x04\x00\x00\x04\x03\x00(\x80 x\x02'  # noqa
     else:
         vector_tile = '\x1a+\n\x05water\x12\x1d\x18\x03"\x19\t\x00\x80@"\x08\x00\x00\x07\x07\x00\x00\x08\t\x02\x01"\x00\x03\x04\x00\x00\x04\x03\x00(\x80 x\x02'  # noqa
     self.assertEqual(mapbox_vector_tile.decode(vector_tile), {
         'water': [{
             'geometry': [
                 [[0, 0], [4, 0], [4, 4], [0, 4], [0, 0]],
                 [[1, 1], [1, 3], [3, 3], [3, 1], [1, 1]],
             ],
             'properties': {},
             'id': 0,
             'type': 3
         }]
     })