PostGIS  3.7.0dev-r@@SVN_REVISION@@
lwline.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2012 Sandro Santilli <strk@kbt.io>
22  * Copyright (C) 2001-2006 Refractions Research Inc.
23  *
24  **********************************************************************/
25 
26 
27 /* basic LWLINE functions */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "liblwgeom_internal.h"
33 #include "lwgeom_log.h"
34 
35 
36 
37 /*
38  * Construct a new LWLINE. points will *NOT* be copied
39  * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
40  */
41 LWLINE *
42 lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
43 {
44  LWLINE *result = (LWLINE *)lwalloc(sizeof(LWLINE));
45  result->type = LINETYPE;
46  result->flags = points->flags;
47  FLAGS_SET_BBOX(result->flags, bbox?1:0);
48  result->srid = srid;
49  result->points = points;
50  result->bbox = bbox;
51  return result;
52 }
53 
54 LWLINE *
55 lwline_construct_empty(int32_t srid, char hasz, char hasm)
56 {
57  LWLINE *result = lwalloc(sizeof(LWLINE));
58  result->type = LINETYPE;
59  result->flags = lwflags(hasz,hasm,0);
60  result->srid = srid;
61  result->points = ptarray_construct_empty(hasz, hasm, 1);
62  result->bbox = NULL;
63  return result;
64 }
65 
66 
67 void lwline_free (LWLINE *line)
68 {
69  if ( ! line ) return;
70 
71  if ( line->bbox )
72  lwfree(line->bbox);
73  if ( line->points )
74  ptarray_free(line->points);
75  lwfree(line);
76 }
77 
78 
79 void printLWLINE(LWLINE *line)
80 {
81  lwnotice("LWLINE {");
82  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(line->flags));
83  lwnotice(" srid = %i", (int)line->srid);
84  printPA(line->points);
85  lwnotice("}");
86 }
87 
88 /* @brief Clone LWLINE object. Serialized point lists are not copied.
89  *
90  * @see ptarray_clone
91  */
92 LWLINE *
94 {
95  LWLINE *ret = lwalloc(sizeof(LWLINE));
96 
97  LWDEBUGF(2, "lwline_clone called with %p", g);
98 
99  memcpy(ret, g, sizeof(LWLINE));
100 
101  ret->points = ptarray_clone(g->points);
102 
103  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
104  return ret;
105 }
106 
107 /* Deep clone LWLINE object. POINTARRAY *is* copied. */
108 LWLINE *
110 {
111  LWLINE *ret = lwalloc(sizeof(LWLINE));
112 
113  LWDEBUGF(2, "lwline_clone_deep called with %p", g);
114  memcpy(ret, g, sizeof(LWLINE));
115 
116  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
117  if ( g->points ) ret->points = ptarray_clone_deep(g->points);
118  FLAGS_SET_READONLY(ret->flags,0);
119 
120  return ret;
121 }
122 
123 
124 void
126 {
128 }
129 
130 
131 LWLINE *
132 lwline_segmentize2d(const LWLINE *line, double dist)
133 {
134  POINTARRAY *segmentized = ptarray_segmentize2d(line->points, dist);
135  if ( ! segmentized ) return NULL;
136  return lwline_construct(line->srid, NULL, segmentized);
137 }
138 
139 /* check coordinate equality */
140 char
141 lwline_same(const LWLINE *l1, const LWLINE *l2)
142 {
143  return ptarray_same(l1->points, l2->points);
144 }
145 
146 /*
147  * Construct a LWLINE from an array of point and line geometries
148  * LWLINE dimensions are large enough to host all input dimensions.
149  */
150 LWLINE *
151 lwline_from_lwgeom_array(int32_t srid, uint32_t ngeoms, LWGEOM **geoms)
152 {
153  uint32_t i;
154  int hasz = LW_FALSE;
155  int hasm = LW_FALSE;
156  POINTARRAY *pa;
157  LWLINE *line;
158  POINT4D pt;
159  LWPOINTITERATOR* it;
160 
161  /*
162  * Find output dimensions, check integrity
163  */
164  for (i=0; i<ngeoms; i++)
165  {
166  if ( FLAGS_GET_Z(geoms[i]->flags) ) hasz = LW_TRUE;
167  if ( FLAGS_GET_M(geoms[i]->flags) ) hasm = LW_TRUE;
168  if ( hasz && hasm ) break; /* Nothing more to learn! */
169  }
170 
171  /*
172  * ngeoms should be a guess about how many points we have in input.
173  * It's an underestimate for lines and multipoints */
174  pa = ptarray_construct_empty(hasz, hasm, ngeoms);
175 
176  for ( i=0; i < ngeoms; i++ )
177  {
178  LWGEOM *g = geoms[i];
179 
180  if ( lwgeom_is_empty(g) ) continue;
181 
182  if ( g->type == POINTTYPE )
183  {
184  lwpoint_getPoint4d_p((LWPOINT*)g, &pt);
185  ptarray_append_point(pa, &pt, LW_TRUE);
186  }
187  else if ( g->type == LINETYPE )
188  {
189  /*
190  * Append the new line points, de-duplicating against the previous points.
191  * Duplicated points internal to the linestring are untouched.
192  */
193  ptarray_append_ptarray(pa, ((LWLINE*)g)->points, -1);
194  }
195  else if ( g->type == MULTILINETYPE )
196  {
197  LWMLINE *mline = lwgeom_as_lwmline(g);
198  for ( uint32_t j = 0; j < mline->ngeoms; j++ )
199  {
200  LWLINE *line = mline->geoms[j];
201  if (lwline_is_empty(line)) continue;
202  ptarray_append_ptarray(pa, line->points, -1);
203  }
204  }
205  else if ( g->type == MULTIPOINTTYPE )
206  {
207  it = lwpointiterator_create(g);
208  while(lwpointiterator_next(it, &pt))
209  {
210  ptarray_append_point(pa, &pt, LW_TRUE);
211  }
213  }
214  else
215  {
216  ptarray_free(pa);
217  lwerror("lwline_from_ptarray: invalid input type: %s", lwtype_name(g->type));
218  return NULL;
219  }
220  }
221 
222  if ( pa->npoints > 0 )
223  line = lwline_construct(srid, NULL, pa);
224  else {
225  /* Is this really any different from the above ? */
226  ptarray_free(pa);
227  line = lwline_construct_empty(srid, hasz, hasm);
228  }
229 
230  return line;
231 }
232 
233 /*
234  * Construct a LWLINE from an array of LWPOINTs
235  * LWLINE dimensions are large enough to host all input dimensions.
236  */
237 LWLINE *
238 lwline_from_ptarray(int32_t srid, uint32_t npoints, LWPOINT **points)
239 {
240  uint32_t i;
241  int hasz = LW_FALSE;
242  int hasm = LW_FALSE;
243  POINTARRAY *pa;
244  LWLINE *line;
245  POINT4D pt;
246 
247  /*
248  * Find output dimensions, check integrity
249  */
250  for (i=0; i<npoints; i++)
251  {
252  if ( points[i]->type != POINTTYPE )
253  {
254  lwerror("lwline_from_ptarray: invalid input type: %s", lwtype_name(points[i]->type));
255  return NULL;
256  }
257  if ( FLAGS_GET_Z(points[i]->flags) ) hasz = LW_TRUE;
258  if ( FLAGS_GET_M(points[i]->flags) ) hasm = LW_TRUE;
259  if ( hasz && hasm ) break; /* Nothing more to learn! */
260  }
261 
262  pa = ptarray_construct_empty(hasz, hasm, npoints);
263 
264  for ( i=0; i < npoints; i++ )
265  {
266  if ( ! lwpoint_is_empty(points[i]) )
267  {
268  lwpoint_getPoint4d_p(points[i], &pt);
269  ptarray_append_point(pa, &pt, LW_TRUE);
270  }
271  }
272 
273  if ( pa->npoints > 0 )
274  line = lwline_construct(srid, NULL, pa);
275  else
276  line = lwline_construct_empty(srid, hasz, hasm);
277 
278  return line;
279 }
280 
281 /*
282  * Construct a LWLINE from a LWMPOINT
283  */
284 LWLINE *
285 lwline_from_lwmpoint(int32_t srid, const LWMPOINT *mpoint)
286 {
287  uint32_t i;
288  POINTARRAY *pa = NULL;
289  LWGEOM *lwgeom = (LWGEOM*)mpoint;
290  POINT4D pt;
291 
292  char hasz = lwgeom_has_z(lwgeom);
293  char hasm = lwgeom_has_m(lwgeom);
294  uint32_t npoints = mpoint->ngeoms;
295 
296  if ( lwgeom_is_empty(lwgeom) )
297  {
298  return lwline_construct_empty(srid, hasz, hasm);
299  }
300 
301  pa = ptarray_construct(hasz, hasm, npoints);
302 
303  for (i=0; i < npoints; i++)
304  {
305  getPoint4d_p(mpoint->geoms[i]->point, 0, &pt);
306  ptarray_set_point4d(pa, i, &pt);
307  }
308 
309  LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points", mpoint->ngeoms);
310 
311  return lwline_construct(srid, NULL, pa);
312 }
313 
318 LWPOINT*
319 lwline_get_lwpoint(const LWLINE *line, uint32_t where)
320 {
321  POINT4D pt;
322  LWPOINT *lwpoint;
323  POINTARRAY *pa;
324 
325  if ( lwline_is_empty(line) || where >= line->points->npoints )
326  return NULL;
327 
329  pt = getPoint4d(line->points, where);
330  ptarray_append_point(pa, &pt, LW_TRUE);
331  lwpoint = lwpoint_construct(line->srid, NULL, pa);
332  return lwpoint;
333 }
334 
335 
336 int
337 lwline_add_lwpoint(LWLINE *line, LWPOINT *point, uint32_t where)
338 {
339  POINT4D pt;
340  getPoint4d_p(point->point, 0, &pt);
341 
342  if ( ptarray_insert_point(line->points, &pt, where) != LW_SUCCESS )
343  return LW_FAILURE;
344 
345  /* Update the bounding box */
346  if ( line->bbox )
347  {
348  lwgeom_refresh_bbox((LWGEOM*)line);
349  }
350 
351  return LW_SUCCESS;
352 }
353 
354 
355 
356 LWLINE *
357 lwline_removepoint(LWLINE *line, uint32_t index)
358 {
359  POINTARRAY *newpa;
360  LWLINE *ret;
361 
362  newpa = ptarray_removePoint(line->points, index);
363 
364  ret = lwline_construct(line->srid, NULL, newpa);
365  lwgeom_add_bbox((LWGEOM *) ret);
366 
367  return ret;
368 }
369 
370 /*
371  * Note: input will be changed, make sure you have permissions for this.
372  */
373 void
374 lwline_setPoint4d(LWLINE *line, uint32_t index, POINT4D *newpoint)
375 {
376  ptarray_set_point4d(line->points, index, newpoint);
377  /* Update the box, if there is one to update */
378  if ( line->bbox )
379  {
380  lwgeom_refresh_bbox((LWGEOM*)line);
381  }
382 }
383 
388 LWLINE*
389 lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
390 {
391  int i = 0;
392  int hasm = 0, hasz = 0;
393  int npoints = 0;
394  double length = 0.0;
395  double length_so_far = 0.0;
396  double m_range = m_end - m_start;
397  double m;
398  POINTARRAY *pa = NULL;
399  POINT3DZ p1, p2;
400 
401  if ( lwline->type != LINETYPE )
402  {
403  lwerror("lwline_construct_from_lwline: only line types supported");
404  return NULL;
405  }
406 
407  hasz = FLAGS_GET_Z(lwline->flags);
408  hasm = 1;
409 
410  /* Null points or npoints == 0 will result in empty return geometry */
411  if ( lwline->points )
412  {
413  npoints = lwline->points->npoints;
414  length = ptarray_length_2d(lwline->points);
415  getPoint3dz_p(lwline->points, 0, &p1);
416  }
417 
418  pa = ptarray_construct(hasz, hasm, npoints);
419 
420  for ( i = 0; i < npoints; i++ )
421  {
422  POINT4D q;
423  POINT2D a, b;
424  getPoint3dz_p(lwline->points, i, &p2);
425  a.x = p1.x;
426  a.y = p1.y;
427  b.x = p2.x;
428  b.y = p2.y;
429  length_so_far += distance2d_pt_pt(&a, &b);
430  if ( length > 0.0 )
431  m = m_start + m_range * length_so_far / length;
432  /* #3172, support (valid) zero-length inputs */
433  else if ( length == 0.0 && npoints > 1 )
434  m = m_start + m_range * i / (npoints-1);
435  else
436  m = 0.0;
437  q.x = p2.x;
438  q.y = p2.y;
439  q.z = p2.z;
440  q.m = m;
441  ptarray_set_point4d(pa, i, &q);
442  p1 = p2;
443  }
444 
445  return lwline_construct(lwline->srid, NULL, pa);
446 }
447 
448 LWGEOM*
449 lwline_remove_repeated_points(const LWLINE *lwline, double tolerance)
450 {
451  return lwgeom_remove_repeated_points((LWGEOM*)lwline, tolerance);
452 }
453 
454 int
456 {
457  if (FLAGS_GET_Z(line->flags))
458  return ptarray_is_closed_3d(line->points);
459 
460  return ptarray_is_closed_2d(line->points);
461 }
462 
463 int
465 {
466  if (!FLAGS_GET_M(line->flags))
467  {
468  lwnotice("Line does not have M dimension");
469  return LW_FALSE;
470  }
471 
472  uint32_t n = line->points->npoints;
473 
474  if (n < 2)
475  return LW_TRUE; /* empty or single-point are "good" */
476 
477  double m = -1 * FLT_MAX;
478  for (uint32_t i = 0; i < n; ++i)
479  {
480  POINT3DM p;
481  if (!getPoint3dm_p(line->points, i, &p))
482  return LW_FALSE;
483  if (p.m <= m)
484  {
485  lwnotice(
486  "Measure of vertex %d (%g) not bigger than measure of vertex %d (%g)", i, p.m, i - 1, m);
487  return LW_FALSE;
488  }
489  m = p.m;
490  }
491 
492  return LW_TRUE;
493 }
494 
495 LWLINE*
496 lwline_force_dims(const LWLINE *line, int hasz, int hasm, double zval, double mval)
497 {
498  POINTARRAY *pdims = NULL;
499  LWLINE *lineout;
500 
501  /* Return 2D empty */
502  if( lwline_is_empty(line) )
503  {
504  lineout = lwline_construct_empty(line->srid, hasz, hasm);
505  }
506  else
507  {
508  pdims = ptarray_force_dims(line->points, hasz, hasm, zval, mval);
509  lineout = lwline_construct(line->srid, NULL, pdims);
510  }
511  lineout->type = line->type;
512  return lineout;
513 }
514 
515 uint32_t lwline_count_vertices(const LWLINE *line)
516 {
517  assert(line);
518  if ( ! line->points )
519  return 0;
520  return line->points->npoints;
521 }
522 
523 double lwline_length(const LWLINE *line)
524 {
525  if ( lwline_is_empty(line) )
526  return 0.0;
527  return ptarray_length(line->points);
528 }
529 
530 double lwline_length_2d(const LWLINE *line)
531 {
532  if ( lwline_is_empty(line) )
533  return 0.0;
534  return ptarray_length_2d(line->points);
535 }
536 
537 
538 POINTARRAY* lwline_interpolate_points(const LWLINE *line, double length_fraction, char repeat) {
539  POINT4D pt;
540  uint32_t i;
541  uint32_t points_to_interpolate;
542  uint32_t points_found = 0;
543  double length;
544  double length_fraction_increment = length_fraction;
545  double length_fraction_consumed = 0;
546  char has_z = (char) lwgeom_has_z(lwline_as_lwgeom(line));
547  char has_m = (char) lwgeom_has_m(lwline_as_lwgeom(line));
548  const POINTARRAY* ipa = line->points;
549  POINTARRAY* opa;
550 
551  /* Empty.InterpolatePoint == Point Empty */
552  if ( lwline_is_empty(line) )
553  {
554  return ptarray_construct_empty(has_z, has_m, 0);
555  }
556 
557  /* If distance is one of the two extremes, return the point on that
558  * end rather than doing any computations
559  */
560  if ( length_fraction == 0.0 || length_fraction == 1.0 )
561  {
562  if ( length_fraction == 0.0 )
563  getPoint4d_p(ipa, 0, &pt);
564  else
565  getPoint4d_p(ipa, ipa->npoints-1, &pt);
566 
567  opa = ptarray_construct(has_z, has_m, 1);
568  ptarray_set_point4d(opa, 0, &pt);
569 
570  return opa;
571  }
572 
573  /* Interpolate points along the line */
574  length = ptarray_length_2d(ipa);
575  points_to_interpolate = repeat ? (uint32_t) floor(1 / length_fraction) : 1;
576  opa = ptarray_construct(has_z, has_m, points_to_interpolate);
577 
578  const POINT2D* p1 = getPoint2d_cp(ipa, 0);
579  for ( i = 0; i < ipa->npoints - 1 && points_found < points_to_interpolate; i++ )
580  {
581  const POINT2D* p2 = getPoint2d_cp(ipa, i+1);
582  double segment_length_frac = distance2d_pt_pt(p1, p2) / length;
583 
584  /* If our target distance is before the total length we've seen
585  * so far. create a new point some distance down the current
586  * segment.
587  */
588  while ( length_fraction < length_fraction_consumed + segment_length_frac && points_found < points_to_interpolate )
589  {
590  POINT4D p1_4d = getPoint4d(ipa, i);
591  POINT4D p2_4d = getPoint4d(ipa, i+1);
592 
593  double segment_fraction = (length_fraction - length_fraction_consumed) / segment_length_frac;
594  interpolate_point4d(&p1_4d, &p2_4d, &pt, segment_fraction);
595  ptarray_set_point4d(opa, points_found++, &pt);
596  length_fraction += length_fraction_increment;
597  }
598 
599  length_fraction_consumed += segment_length_frac;
600 
601  p1 = p2;
602  }
603 
604  /* Return the last point on the line. This shouldn't happen, but
605  * could if there's some floating point rounding errors. */
606  if (points_found < points_to_interpolate) {
607  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
608  ptarray_set_point4d(opa, points_found, &pt);
609  }
610 
611  return opa;
612 }
613 
614 extern LWPOINT *
616 {
617  double length, slength, tlength;
618  POINTARRAY *ipa;
619  POINT4D pt;
620  int nsegs, i;
621  LWGEOM *geom = lwline_as_lwgeom(line);
622  int has_z = lwgeom_has_z(geom);
623  int has_m = lwgeom_has_m(geom);
624  ipa = line->points;
625 
626  /* Empty.InterpolatePoint == Point Empty */
627  if (lwline_is_empty(line))
628  {
629  return lwpoint_construct_empty(line->srid, has_z, has_m);
630  }
631 
632  /* If distance is one of the two extremes, return the point on that
633  * end rather than doing any expensive computations
634  */
635  if (distance == 0.0 || distance == 1.0)
636  {
637  if (distance == 0.0)
638  getPoint4d_p(ipa, 0, &pt);
639  else
640  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
641 
642  return lwpoint_make(line->srid, has_z, has_m, &pt);
643  }
644 
645  /* Interpolate a point on the line */
646  nsegs = ipa->npoints - 1;
647  length = ptarray_length(ipa);
648  tlength = 0;
649  for (i = 0; i < nsegs; i++)
650  {
651  POINT4D p1, p2;
652  POINT4D *p1ptr = &p1, *p2ptr = &p2; /* don't break
653  * strict-aliasing rules
654  */
655 
656  getPoint4d_p(ipa, i, &p1);
657  getPoint4d_p(ipa, i + 1, &p2);
658 
659  /* Find the relative length of this segment */
660  slength = distance3d_pt_pt((POINT3D *)p1ptr, (POINT3D *)p2ptr) / length;
661 
662  /* If our target distance is before the total length we've seen
663  * so far. create a new point some distance down the current
664  * segment.
665  */
666  if (distance < tlength + slength)
667  {
668  double dseg = (distance - tlength) / slength;
669  interpolate_point4d(&p1, &p2, &pt, dseg);
670  return lwpoint_make(line->srid, has_z, has_m, &pt);
671  }
672  tlength += slength;
673  }
674 
675  /* Return the last point on the line. This shouldn't happen, but
676  * could if there's some floating point rounding errors. */
677  getPoint4d_p(ipa, ipa->npoints - 1, &pt);
678  return lwpoint_make(line->srid, has_z, has_m, &pt);
679 }
680 
681 extern LWLINE *
682 lwline_extend(const LWLINE *line, double distance_forward, double distance_backward)
683 {
684  POINTARRAY *pa, *opa;
685  POINT4D p00, p01, p10, p11;
686  POINT4D p_start, p_end;
687  uint32_t i;
688  bool forward = false, backward = false;
689 
690  if (distance_forward < 0 || distance_backward < 0)
691  lwerror("%s: distances must be non-negative", __func__);
692 
693  if (!line || lwline_is_empty(line) || lwline_count_vertices(line) < 2)
694  {
695  lwerror("%s: line must have at least two points", __func__);
696  }
697 
698  pa = line->points;
699  if (distance_backward > 0.0)
700  {
701  i = 0;
702  /* Get two distinct points at start of pointarray */
703  getPoint4d_p(pa, i++, &p00);
704  getPoint4d_p(pa, i, &p01);
705  while(p4d_same(&p00, &p01))
706  {
707  if (i == pa->npoints - 1)
708  {
709  lwerror("%s: line must have at least two distinct points", __func__);
710  }
711  i++;
712  getPoint4d_p(pa, i, &p01);
713  }
714  project_pt_pt(&p01, &p00, distance_backward, &p_start);
715  backward = true;
716  }
717 
718  if (distance_forward > 0.0)
719  {
720  i = pa->npoints - 1;
721  /* Get two distinct points at end of pointarray */
722  getPoint4d_p(pa, i--, &p10);
723  getPoint4d_p(pa, i, &p11);
724  while(p4d_same(&p10, &p11))
725  {
726  if (i == 0)
727  {
728  lwerror("%s: line must have at least two distinct points", __func__);
729  }
730  i--;
731  getPoint4d_p(pa, i, &p11);
732  }
733  project_pt_pt(&p11, &p10, distance_forward, &p_end);
734  forward = true;
735  }
736 
738 
739  if (backward)
740  {
741  ptarray_append_point(opa, &p_start, true);
742  }
743  ptarray_append_ptarray(opa, pa, -1.0);
744  if (forward)
745  {
746  ptarray_append_point(opa, &p_end, true);
747  }
748  return lwline_construct(line->srid, NULL, opa);
749 }
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: gbox.c:438
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoint.c:151
void lwgeom_refresh_bbox(LWGEOM *lwgeom)
Drop current bbox and calculate a fresh one.
Definition: lwgeom.c:735
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
Definition: lwpoint.c:57
POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n)
Definition: lwgeom_api.c:107
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:367
#define LW_FALSE
Definition: liblwgeom.h:94
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
Definition: measures.c:2344
LWPOINTITERATOR * lwpointiterator_create(const LWGEOM *g)
Create a new LWPOINTITERATOR over supplied LWGEOM*.
Definition: lwiterator.c:243
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
Definition: ptarray.c:177
#define LW_FAILURE
Definition: liblwgeom.h:96
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:723
#define MULTILINETYPE
Definition: liblwgeom.h:106
int lwpointiterator_next(LWPOINTITERATOR *s, POINT4D *p)
Attempts to assign the next point in the iterator to p, and advances the iterator to the next point.
Definition: lwiterator.c:210
#define LINETYPE
Definition: liblwgeom.h:103
void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F)
Find interpolation point I between point A and point B so that the len(AI) == len(AB)*F and I falls o...
Definition: lwgeom_api.c:646
POINTARRAY * ptarray_removePoint(POINTARRAY *pa, uint32_t where)
Remove a point from a pointarray.
Definition: ptarray.c:582
#define LW_SUCCESS
Definition: liblwgeom.h:97
#define MULTIPOINTTYPE
Definition: liblwgeom.h:105
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:174
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:643
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:440
void lwpointiterator_destroy(LWPOINTITERATOR *s)
Free all memory associated with the iterator.
Definition: lwiterator.c:268
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition: ptarray.c:51
LWGEOM * lwgeom_remove_repeated_points(const LWGEOM *in, double tolerance)
Definition: lwgeom.c:1562
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1975
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:962
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:102
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:165
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:279
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, uint32_t where)
Insert a point into an existing POINTARRAY.
Definition: ptarray.c:85
double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2)
Definition: measures3d.c:1066
int getPoint3dz_p(const POINTARRAY *pa, uint32_t n, POINT3DZ *point)
Definition: lwgeom_api.c:215
void lwfree(void *mem)
Definition: lwutil.c:248
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:179
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:166
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:125
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:327
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:147
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:176
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:710
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition: lwutil.c:477
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
int getPoint3dm_p(const POINTARRAY *pa, uint32_t n, POINT3DM *point)
Definition: lwgeom_api.c:268
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:496
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:969
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition: lwgeom_api.c:369
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:723
POINTARRAY * ptarray_segmentize2d(const POINTARRAY *ipa, double dist)
Returns a modified POINTARRAY so that no segment is longer than the given distance (computed using 2d...
Definition: ptarray.c:413
LWPOINT * lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p)
Definition: lwpoint.c:206
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm, double zval, double mval)
Definition: ptarray.c:1188
int p4d_same(const POINT4D *p1, const POINT4D *p2)
Definition: lwalgorithm.c:32
int lwline_is_empty(const LWLINE *line)
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:2003
POINTARRAY * ptarray_clone(const POINTARRAY *ptarray)
Clone a POINTARRAY object.
Definition: ptarray.c:674
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:484
int lwpoint_is_empty(const LWPOINT *point)
int ptarray_has_z(const POINTARRAY *pa)
Definition: ptarray.c:37
int project_pt_pt(const POINT4D *A, const POINT4D *B, double distance, POINT4D *R)
Azimuth is angle in radians from vertical axis.
Definition: measures.c:2445
int ptarray_has_m(const POINTARRAY *pa)
Definition: ptarray.c:44
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition: lwinline.h:97
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:199
LWLINE * lwline_removepoint(LWLINE *line, uint32_t index)
Definition: lwline.c:357
double lwline_length_2d(const LWLINE *line)
Definition: lwline.c:530
LWPOINT * lwline_interpolate_point_3d(const LWLINE *line, double distance)
Interpolate one point along a line in 3D.
Definition: lwline.c:615
LWLINE * lwline_segmentize2d(const LWLINE *line, double dist)
Definition: lwline.c:132
LWLINE * lwline_from_ptarray(int32_t srid, uint32_t npoints, LWPOINT **points)
Definition: lwline.c:238
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:455
uint32_t lwline_count_vertices(const LWLINE *line)
Definition: lwline.c:515
void lwline_release(LWLINE *lwline)
Definition: lwline.c:125
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
void lwline_setPoint4d(LWLINE *line, uint32_t index, POINT4D *newpoint)
Definition: lwline.c:374
LWGEOM * lwline_remove_repeated_points(const LWLINE *lwline, double tolerance)
Definition: lwline.c:449
POINTARRAY * lwline_interpolate_points(const LWLINE *line, double length_fraction, char repeat)
Interpolate one or more points along a line.
Definition: lwline.c:538
LWLINE * lwline_clone(const LWLINE *g)
Definition: lwline.c:93
void printLWLINE(LWLINE *line)
Definition: lwline.c:79
LWLINE * lwline_from_lwmpoint(int32_t srid, const LWMPOINT *mpoint)
Definition: lwline.c:285
double lwline_length(const LWLINE *line)
Definition: lwline.c:523
LWLINE * lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
Re-write the measure coordinate (or add one, if it isn't already there) interpolating the measure bet...
Definition: lwline.c:389
char lwline_same(const LWLINE *l1, const LWLINE *l2)
Definition: lwline.c:141
LWLINE * lwline_extend(const LWLINE *line, double distance_forward, double distance_backward)
Extend the ends of a line.
Definition: lwline.c:682
LWLINE * lwline_force_dims(const LWLINE *line, int hasz, int hasm, double zval, double mval)
Definition: lwline.c:496
LWLINE * lwline_clone_deep(const LWLINE *g)
Definition: lwline.c:109
int lwline_is_trajectory(const LWLINE *line)
Definition: lwline.c:464
void lwline_free(LWLINE *line)
Definition: lwline.c:67
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwline.c:55
LWLINE * lwline_from_lwgeom_array(int32_t srid, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwline.c:151
int lwline_add_lwpoint(LWLINE *line, LWPOINT *point, uint32_t where)
Add a LWPOINT to an LWLINE.
Definition: lwline.c:337
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:319
static double distance(double x1, double y1, double x2, double y2)
Definition: lwtree.c:1032
type
Definition: ovdump.py:42
uint8_t type
Definition: liblwgeom.h:462
lwflags_t flags
Definition: liblwgeom.h:485
GBOX * bbox
Definition: liblwgeom.h:482
POINTARRAY * points
Definition: liblwgeom.h:483
uint8_t type
Definition: liblwgeom.h:486
int32_t srid
Definition: liblwgeom.h:484
LWLINE ** geoms
Definition: liblwgeom.h:547
uint32_t ngeoms
Definition: liblwgeom.h:552
uint32_t ngeoms
Definition: liblwgeom.h:538
LWPOINT ** geoms
Definition: liblwgeom.h:533
POINTARRAY * point
Definition: liblwgeom.h:471
double y
Definition: liblwgeom.h:390
double x
Definition: liblwgeom.h:390
double m
Definition: liblwgeom.h:408
double z
Definition: liblwgeom.h:396
double x
Definition: liblwgeom.h:396
double y
Definition: liblwgeom.h:396
double m
Definition: liblwgeom.h:414
double x
Definition: liblwgeom.h:414
double z
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
lwflags_t flags
Definition: liblwgeom.h:431
uint32_t npoints
Definition: liblwgeom.h:427