PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ test_lwcurve_linearize()

static void test_lwcurve_linearize ( void  )
static

Definition at line 50 of file cu_lwstroke.c.

51 {
52  LWGEOM *in;
53  LWGEOM *out, *out2;
54  char *str;
55  int toltype;
56 
57  /***********************************************************
58  *
59  * Segments per quadrant tolerance type
60  *
61  ***********************************************************/
62 
64 
65  /* 2 quadrants arc (180 degrees, PI radians) */
66  in = lwgeom_from_text("CIRCULARSTRING(0 0,100 100,200 0)");
67  /* 2 segment per quadrant */
68  out = lwcurve_linearize(in, 2, toltype, 0);
69  str = lwgeom_to_text(out, 2);
70  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,30 70,100 100,170 70,200 0)");
71  lwfree(str);
72  lwgeom_free(out);
73 
74  /* 3 segment per quadrant */
75  out = lwcurve_linearize(in, 3, toltype, 0);
76  str = lwgeom_to_text(out, 2);
77  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,14 50,50 86,100 100,150 86,186 50,200 0)");
78  lwfree(str);
79  lwgeom_free(out);
80  /* 3.5 segment per quadrant (invalid) */
82  out = lwcurve_linearize(in, 3.5, toltype, 0);
83  CU_ASSERT( out == NULL );
84  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: segments per quadrant must be an integer value, got 3.5");
85  lwgeom_free(out);
86  /* -2 segment per quadrant (invalid) */
88  out = lwcurve_linearize(in, -2, toltype, 0);
89  CU_ASSERT( out == NULL );
90  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: segments per quadrant must be at least 1, got -2");
91  lwgeom_free(out);
92  /* 0 segment per quadrant (invalid) */
94  out = lwcurve_linearize(in, 0, toltype, 0);
95  CU_ASSERT( out == NULL );
96  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: segments per quadrant must be at least 1, got 0");
97  lwgeom_free(out);
98  lwgeom_free(in);
99 
100  /* 1.5 quadrants arc (145 degrees - PI*3/4 radians ) */
101  in = lwgeom_from_text("CIRCULARSTRING(29.2893218813453 70.7106781186548,100 100,200 0)");
102  /* 2 segment per quadrant */
103  out = lwcurve_linearize(in, 2, toltype, 0);
104  str = lwgeom_to_text(out, 2);
105  ASSERT_STRING_EQUAL(str, "LINESTRING(30 70,100 100,170 70,200 0)");
106  lwfree(str);
107  lwgeom_free(out);
108  /* 3 segment per quadrant - non-symmetric */
109  out = lwcurve_linearize(in, 3, toltype, 0);
110  str = lwgeom_to_text(out, 2);
111  ASSERT_STRING_EQUAL(str, "LINESTRING(30 70,74 96,126 96,170 70,196 26,200 0)");
112  lwfree(str);
113  lwgeom_free(out);
114 
115  /* 3 segment per quadrant - symmetric */
116  out = lwcurve_linearize(in, 3, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
117  str = lwgeom_to_text(out, 2);
118  ASSERT_STRING_EQUAL(str, "LINESTRING(30 70,70 96,116 98,158 80,190 46,200 0)");
119  lwfree(str);
120  lwgeom_free(out);
121 
122 #ifndef SKIP_TEST_RETAIN_ANGLE
123  /* 3 segment per quadrant - symmetric/retain_angle */
124  out = lwcurve_linearize(in, 3, toltype,
127  );
128  str = lwgeom_to_text(out, 2);
129  ASSERT_STRING_EQUAL(str, "LINESTRING(30 70,40 80,86 100,138 92,180 60,200 14,200 0)");
130  lwfree(str);
131  lwgeom_free(out);
132 #endif /* SKIP_TEST_RETAIN_ANGLE */
133 
134  lwgeom_free(in);
135 
136  /* 10 segments per quadrant (circular) */
137  in = lwgeom_from_text("CIRCULARSTRING(0 0,1 0,0 0)");
138  // out = lwcurve_linearize(in, 10, toltype, 0);
139  out = lwcurve_linearize(in, 10, toltype, 0);
140  // printf("OUT: %s\n", lwgeom_to_wkt(out, WKT_EXTENDED, 5, NULL));
142  lwgeom_free(out);
143  lwgeom_free(in);
144 
145  /***********************************************************
146  *
147  * Maximum deviation tolerance type
148  *
149  ***********************************************************/
150 
152 
153  in = lwgeom_from_text("CIRCULARSTRING(0 0,100 100,200 0)");
154 
155  /* Maximum of 10 units of difference, asymmetric */
156  out = lwcurve_linearize(in, 10, toltype, 0);
157  str = lwgeom_to_text(out, 2);
158  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,38 78,124 98,190 42,200 0)");
159  lwfree(str);
160  lwgeom_free(out);
161  /* Maximum of 0 units of difference (invalid) */
163  out = lwcurve_linearize(in, 0, toltype, 0);
164  CU_ASSERT( out == NULL );
165  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max deviation must be bigger than 0, got 0");
166  /* Maximum of -2 units of difference (invalid) */
168  out = lwcurve_linearize(in, -2, toltype, 0);
169  CU_ASSERT( out == NULL );
170  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max deviation must be bigger than 0, got -2");
171  /* Maximum of 10 units of difference, symmetric */
172  out = lwcurve_linearize(in, 10, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
173  str = lwgeom_to_text(out, 2);
174  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,30 70,100 100,170 70,200 0)");
175  lwfree(str);
176  lwgeom_free(out);
177  /* Maximum of 20 units of difference, asymmetric */
178  out = lwcurve_linearize(in, 20, toltype, 0);
179  str = lwgeom_to_text(out, 2);
180  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,72 96,184 54,200 0)");
181  lwfree(str);
182  lwgeom_free(out);
183  /* Maximum of 20 units of difference, symmetric */
184  out = lwcurve_linearize(in, 20, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
185  str = lwgeom_to_text(out, 2);
186  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,50 86,150 86,200 0)");
187  lwfree(str);
188  lwgeom_free(out);
189 
190 #ifndef SKIP_TEST_RETAIN_ANGLE
191  /* Maximum of 20 units of difference, symmetric/retain angle */
192  out = lwcurve_linearize(in, 20, toltype,
195  );
196  str = lwgeom_to_text(out, 2);
197  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,4 28,100 100,196 28,200 0)");
198  lwfree(str);
199  lwgeom_free(out);
200 #endif /* SKIP_TEST_RETAIN_ANGLE */
201 
202  lwgeom_free(in);
203 
204  /*
205  * Clockwise ~90 degrees south-west to north-west quadrants
206  * starting at ~22 degrees west of vertical line
207  *
208  * See https://trac.osgeo.org/postgis/ticket/3772
209  */
211  in = lwgeom_from_text("CIRCULARSTRING(71.96 -65.64,22.2 -18.52,20 50)");
212 
213  /* 4 units of max deviation - symmetric */
214  out = lwcurve_linearize(in, 4, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
215  str = lwgeom_to_text(out, 2);
216  ASSERT_STRING_EQUAL(str, "LINESTRING(72 -66,34 -38,16 4,20 50)");
217  lwfree(str);
218  lwgeom_free(out);
219  lwgeom_free(in);
220 
221  /*
222  * Clockwise ~90 degrees north-west to south-west quadrants
223  * starting at ~22 degrees west of vertical line
224  *
225  * See https://trac.osgeo.org/postgis/ticket/3772
226  */
228  in = lwgeom_from_text("CIRCULARSTRING(20 50,22.2 -18.52,71.96 -65.64)");
229 
230  /* 4 units of max deviation - symmetric */
231  out = lwcurve_linearize(in, 4, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
232  str = lwgeom_to_text(out, 2);
233  ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,16 4,34 -38,72 -66)");
234  lwfree(str);
235  lwgeom_free(out);
236 
237  /* max deviation bigger than twice the radius
238  * we really only want to make sure NOT to enter
239  * an infinite loop here.
240  * See https://trac.osgeo.org/postgis/ticket/4031
241  */
242  out = lwcurve_linearize(in, 500, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
243  str = lwgeom_to_text(out, 2);
244  ASSERT_STRING_EQUAL(str, "LINESTRING(20 50,22 -18,72 -66)");
245  lwfree(str);
246  lwgeom_free(out);
247 
248  lwgeom_free(in);
249 
250  /*
251  * ROBUSTNESS: big radius, small tolerance
252  * See https://trac.osgeo.org/postgis/ticket/4058
253  * NOTE: we are really only interested in not entering
254  * an infinite loop here
255  */
257  in = lwgeom_from_text("CIRCULARSTRING("
258  "2696000.553 1125699.831999999936670, "
259  "2695950.552000000141561 1125749.833000000100583, "
260  "2695865.195999999996275 1125835.189000)");
261  out = lwcurve_linearize(in, 0.0001, toltype, 0);
262  str = lwgeom_to_text(out, 2);
263  ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
264  lwfree(str);
265  lwgeom_free(out);
266  out = lwcurve_linearize(in, 0.0001, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
267  str = lwgeom_to_text(out, 2);
268  ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
269  lwfree(str);
270  lwgeom_free(out);
271 #ifndef SKIP_TEST_RETAIN_ANGLE
272  out = lwcurve_linearize(in, 0.0001, toltype,
275  );
276  str = lwgeom_to_text(out, 2);
277  ASSERT_STRING_EQUAL(str, "LINESTRING(2696000 1125700,2695932 1125768,2695866 1125836)");
278  lwfree(str);
279  lwgeom_free(out);
280 #endif /* SKIP_TEST_RETAIN_ANGLE */
281  lwgeom_free(in);
282 
283  /***********************************************************
284  *
285  * Maximum angle tolerance type
286  *
287  ***********************************************************/
288 
290 
291  in = lwgeom_from_text("CIRCULARSTRING(0 0,100 100,200 0)");
292 
293  /* Maximum of 45 degrees per segment, asymmetric */
294  out = lwcurve_linearize(in, M_PI / 4.0, toltype, 0);
295  str = lwgeom_to_text(out, 2);
296  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,30 70,100 100,170 70,200 0)");
297  lwfree(str);
298  lwgeom_free(out);
299  /* Maximum of 0 degrees per segment (invalid) */
301  out = lwcurve_linearize(in, 0, toltype, 0);
302  CU_ASSERT( out == NULL );
303  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got 0");
304  /* Maximum of -2 degrees per segment (invalid) */
306  out = lwcurve_linearize(in, -2, toltype, 0);
307  CU_ASSERT( out == NULL );
308  ASSERT_STRING_EQUAL(cu_error_msg, "lwarc_linearize: max angle must be bigger than 0, got -2");
309  /* Maximum of 360 degrees per segment, just return minimum of two segments... */
311  out = lwcurve_linearize(in, M_PI*4, toltype, 0);
312  str = lwgeom_to_text(out, 2);
313  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,100 100,200 0)");
314  lwfree(str);
315  lwgeom_free(out);
316  /* Maximum of 70 degrees per segment, asymmetric */
317  out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, 0);
318  str = lwgeom_to_text(out, 2);
319  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,66 94,176 64,200 0)");
320  lwfree(str);
321  lwgeom_free(out);
322  /* Maximum of 70 degrees per segment, symmetric */
323  out = lwcurve_linearize(in, 70 * M_PI / 180, toltype, LW_LINEARIZE_FLAG_SYMMETRIC);
324  str = lwgeom_to_text(out, 2);
325  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,50 86,150 86,200 0)");
326  lwfree(str);
327  lwgeom_free(out);
328 
329 #ifndef SKIP_TEST_RETAIN_ANGLE
330  /* Maximum of 70 degrees, symmetric/retain angle */
331  out = lwcurve_linearize(in, 70 * M_PI / 180, toltype,
334  );
335  str = lwgeom_to_text(out, 2);
336  ASSERT_STRING_EQUAL(str, "LINESTRING(0 0,6 34,100 100,194 34,200 0)");
337  lwfree(str);
338  lwgeom_free(out);
339 #endif /* SKIP_TEST_RETAIN_ANGLE */
340 
341  lwgeom_free(in);
342 
343  /***********************************************************
344  *
345  * Direction neutrality
346  *
347  ***********************************************************/
348 
349  in = lwgeom_from_text("CIRCULARSTRING(71.96 -65.64,22.2 -18.52,20 50)");
350  out = lwcurve_linearize(in, M_PI/4.0,
354  out2 = lwcurve_linearize(in, M_PI/4.0,
358  if ( ! lwgeom_same(out, out2) )
359  {
360  fprintf(stderr, "linearization is not direction neutral:\n");
361  str = lwgeom_to_wkt(out, WKT_ISO, 18, NULL);
362  fprintf(stderr, "OUT1: %s\n", str);
363  lwfree(str);
364  str = lwgeom_to_wkt(out2, WKT_ISO, 18, NULL);
365  fprintf(stderr, "OUT2: %s\n", str);
366  lwfree(str);
367  }
368  CU_ASSERT( lwgeom_same(out, out2) );
369  lwgeom_free(out2);
370  lwgeom_free(out);
371  lwgeom_free(in);
372 }
static char * lwgeom_to_text(const LWGEOM *geom, int prec)
Definition: cu_lwstroke.c:34
static LWGEOM * lwgeom_from_text(const char *str)
Definition: cu_lwstroke.c:26
void cu_error_msg_reset()
char cu_error_msg[MAX_CUNIT_ERROR_LENGTH+1]
#define ASSERT_INT_EQUAL(o, e)
#define ASSERT_STRING_EQUAL(o, e)
@ LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE
Tolerance expresses the maximum angle between the radii generating approximation line vertices,...
Definition: liblwgeom.h:2278
@ LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD
Tolerance expresses the number of segments to use for each quarter of circle (quadrant).
Definition: liblwgeom.h:2263
@ LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION
Tolerance expresses the maximum distance between an arbitrary point on the curve and the closest poin...
Definition: liblwgeom.h:2270
char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
geom1 same as geom2 iff
Definition: lwgeom.c:573
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1138
LWGEOM * lwcurve_linearize(const LWGEOM *geom, double tol, LW_LINEARIZE_TOLERANCE_TYPE type, int flags)
Definition: lwstroke.c:826
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1229
@ LW_LINEARIZE_FLAG_SYMMETRIC
Symmetric linearization means that the output vertices would be the same no matter the order of the p...
Definition: liblwgeom.h:2287
@ LW_LINEARIZE_FLAG_RETAIN_ANGLE
Retain angle instructs the engine to try its best to retain the requested angle between generating ra...
Definition: liblwgeom.h:2307
void lwfree(void *mem)
Definition: lwutil.c:242
#define WKT_ISO
Definition: liblwgeom.h:2130
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:676
void lwgeom_reverse_in_place(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:102
#define str(s)

References ASSERT_INT_EQUAL, ASSERT_STRING_EQUAL, cu_error_msg, cu_error_msg_reset(), LW_LINEARIZE_FLAG_RETAIN_ANGLE, LW_LINEARIZE_FLAG_SYMMETRIC, LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE, LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION, LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD, lwcurve_linearize(), lwfree(), lwgeom_count_vertices(), lwgeom_free(), lwgeom_from_text(), lwgeom_reverse_in_place(), lwgeom_same(), lwgeom_to_text(), lwgeom_to_wkt(), str, and WKT_ISO.

Referenced by lwstroke_suite_setup().

Here is the call graph for this function:
Here is the caller graph for this function: