GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-535c39c9fc
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 
40 static geoline *copy_line(geoline *);
41 static 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  */
51 static 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  */
103 static 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  */
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  */
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  */
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  */
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.",
287 
288  return (1);
289 }
#define NULL
Definition: ccmath.h:32
#define G_calloc(m, n)
Definition: defs/gis.h:95
#define G_malloc(n)
Definition: defs/gis.h:94
int G_debug(int, const char *,...) __attribute__((format(printf
float GS_P2distance(float *, float *)
Calculate distance in plane.
Definition: gs_util.c:160
float GS_distance(float *, float *)
Calculate distance.
Definition: gs_util.c:141
#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
Definition: ogsf.h:140
float Point2[2]
Definition: ogsf.h:206
float Point3[3]
Definition: ogsf.h:205
#define Z
Definition: ogsf.h:142
#define Y
Definition: ogsf.h:141
Definition: ogsf.h:312
Point3 * p3
Definition: ogsf.h:316
struct g_line * next
Definition: ogsf.h:324
int npts
Definition: ogsf.h:315
Point2 * p2
Definition: ogsf.h:317
int dims
Definition: ogsf.h:315
Definition: ogsf.h:328
geoline * fastlines
Definition: ogsf.h:338
int n_lines
Definition: ogsf.h:330
geoline * lines
Definition: ogsf.h:337