mmd-osm / Overpass-API

Performance optimized Overpass API fork
GNU Affero General Public License v3.0
19 stars 3 forks source link

Coord_Query_Statement::check_area_block - expensive ilat/ilon conversions #5

Open mmd-osm opened 7 years ago

mmd-osm commented 7 years ago
[timeout:3600][maxsize:3000000000];
area[boundary=administrative][admin_level]["de:amtlicher_gemeindeschluessel"~"^09"]->.a;
.a out count;
( way(area.a)["addr:housenumber"];
  node(area.a)["addr:housenumber"];
);
out count;
@ubuntu:~/osm-3s-patch-version/build/bin$ /usr/bin/time -v ./o3 --db-dir=db/ < ph
encoding remark: Please enter your query and terminate it with CTRL+D.
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base=""/>

  <count>
    <tag k="nodes" v="0"/>
    <tag k="ways" v="0"/>
    <tag k="relations" v="0"/>
    <tag k="areas" v="2317"/>
    <tag k="total" v="2317"/>
  </count>
  <count>
    <tag k="nodes" v="467196"/>
    <tag k="ways" v="1017886"/>
    <tag k="relations" v="0"/>
    <tag k="areas" v="0"/>
    <tag k="total" v="1485082"/>
  </count>

</osm>
    Command being timed: "./o3 --db-dir=db/"
    User time (seconds): 204.09
    System time (seconds): 0.37
    Percent of CPU this job got: 100%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 3:24.46
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 784856
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 168840
    Voluntary context switches: 1
    Involuntary context switches: 259
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
@ubuntu:~/osm-3s-patch-version/build/bin$ /usr/bin/time -v ./osm3s_query --db-dir=db/ < ph
encoding remark: Please enter your query and terminate it with CTRL+D.
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base=""/>

  <count>
    <tag k="nodes" v="0"/>
    <tag k="ways" v="0"/>
    <tag k="relations" v="0"/>
    <tag k="areas" v="2317"/>
    <tag k="total" v="2317"/>
  </count>
  <count>
    <tag k="nodes" v="467196"/>
    <tag k="ways" v="1017886"/>
    <tag k="relations" v="0"/>
    <tag k="areas" v="0"/>
    <tag k="total" v="1485082"/>
  </count>

</osm>
    Command being timed: "./osm3s_query --db-dir=db/"
    User time (seconds): 55.80
    System time (seconds): 0.42
    Percent of CPU this job got: 100%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:56.22
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 883220
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 194466
    Voluntary context switches: 1
    Involuntary context switches: 75
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0
diff --git a/src/overpass_api/core/type_area.h b/src/overpass_api/core/type_area.h
index a57f29a..453e0a9 100644
--- a/src/overpass_api/core/type_area.h
+++ b/src/overpass_api/core/type_area.h
@@ -313,6 +313,8 @@ struct Area_Block
   Id_Type id;
   std::vector< uint64 > coors;

+  std::vector< std::pair< uint32, int32 > > ilat_ilon_pairs;
+
   Area_Block() : id(0u) {}

   Area_Block(void* data) : id(*(Id_Type*)data)
diff --git a/src/overpass_api/statements/area_query.cc b/src/overpass_api/statements/area_query.cc
index cd10022..90ca17f 100644
--- a/src/overpass_api/statements/area_query.cc
+++ b/src/overpass_api/statements/area_query.cc
@@ -35,6 +35,109 @@
 #include "recurse.h"

+
+namespace area_query {
+
+namespace detail {
+
+const static int HIT = 1;
+const static int TOGGLE_EAST = 2;
+const static int TOGGLE_WEST = 4;
+
+int check_area_block2
+(uint32 ll_index_ilat, int32 ll_index_ilon, const Area_Block& area_block,
+    uint32 coord_lat, int32 coord_lon)
+{
+  int state = 0;
+
+  auto it(area_block.ilat_ilon_pairs.begin());
+  uint32 lat = ll_index_ilat | it->first;                             // avoid ::ilat / ::ilon 
+  int32 lon = ll_index_ilon | it->second;                        // avoid ::ilat / ::ilon
+
+  while (++it != area_block.ilat_ilon_pairs.end())
+  {
+    uint32 last_lat = lat;
+    int32 last_lon = lon;
+
+    lat = ll_index_ilat | it->first;
+    lon = ll_index_ilon | it->second;
+
+    if (last_lon < lon)
+    {
+      if (lon < coord_lon)
+        continue; // case (1)
+      else if (last_lon > coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else if (last_lon > lon)
+    {
+      if (lon > coord_lon)
+        continue; // case (1)
+      else if (last_lon < coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else // last_lon == lon
+    {
+      if (lon == coord_lon &&
+          ((last_lat <= coord_lat && coord_lat <= lat) || (lat <= coord_lat && coord_lat <= last_lat)))
+        return HIT; // case (2)
+      continue; // else: case (1)
+    }
+
+    uint32 intersect_lat = lat +
+        ((int64)coord_lon - lon)*((int64)last_lat - lat)/((int64)last_lon - lon);
+    if (coord_lat > intersect_lat)
+      state ^= (TOGGLE_EAST | TOGGLE_WEST); // case (3)
+    else if (coord_lat == intersect_lat)
+      return HIT; // case (2)
+    // else: case (1)
+  }
+  return state;
+}
+
+
+}
+
+}
+
+
+
 class Area_Constraint : public Query_Constraint
 {
   public:
@@ -441,6 +544,10 @@ void Area_Query_Statement::collect_nodes

   uint32 loop_count = 0;
   uint32 current_idx(0);
+
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -459,6 +566,23 @@ void Area_Query_Statement::collect_nodes
       ++area_it;
     }

+    /* Test: Precalculate ilat/ilon pairs */
+    {
+      for (auto &it : areas)
+        for (auto& it2 : it.second)
+          for (auto coor : it2.coors)
+          {
+            uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+            int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff); 
+            it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+          }
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);   // ^ 0x40000000 is only being applies once here
+    }
+
+    /* ------------------------------ */
+
+
     while (nodes_it != nodes.end() && nodes_it->first.val() < current_idx)
     {
       nodes_it->second.clear();
@@ -475,6 +599,7 @@ void Area_Query_Statement::collect_nodes
             + 91.0)*10000000+0.5);
         int32 ilon(::lon(nodes_it->first.val(), iit->ll_lower)*10000000
             + (::lon(nodes_it->first.val(), iit->ll_lower) > 0 ? 0.5 : -0.5));
+
         for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
         it != areas.end(); ++it)
         {
@@ -484,7 +609,8 @@ void Area_Query_Statement::collect_nodes
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
+       //int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT && add_border)
        {
          inside = 1;
@@ -494,10 +620,10 @@ void Area_Query_Statement::collect_nodes
          inside ^= check;
           }
           if (inside)
-     {
-       into.push_back(*iit);
-       break;
-     }
+          {
+            into.push_back(*iit);
+            break;
+          }
         }
       }
       nodes_it->second.swap(into);
@@ -679,6 +805,7 @@ void has_inner_points(const Area_Block& string_a, const Area_Block& string_b, in
     uint32 ilat = (coords_a[i].first + coords_a[i+1].first)/2;
     uint32 ilon = (coords_a[i].second + coords_a[i+1].second)/2 + 0x80000000u;
     int check = Coord_Query_Statement::check_area_block(0, string_b, ilat, ilon);
+
     if (check & Coord_Query_Statement::HIT)
       inside = check;
     else if (check)
@@ -708,6 +835,18 @@ void Area_Query_Statement::collect_ways
       add_way_to_area_blocks(way_geometries.get_geometry(*it2), it2->id.val(), way_segments);
   }

+  /* Test: Populate ilat/ilon pairs */
+  {
+    for (auto &it : way_segments)
+      for (auto& it2 : it.second)
+        for (auto coor : it2.coors)
+        {
+          uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+          int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff);
+          it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+        }
+  }
+
   std::map< uint32, std::vector< std::pair< uint32, Way::Id_Type > > > way_coords_to_id;
   for (typename std::map< Uint31_Index, std::vector< Way_Skeleton > >::iterator it = ways.begin(); it != ways.end(); ++it)
   {
@@ -724,6 +863,9 @@ void Area_Query_Statement::collect_ways
   // Fill node_status with the area related status of each node and segment
   uint32 loop_count = 0;
   uint32 current_idx(0);
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -742,6 +884,20 @@ void Area_Query_Statement::collect_ways
       ++area_it;
     }

+    /* Test: Populate ilat/ilon pairs */
+    {
+      for (auto &it : areas)
+        for (auto& it2 : it.second)
+          for (auto coor : it2.coors)
+          {
+            uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+            int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff);
+            it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+          }
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);
+    }
+
     // check nodes
     while (nodes_it != way_coords_to_id.end() && nodes_it->first < current_idx)
       ++nodes_it;
@@ -763,7 +919,8 @@ void Area_Query_Statement::collect_ways
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       // int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT)
             {
               inside = Coord_Query_Statement::HIT;
mmd-osm commented 7 years ago
diff --git a/src/overpass_api/core/type_area.h b/src/overpass_api/core/type_area.h
index a57f29a..453e0a9 100644
--- a/src/overpass_api/core/type_area.h
+++ b/src/overpass_api/core/type_area.h
@@ -313,6 +313,8 @@ struct Area_Block
   Id_Type id;
   std::vector< uint64 > coors;

+  std::vector< std::pair< uint32, int32 > > ilat_ilon_pairs;
+
   Area_Block() : id(0u) {}

   Area_Block(void* data) : id(*(Id_Type*)data)
diff --git a/src/overpass_api/data/collect_members.cc b/src/overpass_api/data/collect_members.cc
index 99def70..26eff46 100644
--- a/src/overpass_api/data/collect_members.cc
+++ b/src/overpass_api/data/collect_members.cc
@@ -1085,6 +1085,8 @@ std::vector< Quad_Coord > make_geometry(const Way_Skeleton& way, const std::vect
 {
   std::vector< Quad_Coord > result;

+  result.reserve(way.nds.size());
+
   for (std::vector< Node::Id_Type >::const_iterator it3(way.nds.begin());
       it3 != way.nds.end(); ++it3)
   {
diff --git a/src/overpass_api/statements/area_query.cc b/src/overpass_api/statements/area_query.cc
index cd10022..73f0716 100644
--- a/src/overpass_api/statements/area_query.cc
+++ b/src/overpass_api/statements/area_query.cc
@@ -16,6 +16,7 @@
  * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
  */

+#include <assert.h>
 #include <cctype>
 #include <fstream>
 #include <iostream>
@@ -35,6 +36,109 @@
 #include "recurse.h"

+
+namespace area_query {
+
+namespace detail {
+
+const static int HIT = 1;
+const static int TOGGLE_EAST = 2;
+const static int TOGGLE_WEST = 4;
+
+int check_area_block2
+(uint32 ll_index_ilat, int32 ll_index_ilon, const Area_Block& area_block,
+    uint32 coord_lat, int32 coord_lon)
+{
+  int state = 0;
+
+  auto it(area_block.ilat_ilon_pairs.begin());
+  uint32 lat = ll_index_ilat | it->first;
+  int32 lon = ll_index_ilon | it->second;
+
+  while (++it != area_block.ilat_ilon_pairs.end())
+  {
+    uint32 last_lat = lat;
+    int32 last_lon = lon;
+
+    lat = ll_index_ilat | it->first;
+    lon = ll_index_ilon | it->second;
+
+    if (last_lon < lon)
+    {
+      if (lon < coord_lon)
+        continue; // case (1)
+      else if (last_lon > coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else if (last_lon > lon)
+    {
+      if (lon > coord_lon)
+        continue; // case (1)
+      else if (last_lon < coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else // last_lon == lon
+    {
+      if (lon == coord_lon &&
+          ((last_lat <= coord_lat && coord_lat <= lat) || (lat <= coord_lat && coord_lat <= last_lat)))
+        return HIT; // case (2)
+      continue; // else: case (1)
+    }
+
+    uint32 intersect_lat = lat +
+        ((int64)coord_lon - lon)*((int64)last_lat - lat)/((int64)last_lon - lon);
+    if (coord_lat > intersect_lat)
+      state ^= (TOGGLE_EAST | TOGGLE_WEST); // case (3)
+    else if (coord_lat == intersect_lat)
+      return HIT; // case (2)
+    // else: case (1)
+  }
+  return state;
+}
+
+
+}
+
+}
+
+
+
 class Area_Constraint : public Query_Constraint
 {
   public:
@@ -351,79 +455,80 @@ bool Area_Constraint::delivers_data(Resource_Manager& rman)
   return (counter <= 12);
 }

-
-void Area_Query_Statement::collect_nodes
-    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& nodes_req,
-     const std::set< Uint31_Index >& req,
-     std::vector< Node::Id_Type >* ids,
-     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
-     Resource_Manager& rman)
-{
-  Block_Backend< Uint31_Index, Area_Block > area_blocks_db
-      (rman.get_area_transaction()->data_index(area_settings().AREA_BLOCKS));
-  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
-      (rman.get_transaction()->data_index(osm_base_settings().NODES));
-  Block_Backend< Uint31_Index, Area_Block >::Discrete_Iterator
-      area_it(area_blocks_db.discrete_begin(req.begin(), req.end()));
-  Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
-      nodes_it(nodes_db.range_begin(nodes_req.begin(), nodes_req.end()));
-  uint32 current_idx(0);
-  if (!(area_it == area_blocks_db.discrete_end()))
-    current_idx = area_it.index().val();
-  while (!(area_it == area_blocks_db.discrete_end()))
-  {
-    rman.health_check(*this);
-
-    std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > > areas;
-    while ((!(area_it == area_blocks_db.discrete_end())) &&
-        (area_it.index().val() == current_idx))
-    {
-      if (binary_search(area_id.begin(), area_id.end(), area_it.object().id))
-   areas[area_it.object().id].push_back(area_it.object());
-      ++area_it;
-    }
-    while ((!(nodes_it == nodes_db.range_end())) &&
-        ((nodes_it.index().val() & 0xffffff00) == current_idx))
-    {
-      if ((ids != 0) &&
-     (!binary_search(ids->begin(), ids->end(), nodes_it.object().id)))
-      {
-   ++nodes_it;
-   continue;
-      }
-
-      uint32 ilat((::lat(nodes_it.index().val(), nodes_it.object().ll_lower)
-          + 91.0)*10000000+0.5);
-      int32 ilon(::lon(nodes_it.index().val(), nodes_it.object().ll_lower)*10000000
-          + (::lon(nodes_it.index().val(), nodes_it.object().ll_lower) > 0
-         ? 0.5 : -0.5));
-      for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
-      it != areas.end(); ++it)
-      {
-        int inside = 0;
-        for (std::vector< Area_Block >::const_iterator it2 = it->second.begin(); it2 != it->second.end();
-        ++it2)
-        {
-     int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
-     if (check == Coord_Query_Statement::HIT)
-     {
-       inside = 1;
-       break;
-     }
-     else if (check != 0)
-       inside ^= check;
-        }
-        if (inside)
-   {
-     nodes[nodes_it.index()].push_back(nodes_it.object());
-     break;
-   }
-      }
-      ++nodes_it;
-    }
-    current_idx = area_it.index().val();
-  }
-}
+// NO LONGER USED & OBSOLETE CODE?
+//
+//void Area_Query_Statement::collect_nodes
+//    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& nodes_req,
+//     const std::set< Uint31_Index >& req,
+//     std::vector< Node::Id_Type >* ids,
+//     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
+//     Resource_Manager& rman)
+//{
+//  Block_Backend< Uint31_Index, Area_Block > area_blocks_db
+//      (rman.get_area_transaction()->data_index(area_settings().AREA_BLOCKS));
+//  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
+//      (rman.get_transaction()->data_index(osm_base_settings().NODES));
+//  Block_Backend< Uint31_Index, Area_Block >::Discrete_Iterator
+//      area_it(area_blocks_db.discrete_begin(req.begin(), req.end()));
+//  Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
+//      nodes_it(nodes_db.range_begin(nodes_req.begin(), nodes_req.end()));
+//  uint32 current_idx(0);
+//  if (!(area_it == area_blocks_db.discrete_end()))
+//    current_idx = area_it.index().val();
+//  while (!(area_it == area_blocks_db.discrete_end()))
+//  {
+//    rman.health_check(*this);
+//
+//    std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > > areas;
+//    while ((!(area_it == area_blocks_db.discrete_end())) &&
+//        (area_it.index().val() == current_idx))
+//    {
+//      if (binary_search(area_id.begin(), area_id.end(), area_it.object().id))
+// areas[area_it.object().id].push_back(area_it.object());
+//      ++area_it;
+//    }
+//    while ((!(nodes_it == nodes_db.range_end())) &&
+//        ((nodes_it.index().val() & 0xffffff00) == current_idx))
+//    {
+//      if ((ids != 0) &&
+//   (!binary_search(ids->begin(), ids->end(), nodes_it.object().id)))
+//      {
+// ++nodes_it;
+// continue;
+//      }
+//
+//      uint32 ilat((::lat(nodes_it.index().val(), nodes_it.object().ll_lower)
+//          + 91.0)*10000000+0.5);
+//      int32 ilon(::lon(nodes_it.index().val(), nodes_it.object().ll_lower)*10000000
+//          + (::lon(nodes_it.index().val(), nodes_it.object().ll_lower) > 0
+//       ? 0.5 : -0.5));
+//      for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
+//    it != areas.end(); ++it)
+//      {
+//        int inside = 0;
+//        for (std::vector< Area_Block >::const_iterator it2 = it->second.begin(); it2 != it->second.end();
+//      ++it2)
+//        {
+//   int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+//   if (check == Coord_Query_Statement::HIT)
+//   {
+//     inside = 1;
+//     break;
+//   }
+//   else if (check != 0)
+//     inside ^= check;
+//        }
+//        if (inside)
+// {
+//   nodes[nodes_it.index()].push_back(nodes_it.object());
+//   break;
+// }
+//      }
+//      ++nodes_it;
+//    }
+//    current_idx = area_it.index().val();
+//  }
+//}

 template< typename Node_Skeleton >
@@ -441,6 +546,10 @@ void Area_Query_Statement::collect_nodes

   uint32 loop_count = 0;
   uint32 current_idx(0);
+
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -459,6 +568,23 @@ void Area_Query_Statement::collect_nodes
       ++area_it;
     }

+    /* Test: Populate ilat/ilon pairs */
+    {
+      for (auto &it : areas)
+        for (auto& it2 : it.second)
+          for (auto coor : it2.coors)
+          {
+            uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+            int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff);
+            it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+          }
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);
+    }
+
+    /* ------------------------------ */
+
+
     while (nodes_it != nodes.end() && nodes_it->first.val() < current_idx)
     {
       nodes_it->second.clear();
@@ -475,6 +601,7 @@ void Area_Query_Statement::collect_nodes
             + 91.0)*10000000+0.5);
         int32 ilon(::lon(nodes_it->first.val(), iit->ll_lower)*10000000
             + (::lon(nodes_it->first.val(), iit->ll_lower) > 0 ? 0.5 : -0.5));
+
         for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
         it != areas.end(); ++it)
         {
@@ -484,7 +611,8 @@ void Area_Query_Statement::collect_nodes
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
+       //int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT && add_border)
        {
          inside = 1;
@@ -494,10 +622,10 @@ void Area_Query_Statement::collect_nodes
          inside ^= check;
           }
           if (inside)
-     {
-       into.push_back(*iit);
-       break;
-     }
+          {
+            into.push_back(*iit);
+            break;
+          }
         }
       }
       nodes_it->second.swap(into);
@@ -616,6 +744,7 @@ inline int longitude_a_intersects_inner

 int intersects_inner(const Area_Block& string_a, const Area_Block& string_b)
 {
+
   std::vector< std::pair< uint32, uint32 > > coords_a;
   for (std::vector< uint64 >::const_iterator it = string_a.coors.begin(); it != string_a.coors.end(); ++it)
     coords_a.push_back(std::make_pair(::ilat(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull)),
@@ -626,6 +755,15 @@ int intersects_inner(const Area_Block& string_a, const Area_Block& string_b)
     coords_b.push_back(std::make_pair(::ilat(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull)),
                 ::ilon(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull))));

+
+/*
+  std::vector< std::pair< uint32, int32 > > coords_a = string_a.ilat_ilon_pairs;
+  std::vector< std::pair< uint32, int32 > > coords_b = string_b.ilat_ilon_pairs;
+
+  for (auto & v : coords_a) v.second ^= 0x80000000;
+  for (auto & v : coords_b) v.second ^= 0x80000000;
+  */
+
   for (std::vector< std::pair< uint32, uint32 > >::size_type i = 0; i < coords_a.size()-1; ++i)
   {
     if (coords_a[i].second < coords_a[i+1].second)
@@ -678,7 +816,10 @@ void has_inner_points(const Area_Block& string_a, const Area_Block& string_b, in
   {
     uint32 ilat = (coords_a[i].first + coords_a[i+1].first)/2;
     uint32 ilon = (coords_a[i].second + coords_a[i+1].second)/2 + 0x80000000u;
-    int check = Coord_Query_Statement::check_area_block(0, string_b, ilat, ilon);
+
+    //int check = Coord_Query_Statement::check_area_block(0, string_b, ilat, ilon);
+    int check(area_query::detail::check_area_block2(0, 0, string_b, ilat, ilon));
+
     if (check & Coord_Query_Statement::HIT)
       inside = check;
     else if (check)
@@ -708,6 +849,18 @@ void Area_Query_Statement::collect_ways
       add_way_to_area_blocks(way_geometries.get_geometry(*it2), it2->id.val(), way_segments);
   }

+  /* Test: Populate ilat/ilon pairs */
+  {
+    for (auto &it : way_segments)
+      for (auto& it2 : it.second)
+        for (auto coor : it2.coors)
+        {
+          uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+          int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff);
+          it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+        }
+  }
+
   std::map< uint32, std::vector< std::pair< uint32, Way::Id_Type > > > way_coords_to_id;
   for (typename std::map< Uint31_Index, std::vector< Way_Skeleton > >::iterator it = ways.begin(); it != ways.end(); ++it)
   {
@@ -724,6 +877,9 @@ void Area_Query_Statement::collect_ways
   // Fill node_status with the area related status of each node and segment
   uint32 loop_count = 0;
   uint32 current_idx(0);
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -742,6 +898,20 @@ void Area_Query_Statement::collect_ways
       ++area_it;
     }

+    /* Test: Populate ilat/ilon pairs */
+    {
+      for (auto &it : areas)
+        for (auto& it2 : it.second)
+          for (auto coor : it2.coors)
+          {
+            uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+            int32 _lon = ::ilon(((coor>>32)&0xff) ^ 0x40000000, coor & 0xffffffff);
+            it2.ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+          }
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);
+    }
+
     // check nodes
     while (nodes_it != way_coords_to_id.end() && nodes_it->first < current_idx)
       ++nodes_it;
@@ -763,7 +933,8 @@ void Area_Query_Statement::collect_ways
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       // int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT)
             {
               inside = Coord_Query_Statement::HIT;
@@ -845,20 +1016,21 @@ void Area_Query_Statement::collect_ways
 }

-void collect_nodes_from_req
-    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& req,
-     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
-     Resource_Manager& rman)
-{
-  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
-      (rman.get_transaction()->data_index(osm_base_settings().NODES));
-  for (Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
-      it(nodes_db.range_begin
-      (Default_Range_Iterator< Uint32_Index >(req.begin()),
-       Default_Range_Iterator< Uint32_Index >(req.end())));
-      !(it == nodes_db.range_end()); ++it)
-    nodes[it.index()].push_back(it.object());
-}
+//
+//void collect_nodes_from_req
+//    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& req,
+//     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
+//     Resource_Manager& rman)
+//{
+//  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
+//      (rman.get_transaction()->data_index(osm_base_settings().NODES));
+//  for (Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
+//      it(nodes_db.range_begin
+//      (Default_Range_Iterator< Uint32_Index >(req.begin()),
+//       Default_Range_Iterator< Uint32_Index >(req.end())));
+//      !(it == nodes_db.range_end()); ++it)
+//    nodes[it.index()].push_back(it.object());
+//}

 void Area_Query_Statement::execute(Resource_Manager& rman)
mmd-osm commented 7 years ago
diff --git a/src/overpass_api/core/type_area.h b/src/overpass_api/core/type_area.h
index a57f29a..c13b45e 100644
--- a/src/overpass_api/core/type_area.h
+++ b/src/overpass_api/core/type_area.h
@@ -29,6 +29,7 @@
 #include "type_node.h"

 #include "basic_types.h"
+#include "index_computations.h"

 struct Aligned_Segment
@@ -313,9 +314,9 @@ struct Area_Block
   Id_Type id;
   std::vector< uint64 > coors;

-  Area_Block() : id(0u) {}
+  Area_Block() : id(0u), ilat_ilon_initialized(false) {}

-  Area_Block(void* data) : id(*(Id_Type*)data)
+  Area_Block(void* data) : id(*(Id_Type*)data), ilat_ilon_initialized(false)
   {
     id = *(Id_Type*)data;
     coors.resize(*((uint16*)data + 2));
@@ -324,7 +325,7 @@ struct Area_Block
   }

   Area_Block(Id_Type id_, const std::vector< uint64 >& coors_)
-  : id(id_), coors(coors_) {}
+  : id(id_), coors(coors_), ilat_ilon_initialized(false) {}

   uint32 size_of() const
   {
@@ -360,6 +361,25 @@ struct Area_Block
   {
     return ((this->id == a.id) && (this->coors == a.coors));
   }
+
+  const std::vector< std::pair< uint32, int32 > > &  get_ilat_ilon_pairs() const
+  {
+    if (!ilat_ilon_initialized)
+    {
+      for (auto coor : coors)
+      {
+        uint32 _lat = ::ilat((coor>>32)&0xff, coor & 0xffffffff);
+        int32 _lon = ::ilon((coor>>32)&0xff, coor & 0xffffffff);
+        ilat_ilon_pairs.push_back(std::make_pair(_lat, _lon));
+      }
+      ilat_ilon_initialized = true;
+    }
+    return ilat_ilon_pairs;
+  }
+
+private:
+  mutable std::vector< std::pair< uint32, int32 > > ilat_ilon_pairs;
+  mutable bool ilat_ilon_initialized;
 };

 #endif
diff --git a/src/overpass_api/data/collect_members.cc b/src/overpass_api/data/collect_members.cc
index 99def70..26eff46 100644
--- a/src/overpass_api/data/collect_members.cc
+++ b/src/overpass_api/data/collect_members.cc
@@ -1085,6 +1085,8 @@ std::vector< Quad_Coord > make_geometry(const Way_Skeleton& way, const std::vect
 {
   std::vector< Quad_Coord > result;

+  result.reserve(way.nds.size());
+
   for (std::vector< Node::Id_Type >::const_iterator it3(way.nds.begin());
       it3 != way.nds.end(); ++it3)
   {
diff --git a/src/overpass_api/statements/area_query.cc b/src/overpass_api/statements/area_query.cc
index cd10022..765df08 100644
--- a/src/overpass_api/statements/area_query.cc
+++ b/src/overpass_api/statements/area_query.cc
@@ -16,6 +16,7 @@
  * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
  */

+#include <assert.h>
 #include <cctype>
 #include <fstream>
 #include <iostream>
@@ -35,6 +36,109 @@
 #include "recurse.h"

+
+namespace area_query {
+
+namespace detail {
+
+const static int HIT = 1;
+const static int TOGGLE_EAST = 2;
+const static int TOGGLE_WEST = 4;
+
+int check_area_block2
+(uint32 ll_index_ilat, int32 ll_index_ilon, const Area_Block& area_block,
+    uint32 coord_lat, int32 coord_lon)
+{
+  int state = 0;
+
+  auto it(area_block.get_ilat_ilon_pairs().begin());
+  uint32 lat = ll_index_ilat | it->first;
+  int32 lon = ll_index_ilon | (it->second ^ 0x80000000);
+
+  while (++it != area_block.get_ilat_ilon_pairs().end())
+  {
+    uint32 last_lat = lat;
+    int32 last_lon = lon;
+
+    lat = ll_index_ilat | it->first;
+    lon = ll_index_ilon | (it->second ^ 0x80000000);
+
+    if (last_lon < lon)
+    {
+      if (lon < coord_lon)
+        continue; // case (1)
+      else if (last_lon > coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else if (last_lon > lon)
+    {
+      if (lon > coord_lon)
+        continue; // case (1)
+      else if (last_lon < coord_lon)
+        continue; // case (1)
+      else if (lon == coord_lon)
+      {
+        if (lat < coord_lat)
+          state ^= TOGGLE_EAST; // case (4)
+        else if (lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+      else if (last_lon == coord_lon)
+      {
+        if (last_lat < coord_lat)
+          state ^= TOGGLE_WEST; // case (4)
+        else if (last_lat == coord_lat)
+          return HIT; // case (2)
+        // else: case (1)
+        continue;
+      }
+    }
+    else // last_lon == lon
+    {
+      if (lon == coord_lon &&
+          ((last_lat <= coord_lat && coord_lat <= lat) || (lat <= coord_lat && coord_lat <= last_lat)))
+        return HIT; // case (2)
+      continue; // else: case (1)
+    }
+
+    uint32 intersect_lat = lat +
+        ((int64)coord_lon - lon)*((int64)last_lat - lat)/((int64)last_lon - lon);
+    if (coord_lat > intersect_lat)
+      state ^= (TOGGLE_EAST | TOGGLE_WEST); // case (3)
+    else if (coord_lat == intersect_lat)
+      return HIT; // case (2)
+    // else: case (1)
+  }
+  return state;
+}
+
+
+}
+
+}
+
+
+
 class Area_Constraint : public Query_Constraint
 {
   public:
@@ -351,79 +455,80 @@ bool Area_Constraint::delivers_data(Resource_Manager& rman)
   return (counter <= 12);
 }

-
-void Area_Query_Statement::collect_nodes
-    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& nodes_req,
-     const std::set< Uint31_Index >& req,
-     std::vector< Node::Id_Type >* ids,
-     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
-     Resource_Manager& rman)
-{
-  Block_Backend< Uint31_Index, Area_Block > area_blocks_db
-      (rman.get_area_transaction()->data_index(area_settings().AREA_BLOCKS));
-  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
-      (rman.get_transaction()->data_index(osm_base_settings().NODES));
-  Block_Backend< Uint31_Index, Area_Block >::Discrete_Iterator
-      area_it(area_blocks_db.discrete_begin(req.begin(), req.end()));
-  Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
-      nodes_it(nodes_db.range_begin(nodes_req.begin(), nodes_req.end()));
-  uint32 current_idx(0);
-  if (!(area_it == area_blocks_db.discrete_end()))
-    current_idx = area_it.index().val();
-  while (!(area_it == area_blocks_db.discrete_end()))
-  {
-    rman.health_check(*this);
-
-    std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > > areas;
-    while ((!(area_it == area_blocks_db.discrete_end())) &&
-        (area_it.index().val() == current_idx))
-    {
-      if (binary_search(area_id.begin(), area_id.end(), area_it.object().id))
-   areas[area_it.object().id].push_back(area_it.object());
-      ++area_it;
-    }
-    while ((!(nodes_it == nodes_db.range_end())) &&
-        ((nodes_it.index().val() & 0xffffff00) == current_idx))
-    {
-      if ((ids != 0) &&
-     (!binary_search(ids->begin(), ids->end(), nodes_it.object().id)))
-      {
-   ++nodes_it;
-   continue;
-      }
-
-      uint32 ilat((::lat(nodes_it.index().val(), nodes_it.object().ll_lower)
-          + 91.0)*10000000+0.5);
-      int32 ilon(::lon(nodes_it.index().val(), nodes_it.object().ll_lower)*10000000
-          + (::lon(nodes_it.index().val(), nodes_it.object().ll_lower) > 0
-         ? 0.5 : -0.5));
-      for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
-      it != areas.end(); ++it)
-      {
-        int inside = 0;
-        for (std::vector< Area_Block >::const_iterator it2 = it->second.begin(); it2 != it->second.end();
-        ++it2)
-        {
-     int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
-     if (check == Coord_Query_Statement::HIT)
-     {
-       inside = 1;
-       break;
-     }
-     else if (check != 0)
-       inside ^= check;
-        }
-        if (inside)
-   {
-     nodes[nodes_it.index()].push_back(nodes_it.object());
-     break;
-   }
-      }
-      ++nodes_it;
-    }
-    current_idx = area_it.index().val();
-  }
-}
+// NO LONGER USED & OBSOLETE CODE?
+//
+//void Area_Query_Statement::collect_nodes
+//    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& nodes_req,
+//     const std::set< Uint31_Index >& req,
+//     std::vector< Node::Id_Type >* ids,
+//     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
+//     Resource_Manager& rman)
+//{
+//  Block_Backend< Uint31_Index, Area_Block > area_blocks_db
+//      (rman.get_area_transaction()->data_index(area_settings().AREA_BLOCKS));
+//  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
+//      (rman.get_transaction()->data_index(osm_base_settings().NODES));
+//  Block_Backend< Uint31_Index, Area_Block >::Discrete_Iterator
+//      area_it(area_blocks_db.discrete_begin(req.begin(), req.end()));
+//  Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
+//      nodes_it(nodes_db.range_begin(nodes_req.begin(), nodes_req.end()));
+//  uint32 current_idx(0);
+//  if (!(area_it == area_blocks_db.discrete_end()))
+//    current_idx = area_it.index().val();
+//  while (!(area_it == area_blocks_db.discrete_end()))
+//  {
+//    rman.health_check(*this);
+//
+//    std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > > areas;
+//    while ((!(area_it == area_blocks_db.discrete_end())) &&
+//        (area_it.index().val() == current_idx))
+//    {
+//      if (binary_search(area_id.begin(), area_id.end(), area_it.object().id))
+// areas[area_it.object().id].push_back(area_it.object());
+//      ++area_it;
+//    }
+//    while ((!(nodes_it == nodes_db.range_end())) &&
+//        ((nodes_it.index().val() & 0xffffff00) == current_idx))
+//    {
+//      if ((ids != 0) &&
+//   (!binary_search(ids->begin(), ids->end(), nodes_it.object().id)))
+//      {
+// ++nodes_it;
+// continue;
+//      }
+//
+//      uint32 ilat((::lat(nodes_it.index().val(), nodes_it.object().ll_lower)
+//          + 91.0)*10000000+0.5);
+//      int32 ilon(::lon(nodes_it.index().val(), nodes_it.object().ll_lower)*10000000
+//          + (::lon(nodes_it.index().val(), nodes_it.object().ll_lower) > 0
+//       ? 0.5 : -0.5));
+//      for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
+//    it != areas.end(); ++it)
+//      {
+//        int inside = 0;
+//        for (std::vector< Area_Block >::const_iterator it2 = it->second.begin(); it2 != it->second.end();
+//      ++it2)
+//        {
+//   int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+//   if (check == Coord_Query_Statement::HIT)
+//   {
+//     inside = 1;
+//     break;
+//   }
+//   else if (check != 0)
+//     inside ^= check;
+//        }
+//        if (inside)
+// {
+//   nodes[nodes_it.index()].push_back(nodes_it.object());
+//   break;
+// }
+//      }
+//      ++nodes_it;
+//    }
+//    current_idx = area_it.index().val();
+//  }
+//}

 template< typename Node_Skeleton >
@@ -441,6 +546,10 @@ void Area_Query_Statement::collect_nodes

   uint32 loop_count = 0;
   uint32 current_idx(0);
+
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -459,6 +568,15 @@ void Area_Query_Statement::collect_nodes
       ++area_it;
     }

+    /* Test: Populate ilat/ilon pairs */
+    {
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);
+    }
+
+    /* ------------------------------ */
+
+
     while (nodes_it != nodes.end() && nodes_it->first.val() < current_idx)
     {
       nodes_it->second.clear();
@@ -475,6 +593,7 @@ void Area_Query_Statement::collect_nodes
             + 91.0)*10000000+0.5);
         int32 ilon(::lon(nodes_it->first.val(), iit->ll_lower)*10000000
             + (::lon(nodes_it->first.val(), iit->ll_lower) > 0 ? 0.5 : -0.5));
+
         for (std::map< Area_Skeleton::Id_Type, std::vector< Area_Block > >::const_iterator it = areas.begin();
         it != areas.end(); ++it)
         {
@@ -484,7 +603,8 @@ void Area_Query_Statement::collect_nodes
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
+       //int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT && add_border)
        {
          inside = 1;
@@ -494,10 +614,10 @@ void Area_Query_Statement::collect_nodes
          inside ^= check;
           }
           if (inside)
-     {
-       into.push_back(*iit);
-       break;
-     }
+          {
+            into.push_back(*iit);
+            break;
+          }
         }
       }
       nodes_it->second.swap(into);
@@ -616,6 +736,7 @@ inline int longitude_a_intersects_inner

 int intersects_inner(const Area_Block& string_a, const Area_Block& string_b)
 {
+  /*
   std::vector< std::pair< uint32, uint32 > > coords_a;
   for (std::vector< uint64 >::const_iterator it = string_a.coors.begin(); it != string_a.coors.end(); ++it)
     coords_a.push_back(std::make_pair(::ilat(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull)),
@@ -626,6 +747,13 @@ int intersects_inner(const Area_Block& string_a, const Area_Block& string_b)
     coords_b.push_back(std::make_pair(::ilat(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull)),
                 ::ilon(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull))));

+
+  */
+  const std::vector< std::pair< uint32, int32 > > coords_a = string_a.get_ilat_ilon_pairs();
+  const std::vector< std::pair< uint32, int32 > > coords_b = string_b.get_ilat_ilon_pairs();
+
+
+
   for (std::vector< std::pair< uint32, uint32 > >::size_type i = 0; i < coords_a.size()-1; ++i)
   {
     if (coords_a[i].second < coords_a[i+1].second)
@@ -667,10 +795,13 @@ int intersects_inner(const Area_Block& string_a, const Area_Block& string_b)

 void has_inner_points(const Area_Block& string_a, const Area_Block& string_b, int& inside)
 {
+  /*
   std::vector< std::pair< uint32, uint32 > > coords_a;
   for (std::vector< uint64 >::const_iterator it = string_a.coors.begin(); it != string_a.coors.end(); ++it)
     coords_a.push_back(std::make_pair(::ilat(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull)),
                                  ::ilon(uint32((*it>>32)&0xff), uint32(*it & 0xffffffffull))));
+  */
+  const std::vector< std::pair< uint32, int32 > > coords_a = string_a.get_ilat_ilon_pairs();

   // Check additionally the middle of the segment to also get segments
   // that run through the area
@@ -678,7 +809,10 @@ void has_inner_points(const Area_Block& string_a, const Area_Block& string_b, in
   {
     uint32 ilat = (coords_a[i].first + coords_a[i+1].first)/2;
     uint32 ilon = (coords_a[i].second + coords_a[i+1].second)/2 + 0x80000000u;
-    int check = Coord_Query_Statement::check_area_block(0, string_b, ilat, ilon);
+
+    //int check = Coord_Query_Statement::check_area_block(0, string_b, ilat, ilon);
+    int check(area_query::detail::check_area_block2(0, 0, string_b, ilat, ilon));
+
     if (check & Coord_Query_Statement::HIT)
       inside = check;
     else if (check)
@@ -724,6 +858,9 @@ void Area_Query_Statement::collect_ways
   // Fill node_status with the area related status of each node and segment
   uint32 loop_count = 0;
   uint32 current_idx(0);
+  uint32 current_idx_ilat(0);
+  int32 current_idx_ilon(0);
+
   while (!(area_it == area_blocks_db.discrete_end()))
   {
     current_idx = area_it.index().val();
@@ -742,6 +879,12 @@ void Area_Query_Statement::collect_ways
       ++area_it;
     }

+    /* Test: Populate ilat/ilon pairs */
+    {
+      current_idx_ilat = ::ilat(current_idx, 0);
+      current_idx_ilon = ::ilon(current_idx, 0);
+    }
+
     // check nodes
     while (nodes_it != way_coords_to_id.end() && nodes_it->first < current_idx)
       ++nodes_it;
@@ -763,7 +906,8 @@ void Area_Query_Statement::collect_ways
           {
             ++loop_count;

-       int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       // int check(Coord_Query_Statement::check_area_block(current_idx, *it2, ilat, ilon));
+       int check(area_query::detail::check_area_block2(current_idx_ilat, current_idx_ilon, *it2, ilat, ilon));
        if (check == Coord_Query_Statement::HIT)
             {
               inside = Coord_Query_Statement::HIT;
@@ -845,20 +989,21 @@ void Area_Query_Statement::collect_ways
 }

-void collect_nodes_from_req
-    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& req,
-     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
-     Resource_Manager& rman)
-{
-  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
-      (rman.get_transaction()->data_index(osm_base_settings().NODES));
-  for (Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
-      it(nodes_db.range_begin
-      (Default_Range_Iterator< Uint32_Index >(req.begin()),
-       Default_Range_Iterator< Uint32_Index >(req.end())));
-      !(it == nodes_db.range_end()); ++it)
-    nodes[it.index()].push_back(it.object());
-}
+//
+//void collect_nodes_from_req
+//    (const std::set< std::pair< Uint32_Index, Uint32_Index > >& req,
+//     std::map< Uint32_Index, std::vector< Node_Skeleton > >& nodes,
+//     Resource_Manager& rman)
+//{
+//  Block_Backend< Uint32_Index, Node_Skeleton > nodes_db
+//      (rman.get_transaction()->data_index(osm_base_settings().NODES));
+//  for (Block_Backend< Uint32_Index, Node_Skeleton >::Range_Iterator
+//      it(nodes_db.range_begin
+//      (Default_Range_Iterator< Uint32_Index >(req.begin()),
+//       Default_Range_Iterator< Uint32_Index >(req.end())));
+//      !(it == nodes_db.range_end()); ++it)
+//    nodes[it.index()].push_back(it.object());
+//}

 void Area_Query_Statement::execute(Resource_Manager& rman)
mmd-osm commented 5 years ago

Now included in https://github.com/mmd-osm/Overpass-API/commit/2799ab35c8e604235b0a386e189ef31eb514d719 and https://github.com/mmd-osm/Overpass-API/commit/d373603e65ad8cf644dde36d63d03efe7739ccf6