jonas-p / go-shp

Go library for reading and writing ESRI Shapefiles. Pure Golang implementation based on the ESRI Shapefile technical description.
MIT License
255 stars 67 forks source link

Reading Multipolygon Shapes #29

Closed gocluster closed 6 years ago

gocluster commented 6 years ago

In a shp file that I have we have type ""type": called multipolygon. "Feature","geometry":{"type":"MultiPolygon","coordinates":" What is the best way to read this? When I do *shp.Polygon I am only able to retrieve one of the polygons and its bbx.

fawick commented 6 years ago

I have to admit I do not fully understand what you are trying to do. The syntax you provided looks like GeoJSON, not like a ESRI shapefile. Would you kindly elaborate on the file you are trying to read.

go-shp does not read GeoJSON by itself, but there are libraries available, e.g. https://github.com/paulmach/go.geojson

However, if we are really talking about a shapefile here, than you should check the NumParts field of the Polygon feature. If it is higher than 1, your Polygon is indeed a Polygon with holes already.

gocluster commented 6 years ago

Its is a shp file . But since I could see that the bounding box was not right I dumped it into a geojson file to see whats happening. Here is where I get the file http://www.nws.noaa.gov/geodata/catalog/wsom/data/z_03ap18.zip The num parts for one of the shapes is > 1 many times . What is the right way to get all the polygons and their BBx or one bbx which covers all?

fawick commented 6 years ago

The function to obtain the BBox for all parts of the Polygon feature in total is shp.Polygon.BBox()

For obtaining the BBox of a certain part you could do something like this (this is just a rough idea from the top of my head, may contain syntax errors and bugs):

func BBoxOfPart(p shp.Polygon, part int) shp.Box {
    var start, end int
    switch {
    case part < 0 || part >= p.NumParts:
        return shp.Box{}
    case part == p.NumParts - 1:
        start, end := p.Parts[part], p.NumPoints
    default:
        start, end := p.Parts[part], p.Parts[part+1]
    }
    return shp.BBoxFromPoints(p.Points[start:end])
}

Be aware that the bounding boxes of the parts may be nested within each other if the parts are polygons with holes.

gocluster commented 6 years ago

There seems to be more to it . When I dump out the polygon and its points and compare it with the geoJson I see that many of the points are missing. The shp.Bbx returned is also not accurate. I can give specific eg if req.

fawick commented 6 years ago

Yes, please provide a specific example. Otherwise it's going to be very hard to help you to debug this. What would be ideal is if you could provide an error example, consisting of what you did, what that gave you and how it differed from your expectations for the minimum amount of data on which that error occurs.

One natural cause of the GeoJSON having one more point per polygon (here, per point ring) is that GeoJSON requires that the first and last point have to be identical for the polygon to be well-formed. Shapefile polygons do not have this requirement, instead the rings will have an implicit final edge between the last and the first point if those points do not match.

gocluster commented 6 years ago

Sorry it took this long to revert. Turns out this is an issue in the input shp file whether its by spec or not needs more investigation . Two error zones with different polygons had the same zone name . One was getting over-written. Please close this issue.