Is there a way to fill a country with an image similar to R solution using custom library here:
I have a solution where the face colour is filled for instance the below where Italy is blue. However, I would like to add the Italian flag. Is there a way in Python (I have not found much after searching) or is something like QGIS needed:
JavaScript
x
31
31
1
#create a map where I can load images in to fill the countries
2
import cartopy
3
import cartopy.crs as ccrs
4
import matplotlib.pyplot as plt
5
import cartopy.io.shapereader as shpreader
6
7
flag = "italy.png" #this is a locally saved png.
8
9
plt.figure(figsize=(15, 15)) #size of plot
10
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
11
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
12
ax.coastlines(resolution='110m') #simplifies the border lines
13
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0") #colour of ocean
14
# ax.gridlines() #adds global grid lines
15
ax.set_extent ((-7.5, 50, 34, 69), cartopy.crs.PlateCarree()) #makes it european
16
17
18
shpfilename = shpreader.natural_earth(resolution='110m',
19
category='cultural',
20
name='admin_0_countries')
21
22
for country in shpreader.Reader(shpfilename).records():
23
if country.attributes['NAME_LONG'] == "Italy":
24
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
25
facecolor="blue",
26
#no attribute like this img= "fd",
27
28
label=country.attributes['NAME_LONG'])
29
30
plt.show()
31
Any help, much appreciated!
Advertisement
Answer
Here is a demo code that does what you need. As a matter of fact, cartopy logo
uses this technique to create.
JavaScript
1
64
64
1
import cartopy
2
import cartopy.crs as ccrs
3
import matplotlib.pyplot as plt
4
import cartopy.io.shapereader as shpreader
5
import matplotlib.patches as mpatches
6
import numpy as np
7
8
imdat1 = plt.imread('flag-of-italy.jpg', format='jpg') # use your flag
9
10
plt.figure(figsize=(8, 8))
11
ax = plt.axes(projection=cartopy.crs.TransverseMercator(25))
12
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=1)
13
ax.coastlines(resolution='110m')
14
ax.add_feature(cartopy.feature.OCEAN, facecolor="#40e0d0")
15
# ax.gridlines() #adds global grid lines
16
ax.set_extent ((-7.5, 50, 24, 69), cartopy.crs.PlateCarree())
17
18
shpfilename = shpreader.natural_earth(resolution='110m',
19
category='cultural',
20
name='admin_0_countries')
21
22
italy_ctry = None #use this to grab italy's
23
24
for country in shpreader.Reader(shpfilename).records():
25
if country.attributes['NAME_LONG'] == "Italy":
26
italy_ctry = country
27
ax.add_geometries(country.geometry, ccrs.PlateCarree(),
28
facecolor="none",
29
alpha=0.7,
30
zorder=2,
31
label=country.attributes['NAME_LONG'])
32
33
# create mpatch from `italy` geometry
34
cg = italy_ctry.geometry
35
cg2 = cg.simplify(0.02)
36
37
if cg2.geometryType()=='MultiPolygon':
38
# if == `Polygon`, dont need to loop
39
for ea in cg2.geoms:
40
cg2xy = ea.exterior.xy # tuple of (x,y)
41
xys = []
42
for ea in zip(cg2xy[0], cg2xy[1]):
43
#print(ea[0],ea[1])
44
xys.append([ea[0],ea[1]])
45
46
# add a patch
47
poly = mpatches.Polygon(xys, closed=True, ec='r',
48
lw=2, fc='yellow',
49
transform=ccrs.PlateCarree(),
50
alpha=0.5, zorder=30)
51
52
plate_carree_transform = ccrs.PlateCarree()._as_mpl_transform(ax)
53
54
xtent1 = (6.519950, 17.122259, 35.783370, 47.962952)
55
imdat2 = ax.imshow(imdat1, origin='upper', extent=xtent1,
56
transform=ccrs.PlateCarree(),
57
zorder=15, alpha=.9)
58
59
##imdat2 = ax.stock_img() #for testing
60
imdat2.set_clip_path(mpatches.Path(xys), transform=plate_carree_transform)
61
pass
62
63
plt.show()
64
The sample plot (varies with the flag in use):