v0.2.52..v0.2.53 changeset PoiPolygonMatch.cpp
Garret Voltz edited this page Feb 12, 2020
·
1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMatch.cpp b/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMatch.cpp
index 12246b3..0ca787d 100644
--- a/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMatch.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMatch.cpp
@@ -22,7 +22,7 @@
* This will properly maintain the copyright information. DigitalGlobe
* copyrights will be updated automatically.
*
- * @copyright Copyright (C) 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
*/
#include "PoiPolygonMatch.h"
@@ -30,8 +30,6 @@
#include <geos/util/TopologyException.h>
// hoot
-#include <hoot/core/conflate/poi-polygon/PoiPolygonAdvancedMatcher.h>
-#include <hoot/core/conflate/poi-polygon/PoiPolygonDistance.h>
#include <hoot/core/conflate/poi-polygon/PoiPolygonDistanceTruthRecorder.h>
#include <hoot/core/conflate/poi-polygon/PoiPolygonReviewReducer.h>
#include <hoot/core/algorithms/extractors/poi-polygon/PoiPolygonAlphaShapeDistanceExtractor.h>
@@ -42,6 +40,11 @@
#include <hoot/core/criterion/MultiUseBuildingCriterion.h>
#include <hoot/core/criterion/BuildingCriterion.h>
#include <hoot/core/util/StringUtils.h>
+#include <hoot/core/conflate/poi-polygon/PoiPolygonSchema.h>
+
+// Qt
+#include <QElapsedTimer>
+#include <QStringBuilder>
using namespace std;
@@ -50,7 +53,7 @@ namespace hoot
HOOT_FACTORY_REGISTER(Match, PoiPolygonMatch)
-QString PoiPolygonMatch::_matchName = "POI to Polygon";
+const QString PoiPolygonMatch::MATCH_NAME = "POI to Polygon";
std::shared_ptr<ToEnglishTranslator> PoiPolygonMatch::_translator;
long PoiPolygonMatch::matchesProcessed = 0;
@@ -81,9 +84,8 @@ Match(threshold)
PoiPolygonMatch::PoiPolygonMatch(const ConstOsmMapPtr& map, ConstMatchThresholdPtr threshold,
std::shared_ptr<const PoiPolygonRfClassifier> rf,
- PoiPolygonCachePtr infoCache,
- const set<ElementId>& polyNeighborIds,
- const set<ElementId>& poiNeighborIds) :
+ PoiPolygonInfoCachePtr infoCache,
+ const set<ElementId>& polyNeighborIds) :
Match(threshold),
_map(map),
_e1IsPoi(false),
@@ -105,8 +107,6 @@ _addressMatchEnabled(false),
_phoneNumberScore(-1.0),
_phoneNumberMatchEnabled(true),
_polyNeighborIds(polyNeighborIds),
-_poiNeighborIds(poiNeighborIds),
-_enableAdvancedMatching(false),
_enableReviewReduction(true),
_disableSameSourceConflation(false),
_disableSameSourceConflationMatchTagKeyPrefixOnly(true),
@@ -114,12 +114,12 @@ _sourceTagKey(""),
_reviewMultiUseBuildings(false),
_rf(rf),
_explainText(""),
-_infoCache(infoCache)
+_infoCache(infoCache),
+_timingThreshold(1000000) //nanoseconds
{
-// _timer.reset(new QElapsedTimer());
-// _timer->start();
-
LOG_VART(_infoCache.get());
+
+ _typeScorer.reset(new PoiPolygonTypeScoreExtractor(_infoCache));
}
void PoiPolygonMatch::setMatchDistanceThreshold(double distance)
@@ -197,7 +197,7 @@ void PoiPolygonMatch::setConfiguration(const Settings& conf)
ConfigOptions config = ConfigOptions(conf);
setMatchDistanceThreshold(config.getPoiPolygonMatchDistanceThreshold());
- setReviewDistanceThreshold(config.getPoiPolygonReviewDistanceThreshold());
+ setReviewDistanceThreshold(config.getPoiPolygonAdditionalSearchDistance());
setNameScoreThreshold(config.getPoiPolygonNameScoreThreshold());
setTypeScoreThreshold(config.getPoiPolygonTypeScoreThreshold());
@@ -209,7 +209,6 @@ void PoiPolygonMatch::setConfiguration(const Settings& conf)
setReviewMultiUseBuildings(config.getPoiPolygonReviewMultiuseBuildings());
- setEnableAdvancedMatching(config.getPoiPolygonEnableAdvancedMatching());
setEnableReviewReduction(config.getPoiPolygonEnableReviewReduction());
const int matchEvidenceThreshold = config.getPoiPolygonMatchEvidenceThreshold();
@@ -220,16 +219,31 @@ void PoiPolygonMatch::setConfiguration(const Settings& conf)
QString::number(matchEvidenceThreshold) + ". Valid values are 1 to 4.");
}
setMatchEvidenceThreshold(matchEvidenceThreshold);
- LOG_VART(_matchEvidenceThreshold);
- const int reviewEvidenceThreshold = config.getPoiPolygonReviewEvidenceThreshold();
- if (reviewEvidenceThreshold < 0 || reviewEvidenceThreshold > matchEvidenceThreshold - 1)
+ if (_matchEvidenceThreshold == 1)
+ {
+ // reviews are effectively turned off if match thresh = 1
+ _reviewEvidenceThreshold = 0;
+ }
+ else
+ {
+ const int reviewEvidenceThreshold = config.getPoiPolygonReviewEvidenceThreshold();
+ if (reviewEvidenceThreshold < 1 || reviewEvidenceThreshold > 3)
+ {
+ throw HootException(
+ "Invalid value for POI/Polygon review evidence threshold: " +
+ QString::number(reviewEvidenceThreshold) + ". Valid values are 1 to 3.");
+ }
+ setReviewEvidenceThreshold(reviewEvidenceThreshold);
+ }
+ if (_reviewEvidenceThreshold >= _matchEvidenceThreshold)
{
throw HootException(
- "Invalid value for POI/Polygon review evidence threshold: " +
- QString::number(reviewEvidenceThreshold) + ". Valid values are 0 to " +
- QString::number(matchEvidenceThreshold - 1) + ".");
+ "Value for POI/Polygon review evidence threshold: " +
+ QString::number(_reviewEvidenceThreshold) +
+ " is greater than or equal to value for POI/Polyon match evidence threshold: " +
+ QString::number(_matchEvidenceThreshold) + ".");
}
- setReviewEvidenceThreshold(reviewEvidenceThreshold);
+ LOG_VART(_matchEvidenceThreshold);
LOG_VART(_reviewEvidenceThreshold);
_addressMatchEnabled = config.getPoiPolygonAddressMatchEnabled();
@@ -237,7 +251,11 @@ void PoiPolygonMatch::setConfiguration(const Settings& conf)
{
_addressScorer.setConfiguration(conf);
}
- _typeScorer.setConfiguration(conf);
+ if (!_typeScorer)
+ {
+ _typeScorer.reset(new PoiPolygonTypeScoreExtractor(_infoCache));
+ }
+ _typeScorer->setConfiguration(conf);
_nameScorer.setConfiguration(conf);
_phoneNumberMatchEnabled = config.getPoiPolygonPhoneNumberMatchEnabled();
if (_phoneNumberMatchEnabled)
@@ -291,7 +309,7 @@ bool PoiPolygonMatch::_featureHasReviewIfMatchedType(ConstElementPtr element) co
const Tags& tags = element->getTags();
for (Tags::const_iterator it = tags.begin(); it != tags.end(); ++it)
{
- const QString kvp = it.key() + "=" + it.value();
+ const QString kvp = it.key() % "=" % it.value();
if (_reviewIfMatchedTypes.contains(kvp))
{
LOG_TRACE("Matched type for review: " << kvp);
@@ -350,8 +368,7 @@ bool PoiPolygonMatch::_inputFeaturesHaveSameSource() const
bool PoiPolygonMatch::_skipForReviewTypeDebugging() const
{
- if (!PoiPolygonTypeScoreExtractor::hasSpecificType(_poi) ||
- !PoiPolygonTypeScoreExtractor::hasSpecificType(_poly))
+ if (!PoiPolygonSchema::hasSpecificType(_poi) || !PoiPolygonSchema::hasSpecificType(_poly))
{
return true;
}
@@ -373,6 +390,7 @@ void PoiPolygonMatch::calculateMatch(const ElementId& eid1, const ElementId& eid
// const bool oneElementIsRelation =
// e1->getElementType() == ElementType::Relation ||
// e2->getElementType() == ElementType::Relation;
+ //QElapsedTimer timer;
matchesProcessed++;
_explainText = "";
_class.setMiss();
@@ -402,12 +420,23 @@ void PoiPolygonMatch::calculateMatch(const ElementId& eid1, const ElementId& eid
unsigned int evidence = _calculateEvidence(_poi, _poly);
LOG_VART(evidence);
- //no point in trying to reduce reviews if we're still at a miss here
- if (_enableReviewReduction && evidence >= _reviewEvidenceThreshold)
+ bool runReviewReduction = _enableReviewReduction;
+ if (// No point in trying to reduce reviews if we're still at a miss here. Also, if the review
+ // threshold = 0, that means we don't want any reviews at all...so no point in trying to
+ //reduce them.
+ (_reviewEvidenceThreshold > 0 && evidence < _reviewEvidenceThreshold) ||
+ // If the match threshold = 1, then we throw out all reviews and no reason to try and reduce
+ // any.
+ (_matchEvidenceThreshold == 1 && evidence < _matchEvidenceThreshold))
{
- // this constructor has gotten a little out of hand
+ runReviewReduction = false;
+ }
+ LOG_VART(runReviewReduction);
+ if (runReviewReduction)
+ {
+ // this constructor has gotten a little out of hand...
PoiPolygonReviewReducer reviewReducer(
- _map, _polyNeighborIds, _poiNeighborIds, _distance, _nameScoreThreshold, _nameScore,
+ _map, _polyNeighborIds, _distance, _nameScoreThreshold, _nameScore,
_nameScore >= _nameScoreThreshold, _nameScore == 1.0, _typeScoreThreshold, _typeScore,
_typeScore >= _typeScoreThreshold, _matchDistanceThreshold, _addressScore == 1.0,
_addressMatchEnabled, _infoCache);
@@ -416,7 +445,9 @@ void PoiPolygonMatch::calculateMatch(const ElementId& eid1, const ElementId& eid
{
evidence = 0;
// TODO: b/c this is a miss, don't think it will actually get added to the output anywhere...
- _explainText = "Match score automatically dropped by review reduction.";
+ _explainText =
+ "Match score automatically dropped by review reduction rule: " +
+ reviewReducer.getTriggeredRuleDescription();
}
numReviewReductions++;
}
@@ -445,10 +476,10 @@ void PoiPolygonMatch::calculateMatch(const ElementId& eid1, const ElementId& eid
{
_class.setReview();
_explainText =
- "Feature contains tag specified for review from list: " + _reviewIfMatchedTypes.join(";");
+ "Feature contains tag specified for review from list: " % _reviewIfMatchedTypes.join(";");
}
}
- else if (evidence >= _reviewEvidenceThreshold)
+ else if (evidence >= _reviewEvidenceThreshold && _reviewEvidenceThreshold > 0)
//&& oneElementIsRelation) //for testing only
{
_class.setReview();
@@ -494,7 +525,7 @@ void PoiPolygonMatch::calculateMatch(const ElementId& eid1, const ElementId& eid
_explainText = "";
}
- LOG_VART(_class);
+ LOG_TRACE("eid1: " << eid1 << ", eid2: " << eid2 << ", class: " << _class);
LOG_TRACE("**************************");
}
@@ -507,7 +538,7 @@ unsigned int PoiPolygonMatch::_getDistanceEvidence(ConstElementPtr poi, ConstEle
{
LOG_TRACE("Retrieving distance evidence...");
- _distance = PoiPolygonDistanceExtractor().extract(*_map, poi, poly);
+ _distance = PoiPolygonDistanceExtractor(_infoCache).extract(*_map, poi, poly);
if (_distance == -1.0)
{
_closeDistanceMatch = false;
@@ -515,14 +546,10 @@ unsigned int PoiPolygonMatch::_getDistanceEvidence(ConstElementPtr poi, ConstEle
return 0;
}
- //search radius taken from PoiPolygonMatchCreator
- PoiPolygonDistance distanceCalc(
- _matchDistanceThreshold, _reviewDistanceThreshold, poly->getTags(),
- poi->getCircularError() + _reviewDistanceThreshold);
_reviewDistanceThreshold =
max(
- distanceCalc.getReviewDistanceForType(_poi->getTags()),
- distanceCalc.getReviewDistanceForType(_poly->getTags()));
+ _infoCache->getReviewDistance(_poi, poly->getTags(), _reviewDistanceThreshold),
+ _infoCache->getReviewDistance(_poly, poly->getTags(), _reviewDistanceThreshold));
//Tried type and density based match distance changes here too, but they didn't have any positive
//effect.
@@ -578,36 +605,36 @@ unsigned int PoiPolygonMatch::_getTypeEvidence(ConstElementPtr poi, ConstElement
{
LOG_TRACE("Retrieving type evidence...");
- _typeScorer.setFeatureDistance(_distance);
- _typeScorer.setTypeScoreThreshold(_typeScoreThreshold);
- _typeScore = _typeScorer.extract(*_map, poi, poly);
+ _typeScorer->setFeatureDistance(_distance);
+ _typeScorer->setTypeScoreThreshold(_typeScoreThreshold);
+ _typeScore = _typeScorer->extract(*_map, poi, poly);
const bool typeMatch = _typeScore >= _typeScoreThreshold;
if (typeMatch)
{
typeMatches++;
}
- if (_typeScorer.getNoTypeFound())
+ if (_typeScorer->getNoTypeFound())
{
noTypeFoundCount++;
}
- if (_typeScorer.getFailedMatchRequirements().size() > 0)
+ if (_typeScorer->getFailedMatchRequirements().size() > 0)
{
QString failedMatchTypes;
- for (int i = 0; i < _typeScorer.getFailedMatchRequirements().size(); i++)
+ for (int i = 0; i < _typeScorer->getFailedMatchRequirements().size(); i++)
{
- failedMatchTypes += _typeScorer.getFailedMatchRequirements().at(i) + ", ";
+ failedMatchTypes += _typeScorer->getFailedMatchRequirements().at(i) % ", ";
}
failedMatchTypes.chop(2);
QString explainBase = "Failed custom match requirements for: ";
if (_explainText.isEmpty())
{
- _explainText = explainBase + failedMatchTypes;
+ _explainText = explainBase % failedMatchTypes;
}
else
{
- _explainText += ";" + explainBase + failedMatchTypes;
+ _explainText += ";" % explainBase % failedMatchTypes;
}
}
@@ -679,6 +706,8 @@ unsigned int PoiPolygonMatch::_calculateEvidence(ConstElementPtr poi, ConstEleme
//LOG_VART(poi);
//LOG_VART(poly);
+ //QElapsedTimer timer;
+
unsigned int evidence = 0;
evidence += _getDistanceEvidence(poi, poly);
@@ -692,13 +721,11 @@ unsigned int PoiPolygonMatch::_calculateEvidence(ConstElementPtr poi, ConstEleme
//The operations from here are on down are roughly ordered by increasing runtime complexity.
evidence += _getNameEvidence(poi, poly);
+
// Used to allow for kicking out of the method once enough evidence was accumulated for a match
// as a runtime optimization. However, that results in incomplete scoring information passed to
// the review reducer, so have since disabled. It also causes some regression tests to fail.
-// if (_reviewIfMatchedTypes.isEmpty() && evidence >= _matchEvidenceThreshold)
-// {
-// return evidence;
-// }
+
evidence += _getTypeEvidence(poi, poly);
// if (evidence >= _matchEvidenceThreshold)
// {
@@ -727,7 +754,7 @@ unsigned int PoiPolygonMatch::_calculateEvidence(ConstElementPtr poi, ConstEleme
//necessary. The school requirement definitely seems too type specific (this type of evidence
//has actually only been found with school pois in one test dataset so far), but when
//removing it scores dropped for other datasets...so not changing it for now.
- if (evidence == 0 && _distance <= 35.0 && _infoCache->isType(poi, "school") &&
+ if (evidence == 0 && _distance <= 35.0 && _infoCache->isType(poi, PoiPolygonSchemaType::School) &&
_infoCache->hasCriterion(poly, QString::fromStdString(BuildingCriterion::className())))
{
evidence += _getConvexPolyDistanceEvidence(poi, poly);
@@ -737,18 +764,6 @@ unsigned int PoiPolygonMatch::_calculateEvidence(ConstElementPtr poi, ConstEleme
// }
}
- //no point in trying to increase evidence if we're already at a match
- if (_enableAdvancedMatching && evidence < _matchEvidenceThreshold)
- {
- PoiPolygonAdvancedMatcher advancedMatcher(
- _map, _polyNeighborIds, _poiNeighborIds, _distance);
- advancedMatcher.setConfiguration(conf());
- if (advancedMatcher.triggersRule(_poi, _poly))
- {
- evidence++;
- }
- }
-
LOG_VART(evidence);
return evidence;
}