GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
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 \brief Thin line
94
95 For now, just eliminate points at regular interval
96
97 \param gln line (geoline)
98 \param factor
99
100 \return pointer to geoline struct
101 \return NULL on failure
102 */
103static geoline *thin_line(geoline *gln, float factor)
104{
105 geoline *newln;
106 int i, nextp, targp;
107
108 newln = (geoline *)G_malloc(sizeof(geoline)); /* G_fatal_error */
109 if (!newln) {
110 return (NULL);
111 }
112
113 targp = (int)(gln->npts / factor);
114
115 if (targp < 2) {
116 targp = 2;
117 }
118
119 newln->npts = targp;
120
121 if (2 == (newln->dims = gln->dims)) {
122 newln->p2 =
123 (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 =
142 (Point3 *)G_calloc(targp, sizeof(Point3)); /* G_fatal_error */
143 if (!newln->p3) {
144 return (NULL);
145 }
146
147 for (i = 0; i < targp; i++) {
148 if (i == targp - 1) {
149 nextp = gln->npts - 1; /* avoid rounding error */
150 }
151 else {
152 nextp = (int)((i * (gln->npts - 1)) / (targp - 1));
153 }
154
155 newln->p3[i][X] = gln->p3[nextp][X];
156 newln->p3[i][Y] = gln->p3[nextp][Y];
157 newln->p3[i][Z] = gln->p3[nextp][Z];
158 }
159 }
160
161 newln->next = NULL;
162
163 return (newln);
164}
165
166/*!
167 \brief Get line width
168
169 \param gln line (geoline)
170
171 \return line width
172 */
173float gv_line_length(geoline *gln)
174{
175 int n;
176 float length = 0.0;
177
178 for (n = 0; n < gln->npts - 1; n++) {
179 if (gln->p2) {
180 length += GS_P2distance(gln->p2[n + 1], gln->p2[n]);
181 }
182 else {
183 length += GS_distance(gln->p3[n + 1], gln->p3[n]);
184 }
185 }
186
187 return (length);
188}
189
190/*!
191 \brief Get number of line vertices
192
193 \param gln line (geoline)
194
195 \return number of vertices
196 */
197int gln_num_points(geoline *gln)
198{
199 int np = 0;
200 geoline *tln;
201
202 for (tln = gln; tln; tln = tln->next) {
203 np += tln->npts;
204 }
205
206 return (np);
207}
208
209/*!
210 \brief Get number of points in vector
211
212 \param gv vector (geovect)
213
214 \return number of points
215 */
216int gv_num_points(geovect *gv)
217{
218 return (gln_num_points(gv->lines));
219}
220
221/*!
222 \brief Decimate line
223
224 strategy here: if line has more than average number of points, decimate
225 by eliminating points, otherwise decimate by eliminating shorter lines
226
227 \param gv vector (geovect)
228
229 \return
230 */
231int gv_decimate_lines(geovect *gv)
232{
233 int T_pts, A_ppl, N_s;
234 float decim_factor, slength[MFAST_LNS], T_slength, A_slength;
235 geoline *gln, *prev;
236
237 /* should check if already exists & free if != gv->lines */
238 if (TFAST_PTS > (T_pts = gv_num_points(gv))) {
239 gv->fastlines = gv->lines;
240
241 return (1);
242 }
243
244 N_s = 0;
245 T_slength = 0.0;
246 decim_factor = T_pts / TFAST_PTS;
247 A_ppl = T_pts / gv->n_lines; /* (int) Average points per line */
248
249 prev = NULL;
250
251 for (gln = gv->lines; gln; gln = gln->next) {
252 if (gln->npts > A_ppl) {
253 if (prev) {
254 prev->next = thin_line(gln, decim_factor);
255 prev = prev->next;
256 }
257 else {
258 prev = gv->fastlines = thin_line(gln, decim_factor);
259 }
260 }
261 else if (N_s < MFAST_LNS) {
262 T_slength += slength[N_s++] = gv_line_length(gln);
263 }
264 }
265
266 A_slength = T_slength / N_s;
267 N_s = 0;
268
269 for (gln = gv->lines; gln; gln = gln->next) {
270 if (gln->npts <= A_ppl) {
271 if (N_s < MFAST_LNS) {
272 if (slength[N_s++] > A_slength) {
273 if (prev) {
274 prev->next = copy_line(gln);
275 prev = prev->next;
276 }
277 else {
278 prev = gv->fastlines = copy_line(gln);
279 }
280 }
281 }
282 }
283 }
284
285 G_debug(3, "Decimated lines have %d points.",
286 gln_num_points(gv->fastlines));
287
288 return (1);
289}
#define NULL
Definition ccmath.h:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
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:173
int gln_num_points(geoline *gln)
Get number of line vertices.
Definition gv_quick.c:197
int gv_num_points(geovect *gv)
Get number of points in vector.
Definition gv_quick.c:216
int gv_decimate_lines(geovect *gv)
Decimate line.
Definition gv_quick.c:231
#define X(j)
#define Y(j)