g_half.c

Go to the documentation of this file.
00001 /*                        G _ H A L F . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1985-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 g_  */
00023 
00024 /*@{*/
00025 /** @file g_half.c
00026  *  Intersect a ray with a Halfspace.
00027  *
00028  *
00029  *  A HALFSPACE is defined by an outward pointing normal vector,
00030  *  and the distance from the origin to the plane, which is defined
00031  *  by N and d.
00032  *
00033  *  With outward pointing normal vectors,
00034  *  the ray enters the half-space defined by a plane when D dot N < 0,
00035  *  is parallel to the plane when D dot N = 0, and exits otherwise.
00036  *
00037  *  The inside of the halfspace bounded by the plane
00038  *  consists of all points P such that
00039  *      VDOT(P,N) - N[3] <= 0,
00040  *
00041  *  where N[3] stores the value d.
00042  *  See the remarks in h/vmath.h for more details.
00043  *
00044  *  Authors -
00045  *      Michael John Muuss
00046  *      Dave Becker             (Vectorization)
00047  *
00048  *  Source -
00049  *      SECAD/VLD Computing Consortium, Bldg 394
00050  *      The U. S. Army Ballistic Research Laboratory
00051  *      Aberdeen Proving Ground, Maryland  21005
00052  *
00053  */
00054 
00055 #ifndef lint
00056 static const char RCShalf[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_half.c,v 14.12 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00057 #endif
00058 
00059 #include "common.h"
00060 
00061 #include <stddef.h>
00062 #include <stdio.h>
00063 #include <math.h>
00064 
00065 #include "machine.h"
00066 #include "vmath.h"
00067 #include "raytrace.h"
00068 #include "nmg.h"
00069 #include "db.h"
00070 #include "rtgeom.h"
00071 #include "./debug.h"
00072 
00073 struct half_specific  {
00074         plane_t half_eqn;               /* Plane equation, outward normal */
00075         vect_t  half_Xbase;             /* "X" basis direction */
00076         vect_t  half_Ybase;             /* "Y" basis direction */
00077 };
00078 #define HALF_NULL       ((struct half_specific *)0)
00079 
00080 const struct bu_structparse rt_hlf_parse[] = {
00081     { "%f", 3, "N", bu_offsetof(struct rt_half_internal, eqn[X]), BU_STRUCTPARSE_FUNC_NULL },
00082     { "%f", 1, "d", bu_offsetof(struct rt_half_internal, eqn[3]), BU_STRUCTPARSE_FUNC_NULL },
00083     { {'\0','\0','\0','\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL }
00084 };
00085 /**
00086  *                      R T _ H L F _ P R E P
00087  */
00088 int
00089 rt_hlf_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00090 {
00091         struct rt_half_internal *hip;
00092         register struct half_specific *halfp;
00093 
00094         hip = (struct rt_half_internal *)ip->idb_ptr;
00095         RT_HALF_CK_MAGIC(hip);
00096 
00097         /*
00098          * Process a HALFSPACE, which is represented as a
00099          * normal vector, and a distance.
00100          */
00101         BU_GETSTRUCT( halfp, half_specific );
00102         stp->st_specific = (genptr_t)halfp;
00103 
00104         VMOVE( halfp->half_eqn, hip->eqn );
00105         halfp->half_eqn[3] = hip->eqn[3];
00106 
00107         /* Select one point on the halfspace as the "center" */
00108         VSCALE( stp->st_center, halfp->half_eqn, halfp->half_eqn[3] );
00109 
00110         /* X and Y basis for uv map */
00111         bn_vec_perp( halfp->half_Xbase, halfp->half_eqn );
00112         VCROSS( halfp->half_Ybase, halfp->half_Xbase, halfp->half_eqn );
00113         VUNITIZE( halfp->half_Xbase );
00114         VUNITIZE( halfp->half_Ybase );
00115 
00116         /* No bounding sphere or bounding RPP is possible */
00117         VSETALL( stp->st_min, -INFINITY);
00118         VSETALL( stp->st_max,  INFINITY);
00119 
00120         stp->st_aradius = INFINITY;
00121         stp->st_bradius = INFINITY;
00122         return(0);              /* OK */
00123 }
00124 
00125 /**
00126  *                      R T _ H L F _ P R I N T
00127  */
00128 void
00129 rt_hlf_print(register const struct soltab *stp)
00130 {
00131         register const struct half_specific *halfp =
00132                 (struct half_specific *)stp->st_specific;
00133 
00134         if( halfp == HALF_NULL )  {
00135                 bu_log("half(%s):  no data?\n", stp->st_name);
00136                 return;
00137         }
00138         VPRINT( "Normal", halfp->half_eqn );
00139         bu_log( "d = %f\n", halfp->half_eqn[3] );
00140         VPRINT( "Xbase", halfp->half_Xbase );
00141         VPRINT( "Ybase", halfp->half_Ybase );
00142 }
00143 
00144 /**
00145  *                      R T _ H L F _ S H O T
00146  *
00147  * Function -
00148  *      Shoot a ray at a HALFSPACE
00149  *
00150  * Algorithm -
00151  *      The intersection distance is computed.
00152  *
00153  * Returns -
00154  *      0       MISS
00155  *      >0      HIT
00156  */
00157 int
00158 rt_hlf_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00159 {
00160         register struct half_specific *halfp =
00161                 (struct half_specific *)stp->st_specific;
00162         LOCAL fastf_t   in, out;        /* ray in/out distances */
00163 
00164         in = -INFINITY;
00165         out = INFINITY;
00166 
00167         {
00168                 FAST fastf_t    slant_factor;   /* Direction dot Normal */
00169                 FAST fastf_t    norm_dist;
00170 
00171                 norm_dist = VDOT( halfp->half_eqn, rp->r_pt ) - halfp->half_eqn[3];
00172                 if( (slant_factor = -VDOT( halfp->half_eqn, rp->r_dir )) < -1.0e-10 )  {
00173                         /* exit point, when dir.N < 0.  out = min(out,s) */
00174                         out = norm_dist/slant_factor;
00175                         if( !NEAR_ZERO(out, INFINITY) )
00176                                 return(0);      /* MISS */
00177                 } else if ( slant_factor > 1.0e-10 )  {
00178                         /* entry point, when dir.N > 0.  in = max(in,s) */
00179                         in = norm_dist/slant_factor;
00180                         if( !NEAR_ZERO(in, INFINITY) )
00181                                 return(0);      /* MISS */
00182                 }  else  {
00183                         /* ray is parallel to plane when dir.N == 0.
00184                          * If it is outside the solid, stop now */
00185                         if( norm_dist > 0.0 )
00186                                 return(0);      /* MISS */
00187                 }
00188         }
00189         if( RT_G_DEBUG & DEBUG_ARB8 )
00190                 bu_log("half: in=%f, out=%f\n", in, out);
00191 
00192         {
00193                 register struct seg *segp;
00194 
00195                 RT_GET_SEG( segp, ap->a_resource );
00196                 segp->seg_stp = stp;
00197                 segp->seg_in.hit_dist = in;
00198                 segp->seg_out.hit_dist = out;
00199                 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00200         }
00201         return(2);                      /* HIT */
00202 }
00203 
00204 #define RT_HALF_SEG_MISS(SEG)   (SEG).seg_stp=RT_SOLTAB_NULL
00205 
00206 /**
00207  *                      R T _ H L F _ V S H O T
00208  *
00209  *  This is the Becker vector version
00210  */
00211 void
00212 rt_hlf_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00213                                /* An array of solid pointers */
00214                                /* An array of ray pointers */
00215                                /* array of segs (results returned) */
00216                                /* Number of ray/object pairs */
00217 
00218 {
00219         register int    i;
00220         register struct half_specific *halfp;
00221         LOCAL fastf_t   in, out;        /* ray in/out distances */
00222         FAST fastf_t    slant_factor;   /* Direction dot Normal */
00223         FAST fastf_t    norm_dist;
00224 
00225         /* for each ray/halfspace pair */
00226 #       include "noalias.h"
00227         for(i = 0; i < n; i++){
00228                 if (stp[i] == 0) continue; /* indicates "skip this pair" */
00229 
00230                 halfp = (struct half_specific *)stp[i]->st_specific;
00231 
00232                 in = -INFINITY;
00233                 out = INFINITY;
00234 
00235                 norm_dist = VDOT(halfp->half_eqn, rp[i]->r_pt) - halfp->half_eqn[3];
00236 
00237                 if((slant_factor = -VDOT(halfp->half_eqn, rp[i]->r_dir)) <
00238                                                                 -1.0e-10) {
00239                         /* exit point, when dir.N < 0.  out = min(out,s) */
00240                         out = norm_dist/slant_factor;
00241                 } else if ( slant_factor > 1.0e-10 )  {
00242                         /* entry point, when dir.N > 0.  in = max(in,s) */
00243                         in = norm_dist/slant_factor;
00244                 }  else  {
00245                         /* ray is parallel to plane when dir.N == 0.
00246                          * If it is outside the solid, stop now */
00247                         if( norm_dist > 0.0 ) {
00248                                 RT_HALF_SEG_MISS(segp[i]);      /* No hit */
00249                                 continue;
00250                         }
00251                 }
00252 
00253                 /* HIT */
00254                 segp[i].seg_stp = stp[i];
00255                 segp[i].seg_in.hit_dist = in;
00256                 segp[i].seg_out.hit_dist = out;
00257         }
00258 }
00259 
00260 /**
00261  *                      R T _ H L F _ N O R M
00262  *
00263  *  Given ONE ray distance, return the normal and entry/exit point.
00264  *  The normal is already filled in.
00265  */
00266 void
00267 rt_hlf_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00268 {
00269         register struct half_specific *halfp =
00270                 (struct half_specific *)stp->st_specific;
00271         FAST fastf_t f;
00272 
00273         RT_CK_SOLTAB(stp);
00274         RT_CK_RAY(rp);
00275 
00276         /*
00277          * At most one normal is really defined, but whichever one
00278          * it is, it has value half_eqn.
00279          */
00280         VMOVE( hitp->hit_normal, halfp->half_eqn );
00281 
00282         /* We are expected to compute hit_point here.  May be infinite. */
00283         f = hitp->hit_dist;
00284         if( f <= -INFINITY )  {
00285                 bu_log("rt_hlf_norm:  hit_dist = -INFINITY, unable to compute pt.\n");
00286                 VSETALL( hitp->hit_point, -INFINITY );
00287         } else if( f >= INFINITY )  {
00288                 bu_log("rt_hlf_norm:  hit_dist = +INFINITY, unable to compute pt.\n");
00289                 VSETALL( hitp->hit_point, INFINITY );
00290         } else {
00291                 VJOIN1( hitp->hit_point, rp->r_pt, f, rp->r_dir );
00292         }
00293 }
00294 
00295 /**
00296  *                      R T _ H L F _ C U R V E
00297  *
00298  *  Return the "curvature" of the halfspace.
00299  *  Pick a principle direction orthogonal to normal, and
00300  *  indicate no curvature.
00301  */
00302 void
00303 rt_hlf_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00304 {
00305         register struct half_specific *halfp =
00306                 (struct half_specific *)stp->st_specific;
00307 
00308         bn_vec_ortho( cvp->crv_pdir, halfp->half_eqn );
00309         cvp->crv_c1 = cvp->crv_c2 = 0;
00310 }
00311 
00312 /**
00313  *                      R T _ H L F _ U V
00314  *
00315  *  For a hit on a face of an HALF, return the (u,v) coordinates
00316  *  of the hit point.  0 <= u,v <= 1.
00317  *  u extends along the Xbase direction
00318  *  v extends along the "Ybase" direction
00319  *  Note that a "toroidal" map is established, varying each from
00320  *  0 up to 1 and then back down to 0 again.
00321  */
00322 void
00323 rt_hlf_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00324 {
00325         register struct half_specific *halfp =
00326                 (struct half_specific *)stp->st_specific;
00327         LOCAL vect_t P_A;
00328         FAST fastf_t f;
00329         auto double ival;
00330 
00331         f = hitp->hit_dist;
00332         if( f <= -INFINITY || f >= INFINITY )  {
00333                 bu_log("rt_hlf_uv:  infinite dist\n");
00334                 rt_pr_hit( "rt_hlf_uv", hitp );
00335                 uvp->uv_u = uvp->uv_v = 0;
00336                 uvp->uv_du = uvp->uv_dv = 0;
00337                 return;
00338         }
00339         VSUB2( P_A, hitp->hit_point, stp->st_center );
00340 
00341         f = VDOT( P_A, halfp->half_Xbase )/10000;
00342         if( f <= -INFINITY || f >= INFINITY )  {
00343                 bu_log("rt_hlf_uv:  bad X vdot\n");
00344                 VPRINT("Xbase", halfp->half_Xbase);
00345                 rt_pr_hit( "rt_hlf_uv", hitp );
00346                 VPRINT("st_center", stp->st_center );
00347                 f = 0;
00348         }
00349         if( f < 0 )  f = -f;
00350         f = modf( f, &ival );
00351         if( f < 0.5 )
00352                 uvp->uv_u = 2 * f;              /* 0..1 */
00353         else
00354                 uvp->uv_u = 2 * (1 - f);        /* 1..0 */
00355 
00356         f = VDOT( P_A, halfp->half_Ybase )/10000;
00357         if( f <= -INFINITY || f >= INFINITY )  {
00358                 bu_log("rt_hlf_uv:  bad Y vdot\n");
00359                 VPRINT("Xbase", halfp->half_Ybase);
00360                 rt_pr_hit( "rt_hlf_uv", hitp );
00361                 VPRINT("st_center", stp->st_center );
00362                 f = 0;
00363         }
00364         if( f < 0 )  f = -f;
00365         f = modf( f, &ival );
00366         if( f < 0.5 )
00367                 uvp->uv_v = 2 * f;              /* 0..1 */
00368         else
00369                 uvp->uv_v = 2 * (1 - f);        /* 1..0 */
00370 
00371         if( uvp->uv_u < 0 || uvp->uv_v < 0 )  {
00372                 if( RT_G_DEBUG )
00373                         bu_log("half_uv: bad uv=%f,%f\n", uvp->uv_u, uvp->uv_v);
00374                 /* Fix it up */
00375                 if( uvp->uv_u < 0 )  uvp->uv_u = (-uvp->uv_u);
00376                 if( uvp->uv_v < 0 )  uvp->uv_v = (-uvp->uv_v);
00377         }
00378 
00379         uvp->uv_du = uvp->uv_dv =
00380                 (ap->a_rbeam + ap->a_diverge * hitp->hit_dist) / (10000/2);
00381         if( uvp->uv_du < 0 || uvp->uv_dv < 0 )  {
00382                 rt_pr_hit( "rt_hlf_uv", hitp );
00383                 uvp->uv_du = uvp->uv_dv = 0;
00384         }
00385 }
00386 
00387 /**
00388  *                      R T _ H L F _ F R E E
00389  */
00390 void
00391 rt_hlf_free(struct soltab *stp)
00392 {
00393         register struct half_specific *halfp =
00394                 (struct half_specific *)stp->st_specific;
00395 
00396         bu_free( (char *)halfp, "half_specific");
00397 }
00398 
00399 /**
00400  *                      R T _ H L F _ C L A S S
00401  *
00402  *  Classify this halfspace against a bounding RPP.
00403  *  Since this is an infinite solid, it is very important that this
00404  *  function properly.
00405  *
00406  *  Returns -
00407  *      BN_CLASSIFY_INSIDE
00408  *      BN_CLASSIFY_OVERLAPPING
00409  *      BN_CLASSIFY_OUTSIDE
00410  */
00411 int
00412 rt_hlf_class(register const struct soltab *stp, const fastf_t *min, const fastf_t *max, const struct bn_tol *tol)
00413 {
00414         register const struct half_specific *halfp =
00415                 (struct half_specific *)stp->st_specific;
00416 
00417         if( halfp == HALF_NULL ) {
00418                 bu_log( "half(%s):  no data?\n", stp->st_name );
00419                 return 0;
00420         }
00421 
00422         return bn_hlf_class( halfp->half_eqn, min, max, tol );
00423 }
00424 
00425 /**
00426  *                      R T _ H L F _ P L O T
00427  *
00428  *  The representation of a halfspace is an OUTWARD pointing
00429  *  normal vector, and the distance of the plane from the origin.
00430  *
00431  *  Drawing a halfspace is difficult when using a finite display.
00432  *  Drawing the boundary plane is hard enough.
00433  *  We just make a cross in the plane, with the outward normal
00434  *  drawn shorter.
00435  */
00436 int
00437 rt_hlf_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00438 {
00439         struct rt_half_internal *hip;
00440         vect_t cent;            /* some point on the plane */
00441         vect_t xbase, ybase;    /* perpendiculars to normal */
00442         vect_t x1, x2;
00443         vect_t y1, y2;
00444         vect_t tip;
00445 
00446         RT_CK_DB_INTERNAL(ip);
00447         hip = (struct rt_half_internal *)ip->idb_ptr;
00448         RT_HALF_CK_MAGIC(hip);
00449 
00450         /* Invent a "center" point on the plane -- point closets to origin */
00451         VSCALE( cent, hip->eqn, hip->eqn[3] );
00452 
00453         /* The use of "x" and "y" here is not related to the axis */
00454         bn_vec_perp( xbase, &hip->eqn[0] );
00455         VCROSS( ybase, xbase, hip->eqn );
00456 
00457         /* Arrange for the cross to be 2 meters across */
00458         VUNITIZE( xbase );
00459         VUNITIZE( ybase);
00460         VSCALE( xbase, xbase, 1000 );
00461         VSCALE( ybase, ybase, 1000 );
00462 
00463         VADD2( x1, cent, xbase );
00464         VSUB2( x2, cent, xbase );
00465         VADD2( y1, cent, ybase );
00466         VSUB2( y2, cent, ybase );
00467 
00468         RT_ADD_VLIST( vhead, x1, BN_VLIST_LINE_MOVE );  /* the cross */
00469         RT_ADD_VLIST( vhead, x2, BN_VLIST_LINE_DRAW );
00470         RT_ADD_VLIST( vhead, y1, BN_VLIST_LINE_MOVE );
00471         RT_ADD_VLIST( vhead, y2, BN_VLIST_LINE_DRAW );
00472         RT_ADD_VLIST( vhead, x2, BN_VLIST_LINE_DRAW );  /* the box */
00473         RT_ADD_VLIST( vhead, y1, BN_VLIST_LINE_DRAW );
00474         RT_ADD_VLIST( vhead, x1, BN_VLIST_LINE_DRAW );
00475         RT_ADD_VLIST( vhead, y2, BN_VLIST_LINE_DRAW );
00476 
00477         VSCALE( tip, hip->eqn, 500 );
00478         VADD2( tip, cent, tip );
00479         RT_ADD_VLIST( vhead, cent, BN_VLIST_LINE_MOVE );
00480         RT_ADD_VLIST( vhead, tip, BN_VLIST_LINE_DRAW );
00481         return(0);
00482 }
00483 /**
00484  *                      H A L F _ X F O R M
00485  *
00486  *  Returns -
00487  *      -1      failure
00488  *       0      success
00489  */
00490 int
00491 rt_hlf_xform(
00492         struct rt_db_internal   *op,
00493         const mat_t             mat,
00494         struct rt_db_internal *ip,
00495         int             free,
00496         struct db_i     *dbip,
00497         struct resource *resp)
00498 {
00499         struct rt_half_internal *hip, *hop;
00500         point_t                 orig_pt, pt;
00501         register double         f,t;
00502 
00503         RT_CK_DB_INTERNAL( ip );
00504         hip = (struct rt_half_internal *)ip->idb_ptr;
00505         RT_HALF_CK_MAGIC(hip);
00506         RT_CK_DB_INTERNAL( op );
00507         hop = (struct rt_half_internal *)op->idb_ptr;
00508         RT_HALF_CK_MAGIC(hop);
00509 
00510         /* Pick a point on the original halfspace */
00511         VSCALE( orig_pt, hip->eqn, hip->eqn[1*ELEMENTS_PER_VECT] );
00512 
00513         /* Transform the picked point and the normal */
00514         MAT4X3VEC( hop->eqn, mat, hip->eqn);
00515         MAT4X3PNT( pt, mat, orig_pt);
00516 
00517         /*
00518          * We are done with the input solid so free it if required.
00519          */
00520         if (free && ip != op)
00521                 rt_db_free_internal( ip, resp );
00522 
00523         /*
00524          * The transformed normal is all that is required.
00525          * The new distance is found from the transforemd point on the plane.
00526          */
00527         hop->eqn[3] = VDOT( pt, hop->eqn );
00528 
00529         /* Now some safety.  Verify that the normal has unit length */
00530         f = MAGNITUDE( hop->eqn);
00531         if ( f < SMALL ) {
00532                 bu_log("rt_half_xform: bad normal, len = %g\n", f);
00533                 return(-1);
00534         }
00535         t = f - 1.0;
00536         if ( !NEAR_ZERO( t, 0.001 ) ) {
00537                 /* Restore normal to unit length */
00538                 f = 1/f;
00539                 VSCALE( hop->eqn, hop->eqn, f );
00540                 hip->eqn[3] *= f;
00541         }
00542         return 0;
00543 }
00544 /**
00545  *                      H A L F _ I M P O R T
00546  *
00547  *  Returns -
00548  *      -1      failure
00549  *       0      success
00550  */
00551 int
00552 rt_hlf_import(struct rt_db_internal *ip, const struct bu_external *ep, const fastf_t *mat, const struct db_i *dbip)
00553 {
00554         struct rt_half_internal *hip;
00555         union record    *rp;
00556         point_t         orig_pt;
00557         point_t         pt;
00558         fastf_t         orig_eqn[3*2];
00559         register double f,t;
00560 
00561         BU_CK_EXTERNAL( ep );
00562         rp = (union record *)ep->ext_buf;
00563         if( rp->u_id != ID_SOLID )  {
00564                 bu_log("rt_hlf_import: defective record, id=x%x\n", rp->u_id);
00565                 return(-1);
00566         }
00567 
00568         RT_CK_DB_INTERNAL( ip );
00569         ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00570         ip->idb_type = ID_HALF;
00571         ip->idb_meth = &rt_functab[ID_HALF];
00572         ip->idb_ptr = bu_malloc( sizeof(struct rt_half_internal), "rt_half_internal");
00573         hip = (struct rt_half_internal *)ip->idb_ptr;
00574         hip->magic = RT_HALF_INTERNAL_MAGIC;
00575 
00576         rt_fastf_float( orig_eqn, rp->s.s_values, 2 );  /* 2 floats too many */
00577 
00578         /* Pick a point on the original halfspace */
00579         VSCALE( orig_pt, orig_eqn, orig_eqn[1*ELEMENTS_PER_VECT] );
00580 
00581         /* Transform the point, and the normal */
00582         MAT4X3VEC( hip->eqn, mat, orig_eqn );
00583         MAT4X3PNT( pt, mat, orig_pt );
00584 
00585         /*
00586          *  The transformed normal is all that is required.
00587          *  The new distance is found from the transformed point on the plane.
00588          */
00589         hip->eqn[3] = VDOT( pt, hip->eqn );
00590 
00591         /* Verify that normal has unit length */
00592         f = MAGNITUDE( hip->eqn );
00593         if( f < SMALL )  {
00594                 bu_log("rt_hlf_import:  bad normal, len=%g\n", f );
00595                 return(-1);             /* BAD */
00596         }
00597         t = f - 1.0;
00598         if( !NEAR_ZERO( t, 0.001 ) )  {
00599                 /* Restore normal to unit length */
00600                 f = 1/f;
00601                 VSCALE( hip->eqn, hip->eqn, f );
00602                 hip->eqn[3] *= f;
00603         }
00604         return(0);                      /* OK */
00605 }
00606 
00607 /**
00608  *                      R T _ H L F _ E X P O R T
00609  */
00610 int
00611 rt_hlf_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00612 {
00613         struct rt_half_internal *hip;
00614         union record            *rec;
00615 
00616         RT_CK_DB_INTERNAL(ip);
00617         if( ip->idb_type != ID_HALF )  return(-1);
00618         hip = (struct rt_half_internal *)ip->idb_ptr;
00619         RT_HALF_CK_MAGIC(hip);
00620 
00621         BU_CK_EXTERNAL(ep);
00622         ep->ext_nbytes = sizeof(union record);
00623         ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "half external");
00624         rec = (union record *)ep->ext_buf;
00625 
00626         rec->s.s_id = ID_SOLID;
00627         rec->s.s_type = HALFSPACE;
00628         VMOVE( rec->s.s_values, hip->eqn );
00629         rec->s.s_values[3] = hip->eqn[3] * local2mm;
00630 
00631         return(0);
00632 }
00633 
00634 /**
00635  *                      R T _ H L F _ I M P O R T 5
00636  */
00637 int
00638 rt_hlf_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00639 {
00640         struct rt_half_internal *hip;
00641         point_t                 tmp_pt, new_pt;
00642         plane_t                 tmp_plane;
00643         register double         f,t;
00644 
00645         BU_CK_EXTERNAL( ep );
00646 
00647         BU_ASSERT_LONG( ep->ext_nbytes, ==, SIZEOF_NETWORK_DOUBLE * 4 );
00648 
00649         RT_CK_DB_INTERNAL( ip );
00650         ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00651         ip->idb_type = ID_HALF;
00652         ip->idb_meth = &rt_functab[ID_HALF];
00653         ip->idb_ptr = bu_malloc( sizeof(struct rt_half_internal), "rt_half_internal");
00654 
00655         hip = (struct rt_half_internal *)ip->idb_ptr;
00656         hip->magic = RT_HALF_INTERNAL_MAGIC;
00657 
00658         /* Convert from database (network) to internal (host) format */
00659         ntohd( (unsigned char *)tmp_plane, ep->ext_buf, 4 );
00660 
00661         /* to apply modeling transformations, create a temporary
00662          * normal vector and point on the plane
00663          */
00664         VSCALE( tmp_pt, tmp_plane, tmp_plane[3] );
00665 
00666         /* transform both the point and the vector */
00667         MAT4X3VEC( hip->eqn, mat, tmp_plane );
00668         MAT4X3PNT( new_pt, mat, tmp_pt );
00669 
00670         /* and calculate the new distance */
00671         hip->eqn[3] = VDOT( hip->eqn, new_pt );
00672 
00673         /* Verify that normal has unit length */
00674         f = MAGNITUDE( hip->eqn );
00675         if( f < SMALL )  {
00676                 bu_log("rt_hlf_import:  bad normal, len=%g\n", f );
00677                 return(-1);             /* BAD */
00678         }
00679         t = f - 1.0;
00680         if( !NEAR_ZERO( t, 0.001 ) )  {
00681                 /* Restore normal to unit length */
00682                 f = 1/f;
00683                 VSCALE( hip->eqn, hip->eqn, f );
00684                 hip->eqn[3] *= f;
00685         }
00686         return(0);                      /* OK */
00687 }
00688 
00689 /**
00690  *              R T _ H A L F _ E X P O R T 5
00691  */
00692 int
00693 rt_hlf_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00694 {
00695         struct rt_half_internal         *hip;
00696         fastf_t                         scaled_dist;
00697 
00698         RT_CK_DB_INTERNAL( ip );
00699         if( ip->idb_type != ID_HALF ) return -1;
00700         hip = (struct rt_half_internal *)ip->idb_ptr;
00701         RT_HALF_CK_MAGIC( hip );
00702 
00703         BU_CK_EXTERNAL( ep );
00704         ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE * 4;
00705         ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "half external" );
00706 
00707         /* only the distance needs to be scaled */
00708         scaled_dist = hip->eqn[3] * local2mm;
00709 
00710         /* Convert from internal (host) to database (network) format */
00711         /* the normal */
00712         htond( (unsigned char *)ep->ext_buf, (unsigned char *)hip->eqn, 3 );
00713         /* the distance */
00714         htond( ((unsigned char *)(ep->ext_buf)) + SIZEOF_NETWORK_DOUBLE*3,
00715                 (unsigned char *)&scaled_dist, 1);
00716 
00717         return 0;
00718 }
00719 
00720 /**
00721  *                      R T _ H L F _ D E S C R I B E
00722  *
00723  *  Make human-readable formatted presentation of this solid.
00724  *  First line describes type of solid.
00725  *  Additional lines are indented one tab, and give parameter values.
00726  */
00727 int
00728 rt_hlf_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
00729 {
00730         register struct rt_half_internal        *hip =
00731                 (struct rt_half_internal *)ip->idb_ptr;
00732         char    buf[256];
00733 
00734         RT_HALF_CK_MAGIC(hip);
00735         bu_vls_strcat( str, "halfspace\n");
00736 
00737         sprintf(buf, "\tN (%g, %g, %g) d=%g\n",
00738                 V3INTCLAMPARGS(hip->eqn),               /* should have unit length */
00739                 INTCLAMP(hip->eqn[3] * mm2local) );
00740         bu_vls_strcat( str, buf );
00741 
00742         return(0);
00743 }
00744 
00745 /**
00746  *                      R T _ H L F _ I F R E E
00747  *
00748  *  Free the storage associated with the rt_db_internal version of this solid.
00749  */
00750 void
00751 rt_hlf_ifree(struct rt_db_internal *ip)
00752 {
00753         RT_CK_DB_INTERNAL(ip);
00754         bu_free( ip->idb_ptr, "hlf ifree" );
00755         ip->idb_ptr = GENPTR_NULL;
00756 }
00757 
00758 /**
00759  *                      R T _ H L F _ T E S S
00760  */
00761 int
00762 rt_hlf_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00763 {
00764         struct rt_half_internal *vip;
00765 #if 0
00766         register int    i;
00767         struct shell    *s;
00768         struct vertex   **verts;        /* dynamic array of pointers */
00769         struct vertex   ***vertp;       /* dynam array of ptrs to pointers */
00770         struct faceuse  *fu;
00771 #endif
00772 
00773         RT_CK_DB_INTERNAL(ip);
00774         vip = (struct rt_half_internal *)ip->idb_ptr;
00775         RT_HALF_CK_MAGIC(vip);
00776 
00777         /* XXX tess routine needed */
00778         return(-1);
00779 }
00780 
00781 /*@}*/
00782 /*
00783  * Local Variables:
00784  * mode: C
00785  * tab-width: 8
00786  * c-basic-offset: 4
00787  * indent-tabs-mode: t
00788  * End:
00789  * ex: shiftwidth=4 tabstop=8
00790  */

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