void RemoveDuplicateReviewsOp::apply(shared_ptr<OsmMap>& map)
{
    _map = map;

    // go through all the relations to get duplicate reviews
    const RelationMap& relations = map->getRelationMap();
    QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> > membersToReview;
    for (RelationMap::const_iterator it = relations.begin(); it != relations.end(); it++)
    {
        ElementId eid = ElementId::relation(it->first);
        if (ReviewMarker::isReviewUid(map, eid))
        {
            membersToReview[ReviewMarker::getReviewElements(map, eid)].append(eid);
        }
    }

    //loop through dupplicate reviews
    QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> >::iterator it = membersToReview.begin();
    while (it != membersToReview.end())
    {
        set<ElementId> eids = it.key();

        //remove duplicate reviews
        QList<ReviewMarker::ReviewUid> duplicateReviews = it.value();

        //Only remove reviews and process if there is more than one review
        // See discussion here: https://github.com/ngageoint/hootenanny/issues/81#issuecomment-162980656
        if (eids.size() == 2 && duplicateReviews.size() > 1)
        {
            for (int i = 0; i < duplicateReviews.size(); i++)
            {
                ReviewMarker::removeElement(map, duplicateReviews[i]);
            }

            ElementId beid = *eids.begin();
            ElementId eeid = *eids.rbegin();

            OsmMapPtr copy(new OsmMap());
            CopySubsetOp(map, beid, eeid).apply(copy);
            copy->getElement(beid)->setStatus(Status::Unknown1);
            copy->getElement(eeid)->setStatus(Status::Unknown2);

            Match* match = MatchFactory::getInstance().createMatch(copy, beid, eeid);
            if (match && match->getType() != MatchType::Miss)
            {
                QString explain = match->explain();
                if (match->getType() == MatchType::Match)
                {
                    if (explain.isEmpty())
                    {
                        explain = "Multiple overlapping high confidence reviews";
                    }
                    else
                    {
                        explain = "Multiple overlapping high confidence reviews: " + explain;
                    }
                }
                ReviewMarker::mark(map, map->getElement(beid), map->getElement(eeid),
                                   explain, match->getMatchName(), match->getClassification().getReviewP());
            }
        }
        ++it;
    }
}
Beispiel #2
0
bool ScriptMatch::isConflicting(const Match& other, const ConstOsmMapPtr& map) const
{
  if (_neverCausesConflict)
  {
    return false;
  }

  bool conflicting = true;

  const ScriptMatch* hm = dynamic_cast<const ScriptMatch*>(&other);
  if (hm == 0)
  {
    return true;
  }
  if (hm == this)
  {
    return false;
  }

  // See ticket #5272
  if (getClassification().getReviewP() == 1.0 || other.getClassification().getReviewP() == 1.0)
  {
    return true;
  }

  ElementId sharedEid;
  if (_eid1 == hm->_eid1 || _eid1 == hm->_eid2)
  {
    sharedEid = _eid1;
  }

  if (_eid2 == hm->_eid1 || _eid2 == hm->_eid2)
  {
    // both eids should never be the same.
    assert(sharedEid.isNull());
    sharedEid = _eid2;
  }

  // if the matches don't share at least one eid then it isn't a conflict.
  if (sharedEid.isNull())
  {
    return false;
  }

  // assign o1 and o2 to the non-shared eids
  ElementId o1 = _eid1 == sharedEid ? _eid2 : _eid1;
  ElementId o2 = hm->_eid1 == sharedEid ? hm->_eid2 : hm->_eid1;

  bool foundCache = false;
  bool cacheConflict = false;
  QHash<ConflictKey, bool>::const_iterator cit1 = _conflicts.find(hm->_getConflictKey());
  if (cit1 != _conflicts.end())
  {
    foundCache = true;
    cacheConflict = cit1.value();
  }
  QHash<ConflictKey, bool>::const_iterator cit2 = hm->_conflicts.find(_getConflictKey());
  if (cit2 != hm->_conflicts.end())
  {
    foundCache = true;
    cacheConflict = cit2.value();
  }

  if (foundCache)
  {
    conflicting = cacheConflict;
  }
  else
  {
    try
    {
      // we need to check for a conflict in two directions. Is it conflicting if we merge the shared
      // EID with this class first, then is it a conflict if we merge with the other EID first.
      if (_isOrderedConflicting(map, sharedEid, o1, o2) ||
          hm->_isOrderedConflicting(map, sharedEid, o2, o1))
      {
        conflicting = true;
      }
      else
      {
        conflicting = false;
      }
    }
    catch (const NeedsReviewException& e)
    {
      conflicting = true;
    }
    _conflicts[hm->_getConflictKey()] = conflicting;
  }

  return conflicting;
}