def test_landmask_contains():
    delete_mask()
    l = Landmask()

    onland = (np.array([15.]), np.array([65.6]))
    assert l.contains(onland[0], onland[1])

    onland = (np.array([10.]), np.array([60.0]))
    assert l.contains(onland[0], onland[1])

    onocean = (np.array([5.]), np.array([65.6]))
    assert not l.contains(onocean[0], onocean[1])

    l.contains([180], [90])
    l.contains([-180], [90])
    l.contains([180], [-90])
    l.contains([-180], [-90])
def test_tromsoe(tmpdir):
    delete_mask()

    # xmin, ymin, xmax, ymax
    extent = [18.64, 69.537, 19.37, 69.91]
    l = Landmask(extent)

    lon = np.arange(18.8, 18.969, .0003)
    lat = np.arange(69.59, 69.70, .0003)

    xx, yy = np.meshgrid(lon, lat)
    c = l.contains(xx.ravel(), yy.ravel(), True)
    c = c.reshape(xx.shape)

    print("c:", c)

    import cartopy
    import cartopy.crs as ccrs
    import matplotlib.pyplot as plt
    import os
    plt.figure(dpi=200)
    ax = plt.axes(projection=ccrs.PlateCarree())
    # ax.contourf(lon, lat, c, transform = ccrs.PlateCarree())
    ax.imshow(c,
              extent=[np.min(lon),
                      np.max(lon),
                      np.min(lat),
                      np.max(lat)],
              transform=ccrs.PlateCarree())

    reader = cartopy.feature.GSHHSFeature('f') \
             .intersecting_geometries([
               extent[0],
               extent[2],
               extent[1],
               extent[3]])
    ax.add_geometries(list(reader), ccrs.PlateCarree(), alpha=.5)

    ax.coastlines()
    # ax.set_global()
    plt.savefig(os.path.join(tmpdir, 'tromsoe.png'))
def test_norway(tmpdir):
    delete_mask()
    l = Landmask(extent=[-1, 44, 41, 68])

    lon = np.arange(0, 40, .1)
    lat = np.arange(45, 67, .1)

    xx, yy = np.meshgrid(lon, lat)
    c = l.contains(xx.ravel(), yy.ravel())
    c = c.reshape(xx.shape)

    print("c:", c)

    import cartopy.crs as ccrs
    import matplotlib.pyplot as plt
    import os
    plt.figure(dpi=200)
    ax = plt.axes(projection=ccrs.PlateCarree())
    # ax.contourf(lon, lat, c, transform = ccrs.PlateCarree())
    ax.imshow(c, extent=[0, 40, 45, 67], transform=ccrs.PlateCarree())
    ax.coastlines()
    ax.set_global()
    plt.savefig(os.path.join(tmpdir, 'norway.png'))
class Reader(BaseReader):
    """
    The global landmask reader is based on the coastline data from
    GSHHG (https://www.ngdc.noaa.gov/mgg/shorelines/) optimized for
    checking against landmasks.

    Args:
        :param extent: minx, miny, maxx, maxy bounding box in source CRS for which to include
            geometries. Default None (all geometries).
        :type extent: array of floats, optional

        :param llcrnrlon: minx.
        :type llcrnrlon: float, optional, deprecated in favor of extent.

        :param llcrnrlat: miny.
        :type llcrnrlat: float, optional, deprecated in favor of extent.

        :param urcrnrlon: maxx.
        :type urcrnrlon: float, optional, deprecated in favor of extent.

        :param urcrnrlat: maxy.
        :type urcrnrlat: float, optional, deprecated in favor of extent.

        :param skippoly: use only rasterized landmask to determine whether points are on land.
        :type skippoly: bool, optional, default False.
    """
    name = 'global_landmask'
    return_block = False
    variables = ['land_binary_mask']
    proj4 = None
    crs   = None
    skippoly = False

    def __init__(self,
                 extent = None,
                 llcrnrlon = None,
                 llcrnrlat = None,
                 urcrnrlon = None,
                 urcrnrlat = None,
                 skippoly = False):
        self.proj4 = '+proj=lonlat +ellps=WGS84'
        self.crs = pyproj.CRS(self.proj4)
        self.skippoly = skippoly

        super (Reader, self).__init__ ()

        # Depth
        self.z = None

        if extent and (llcrnrlat or llcrnrlon or urcrnrlat or urcrnrlon):
            raise Exception ("'extent' cannot be given togheter with any of 'llcrnrlon', ..'")
        elif extent is None and (llcrnrlat or llcrnrlon or urcrnrlat or urcrnrlon):
            warnings.warn("llcrnrlon, llcrnrlat, et. al. is deprecated for the global landmask reader. Prefer 'extent' in stead.", DeprecationWarning)
            extent = [llcrnrlon, llcrnrlat, urcrnrlon, urcrnrlat]

        # Read and store min, max and step of x and y
        if extent is not None:
            self.xmin, self.ymin, self.xmax, self.ymax = extent
        else:
            self.xmin, self.ymin = -180, -90
            self.xmax, self.ymax = 180, 90

        self.xmin, self.ymin = self.lonlat2xy(self.xmin, self.ymin)
        self.xmax, self.ymax = self.lonlat2xy(self.xmax, self.ymax)

        # setup landmask
        self.mask = Landmask(extent, skippoly)

    def __on_land__(self, x, y):
        return self.mask.contains (x, y, skippoly = self.skippoly, checkextent = False)

    def get_variables(self, requestedVariables, time = None,
                      x = None, y = None, z = None, block = False):
        """
        Get binary mask of whether elements are on land or not.

        Args:
            x (deg[]): longitude (decimal degrees)
            y (deg[]): latitude (decimal degrees)
            ...

        x, y is given in reader local projection.

        Returns:
            Binary mask of point x, y on land.

        """

        self.check_arguments(requestedVariables, time, x, y, z)
        return { 'land_binary_mask': self.__on_land__(x,y) }