PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwt_edgeend_star.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) 2024 Sandro Santilli <strk@kbt.io>
22 *
23 **********************************************************************/
24
25#include "../postgis_config.h"
26
27//#define POSTGIS_DEBUG_LEVEL 1
28#include "lwgeom_log.h"
29
30#include "liblwgeom_internal.h"
32
33#include "lwt_edgeend_star.h"
34#include "lwt_edgeend.h"
35
36#include <inttypes.h>
37
40{
42 star->numEdgeEnds = 0;
43 star->edgeEndsCapacity = 0;
44 star->edgeEnds = NULL;
45 star->nodeID = nodeID;
46 star->sorted = 0;
47
48 return star;
49}
50
51void
53{
54 uint64_t i;
55 for (i=0; i<star->edgeEndsCapacity; ++i)
56 {
57 lwfree( star->edgeEnds[i] );
58 }
59 if ( star->edgeEndsCapacity ) {
60 lwfree( star->edgeEnds );
61 }
62 lwfree( star );
63}
64
65void
67{
68 int numEdgeEnds = 0;
69 LWT_EDGEEND *edgeEnds[2];
70 uint64_t newCapacity;
71
72 if ( edge->start_node == star->nodeID )
73 {
74 LWT_EDGEEND *ee = lwt_edgeEnd_fromEdge( edge, 1 );
75 if ( ! ee ) {
76 lwerror("Could not construct outgoing EdgeEnd for edge %"
77 LWTFMT_ELEMID, edge->edge_id);
78 return;
79 }
80 edgeEnds[numEdgeEnds++] = ee;
81 }
82 if ( edge->end_node == star->nodeID )
83 {
84 LWT_EDGEEND *ee = lwt_edgeEnd_fromEdge( edge, 0 );
85 if ( ! ee ) {
86 lwerror("Could not construct outgoing incoming for edge %"
87 LWTFMT_ELEMID, edge->edge_id);
88 return;
89 }
90 edgeEnds[numEdgeEnds++] = ee;
91 }
92
93 if ( ! numEdgeEnds )
94 {
95 lwerror("Edge %" LWTFMT_ELEMID
96 " doesn't start nor end on star node %" LWTFMT_ELEMID,
97 edge->edge_id, star->nodeID);
98 return;
99 }
100
101 LWDEBUGF(1, "Edge %" LWTFMT_ELEMID
102 " got %d" " ends incident to star node %" LWTFMT_ELEMID,
103 edge->edge_id, numEdgeEnds, star->nodeID );
104
105 newCapacity = star->numEdgeEnds + numEdgeEnds;
106 LWDEBUGF(3, "Current star capacity:%lld, required:%lld",
107 star->edgeEndsCapacity, newCapacity);
108 if ( newCapacity > star->edgeEndsCapacity )
109 {
110 LWDEBUGF(3, "Reallocating edgeEnds from %p to new size %lld", star->edgeEnds, newCapacity * sizeof(LWT_EDGEEND *));
111 if ( star->edgeEnds ) {
112 star->edgeEnds = lwrealloc(star->edgeEnds, newCapacity * sizeof(LWT_EDGEEND *));
113 } else {
114 star->edgeEnds = lwalloc(newCapacity * sizeof(LWT_EDGEEND *));
115 }
116 LWDEBUGF(3, "Reallocated edgeEnds are %p", star->edgeEnds);
117 star->edgeEndsCapacity = newCapacity;
118 LWDEBUGF(3, "New star capacity: %lld", newCapacity);
119 }
120
121 for (int i=0; i<numEdgeEnds; ++i)
122 {
123 star->edgeEnds[ star->numEdgeEnds++ ] = edgeEnds[i];
124 }
125 star->sorted = 0;
126}
127
128static int
129lwt_edgeEnd_compare(const void *i1, const void *i2)
130{
131 const LWT_EDGEEND *ee1 = *(const LWT_EDGEEND **)i1;
132 const LWT_EDGEEND *ee2 = *(const LWT_EDGEEND **)i2;
133 int ret;
134 if ( ee1->azimuth < ee2->azimuth )
135 ret = -1;
136 else if ( ee1->azimuth > ee2->azimuth )
137 ret = 1;
138 else
139 ret = 0;
140
141 LWDEBUGF(4, "qsort comparator for %s edge %lld with azimuth %g and %s edge %lld with azimuth %g returning %d",
142 ee1->outgoing ? "outgoing" : "incoming", ee1->edge->edge_id, ee1->azimuth,
143 ee2->outgoing ? "outgoing" : "incoming", ee2->edge->edge_id, ee2->azimuth,
144 ret
145 );
146
147 return ret;
148}
149
150static void
152{
153 if ( star->sorted ) return; // nothing to do
154 qsort( star->edgeEnds, star->numEdgeEnds, sizeof(LWT_EDGEEND *), lwt_edgeEnd_compare);
155 star->sorted = 1;
156}
157
158void
160{
161 lwdebug(1, "Star around node %" LWTFMT_ELEMID " has %" PRIu64 " edgeEnds, %s",
162 star->nodeID, star->numEdgeEnds, star->sorted ? "sorted" : "unsorted" );
163 for ( uint64_t i=0; i<star->numEdgeEnds; ++i )
164 {
165 LWT_EDGEEND *ee = star->edgeEnds[i];
166 lwdebug(1, " EdgeEnd %" PRIu64 " is %s edge %" LWTFMT_ELEMID ", azimuth=%.15g",
167 i, ee->outgoing ? "outgoing" : "incoming",
168 ee->edge->edge_id, ee->azimuth
169 );
170 }
171}
172
173const LWT_EDGEEND *
175{
177
178 uint64_t i=0;
179 LWT_EDGEEND *thisEdgeEnd = NULL;
180 for ( i=0; i<star->numEdgeEnds; ++i )
181 {
182 LWT_EDGEEND *ee = star->edgeEnds[i];
183 if ( ee->edge == edge && ee->outgoing == outgoing ) {
184 thisEdgeEnd = ee;
185 break;
186 }
187 }
188 if ( ! thisEdgeEnd ) {
189 lwerror("Could not find %s edge %" LWTFMT_ELEMID " in the star",
190 outgoing ? "outgoing" : "incoming", edge->edge_id);
191 return NULL;
192 }
193 LWT_EDGEEND *nextEdgeEnd = i < star->numEdgeEnds-1 ? star->edgeEnds[i+1] : star->edgeEnds[0];
194 return nextEdgeEnd;
195}
196
197const LWT_EDGEEND *
199{
201
202 uint64_t i=0;
203 LWT_EDGEEND *thisEdgeEnd = NULL;
204 for ( i=0; i<star->numEdgeEnds; ++i )
205 {
206 LWT_EDGEEND *ee = star->edgeEnds[i];
207 if ( ee->edge == edge && ee->outgoing == outgoing ) {
208 thisEdgeEnd = ee;
209 break;
210 }
211 }
212 if ( ! thisEdgeEnd ) {
213 lwerror("Could not find %s edge %" LWTFMT_ELEMID " in the star",
214 outgoing ? "outgoing" : "incoming", edge->edge_id);
215 return NULL;
216 }
217 LWT_EDGEEND *nextEdgeEnd = i > 0 ? star->edgeEnds[i-1] : star->edgeEnds[star->numEdgeEnds-1];
218 return nextEdgeEnd;
219}
void * lwrealloc(void *mem, size_t size)
Definition lwutil.c:242
void * lwalloc(size_t size)
Definition lwutil.c:227
void lwfree(void *mem)
Definition lwutil.c:248
LWT_INT64 LWT_ELEMID
Identifier of topology element.
#define LWTFMT_ELEMID
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
void void void lwdebug(int level, const char *fmt,...) __attribute__((format(printf
Write a debug message out.
LWT_EDGEEND * lwt_edgeEnd_fromEdge(const LWT_ISO_EDGE *edge, int outgoing)
Definition lwt_edgeend.c:68
static void lwt_edgeEndStar_ensureSorted(LWT_EDGEEND_STAR *star)
const LWT_EDGEEND * lwt_edgeEndStar_getNextCW(LWT_EDGEEND_STAR *star, LWT_ISO_EDGE *edge, int outgoing)
LWT_EDGEEND_STAR * lwt_edgeEndStar_init(LWT_ELEMID nodeID)
static int lwt_edgeEnd_compare(const void *i1, const void *i2)
const LWT_EDGEEND * lwt_edgeEndStar_getNextCCW(LWT_EDGEEND_STAR *star, LWT_ISO_EDGE *edge, int outgoing)
void lwt_edgeEndStar_release(LWT_EDGEEND_STAR *star)
void lwt_EdgeEndStar_debugPrint(const LWT_EDGEEND_STAR *star)
void lwt_edgeEndStar_addEdge(LWT_EDGEEND_STAR *star, const LWT_ISO_EDGE *edge)
LWT_EDGEEND ** edgeEnds
const LWT_ISO_EDGE * edge
Definition lwt_edgeend.h:33
LWT_ELEMID end_node
LWT_ELEMID edge_id
LWT_ELEMID start_node