plus_node.c

Go to the documentation of this file.
00001 /*
00002 * $Id: plus_node.c,v 1.9 2006/02/09 03:08:58 glynn Exp $
00003 *
00004 ****************************************************************************
00005 *
00006 * MODULE:       Vector library 
00007 *               
00008 * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
00009 *               Update to GRASS 5.7 Radim Blazek.
00010 *
00011 * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
00012 *
00013 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00014 *
00015 *               This program is free software under the GNU General Public
00016 *               License (>=v2). Read the file COPYING that comes with GRASS
00017 *               for details.
00018 *
00019 *****************************************************************************/
00020 #include <stdlib.h>
00021 #include <math.h>
00022 #include <grass/Vect.h>
00023 
00024 static double dist_squared (double, double, double, double);
00025 
00026 /* dig_node_add_line ()
00027 **   add 'line' info to 'node'
00028 **   line will be negative if END node 
00029 **   'node' must of course already exist
00030 **   space will be alloced to add 'line' to array
00031 **
00032 **   Returns -1 on error      
00033 **            0 line not added  (degenerate)
00034 **            else new number of lines in node 
00035 **        
00036 */
00037 int 
00038 dig_node_add_line ( struct Plus_head *plus, int nodeid, int lineid,
00039                     struct line_pnts *points, int type)
00040 {
00041     register int i, j, nlines;
00042     float angle;
00043     int ret;
00044     P_NODE *node;
00045 
00046     G_debug (3, "dig_node_add_line(): node = %d line = %d", nodeid, lineid);
00047 
00048     node = plus->Node[nodeid];
00049     nlines = node->n_lines;
00050 
00051     /* reallocate memory */
00052     ret = dig_node_alloc_line ( node, 1);
00053     if ( ret == -1 ) return -1;
00054     
00055     if ( type & GV_LINES ) { 
00056         if (lineid < 0)
00057           angle = dig_calc_end_angle (points, 0);
00058         else
00059           angle = dig_calc_begin_angle (points, 0);
00060     } else {
00061         angle = -9.;
00062     }
00063     G_debug (3, "    angle = %f", angle);
00064         
00065     /* make sure the new angle is less than the empty space at end */
00066     node->angles[nlines] = 999.;
00067 
00068     for (i = 0; i <= nlines; i++)       /* alloced for 1 more */
00069     {
00070       if (angle < node->angles[i])
00071         {
00072           /* make room for insertion */
00073           for (j = nlines - 1; j >= i; j--)
00074             {
00075               node->angles[j + 1] = node->angles[j];
00076               node->lines[j + 1] = node->lines[j];
00077             }
00078           node->angles[i] = angle;
00079           node->lines[i] = lineid;
00080           break;
00081         }
00082     }
00083 
00084     node->n_lines++;
00085 #ifdef GDEBUG
00086     G_debug (3, "dig_node_add_line(): line %d added position %d n_lines: %d angle %f", lineid, i, node->n_lines, angle);
00087 #endif
00088     return ((int) node->n_lines);
00089 }
00090 
00091 
00092 /* dig_add_node ()
00093 ** add new node to plus structure 
00094 **
00095 ** Returns -1 on error      
00096 **          number of node
00097 */
00098 int 
00099 dig_add_node ( struct Plus_head *plus, double x, double y, double z) {
00100     int  nnum;
00101     P_NODE *node;
00102     
00103     /* First look if we have space in array of pointers to nodes
00104     *  and reallocate if necessary */
00105     G_debug(3, "dig_add_node(): n_nodes = %d, alloc_nodes = %d", plus->n_nodes, plus->alloc_nodes );
00106     if ( plus->n_nodes >= plus->alloc_nodes ) { /* array is full */
00107         if ( dig_alloc_nodes(plus,1000) == -1 )
00108             return -1;
00109     }
00110     
00111     /* allocate node structure */
00112     nnum = plus->n_nodes + 1;
00113 
00114     plus->Node[nnum] = dig_alloc_node();
00115       
00116     node = plus->Node[nnum];
00117     node->x = x;
00118     node->y = y;
00119     node->z = z;
00120  
00121     dig_spidx_add_node (plus, nnum, x, y, z); 
00122     
00123     plus->n_nodes++;
00124     
00125     G_debug(3, "new node = %d, n_nodes = %d, alloc_nodes = %d", nnum, plus->n_nodes, plus->alloc_nodes );
00126      
00127     return ( nnum );
00128 }
00129 
00130 /*  which_node returns the actual index into node arrays of the first set of
00131    *    matching coordinates.  else -1;
00132  */
00133 
00134 int 
00135 dig_which_node ( struct Plus_head *plus, double x, double y, double thresh) {
00136   register int i;
00137   register int first_time;
00138   register int have_match;
00139   int winner;
00140   double least_dist, dist;
00141   P_NODE *node;
00142 
00143   first_time = 1;
00144   have_match = 0;
00145   winner = 0;
00146   least_dist = 0.0;
00147   for (i = 1; i <= plus->n_nodes; i++)
00148     {
00149       if (plus->Node[i] == NULL)
00150         continue;
00151 
00152       node = plus->Node[i];
00153       if ((fabs (node->x - x) <= thresh) &&
00154           (fabs (node->y - y) <= thresh))
00155         {
00156           dist = dist_squared (x, y, node->x, node->y);
00157           if (first_time)
00158             {
00159               least_dist = dist;
00160               first_time = 0;
00161               winner = i;
00162               have_match = 1;
00163             }
00164           if (dist < least_dist)
00165             {
00166               least_dist = dist;
00167               winner = i;
00168             }
00169         }
00170     }
00171 
00172   if (!have_match)
00173     return (-1);
00174 
00175   return (winner);
00176 }                               /*  which_node ()  */
00177 
00178 /* dig_node_get_line_angle ()
00179 **   Lines is specified by line ID in topology, NOT by order number.
00180 **   Negative ID if looking for line end point.
00181 **
00182 **   Returns  line angle <-PI,PI>
00183 **            9 not a line (point/degenerate)
00184 */
00185 float
00186 dig_node_line_angle ( struct Plus_head *plus, int nodeid, int lineid )
00187 {
00188     int    i, nlines;
00189     P_NODE *node;
00190 
00191     G_debug (3, "dig_node_line_angle: node = %d line = %d", nodeid, lineid);
00192 
00193     node = plus->Node[nodeid];
00194     nlines = node->n_lines;
00195 
00196     for (i = 0; i < nlines; i++)
00197     {
00198       if ( node->lines[i] == lineid )
00199           return ( node->angles[i] );
00200     }
00201 
00202     G_fatal_error ("Attempt to read line angle for the line which is not connected to the node: "
00203                    "node = %d line = %d", nodeid, lineid);
00204     
00205     return 0.0; /* not reached */
00206 }
00207 
00208 static double 
00209 dist_squared (double x1, double y1, double x2, double y2)
00210 {
00211   double dx, dy;
00212 
00213   dx = x1 - x2;
00214   dy = y1 - y2;
00215   return (dx * dx + dy * dy);
00216 }

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