/*private*/ void DouglasPeuckerLineSimplifier::simplifySection( std::size_t i, std::size_t j) { if((i + 1) == j) { return; } geos::geom::LineSegment seg(pts[i], pts[j]); double maxDistance = -1.0; std::size_t maxIndex = i; for(std::size_t k = i + 1; k < j; k++) { double distance = seg.distance(pts[k]); if(distance > maxDistance) { maxDistance = distance; maxIndex = k; } } if(maxDistance <= distanceTolerance) { for(std::size_t k = i + 1; k < j; k++) { usePt->operator[](k) = false; } } else { simplifySection(i, maxIndex); simplifySection(maxIndex, j); } }
/*public*/ void TaggedLineStringSimplifier::simplify(TaggedLineString* nLine) { assert(nLine); line = nLine; linePts = line->getParentCoordinates(); assert(linePts); #if GEOS_DEBUG std::cerr << "TaggedLineStringSimplifier[" << this << "] " << " TaggedLineString[" << line << "] " << " has " << linePts->size() << " coords in input" << std::endl; #endif simplifySection(0, linePts->size() - 1, 0); }
/*public*/ DouglasPeuckerLineSimplifier::CoordsVectAutoPtr DouglasPeuckerLineSimplifier::simplify() { CoordsVectAutoPtr coordList(new CoordsVect()); // empty coordlist is the simplest, won't simplify further if(! pts.size()) { return coordList; } usePt = BoolVectAutoPtr(new BoolVect(pts.size(), true)); simplifySection(0, pts.size() - 1); for(std::size_t i = 0, n = pts.size(); i < n; ++i) { if(usePt->operator[](i)) { coordList->push_back(pts[i]); } } // unique_ptr transfer ownership to its // returned copy return coordList; }
/*private*/ void TaggedLineStringSimplifier::simplifySection(size_t i, size_t j, size_t depth) { depth += 1; #if GEOS_DEBUG std::cerr << "TaggedLineStringSimplifier[" << this << "] " << " simplifying section " << i << "-" << j << std::endl; #endif vector<size_t> sectionIndex(2); if((i+1) == j) { #if GEOS_DEBUG std::cerr << "single segment, no flattening" << std::endl; #endif auto_ptr<TaggedLineSegment> newSeg(new TaggedLineSegment(*(line->getSegment(i)))); line->addToResult(newSeg); // leave this segment in the input index, for efficiency return; } bool isValidToSimplify = true; /** * Following logic ensures that there is enough points in the * output line. * If there is already more points than the minimum, there's * nothing to check. * Otherwise, if in the worst case there wouldn't be enough points, * don't flatten this segment (which avoids the worst case scenario) */ if (line->getResultSize() < line->getMinimumSize()) { size_t worstCaseSize = depth + 1; if (worstCaseSize < line->getMinimumSize()) isValidToSimplify = false; } double distance; // pass distance by ref size_t furthestPtIndex = findFurthestPoint(linePts, i, j, distance); #if GEOS_DEBUG std::cerr << "furthest point " << furthestPtIndex << " at distance " << distance << std::endl; #endif // flattening must be less than distanceTolerance if ( distance > distanceTolerance ) isValidToSimplify = false; // test if flattened section would cause intersection LineSegment candidateSeg(linePts->getAt(i), linePts->getAt(j)); sectionIndex[0] = i; sectionIndex[1] = j; if (hasBadIntersection(line, sectionIndex, candidateSeg)) isValidToSimplify = false; if (isValidToSimplify) { auto_ptr<TaggedLineSegment> newSeg = flatten(i, j); #if GEOS_DEBUG std::cerr << "isValidToSimplify, adding seg " << newSeg->p0 << ", " << newSeg->p1 << " to TaggedLineSegment["<<line<<"] result " << std::endl; #endif line->addToResult(newSeg); return; } simplifySection(i, furthestPtIndex, depth); simplifySection(furthestPtIndex, j, depth); }