1

I am new to OGR and Folium but learning fast. In short, I have an issue which I think might be a projection problem.

Basically, I have three circles plotted in folium that work fine. Then I have a fourth circle that I created with OGR, by adding a point then buffering it and plotting the geoJSON polygone onto the folium map. This fourth circle comes out as an oval, see:

enter image description here

The code to make this is as follows:

import folium
import pandas as pd
import json
from numpy import median
from osgeo import ogr

# MY CO-ORDINATES -- FOUR POINTS

datatest = pd.read_csv('data.csv')

p1_lat, p1_lon, p2_lat, p2_lon, p3_lat, p3_lon, p4_lat, p4_lon = datatest['POINT1_LAT'], datatest['POINT1_LON'], datatest['POINT2_LAT'], datatest['POINT2_LON'], datatest['POINT3_LAT'], datatest['POINT3_LON'], datatest['POINT4_LAT'], datatest['POINT4_LON']

# CENTER THE MAP

middle_lat = median([p1_lat, p2_lat, p3_lat, p4_lat])
middle_lon = median([p1_lon, p2_lon, p3_lon, p4_lon])

testmap = folium.Map(location=[middle_lat, middle_lon], zoom_start=13)

# MAKE THREE FOLIUM CIRCULES

folium.Circle(location=[p1_lat, p1_lon], popup='Point 1A', fill_color='#000', radius=2000, weight=2, color="#000").add_to(testmap)
folium.Circle(location=[p2_lat, p2_lon], popup='Point 1B', fill_color='#000', radius=2000, weight=2, color="#000").add_to(testmap)
folium.Circle(location=[p3_lat, p3_lon], popup='Point 1C', fill_color='#008080', radius=1000, weight=2, color="#008080").add_to(testmap)

# MAKE A FOURTH CIRCULE IN OGR

p4_lat = float(p4_lat[0])
p4_lon = float(p4_lon[0])

point_four = ogr.Geometry(ogr.wkbPoint)
point_four.AddPoint(p4_lon, p4_lat)

bufferDistance = 0.01
poly = point_four.Buffer(bufferDistance)

geojson_poly = poly.ExportToJson()

# STYLING THE FOURTH CIRCLE (IGNORE THIS)

import random

def random_html_color():
    r = random.randint(0,256)
    g = random.randint(0,256)
    b = random.randint(0,256)
    return '#%02x%02x%02x' % (r, g, b)

def style_fcn(x):
    return { 'fillColor': random_html_color() }

def highlight_fcn(x):
    return { 'fillColor': '#ff0000' }

# ADD CIRCLE FOUR TO FOLIUM

folium.GeoJson(geojson_poly,name='geojson', style_function=style_fcn).add_to(testmap)

# GENERATE MAP SEEN IN IMAGE

testmap.save('testing_map.html')

So, can anyone tell me why my OGR point is an oval shape? Do I need to set the proper projection somewhere? Presumably to WGS 1984?

EDIT: CSV coordinates are (1-4 in rows, lat and lon):

40.729047,-73.957472
40.70797,-73.93095
40.706799,-73.958416
40.681289,-74.004936
2
  • Could you please also provide the coordinates that are in the *.csv file? Apr 13 '20 at 15:34
  • Have provided csv coordinates as req Apr 13 '20 at 16:24
1

Your buffer:

bufferDistance = 0.01
poly = point_four.Buffer(bufferDistance)

is applied to the Lat/Long point, so the value 0.01 is in units of degrees.

With the method folium.Circle the radius parameter is in units of meters.

Perhaps the simplest fix is to use folium.Circle to plot the forth circle as well.

It is a bit messier, but you could also reproject your points into a flat projection (maybe epsg:6347,) apply the buffer, and then plot.

Edit: Using GeoPandas for the second option (Warning, didn't actually run this code)

import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
df = pd.DataFrame(
    {
        'lat':[p1_lat, p2_lat, p3_lat, p4_lat],
        'lon':[p1_lon, p2_lon, p3_lon, p4_lon],
        'rad':[2000, 2000, 1000, 100]
    }
)
df['geom'] = df.apply(lambda r: Point(r['lon'], r['lat']), axis=1)
gdf = gpd.GeoDataFrame(df, geometry='geom', crs='epsg:4326')
gdf_flat = gdf.to_crs('epsg:6347')
gdf_flat['geom'] = gdf_flat.geometry.buffer(df.rad)
gdf = gdf_flat.to_crs('epsg:4326')
gdf.to_file('data.geojson', driver='GeoJSON')
8
  • Hi -- thanks! That makes lots more sense. However, I'd like to plot it all in OGR because I may not end up using folium for this project. Is there a way to create the circle with OGR (or sth else) before it is plotted into folium (or anything else)? I'd like to get all my geometry done in geoJSON ideally before it goes to be plotted anywhere (by anything!). Apr 13 '20 at 16:13
  • I've never done this with plain OGR calls, but I did update the answer with how to do it with GeoPandas.
    – Ryan
    Apr 13 '20 at 16:46
  • Mhmmm, code gives me an error on the last line with Invalid field type... Apr 13 '20 at 17:02
  • It works for me, perhaps you added a field that isn't supported by JSON? Maybe a Datetime object?
    – Ryan
    Apr 13 '20 at 17:25
  • Ovals, or, more accurately, egg shapes, are expected when buffering in degrees. Plotting them in Web Mercator warps them differently, as well.
    – Vince
    Apr 13 '20 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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