1

I have a polygon dataset (shapefile, mapinfo tab file) which I would like to "clean" to be topologically correct. The polygons are assigned an ID which represents a specific class. For example ID 3 is forest and ID 2 is grass. In general the polygons does not touch or overlay but there are some exceptions. For example, a small polygon, forest, is on top of a larger polygon, grass. What I would like to do is to have a hole in the grass polygon where the forest polygon intersects.

What I have tried thus far was the v.clean tool in QGIS/grass plugin. But for some reason it also creates a grass polygon the same size as the forest polygon. So instead of two polygons there are three polygons. The images below illustrate what I have, what I want, what I would like and what the v.clean tool does.

Illustrates the tree polygon on top of the grass polygon

The forest polygon moved to illustrate that the grass polygon does not have a hole

The result from v.clean. Three polygons and a hole.

The result I would like

There are about 100 000 000 polygons (not all in one file) so doing it manually is not an option. I have arcmap and mapinfo but would like an opensource (QGIS/greass/saga/postgis/python script) to clean the polygons. Any suggestions?

1

For GRASS, this is a documented feature of v.in.ogr, and as said in the manual, in the case of overlapping polygons, the overlapping areas are given the catgories of both of the original imported polygons. So the solution would be to find the centroids with double categories and remove the grass category from this. The solution below is for the command line GRASS.

This example assumes that you import the shapefile with v.in.ogr input=INFILE.shp output=test key=ID, which will ensure, that the original ID's for grass and forest will become categories in the GRASS vector.

v.edit map=test tool=catdel ids=$(v.edit map=test ids=$(v.edit map=test tool=select where="cat=1" --q) tool=select where="cat=2" --q) cat=1

This rather complicated looking script has three different operations. The most internal one first finds all the feature ids with category=1 and gives this as an argument to the second v.edit, which from these features finds all that also have category=2, and in the end, the outernmost one takes this list, that now contains all the features with both categories 1 and 2, and removes the category 1 from these. This should remove the double categories.

Second thoughts

Actually, in the case of 100 000 000 polygons this probably does not work, as I would not count on the shell scripts being able to handle this large lists or arguments.

You could turn this into a larger script, perhaps with python, to achieve the same result:

  1. use v.edit as above to find the list of ids with the category=1
  2. for each of these ids, use v.category to find out if it also has category=2, and
  3. if the id has also the category=2, use v.edit as above to remove category=1 form the id in question.

This is clumsy, but will achieve the desired result in due time.

2

If it's only a small amount of polygons you have to cut out, you can use the tools from the advanced digitizing tools toolbar (View--> Toolbars).

If you want to check is shapefiles are overlapping, I recommend the Topology checker-plugin. This tool allows you to configure which layers should not overlap, shapes within layes who should not overlap, etc. Very easy tool, use it all the time. Good luck;)

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.