Coverage Report

Created: 2026-08-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}