Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't transform geometry to geojson

My problem is this. I'm creating a model for some data.

class Cables(Base):
    __tablename__ = 'cables'

    id = Column(Integer, nullable=False)
    route = Column(Geometry(geometry_type='LINESTRING', srid=4326), nullable=False)

Now, I want to transform such a route to GeoJSON.

Things I've tried

@app.route("/api/cable/<int:id>", methods=['GET'])
def get_cable(id):
    cable = session.query(Cables).filter(Cables.id == id).first()
    return str(geoalchemy2.functions.ST_AsGeoJSON(cable.route))

returns ST_AsGeoJSON(ST_GeomFromEWKB(:ST_GeomFromEWKB_1))

If I change the return:

return geoalchemy2.functions.ST_AsGeoJSON(cable.route)

returns TypeError: 'ST_AsGeoJSON' object is not callable

return str(cable.route)

returns 0102000020e610000002000000b34fd4d9bca351c032e14d5134c240c0d24f8055e0a351c0dedea9f4dcbf40c0 This would signal that I do have a geometry object.

return cable.route

returns TypeError: 'WKBElement' object is not callable

If I print the route type,

print(type(cable.route))

returns

<class 'geoalchemy2.elements.WKBElement'>

I thought it should have returned an object of such class, and not the class itself. I'm baffled at this point and I don't know what I should do now.

Any suggestions?

like image 389
Tomas Wolf Avatar asked Jan 16 '17 20:01

Tomas Wolf


1 Answers

It seems to be that the correct way to call ST_AsGeoJSON is inside a query. For instance,

ruta = session.query(Cables.route.ST_AsGeoJSON()).filter(Cables.id == id).first()

What I ended up doing was installing a new library (shapely) in order to read the hex bytestring and then transform it to a dictionary, as dictionaries can be transformed to json in an easy way.

def ewkb_route_to_dict(self):
    """
    returns the cable's route as a dictionary.
    It uses shapely.wkb.loads. The first argument is the route as a bytestring,
    and the second one (True) is to tell loads that
    the input wkb will be represented as a hex string
    """
    return mapping(shapely.wkb.loads(str(self.route), True))

Then in my to string method:

def __str__(self):
    d = dict()
    ...
    d["route"] = self.ewkb_route_to_dict()
    ...
    return dumps(d)

That will correctly transform the geometry to GeoJSON.

like image 66
Tomas Wolf Avatar answered Sep 30 '22 06:09

Tomas Wolf