-
Notifications
You must be signed in to change notification settings - Fork 74
v0.2.52..v0.2.53 changeset ScriptMatchCreator.cpp
Garret Voltz edited this page Feb 12, 2020
·
1 revision
diff --git a/hoot-js/src/main/cpp/hoot/js/conflate/matching/ScriptMatchCreator.cpp b/hoot-js/src/main/cpp/hoot/js/conflate/matching/ScriptMatchCreator.cpp
index 1af7de2..2ba58b4 100644
--- a/hoot-js/src/main/cpp/hoot/js/conflate/matching/ScriptMatchCreator.cpp
+++ b/hoot-js/src/main/cpp/hoot/js/conflate/matching/ScriptMatchCreator.cpp
@@ -22,7 +22,7 @@
* This will properly maintain the copyright information. DigitalGlobe
* copyrights will be updated automatically.
*
- * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
*/
#include "ScriptMatchCreator.h"
@@ -30,7 +30,6 @@
#include <hoot/core/conflate/matching/MatchThreshold.h>
#include <hoot/core/conflate/matching/MatchType.h>
#include <hoot/core/criterion/ArbitraryCriterion.h>
-#include <hoot/core/criterion/ChainCriterion.h>
#include <hoot/core/criterion/StatusCriterion.h>
#include <hoot/core/index/OsmMapIndex.h>
#include <hoot/core/schema/OsmSchema.h>
@@ -39,15 +38,19 @@
#include <hoot/core/util/Factory.h>
#include <hoot/core/util/StringUtils.h>
#include <hoot/core/visitors/ElementConstOsmMapVisitor.h>
-#include <hoot/core/visitors/IndexElementsVisitor.h>
-
+#include <hoot/core/visitors/SpatialIndexer.h>
+#include <hoot/core/criterion/PolygonCriterion.h>
+#include <hoot/core/criterion/NonConflatableCriterion.h>
+#include <hoot/core/criterion/PointCriterion.h>
#include <hoot/js/conflate/matching/ScriptMatch.h>
#include <hoot/js/elements/OsmMapJs.h>
#include <hoot/js/elements/ElementJs.h>
+#include <hoot/core/criterion/ChainCriterion.h>
// Qt
#include <QFileInfo>
#include <qnumeric.h>
+#include <QStringBuilder>
#include <QElapsedTimer>
// Standard
@@ -69,6 +72,8 @@ namespace hoot
HOOT_FACTORY_REGISTER(MatchCreator, ScriptMatchCreator)
+const QString ScriptMatchCreator::POINT_POLYGON_SCRIPT_NAME = "PointPolygon.js";
+
/**
* Searches the specified map for any match potentials.
*/
@@ -79,7 +84,7 @@ public:
ScriptMatchVisitor(const ConstOsmMapPtr& map, vector<ConstMatchPtr>& result,
ConstMatchThresholdPtr mt, std::shared_ptr<PluginContext> script,
- ElementCriterionPtr filter = ElementCriterionPtr()) :
+ ElementCriterionPtr filter = ElementCriterionPtr()) :
_map(map),
_result(result),
_mt(mt),
@@ -95,16 +100,36 @@ public:
_numMatchCandidatesVisited = 0;
_taskStatusUpdateInterval = ConfigOptions().getTaskStatusUpdateInterval();
+ // Calls to script functions/var are expensive, both memory-wise and processing-wise. Since this
+ // constructor gets called repeatedly by createMatch, keep them out of this constructor.
+
+ // Point/Polygon is not meant to conflate any polygons that are conflatable by other conflation
+ // routines, hence the use of NonConflatableCriterion.
+ _pointPolyCrit.reset(
+ new ChainCriterion(
+ ElementCriterionPtr(new PolygonCriterion()),
+ ElementCriterionPtr(new NonConflatableCriterion(map))));
+ }
+
+ ~ScriptMatchVisitor()
+ {
+ }
+
+ void initSearchRadiusInfo()
+ {
+ LOG_DEBUG("Initializing search radius info...");
+
Isolate* current = v8::Isolate::GetCurrent();
HandleScope handleScope(current);
Context::Scope context_scope(_script->getContext(current));
Handle<Object> plugin = getPlugin();
+
_candidateDistanceSigma = getNumber(plugin, "candidateDistanceSigma", 0.0, 1.0);
//this is meant to have been set externally in a js rules file
_customSearchRadius =
getNumber(plugin, "searchRadius", -1.0, ConfigOptions().getCircularErrorDefaultValue());
- LOG_VART(_customSearchRadius);
+ LOG_VARD(_customSearchRadius);
Handle<Value> value = plugin->Get(toV8("getSearchRadius"));
if (value->IsUndefined())
@@ -121,10 +146,6 @@ public:
}
}
- ~ScriptMatchVisitor()
- {
- }
-
virtual QString getDescription() const { return ""; }
void checkForMatch(const std::shared_ptr<const Element>& e)
@@ -135,29 +156,58 @@ public:
Persistent<Object> plugin(current, getPlugin(_script));
Local<Object> mapJs(ToLocal(&_mapJs));
+ LOG_VART(e->getElementId());
+
ConstOsmMapPtr map = getMap();
- // create an envlope around the e plus the search radius.
+ // create an envelope around the e plus the search radius.
std::shared_ptr<Envelope> env(e->getEnvelope(map));
- LOG_VART(env);
Meters searchRadius = getSearchRadius(e);
+ LOG_VART(searchRadius);
env->expandBy(searchRadius);
+ LOG_VART(env);
// find other nearby candidates
- set<ElementId> neighbors =
- IndexElementsVisitor::findNeighbors(*env, getIndex(), _indexToEid, getMap());
+ LOG_TRACE(
+ "Finding neighbors for: " << e->getElementId() << " during conflation: " << _scriptPath <<
+ "...");
+ const set<ElementId> neighbors =
+ SpatialIndexer::findNeighbors(*env, getIndex(), _indexToEid, map);
+ LOG_VART(neighbors);
ElementId from = e->getElementId();
_elementsEvaluated++;
+ const bool isPointPolyConflation =
+ _scriptPath.contains(ScriptMatchCreator::POINT_POLYGON_SCRIPT_NAME);
for (set<ElementId>::const_iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
ConstElementPtr e2 = map->getElement(*it);
- LOG_VART(e2.get());
- if (isCorrectOrder(e, e2) && isMatchCandidate(e2))
+ LOG_VART(e2->getElementId());
+
+ // isCorrectOrder and isMatchCandidate don't apply to Point/Polygon, so we add a different
+ // workflow for it here. All other generic scripts use isMatchCandidate to identify both
+ // what to index and what to match and that doesn't work for Point/Polygon matching two
+ // different geometries. See related note in getIndex about Point/Polygon.
+
+ bool attemptToMatch = false;
+ if (!isPointPolyConflation)
+ {
+ LOG_VART(isCorrectOrder(e, e2));
+ LOG_VART(isMatchCandidate(e2));
+ attemptToMatch = isCorrectOrder(e, e2) && isMatchCandidate(e2);
+ }
+ else
+ {
+ attemptToMatch = _pointPolyCrit->isSatisfied(e2);
+ }
+ LOG_VART(attemptToMatch);
+
+ if (attemptToMatch)
{
// score each candidate and push it on the result vector
- std::shared_ptr<ScriptMatch> m(new ScriptMatch(_script, plugin, map, mapJs, from, *it, _mt));
+ std::shared_ptr<ScriptMatch> m(
+ new ScriptMatch(_script, plugin, map, mapJs, from, *it, _mt));
// if we're confident this is a miss
if (m->getType() != MatchType::Miss)
{
@@ -233,11 +283,13 @@ public:
if (_customSearchRadius < 0)
{
//base the radius off of the element itself
+ LOG_TRACE("Calculating search radius based off of element...");
result = e->getCircularError() * _candidateDistanceSigma;
}
else
{
//base the radius off some predefined radius
+ LOG_TRACE("Calculating search radius based off of custom defined script value...");
result = _customSearchRadius * _candidateDistanceSigma;
}
}
@@ -245,10 +297,13 @@ public:
{
if (_searchRadiusCache.contains(e->getElementId()))
{
+ LOG_TRACE("Retrieving search radius from cache...");
result = _searchRadiusCache[e->getElementId()];
}
else
{
+ LOG_TRACE("Calling getSearchRadius function for: " << _scriptPath << "...");
+
Isolate* current = v8::Isolate::GetCurrent();
HandleScope handleScope(current);
Context::Scope context_scope(_script->getContext(current));
@@ -258,7 +313,6 @@ public:
int argc = 0;
jsArgs[argc++] = ElementJs::New(e);
- LOG_TRACE("Calling getSearchRadius...");
Handle<Value> f = ToLocal(&_getSearchRadius)->Call(getPlugin(), argc, jsArgs);
result = toCpp<Meters>(f) * _candidateDistanceSigma;
@@ -267,14 +321,15 @@ public:
}
}
+ LOG_VART(result);
return result;
}
void calculateSearchRadius()
{
- /*
- * This is meant to run one time when the match creator is initialized.
- */
+ // This is meant to run one time when the match creator is initialized.
+
+ LOG_DEBUG("Checking for existence of search radius export for: " << _scriptPath << "...");
Isolate* current = v8::Isolate::GetCurrent();
HandleScope handleScope(current);
@@ -295,7 +350,7 @@ public:
return;
}
- LOG_DEBUG("Calculating search radius for: " << _scriptPath << "...");
+ LOG_STATUS("Calculating search radius for: " << _scriptPath << "...");
Handle<Function> func = Handle<Function>::Cast(value);
Handle<Value> jsArgs[1];
@@ -327,33 +382,69 @@ public:
{
if (!_index)
{
+ LOG_INFO("Creating script feature index for: " << _scriptPath << "...");
+
// No tuning was done, I just copied these settings from OsmMapIndex.
// 10 children - 368 - see #3054
std::shared_ptr<MemoryPageStore> mps(new MemoryPageStore(728));
_index.reset(new HilbertRTree(mps, 2));
- // Only index elements that satisfy the isMatchCandidate
- // previously we only indexed Unknown2, but that causes issues when wanting to conflate
- // from n datasets and support intradataset conflation. This approach over-indexes a bit and
- // will likely slow things down, but should give the same results.
- // An option in the future would be to support an "isIndexedFeature" or similar function
- // to speed the operation back up again.
- std::function<bool (ConstElementPtr)> f =
- std::bind(&ScriptMatchVisitor::isMatchCandidate, this, placeholders::_1);
- std::shared_ptr<ArbitraryCriterion> pC(new ArbitraryCriterion(f));
+ // Only index elements that satisfy the isMatchCandidate. Previously we only indexed Unknown2,
+ // but that causes issues when wanting to conflate from n datasets and support intra-dataset
+ // conflation. This approach over-indexes a bit and will likely slow things down, but should
+ // give the same results. An option in the future would be to support an "isIndexedFeature" or
+ // similar function to speed the operation back up again.
- // Instantiate our visitor
- IndexElementsVisitor v(_index,
- _indexToEid,
- pC,
- std::bind(&ScriptMatchVisitor::getSearchRadius, this, placeholders::_1),
- getMap());
+ // Point/Polygon conflation behaves diferently than all other generic scripts in that it
+ // conflates geometries of different types. This class wasn't really originally designed to
+ // handle that, so we add a logic path here to accommodate Point/Polygon.
+ if (!_scriptPath.contains(ScriptMatchCreator::POINT_POLYGON_SCRIPT_NAME))
+ {
+ std::function<bool (ConstElementPtr)> f =
+ std::bind(&ScriptMatchVisitor::isMatchCandidate, this, placeholders::_1);
+ std::shared_ptr<ArbitraryCriterion> pC(new ArbitraryCriterion(f));
+
+ SpatialIndexer v(_index,
+ _indexToEid,
+ pC,
+ std::bind(&ScriptMatchVisitor::getSearchRadius, this, placeholders::_1),
+ getMap());
+ switch (_scriptInfo.geometryType)
+ {
+ case GeometryTypeCriterion::GeometryType::Point:
+ getMap()->visitNodesRo(v);
+ break;
+ case GeometryTypeCriterion::GeometryType::Line:
+ getMap()->visitWaysRo(v);
+ getMap()->visitRelationsRo(v);
+ break;
+ case GeometryTypeCriterion::GeometryType::Polygon:
+ getMap()->visitWaysRo(v);
+ getMap()->visitRelationsRo(v);
+ break;
+ default:
+ // visit all geometry types if the script didn't identify its geometry
+ getMap()->visitRo(v);
+ break;
+ }
+ v.finalizeIndex();
+ }
+ else
+ {
+ // Point/Polygon identifies points as match candidates, so we just index all polygons here.
+ SpatialIndexer v(_index,
+ _indexToEid,
+ _pointPolyCrit,
+ std::bind(&ScriptMatchVisitor::getSearchRadius, this, placeholders::_1),
+ getMap());
+ getMap()->visitWaysRo(v);
+ getMap()->visitRelationsRo(v);
+ v.finalizeIndex();
+ }
+ LOG_VART(_indexToEid.size());
- // Do the visiting
- getMap()->visitRo(v);
- v.finalizeIndex();
+ LOG_DEBUG("Script feature index created for: " << _scriptPath << ".");
}
-
return _index;
}
@@ -377,6 +468,11 @@ public:
*/
bool isCorrectOrder(const ConstElementPtr& e1, const ConstElementPtr& e2)
{
+ LOG_VART(e1->getStatus().getEnum());
+ LOG_VART(e2->getStatus().getEnum());
+ LOG_VART(e1->getElementId());
+ LOG_VART(e2->getElementId());
+
if (e1->getStatus().getEnum() == e2->getStatus().getEnum())
{
return e1->getElementId() < e2->getElementId();
@@ -459,10 +555,10 @@ public:
Handle<Value> f = func->Call(ToLocal(&plugin), argc, jsArgs);
result = f->BooleanValue();
- LOG_VART(result);
//}
_matchCandidateCache[e->getElementId()] = result;
+
return result;
}
@@ -496,8 +592,16 @@ public:
Meters getCustomSearchRadius() const { return _customSearchRadius; }
void setCustomSearchRadius(Meters searchRadius) { _customSearchRadius = searchRadius; }
+ double getCandidateDistanceSigma() const { return _candidateDistanceSigma; }
+ void setCandidateDistanceSigma(double sigma) { _candidateDistanceSigma = sigma; }
+
+ CreatorDescription getCreatorDescription() const { return _scriptInfo; }
+ void setCreatorDescription(const CreatorDescription& description) { _scriptInfo = description; }
+
long getNumMatchCandidatesFound() const { return _numMatchCandidatesVisited; }
+ bool hasCustomSearchRadiusFunction() const { return !_getSearchRadius.IsEmpty(); }
+
private:
// don't hold on to the map.
@@ -512,12 +616,13 @@ private:
size_t _maxGroupSize;
ConstMatchThresholdPtr _mt;
std::shared_ptr<PluginContext> _script;
+ CreatorDescription _scriptInfo;
ElementCriterionPtr _filter;
Persistent<Function> _getSearchRadius;
QHash<ElementId, bool> _matchCandidateCache;
QHash<ElementId, double> _searchRadiusCache;
- QMap<QString, ElementCriterionPtr> _matchCandidateCriterionCache;
+ //QMap<QString, ElementCriterionPtr> _matchCandidateCriterionCache;
// Used for finding neighbors
std::shared_ptr<HilbertRTree> _index;
@@ -532,6 +637,8 @@ private:
long _numElementsVisited;
long _numMatchCandidatesVisited;
int _taskStatusUpdateInterval;
+
+ std::shared_ptr<ChainCriterion> _pointPolyCrit;
};
ScriptMatchCreator::ScriptMatchCreator()
@@ -543,6 +650,11 @@ ScriptMatchCreator::~ScriptMatchCreator()
{
}
+void ScriptMatchCreator::init(const ConstOsmMapPtr& map)
+{
+ _getCachedVisitor(map)->initSearchRadiusInfo();
+}
+
Meters ScriptMatchCreator::calculateSearchRadius(const ConstOsmMapPtr& map,
const ConstElementPtr& e)
{
@@ -566,13 +678,57 @@ void ScriptMatchCreator::setArguments(QStringList args)
_description = QString::fromStdString(className()) + "," + args[0];
_cachedScriptVisitor.reset();
- QFileInfo scriptFileInfo(_scriptPath);
- LOG_DEBUG("Set arguments for: " << className() << " - rules: " << scriptFileInfo.fileName());
+ LOG_DEBUG(
+ "Set arguments for: " << className() << " - rules: " << QFileInfo(_scriptPath).fileName());
}
-MatchPtr ScriptMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId eid1, ElementId eid2)
+MatchPtr ScriptMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId eid1,
+ ElementId eid2)
{
- if (isMatchCandidate(map->getElement(eid1), map) && isMatchCandidate(map->getElement(eid2), map))
+ LOG_VART(eid1);
+ LOG_VART(eid2);
+
+ // There may be some benefit at some point in caching matches calculated in ScriptMatchVisitor and
+ // accessing that cached information here to avoid extra calls into the JS match script. So far,
+ // haven't seen any performance improvement after adding match caching.
+
+ const bool isPointPolyConflation = _scriptPath.contains(POINT_POLYGON_SCRIPT_NAME);
+ LOG_VART(isPointPolyConflation);
+ bool attemptToMatch = false;
+ ConstElementPtr e1 = map->getElement(eid1);
+ ConstElementPtr e2 = map->getElement(eid2);
+ if (e1 && e2)
+ {
+ if (!isPointPolyConflation)
+ {
+ attemptToMatch = isMatchCandidate(e1, map) && isMatchCandidate(e2, map);
+ }
+ else
+ {
+ if (!_pointPolyPolyCrit)
+ {
+ _pointPolyPolyCrit.reset(
+ new ChainCriterion(
+ ElementCriterionPtr(new PolygonCriterion()),
+ ElementCriterionPtr(new NonConflatableCriterion(map))));
+ }
+ if (!_pointPolyPointCrit)
+ {
+ _pointPolyPointCrit.reset(
+ new ChainCriterion(
+ ElementCriterionPtr(new PointCriterion(map)),
+ ElementCriterionPtr(new NonConflatableCriterion(map))));
+ }
+
+ // see related note in ScriptMatchVisitor::checkForMatch
+ attemptToMatch =
+ (_pointPolyPointCrit->isSatisfied(e1) && _pointPolyPolyCrit->isSatisfied(e2)) ||
+ (_pointPolyPolyCrit->isSatisfied(e1) && _pointPolyPointCrit->isSatisfied(e2));
+ }
+ }
+ LOG_VART(attemptToMatch);
+
+ if (attemptToMatch)
{
Isolate* current = v8::Isolate::GetCurrent();
HandleScope handleScope(current);
@@ -583,38 +739,89 @@ MatchPtr ScriptMatchCreator::createMatch(const ConstOsmMapPtr& map, ElementId ei
return MatchPtr(new ScriptMatch(_script, plugin, map, mapJs, eid1, eid2, getMatchThreshold()));
}
+
return MatchPtr();
}
-void ScriptMatchCreator::createMatches(const ConstOsmMapPtr& map, std::vector<ConstMatchPtr>& matches,
- ConstMatchThresholdPtr threshold)
+void ScriptMatchCreator::createMatches(
+ const ConstOsmMapPtr& map, std::vector<ConstMatchPtr>& matches, ConstMatchThresholdPtr threshold)
{
if (!_script)
{
throw IllegalArgumentException("The script must be set on the ScriptMatchCreator.");
}
- const CreatorDescription scriptInfo = _getScriptDescription(_scriptPath);
+ QElapsedTimer timer;
+ timer.start();
ScriptMatchVisitor v(map, matches, threshold, _script, _filter);
v.setScriptPath(_scriptPath);
+ const CreatorDescription scriptInfo = _getScriptDescription(_scriptPath);
+ _descriptionCache[_scriptPath] = scriptInfo;
+ v.setCreatorDescription(scriptInfo);
+ v.initSearchRadiusInfo();
v.calculateSearchRadius();
- _cachedCustomSearchRadii[_scriptPath] = v.getCustomSearchRadius();
- LOG_VART(_scriptPath);
- LOG_VART(_cachedCustomSearchRadii[_scriptPath]);
QFileInfo scriptFileInfo(_scriptPath);
-
- QElapsedTimer timer;
- timer.start();
- LOG_INFO(
- "Looking for matches with: " << className() << ";" << scriptFileInfo.fileName() << "...");
+ // This doesn't work with _candidateDistanceSigma, but right now its set to 1.0 in every script
+ // and has no effect on the search radius.
+ QString searchRadiusStr;
+ const double searchRadius = v.getCustomSearchRadius();
+ if (v.hasCustomSearchRadiusFunction())
+ {
+ searchRadiusStr = "within a function calculated search radius";
+ }
+ else if (searchRadius < 0)
+ {
+ searchRadiusStr = "within a feature dependent search radius";
+ }
+ else
+ {
+ searchRadiusStr =
+ "within a search radius of " + QString::number(searchRadius, 'g', 2) + " meters";
+ }
+ LOG_STATUS(
+ "Looking for matches with: " << className() << ";" << scriptFileInfo.fileName() << " " <<
+ searchRadiusStr << "...");
LOG_VARD(*threshold);
- map->visitRo(v);
- LOG_INFO(
+ const int matchesSizeBefore = matches.size();
+
+ _cachedCustomSearchRadii[_scriptPath] = searchRadius;
+ _candidateDistanceSigmaCache[_scriptPath] = v.getCandidateDistanceSigma();
+
+ LOG_VARD(GeometryTypeCriterion::typeToString(scriptInfo.geometryType));
+ switch (scriptInfo.geometryType)
+ {
+ case GeometryTypeCriterion::GeometryType::Point:
+ map->visitNodesRo(v);
+ break;
+ case GeometryTypeCriterion::GeometryType::Line:
+ map->visitWaysRo(v);
+ map->visitRelationsRo(v);
+ break;
+ case GeometryTypeCriterion::GeometryType::Polygon:
+ map->visitWaysRo(v);
+ map->visitRelationsRo(v);
+ break;
+ default:
+ // visit all geometry types if the script didn't identify its geometry
+ map->visitRo(v);
+ break;
+ }
+ const int matchesSizeAfter = matches.size();
+
+ QString matchType = CreatorDescription::baseFeatureTypeToString(scriptInfo.baseFeatureType);
+ // Workaround for the Point/Polygon script since it doesn't identify a base feature type. See
+ // note in ScriptMatchVisitor::getIndex and rules/PointPolygon.js.
+ if (_scriptPath.contains(POINT_POLYGON_SCRIPT_NAME))
+ {
+ matchType = "PointPolygon";
+ }
+ LOG_STATUS(
"Found " << StringUtils::formatLargeNumber(v.getNumMatchCandidatesFound()) << " " <<
- CreatorDescription::baseFeatureTypeToString(scriptInfo.baseFeatureType) <<
- " match candidates in: " << StringUtils::millisecondsToDhms(timer.elapsed()) << ".");
+ matchType << " match candidates and " <<
+ StringUtils::formatLargeNumber(matchesSizeAfter - matchesSizeBefore) <<
+ " total matches in: " << StringUtils::millisecondsToDhms(timer.elapsed()) << ".");
}
vector<CreatorDescription> ScriptMatchCreator::getAllCreators() const
@@ -665,12 +872,28 @@ std::shared_ptr<ScriptMatchVisitor> ScriptMatchCreator::_getCachedVisitor(
LOG_VART(scriptPath);
QFileInfo scriptFileInfo(_scriptPath);
- LOG_TRACE("Resetting the match candidate checker " << scriptFileInfo.fileName() << "...");
+ LOG_TRACE("Resetting the match candidate checker: " << scriptFileInfo.fileName() << "...");
vector<ConstMatchPtr> emptyMatches;
_cachedScriptVisitor.reset(
new ScriptMatchVisitor(map, emptyMatches, ConstMatchThresholdPtr(), _script, _filter));
+
_cachedScriptVisitor->setScriptPath(scriptPath);
+
+ // setting these cached values on the visitor here for performance reasons; this could all be
+ // consolidated and cleaned up
+ LOG_VART(_descriptionCache.contains(scriptPath));
+ if (_descriptionCache.contains(scriptPath))
+ {
+ _cachedScriptVisitor->setCreatorDescription(_descriptionCache[scriptPath]);
+ }
+
+ LOG_VART(_candidateDistanceSigmaCache.contains(scriptPath));
+ if (_candidateDistanceSigmaCache.contains(scriptPath))
+ {
+ _cachedScriptVisitor->setCandidateDistanceSigma(_candidateDistanceSigmaCache[scriptPath]);
+ }
+
//If the search radius has already been calculated for this matcher once, we don't want to do
//it again due to the expense.
LOG_VART(_cachedCustomSearchRadii.contains(scriptPath));
@@ -690,6 +913,8 @@ std::shared_ptr<ScriptMatchVisitor> ScriptMatchCreator::_getCachedVisitor(
CreatorDescription ScriptMatchCreator::_getScriptDescription(QString path) const
{
+ LOG_DEBUG("Getting script description...");
+
CreatorDescription result;
result.experimental = true;
@@ -718,6 +943,12 @@ CreatorDescription ScriptMatchCreator::_getScriptDescription(QString path) const
Handle<Value> value = ToLocal(&plugin)->Get(featureTypeStr);
result.baseFeatureType = CreatorDescription::stringToBaseFeatureType(toCpp<QString>(value));
}
+ Handle<String> geometryTypeStr = String::NewFromUtf8(current, "geometryType");
+ if (ToLocal(&plugin)->Has(geometryTypeStr))
+ {
+ Handle<Value> value = ToLocal(&plugin)->Get(geometryTypeStr);
+ result.geometryType = GeometryTypeCriterion::typeFromString(toCpp<QString>(value));
+ }
QFileInfo fi(path);
result.className = (QString::fromStdString(className()) + "," + fi.fileName()).toStdString();
@@ -774,4 +1005,10 @@ std::shared_ptr<MatchThreshold> ScriptMatchCreator::getMatchThreshold()
return _matchThreshold;
}
+QString ScriptMatchCreator::getName() const
+{
+ QFileInfo scriptFileInfo(_scriptPath);
+ return QString::fromStdString(className()) + ";" + scriptFileInfo.fileName();
+}
+
}