@@ -3130,13 +3130,30 @@ static double point_segment_dist_sq(const vertex_xy &p, const vertex_xy &a, cons
31303130 return diff.norm_sq ();
31313131}
31323132
3133+ // Check if point P is on segment QR
31333134static bool point_on_segment (const vertex_xy &p, const vertex_xy &q, const vertex_xy &r) {
31343135 return q.x >= std::min (p.x , r.x ) && q.x <= std::max (p.x , r.x ) && q.y >= std::min (p.y , r.y ) &&
31353136 q.y <= std::max (p.y , r.y );
31363137}
31373138
31383139static bool segment_intersects (const vertex_xy &a1, const vertex_xy &a2, const vertex_xy &b1, const vertex_xy &b2) {
31393140 // Check if two segments intersect using the orientation method
3141+ // Handle degenerate cases where a segment is actually a single point
3142+ const bool a_is_point = (a1.x == a2.x && a1.y == a2.y );
3143+ const bool b_is_point = (b1.x == b2.x && b1.y == b2.y );
3144+
3145+ if (a_is_point && b_is_point) {
3146+ // Both are points: intersect only if identical
3147+ return (a1.x == b1.x && a1.y == b1.y );
3148+ }
3149+ if (a_is_point) {
3150+ // A is a point: check if A lies on segment B
3151+ return point_on_segment (a1, b1, b2);
3152+ }
3153+ if (b_is_point) {
3154+ // B is a point: check if B lies on segment A
3155+ return point_on_segment (b1, a1, a2);
3156+ }
31403157
31413158 const auto o1 = orient2d_fast (a1, a2, b1);
31423159 const auto o2 = orient2d_fast (a1, a2, b2);
@@ -3250,6 +3267,15 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32503267 for (uint32_t i = lhs_beg_idx + 1 ; i < lhs_end_idx; i++) {
32513268 memcpy (&lhs_next, lhs_vertex_array + i * lhs_vertex_width, sizeof (vertex_xy));
32523269
3270+ // If this is a zero-length segment, skip it
3271+ // LINESTRINGs must have at least two distinct vertices to be valid, so this is safe. Even if we skip
3272+ // this vertex now, we must eventually reach a non-zero-length segment that includes this vertex as
3273+ // its start point. It will therefore still contribute to the distance calculation once we process that
3274+ // segment.
3275+ if (lhs_prev.x == lhs_next.x && lhs_prev.y == lhs_next.y ) {
3276+ continue ;
3277+ }
3278+
32533279 // Quick check: If the distance between the segment and the box (all the segments)
32543280 // is greater than min_dist, we can skip the exact distance check
32553281
@@ -3268,6 +3294,13 @@ static bool try_get_prepared_distance_lines(const prepared_geometry &lhs, const
32683294 for (uint32_t j = rhs_beg_idx + 1 ; j < rhs_end_idx; j++) {
32693295 memcpy (&rhs_next, rhs_vertex_array + j * rhs_vertex_width, sizeof (vertex_xy));
32703296
3297+ // If this is a zero-length segment, skip it
3298+ // LINESTRINGs must have at least two distinct points to be valid, so this is safe.
3299+ // (see comment above)
3300+ if (rhs_prev.x == rhs_next.x && rhs_prev.y == rhs_next.y ) {
3301+ continue ;
3302+ }
3303+
32713304 // Quick check: If the distance between the segment bounds are greater than min_dist,
32723305 // we can skip the exact distance check
32733306 extent_xy rhs_seg;
0 commit comments