0

I am reading a points shapefile containing the azimuth information in the attribute table, and I want to generate lines from these data. I have tried to use shapely.Point as a tool, however it can't read geodataframe but only given values.

Here is a sample of my data:

lat lon Azimuth
0 22.969411 120.202380 165.0
1 22.969329 120.202314 55.370
2 22.969297 120.202294 5.0
3 22.968941 120.202245 145.0

Here is my code:

from shapely.geometry import Point, LineString

def cosdir(azim):
    az = np.radians(azim)
    cosa = np.sin(az)
    cosb = np.cos(az)
    return cosa,cosb

az = gdf['Azimuth']

point = Point(gdf['lon'],gdf['lat'])

cosa, cosb = cosdir(az)
print(cosa, cosb)
length = 10000

endline = Point(point.x(length*cosa), point.y+ +(length*cosb))
line = LineString([point,endline])

and here is the the response:

ValueError                                Traceback (most recent call last)
Cell In[124], line 12
      9 # dfp = pd.DataFrame(gdf)
     10 az = gdf['Azimuth']
---> 12 point = Point(gdf['經度'],gdf['緯度'])
     14 cosa, cosb = cosdir(az)
     15 print(cosa, cosb)

File ~\AppData\Local\Programs\python\Lib\site-packages\shapely\geometry\point.py:73, in Point.__new__(self, *args)
     70     coords = np.array(args).squeeze()
     72 if coords.ndim > 1:
---> 73     raise ValueError(
     74         f"Point() takes only scalar or 1-size vector arguments, got {args}"
     75     )
     76 if not np.issubdtype(coords.dtype, np.number):
     77     coords = [float(c) for c in coords]

ValueError: Point() takes only scalar or 1-size vector arguments

So what should I do to read every value in the geodataframe and form lines from the data?

1

1 Answer 1

2

Try this:

from shapely import Point, LineString
import numpy as np
import geopandas as gpd

length = 10000 #The length of the lines, in meters

#Create a geodataframe
data = {"lat":[22.969411, 22.969329, 22.969297, 22.968941],
        "lon":[120.202380, 120.202314, 120.202294, 120.202245],
        "Azimuth":[165, 55.370, 5, 145]}
df = gpd.pd.DataFrame(data=data)
geometry = gpd.points_from_xy(x=df["lon"], y=df["lat"], crs=4326)
df = gpd.GeoDataFrame(data=data, geometry=geometry, crs=4326)
df = df.to_crs(3829) #You need to have a projected coordinate system with meters as units, for example 3829

df.to_file(r"C:\GIS\data\testdata\input_points.shp") #Save the points

#Calculate end coordinates and create a line
df["endx"] = df.apply(lambda row: np.sin(np.radians(row["Azimuth"]))*length+row["geometry"].x, axis=1)
df["endy"] = df.apply(lambda row: np.cos(np.radians(row["Azimuth"]))*length+row["geometry"].y, axis=1)
df["line"] = df.apply(lambda row: LineString([row.geometry, Point(row["endx"], row["endy"])]), axis=1)

df = df.set_geometry("line").drop(columns="geometry").rename_geometry("geometry").set_crs(3829)
df.to_file(r"C:\GIS\data\testdata\lines.shp")

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.