fortray.c

Go to the documentation of this file.
00001 /*                       F O R T R A Y . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1986-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup fort */
00023 /*@{*/
00024 /** @file fortray.c
00025  *  A general-purpose set of FORTRAN-callable interface routines to
00026  *  permit any FORTRAN program to use LIBRT, the ray-tracing library
00027  *  of the BRL-CAD Package.
00028  *
00029  *
00030  *  Author -
00031  *      Michael John Muuss
00032  *
00033  *  Source -
00034  *      SECAD/VLD Computing Consortium, Bldg 394
00035  *      The U. S. Army Ballistic Research Laboratory
00036  *      Aberdeen Proving Ground, Maryland  21005-5066
00037  *
00038  */
00039 #ifndef lint
00040 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/fortray.c,v 14.12 2006/09/16 02:04:24 lbutler Exp $";
00041 #endif
00042 
00043 #include "common.h"
00044 
00045 
00046 
00047 #include <stdio.h>
00048 #include <string.h>
00049 #include "machine.h"
00050 #include "vmath.h"
00051 #include "raytrace.h"
00052 
00053 
00054 extern struct resource rt_uniresource;  /* From librt/shoot.c */
00055 
00056 int                     fr_hit(struct application *ap, struct partition *headp, struct seg *segp), fr_miss(struct application *ap);
00057 struct partition        fr_global_head;
00058 
00059 /*
00060  *                      F R _ S T R I N G _ C 2 F
00061  *
00062  *  Take a null-terminated C string, and place it with space padding
00063  *  on the right into a FORTRAN string of given length.
00064  */
00065 void
00066 fr_string_c2f(register char *fstr, register char *cstr, register int flen)
00067 {
00068         register int    i;
00069 
00070         for( i=0; i < flen; i++ )  {
00071                 if( (fstr[i] = cstr[i]) == '\0' )  break;
00072         }
00073         for( ; i < flen; i++ )
00074                 fstr[i] = ' ';
00075 }
00076 
00077 /*
00078  *                      F R _ S T R I N G _ F 2 C
00079  *
00080  *  Take a FORTRAN string with a length, and return a pointer to
00081  *  null terminated copy of that string in a STATIC buffer.
00082  */
00083 static char *
00084 fr_string_f2c(char *str, int maxlen)
00085 {
00086         static char     buf[512];
00087         int     len;
00088         int     i;
00089 
00090         len = sizeof(buf)-1;
00091         if( maxlen < len )  len = maxlen;
00092         strncpy( buf, str, len );
00093         buf[len] = '\0';
00094 
00095         /* Remove any trailing blanks */
00096         for( i=strlen(buf)-1; i >= 0; i-- )  {
00097                 if( buf[i] != ' ' && buf[i] != '\n' )  break;
00098                 buf[i] = '\0';
00099         }
00100         return(buf);
00101 }
00102 
00103 /*
00104  *                      F R D I R
00105  *
00106  *  FORTRAN to RT interface for rt_dirbuild()
00107  *
00108  *  XXX NOTE Apollo FORTRAN passes string length as extra (invisible)
00109  *  argument, by value.  Other systems probably are different.
00110  *
00111  *  XXX On some systems, the C standard I/O library may need to be
00112  *  initialized here (eg, Cray).
00113  */
00114 void
00115 BU_FORTRAN(frdir,FRDIR)(struct rt_i **rtip, char *filename, int *filelen)
00116 {
00117         char    *file;
00118 
00119         file = fr_string_f2c( filename, *filelen );
00120         *rtip = rt_dirbuild( file, (char *)0, 0 );
00121 }
00122 
00123 /*
00124  *                      F R T R E E
00125  *
00126  *  Add another top-level tree to the in-core geometry.
00127  */
00128 void
00129 BU_FORTRAN(frtree,FRTREE)(int           *fail,
00130                           struct rt_i   **rtip,
00131                           char          *objname,
00132                           int           *objlen)
00133 {
00134         char    *obj;
00135 
00136         RT_CHECK_RTI(*rtip);
00137 
00138         obj = fr_string_f2c( objname, *objlen );
00139         *fail = rt_gettree( *rtip, obj );
00140 }
00141 
00142 /*
00143  *      F R P R E P
00144  *
00145  */
00146 void
00147 BU_FORTRAN(frprep,FRPREP)(struct rt_i   **rtip)
00148 {
00149     RT_CHECK_RTI(*rtip);
00150     rt_prep(*rtip);
00151 }
00152 
00153 
00154 #define CONTEXT_LEN     6       /* Reserve this many FORTRAN Doubles for each */
00155 struct context {
00156         double          co_vpriv[3];
00157         struct soltab   *co_stp;
00158         char            *co_priv;
00159         int             co_inflip;
00160 };
00161 
00162 /*
00163  *                      F R S H O T
00164  *
00165  * NOTE that the [0] element here corresponds with the caller's (1) element.
00166  */
00167 void
00168 BU_FORTRAN(frshot,FRSHOT)(int                   *nloc,          /* input & output */
00169                           double                *indist,        /* output only */
00170                           double                *outdist,
00171                           int                   *region_ids,
00172                           struct context        *context,
00173                           struct rt_i           **rtip,         /* input only */
00174                           double                *pt,
00175                           double                *dir)
00176 {
00177         struct application      ap;
00178         register struct partition *pp;
00179         int             ret;
00180         register int    i;
00181 
00182         RT_CHECK_RTI(*rtip);
00183 
00184         if( *nloc <= 0 )  {
00185                 bu_log("ERROR frshot: nloc=%d\n", *nloc);
00186                 *nloc = 0;
00187                 return;
00188         }
00189 
00190         RT_APPLICATION_INIT(&ap);
00191         ap.a_ray.r_pt[X] = pt[0];
00192         ap.a_ray.r_pt[Y] = pt[1];
00193         ap.a_ray.r_pt[Z] = pt[2];
00194         ap.a_ray.r_dir[X] = dir[0];
00195         ap.a_ray.r_dir[Y] = dir[1];
00196         ap.a_ray.r_dir[Z] = dir[2];
00197         VUNITIZE( ap.a_ray.r_dir );
00198         ap.a_hit = fr_hit;
00199         ap.a_miss = fr_miss;
00200         ap.a_level = 0;
00201         ap.a_onehit = *nloc * 2;
00202         ap.a_resource = &rt_uniresource;
00203         rt_uniresource.re_magic = RESOURCE_MAGIC;
00204         ap.a_purpose = "frshot";
00205         ap.a_rt_i = *rtip;
00206 
00207         /*
00208          *  Actually fire the ray
00209          *  The list of results will be linked to fr_global_head
00210          *  by fr_hit(), for further use below.
00211          *
00212          *  It is a bit risky to rely on the segment structures
00213          *  pointed to by the partition list to still be valid,
00214          *  because rt_shootray has already put them back on the
00215          *  free segment queue.  However, they will remain unchanged
00216          *  until the next call to rt_shootray(), so copying out the
00217          *  data here will work fine.
00218          */
00219         ret = rt_shootray( &ap );
00220 
00221         if( ret <= 0 )  {
00222                 /* Signal no hits */
00223                 *nloc = 0;
00224                 return;
00225         }
00226 
00227         /* Copy hit information from linked list to argument arrays */
00228         pp = fr_global_head.pt_forw;
00229         if( pp == &fr_global_head )  {
00230                 *nloc = 0;
00231                 return;
00232         }
00233         for( i=0 ; i < *nloc; i++, pp=pp->pt_forw )  {
00234                 register struct context *ctp;
00235 
00236                 if( pp == &fr_global_head )  break;
00237                 indist[i] = pp->pt_inhit->hit_dist;
00238                 outdist[i] = pp->pt_outhit->hit_dist;
00239                 /* This might instead be reg_regionid ?? */
00240                 region_ids[i] = pp->pt_regionp->reg_bit+1;
00241                 ctp = &context[i];
00242                 ctp->co_stp = pp->pt_inseg->seg_stp;
00243                 VMOVE( ctp->co_vpriv, pp->pt_inhit->hit_vpriv);
00244                 ctp->co_priv = pp->pt_inhit->hit_private;
00245                 ctp->co_inflip = pp->pt_inflip;
00246         }
00247         *nloc = i;      /* Will have been incremented above, if successful */
00248 
00249         /* Free linked list storage */
00250         for( pp = fr_global_head.pt_forw; pp != &fr_global_head;  )  {
00251                 register struct partition *newpp;
00252 
00253                 newpp = pp;
00254                 pp = pp->pt_forw;
00255                 FREE_PT(newpp, (&rt_uniresource));
00256         }
00257 }
00258 
00259 int
00260 fr_hit(struct application *ap, struct partition *headp, struct seg *segp)
00261 {
00262         if( headp->pt_forw == headp )  return(0);
00263 
00264         /* Steal the linked list, hang it off a global header */
00265         fr_global_head.pt_forw = headp->pt_forw;
00266         fr_global_head.pt_back = headp->pt_back;
00267         fr_global_head.pt_back->pt_forw = &fr_global_head;
00268         fr_global_head.pt_forw->pt_back = &fr_global_head;
00269 
00270         headp->pt_forw = headp->pt_back = headp;
00271         return(1);
00272 }
00273 
00274 int
00275 fr_miss(struct application *ap)
00276 {
00277         fr_global_head.pt_forw = fr_global_head.pt_back = &fr_global_head;
00278         return(0);
00279 }
00280 /*
00281  *                      F R N O R M
00282  *
00283  *  Given the data returned by a previous call to frshot(),
00284  *  compute the surface normal at the entry point to the indicated solid.
00285  *
00286  *  In order to save storage, and copying time, frshot() saved only
00287  *  the minimum amount of data required.  Here, the hit and xray
00288  *  structures are reconstructed, suitable for passing to RT_HIT_NORM.
00289  */
00290 void
00291 BU_FORTRAN(frnorm,FRNORM)(double                *normal,        /* output only */
00292                           int                   *index,         /* input only */
00293                           double                *indist,
00294                           struct context        *context,
00295                           double                *pt,
00296                           double                *dir)
00297 {
00298         register struct context *ctp;
00299         struct hit      hit;
00300 #if 0
00301         struct xray     ray;
00302 #endif
00303         struct soltab   *stp;
00304         register int    i;
00305 
00306         i = *index-1;           /* Selects which inhit is used */
00307 
00308 #if 0
00309         /* Reconstruct the ray structure */
00310         ray.r_pt[X] = pt[0];
00311         ray.r_pt[Y] = pt[1];
00312         ray.r_pt[Z] = pt[2];
00313         ray.r_dir[X] = dir[0];
00314         ray.r_dir[Y] = dir[1];
00315         ray.r_dir[Z] = dir[2];
00316         /* Unitize r_dir? */
00317 #endif
00318 
00319         /* Reconstruct the hit structure */
00320         hit.hit_dist = indist[i];
00321         ctp = &context[i];
00322         stp = ctp->co_stp;
00323         VMOVE( hit.hit_vpriv, ctp->co_vpriv );
00324         hit.hit_private = ctp->co_priv;
00325 
00326 #if 0
00327         RT_HIT_NORMAL( normal, &hit, stp, &ray, ctp->co_inflip );
00328 #else
00329         /* The new macro doesn't use ray argument */
00330         RT_HIT_NORMAL( normal, &hit, stp, NULL, ctp->co_inflip );
00331 #endif
00332 }
00333 
00334 /*
00335  *                      F R N R E G
00336  *
00337  *  Return the number of regions that exist in the model
00338  */
00339 void
00340 BU_FORTRAN(frnreg,FRNREG)(int *nreg, struct rt_i **rtip)
00341 {
00342         *nreg = (*rtip)->nregions;
00343 }
00344 
00345 /*
00346  *                      F R N A M E
00347  *
00348  *  Given a region number (range 1..nregions), return the
00349  *  right-hand portion of the name in the provided buffer.
00350  *
00351  *  XXX buflen is provided "automaticly" on the Apollo.
00352  */
00353 void
00354 BU_FORTRAN(frname,FRNAME)(char          *fbuf,
00355                           int           *region_num,
00356                           struct rt_i   **rtip,
00357                           int           fbuflen)
00358 {
00359         register struct region *rp;
00360         int     i;
00361         int     len;
00362         int     offset;
00363         int     rnum;
00364         char    buf[512];
00365 
00366         rnum = *region_num-1;
00367         if( rnum < 0 || rnum > (*rtip)->nregions )  {
00368                 sprintf( buf, "Region id %d out of range, max=%ld",
00369                         *region_num, (long)((*rtip)->nregions) );
00370                 fr_string_c2f( fbuf, buf, fbuflen );
00371                 return;
00372         }
00373         for( BU_LIST_FOR( rp, region, &((*rtip)->HeadRegion) ) )  {
00374                 if( rp->reg_bit != rnum )  continue;
00375                 len = strlen( rp->reg_name );
00376                 offset = 0;
00377                 if( len >= fbuflen )  {
00378                         offset = len-(fbuflen+1);
00379                         len -= (fbuflen+1);
00380                 }
00381                 strncpy( fbuf, rp->reg_name+offset, len );
00382                 for( i=offset+len; i < fbuflen; i++ )
00383                         fbuf[i] = ' ';
00384                 return;
00385         }
00386         sprintf(fbuf, "Unable to find region %d", *region_num );
00387         fr_string_c2f( fbuf, buf, fbuflen );
00388 }
00389 
00390 /*@}*/
00391 /*
00392  * Local Variables:
00393  * mode: C
00394  * tab-width: 8
00395  * c-basic-offset: 4
00396  * indent-tabs-mode: t
00397  * End:
00398  * ex: shiftwidth=4 tabstop=8
00399  */

Generated on Mon Sep 18 01:24:49 2006 for BRL-CAD by  doxygen 1.4.6