Giter VIP home page Giter VIP logo

prepair's Introduction

What is prepair?

prepair — pronounce 'pee-repair' as in 'polygon repair' — permits us to easily repair "broken" GIS polygons according to the international standard ISO19107 (Geographic information — Spatial schema). Given one input polygon, it automatically repairs it and returns back a valid polygon (actually a MultiPolygon since the input can represent more than one polygon — think of a 'bowtie' for instance).

Automated repair methods can be considered as interpreting ambiguous or ill-defined polygons and giving a coherent and clearly defined output. Examples of errors are: polygon has a dangling edge; polygon is not closed; polygon self-intersects; an inner ring of the polygon is located outside the outer ring; etc.

prepair performs more or less the same as the PostGIS 2.0's function ST_MakeValid(), but is faster, scales better to massive polygons, and predicting its behaviour is simple (so one can guess how polygons will be repaired).

prepair is based on a constrained triangulation (CGAL is used) and GDAL is used to read/write WKT.

It is available under the GPLv3 licence, which allows you to use, copy and modify the software freely. However, if you incorporate prepair in your software, you must distribute the source code of your software, as well as any modifications made to pprepair, under the GPLv3 as well.

Note that prepair is only concerned with single polygons, and if you're interested in validating how different polygons interact with each other (to be precise: to check if they form a planar partition) have a look at our other project pprepair.

Details

Details of how we automatically repair broken polygons, and what results you can expect, are available in this scientific article:

Ledoux, H., Arroyo Ohori, K., and Meijers, M. (2014). A triangulation-based approach to automatically repair GIS polygons. Computers & Geosciences 66:121–131. [DOI] [PDF]

If you use prepair for a scientific project, please cite this article.

How to get it?

prepair is very easy to compile on Mac and Linux using the included CMake file. It should also work on other Unix-like systems and is possible to compile under Windows. To compile prepair, you need to have a recent version of the following three (free) libraries:

  1. CGAL
  2. GDAL
  3. CMake

On Mac, you can install it using Homebrew:

$ brew install tudelft3d/software/prepair

Once all the dependencies are met, just generate the makefile for your system and compile:

$ cmake -DCMAKE_BUILD_TYPE=Release .
$ make

How to run it?

You can run prepair from the command-line or through our QGIS plug-in, which you can get from the official QGIS repository.

A WKT or a path to a dataset (geopackage, geojson or shapefile for instance) is read as input, and a WKT or a path to a dataset is given as output:

$ ./prepair -w 'POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))'  
MULTIPOLYGON (((0 0,5 5,0 10,0 0)),((5 5,10 0,10 10,5 5)))

$ ./prepair -w 'POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))' -o myfile.gpkg
Writing GPKG file myfile.gpkg...

$ ./prepair -w 'POLYGON((0 0 0, 0 10 5, 10 0 10, 10 10 15, 0 0 0))'
MULTIPOLYGON (((0 0,5 5,0 10,0 0)),((5 5,10 0,10 10,5 5)))

Examples of invalid input you can try

The folder 'data' contains examples of relatively big invalid polygons. These are from the Corine Land Cover 2006 dataset.

A 'bowtie' polygon:

POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))

Square with wrong orientation:

POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))

Inner ring with one edge sharing part of an edge of the outer ring:

POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(5 2,5 7,10 7, 10 2, 5 2))

Dangling edge:

POLYGON((0 0, 10 0, 15 5, 10 0, 10 10, 0 10, 0 0))

Outer ring not closed:

POLYGON((0 0, 10 0, 10 10, 0 10))

Two adjacent inner rings:

POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 8, 3 8, 3 1, 1 1), (3 1, 3 8, 5 8, 5 1, 3 1))

Polygon with an inner ring inside another inner ring:

POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (2 8, 5 8, 5 2, 2 2, 2 8), (3 3, 4 3, 3 4, 3 3))

prepair's People

Contributors

kenohori avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prepair's Issues

GDAL 2.3.0 support

Hi there,

Is it known whether or not prepair supports GDAL 2.3.0 which uses C++11?

After running make I get the following error:

Scanning dependencies of target prepair
[ 25%] Building CXX object CMakeFiles/prepair.dir/TriangleInfo.cpp.o
[ 50%] Building CXX object CMakeFiles/prepair.dir/PolygonRepair.cpp.o
In file included from /Users/ronanduddy/dev/prepair_original/PolygonRepair.cpp:22:
In file included from /Users/ronanduddy/dev/prepair_original/PolygonRepair.h:24:
In file included from /Users/ronanduddy/dev/prepair_original/definitions.h:35:
In file included from /usr/local/include/ogrsf_frmts.h:34:
In file included from /usr/local/include/cpl_progress.h:33:
/usr/local/include/cpl_port.h:187:6: error: Must have C++11 or newer.
#    error Must have C++11 or newer.
     ^
1 error generated.
make[2]: *** [CMakeFiles/prepair.dir/PolygonRepair.cpp.o] Error 1
make[1]: *** [CMakeFiles/prepair.dir/all] Error 2
make: *** [all] Error 2

Cheers

PolygonRepair::insertConstraints: Cannot understand input. Segmentation fault (core dumped)

Hi there,
I have incorporated prepair and pprepair as cleaning utilities (called via python scripts) as cleaning utilities for a postgis database.

I found the above mentioned error with the following wkt, which I can't understand.

prepair --wkt 'POLYGON((30.2101265604148 -25.5694229047629,30.2094828302513 -25.5711649475588,30.2125727350371 -25.5716101322077,30.2128516847743 -25.5694616171007,30.2101265604148 -25.5694229047629))' --minarea 0.000000001

Looking at the plotted polygon, it seems to be fairly standard. Any pointers on this will be welcome!

Thanks!

Segmentation Fault (core dumped) when running on large polygons

when running at your dataset (Data/CLC2006_180927.geojson)
prepair --ogr CLC2006_180927.geojson
I get a segmentation fault (core dumped)
(small polygons are ok)
DETAILS:
branch: master:
OS: RHEL 6.2 (Santiago)
compiled by gcc 4.4.7
Boost 1.41.0
CGAL 4.6

Polygon with internal ring causes app failure in Win64

All,

The attached WKT file triggers an unknown failure in prepair under Windows 7. Removing the inner ring allows successful execution. Using the inner ring as a stand-alone polygon also is successful. Prepair was run from the executable within prepair_win64.zip.

wkt01.txt

Thanks. - Phil

prepair v2

Hi @kenohori ,

I hope all is good, I noticed that you worked a new version of prepair and really happy to see that you had time to work on it again.
I was checking if this version is final enough to be used or you'll work on it in the future. I'm still using v1 and wanted to check if it was move my R package from v1 to v2 or wait before submitting to CRAN.

Thanks again,
Ahmadou

remove_small_parts() crashes

in branch improvements_ogr, for MultiPolygons OGR complains that a virtual function is called:
libc++abi.dylib: Pure virtual function called!

for very simple input

build error when using OS X 10.10 and homebrew gdal

When I try to compile prepair from source, I get an error about an OGR header file:

build $ cmake ..
-- The C compiler identification is AppleClang 6.1.0.6020053
-- The CXX compiler identification is AppleClang 6.1.0.6020053
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Build type: Release
-- USING CXXFLAGS = ' -O3 -DNDEBUG'
-- USING EXEFLAGS = ' '
-- Targetting Unix Makefiles
-- Using /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ compiler.
-- DARWIN_VERSION=14
-- Mac Leopard detected
-- Requested component: MPFR
-- Requested component: GMP
-- Boost version: 1.58.0
-- Found the following Boost libraries:
--   program_options
-- Found GDAL: /usr/local/Cellar/gdal/1.11.2_2/lib/libgdal.dylib  
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ravi/git/prepair/build
build $ make
Scanning dependencies of target prepair
[ 25%] Building CXX object CMakeFiles/prepair.dir/TriangleInfo.cpp.o
[ 50%] Building CXX object CMakeFiles/prepair.dir/PolygonRepair.cpp.o
In file included from /Users/ravi/git/prepair/PolygonRepair.cpp:22:
In file included from /Users/ravi/git/prepair/PolygonRepair.h:24:
/Users/ravi/git/prepair/definitions.h:35:10: fatal error: 'gdal/ogrsf_frmts.h' file not found
#include <gdal/ogrsf_frmts.h>
         ^
1 error generated.
make[2]: *** [CMakeFiles/prepair.dir/PolygonRepair.cpp.o] Error 1
make[1]: *** [CMakeFiles/prepair.dir/all] Error 2
make: *** [all] Error 2

As far as I can tell, the header file is present on my system, just not in the gdal directory that prepair expects:

build $ ls -lash /usr/local/include/ogrsf_frmts.h 
8 lrwxr-xr-x  1 ravi  admin    45B Aug  6 15:25 /usr/local/include/ogrsf_frmts.h -> ../Cellar/gdal/1.11.2_2/include/ogrsf_frmts.h

When I manually create a gdal directory and copy the OGR header files it works.

new win64 build missing dlls

Just to let you know I had to copy over libmpfr-4.dll and libgmp-10.dll from the older build to the new one before it would work - Win 7 only requires the first one I'm pretty sure, but Win 10.1 needed both.

Linux compilation issues

To check:

hledoux@geovalidation:~/projects/prepair$ make

[ 33%] Building CXX object CMakeFiles/prepair.dir/prepair.cpp.o

/home/hledoux/projects/prepair/prepair.cpp: In function 'int main(int,
const char**)':

/home/hledoux/projects/prepair/prepair.cpp:30:39: error: 'class
boost::program_options::typed_valuestd::basic_string<char, char>'
has no member named 'value_name'

/home/hledoux/projects/prepair/prepair.cpp:31:43: error: 'class
boost::program_options::typed_valuestd::basic_string<char, char>'
has no member named 'value_name'

/home/hledoux/projects/prepair/prepair.cpp:32:39: error: 'class
boost::program_options::typed_valuestd::basic_string<char, char>'
has no member named 'value_name'

/home/hledoux/projects/prepair/prepair.cpp:40:36: error: 'class
boost::program_options::typed_value<double, char>' has no member named
'value_name'

/home/hledoux/projects/prepair/prepair.cpp:41:40: error: 'class
boost::program_options::typed_valuestd::basic_string<char, char>'
has no member named 'value_name'

/home/hledoux/projects/prepair/prepair.cpp:104:63: error: no matching
function for call to 'std::basic_ifstream::open(const
std::basic_string&, const openmode&)'

/home/hledoux/projects/prepair/prepair.cpp:104:63: note: candidate is:

/usr/include/c++/4.6/fstream:531:7: note: void
std::basic_ifstream<_CharT, _Traits>::open(const char*,
std::ios_base::openmode) [with _CharT = char, _Traits =
std::char_traits, std::ios_base::openmode = std::_Ios_Openmode]

/usr/include/c++/4.6/fstream:531:7: note: no known conversion for
argument 1 from 'const std::basic_string' to 'const char*'

make[2]: *** [CMakeFiles/prepair.dir/prepair.cpp.o] Error 1

make[1]: *** [CMakeFiles/prepair.dir/all] Error 2

make: *** [all] Error 2

Crash in TriangleInfo with certain corrupt polygon

Using current master branch, this WKT crashes in TriangleInfo::beenTagged():

"POLYGON ((65.0912 4.2826,65.0911 4.3264,65.0911 4.3264,65.0911 4.3264,65.0912 4.2826))"

It's like TriangleInfo itself is corrupt after it got called three times previously from PolygonRepair::tagOddEven.

One observation that may be helpful is that TriangleInfo::clear() get's never called on this one.

Cheers
Ben

Question on repairing the vertex order

My input is POLYGON ((85002.60900146485 447422.1309907227, 84999.41800146484 447425.8499907227, 84992.16200146485 447431.2489907226, 84991.65300146485 447431.6269907227, 84995.05100146485 447429.0989907227, 84989.12400146485 447433.5089907227, 84990.52000146484 447435.2609907227, 84987.82000146485 447437.3439907227, 84985.77100146485 447434.2329907226, 84988.13000146484 447431.9589907227, 84988.37700146485 447432.2149907227, 84989.20900146486 447429.8119907227, 84987.37900146485 447428.4259907227, 84997.80600146485 447418.3269907227, 85002.60900146485 447422.1309907227))

The problem here is that the order of some of the vertices are incorrect, which creates sort of a spike that is collinear with an edge.

I tried repairing the polygon with and without --minarea 1, and I get a multipolygon, where the "main" polygon, which I expect as outcome, doesn't have all the input vertices anymore.

What I expect is to get this result, including all vertices and their position: POLYGON ((85002.60900146485 447422.1309907227, 84999.41800146484 447425.8499907227, 84995.05100146485 447429.0989907227, 84992.16200146485 447431.2489907226, 84991.65300146485 447431.6269907227, 84989.12400146485 447433.5089907227, 84990.52000146484 447435.2609907227, 84987.82000146485 447437.3439907227, 84985.77100146485 447434.2329907226, 84988.13000146484 447431.9589907227, 84988.37700146485 447432.2149907227, 84989.20900146486 447429.8119907227, 84987.37900146485 447428.4259907227, 84997.80600146485 447418.3269907227, 85002.60900146485 447422.1309907227))

Is this possible?

Batch processing?

Your library is awesome and the only thing on the internet that can be used easily to fix shapes from various datasets.

The only thing it is lacking is batch processing. Invoking this for each file is just too slow. Is there any way to use it for batch processing?

Overlapping constraints

The CGAL constraint hierarchy doesn't always behave how we want. When we remove a part of a constraint, the number_of_enclosing_constraints() is still 1. This can cause issues when 3 or more constraints overlap.

Set-diff and multipolygons

Multipolygons should be repaired in 3 stages:

  • odd-even for rings
  • outer \ inner for polygons
  • union of polygons

Segmentation fault/core dump

Hi Hugo and Ken,

I have prepair and pprepair integrated into a nice workflow on my system with postgis/postGRES, called out of a set of python scripts (I am happy to send these along if interested).
I am writing an updated script now, but have come across a segmentation fault with prepair.

./prepair --wkt 'POLYGON((27.6731453499999986 -31.9559552800000013, 27.6731453499999986 -31.9559552800000013, 27.6735961699999997 -31.9556177800000007, 27.6735961699999997 -31.9556177800000007, 27.6739497499999985 -31.9559627800000001, 27.6739497499999985 -31.9559627800000001, 27.6735342899999992 -31.9562815299999983, 27.6735342899999992 -31.9562815299999983, 27.6735342899999992 -31.9562815299999983, 27.6731453499999986 -31.9559552800000013))'

Segmentation fault (core dumped)

Could you please advise what I am doing wrong here, or whether this geometry has something flawed (although geos tells me its valid).

Thanks!

Namespace

Every primitive should go in a namespace to avoid clashes

--minarea doesn't remove zero area polygon

My input is POLYGON ((85002.60900146485 447422.1309907227, 84999.41800146484 447425.8499907227, 84992.16200146485 447431.2489907226, 84991.65300146485 447431.6269907227, 84995.05100146485 447429.0989907227, 84989.12400146485 447433.5089907227, 84990.52000146484 447435.2609907227, 84987.82000146485 447437.3439907227, 84985.77100146485 447434.2329907226, 84988.13000146484 447431.9589907227, 84988.37700146485 447432.2149907227, 84989.20900146486 447429.8119907227, 84987.37900146485 447428.4259907227, 84997.80600146485 447418.3269907227, 85002.60900146485 447422.1309907227))

I run prepair with --minarea 1 and one of the polygons in the output multipolygon still has a near-zero area.

Result from prepair: MULTIPOLYGON (((84999.4180014648 447425.849990723,84992.1620014649 447431.248990723,84991.857837151 447431.474873062,84989.1240014649 447433.508990723,84990.5200014648 447435.260990723,84987.8200014648 447437.343990723,84985.7710014648 447434.232990723,84988.1300014648 447431.958990723,84988.3770014648 447432.214990723,84989.2090014649 447429.811990723,84987.3790014649 447428.425990723,84997.8060014649 447418.326990723,85002.6090014649 447422.130990723,84999.4180014648 447425.849990723),(84995.0510014648 447429.098990723,84991.6530014648 447431.626990723,84991.857837151 447431.474873062,84995.0510014648 447429.098990723)))

where the second polygon (84995.0510014648 447429.098990723,84991.6530014648 447431.626990723,84991.857837151 447431.474873062,84995.0510014648 447429.098990723) has near-zero area.

create an extension for PostgreSQL

Thanks for your presentation at #osgeonl today.

I talked to my colleague Paul Ramsey about how to integrate this into PostGIS, and he came up with an alternative. See below:

Their code could be an extension that consumes WKB and outputs WKB
Requires no dependency on postgis at compile time
And just has a couple SQL functions that take in geometry, output wkb, hand to the internal functions, etc
Basically, that's how I did the pgpointcloud postgis integration
Pointcloud has no compile-time dependency on postgis
And all the interaction is via wkb in bytea structures
Makes it easy to write add-ons without the overhead of getting into the postgis build

Extracting just the triangulation result

Hi!
I'd been using prepair before to fix land polygons so that I could subsequently triangulate and then render them in 3d. However, since prepair uses triangulation as a basis to fix degenerate polygons, I've been trying to extract the relevant triangulation directly.

I do this by looking at the value of the additional 'info()' param that's attached to each triangulation face and compare the value to the 'interior' and 'exterior' addresses defined in the repair() function. I opt to keep triangles that have an info() == NULL because it seems like the repair() function sets all interior faces to NULL after processing them whereas exterior faces will have a non null address.

The result seems to work, but I'm not sure if what I'm doing is correct. Will interior triangles always correspond to NULL? Am I collecting the right set of triangles by doing the following?:

    Triangulation opTriangulation;
    OGRMultiPolygon * opPolygons = repair(ipGeometry,
                                          opTriangulation);
    Triangulation::Finite_faces_iterator fIt;
    for(fIt  = opTriangulation.finite_faces_begin();
        fIt != opTriangulation.finite_faces_end(); ++fIt)
    {
        // assumption: if face->info() == NULL, we
        // have the correct interior triangle
        if(fIt->info() == NULL)   {
            // get triangle
            Triangulation::Triangle cdtTri =
                    opTriangulation.triangle(fIt);

            // ... copy triangle coords ... //
        }
    }

Regards,

Preet

semi-static compilation

Find out how to automate the compilation with static CGAL, boost, GMP, MPFR, etc. and put it as a new option in our CMake file

User-defined output folder and file name

When dealing with OGR datasets in combination with --shOut, it would be great to be able to specify both the output folder and file name, which currently defaults to 'out.shp'. As concerns the command-line interface (I haven't checked the QGIS plug-in so far), do you plan to implement such functionality?

wrong WKT input can make prepair segfault

Added some defensive code to parse the WKT, but OGR doesn't seem to handle all case. Eg:

$ ./prepair --wkt 'POLYGON((0 0))'
Segmentation fault: 11

And it doesn't check the first-last are the same either

Crashes on thin polygon

Here is coordinates:

[[[[-73.92322762969822 40.828852037931064] [-73.9235617653475 40.828967083658526] [-73.92356166246613 40.82896725925209] [-73.9232275268162 40.828852213524335] [-73.92322762969822 40.828852037931064]]]]

This will crash prepair with segmentation fault.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.