- #4031, Survive to big MaxError tolerances passed to ST_CurveToLine
(Sandro Santilli)
+ - #4058, Fix infinite loop in linearization of a big radius small arc
+ (Sandro Santilli)
- #4071, ST_ClusterKMeans crash on NULL/EMPTY fixed (Darafei Praliaskouski)
- #4079, ensure St_AsMVTGeom outputs CW oriented polygons (Paul Ramsey)
- #4070, use standard interruption error code on GEOS interruptions
lwgeom_free(in);
+ /*
+ * ROBUSTNESS: big radius, small tolerance
+ * See https://trac.osgeo.org/postgis/ticket/4058
+ * NOTE: we are really only interested in not enterying
+ * an infinite loop here
+ */
+ toltype = LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION;
+ in = lwgeom_from_text("CIRCULARSTRING("
+ "2696000.553 1125699.831999999936670, "
+ "2695950.552000000141561 1125749.833000000100583, "
+ "2695865.195999999996275 1125835.189000)");
+ out = lwcurve_linearize(in, 0.0001, toltype, 0);
+ str = lwgeom_to_text(out, 2);
+ ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
+ lwfree(str);
+ lwgeom_free(out);
+ out = lwcurve_linearize(in, 0.0001, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
+ str = lwgeom_to_text(out, 2);
+ ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695866 1125836)");
+ lwfree(str);
+ lwgeom_free(out);
+#ifndef SKIP_TEST_RETAIN_ANGLE
+ out = lwcurve_linearize(in, 0.0001, toltype,
+ LW_LINEARIZE_FLAG_SYMMETRIC |
+ LW_LINEARIZE_FLAG_RETAIN_ANGLE
+ );
+ str = lwgeom_to_text(out, 2);
+ ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
+ lwfree(str);
+ lwgeom_free(out);
+#endif /* SKIP_TEST_RETAIN_ANGLE */
+ lwgeom_free(in);
+
/***********************************************************
*
* Maximum angle tolerance type
LWDEBUG(2, "lwarc_linearize called.");
+ LWDEBUGF(2, " curve is CIRCULARSTRING(%.15g %.15f, %.15f %.15f, %.15f %15f)",
+ t1->x, t1->y, t2->x, t2->y, t3->x, t3->y);
+
p2_side = lw_segment_side(t1, t3, t2);
+ LWDEBUGF(2, " p2 side is %d", p2_side);
+
/* Force counterclockwise scan if SYMMETRIC operation is requsested */
if ( p2_side == -1 && flags & LW_LINEARIZE_FLAG_SYMMETRIC )
{
* angle = acos( 1 - tol/radius )
*
* Constraints: 1.0 - tol/radius must be between -1 and 1
- * which means tol/radius must be between 0 and 2 times
+ * which means tol must be between 0 and 2 times
* the radius, which makes sense as you cannot have a
* sagitta bigger than twice the radius!
*
LWDEBUGF(2, "lwarc_linearize: tolerance %g is too big, "
"using arc-max 2 * radius == %g", tol, maxErr);
}
- halfAngle = acos( 1.0 - maxErr / radius );
+ do {
+ halfAngle = acos( 1.0 - maxErr / radius );
+ /* TODO: avoid a loop here, going rather straight to
+ * a minimum angle value */
+ if ( halfAngle != 0 ) break;
+ LWDEBUGF(2, "lwarc_linearize: tolerance %g is too small for this arc"
+ " to compute approximation angle, doubling it", maxErr);
+ maxErr *= 2;
+ } while(1);
increment = 2 * halfAngle;
LWDEBUGF(2, "lwarc_linearize: maxDiff:%g, radius:%g, halfAngle:%g, increment:%g (%g degrees)", tol, radius, halfAngle, increment, increment*180/M_PI);
}}