-
Notifications
You must be signed in to change notification settings - Fork 74
v0.2.50..v0.2.51 changeset BuildingMatchCreator.cpp
Garret Voltz edited this page Jan 15, 2020
·
1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/conflate/polygon/BuildingMatchCreator.cpp b/hoot-core/src/main/cpp/hoot/core/conflate/polygon/BuildingMatchCreator.cpp
index 546f165..23f6ef6 100644
--- a/hoot-core/src/main/cpp/hoot/core/conflate/polygon/BuildingMatchCreator.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/polygon/BuildingMatchCreator.cpp
@@ -42,6 +42,8 @@
#include <hoot/core/visitors/IndexElementsVisitor.h>
#include <hoot/core/util/StringUtils.h>
#include <hoot/core/util/CollectionUtils.h>
+#include <hoot/core/algorithms/extractors/OverlapExtractor.h>
+#include <hoot/core/schema/OsmSchema.h>
// Standard
#include <fstream>
@@ -130,7 +132,6 @@ public:
int neighborCount = 0;
std::vector<MatchPtr> tempMatches;
-
for (std::set<ElementId>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
const ElementId neighborId = *it;
@@ -150,13 +151,16 @@ public:
}
}
}
+ LOG_VART(neighborCount);
- if (ConfigOptions().getBuildingReviewMatchesOtherThanOneToOne() && neighborCount > 1)
+ if (neighborCount > 1 && ConfigOptions().getBuildingReviewMatchesOtherThanOneToOne())
{
_markNonOneToOneMatchesAsReview(tempMatches);
}
+ _adjustForOverlappingAdjoiningBuildingMatches(tempMatches);
- for (std::vector<MatchPtr>::const_iterator it = tempMatches.begin(); it != tempMatches.end(); ++it)
+ for (std::vector<MatchPtr>::const_iterator it = tempMatches.begin(); it != tempMatches.end();
+ ++it)
{
_result.push_back(*it);
}
@@ -282,7 +286,7 @@ private:
int _taskStatusUpdateInterval;
void _markNonOneToOneMatchesAsReview(std::vector<MatchPtr>& matches)
- {
+ {
for (std::vector<MatchPtr>::iterator it = matches.begin(); it != matches.end(); ++it)
{
MatchPtr match = *it;
@@ -294,6 +298,88 @@ private:
match->setExplain("Match involved in multiple building relationships.");
}
}
+
+ void _adjustForOverlappingAdjoiningBuildingMatches(std::vector<MatchPtr>& matches)
+ {
+ // If we have matches or reviews between adjoining houses (building=terrace; townhouses and
+ // the like), check for many to one relationships. From the many to one, keep only the match
+ // with the highest overlap. Convert all others to misses by removing the matches completely.
+ //
+ // The argument could be made that this overlap check could be done for all buildings, not just
+ // adjoining buildings, to reduce bad matches/reviews. Not sure how much havoc that might wreak,
+ // but maybe worth trying.
+
+ LOG_VART(matches);
+
+ QMap<ElementId, double> highestOverlapScores;
+ QMap<ElementId, MatchPtr> highestOverlapMatches;
+ const double tagScoreThreshold = ConfigOptions().getBuildingAdjoiningTagScoreThreshold();
+ bool adjoiningBuildingEncountered = false;
+
+ for (std::vector<MatchPtr>::const_iterator matchItr = matches.begin();
+ matchItr != matches.end(); ++matchItr)
+ {
+ MatchPtr match = *matchItr;
+ LOG_VART(match->getType());
+ assert(match->getType() != MatchType::Miss);
+
+ std::set<std::pair<ElementId, ElementId>> matchPairs = match->getMatchPairs();
+ LOG_VART(matchPairs.size());
+ assert(matchPairs.size() == 1);
+ std::pair<ElementId, ElementId> matchPair = *matchPairs.begin();
+
+ ConstElementPtr element1 = _map->getElement(matchPair.first);
+ ConstElementPtr element2 = _map->getElement(matchPair.second);
+
+ const QString adjoiningBuildingKvp = "building=terrace";
+ if (element1->getElementType() == ElementType::Way &&
+ element2->getElementType() == ElementType::Way &&
+ (OsmSchema::getInstance().score(adjoiningBuildingKvp, element1->getTags()) >=
+ tagScoreThreshold ||
+ OsmSchema::getInstance().score(adjoiningBuildingKvp, element2->getTags()) >=
+ tagScoreThreshold))
+ {
+ LOG_TRACE(
+ "one or both is adjoining building: " << element1->getElementId() << ", " <<
+ element2->getElementId());
+ adjoiningBuildingEncountered = true;
+
+ const double overlap = OverlapExtractor().extract(*_map, element1, element2);
+ if (!highestOverlapScores.contains(element1->getElementId()) ||
+ overlap > highestOverlapScores[element1->getElementId()])
+ {
+ highestOverlapScores[element1->getElementId()] = overlap;
+ highestOverlapMatches[element1->getElementId()] = match;
+ LOG_TRACE(
+ "Updating highest overlap score: " << overlap << " for ref: " <<
+ element1->getElementId() << ", sec: " << element2->getElementId());
+ }
+ else
+ {
+ LOG_TRACE(
+ "Dropping match with lower overlap score: " << overlap <<
+ " compared to highest overlap score: " <<
+ highestOverlapScores[element1->getElementId()] << " for ref: " <<
+ element1->getElementId() << ", sec: " << element2->getElementId());
+ }
+ }
+ }
+ highestOverlapScores.clear();
+ LOG_VART(adjoiningBuildingEncountered);
+
+ if (adjoiningBuildingEncountered)
+ {
+ std::vector<MatchPtr> modifiedMatches;
+ for (QMap<ElementId, MatchPtr>::const_iterator modifiedMatchItr = highestOverlapMatches.begin();
+ modifiedMatchItr != highestOverlapMatches.end(); ++modifiedMatchItr)
+ {
+ modifiedMatches.push_back(modifiedMatchItr.value());
+ }
+ matches = modifiedMatches;
+ }
+ highestOverlapMatches.clear();
+ LOG_VART(matches);
+ }
};
BuildingMatchCreator::BuildingMatchCreator() :
@@ -301,10 +387,10 @@ _conflateMatchBuildingModel(ConfigOptions().getConflateMatchBuildingModel())
{
}
-MatchPtr BuildingMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId eid1, ElementId eid2)
+MatchPtr BuildingMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId eid1,
+ ElementId eid2)
{
std::shared_ptr<BuildingMatch> result;
-
if (eid1.getType() != ElementType::Node && eid2.getType() != ElementType::Node)
{
ConstElementPtr e1 = map->getElement(eid1);
@@ -316,7 +402,6 @@ MatchPtr BuildingMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId
result.reset(new BuildingMatch(map, _getRf(), eid1, eid2, getMatchThreshold()));
}
}
-
return result;
}