Exemplo n.º 1
0
def hfun_(coastlines, res=.1, R=1.):

    amask = (coastlines.bounds.miny < coastlines.bounds.miny.min() + .1)
    anta = coastlines[amask]
    anta = anta.reset_index(drop=True)

    ### convert to stereo
    try:
        ant = pd.DataFrame(anta.boundary.values[0].coords[:],
                           columns=['lon', 'lat'])
    except:
        ant = pd.DataFrame(anta.boundary.explode().values[0].coords[:],
                           columns=['lon', 'lat'
                                    ])  # convert boundary values to pandas

    d1 = ant.where(ant.lon == ant.lon.max()).dropna().index[
        1:]  # get artificial boundaries as -180/180
    d2 = ant.where(ant.lon == ant.lon.min()).dropna().index[1:]
    ant = ant.drop(d1).drop(d2)  # drop the points
    d3 = ant.where(
        ant.lat == ant.lat.min()).dropna().index  # drop lat=-90 line
    ant = ant.drop(d3)
    ub, vb = to_stereo(ant.lon.values, ant.lat.values, R)
    ant.lon = ub
    ant.lat = vb

    an = gp.GeoDataFrame({
        'geometry': [shapely.geometry.LineString(ant.values)],
        'length':
        shapely.geometry.LineString(ant.values).length
    })  # put together a LineString

    # create simple grid
    d1 = np.linspace(an.bounds.minx, an.bounds.maxx, 100)
    d2 = np.linspace(an.bounds.miny, an.bounds.maxy, 100)

    ui, vi = np.meshgrid(d1, d2)
    # Use Matplotlib for triangulation
    triang = matplotlib.tri.Triangulation(ui.flatten(), vi.flatten())
    tri = triang.triangles

    #stereo->2D scale
    ci = 4 * R**2 / (ui**2 + vi**2 + 4 * R**2)
    ci

    # create weight field
    points = np.column_stack([ui.flatten(), vi.flatten()])
    dps = pd.DataFrame(points, columns=['u', 'v'])
    dps['z'] = 0
    dps['h'] = res / ci.flatten()

    tria3 = pd.DataFrame(tri, columns=['a', 'b', 'c'])
    tria3['w'] = 0

    p1 = dps.to_xarray()
    p1 = p1.rename({'index': 'nodes'})
    p1 = p1.assign({'tria': (['elem', 'n'], tria3.values)})

    return p1
Exemplo n.º 2
0
def sgl(**kwargs):

    try:
        geo = gp.GeoDataFrame.from_file(kwargs.get('coastlines', None))
    except:
        logger.warning(
            'coastlines is not a file, trying with geopandas Dataset')
        try:
            geo = kwargs.get('coastlines', None)
        except:
            logger.error('coastlines argument not valid ')
            sys.exit(1)

        # Manage coastlines
        logger.info('preparing coastlines')
        #Kaspian Sea, if present
        kasp = ((geo.bounds.miny > 36.) & (geo.bounds.maxy < 48.) &
                (geo.bounds.maxx < 55.) & (geo.bounds.minx > 45.))
        geo = geo.drop(geo.loc[kasp].index)

        #ANTARTICA
        anta_mask = (geo.bounds.miny < geo.bounds.miny.min() + .1
                     )  # indentify antartica
        anta = geo.loc[anta_mask]
        indx = anta.index  # keep index

        try:
            anta = pd.DataFrame(anta.boundary.values[0].coords[:],
                                columns=['lon', 'lat'])
        except:
            anta = pd.DataFrame(
                anta.boundary.explode()[0].coords[:],
                columns=['lon', 'lat'])  # convert boundary values to pandas
        d1 = anta.where(anta.lon == anta.lon.max()).dropna().index[
            1:]  # get artificial boundaries as -180/180
        d2 = anta.where(anta.lon == anta.lon.min()).dropna().index[1:]
        anta = anta.drop(d1).drop(d2)  # drop the points
        d3 = anta.where(
            anta.lat == anta.lat.min()).dropna().index  # drop lat=-90 line
        anta = anta.drop(d3)
        an = gp.GeoDataFrame(
            {
                'geometry': [shapely.geometry.LineString(anta.values)],
                'length': shapely.geometry.LineString(anta.values).length
            },
            index=indx)  # put together a LineString
        geo.loc[indx] = shapely.geometry.LineString(
            anta.values)  # put it back to geo

        # International Meridian
        m1 = geo[geo.bounds.minx == -180.].index
        m2 = geo[geo.bounds.maxx == 180.].index
        mm = np.concatenate((m1, m2))  # join them
        mm = [j for j in mm if j != indx]  # subtract antartica

        # convert to u,v (stereographic coordinates)
        for idx, poly in geo.iterrows():
            geo.loc[idx, 'geometry'] = shapely.ops.transform(
                lambda x, y, z=None: to_stereo(x, y, R=kwargs.get('R', 1.)),
                poly.geometry)

        w = geo.drop(indx)  # get all polygons
        ww = w.loc[mm]  # join the split polygons
        gw = gp.GeoDataFrame(
            geometry=list(ww.buffer(.0001).unary_union)
        )  # merge the polygons that are split (around -180/180)

        w = w.drop(mm)
        # Check antartica LineString
        if not geo.iloc[indx].geometry.values[0].is_ring:
            ca = gp.GeoDataFrame(geometry=[
                shapely.geometry.LinearRing(geo.loc[indx].geometry.values[0])
            ],
                                 index=indx)
            ca['geometry'] = shapely.geometry.LineString(ca.geometry.values[0])
        else:
            ca = geo.loc[indx]

        # PUT ALL TOGETHER
        geo = pd.concat([w, gw, ca], ignore_index=True).reset_index(drop=True)

    logger.info('storing boundaries')

    geo['tag'] = -(geo.index + 1)

    idx = 0
    dic = {}
    for i, line in geo.iloc[:-1].iterrows():
        lon = []
        lat = []
        try:
            for x, y in line.geometry.boundary.coords[:]:
                lon.append(x)
                lat.append(y)
            dic.update({
                'line{}'.format(idx): {
                    'lon': lon,
                    'lat': lat,
                    'tag': line.tag
                }
            })
            idx += 1
        except:
            for x, y in line.geometry.boundary[0].coords[:]:
                lon.append(x)
                lat.append(y)
            dic.update({
                'line{}'.format(idx): {
                    'lon': lon,
                    'lat': lat,
                    'tag': line.tag
                }
            })
            idx += 1

    for i, line in geo.iloc[-1:].iterrows():
        lon = []
        lat = []
        for x, y in line.geometry.coords[:]:
            lon.append(x)
            lat.append(y)
            dic.update({
                'line{}'.format(idx): {
                    'lon': lon,
                    'lat': lat,
                    'tag': line.tag
                }
            })

    dict_of_df = {k: pd.DataFrame(v) for k, v in dic.items()}

    df = pd.concat(dict_of_df, axis=0)

    df['z'] = 0
    df = df.drop_duplicates()  # drop the repeat value on closed boundaries

    return df