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