vgb_backup
vgb_backup

Reputation: 49

How to create a line/polygon using shapely with a width provided only two points?

I want to create a line with custom defined width (km) using shapely. But it seems like line basically defined as a geometry without depth. In that I am more than happy to create a line with width in the form of rectangular polygon PROVIDED only start and end point of the line is available.

Is it possible to use buffer option in linestring to add the width?

Upvotes: 1

Views: 1398

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31226

  • you can create a buffer around a LineString. It's important to take CRS into account
  • image shows an example by taking two random cities in UK
  • you note that you don't want points in polygon to be accessible. Depends on your use case, but as image shows it adds a layer for straight line and buffered area. How you hide buffered polygon is down to how you design private / public parts of your data interface
import pandas as pd
import numpy as np
import geopandas as gpd
import shapely.geometry
import requests, json
import plotly.express as px

# source some points and polygons
# fmt: off
dfp = pd.read_html("https://www.latlong.net/category/cities-235-15.html")[0]
dfp = gpd.GeoDataFrame(
    dfp,
    geometry=dfp.loc[:,["Longitude","Latitude"]].apply(shapely.geometry.Point, axis=1),
    crs="EPSG: 4326",
)
# fmt: on

# ramdonly select just two points
dfp = dfp.sample(2)

# construct a LineString from points
line = shapely.geometry.LineString(dfp.loc[:, ["Longitude", "Latitude"]].values)
# add a buffer to LineString (hence becomes a polygon)
DISTANCE = 10 ** 4  # 10km
lineb = (
    gpd.GeoSeries([line], crs="EPSG: 4326")
    .to_crs(dfp.estimate_utm_crs())
    .buffer(DISTANCE ,cap_style=2)
    .to_crs("EPSG: 4326")
)

# plot the points, the buffered line (polygon) and the line
px.scatter_mapbox(dfp, lat="Latitude", lon="Longitude").update_layout(
    mapbox={
        "style": "carto-positron",
        "zoom": 4,
        "layers": [
            {
                "source": json.loads(lineb.to_json()),
                "below": "traces",
                "type": "fill",
                "color": "lightgrey",
            },
            {
                "source": json.loads(gpd.GeoSeries(line).to_json()),
                "type": "line",
                "color": "green",
            },
        ],
    }
)


enter image description here

Upvotes: 1

Related Questions