clean_nodes.c

Go to the documentation of this file.
00001 /* **************************************************************
00002  * 
00003  * MODULE:       vector library
00004  * 
00005  * AUTHOR(S):    Radim Blazek
00006  *               
00007  * PURPOSE:      Clean boundaries at nodes
00008  *               
00009  * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00010  *
00011  *               This program is free software under the 
00012  *               GNU General Public License (>=v2). 
00013  *               Read the file COPYING that comes with GRASS
00014  *               for details.
00015  *
00016  **************************************************************/
00017 #include <stdlib.h> 
00018 #include <grass/gis.h>
00019 #include <grass/Vect.h>
00020 
00032 int 
00033 Vect_clean_small_angles_at_nodes ( struct Map_info *Map, int otype, struct Map_info *Err, FILE *msgout)
00034 {
00035     int node;
00036     int nmodif = 0;
00037     struct line_pnts *Points;
00038     struct line_cats *SCats, *LCats, *OCats;
00039 
00040     Points = Vect_new_line_struct ();
00041     SCats = Vect_new_cats_struct ();
00042     LCats = Vect_new_cats_struct ();
00043     OCats = Vect_new_cats_struct ();
00044 
00045     if ( msgout ) fprintf (msgout, "Modifications: %5d", nmodif ); 
00046     
00047     for ( node = 1; node <= Vect_get_num_nodes(Map); node++ ){ 
00048         int i, nlines;
00049         
00050         G_debug (3, "node = %d", node );
00051         if ( !Vect_node_alive ( Map, node ) ) continue;
00052 
00053         while ( 1 ) {
00054             float angle1 = -100;
00055             int line1 = -999; /* value not important, just for debug */
00056             int clean = 1;
00057             
00058             
00059             nlines = Vect_get_node_n_lines ( Map, node );
00060             G_debug (3, "nlines = %d", nlines );
00061 
00062             for ( i = 0; i < nlines; i++ ) {
00063                 P_LINE *Line;
00064                 int line2;
00065                 float angle2;
00066                     
00067                 line2 = Vect_get_node_line ( Map, node, i );
00068                 Line = Map->plus.Line[abs(line2)];
00069                 if ( !Line ) continue;
00070                 G_debug (4, "  type = %d", Line->type );
00071                 if ( !(Line->type & (otype & GV_LINES)) ) continue;
00072                 
00073                 angle2 = Vect_get_node_line_angle ( Map, node, i );
00074                 if ( angle2 == -9.0 ) continue; /* Degenerated line */
00075             
00076                 G_debug (4, "  line1 = %d angle1 = %e line2 = %d angle2 = %e", line1, angle1, line2, angle2 );
00077 
00078                 if ( angle2 == angle1 ) { 
00079                     int j;
00080                     double length1, length2;
00081                     int short_line; /* line with shorter end segment */
00082                     int long_line;  /* line with longer end segment */
00083                     int new_short_line=0; /* line number of short line after rewrite */
00084                     int short_type, long_type, type;
00085                     double x, y, z, nx, ny, nz;
00086                     
00087                     G_debug (4, "  identical angles -> clean" );
00088 
00089                     /* Length of end segments for both lines */
00090                     Vect_read_line ( Map, Points, NULL, abs(line1) );
00091                     if ( line1 > 0 ) {
00092                         length1 = Vect_points_distance ( Points->x[0], Points->y[0], 0.0,
00093                                                          Points->x[1], Points->y[1], 0.0, 0 );
00094                     } else {
00095                         int np;
00096                         np = Points->n_points;
00097                         length1 = Vect_points_distance ( Points->x[np-1], Points->y[np-1], 0.0,
00098                                                          Points->x[np-2], Points->y[np-2], 0.0, 0 );
00099                     }
00100 
00101                     Vect_read_line ( Map, Points, NULL, abs(line2) );
00102                     if ( line2 > 0 ) {
00103                         length2 = Vect_points_distance ( Points->x[0], Points->y[0], 0.0,
00104                                                          Points->x[1], Points->y[1], 0.0, 0 );
00105                     } else {
00106                         int np;
00107                         np = Points->n_points;
00108                         length2 = Vect_points_distance ( Points->x[np-1], Points->y[np-1], 0.0,
00109                                                          Points->x[np-2], Points->y[np-2], 0.0, 0 );
00110                     }
00111                     
00112                     G_debug (4, "  length1 = %f length2 = %f", length1, length2 );
00113 
00114                     if ( length1 < length2 ) {
00115                         short_line = line1;
00116                         long_line = line2;
00117                     } else { 
00118                         short_line = line2;
00119                         long_line = line1;
00120                     }
00121 
00122                     /* Remove end segment from short_line */
00123                     short_type = Vect_read_line ( Map, Points, SCats, abs(short_line) );
00124                             
00125                     if ( short_line > 0 ) {
00126                         x = Points->x[1];
00127                         y = Points->y[1];
00128                         z = Points->z[1];
00129                         Vect_line_delete_point ( Points, 0 ); /* first */
00130                     } else {
00131                         x = Points->x[Points->n_points-2];
00132                         y = Points->y[Points->n_points-2];
00133                         z = Points->z[Points->n_points-2];
00134                         Vect_line_delete_point ( Points, Points->n_points-1 ); /* last */
00135                     }
00136 
00137                     if ( Points->n_points > 1 ) {
00138                         new_short_line = Vect_rewrite_line ( Map, abs(short_line), short_type, Points, SCats );
00139                     } else {
00140                         Vect_delete_line ( Map, abs(short_line) );
00141                     }
00142 
00143                     /* It may happen that it is one line, in that case we have to take the new
00144                      * short line as long line, orientation is not changed */
00145                     if ( abs(line1) == abs(line2) ) {
00146                         if ( long_line > 0 )
00147                             long_line = new_short_line;
00148                         else 
00149                             long_line = -new_short_line;
00150                     }
00151                     
00152 
00153                     /* Add new line (must be before rewrite of long_line otherwise node could be deleted) */
00154                     long_type = Vect_read_line ( Map, NULL, LCats, abs(long_line) );
00155                     
00156                     Vect_reset_cats ( OCats );
00157                     for ( j = 0; j < SCats->n_cats; j++ ) {
00158                         Vect_cat_set ( OCats, SCats->field[j], SCats->cat[j] );
00159                     }
00160                     for ( j = 0; j < LCats->n_cats; j++ ) {
00161                         Vect_cat_set ( OCats, LCats->field[j], LCats->cat[j] );
00162                     }
00163 
00164                     if ( long_type == GV_BOUNDARY || short_type == GV_BOUNDARY ) {
00165                         type = GV_BOUNDARY;
00166                     } else { 
00167                         type = GV_LINE;
00168                     }
00169 
00170                     Vect_get_node_coor ( Map, node, &nx, &ny, &nz );
00171                     Vect_reset_line ( Points );
00172                     Vect_append_point ( Points, nx, ny, nz );
00173                     Vect_append_point ( Points, x, y, z );
00174                     Vect_write_line ( Map, type, Points, OCats );
00175 
00176                     if ( Err ) {
00177                         Vect_write_line ( Err, type, Points, OCats );
00178                     }
00179 
00180                     /* Snap long_line to the new short_line end */ 
00181                     long_type = Vect_read_line ( Map, Points, LCats, abs(long_line) );
00182                     if ( long_line > 0 ) {
00183                         Points->x[0] = x;
00184                         Points->y[0] = y;
00185                         Points->z[0] = z;
00186                     } else {
00187                         Points->x[Points->n_points-1] = x;
00188                         Points->y[Points->n_points-1] = y;
00189                         Points->z[Points->n_points-1] = z;
00190                     }
00191                     Vect_line_prune ( Points );
00192                     if ( Points->n_points > 1 ) {
00193                         Vect_rewrite_line ( Map, abs(long_line), long_type, Points, LCats );
00194                     } else {
00195                         Vect_delete_line ( Map, abs(long_line) );
00196                     }
00197 
00198                     nmodif += 3;
00199                     clean = 0;
00200                     
00201                     break;
00202                 }
00203                 
00204                 line1 = line2;
00205                 angle1 = angle2;
00206             }
00207     
00208             if ( msgout ) {
00209                 fprintf (msgout, "\rModifications: %5d", nmodif ); 
00210                 fflush ( msgout );
00211             }
00212 
00213             if ( clean )
00214                 break;
00215 
00216         }
00217 
00218     }
00219     if ( msgout ) fprintf (stderr, "\n" ); 
00220 
00221     return (nmodif);
00222 }
00223 

Generated on Sun Apr 6 17:32:44 2008 for GRASS by  doxygen 1.5.5