/**
 * Because Delete Events have a link to their corresponding Insert event,
 * it is possible to compute exactly the range of events which must be
 * compared to a given Insert event object.
 */
void
SimpleMCSweepLineIntersector::prepareEvents()
{
	sort(events.begin(), events.end(), SweepLineEventLessThen());
	for(size_t i=0; i<events.size(); ++i)
	{
		GEOS_CHECK_FOR_INTERRUPTS();
		SweepLineEvent *ev=events[i];
		if (ev->isDelete())
		{
			ev->getInsertEvent()->setDeleteEventIndex(i);
		}
	}
}
void
SimpleMCSweepLineIntersector::add(Edge *edge, void* edgeSet)
{
	MonotoneChainEdge *mce=edge->getMonotoneChainEdge();
	auto& startIndex = mce->getStartIndexes();
	size_t n = startIndex.size() - 1;
	events.reserve(events.size()+(n*2));
	for(size_t i = 0; i < n; ++i)
	{
		GEOS_CHECK_FOR_INTERRUPTS();
		MonotoneChain *mc=new MonotoneChain(mce, i);
		SweepLineEvent *insertEvent=new SweepLineEvent(edgeSet, mce->getMinX(i), nullptr, mc);
		events.push_back(insertEvent);
		events.push_back(new SweepLineEvent(edgeSet, mce->getMaxX(i), insertEvent, mc));
	}
}
Exemplo n.º 3
0
/*private*/
void
MCIndexNoder::intersectChains()
{
	assert(segInt);

	SegmentOverlapAction overlapAction(*segInt);

	for (vector<MonotoneChain*>::iterator
			i=monoChains.begin(), iEnd=monoChains.end();
			i != iEnd;
			++i)
	{

		GEOS_CHECK_FOR_INTERRUPTS();

		MonotoneChain* queryChain = *i;
		assert(queryChain);
		vector<void*> overlapChains;
		index.query(&(queryChain->getEnvelope()), overlapChains);
		for (vector<void*>::iterator
			j=overlapChains.begin(), jEnd=overlapChains.end();
			j != jEnd;
			++j)
		{
			MonotoneChain* testChain = static_cast<MonotoneChain*>(*j);
			assert(testChain);

			/**
			 * following test makes sure we only compare each
			 * pair of chains once and that we don't compare a
			 * chain to itself
			 */
			if (testChain->getId() > queryChain->getId()) {
				queryChain->computeOverlaps(testChain,
						&overlapAction);
				nOverlaps++;
			}

			// short-circuit if possible
			if (segInt->isDone()) return;

		}
	}
}
void
SimpleMCSweepLineIntersector::computeIntersections(SegmentIntersector *si)
{
	nOverlaps=0;
	prepareEvents();
	for(size_t i=0; i<events.size(); ++i)
	{
		GEOS_CHECK_FOR_INTERRUPTS();
		SweepLineEvent *ev=events[i];
		if (ev->isInsert())
		{
			processOverlaps(i, ev->getDeleteEventIndex(), ev, si);
		}
		if (si->getIsDone())
		{
			break;
		}
	}
}
Exemplo n.º 5
0
IntersectionMatrix*
RelateComputer::computeIM()
{
	// since Geometries are finite and embedded in a 2-D space, the EE element must always be 2
	im->set(Location::EXTERIOR,Location::EXTERIOR,2);
	// if the Geometries don't overlap there is nothing to do
	const Envelope *e1=(*arg)[0]->getGeometry()->getEnvelopeInternal();
	const Envelope *e2=(*arg)[1]->getGeometry()->getEnvelopeInternal();
	if (!e1->intersects(e2)) {
		computeDisjointIM(im.get());
		return im.release();
	}

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing self nodes 1"
            << std::endl;
#endif

	std::unique_ptr<SegmentIntersector> si1 (
		(*arg)[0]->computeSelfNodes(&li,false)
	);

	GEOS_CHECK_FOR_INTERRUPTS();

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing self nodes 2"
            << std::endl;
#endif

	std::unique_ptr<SegmentIntersector> si2 (
		(*arg)[1]->computeSelfNodes(&li,false)
	);

	GEOS_CHECK_FOR_INTERRUPTS();

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing edge intersections"
            << std::endl;
#endif

	// compute intersections between edges of the two input geometries
	std::unique_ptr< SegmentIntersector> intersector (
    (*arg)[0]->computeEdgeIntersections((*arg)[1], &li,false)
  );

	GEOS_CHECK_FOR_INTERRUPTS();

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "copying intersection nodes"
            << std::endl;
#endif

	computeIntersectionNodes(0);
	computeIntersectionNodes(1);

	GEOS_CHECK_FOR_INTERRUPTS();

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "copying nodes and labels"
            << std::endl;
#endif

	GEOS_CHECK_FOR_INTERRUPTS();

	/*
	 * Copy the labelling for the nodes in the parent Geometries.
	 * These override any labels determined by intersections
	 * between the geometries.
	 */
	copyNodesAndLabels(0);
	copyNodesAndLabels(1);

	GEOS_CHECK_FOR_INTERRUPTS();

	/*
	 * complete the labelling for any nodes which only have a
	 * label for a single geometry
	 */
	//Debug.addWatch(nodes.find(new Coordinate(110, 200)));
	//Debug.printWatch();
#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "labeling isolated nodes"
            << std::endl;
#endif
	labelIsolatedNodes();
	//Debug.printWatch();

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing proper intersection matrix"
            << std::endl;
#endif

	/*
	 * If a proper intersection was found, we can set a lower bound
	 * on the IM.
	 */
	computeProperIntersectionIM(intersector.get(), im.get());

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing improper intersections"
            << std::endl;
#endif

	/*
	 * Now process improper intersections
	 * (eg where one or other of the geometrys has a vertex at the
	 * intersection point)
	 * We need to compute the edge graph at all nodes to determine
	 * the IM.
	 */
	// build EdgeEnds for all intersections
	EdgeEndBuilder eeBuilder;
	std::unique_ptr< std::vector<EdgeEnd*> > ee0 (
		eeBuilder.computeEdgeEnds((*arg)[0]->getEdges())
  );
	insertEdgeEnds(ee0.get());
	std::unique_ptr< std::vector<EdgeEnd*> > ee1 (
		eeBuilder.computeEdgeEnds((*arg)[1]->getEdges())
  );

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "inserting edge ends"
            << std::endl;
#endif

	insertEdgeEnds(ee1.get());
	//Debug.println("==== NodeList ===");
	//Debug.print(nodes);

#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "labeling node edges"
            << std::endl;
#endif

	labelNodeEdges();

	/**
	 * Compute the labeling for isolated components.
	 * Isolated components are components that do not touch any
	 * other components in the graph.
	 * They can be identified by the fact that they will
	 * contain labels containing ONLY a single element, the one for
	 * their parent geometry.
	 * We only need to check components contained in the input graphs,
	 * since isolated components will not have been replaced by new
	 * components formed by intersections.
	 */
#if GEOS_DEBUG
	std::cerr << "RelateComputer::computeIM: "
            << "computing labeling for isolated components"
            << std::endl;
#endif
	//debugPrintln("Graph A isolated edges - ");
	labelIsolatedEdges(0,1);
	//debugPrintln("Graph B isolated edges - ");
	labelIsolatedEdges(1,0);
	// update the IM from all components
	updateIM( *im );
	return im.release();
}
Exemplo n.º 6
0
/*private*/
void
LineStringSnapper::snapSegments(geom::CoordinateList& srcCoords,
                                const geom::Coordinate::ConstVect& snapPts)
{

    // nothing to do if there are no source coords..
    if(srcCoords.empty()) {
        return;
    }

    GEOS_CHECK_FOR_INTERRUPTS();

#if GEOS_DEBUG
    cerr << "Snapping segments of: " << srcCoords << endl;
#endif

    for(Coordinate::ConstVect::const_iterator
            it = snapPts.begin(), end = snapPts.end();
            it != end;
            ++it) {
        assert(*it);
        const Coordinate& snapPt = *(*it);

#if GEOS_DEBUG
        cerr << "Checking for a segment to snap to snapPt " << snapPt << endl;
#endif

        CoordinateList::iterator too_far = srcCoords.end();
        --too_far;
        CoordinateList::iterator segpos =
            findSegmentToSnap(snapPt, srcCoords.begin(), too_far);
        if(segpos == too_far) {
#if GEOS_DEBUG
            cerr << " No segment to snap" << endl;
#endif
            continue;
        }

        /* Check if the snap point falls outside of the segment */
        // If the snap point is outside, this means that an endpoint
        // was not snap where it should have been
        // so what we should do is re-snap the endpoint to this
        // snapPt and then snap the closest between this and
        // previous (for pf < 0.0) or next (for pf > 1.0) segment
        // to the old endpoint.
        //     --strk May 2013
        //
        // TODO: simplify this code, make more readable
        //
        CoordinateList::iterator to = segpos;
        ++to;
        LineSegment seg(*segpos, *to);
        double pf = seg.projectionFactor(snapPt);
        if(pf >= 1.0) {
#if GEOS_DEBUG
            cerr << " Segment to be snapped is closer on his end point" << endl;
#endif
            Coordinate newSnapPt = seg.p1;
            *to = seg.p1 = snapPt;
            // now snap from-to (segpos) or to-next (segpos++) to newSnapPt
            if(to == too_far) {
                if(isClosed) {
#if GEOS_DEBUG
                    cerr << " His end point is the last one, but is closed " << endl;
#endif
                    *(srcCoords.begin()) = snapPt; // sync to start point
                    to = srcCoords.begin();
                }
                else {
#if GEOS_DEBUG
                    cerr << " His end point is the last one, inserting " << newSnapPt << " before it" << endl;
#endif
                    srcCoords.insert(to, newSnapPt);
                    continue;
                }
            }
            ++to;
            LineSegment nextSeg(seg.p1, *to);
            if(nextSeg.distance(newSnapPt) < seg.distance(newSnapPt)) {
#if GEOS_DEBUG
                cerr << " Next segment closer, inserting " << newSnapPt << " into " << nextSeg << endl;
#endif
                // insert into next segment
                srcCoords.insert(to, newSnapPt);
            }
            else {
#if GEOS_DEBUG
                cerr << " This segment closer, inserting " << newSnapPt << " into " << seg << endl;
#endif
                // insert must happen one-past first point (before next point)
                ++segpos;
                srcCoords.insert(segpos, newSnapPt);
            }
        }
        else if(pf <= 0.0) {
#if GEOS_DEBUG
            cerr << " Segment to be snapped is closer on his start point" << endl;
#endif
            Coordinate newSnapPt = seg.p0;
            *segpos = seg.p0 = snapPt;
            // now snap prev-from (--segpos) or from-to (segpos) to newSnapPt
            if(segpos == srcCoords.begin()) {
                if(isClosed) {
#if GEOS_DEBUG
                    cerr << " His start point is the first one, but is closed " << endl;
#endif
                    segpos = srcCoords.end();
                    --segpos;
                    *segpos = snapPt; // sync to end point
                }
                else {
#if GEOS_DEBUG
                    cerr << " His start point is the first one, inserting " << newSnapPt << " before it" << endl;
#endif
                    ++segpos;
                    srcCoords.insert(segpos, newSnapPt);
                    continue;
                }
            }

#if GEOS_DEBUG
            cerr << " Before seg-snapping, srcCoors are: " << srcCoords << endl;
#endif

            --segpos;
            LineSegment prevSeg(*segpos, seg.p0);
            if(prevSeg.distance(newSnapPt) < seg.distance(newSnapPt)) {
#if GEOS_DEBUG
                cerr << " Prev segment closer, inserting " << newSnapPt << " into "
                     << prevSeg << endl;
#endif
                // insert into prev segment
                ++segpos;
                srcCoords.insert(segpos, newSnapPt);
            }
            else {
#if GEOS_DEBUG
                cerr << " This segment closer, inserting " << newSnapPt << " into " << seg << endl;
#endif
                // insert must happen one-past first point (before next point)
                srcCoords.insert(to, newSnapPt);
            }
        }
        else {
            //assert(pf != 0.0);
#if GEOS_DEBUG
            cerr << " Segment to be snapped found, projection factor is " << pf << ", inserting point" << endl;
#endif
            // insert must happen one-past first point (before next point)
            ++segpos;
            srcCoords.insert(segpos, snapPt);
        }
    }

#if GEOS_DEBUG
    cerr << " After segment snapping, srcCoors are: " << srcCoords << endl;
#endif

}
Exemplo n.º 7
0
/*private*/
void
LineStringSnapper::snapVertices(geom::CoordinateList& srcCoords,
                                const geom::Coordinate::ConstVect& snapPts)
{
    // nothing to do if there are no source coords..
    if(srcCoords.empty()) {
        return;
    }

#if GEOS_DEBUG
    cerr << "Snapping vertices of: " << srcCoords << endl;
#endif

    for(Coordinate::ConstVect::const_iterator
            it = snapPts.begin(), end = snapPts.end();
            it != end;
            ++it) {
        GEOS_CHECK_FOR_INTERRUPTS();
        assert(*it);
        const Coordinate& snapPt = *(*it);

#if GEOS_DEBUG
        cerr << "Checking for a vertex to snap to snapPt " << snapPt << endl;
#endif

        CoordinateList::iterator too_far = srcCoords.end();
        if(isClosed) {
            --too_far;
        }
        CoordinateList::iterator vertpos =
            findVertexToSnap(snapPt, srcCoords.begin(), too_far);
        if(vertpos == too_far) {
#if GEOS_DEBUG
            cerr << " No vertex to snap" << endl;
#endif
            continue;
        }

#if GEOS_DEBUG
        cerr << " Vertex to be snapped found, snapping" << endl;
#endif
        *vertpos = snapPt;

        // keep final closing point in synch (rings only)
        if(vertpos == srcCoords.begin() && isClosed) {
            vertpos = srcCoords.end();
            --vertpos;
#if GEOS_DEBUG
            cerr << " Snapped vertex was first in a closed line, also snapping last" << endl;
#endif
            *vertpos = snapPt;
        }

#if GEOS_DEBUG
        cerr << " After snapping of vertex " << snapPt << ", srcCoors are: " << srcCoords << endl;
#endif

    }

#if GEOS_DEBUG
    cerr << " After vertices snapping, srcCoors are: " << srcCoords << endl;
#endif

}