GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
gv_quick.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gv_quick.c
3
4 \brief OGSF library -
5
6 GRASS OpenGL gsurf OGSF Library
7
8 Trying some stuff to draw a quick version of a vector map, to represent
9 it when doing interactive translations.
10
11 (C) 1999-2008 by the GRASS Development Team
12
13 This program is free software under the
14 GNU General Public License (>=v2).
15 Read the file COPYING that comes with GRASS
16 for details.
17
18 \author Bill Brown, USACERL (December 1993)
19 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24
25#include <grass/gis.h>
26#include <grass/ogsf.h>
27
28#include "rowcol.h"
29
30/*!
31 \brief target number of desired points to represent entire file
32 */
33#define TFAST_PTS 800
34
35/*!
36 \brief max number of lines desired
37 */
38#define MFAST_LNS 400
39
40static geoline *copy_line(geoline *);
41static geoline *thin_line(geoline *, float);
42
43/*!
44 \brief Copy line
45
46 \param gln source line (geoline)
47
48 \return pointer to geoline struct
49 \return on failure
50 */
51static geoline *copy_line(geoline * gln)
52{
53 geoline *newln;
54 int i, np;
55
56 newln = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
57 if (!newln) {
58 return (NULL);
59 }
60
61 np = newln->npts = gln->npts;
62
63 if (2 == (newln->dims = gln->dims)) {
64 newln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
65 if (!newln->p2) {
66 return (NULL);
67 }
68
69 for (i = 0; i < np; i++) {
70 newln->p2[i][X] = gln->p2[i][X];
71 newln->p2[i][Y] = gln->p2[i][Y];
72 }
73 }
74 else {
75 newln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
76 if (!newln->p3) {
77 return (NULL);
78 }
79
80 for (i = 0; i < np; i++) {
81 newln->p3[i][X] = gln->p3[i][X];
82 newln->p3[i][Y] = gln->p3[i][Y];
83 newln->p3[i][Z] = gln->p3[i][Z];
84 }
85 }
86
87 newln->next = NULL;
88
89 return (newln);
90}
91
92
93/*!
94 \brief Thin line
95
96 For now, just eliminate points at regular interval
97
98 \param gln line (geoline)
99 \param factor
100
101 \return pointer to geoline struct
102 \return NULL on failure
103 */
104static geoline *thin_line(geoline * gln, float factor)
105{
106 geoline *newln;
107 int i, nextp, targp;
108
109 newln = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
110 if (!newln) {
111 return (NULL);
112 }
113
114 targp = (int)(gln->npts / factor);
115
116 if (targp < 2) {
117 targp = 2;
118 }
119
120 newln->npts = targp;
121
122 if (2 == (newln->dims = gln->dims)) {
123 newln->p2 = (Point2 *) G_calloc(targp, sizeof(Point2)); /* G_fatal_error */
124 if (!newln->p2) {
125 return (NULL);
126 }
127
128 for (i = 0; i < targp; i++) {
129 if (i == targp - 1) {
130 nextp = gln->npts - 1; /* avoid rounding error */
131 }
132 else {
133 nextp = (int)((i * (gln->npts - 1)) / (targp - 1));
134 }
135
136 newln->p2[i][X] = gln->p2[nextp][X];
137 newln->p2[i][Y] = gln->p2[nextp][Y];
138 }
139 }
140 else {
141 newln->p3 = (Point3 *) G_calloc(targp, sizeof(Point3)); /* G_fatal_error */
142 if (!newln->p3) {
143 return (NULL);
144 }
145
146 for (i = 0; i < targp; i++) {
147 if (i == targp - 1) {
148 nextp = gln->npts - 1; /* avoid rounding error */
149 }
150 else {
151 nextp = (int)((i * (gln->npts - 1)) / (targp - 1));
152 }
153
154 newln->p3[i][X] = gln->p3[nextp][X];
155 newln->p3[i][Y] = gln->p3[nextp][Y];
156 newln->p3[i][Z] = gln->p3[nextp][Z];
157 }
158 }
159
160 newln->next = NULL;
161
162 return (newln);
163}
164
165/*!
166 \brief Get line width
167
168 \param gln line (geoline)
169
170 \return line width
171 */
172float gv_line_length(geoline * gln)
173{
174 int n;
175 float length = 0.0;
176
177 for (n = 0; n < gln->npts - 1; n++) {
178 if (gln->p2) {
179 length += GS_P2distance(gln->p2[n + 1], gln->p2[n]);
180 }
181 else {
182 length += GS_distance(gln->p3[n + 1], gln->p3[n]);
183 }
184 }
185
186 return (length);
187}
188
189/*!
190 \brief Get number of line vertices
191
192 \param gln line (geoline)
193
194 \return number of vertices
195 */
196int gln_num_points(geoline * gln)
197{
198 int np = 0;
199 geoline *tln;
200
201 for (tln = gln; tln; tln = tln->next) {
202 np += tln->npts;
203 }
204
205 return (np);
206}
207
208/*!
209 \brief Get number of points in vector
210
211 \param gv vector (geovect)
212
213 \return number of points
214 */
215int gv_num_points(geovect * gv)
216{
217 return (gln_num_points(gv->lines));
218}
219
220
221
222/*!
223 \brief Decimate line
224
225 strategy here: if line has more than average number of points, decimate
226 by eliminating points, otherwise decimate by eliminating shorter lines
227
228 \param gv vector (geovect)
229
230 \return
231 */
232int gv_decimate_lines(geovect * gv)
233{
234 int T_pts, A_ppl, N_s;
235 float decim_factor, slength[MFAST_LNS], T_slength, A_slength;
236 geoline *gln, *prev;
237
238 /* should check if already exists & free if != gv->lines */
239 if (TFAST_PTS > (T_pts = gv_num_points(gv))) {
240 gv->fastlines = gv->lines;
241
242 return (1);
243 }
244
245 N_s = 0;
246 T_slength = 0.0;
247 decim_factor = T_pts / TFAST_PTS;
248 A_ppl = T_pts / gv->n_lines; /* (int) Average points per line */
249
250 prev = NULL;
251
252 for (gln = gv->lines; gln; gln = gln->next) {
253 if (gln->npts > A_ppl) {
254 if (prev) {
255 prev->next = thin_line(gln, decim_factor);
256 prev = prev->next;
257 }
258 else {
259 prev = gv->fastlines = thin_line(gln, decim_factor);
260 }
261 }
262 else if (N_s < MFAST_LNS) {
263 T_slength += slength[N_s++] = gv_line_length(gln);
264 }
265 }
266
267 A_slength = T_slength / N_s;
268 N_s = 0;
269
270 for (gln = gv->lines; gln; gln = gln->next) {
271 if (gln->npts <= A_ppl) {
272 if (N_s < MFAST_LNS) {
273 if (slength[N_s++] > A_slength) {
274 if (prev) {
275 prev->next = copy_line(gln);
276 prev = prev->next;
277 }
278 else {
279 prev = gv->fastlines = copy_line(gln);
280 }
281 }
282 }
283 }
284 }
285
286 G_debug(3, "Decimated lines have %d points.",
287 gln_num_points(gv->fastlines));
288
289 return (1);
290}
#define NULL
Definition: ccmath.h:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
float GS_distance(float *from, float *to)
Calculate distance.
Definition: gs_util.c:141
float GS_P2distance(float *from, float *to)
Calculate distance in plane.
Definition: gs_util.c:160
#define TFAST_PTS
target number of desired points to represent entire file
Definition: gv_quick.c:33
#define MFAST_LNS
max number of lines desired
Definition: gv_quick.c:38
float gv_line_length(geoline *gln)
Get line width.
Definition: gv_quick.c:172
int gln_num_points(geoline *gln)
Get number of line vertices.
Definition: gv_quick.c:196
int gv_num_points(geovect *gv)
Get number of points in vector.
Definition: gv_quick.c:215
int gv_decimate_lines(geovect *gv)
Decimate line.
Definition: gv_quick.c:232
#define X(j)
#define Y(j)