Icinga-core 1.4.0
next gen monitoring
cgi/statuswrl.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * STATUSWRL.C - Icinga 3-D (VRML) Network Status View
00004  *
00005  * Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org)
00006  * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org)
00007  *
00008  * Description:
00009  *
00010  * This CGI will dynamically create a 3-D VRML model of all hosts that are
00011  * being monitored on your network.
00012  *
00013  * License:
00014  *
00015  * This program is free software; you can redistribute it and/or modify
00016  * it under the terms of the GNU General Public License version 2 as
00017  * published by the Free Software Foundation.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00027  *
00028  *****************************************************************************/
00029 
00030 #include "../include/config.h"
00031 #include "../include/common.h"
00032 #include "../include/objects.h"
00033 #include "../include/statusdata.h"
00034 
00035 #include "../include/cgiutils.h"
00036 #include "../include/getcgi.h"
00037 #include "../include/cgiauth.h"
00038 
00039 extern char main_config_file[MAX_FILENAME_LENGTH];
00040 extern char url_html_path[MAX_FILENAME_LENGTH];
00041 extern char url_images_path[MAX_FILENAME_LENGTH];
00042 extern char url_logo_images_path[MAX_FILENAME_LENGTH];
00043 extern char url_js_path[MAX_FILENAME_LENGTH];
00044 
00045 extern char *statuswrl_include;
00046 
00047 extern host *host_list;
00048 extern service *service_list;
00049 
00050 extern int default_statuswrl_layout_method;
00051 
00052 
00053 #define ICINGA_VRML_IMAGE               "icingavrml.png"
00054 
00055 #define DEFAULT_NODE_WIDTH              0.5
00056 #define DEFAULT_HORIZONTAL_SPACING      1.0
00057 #define DEFAULT_VERTICAL_SPACING        1.0
00058 
00059 /* needed for auto-layout modes */
00060 #define DEFAULT_NODE_HEIGHT             0.5
00061 #define DEFAULT_NODE_HSPACING           1.0
00062 #define DEFAULT_NODE_VSPACING           1.0
00063 #define CIRCULAR_DRAWING_RADIUS         5.0
00064 
00065 #define LAYOUT_USER_SUPPLIED            0
00066 #define LAYOUT_COLLAPSED_TREE           2
00067 #define LAYOUT_BALANCED_TREE            3
00068 #define LAYOUT_CIRCULAR                 4
00069 
00070 
00071 void calculate_host_coords(void);
00072 void calculate_world_bounds(void);
00073 void display_world(void);
00074 void write_global_vrml_data(void);
00075 void draw_process_icon(void);
00076 void draw_host(host *);
00077 void draw_host_links(void);
00078 void draw_host_link(host *,double,double,double,double,double,double);
00079 int process_cgivars(void);
00080 
00081 int number_of_host_layer_members(host *,int);
00082 int max_child_host_layer_members(host *);
00083 int host_child_depth_separation(host *, host *);
00084 int max_child_host_drawing_width(host *);
00085 
00086 void calculate_balanced_tree_coords(host *,int,int);
00087 void calculate_circular_coords(void);
00088 void calculate_circular_layer_coords(host *,double,double,int,int);
00089 
00090 
00091 authdata current_authdata;
00092 
00093 float link_radius=0.016;
00094 
00095 float floor_width=0.0;
00096 float floor_depth=0.0;
00097 
00098 double min_z_coord=0.0;
00099 double min_x_coord=0.0;
00100 double min_y_coord=0.0;
00101 double max_z_coord=0.0;
00102 double max_x_coord=0.0;
00103 double max_y_coord=0.0;
00104 
00105 double max_world_size=0.0;
00106 
00107 double nagios_icon_x=0.0;
00108 double nagios_icon_y=0.0;
00109 int draw_nagios_icon=FALSE;
00110 
00111 double custom_viewpoint_x=0.0;
00112 double custom_viewpoint_y=0.0;
00113 double custom_viewpoint_z=0.0;
00114 int custom_viewpoint=FALSE;
00115 
00116 float vertical_spacing=DEFAULT_VERTICAL_SPACING;
00117 float horizontal_spacing=DEFAULT_HORIZONTAL_SPACING;
00118 float node_width=DEFAULT_NODE_WIDTH;
00119 float node_height=DEFAULT_NODE_WIDTH;   /* should be the same as the node width */
00120 
00121 int use_textures=TRUE;
00122 int use_text=TRUE;
00123 int use_links=TRUE;
00124 
00125 int layout_method=LAYOUT_USER_SUPPLIED;
00126 
00127 int coordinates_were_specified=FALSE;   /* were drawing coordinates specified with extended host info entries? */
00128 
00129 extern int daemon_check;
00130 
00131 int display_type=DISPLAY_HOSTS;
00132 int show_all_hosts=TRUE;
00133 int show_all_hostgroups=TRUE;
00134 int show_all_servicegroups=TRUE;
00135 
00136 char *host_name="all";
00137 char *host_filter=NULL;
00138 char *hostgroup_name=NULL;
00139 char *servicegroup_name=NULL;
00140 char *service_desc=NULL;
00141 char *service_filter=NULL;
00142 
00143 int CGI_ID=STATUSWRL_CGI_ID;
00144 
00145 int main(int argc, char **argv){
00146         int result;
00147 
00148         /* reset internal variables */
00149         reset_cgi_vars();
00150 
00151         /* read the CGI configuration file */
00152         result=read_cgi_config_file(get_cgi_config_location());
00153         if(result==ERROR){
00154                 document_header(CGI_ID,TRUE);
00155                 return ERROR;
00156                 }
00157 
00158         /* defaults from CGI config file */
00159         layout_method=default_statuswrl_layout_method;
00160 
00161         /* get the arguments passed in the URL */
00162         process_cgivars();
00163 
00164         document_header(CGI_ID,TRUE);
00165 
00166         /* read the main configuration file */
00167         result=read_main_config_file(main_config_file);
00168         if(result==ERROR)
00169                 return ERROR;
00170 
00171         /* read all object configuration data */
00172         result=read_all_object_configuration_data(main_config_file,READ_ALL_OBJECT_DATA);
00173         if(result==ERROR)
00174                 return ERROR;
00175 
00176         /* read all status data */
00177         result=read_all_status_data(get_cgi_config_location(),READ_ALL_STATUS_DATA);
00178         if(result==ERROR && daemon_check==TRUE){
00179                 free_memory();
00180                 return ERROR;
00181                 }
00182 
00183         /* get authentication information */
00184         get_authentication_information(&current_authdata);
00185 
00186         /* display the 3-D VRML world... */
00187         display_world();
00188 
00189         /* free all allocated memory */
00190         free_memory();
00191 
00192         return OK;
00193         }
00194 
00195 int process_cgivars(void){
00196         char **variables;
00197         int error=FALSE;
00198         int x;
00199 
00200         variables=getcgivars();
00201 
00202         for(x=0;variables[x]!=NULL;x++){
00203 
00204                 /* do some basic length checking on the variable identifier to prevent buffer overflows */
00205                 if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){
00206                         x++;
00207                         continue;
00208                         }
00209 
00210 
00211                 /* we found the host argument */
00212                 else if(!strcmp(variables[x],"host")){
00213                         x++;
00214                         if(variables[x]==NULL){
00215                                 error=TRUE;
00216                                 break;
00217                                 }
00218 
00219                         if((host_name=(char *)strdup(variables[x]))==NULL)
00220                                 host_name="all";
00221                         else
00222                                 strip_html_brackets(host_name);
00223 
00224                         if(!strcmp(host_name,"all"))
00225                                 show_all_hosts=TRUE;
00226                         else
00227                                 show_all_hosts=FALSE;
00228                         }
00229 
00230                 /* we found the no textures argument*/
00231                 else if(!strcmp(variables[x],"notextures"))
00232                         use_textures=FALSE;
00233 
00234                 /* we found the no text argument*/
00235                 else if(!strcmp(variables[x],"notext"))
00236                         use_text=FALSE;
00237 
00238                 /* we found the no links argument*/
00239                 else if(!strcmp(variables[x],"nolinks"))
00240                         use_links=FALSE;
00241 
00242                 /* we found the layout method option */
00243                 else if(!strcmp(variables[x],"layout")){
00244                         x++;
00245                         if(variables[x]==NULL){
00246                                 error=TRUE;
00247                                 break;
00248                                 }
00249                         layout_method=atoi(variables[x]);
00250                         }
00251 
00252                 /* we found custom viewpoint coord */
00253                 else if(!strcmp(variables[x],"viewx")){
00254                         x++;
00255                         if(variables[x]==NULL){
00256                                 error=TRUE;
00257                                 break;
00258                                 }
00259                         custom_viewpoint_x=strtod(variables[x],NULL);
00260                         custom_viewpoint=TRUE;
00261                         }
00262                 else if(!strcmp(variables[x],"viewy")){
00263                         x++;
00264                         if(variables[x]==NULL){
00265                                 error=TRUE;
00266                                 break;
00267                                 }
00268                         custom_viewpoint_y=strtod(variables[x],NULL);
00269                         custom_viewpoint=TRUE;
00270                         }
00271                 else if(!strcmp(variables[x],"viewz")){
00272                         x++;
00273                         if(variables[x]==NULL){
00274                                 error=TRUE;
00275                                 break;
00276                                 }
00277                         custom_viewpoint_z=strtod(variables[x],NULL);
00278                         custom_viewpoint=TRUE;
00279                         }
00280 
00281                 /* we found the nodaemoncheck option */
00282                 else if(!strcmp(variables[x],"nodaemoncheck"))
00283                         daemon_check=FALSE;
00284 
00285                 }
00286 
00287         /* free memory allocated to the CGI variables */
00288         free_cgivars(variables);
00289 
00290         return error;
00291         }
00292 
00293 
00294 
00295 /* top-level VRML world generation... */
00296 void display_world(void){
00297         host *temp_host=NULL;
00298 
00299         /* get the url we will use to grab the logo images... */
00300         snprintf(url_logo_images_path,sizeof(url_logo_images_path),"%slogos/",url_images_path);
00301         url_logo_images_path[sizeof(url_logo_images_path)-1]='\x0';
00302 
00303         /* calculate host drawing coordinates */
00304         calculate_host_coords();
00305 
00306         /* calculate world bounds */
00307         calculate_world_bounds();
00308 
00309         /* get the floor dimensions */
00310         if(max_x_coord>0)
00311                 floor_width=(float)(max_x_coord-min_x_coord)+(node_width*2);
00312         else
00313                 floor_width=(float)(max_x_coord+min_x_coord)+(node_width*2);
00314         if(max_z_coord>0)
00315                 floor_depth=(float)(max_z_coord-min_z_coord)+(node_height*2);
00316         else
00317                 floor_depth=(float)(max_z_coord+min_z_coord)+(node_height*2);
00318 
00319         /* write global VRML data */
00320         write_global_vrml_data();
00321 
00322         /* no coordinates were specified, so display warning message */
00323         if(coordinates_were_specified==FALSE){
00324 
00325                 printf("\n");
00326                 printf("Transform{\n");
00327                 printf("translation 0.0 0.0 0.0\n");
00328                 printf("children[\n");
00329 
00330                 printf("Billboard{\n");
00331                 printf("children[\n");
00332                 printf("Shape{\n");
00333                 printf("appearance Appearance {\n");
00334                 printf("material Material {\n");
00335                 printf("diffuseColor 1 0 0\n");
00336                 printf("}\n");
00337                 printf("}\n");
00338                 printf("geometry Text {\n");
00339                 printf("string [ \"Error: You have not supplied any 3-D drawing coordinates.\", \"Read the documentation for more information on supplying\", \"3-D drawing coordinates by defining\", \"extended host information entries in your config files.\" ]\n");
00340                 printf("fontStyle FontStyle {\n");
00341                 printf("family \"TYPEWRITER\"\n");
00342                 printf("size 0.3\n");
00343                 printf("justify \"MIDDLE\"\n");
00344                 printf("}\n");
00345                 printf("}\n");
00346                 printf("}\n");
00347                 printf("]\n");
00348                 printf("}\n");
00349 
00350                 printf("]\n");
00351                 printf("}\n");
00352                 }
00353 
00354         /* coordinates were specified... */
00355         else{
00356 
00357                 /* draw Icinga icon */
00358                 if(layout_method!=LAYOUT_USER_SUPPLIED)
00359                         draw_process_icon();
00360 
00361                 /* draw all hosts */
00362                 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next)
00363                         draw_host(temp_host);
00364 
00365                 /* draw host links */
00366                 draw_host_links();
00367                 }
00368 
00369         return;
00370         }
00371 
00372 
00373 
00374 
00375 /******************************************************************/
00376 /************************ UTILITY FUNCTIONS ***********************/
00377 /******************************************************************/
00378 
00379 /* calculates how many "layers" separate parent and child - used by collapsed tree layout method */
00380 int host_child_depth_separation(host *parent, host *child){
00381         int this_depth=0;
00382         int min_depth=0;
00383         int have_min_depth=FALSE;
00384         host *temp_host;
00385 
00386         if(child==NULL)
00387                 return -1;
00388 
00389         if(parent==child)
00390                 return 0;
00391 
00392         if(is_host_immediate_child_of_host(parent,child)==TRUE)
00393                 return 1;
00394 
00395         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00396 
00397                 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){
00398 
00399                         this_depth=host_child_depth_separation(temp_host,child);
00400 
00401                         if(this_depth>=0 && (have_min_depth==FALSE || (have_min_depth==TRUE && (this_depth<min_depth)))){
00402                                 have_min_depth=TRUE;
00403                                 min_depth=this_depth;
00404                                 }
00405                         }
00406                 }
00407 
00408         if(have_min_depth==FALSE)
00409                 return -1;
00410         else
00411                 return min_depth+1;
00412         }
00413 
00414 
00415 
00416 /* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */
00417 int number_of_host_layer_members(host *parent, int layer){
00418         int current_layer;
00419         int layer_members=0;
00420         host *temp_host;
00421 
00422         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00423 
00424                 current_layer=host_child_depth_separation(parent,temp_host);
00425 
00426                 if(current_layer==layer)
00427                         layer_members++;
00428                 }
00429 
00430         return layer_members;
00431         }
00432 
00433 
00434 
00435 /* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */
00436 int max_child_host_layer_members(host *parent){
00437         int current_layer;
00438         int max_members=1;
00439         int current_members=0;
00440 
00441         for(current_layer=1;;current_layer++){
00442 
00443                 current_members=number_of_host_layer_members(parent,current_layer);
00444 
00445                 if(current_members<=0)
00446                         break;
00447 
00448                 if(current_members>max_members)
00449                         max_members=current_members;
00450                 }
00451 
00452         return max_members;
00453         }
00454 
00455 
00456 
00457 /* calculate max drawing width for host and children - used by balanced tree layout method */
00458 int max_child_host_drawing_width(host *parent){
00459         host *temp_host;
00460         int child_width=0;
00461 
00462         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00463                 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE)
00464                         child_width+=max_child_host_drawing_width(temp_host);
00465                 }
00466 
00467         /* no children, so set width to 1 for this host */
00468         if(child_width==0)
00469                 return 1;
00470 
00471         else
00472                 return child_width;
00473         }
00474         
00475 
00476 
00477 
00478 /******************************************************************/
00479 /********************* CALCULATION FUNCTIONS **********************/
00480 /******************************************************************/
00481 
00482 /* calculates host drawing coordinates */
00483 void calculate_host_coords(void){
00484         host *this_host;
00485         host *temp_host;
00486         int parent_hosts=0;
00487         int max_layer_width=1;
00488         int current_parent_host=0;
00489         int center_x=0;
00490         int offset_x=DEFAULT_NODE_WIDTH/2;
00491         int offset_y=DEFAULT_NODE_WIDTH/2;
00492         int current_layer=0;
00493         int layer_members=0;
00494         int current_layer_member=0;
00495         int max_drawing_width=0;
00496 
00497 
00498         /******************************/
00499         /***** MANUAL LAYOUT MODE *****/
00500         /******************************/
00501 
00502         /* user-supplied coords */
00503         if(layout_method==LAYOUT_USER_SUPPLIED){
00504 
00505                 /* see which hosts we should draw (only those with 3-D coords) */
00506                 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00507 
00508                         if(temp_host->have_3d_coords==TRUE)
00509                                 temp_host->should_be_drawn=TRUE;
00510                         else
00511                                 temp_host->should_be_drawn=FALSE;
00512                         }
00513 
00514                 return;
00515                 }
00516 
00517         /*****************************/
00518         /***** AUTO-LAYOUT MODES *****/
00519         /*****************************/
00520 
00521         /* add empty extended host info entries for all hosts that don't have any */
00522         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00523 
00524                 /* none was found, so add a blank one */
00525                 /*
00526                 if(temp_hostextinfo==NULL)
00527                         add_hostextinfo(temp_host->name,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0.0,0.0,0.0,0,0);
00528                 */
00529 
00530                 /* default z coord should 0 for auto-layout modes unless overridden later */
00531                 /*
00532                 else
00533                 */
00534                 temp_host->z_3d=0.0;
00535                 }
00536 
00537 
00538         /***** COLLAPSED TREE MODE *****/
00539         if(layout_method==LAYOUT_COLLAPSED_TREE){
00540 
00541                 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */
00542                 this_host=NULL;
00543 
00544                 /* find total number of immediate parents for this host */
00545                 parent_hosts=number_of_immediate_parent_hosts(this_host);
00546 
00547                 /* find the max layer width we have... */
00548                 max_layer_width=max_child_host_layer_members(this_host);
00549                 if(parent_hosts>max_layer_width)
00550                         max_layer_width=parent_hosts;
00551 
00552                 /* calculate center x coord */
00553                 center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x;
00554 
00555                 /* coords for Icinga icon if necessary */
00556                 if(this_host==NULL || this_host->parent_hosts==NULL){
00557                         nagios_icon_x=center_x;
00558                         nagios_icon_y=offset_y;
00559                         draw_nagios_icon=TRUE;
00560                         }
00561 
00562                 /* do we need to draw a link to parent(s)? */
00563                 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE)
00564                         offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;
00565 
00566                 /* see which hosts we should draw and calculate drawing coords */
00567                 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00568 
00569                         /* this is an immediate parent of the "main" host we're drawing */
00570                         if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){
00571                                 temp_host->should_be_drawn=TRUE;
00572                                 temp_host->have_3d_coords=TRUE;
00573                                 temp_host->x_3d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2);
00574                                 temp_host->y_3d=offset_y;
00575                                 current_parent_host++;
00576                                 }
00577                         
00578                         /* this is the "main" host we're drawing */
00579                         else if(this_host==temp_host){
00580                                 temp_host->should_be_drawn=TRUE;
00581                                 temp_host->have_3d_coords=TRUE;
00582                                 temp_host->x_3d=center_x;
00583                                 temp_host->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y;
00584                                 }
00585 
00586                         /* else do not draw this host (we might if its a child - see below, but assume no for now) */
00587                         else{
00588                                 temp_host->should_be_drawn=FALSE;
00589                                 temp_host->have_3d_coords=FALSE;
00590                                 }
00591                         }
00592 
00593 
00594                 /* TODO: REORDER CHILD LAYER MEMBERS SO THAT WE MINIMIZE LINK CROSSOVERS FROM PARENT HOSTS */
00595 
00596                 /* draw hosts in child "layers" */
00597                 for(current_layer=1;;current_layer++){
00598                         
00599                         /* how many members in this layer? */
00600                         layer_members=number_of_host_layer_members(this_host,current_layer);
00601 
00602                         if(layer_members==0)
00603                                 break;
00604 
00605                         current_layer_member=0;
00606 
00607                         /* see which hosts are members of this layer and calculate drawing coords */
00608                         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00609 
00610                                 /* is this host a member of the current child layer? */
00611                                 if(host_child_depth_separation(this_host,temp_host)==current_layer){
00612                                         temp_host->should_be_drawn=TRUE;
00613                                         temp_host->have_3d_coords=TRUE;
00614                                         temp_host->x_3d=center_x-(((layer_members*DEFAULT_NODE_WIDTH)+((layer_members-1)*DEFAULT_NODE_HSPACING))/2)+(current_layer_member*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2);
00615                                         if(this_host==NULL)
00616                                                 temp_host->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*current_layer)+offset_y;
00617                                         else
00618                                                 temp_host->y_3d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*(current_layer+1))+offset_y;
00619                                         current_layer_member++;
00620                                         }
00621                                 }
00622                         }
00623 
00624                 }
00625 
00626 
00627         /***** "BALANCED" TREE MODE *****/
00628         else if(layout_method==LAYOUT_BALANCED_TREE){
00629 
00630                 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */
00631                 this_host=NULL;
00632 
00633                 /* find total number of immediate parents for this host */
00634                 parent_hosts=number_of_immediate_parent_hosts(this_host);
00635 
00636                 /* find the max drawing width we have... */
00637                 max_drawing_width=max_child_host_drawing_width(this_host);
00638                 if(parent_hosts>max_drawing_width)
00639                         max_drawing_width=parent_hosts;
00640 
00641                 /* calculate center x coord */
00642                 center_x=(((DEFAULT_NODE_WIDTH*max_drawing_width)+(DEFAULT_NODE_HSPACING*(max_drawing_width-1)))/2)+offset_x;
00643 
00644                 /* coords for Icinga icon if necessary */
00645                 if(this_host==NULL || this_host->parent_hosts==NULL){
00646                         nagios_icon_x=center_x;
00647                         nagios_icon_y=offset_y;
00648                         draw_nagios_icon=TRUE;
00649                         }
00650 
00651                 /* do we need to draw a link to parent(s)? */
00652                 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE)
00653                         offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;
00654 
00655                 /* see which hosts we should draw and calculate drawing coords */
00656                 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00657 
00658                         /* this is an immediate parent of the "main" host we're drawing */
00659                         if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){
00660                                 temp_host->should_be_drawn=TRUE;
00661                                 temp_host->have_3d_coords=TRUE;
00662                                 temp_host->x_3d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2);
00663                                 temp_host->y_3d=offset_y;
00664                                 current_parent_host++;
00665                                 }
00666                         
00667                         /* this is the "main" host we're drawing */
00668                         else if(this_host==temp_host){
00669                                 temp_host->should_be_drawn=TRUE;
00670                                 temp_host->have_3d_coords=TRUE;
00671                                 temp_host->x_3d=center_x;
00672                                 temp_host->y_3d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y;
00673                                 }
00674 
00675                         /* else do not draw this host (we might if its a child - see below, but assume no for now) */
00676                         else{
00677                                 temp_host->should_be_drawn=FALSE;
00678                                 temp_host->have_3d_coords=FALSE;
00679                                 }
00680                         }
00681 
00682                 /* draw all children hosts */
00683                 calculate_balanced_tree_coords(this_host,center_x,DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y);
00684 
00685                 }
00686 
00687 
00688         /***** CIRCULAR LAYOUT MODE *****/
00689         else if(layout_method==LAYOUT_CIRCULAR){
00690 
00691                 /* draw process icon */
00692                 nagios_icon_x=0;
00693                 nagios_icon_y=0;
00694                 draw_nagios_icon=TRUE;
00695 
00696                 /* calculate coordinates for all hosts */
00697                 calculate_circular_coords();
00698                 }
00699 
00700         return;
00701         }
00702 
00703 
00704 
00705 /* calculate world dimensions */
00706 void calculate_world_bounds(void){
00707         host *temp_host;
00708 
00709         min_x_coord=0.0;
00710         min_y_coord=0.0;
00711         min_z_coord=0.0;
00712         max_x_coord=0.0;
00713         max_y_coord=0.0;
00714         max_z_coord=0.0;
00715 
00716         /* check all extended host entries */
00717         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
00718 
00719                 if(temp_host->have_3d_coords==FALSE){
00720                         temp_host->should_be_drawn=FALSE;
00721                         continue;
00722                         }
00723 
00724                 if(temp_host->should_be_drawn==FALSE)
00725                         continue;
00726 
00727                 if(temp_host->x_3d < min_x_coord)
00728                         min_x_coord=temp_host->x_3d;
00729                 else if(temp_host->x_3d > max_x_coord)
00730                         max_x_coord=temp_host->x_3d;
00731                 if(temp_host->y_3d < min_y_coord)
00732                         min_y_coord=temp_host->y_3d;
00733                 else if(temp_host->y_3d > max_y_coord)
00734                         max_y_coord=temp_host->y_3d;
00735                 if(temp_host->z_3d < min_z_coord)
00736                         min_z_coord=temp_host->z_3d;
00737                 else if(temp_host->z_3d > max_z_coord)
00738                         max_z_coord=temp_host->z_3d;
00739 
00740                 coordinates_were_specified=TRUE;
00741                 }
00742 
00743         /* no drawing coordinates were specified */
00744         if(coordinates_were_specified==FALSE){
00745                 min_x_coord=0.0;
00746                 max_x_coord=0.0;
00747                 min_y_coord=0.0;
00748                 max_y_coord=0.0;
00749                 min_z_coord=0.0;
00750                 max_z_coord=6.0;
00751                 }
00752 
00753         max_world_size=max_x_coord-min_x_coord;
00754         if(max_world_size<(max_y_coord-min_y_coord))
00755                 max_world_size=max_y_coord-min_y_coord;
00756         if(max_world_size<(max_z_coord-min_z_coord))
00757                 max_world_size=max_z_coord-min_z_coord;
00758 
00759         return;
00760         }
00761 
00762 
00763 /******************************************************************/
00764 /*********************** DRAWING FUNCTIONS ************************/
00765 /******************************************************************/
00766 
00767 
00768 /* write global VRML data */
00769 void write_global_vrml_data(void){
00770         host *temp_host;
00771         float visibility_range=0.0;
00772         float viewpoint_z=0.0;
00773 
00774         /* write VRML code header */
00775         printf("#VRML V2.0 utf8\n");
00776 
00777         /* write world information */
00778         printf("\n");
00779         printf("WorldInfo{\n");
00780         printf("title \"%s 3-D Network Status View\"\n", PROGRAM_NAME);
00781         printf("info [\"Copyright (c) 1999-2002 Ethan Galstad\"\n");
00782         printf("\"egalstad@nagios.org\"]\n");
00783         printf("}\n");
00784 
00785         /* background color */
00786         printf("\n");
00787         printf("Background{\n");
00788         printf("skyColor 0.1 0.1 0.15\n");
00789         printf("}\n");
00790 
00791         /* calculate visibility range - don't let it get too low */
00792         visibility_range=(max_world_size*2.0);
00793         if(visibility_range<25.0)
00794                 visibility_range=25.0;
00795 
00796         /* write fog information */
00797         printf("\n");
00798         printf("Fog{\n");
00799         printf("color 0.1 0.1 0.15\n");
00800         printf("fogType \"EXPONENTIAL\"\n");
00801         printf("visibilityRange %2.2f\n",visibility_range);
00802         printf("}\n");
00803 
00804         /* custom viewpoint */
00805         if(custom_viewpoint==TRUE){
00806                 printf("\n");
00807                 printf("Viewpoint{\n");
00808                 printf("position %2.2f %2.2f %2.2f\n",custom_viewpoint_x,custom_viewpoint_y,custom_viewpoint_z);
00809                 printf("fieldOfView 0.78\n");
00810                 printf("description \"Entry Viewpoint\"\n");
00811                 printf("}\n");
00812                 }
00813 
00814         /* host close-up viewpoint */
00815         if(show_all_hosts==FALSE){
00816 
00817                 temp_host=find_host(host_name);
00818                 if(temp_host!=NULL && temp_host->have_3d_coords==TRUE){
00819                         printf("\n");
00820                         printf("Viewpoint{\n");
00821                         printf("position %2.3f %2.3f %2.3f\n",temp_host->x_3d,temp_host->y_3d,temp_host->z_3d+5.0);
00822                         printf("fieldOfView 0.78\n");
00823                         printf("description \"Host Close-Up Viewpoint\"\n");
00824                         printf("}\n");
00825                         }
00826                 }
00827 
00828         /* calculate z coord for default viewpoint - don't get too close */
00829         viewpoint_z=max_world_size;
00830         if(viewpoint_z<10.0)
00831                 viewpoint_z=10.0;
00832 
00833         /* default viewpoint */
00834         printf("\n");
00835         printf("Viewpoint{\n");
00836         printf("position %2.2f %2.2f %2.2f\n",min_x_coord+((max_x_coord-min_x_coord)/2.0),min_y_coord+((max_y_coord-min_y_coord)/2.0),viewpoint_z);
00837         printf("fieldOfView 0.78\n");
00838         printf("description \"Default Viewpoint\"\n");
00839         printf("}\n");
00840 
00841         /* problem timer */
00842         printf("DEF ProblemTimer TimeSensor{\n");
00843         printf("loop TRUE\n");
00844         printf("cycleInterval 5\n");
00845         printf("}\n");
00846 
00847         /* host text prototype */
00848         printf("PROTO HostText[\n");
00849         printf("field MFString the_text [\"\"]\n");
00850         printf("field SFColor font_color 0.6 0.6 0.6");
00851         printf("]\n");
00852         printf("{\n");
00853         printf("Billboard{\n");
00854         printf("children[\n");
00855         printf("Shape{\n");
00856         printf("appearance Appearance {\n");
00857         printf("material Material {\n");
00858         printf("diffuseColor IS font_color\n");
00859         printf("}\n");
00860         printf("}\n");
00861         printf("geometry Text {\n");
00862         printf("string IS the_text\n");
00863         printf("fontStyle FontStyle {\n");
00864         printf("family \"TYPEWRITER\"\n");
00865         printf("size 0.1\n");
00866         printf("justify \"MIDDLE\"\n");
00867         printf("}\n");
00868         printf("}\n");
00869         printf("}\n");
00870         printf("]\n");
00871         printf("}\n");
00872         printf("}\n");
00873 
00874         /* include user-defined world */
00875         if(statuswrl_include!=NULL && coordinates_were_specified==TRUE && layout_method==LAYOUT_USER_SUPPLIED){
00876                 printf("\n");
00877                 printf("Inline{\n");
00878                 printf("url \"%s%s\"\n",url_html_path,statuswrl_include);
00879                 printf("}\n");
00880                 }
00881 
00882         return;
00883         }
00884 
00885 
00886 
00887 /* draws a host */
00888 void draw_host(host *temp_host){
00889         hoststatus *temp_hoststatus=NULL;
00890         char state_string[16]="";
00891         double x, y, z;
00892         char *vrml_safe_hostname=NULL;
00893         int a, ch;
00894 
00895         if(temp_host==NULL)
00896                 return;
00897 
00898         /* make sure we have the coordinates */
00899         if(temp_host->have_3d_coords==FALSE)
00900                 return;
00901         else{
00902                 x=temp_host->x_3d;
00903                 y=temp_host->y_3d;
00904                 z=temp_host->z_3d;
00905                 }
00906 
00907         /* make the host name safe for embedding in VRML */
00908         vrml_safe_hostname=(char *)strdup(temp_host->name);
00909         if(vrml_safe_hostname==NULL)
00910                 return;
00911         for(a=0;vrml_safe_hostname[a]!='\x0';a++){
00912                 ch=vrml_safe_hostname[a];
00913                 if((ch<'a' || ch>'z') && (ch<'A' || ch>'Z') && (ch<'0' || ch>'9'))
00914                         vrml_safe_hostname[a]='_';
00915                 }
00916 
00917         /* see if user is authorized to view this host  */
00918         if(is_authorized_for_host(temp_host,&current_authdata)==FALSE)
00919                 return;
00920 
00921         /* get the status of the host */
00922         temp_hoststatus=find_hoststatus(temp_host->name);
00923 
00924         printf("\n");
00925 
00926 
00927         /* host object */
00928         printf("Anchor{\n");
00929         printf("children[\n");
00930 
00931         printf("Transform {\n");
00932         printf("translation %2.2f %2.2f %2.2f\n",x,y,z);
00933         printf("children [\n");
00934 
00935         printf("DEF Host%s Shape{\n",vrml_safe_hostname);
00936         printf("appearance Appearance{\n");
00937         printf("material DEF HostMat%s Material{\n",vrml_safe_hostname);
00938         if(temp_hoststatus==NULL)
00939                 printf("emissiveColor 0.2 0.2 0.2\ndiffuseColor 0.2 0.2 0.2\n");
00940         else if(temp_hoststatus->status==HOST_UP)
00941                 printf("emissiveColor 0.2 1.0 0.2\ndiffuseColor 0.2 1.0 0.2\n");
00942         else
00943                 printf("emissiveColor 1.0 0.2 0.2\ndiffuseColor 1.0 0.2 0.2\n");
00944         printf("transparency 0.4\n");
00945         printf("}\n");
00946         if(use_textures==TRUE && temp_host->vrml_image!=NULL){
00947                 printf("texture ImageTexture{\n");
00948                 printf("url \"%s%s\"\n",url_logo_images_path,temp_host->vrml_image);
00949                 printf("}\n");
00950                 }
00951         printf("}\n");
00952         printf("geometry Box{\n");
00953         printf("size %2.2f %2.2f %2.2f\n",node_width,node_width,node_width);
00954         printf("}\n");
00955         printf("}\n");
00956 
00957         printf("]\n");
00958         printf("}\n");
00959 
00960         printf("]\n");
00961         printf("description \"View status details for host '%s' (%s)\"\n",(temp_host->display_name!=NULL)?temp_host->display_name:temp_host->name,temp_host->alias);
00962         printf("url \"%s?host=%s\"\n",STATUS_CGI,temp_host->name);
00963         printf("}\n");
00964 
00965 
00966         /* draw status text */
00967         if(use_text==TRUE){
00968 
00969                 printf("\n");
00970                 printf("Transform{\n");
00971                 printf("translation %2.3f %2.3f %2.3f\n",x,y+DEFAULT_NODE_WIDTH,z);
00972                 printf("children[\n");
00973                 printf("HostText{\n");
00974 
00975                 if(temp_hoststatus!=NULL){
00976                         if(temp_hoststatus->status==HOST_UP)
00977                                 printf("font_color 0 1 0\n");
00978                         else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE)
00979                                 printf("font_color 1 0 0\n");
00980                         }
00981                 printf("the_text [\"%s\", \"%s\", ",(temp_host->display_name!=NULL)?temp_host->display_name:temp_host->name,temp_host->alias);
00982                 if(temp_hoststatus==NULL)
00983                         strcpy(state_string,"UNKNOWN");
00984                 else{
00985                         if(temp_hoststatus->status==HOST_DOWN)
00986                                 strcpy(state_string,"DOWN");
00987                         else if(temp_hoststatus->status==HOST_UNREACHABLE)
00988                                 strcpy(state_string,"UNREACHABLE");
00989                         else if(temp_hoststatus->status==HOST_PENDING)
00990                                 strcpy(state_string,"PENDING");
00991                         else
00992                                 strcpy(state_string,"UP");
00993                         }
00994                 printf("\"%s\"]\n",state_string);
00995 
00996                 printf("}\n");
00997                 printf("]\n");
00998                 printf("}\n");
00999                 }
01000 
01001         /* host is down or unreachable, so make it fade in and out */
01002         if(temp_hoststatus!=NULL && (temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE))
01003                 printf("ROUTE ProblemTimer.fraction_changed TO HostMat%s.set_transparency\n",vrml_safe_hostname);
01004 
01005         free(vrml_safe_hostname);
01006 
01007         return;
01008         }
01009 
01010 
01011 
01012 /* draw links between hosts */
01013 void draw_host_links(void){
01014         host *parent_host;
01015         host *child_host;
01016 
01017         if(use_links==FALSE)
01018                 return;
01019 
01020         for(child_host=host_list;child_host!=NULL;child_host=child_host->next){
01021 
01022                 if(child_host->have_3d_coords==FALSE)
01023                         continue;
01024 
01025                 /* check authorization */
01026                 if(is_authorized_for_host(child_host,&current_authdata)==FALSE)
01027                         continue;
01028 
01029                 /* draw a link from this host to all of its parent hosts */
01030                 for(parent_host=host_list;parent_host!=NULL;parent_host=parent_host->next){
01031 
01032                         if(is_host_immediate_child_of_host(child_host,parent_host)==TRUE){
01033 
01034                                 if(parent_host->have_3d_coords==FALSE)
01035                                         continue;
01036                                 
01037                                 /* check authorization */
01038                                 if(is_authorized_for_host(parent_host,&current_authdata)==FALSE)
01039                                         continue;
01040 
01041                                 /* draw the link between the child and parent hosts */
01042                                 draw_host_link(parent_host,parent_host->x_3d,parent_host->y_3d,parent_host->z_3d,child_host->x_3d,child_host->y_3d,child_host->z_3d);
01043                                 }
01044                         }
01045                 }
01046 
01047         
01048         return;
01049         }
01050 
01051 
01052 
01053 
01054 /* draws a link from a parent host to a child host */
01055 void draw_host_link(host *hst,double x0, double y0, double z0, double x1, double y1, double z1){
01056 
01057         printf("\n");
01058 
01059         if(hst!=NULL)
01060                 printf("# Host '%s' LINK\n",hst->name);
01061 
01062         printf("Shape{\n");
01063 
01064         printf("appearance DEF MATslategrey_0_ Appearance {\n");
01065         printf("material Material {\n");
01066         printf("diffuseColor 0.6 0.6 0.6\n");
01067         printf("ambientIntensity 0.5\n");
01068         printf("emissiveColor 0.6 0.6 0.6\n");
01069         printf("}\n");
01070         printf("}\n");
01071 
01072         printf("geometry IndexedLineSet{\n");
01073         printf("coord Coordinate{\n");
01074         printf("point [ %2.3f %2.3f %2.3f, %2.3f %2.3f %2.3f ]\n",x0,y0,z0,x1,y1,z1);
01075         printf("}\n");
01076         printf("coordIndex [ 0,1,-1 ]\n");
01077         printf("}\n");
01078 
01079         printf("}\n");
01080 
01081         return;
01082         }
01083 
01084 
01085 
01086 /* draw process icon */
01087 void draw_process_icon(void){
01088         host *child_host;
01089 
01090         if(draw_nagios_icon==FALSE)
01091                 return;
01092 
01093         /* draw process icon */
01094         printf("\n");
01095 
01096 
01097         printf("Anchor{\n");
01098         printf("children[\n");
01099 
01100         printf("Transform {\n");
01101         printf("translation %2.2f %2.2f %2.2f\n",nagios_icon_x,nagios_icon_y,0.0);
01102         printf("children [\n");
01103 
01104         printf("DEF ProcessNode Shape{\n");
01105         printf("appearance Appearance{\n");
01106         printf("material Material{\n");
01107         printf("emissiveColor 0.5 0.5 0.5\n");
01108         printf("diffuseColor 0.5 0.5 0.5\n");
01109         printf("transparency 0.2\n");
01110         printf("}\n");
01111         if(use_textures==TRUE){
01112                 printf("texture ImageTexture{\n");
01113                 printf("url \"%s%s\"\n",url_logo_images_path,ICINGA_VRML_IMAGE);
01114                 printf("}\n");
01115                 }
01116         printf("}\n");
01117         printf("geometry Box{\n");
01118         printf("size %2.2f %2.2f %2.2f\n",node_width*3.0,node_width*3.0,node_width*3.0);
01119         printf("}\n");
01120         printf("}\n");
01121 
01122         printf("]\n");
01123         printf("}\n");
01124 
01125         printf("]\n");
01126         printf("description \"View %s Process Information\"\n", PROGRAM_NAME);
01127         printf("url \"%s?type=%d\"\n",EXTINFO_CGI,DISPLAY_PROCESS_INFO);
01128         printf("}\n");
01129 
01130 
01131         if(use_links==FALSE)
01132                 return;
01133 
01134         /* draw links to immediate child hosts */
01135         for(child_host=host_list;child_host!=NULL;child_host=child_host->next){
01136 
01137                 if(child_host->have_3d_coords==FALSE)
01138                         continue;
01139 
01140                 /* check authorization */
01141                 if(is_authorized_for_host(child_host,&current_authdata)==FALSE)
01142                         continue;
01143 
01144                 /* draw a link to the host */
01145                 if(is_host_immediate_child_of_host(NULL,child_host)==TRUE)
01146                         draw_host_link(NULL,nagios_icon_x,nagios_icon_y,0.0,child_host->x_3d,child_host->y_3d,child_host->z_3d);
01147                 }
01148 
01149         return;
01150         }
01151 
01152 
01153 
01154 
01155 /******************************************************************/
01156 /***************** COORDINATE CALCULATION FUNCTIONS ***************/
01157 /******************************************************************/
01158 
01159 /* calculates coords of a host's children - used by balanced tree layout method */
01160 void calculate_balanced_tree_coords(host *parent, int x, int y){
01161         int parent_drawing_width;
01162         int start_drawing_x;
01163         int current_drawing_x;
01164         int this_drawing_width;
01165         host *temp_host;
01166 
01167         /* calculate total drawing width of parent host */
01168         parent_drawing_width=max_child_host_drawing_width(parent);
01169 
01170         /* calculate starting x coord */
01171         start_drawing_x=x-(((DEFAULT_NODE_WIDTH*parent_drawing_width)+(DEFAULT_NODE_HSPACING*(parent_drawing_width-1)))/2);
01172         current_drawing_x=start_drawing_x;
01173 
01174 
01175         /* calculate coords for children */
01176         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
01177 
01178                 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){
01179 
01180                         /* get drawing width of child host */
01181                         this_drawing_width=max_child_host_drawing_width(temp_host);
01182 
01183                         temp_host->x_3d=current_drawing_x+(((DEFAULT_NODE_WIDTH*this_drawing_width)+(DEFAULT_NODE_HSPACING*(this_drawing_width-1)))/2);
01184                         temp_host->y_3d=y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING;
01185                         temp_host->have_3d_coords=TRUE;
01186                         temp_host->should_be_drawn=TRUE;
01187                         
01188                         current_drawing_x+=(this_drawing_width*DEFAULT_NODE_WIDTH)+((this_drawing_width-1)*DEFAULT_NODE_HSPACING)+DEFAULT_NODE_HSPACING;
01189 
01190                         /* recurse into child host ... */
01191                         calculate_balanced_tree_coords(temp_host,temp_host->x_3d,temp_host->y_3d);
01192                         }
01193 
01194                 }
01195 
01196         return;
01197         }
01198 
01199 
01200 /* calculate coords of all hosts in circular layout method */
01201 void calculate_circular_coords(void){
01202 
01203         /* calculate all host coords, starting with first layer */
01204         calculate_circular_layer_coords(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS);
01205 
01206         return;
01207         }
01208         
01209 
01210 /* calculates coords of all hosts in a particular "layer" in circular layout method */
01211 void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius){
01212         int parent_drawing_width=0;
01213         int this_drawing_width=0;
01214         int immediate_children=0;
01215         double current_drawing_angle=0.0;
01216         double this_drawing_angle=0.0;
01217         double available_angle=0.0;
01218         double clipped_available_angle=0.0;
01219         double average_child_angle=0.0;
01220         double x_coord=0.0;
01221         double y_coord=0.0;
01222         host *temp_host;
01223 
01224 
01225         /* get the total number of immediate children to this host */
01226         immediate_children=number_of_immediate_child_hosts(parent);
01227 
01228         /* bail out if we're done */
01229         if(immediate_children==0)
01230                 return;
01231 
01232         /* calculate total drawing "width" of parent host */
01233         parent_drawing_width=max_child_host_drawing_width(parent);
01234 
01235         /* calculate average angle given to each child host */
01236         average_child_angle=(double)(useable_angle/(double)immediate_children);
01237 
01238         /* calculate initial drawing angle */
01239         current_drawing_angle=start_angle;
01240 
01241 
01242         /* calculate coords for children */
01243         for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){
01244 
01245                 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){
01246 
01247                         /* get drawing width of child host */
01248                         this_drawing_width=max_child_host_drawing_width(temp_host);
01249 
01250                         /* calculate angle this host gets for drawing */
01251                         available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width);
01252 
01253                         /* clip available angle if necessary */
01254                         /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
01255                         clipped_available_angle=360.0/layer;
01256                         if(available_angle<clipped_available_angle)
01257                                 clipped_available_angle=available_angle;
01258 
01259                         /* calculate the exact angle at which we should draw this child */
01260                         this_drawing_angle=current_drawing_angle+(available_angle/2.0);
01261 
01262                         /* compensate for angle overflow */
01263                         while(this_drawing_angle>=360.0)
01264                                 this_drawing_angle-=360.0;
01265                         while(this_drawing_angle<0.0)
01266                                 this_drawing_angle+=360.0;
01267 
01268                         /* calculate drawing coords of this host using good ol' geometry... */
01269                         x_coord=-(sin(-this_drawing_angle*(M_PI/180.0))*radius);
01270                         y_coord=-(sin((90+this_drawing_angle)*(M_PI/180.0))*radius);
01271 
01272                         temp_host->x_3d=(int)x_coord;
01273                         temp_host->y_3d=(int)y_coord;
01274                         temp_host->have_3d_coords=TRUE;
01275                         temp_host->should_be_drawn=TRUE;
01276 
01277                         /* recurse into child host ... */
01278                         calculate_circular_layer_coords(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS);
01279 
01280                         /* increment current drawing angle */
01281                         current_drawing_angle+=available_angle;
01282                         }
01283                 }
01284 
01285         return;
01286         }
01287 
01288 
 All Data Structures Files Functions Variables Typedefs Defines