Skip to content

v0.2.53..v0.2.54 changeset Area.js

Garret Voltz edited this page Mar 31, 2020 · 1 revision
diff --git a/rules/Area.js b/rules/Area.js
index d0e7247..9c39112 100644
--- a/rules/Area.js
+++ b/rules/Area.js
@@ -13,12 +13,19 @@ exports.matchThreshold = parseFloat(hoot.get("conflate.match.threshold.default")
 exports.missThreshold = parseFloat(hoot.get("conflate.miss.threshold.default"));
 exports.reviewThreshold = parseFloat(hoot.get("conflate.review.threshold.default"));
 exports.searchRadius = parseFloat(hoot.get("search.radius.area"));
+exports.tagThreshold = parseFloat(hoot.get("area.tag.threshold"));
 exports.experimental = true;
 exports.baseFeatureType = "Area";
 exports.writeMatchedBy = hoot.get("writer.include.matched.by.tag");
 exports.geometryType = "polygon";
+exports.matchCandidateCriterion = "hoot::AreaCriterion";
 
 var sublineMatcher = new hoot.MaximalSublineStringMatcher();
+var smallerOverlapExtractor = new hoot.SmallerOverlapExtractor();
+var overlapExtractor = new hoot.OverlapExtractor();
+var bufferedOverlapExtractor = new hoot.BufferedOverlapExtractor();
+var edgeDistanceExtractor = new hoot.EdgeDistanceExtractor();
+var angleHistogramExtractor = new hoot.AngleHistogramExtractor();
 
 /*
 This matches areas to areas (area=yes), where an area is a non-building polygon.  
@@ -37,7 +44,7 @@ nodes and polygons or a school polygon which encloses school buildings on the ca
  */
 exports.isMatchCandidate = function(map, e)
 {
-  return isArea(map, e) && !isBuilding(map, e);
+  return isNonBuildingArea(map, e);
 };
 
 /**
@@ -71,46 +78,95 @@ exports.matchScore = function(map, e1, e2)
     return result;
   }
 
-  // Do we need to be looking at tags too, since area is such a broad concept?
+  hoot.trace("e1: " + e1.getId() + ", " + e1.getTags().get("name"));
+  if (e1.getTags().get("note"))
+  {
+    hoot.trace("e1 note: " + e1.getTags().get("note"));
+  }
+  hoot.trace("e2: " + e2.getId() + ", " + e2.getTags().get("name"));
+  if (e2.getTags().get("note"))
+  {
+    hoot.trace("e2 note: " + e2.getTags().get("note"));
+  }
 
-  var smallerOverlap = new hoot.SmallerOverlapExtractor().extract(map, e1, e2);
-  var overlap = new hoot.OverlapExtractor().extract(map, e1, e2);
-  var bufferedOverlap = new hoot.BufferedOverlapExtractor().extract(map, e1, e2);
-  var edgeDist = new hoot.EdgeDistanceExtractor().extract(map, e1, e2);
-  var angleHist = new hoot.AngleHistogramExtractor().extract(map, e1, e2);
+  // The geometry matching model was derived against only one dataset using Weka, so likely needs 
+  // more refinement. The tag matching was derived manually after the fact outside of Weka and is 
+  // the same that is used with Generic Conflation. The original geometry matching model from Weka 
+  // has been updated to account for the fact that buffered overlap, edge distance, and overlap 
+  // are processing intensive (roughly in order from most to least). You can see the original 
+  // geometry matching model by looking at the revision history for this file.
 
-  // This geometry matching model was derived against only one dataset using Weka, so may need more refinement.
+  // TODO: Should we do anything with names?
 
-  if (bufferedOverlap < 0.57)
+  // If both features have types and they aren't just generic types, let's do a detailed type comparison and 
+  // look for an explicit type mismatch. Otherwise, move on to the geometry comparison.
+  var typeScorePassesThreshold = !explicitTypeMismatch(e1, e2, exports.tagThreshold);
+  hoot.trace("typeScorePassesThreshold: " + typeScorePassesThreshold);
+  if (!typeScorePassesThreshold)
   {
-    if (overlap >= 0.18 && edgeDist >= 0.99)
+    return result;
+  }
+  
+  var angleHist = angleHistogramExtractor.extract(map, e1, e2);
+  var edgeDist;
+  var bufferedOverlap;
+  var smallerOverlap;
+  var overlap;
+
+  if (angleHist >= 0.98 || angleHist < 0.4)
+  {
+    edgeDist = edgeDistanceExtractor.extract(map, e1, e2);
+    if (edgeDist < 0.97)
     {
-      result = { match: 1.0, miss: 0.0, review: 0.0 };
+      bufferedOverlap = bufferedOverlapExtractor.extract(map, e1, e2);
+      if (bufferedOverlap >= 0.57)
+      {
+        result = { match: 1.0, miss: 0.0, review: 0.0 };
+        return result;
+      }
     }
   }
-  else
+  else if (angleHist >= 0.4)
   {
-    if (edgeDist < 0.97)
+    smallerOverlap = smallerOverlapExtractor.extract(map, e1, e2);
+    if (smallerOverlap < 0.89)
     {
-      if (angleHist < 0.98)
+      edgeDist = edgeDistanceExtractor.extract(map, e1, e2);
+      if (edgeDist < 0.97)
       {
-        if (angleHist < 0.4)
-        {
-          result = { match: 1.0, miss: 0.0, review: 0.0 };
-        }
-        else if (smallerOverlap < 0.89)
+        bufferedOverlap = bufferedOverlapExtractor.extract(map, e1, e2);
+        if (bufferedOverlap >= 0.57)
         {
           result = { match: 1.0, miss: 0.0, review: 0.0 };
+          return result;
         }
       }
-      else
+    }
+  }
+
+  overlap = overlapExtractor.extract(map, e1, e2);
+  if (overlap >= 0.18)
+  {
+    edgeDist = edgeDistanceExtractor.extract(map, e1, e2);
+    if (edgeDist >= 0.99)
+    {
+      bufferedOverlap = bufferedOverlapExtractor.extract(map, e1, e2);
+      if (bufferedOverlap < 0.57)
       {
         result = { match: 1.0, miss: 0.0, review: 0.0 };
+        return result;
       }
     }
-    else
+  }
+
+  edgeDist = edgeDistanceExtractor.extract(map, e1, e2);
+  if (edgeDist >= 0.97)
+  {
+    bufferedOverlap = bufferedOverlapExtractor.extract(map, e1, e2);
+    if (bufferedOverlap >= 0.57)
     {
       result = { match: 1.0, miss: 0.0, review: 0.0 };
+      return result;
     }
   }
 
Clone this wiki locally