Coverage Report

Created: 2026-08-13 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgis/liblwgeom/lwcurvepoly.c
Line
Count
Source
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) 2001-2006 Refractions Research Inc.
22
 *
23
 **********************************************************************/
24
25
26
/* basic LWCURVEPOLY manipulation */
27
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include "liblwgeom_internal.h"
32
#include "lwgeom_log.h"
33
34
LWCURVEPOLY *
35
lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm)
36
0
{
37
0
  LWCURVEPOLY *ret;
38
39
0
  ret = lwalloc(sizeof(LWCURVEPOLY));
40
0
  ret->type = CURVEPOLYTYPE;
41
0
  ret->flags = lwflags(hasz, hasm, 0);
42
0
  ret->srid = srid;
43
0
  ret->nrings = 0;
44
0
  ret->maxrings = 1; /* Allocate room for sub-members, just in case. */
45
0
  ret->rings = lwalloc(ret->maxrings * sizeof(LWGEOM*));
46
0
  ret->bbox = NULL;
47
48
0
  return ret;
49
0
}
50
51
LWCURVEPOLY *
52
lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly)
53
0
{
54
0
  LWCURVEPOLY *ret;
55
0
  uint32_t i;
56
0
  ret = lwalloc(sizeof(LWCURVEPOLY));
57
0
  ret->type = CURVEPOLYTYPE;
58
0
  ret->flags = lwpoly->flags;
59
0
  ret->srid = lwpoly->srid;
60
0
  ret->nrings = lwpoly->nrings;
61
0
  ret->maxrings = lwpoly->nrings; /* Allocate room for sub-members, just in case. */
62
0
  ret->rings = lwalloc(ret->maxrings * sizeof(LWGEOM*));
63
0
  ret->bbox = lwpoly->bbox ? gbox_clone(lwpoly->bbox) : NULL;
64
0
  for ( i = 0; i < ret->nrings; i++ )
65
0
  {
66
0
    ret->rings[i] = lwline_as_lwgeom(lwline_construct(ret->srid, NULL, ptarray_clone_deep(lwpoly->rings[i])));
67
0
  }
68
0
  return ret;
69
0
}
70
71
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
72
0
{
73
0
  uint32_t i;
74
75
  /* Can't do anything with NULLs */
76
0
  if( ! poly || ! ring )
77
0
  {
78
0
    LWDEBUG(4,"NULL inputs!!! quitting");
79
0
    return LW_FAILURE;
80
0
  }
81
82
  /* Check that we're not working with garbage */
83
0
  if ( poly->rings == NULL && (poly->nrings || poly->maxrings) )
84
0
  {
85
0
    LWDEBUG(4,"mismatched nrings/maxrings");
86
0
    lwerror("Curvepolygon is in inconsistent state. Null memory but non-zero collection counts.");
87
0
    return LW_FAILURE;
88
0
  }
89
90
  /* Check that we're adding an allowed ring type */
91
0
  if ( ! ( ring->type == LINETYPE || ring->type == CIRCSTRINGTYPE ||
92
0
            ring->type == COMPOUNDTYPE || ring->type == NURBSCURVETYPE ) )
93
0
  {
94
0
    LWDEBUGF(4,"got incorrect ring type: %s",lwtype_name(ring->type));
95
0
    return LW_FAILURE;
96
0
  }
97
98
99
  /* In case this is a truly empty, make some initial space  */
100
0
  if ( poly->rings == NULL )
101
0
  {
102
0
    poly->maxrings = 2;
103
0
    poly->nrings = 0;
104
0
    poly->rings = lwalloc(poly->maxrings * sizeof(LWGEOM*));
105
0
  }
106
107
  /* Allocate more space if we need it */
108
0
  if ( poly->nrings == poly->maxrings )
109
0
  {
110
0
    poly->maxrings *= 2;
111
0
    poly->rings = lwrealloc(poly->rings, sizeof(LWGEOM*) * poly->maxrings);
112
0
  }
113
114
  /* Make sure we don't already have a reference to this geom */
115
0
  for ( i = 0; i < poly->nrings; i++ )
116
0
  {
117
0
    if ( poly->rings[i] == ring )
118
0
    {
119
0
      LWDEBUGF(4, "Found duplicate geometry in collection %p == %p", poly->rings[i], ring);
120
0
      return LW_SUCCESS;
121
0
    }
122
0
  }
123
124
  /* Add the ring and increment the ring count */
125
0
  poly->rings[poly->nrings] = (LWGEOM*)ring;
126
0
  poly->nrings++;
127
0
  return LW_SUCCESS;
128
0
}
129
130
/**
131
 * This should be rewritten to make use of the curve itself.
132
 */
133
double
134
lwcurvepoly_area(const LWCURVEPOLY *curvepoly)
135
0
{
136
0
  double area = 0.0;
137
0
  LWPOLY *poly;
138
0
  if( lwgeom_is_empty((LWGEOM*)curvepoly) )
139
0
    return 0.0;
140
0
  poly = lwcurvepoly_stroke(curvepoly, 32);
141
0
  area = lwpoly_area(poly);
142
0
  lwpoly_free(poly);
143
0
  return area;
144
0
}
145
146
147
double
148
lwcurvepoly_perimeter(const LWCURVEPOLY *poly)
149
0
{
150
0
  double result=0.0;
151
0
  uint32_t i;
152
153
0
  for (i=0; i<poly->nrings; i++)
154
0
    result += lwgeom_length(poly->rings[i]);
155
156
0
  return result;
157
0
}
158
159
double
160
lwcurvepoly_perimeter_2d(const LWCURVEPOLY *poly)
161
0
{
162
0
  double result=0.0;
163
0
  uint32_t i;
164
165
0
  for (i=0; i<poly->nrings; i++)
166
0
    result += lwgeom_length_2d(poly->rings[i]);
167
168
0
  return result;
169
0
}