Repository navigation
Centroid of linestrings #1771
Description
Activity
Lets try to unpack this:
- Yes, the documentation is incomplete. Calculating the centroid is actually possible for all geometry types except GeometryCollection. We should change the docs.
- The
centroid()of a geometry is defined as the center of gravity of that geometry. If you have an invalid geometry there is no meaning to that. osm2pgsql is more picky about invalid geometries than PostGIS is. We consider creating invalid geometries a bug, because working with invalid geometries leads to all sorts of problems. - Your example
select ST_Centroid(ST_MakePoint(1,1))is wrong, this will create a point and centroids for points work in osm2pgsql also. The right example would beST_Centroid(ST_MakeLine(ST_MakePoint(1, 1)))which indeed does work in PostGIS but not in osm2pgsql, as discussed in 2. - I think the real question is: Should it be possible to create a point geometry from a way that has only a single point? If the answer is yes, we need
object:as_point()to work in that case. For consistency it should probably return the null geometry if there is more than one point. (Note that there are many reasons why there can be only one point in a way, either because there is only one node, or because there are several nodes with the same ids or different ids but same locations, or because some of the nodes are not in the input data in which case osm2pgsql will just use the ones it finds.) - The example you mention is a bit different, because it is a relation only containing a single node. There is nothing wrong with that. Currently, the only way to get to that node is
as_geometrycollection()though, and centroid isn't supported for GeometryCollections (mostly because I am not sure what the correct semantic would be for that). From your description I understand you tried to treat that relation as a MultiLineString, which will return a null geometry, because the relation doesn't contains any lines.
I think we should probably add (4). This would at least allow you to do whatever you want to do, although it is a bit annoying that you have to try
as_polygon(),as_linestring(), andas_point()in that order for best results. But the normal use case is still that you want to be sure to always have good data and wrong data is ignored by default.We are already thinking about how to fix (5). There will be some way of accessing single member geometries of relations directly. (And we should probably also add an
as_multipoint()for consistency.)Sorry for my bad explanation yesterday. I was rethinking today, and maybe I can give you a complete picture.
The spatial function set of this library is very limited, compared to PostGIS. This is completely fine, as this library has another use case. However, it trapped me in thinking I can replace this library now with PostGIS... After further investigations today, I also need to use PostGIS's
ST_PointOnSurface(when the centroid is outside the surface) andST_LineInterpolatePoint(to get the "middle" of a linestring). So this usage is far beyond the limitations.In fact, I want to have four tables:
- element (contains some medtadata of an osm object)
- node (linked node geometry of a element)
- line (linked line geometry of a element)
- polygon (linked polygon geometry of a element)
In my case I don't care if it is a relation, way or node.
A way can be a polygon (
is_closed()) or just a simple line.
A relation can be (multiple) polygon(s) (also with holes), disjoint polygons, or just straight lines.osm2pgsql is very oriented on node/way/relation structure and is restricting access to e.g.
as_geometrycollection()outside of relation processing.Is there a way to do what I want without having a lot of intermediate tables and disk usage?
I was thinking (as I use triggers anyway, to push all geom as
geometrycollectioninto myelementtable and do all the processing inside a trigger, like filling my geometry tables. But as I descibed above,as_geometrycollection()is exclusive to relations. I understandgeometrycollectionas a universal container for several geometries. I'm not sure if this is the right thinking tho!So I think my demand with the centroid processing was just a side effect of an incomplete plan. You have to decide, if you want to investigate this further.
Can you give me a suggestion on how to approach my import?
- locked and limited conversation to collaborators
on Sep 22, 2022
In some scenarios it is not possible to create a polygon (when e.g. the way has less than 4 points). But I still want to obtain the centroid.
In the documentation it is stated, that this only works with polygons/multipolygons. I gave it a shot and anyways, it is possible to obtain a centroid from linestrings like
object:as_linestring():centroid(). This works in all cases, when it is not possible to create a polygon (whenpolygon:is_null()), with the single exception when a line(multiline has only one node (like https://www.openstreetmap.org/relation/7360610). PostGis is working in this scenarioselect ST_Centroid(ST_MakePoint(1, 1)).I tried to convert the geometry into a single point via
object:as_point()but the call is not possible outside node processing.