std::vector<std::shared_ptr<MultipolygonProcessor::CoordinateSequence>> MultipolygonProcessor::createRings(
    CoordinateSequences &sequences) const {
  CoordinateSequences closedRings;
  std::shared_ptr<MultipolygonProcessor::CoordinateSequence> currentRing = nullptr;
  while (!sequences.empty()) {
    if (currentRing==nullptr) {
      // start a new ring with any remaining node sequence
      auto lastIndex = sequences.size() - 1;
      currentRing = sequences[lastIndex];
      sequences.erase(sequences.begin() + lastIndex);
    } else {
      // try to continue the ring by appending a node sequence
      bool isFound = false;
      for (auto it = sequences.begin(); it!=sequences.end(); ++it) {
        if (!currentRing->tryAdd(**it)) continue;
        isFound = true;
        sequences.erase(it);
        break;
      }

      if (!isFound)
        return CoordinateSequences();
    }

    // check whether the ring under construction is closed
    if (currentRing!=nullptr && currentRing->isClosed()) {
      // TODO check that it isn't self-intersecting!
      closedRings.push_back(currentRing);
      currentRing = nullptr;
    }
  }

  return std::move(closedRings);
}
示例#2
0
void MultipolygonProcessor::fillRelation(CoordinateSequences& rings)
{
    while (!rings.empty()) {
        // find an outer ring
        std::shared_ptr<CoordinateSequence> outer = nullptr;
        for (auto candidate = rings.begin(); candidate != rings.end(); ++candidate) {
            bool containedInOtherRings = false;
            for (auto other = rings.begin(); other != rings.end(); ++other) {
                if (other != candidate && (*other)->containsRing((*candidate)->coordinates)) {
                    containedInOtherRings = true;
                    break;
                }
            }
            if (containedInOtherRings) continue;
            outer = *candidate;
            rings.erase(candidate);
            break;
        }

        // find inner rings of that ring
        CoordinateSequences inners;
        for (auto ring = rings.begin(); ring != rings.end();) {
            if (outer->containsRing((*ring)->coordinates)) {
                bool containedInOthers = false;
                for (auto other = rings.begin(); other != rings.end(); ++other) {
                    if (other != ring && (*other)->containsRing((*ring)->coordinates)) {
                        containedInOthers = true;
                        break;
                    }
                }
                if (!containedInOthers) {
                    inners.push_back(*ring);
                    ring = rings.erase(ring);
                    continue;
                }
            }
            ++ring;
        }

        // outer
        auto outerArea = std::make_shared<Area>();
        outerArea->id = outer->id;
        insertCoordinates(outer->coordinates, outerArea->coordinates, true);
        relation_.elements.push_back(outerArea);

        // inner: create a new area and remove the used rings
        for (const auto& innerRing : inners) {
            auto innerArea = std::make_shared<Area>();
            insertCoordinates(innerRing->coordinates, innerArea->coordinates, false);
            relation_.elements.push_back(innerArea);
        }
    }
}