/* private */
auto_ptr<Geometry>
GeometryPrecisionReducer::fixPolygonalTopology(const geom::Geometry& geom )
{
  /**
   * If precision model was *not* changed, need to flip
   * geometry to targetPM, buffer in that model, then flip back
   */
  auto_ptr<Geometry> tmp;
  auto_ptr<GeometryFactory> tmpFactory;

  const Geometry* geomToBuffer = &geom;

  if ( ! newFactory ) {
    tmpFactory = createFactory(*geom.getFactory(), targetPM);
    tmp.reset( tmpFactory->createGeometry(&geom) );
    geomToBuffer = tmp.get();
  }

  auto_ptr<Geometry> bufGeom ( geomToBuffer->buffer(0) );

  if ( ! newFactory ) {
    // a slick way to copy the geometry with the original precision factory
    bufGeom.reset( geom.getFactory()->createGeometry(bufGeom.get()) );
  }

  return bufGeom;
}
Exemple #2
0
static int
checkSingleSidedBufferSuccess(geom::Geometry& gRes,
        geom::Geometry& gRealRes, double dist)
{
    int success = 1;
    do
    {

        if ( gRes.getGeometryTypeId() != gRealRes.getGeometryTypeId() )
        {
            std::cerr << "Expected result is of type "
                << gRes.getGeometryType()
                << "; obtained result is of type "
                << gRealRes.getGeometryType()
                << std::endl;
            success=0;
            break;
        }

        geos::xmltester::SingleSidedBufferResultMatcher matcher;
        if ( ! matcher.isBufferResultMatch(gRealRes,
                           gRes,
                           dist) )
        {
std::cerr << "SingleSidedBufferResultMatcher FAILED" << std::endl;
            success=0;
            break;
        }

    }
    while (0);

    return success;
}
bool
BufferResultMatcher::isBoundaryHausdorffDistanceInTolerance(
	const geom::Geometry& actualBuffer,
	const geom::Geometry& expectedBuffer, double distance)
{
	typedef std::auto_ptr<geom::Geometry> GeomPtr;

	using geos::algorithm::distance::DiscreteHausdorffDistance;

	GeomPtr actualBdy ( actualBuffer.getBoundary() );
	GeomPtr expectedBdy ( expectedBuffer.getBoundary() );

	DiscreteHausdorffDistance haus(*actualBdy, *expectedBdy);
	haus.setDensifyFraction(0.25);

	double maxDistanceFound = haus.orientedDistance();

	double expectedDistanceTol = fabs(distance) / MAX_HAUSDORFF_DISTANCE_FACTOR;
	if (expectedDistanceTol < MIN_DISTANCE_TOLERANCE)
	{
		expectedDistanceTol = MIN_DISTANCE_TOLERANCE;
	}

	if (maxDistanceFound > expectedDistanceTol)
	{
std::cerr << "maxDistanceFound: " << maxDistanceFound << " tolerated " << expectedDistanceTol << std::endl;
		return false;
	}

	return true;
}
bool
BufferResultMatcher::isBufferResultMatch(const geom::Geometry& actualBuffer,
	                         const geom::Geometry& expectedBuffer,
	                         double distance)
{
	if (actualBuffer.isEmpty() && expectedBuffer.isEmpty())
		return true;

	/**
	 * MD - need some more checks here - symDiffArea won't catch
	 * very small holes ("tears")
	 * near the edge of computed buffers (which can happen
	 * in current version of JTS (1.8)).
	 * This can probably be handled by testing
	 * that every point of the actual buffer is at least a certain
	 * distance away from the geometry boundary.
	 */
	if (! isSymDiffAreaInTolerance(actualBuffer, expectedBuffer))
	{
std::cerr << "isSymDiffAreaInTolerance failed" << std::endl;
		return false;
	}

	if (! isBoundaryHausdorffDistanceInTolerance(actualBuffer,
	           expectedBuffer, distance))
	{
std::cerr << "isBoundaryHasudorffDistanceInTolerance failed" << std::endl;
		return false;
	}

	return true;
}
bool
AbstractPreparedPolygonContains::isSingleShell( const geom::Geometry & geom)
{
    // handles single-element MultiPolygons, as well as Polygons
    if ( geom.getNumGeometries() != 1)
        return false;

    const geom::Polygon * poly = (Polygon *)geom.getGeometryN( 0);

    int numHoles = poly->getNumInteriorRing();
    return (numHoles == 0);
}
Exemple #6
0
/* private */
void
SnapOverlayOp::removeCommonBits(const geom::Geometry& geom0,
                                const geom::Geometry& geom1,
				geom::GeomPtrPair& remGeom)
{
	cbr.reset(new precision::CommonBitsRemover());
	cbr->add(&geom0);
	cbr->add(&geom1);

	remGeom.first.reset( cbr->removeCommonBits(geom0.clone()) );
	remGeom.second.reset( cbr->removeCommonBits(geom1.clone()) );
}
bool 
AbstractPreparedPolygonContains::isSingleShell(const geom::Geometry& geom)
{
	// handles single-element MultiPolygons, as well as Polygons
	if (geom.getNumGeometries() != 1)
    {
		return false;
    }
	
    const geom::Geometry* g = geom.getGeometryN(0);
	const geom::Polygon* poly = static_cast<const Polygon*>(g);

    std::size_t numHoles = poly->getNumInteriorRing();
	return (0 == numHoles);
}
bool
RectangleIntersects::intersects(const geom::Geometry& geom)
{
	if (!rectEnv.intersects(geom.getEnvelopeInternal()))
		return false;

	// test envelope relationships
	EnvelopeIntersectsVisitor visitor(rectEnv);
	visitor.applyTo(geom);
	if (visitor.intersects()) return true;

	// test if any rectangle corner is contained in the target
	ContainsPointVisitor ecpVisitor(rectangle);
	ecpVisitor.applyTo(geom);
	if (ecpVisitor.containsPoint())
		return true;

	// test if any lines intersect
	LineIntersectsVisitor liVisitor(rectangle);
	liVisitor.applyTo(geom);
	if (liVisitor.intersects())
		return true;

	return false;
}
bool
BufferResultMatcher::isSymDiffAreaInTolerance(
	const geom::Geometry& actualBuffer,
	const geom::Geometry& expectedBuffer)
{
	typedef std::auto_ptr<geom::Geometry> GeomPtr;

	using namespace operation::overlay;
	using geos::geom::BinaryOp;

	double area = expectedBuffer.getArea();
	GeomPtr diff = BinaryOp(&actualBuffer, &expectedBuffer,
	                   overlayOp(OverlayOp::opSYMDIFFERENCE));

	double areaDiff = diff->getArea();
	
	// can't get closer than difference area = 0 ! 
	// This also handles case when symDiff is empty
	if (areaDiff <= 0.0) return true;

	if (area <= 0) return false; 
	double frac = areaDiff / area;

	bool ret = frac < MAX_RELATIVE_AREA_DIFFERENCE;
	if ( ! ret )
	{
std::cerr << "symDiffArea frac: " << frac << " tolerated " << MAX_RELATIVE_AREA_DIFFERENCE << std::endl;
	}
	return ret;
}
	void visit(const geom::Geometry &geom)
	{
		using GEOMETRY::algorithm::locate::SimplePointInAreaLocator;

		const geom::Polygon *poly;

		if ( !(poly=dynamic_cast<const geom::Polygon *>(&geom)) ) {
			return;
		}

		const geom::Envelope &elementEnv = *(geom.getEnvelopeInternal());

		if ( !rectEnv.intersects(elementEnv) ) {
			return;
		}

		// test each corner of rectangle for inclusion
		for (int i=0; i<4; i++)
		{

			const geom::Coordinate &rectPt=rectSeq.getAt(i);

			if ( !elementEnv.contains(rectPt) ) {
				continue;
			}

			// check rect point in poly (rect is known not to
			// touch polygon at this point)
			if ( SimplePointInAreaLocator::containsPointInPolygon(rectPt, poly) )
			{
				containsPointVar=true;
				return;
			}
		}
	}
Exemple #11
0
/* private static */
void
GeometryNoder::extractSegmentStrings(const geom::Geometry& g,
                                     SegmentString::NonConstVect& to)
{
  SegmentStringExtractor ex(to);
	g.apply_ro(&ex);
}
Exemple #12
0
/* public static */
void
DistanceToPoint::computeDistance(const geom::Geometry& geom,
                                          const geom::Coordinate& pt,
                                          PointPairDistance& ptDist)
{
	if ( const LineString* ls = dynamic_cast<const LineString*>(&geom) )
	{
		computeDistance(*ls, pt, ptDist);
	}
	else if ( const Polygon* pl = dynamic_cast<const Polygon*>(&geom) )
	{
		computeDistance(*pl, pt, ptDist);
	}
	else if ( const GeometryCollection* gc = dynamic_cast<const GeometryCollection*>(&geom) )
	{
		for (size_t i = 0; i < gc->getNumGeometries(); i++)
		{
			const Geometry* g = gc->getGeometryN(i);
			computeDistance(*g, pt, ptDist);
		}
	}
	else
	{
		// assume geom is Point
		ptDist.setMinimum(*(geom.getCoordinate()), pt);
	}
}
/*public static*/
double
GeometrySnapper::computeSizeBasedSnapTolerance(const geom::Geometry& g)
{
	const Envelope* env = g.getEnvelopeInternal();
	double minDimension = (std::min)(env->getHeight(), env->getWidth());
	double snapTol = minDimension * snapPrecisionFactor;
	return snapTol;
}
	void visit(const geom::Geometry &geom)
	{
		const geom::Envelope &elementEnv = *(geom.getEnvelopeInternal());
		if (! rectEnv.intersects(elementEnv) ) {
			return;
		}

		// check if general relate algorithm should be used,
		// since it's faster for large inputs
		if (geom.getNumPoints() > RectangleIntersects::MAXIMUM_SCAN_SEGMENT_COUNT)
		{
			intersectsVar = rectangle.relate(geom)->isIntersects();
			return;
		}

		// if small enough, test for segment intersection directly
		computeSegmentIntersection(geom);
	}
Exemple #15
0
/* Could be an XMLTester class private but oh well.. */
static int
checkBufferSuccess(geom::Geometry const& gRes, geom::Geometry const& gRealRes, double dist)
{
    int success = 1;
    do
    {

        if ( gRes.getGeometryTypeId() != gRealRes.getGeometryTypeId() )
        {
            std::cerr << "Expected result is of type "
                << gRes.getGeometryType()
                << "; obtained result is of type "
                << gRealRes.getGeometryType()
                << std::endl;
            success=0;
            break;
        }

        // Is a buffer always an area ?
        if ( gRes.getDimension() != 2 )
        {
            std::cerr << "Don't know how to validate "
                << "result of buffer operation "
                << "when expected result is not an "
                << "areal type."
                << std::endl;
        }
        

        geos::xmltester::BufferResultMatcher matcher;
        if ( ! matcher.isBufferResultMatch(gRealRes,
                           gRes,
                           dist) )
        {
std::cerr << "BufferResultMatcher FAILED" << std::endl;
            success=0;
            break;
        }

    }
    while (0);

    return success;
}
Exemple #16
0
/* public */
SharedPathsOp::SharedPathsOp(
    const geom::Geometry& g1, const geom::Geometry& g2)
  :
  _g1(g1),
  _g2(g2),
  _gf(*g1.getFactory())
{
  checkLinealInput(_g1);
  checkLinealInput(_g2);
}
bool
SingleSidedBufferResultMatcher::isBufferResultMatch(const geom::Geometry& actualBuffer,
	                         const geom::Geometry& expectedBuffer,
	                         double distance)
{
	bool aEmpty = actualBuffer.isEmpty();
	bool eEmpty = expectedBuffer.isEmpty();

	// Both empty succeeds
	if (aEmpty && eEmpty) return true;

	// One empty and not the other is a failure
	if (aEmpty || eEmpty)
	{
std::cerr << "isBufferResultMatch failed (one empty and one not)" << std::endl;
		return false;
	}


   // NOTE: we need to test hausdorff distance in both directions

	if (! isBoundaryHausdorffDistanceInTolerance(actualBuffer,
	           expectedBuffer, distance))
	{
std::cerr << "isBoundaryHasudorffDistanceInTolerance failed (actual,expected)" << std::endl;
		return false;
	}

	if (! isBoundaryHausdorffDistanceInTolerance(expectedBuffer,
	           actualBuffer, distance))
	{
std::cerr << "isBoundaryHasudorffDistanceInTolerance failed (expected,actual)" << std::endl;
		return false;
	}

	return true;
}
/*public static*/
double
GeometrySnapper::computeOverlaySnapTolerance(const geom::Geometry& g)
{
	double snapTolerance = computeSizeBasedSnapTolerance(g);

	/**
	 * Overlay is carried out in the precision model
	 * of the two inputs.
	 * If this precision model is of type FIXED, then the snap tolerance
	 * must reflect the precision grid size.
	 * Specifically, the snap tolerance should be at least
	 * the distance from a corner of a precision grid cell
	 * to the centre point of the cell.
	 */
	assert(g.getPrecisionModel());
	const PrecisionModel& pm = *(g.getPrecisionModel());
	if (pm.getType() == PrecisionModel::FIXED)
	{
		double fixedSnapTol = (1 / pm.getScale()) * 2 / 1.415;
		if ( fixedSnapTol > snapTolerance )
			snapTolerance = fixedSnapTol;
	}
	return snapTolerance;
}
	/**
	 * Reports whether it can be concluded that an intersection occurs,
	 * or whether further testing is required.
	 *
	 * @return <code>true</code> if an intersection must occur
	 * <code>false</code> if no conclusion can be made
	 */
	void visit(const geom::Geometry &element)
	{
		const geom::Envelope &elementEnv = *(element.getEnvelopeInternal());

		// disjoint
		if ( ! rectEnv.intersects(elementEnv) ) {
			return;
		}

		// fully contained - must intersect
		if ( rectEnv.contains(elementEnv) ) {
			intersectsVar = true;
			return;
		}

		/*
		 * Since the envelopes intersect and the test element is
		 * connected, if the test envelope is completely bisected by
		 * an edge of the rectangle the element and the rectangle
		 * must touch (This is basically an application of the
		 * Jordan Curve Theorem).  The alternative situation
		 * is that the test envelope is "on a corner" of the
		 * rectangle envelope, i.e. is not completely bisected.
		 * In this case it is not possible to make a conclusion
		 * about the presence of an intersection.
		 */
		if (elementEnv.getMinX() >= rectEnv.getMinX()
			&& elementEnv.getMaxX() <= rectEnv.getMaxX())
		{
			intersectsVar=true;
			return;
		}
		if (elementEnv.getMinY() >= rectEnv.getMinY()
			&& elementEnv.getMaxY() <= rectEnv.getMaxY())
		{
			intersectsVar = true;
			return;
		}
	}