XS-libgeos

 view release on metacpan or  search on metacpan

geos-3.7.3/include/geos/geom/BinaryOp.h  view on Meta::CPAN

 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2013 Sandro Santilli <strk@kbt.io>
 * Copyright (C) 2006 Refractions Research Inc.
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************
 *
 * Last port: ORIGINAL WORK
 *
 **********************************************************************
 *
 * This file provides a single templated function, taking two
 * const Geometry pointers, applying a binary operator to them
 * and returning a result Geometry in an unique_ptr<>.
 *
 * The binary operator is expected to take two const Geometry pointers
 * and return a newly allocated Geometry pointer, possibly throwing
 * a TopologyException to signal it couldn't succeed due to robustness
 * issues.
 *
 * This function will catch TopologyExceptions and try again with
 * slightly modified versions of the input. The following heuristic
 * is used:
 *
 *	- Try with original input.
 *	- Try removing common bits from input coordinate values
 *	- Try snaping input geometries to each other
 *	- Try snaping input coordinates to a increasing grid (size from 1/25 to 1)
 *	- Try simplifiying input with increasing tolerance (from 0.01 to 0.04)
 *
 * If none of the step succeeds the original exception is thrown.
 *
 * Note that you can skip Grid snapping, Geometry snapping and Simplify policies
 * by a compile-time define when building geos.
 * See USE_TP_SIMPLIFY_POLICY, USE_PRECISION_REDUCTION_POLICY and
 * USE_SNAPPING_POLICY macros below.
 *
 *
 **********************************************************************/

#ifndef GEOS_GEOM_BINARYOP_H
#define GEOS_GEOM_BINARYOP_H

#include <geos/algorithm/BoundaryNodeRule.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/GeometryCollection.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/Lineal.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/precision/CommonBitsRemover.h>
#include <geos/precision/SimpleGeometryPrecisionReducer.h>
#include <geos/precision/GeometryPrecisionReducer.h>

#include <geos/operation/overlay/snap/GeometrySnapper.h>

#include <geos/simplify/TopologyPreservingSimplifier.h>
#include <geos/operation/IsSimpleOp.h>
#include <geos/operation/valid/IsValidOp.h>
#include <geos/operation/valid/TopologyValidationError.h>
#include <geos/util/TopologyException.h>
#include <geos/util.h>

#include <memory> // for unique_ptr

//#define GEOS_DEBUG_BINARYOP 1
#define GEOS_DEBUG_BINARYOP_PRINT_INVALID 1

#ifdef GEOS_DEBUG_BINARYOP
# include <iostream>
# include <iomanip>
# include <sstream>
#endif


/*
 * Always try original input first
 */
#ifndef USE_ORIGINAL_INPUT
# define USE_ORIGINAL_INPUT 1
#endif

/*
 * Check validity of operation between original geometries
 */
#define GEOS_CHECK_ORIGINAL_RESULT_VALIDITY 0


/*
 * Define this to use PrecisionReduction policy
 * in an attempt at by-passing binary operation
 * robustness problems (handles TopologyExceptions)
 */
#ifndef USE_PRECISION_REDUCTION_POLICY
# define USE_PRECISION_REDUCTION_POLICY 1
#endif

/*
 * Check validity of operation performed
 * by precision reduction policy.
 *
 * Precision reduction policy reduces precision of inputs
 * and restores it in the result. The restore phase may
 * introduce invalidities.
 *
 */
#define GEOS_CHECK_PRECISION_REDUCTION_VALIDITY 0

/*
 * Define this to use TopologyPreserving simplification policy
 * in an attempt at by-passing binary operation
 * robustness problems (handles TopologyExceptions)
 */
#ifndef USE_TP_SIMPLIFY_POLICY
//# define USE_TP_SIMPLIFY_POLICY 1

geos-3.7.3/include/geos/geom/BinaryOp.h  view on Meta::CPAN

 * self-intersection of multipolygons
 *
 * May return the input untouched.
 */
inline std::unique_ptr<Geometry>
fix_self_intersections(std::unique_ptr<Geometry> g, const std::string& label)
{
  ::geos::ignore_unused_variable_warning(label);
#ifdef GEOS_DEBUG_BINARYOP
	std::cerr << label << " fix_self_intersection (UnaryUnion)" << std::endl;
#endif

  // Only multi-components can be fixed by UnaryUnion
  if ( ! dynamic_cast<const GeometryCollection*>(g.get()) ) return g;

  using operation::valid::IsValidOp;

  IsValidOp ivo(g.get());

  // Polygon is valid, nothing to do
  if ( ivo.isValid() ) return g;

  // Not all invalidities can be fixed by this code

  using operation::valid::TopologyValidationError;
  TopologyValidationError* err = ivo.getValidationError();
  switch ( err->getErrorType() ) {
    case TopologyValidationError::eRingSelfIntersection:
    case TopologyValidationError::eTooFewPoints: // collapsed lines
#ifdef GEOS_DEBUG_BINARYOP
	    std::cerr << label << " ATTEMPT_TO_FIX: " << err->getErrorType() << ": " << *g << std::endl;
#endif
      g = g->Union();
#ifdef GEOS_DEBUG_BINARYOP
	    std::cerr << label << " ATTEMPT_TO_FIX succeeded.. " << std::endl;
#endif
      return g;
    case TopologyValidationError::eSelfIntersection:
      // this one is within a single component, won't be fixed
    default:
#ifdef GEOS_DEBUG_BINARYOP
	    std::cerr << label << " invalidity is: " << err->getErrorType() << std::endl;
#endif
      return g;
  }
}


/// \brief
/// Apply a binary operation to the given geometries
/// after snapping them to each other after common-bits
/// removal.
///
template <class BinOp>
std::unique_ptr<Geometry>
SnapOp(const Geometry* g0, const Geometry *g1, BinOp _Op)
{
	typedef std::unique_ptr<Geometry> GeomPtr;

	//using geos::precision::GeometrySnapper;
	using geos::operation::overlay::snap::GeometrySnapper;

	// Snap tolerance must be computed on the original
	// (not commonbits-removed) geoms
	double snapTolerance = GeometrySnapper::computeOverlaySnapTolerance(*g0, *g1);
#if GEOS_DEBUG_BINARYOP
	std::cerr<< std::setprecision(20) << "Computed snap tolerance: "<<snapTolerance<<std::endl;
#endif


#if CBR_BEFORE_SNAPPING
	// Compute common bits
	geos::precision::CommonBitsRemover cbr;
	cbr.add(g0); cbr.add(g1);
#if GEOS_DEBUG_BINARYOP
	std::cerr<<"Computed common bits: "<<cbr.getCommonCoordinate()<<std::endl;
#endif

	// Now remove common bits
	GeomPtr rG0( cbr.removeCommonBits(g0->clone()) );
	GeomPtr rG1( cbr.removeCommonBits(g1->clone()) );

#if GEOS_DEBUG_BINARYOP
	check_valid(*rG0, "CBR: removed-bits geom 0");
	check_valid(*rG1, "CBR: removed-bits geom 1");
#endif

	const Geometry& operand0 = *rG0;
	const Geometry& operand1 = *rG1;
#else // don't CBR before snapping
	const Geometry& operand0 = *g0;
	const Geometry& operand1 = *g1;
#endif


	GeometrySnapper snapper0( operand0 );
	GeomPtr snapG0( snapper0.snapTo(operand1, snapTolerance) );
	//snapG0 = fix_self_intersections(snapG0, "SNAP: snapped geom 0");

	// NOTE: second geom is snapped on the snapped first one
	GeometrySnapper snapper1( operand1 );
	GeomPtr snapG1( snapper1.snapTo(*snapG0, snapTolerance) );
	//snapG1 = fix_self_intersections(snapG1, "SNAP: snapped geom 1");

	// Run the binary op
	GeomPtr result( _Op(snapG0.get(), snapG1.get()) );

#if GEOS_DEBUG_BINARYOP
	check_valid(*result, "SNAP: result (before common-bits addition");
#endif

#if CBR_BEFORE_SNAPPING
	// Add common bits back in
	cbr.addCommonBits( result.get() );
	//result = fix_self_intersections(result, "SNAP: result (after common-bits addition)");

  check_valid(*result, "CBR: result (after common-bits addition)", true);

#endif

	return result;



( run in 2.847 seconds using v1.01-cache-2.11-cpan-63c85eba8c4 )