如何在不连接数据库时将PostGIS ST_MakeValid应用于Boost.Geometry多边形?
Great question! If you want to replicate PostGIS's ST_MakeValid functionality for Boost.Geometry polygons without connecting to a PostgreSQL database, you can use Boost.Geometry's built-in validation and correction tools. Here's how to do it step by step:
Step 1: Check Polygon Validity
First, confirm if your polygon is invalid and understand the root cause. Boost.Geometry's is_valid function returns validity status along with a human-readable error message.
#include <boost/geometry.hpp> #include <boost/geometry/geometries/polygon.hpp> #include <boost/geometry/io/wkt/wkt.hpp> #include <iostream> #include <string> namespace bg = boost::geometry; typedef bg::model::point<double, 2, bg::cs::cartesian> Point; typedef bg::model::polygon<Point> Polygon; int main() { // Load your polygon from WKT Polygon poly; bg::read_wkt("POLYGON((0 0, 10 0, 10 11, 11 10, 0 10))", poly); // Check validity and get error details std::string error_msg; bool is_valid = bg::is_valid(poly, error_msg); if (!is_valid) { std::cout << "Polygon is invalid: " << error_msg << std::endl; } else { std::cout << "Polygon is already valid!" << std::endl; return 0; }
Step 2: Apply Basic Corrections
Start with bg::correct—this fixes common simple invalidities like:
- Unclosed polygon rings
- Incorrect ring orientation (violating the right-hand rule)
- Duplicate consecutive vertices
Add this code right after checking validity:
// Fix basic issues with boost::geometry::correct bg::correct(poly); // Re-check validity after basic correction is_valid = bg::is_valid(poly, error_msg); if (is_valid) { std::cout << "Polygon fixed with basic correction!" << std::endl; // Convert back to WKT if needed std::string corrected_wkt; bg::write_wkt(corrected_wkt, poly); std::cout << "Corrected WKT: " << corrected_wkt << std::endl; return 0; }
Step 3: Fix Complex Invalidities (e.g., Self-Intersections)
If basic correction isn't enough (like with self-intersecting polygons), use the buffer(0) trick—this is a widely used workaround in Boost.Geometry to resolve self-intersections, mirroring how ST_MakeValid handles such cases.
For scenarios where correction splits the polygon into multiple shapes, use a multi_polygon to capture all valid results:
// Handle complex issues like self-intersections with buffer(0) typedef bg::model::multi_polygon<Polygon> MultiPolygon; MultiPolygon corrected_multi; // Buffer with 0 distance to auto-resolve self-intersections bg::buffer(poly, corrected_multi, bg::strategy::buffer::distance_symmetric<double>(0.0)); // Verify and output all corrected polygons std::cout << "Corrected into " << corrected_multi.size() << " valid polygon(s):" << std::endl; for (const auto& corrected_poly : corrected_multi) { if (bg::is_valid(corrected_poly, error_msg)) { std::string wkt; bg::write_wkt(wkt, corrected_poly); std::cout << "- " << wkt << std::endl; } else { std::cout << "- Failed to validate a corrected sub-polygon: " << error_msg << std::endl; } } return 0; }
Key Notes
- Boost.Geometry doesn't have a direct 1:1 equivalent to
ST_MakeValid, but combiningbg::correctand the buffer(0) trick covers most common invalid polygon scenarios. - The buffer strategy can be customized for edge-case resolution, but the default symmetric 0-distance buffer works for most use cases.
- Always re-validate after correction to ensure the final geometry is valid.
内容的提问来源于stack exchange,提问作者sergio campo

