/src/postgis/liblwgeom/lwtriangle.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) 2010 - Oslandia |
22 | | * |
23 | | **********************************************************************/ |
24 | | |
25 | | |
26 | | /* basic LWTRIANGLE 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 | | |
35 | | |
36 | | /* construct a new LWTRIANGLE. |
37 | | * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0) |
38 | | */ |
39 | | LWTRIANGLE * |
40 | | lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points) |
41 | 0 | { |
42 | 0 | LWTRIANGLE *result; |
43 | |
|
44 | 0 | result = (LWTRIANGLE*) lwalloc(sizeof(LWTRIANGLE)); |
45 | 0 | result->type = TRIANGLETYPE; |
46 | |
|
47 | 0 | result->flags = points->flags; |
48 | 0 | FLAGS_SET_BBOX(result->flags, bbox?1:0); |
49 | |
|
50 | 0 | result->srid = srid; |
51 | 0 | result->points = points; |
52 | 0 | result->bbox = bbox; |
53 | |
|
54 | 0 | return result; |
55 | 0 | } |
56 | | |
57 | | LWTRIANGLE * |
58 | | lwtriangle_construct_empty(int32_t srid, char hasz, char hasm) |
59 | 0 | { |
60 | 0 | LWTRIANGLE *result = lwalloc(sizeof(LWTRIANGLE)); |
61 | 0 | result->type = TRIANGLETYPE; |
62 | 0 | result->flags = lwflags(hasz,hasm,0); |
63 | 0 | result->srid = srid; |
64 | 0 | result->points = ptarray_construct_empty(hasz, hasm, 1); |
65 | 0 | result->bbox = NULL; |
66 | 0 | return result; |
67 | 0 | } |
68 | | |
69 | | void lwtriangle_free(LWTRIANGLE *triangle) |
70 | 0 | { |
71 | 0 | if ( ! triangle ) return; |
72 | | |
73 | 0 | if (triangle->bbox) |
74 | 0 | lwfree(triangle->bbox); |
75 | |
|
76 | 0 | if (triangle->points) |
77 | 0 | ptarray_free(triangle->points); |
78 | |
|
79 | 0 | lwfree(triangle); |
80 | 0 | } |
81 | | |
82 | | void printLWTRIANGLE(LWTRIANGLE *triangle) |
83 | 0 | { |
84 | 0 | if (triangle->type != TRIANGLETYPE) |
85 | 0 | lwerror("printLWTRIANGLE called with something else than a Triangle"); |
86 | |
|
87 | 0 | lwnotice("LWTRIANGLE {"); |
88 | 0 | lwnotice(" ndims = %i", (int)FLAGS_NDIMS(triangle->flags)); |
89 | 0 | lwnotice(" SRID = %i", (int)triangle->srid); |
90 | 0 | printPA(triangle->points); |
91 | 0 | lwnotice("}"); |
92 | 0 | } |
93 | | |
94 | | /* @brief Clone LWTRIANGLE object. Serialized point lists are not copied. |
95 | | * |
96 | | * @see ptarray_clone |
97 | | */ |
98 | | LWTRIANGLE * |
99 | | lwtriangle_clone(const LWTRIANGLE *g) |
100 | 0 | { |
101 | 0 | LWDEBUGF(2, "lwtriangle_clone called with %p", g); |
102 | 0 | return (LWTRIANGLE *)lwline_clone((const LWLINE *)g); |
103 | 0 | } |
104 | | |
105 | | int |
106 | | lwtriangle_has_orientation(const LWTRIANGLE *triangle, int orientation) |
107 | 0 | { |
108 | 0 | return ptarray_has_orientation(triangle->points, orientation); |
109 | 0 | } |
110 | | |
111 | | void |
112 | | lwtriangle_force_orientation(LWTRIANGLE *triangle, int orientation) |
113 | 0 | { |
114 | 0 | if (!lwtriangle_has_orientation(triangle, orientation)) |
115 | 0 | ptarray_reverse_in_place(triangle->points); |
116 | 0 | } |
117 | | |
118 | | void |
119 | | lwtriangle_release(LWTRIANGLE *lwtriangle) |
120 | 0 | { |
121 | 0 | lwgeom_release(lwtriangle_as_lwgeom(lwtriangle)); |
122 | 0 | } |
123 | | |
124 | | /* check coordinate equality */ |
125 | | char |
126 | | lwtriangle_same(const LWTRIANGLE *t1, const LWTRIANGLE *t2) |
127 | 0 | { |
128 | 0 | char r = ptarray_same(t1->points, t2->points); |
129 | 0 | LWDEBUGF(5, "returning %d", r); |
130 | 0 | return r; |
131 | 0 | } |
132 | | |
133 | | static char |
134 | | lwtriangle_is_repeated_points(LWTRIANGLE *triangle) |
135 | 0 | { |
136 | 0 | char ret; |
137 | 0 | POINTARRAY *pa; |
138 | |
|
139 | 0 | pa = ptarray_remove_repeated_points(triangle->points, 0.0); |
140 | 0 | ret = ptarray_same(pa, triangle->points); |
141 | 0 | ptarray_free(pa); |
142 | |
|
143 | 0 | return ret; |
144 | 0 | } |
145 | | |
146 | | /* |
147 | | * Construct a triangle from a LWLINE being |
148 | | * the shell |
149 | | * Pointarray from input geom is cloned. |
150 | | * Input line must have 4 points, and be closed. |
151 | | */ |
152 | | LWTRIANGLE * |
153 | | lwtriangle_from_lwline(const LWLINE *shell) |
154 | 0 | { |
155 | 0 | LWTRIANGLE *ret; |
156 | 0 | POINTARRAY *pa; |
157 | |
|
158 | 0 | if ( shell->points->npoints != 4 ) |
159 | 0 | lwerror("lwtriangle_from_lwline: shell must have exactly 4 points"); |
160 | |
|
161 | 0 | if ( (!FLAGS_GET_Z(shell->flags) && !ptarray_is_closed_2d(shell->points)) || |
162 | 0 | (FLAGS_GET_Z(shell->flags) && !ptarray_is_closed_3d(shell->points)) ) |
163 | 0 | lwerror("lwtriangle_from_lwline: shell must be closed"); |
164 | |
|
165 | 0 | pa = ptarray_clone_deep(shell->points); |
166 | 0 | ret = lwtriangle_construct(shell->srid, NULL, pa); |
167 | |
|
168 | 0 | if (lwtriangle_is_repeated_points(ret)) |
169 | 0 | lwerror("lwtriangle_from_lwline: some points are repeated in triangle"); |
170 | |
|
171 | 0 | return ret; |
172 | 0 | } |
173 | | |
174 | | /** |
175 | | * Find the area of the outer ring |
176 | | */ |
177 | | double |
178 | | lwtriangle_area(const LWTRIANGLE *triangle) |
179 | 0 | { |
180 | 0 | double area=0.0; |
181 | 0 | uint32_t i; |
182 | 0 | POINT2D p1; |
183 | 0 | POINT2D p2; |
184 | |
|
185 | 0 | if (! triangle->points->npoints) return area; /* empty triangle */ |
186 | | |
187 | 0 | for (i=0; i < triangle->points->npoints-1; i++) |
188 | 0 | { |
189 | 0 | getPoint2d_p(triangle->points, i, &p1); |
190 | 0 | getPoint2d_p(triangle->points, i+1, &p2); |
191 | 0 | area += ( p1.x * p2.y ) - ( p1.y * p2.x ); |
192 | 0 | } |
193 | |
|
194 | 0 | area /= 2.0; |
195 | |
|
196 | 0 | return fabs(area); |
197 | 0 | } |
198 | | |
199 | | |
200 | | double |
201 | | lwtriangle_perimeter(const LWTRIANGLE *triangle) |
202 | 0 | { |
203 | 0 | if( triangle->points ) |
204 | 0 | return ptarray_length(triangle->points); |
205 | 0 | else |
206 | 0 | return 0.0; |
207 | 0 | } |
208 | | |
209 | | double |
210 | | lwtriangle_perimeter_2d(const LWTRIANGLE *triangle) |
211 | 0 | { |
212 | 0 | if( triangle->points ) |
213 | 0 | return ptarray_length_2d(triangle->points); |
214 | 0 | else |
215 | 0 | return 0.0; |
216 | 0 | } |