@@ -2857,7 +2857,10 @@ void prepared_geometry::build(allocator &allocator) {
28572857 box = extent_xy::smallest ();
28582858
28592859 const auto beg = i * NODE_SIZE;
2860- const auto end = math::min (beg + NODE_SIZE, vertex_count);
2860+
2861+ // We add +1 to the node size here, to get not just the start point of the segment, but also the end point,
2862+ // which may be in the next node. This ensures there is no gaps between node bounding boxes.
2863+ const auto end = math::min (beg + NODE_SIZE + 1 , vertex_count);
28612864
28622865 for (uint32_t j = beg; j < end; j++) {
28632866 vertex_xy curr = {0 , 0 };
@@ -2921,6 +2924,7 @@ point_in_polygon_result prepared_geometry::contains(const vertex_xy &vert) const
29212924 const auto &box = level.entry_array [entry];
29222925
29232926 // Check if the vertex is in the box y-slice
2927+ D_ASSERT (box.min .y <= box.max .y );
29242928 if (box.min .y <= vert.y && box.max .y >= vert.y ) {
29252929 if (depth != index.level_count - 1 ) {
29262930 // We are not at a leaf, so go downwards
@@ -2966,7 +2970,13 @@ point_in_polygon_result prepared_geometry::contains(const vertex_xy &vert) const
29662970 return crossings % 2 == 0 ? point_in_polygon_result::EXTERIOR : point_in_polygon_result::INTERIOR;
29672971 }
29682972
2969- if (stack[depth] != index.level_array [depth].entry_count - 1 ) {
2973+ // The end of this node is either the end of the current node, or the end of the level
2974+ const auto node_end = ((stack[depth - 1 ] + 1 ) * NODE_SIZE) - 1 ;
2975+ const auto levl_end = index.level_array [depth].entry_count - 1 ;
2976+
2977+ const auto end = math::min (node_end, levl_end);
2978+
2979+ if (stack[depth] != end) {
29702980 // Go sideways!
29712981 stack[depth]++;
29722982 break ;
@@ -3220,10 +3230,10 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32203230 if (lhs_is_leaf && rhs_is_leaf) {
32213231
32223232 const auto lhs_beg_idx = pair.lhs_entry * NODE_SIZE;
3223- const auto lhs_end_idx = math::min (lhs_beg_idx + NODE_SIZE, lhs.index .items_count );
3233+ const auto lhs_end_idx = math::min (lhs_beg_idx + NODE_SIZE + 1 , lhs.index .items_count );
32243234
32253235 const auto rhs_beg_idx = pair.rhs_entry * NODE_SIZE;
3226- const auto rhs_end_idx = math::min (rhs_beg_idx + NODE_SIZE, rhs.index .items_count );
3236+ const auto rhs_end_idx = math::min (rhs_beg_idx + NODE_SIZE + 1 , rhs.index .items_count );
32273237
32283238 if (lhs_beg_idx >= lhs_end_idx || rhs_beg_idx >= rhs_end_idx) {
32293239 continue ; // No segments to check
@@ -3240,9 +3250,15 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32403250 for (uint32_t i = lhs_beg_idx + 1 ; i < lhs_end_idx; i++) {
32413251 memcpy (&lhs_next, lhs_vertex_array + i * lhs_vertex_width, sizeof (vertex_xy));
32423252
3243- // Quick check. If the distance between the segment and the box (all the segments)
3253+ // Quick check: If the distance between the segment and the box (all the segments)
32443254 // is greater than min_dist, we can skip the exact distance check
3245- extent_xy lhs_seg = {lhs_prev, lhs_next};
3255+
3256+ extent_xy lhs_seg;
3257+ lhs_seg.min .x = std::min (lhs_prev.x , lhs_next.x );
3258+ lhs_seg.min .y = std::min (lhs_prev.y , lhs_next.y );
3259+ lhs_seg.max .x = std::max (lhs_prev.x , lhs_next.x );
3260+ lhs_seg.max .y = std::max (lhs_prev.y , lhs_next.y );
3261+
32463262 if (lhs_seg.distance_to_sq (rhs_box) > min_dist) {
32473263 lhs_prev = lhs_next;
32483264 continue ;
@@ -3252,17 +3268,21 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32523268 for (uint32_t j = rhs_beg_idx + 1 ; j < rhs_end_idx; j++) {
32533269 memcpy (&rhs_next, rhs_vertex_array + j * rhs_vertex_width, sizeof (vertex_xy));
32543270
3255- extent_xy rhs_seg = {rhs_prev, rhs_next};
3256-
3257- // Quick check. If the distance between the segment bounds are greater than min_dist,
3271+ // Quick check: If the distance between the segment bounds are greater than min_dist,
32583272 // we can skip the exact distance check
3259- if (lhs_seg.distance_to_sq (rhs_seg) > min_dist) {
3273+ extent_xy rhs_seg;
3274+ rhs_seg.min .x = std::min (rhs_prev.x , rhs_next.x );
3275+ rhs_seg.min .y = std::min (rhs_prev.y , rhs_next.y );
3276+ rhs_seg.max .x = std::max (rhs_prev.x , rhs_next.x );
3277+ rhs_seg.max .y = std::max (rhs_prev.y , rhs_next.y );
3278+
3279+ if (rhs_seg.distance_to_sq (lhs_seg) > min_dist) {
32603280 rhs_prev = rhs_next;
32613281 continue ;
32623282 }
32633283
32643284 const auto dist = segment_segment_dist_sq (lhs_prev, lhs_next, rhs_prev, rhs_next);
3265- if (dist <= min_dist) {
3285+ if (dist < min_dist) {
32663286 min_dist = dist;
32673287 found_any = true ;
32683288 }
@@ -3346,7 +3366,7 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
33463366 }
33473367
33483368 if (found_any) {
3349- distance = std::sqrt (min_dist);
3369+ distance = std::sqrt (min_dist); // Convert squared distance to actual distance
33503370 return true ; // We found a distance
33513371 }
33523372 return false ; // No distance found
@@ -3361,6 +3381,7 @@ bool prepared_geometry::try_get_distance(const prepared_geometry &other, double
33613381// WKT Parsing
33623382// ======================================================================================================================
33633383
3384+
33643385namespace sgl {
33653386
33663387namespace {
0 commit comments