/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 | } |