BRL-CAD
#include "common.h"
#include <stddef.h>
#include <string.h>
#include <math.h>
#include "bio.h"
#include "bu/cv.h"
#include "vmath.h"
#include "db.h"
#include "rtgeom.h"
#include "raytrace.h"
#include "nmg.h"
#include "../../librt_private.h"
Include dependency graph for part.c:

Go to the source code of this file.

Data Structures

struct  part_specific
 
struct  part_state
 
struct  part_vert_strip
 

Macros

#define RT_PARTICLE_SURF_VSPHERE   1
 
#define RT_PARTICLE_SURF_BODY   2
 
#define RT_PARTICLE_SURF_HSPHERE   3
 

Functions

int rt_part_bbox (struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *tol)
 
int rt_part_prep (struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
 
void rt_part_print (register const struct soltab *stp)
 
int rt_part_shot (struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
 
void rt_part_norm (register struct hit *hitp, struct soltab *stp, register struct xray *rp)
 
void rt_part_curve (register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
 
void rt_part_uv (struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
 
void rt_part_free (register struct soltab *stp)
 
HIDDEN void rt_part_hemisphere (register point_t(*ov), register fastf_t *v, fastf_t *a, fastf_t *b, fastf_t *h)
 
int rt_part_plot (struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol, const struct rt_view_info *info)
 
int rt_part_tess (struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
 
int rt_part_import4 (struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
 
int rt_part_export4 (struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
 
int rt_part_import5 (struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
 
int rt_part_export5 (struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
 
int rt_part_describe (struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
 
void rt_part_ifree (struct rt_db_internal *ip)
 
int rt_part_params (struct pc_pc_set *ps, const struct rt_db_internal *ip)
 
void rt_part_volume (fastf_t *vol, const struct rt_db_internal *ip)
 
void rt_part_surf_area (fastf_t *area, const struct rt_db_internal *ip)
 

Variables

const struct bu_structparse rt_part_parse []
 

Detailed Description

Intersect a ray with a "particle" solid, which can have three main forms: sphere, hemisphere-tipped cylinder (lozenge), and hemisphere-tipped cone. This code draws on the examples of g_rec (Davisson) & g_sph (Dykstra).

Algorithm for the hemisphere-tipped cylinder and cone cases -

Given V, H, vrad, and hrad, there is a set of points on this cylinder

{ (x, y, z) | (x, y, z) is on cylinder }

Through a series of Affine Transformations, this set of points will be transformed into a set of points on a unit cylinder (or cone) with the transformed base (V') located at the origin with a transformed radius of 1 (vrad'). The height of the cylinder (or cone) along the +Z axis is +1 (i.e., H' = (0, 0, 1)), with a transformed radius of hrad/vrad.

{ (x', y', z') | (x', y', z') is on cylinder at origin }

The transformation from X to X' is accomplished by:

finding two unit vectors A and B mutually perpendicular, and perp. to H.

X' = S(R(X - V))

where R(X) rotates H to the +Z axis, and S(X) scales vrad' to 1 and |H'| to 1.

where R(X) = (A/(|A|)) (B/(|B|)) . X (H/(|H|))

and S(X) = (1/|A| 0 0) (0 1/|B| 0) . X (0 0 1/|H|)

To find the intersection of a line with the surface of the cylinder, consider the parametric line L:

    L : { P(n) | P + t(n) . D }

Call W the actual point of intersection between L and the cylinder. Let W' be the point of intersection between L' and the unit cylinder.

    L' : { P'(n) | P' + t(n) . D' }

W = invR(invS(W')) + V

Where W' = k D' + P'.

If Dx' and Dy' are both 0, then there is no hit on the cylinder; but the end spheres need checking.

The equation for the unit cylinder ranging along Z is

 x**2 + y**2 - r**2 = 0

and the equation for a unit cone ranging along Z is

 x**2 + y**2 - f(z)**2 = 0

where in this case f(z) linearly interpolates the radius of the cylinder from vrad (r1) to hrad (r2) as z ranges from 0 to 1, i.e.:

 f(z) = (r2-r1)/1 * z + r1

let m = (r2-r1)/1, and substitute:

 x**2 + y**2 - (m*z+r1)**2 = 0 .

For the cylinder case, r1 == r2, so m == 0, and everything simplifies.

The parametric formulation for line L' is P' + t * D', or

 x = Px' + t * Dx'
 y = Py' + t * Dy'
 z = Pz' + t * Dz' .

Substituting these definitions into the formula for the unit cone gives

 (Px'+t*Dx')**2 + (Py'+t*Dy')**2 + (m*(Pz'+t*Dz')+r1)**2 = 0

Expanding and regrouping terms gives a quadratic in "t" which has the form

 a * t**2 + b * t + c = 0

where

 a = Dx'**2 + Dy'**2 - m**2 * Dz'**2
 b = 2 * (Px'*Dx' + Py'*Dy' - m**2 * Pz'*Dz' - m*r1*Dz')
 c = Px'**2 + Py'**2 - m**2 * Pz'**2 - 2*m*r1*Pz' - r1**2

Line L' hits the infinitely tall unit cone at point(s) W' which correspond to the roots of the quadratic. The quadratic formula yields values for "t"

 t = [ -b +/- sqrt(b** - 4 * a * c) ] / (2 * a)

This parameter "t" can be substituted into the formulas for either L' or L, because affine transformations preserve distances along lines.

Now, D' = S(R(D)) and P' = S(R(P - V))

Substituting,

W = V + invR(invS[ k *(S(R(D))) + S(R(P - V)) ]) = V + invR((k * R(D)) + R(P - V)) = V + k * D + P - V = k * D + P

Note that ``t'' is constant, and is the same in the formulations for both W and W'.

The hit at ``t'' is a hit on the height=1 unit cylinder IFF 0 <= Wz' <= 1.

NORMALS. Given the point W on the surface of the cylinder, what is the vector normal to the tangent plane at that point?

Map W onto the unit cylinder, i.e.: W' = S(R(W - V)).

Plane on unit cylinder at W' has a normal vector N' of the same value as W' in x and y, with z set to zero, i.e., (Wx', Wy', 0)

The plane transforms back to the tangent plane at W, and this new plane (on the original cylinder) has a normal vector of N, viz:

N = inverse[ transpose(invR o invS) ] (N') = inverse[ transpose(invS) o transpose(invR) ] (N') = inverse[ inverse(S) o R ] (N') = invR o S (N')

Note that the normal vector produced above will not have unit length.

THE HEMISPHERES.

THE "EQUIVALENT CONE":

In order to have exact matching of the surface normals at the join between the conical body of the particle and the hemispherical end, it is necessary to alter the cone to form an "equivalent cone", where the end caps of the cone are both shifted away from the large hemisphere and towards the smaller one. This makes the cone end where it is tangent to the hemisphere. The calculation for theta come from a diagram drawn by PJT on 18-Nov-99.

Definition in file part.c.

Macro Definition Documentation

#define RT_PARTICLE_SURF_VSPHERE   1

Definition at line 211 of file part.c.

Referenced by rt_part_curve(), rt_part_norm(), and rt_part_shot().

#define RT_PARTICLE_SURF_BODY   2

Definition at line 212 of file part.c.

Referenced by rt_part_curve(), rt_part_norm(), and rt_part_shot().

#define RT_PARTICLE_SURF_HSPHERE   3

Definition at line 213 of file part.c.

Referenced by rt_part_curve(), rt_part_norm(), and rt_part_shot().

Function Documentation

int rt_part_bbox ( struct rt_db_internal ip,
point_t *  min,
point_t *  max,
const struct bn_tol tol 
)

Compute the bounding RPP for a particle

Definition at line 227 of file part.c.

References rt_db_internal::idb_ptr, RT_CK_DB_INTERNAL, X, Y, and Z.

Referenced by rt_part_prep().

int rt_part_prep ( struct soltab stp,
struct rt_db_internal ip,
struct rt_i rtip 
)

Given a pointer to a GED database record, and a transformation matrix, determine if this is a valid particle, and if so, precompute various terms of the formula.

Returns - 0 particle is OK !0 Error in description

Implicit return - A struct part_specific is created, and its address is stored in stp->st_specific for use by part_shot().

Definition at line 274 of file part.c.

References bn_mat_mul(), bn_mat_trn(), bn_vec_ortho(), BU_GET, bu_log(), directory::d_namep, rt_db_internal::idb_ptr, part_specific::part_h_erad, part_specific::part_h_hdist, part_specific::part_hrad_prime, part_specific::part_int, part_specific::part_invRoS, part_specific::part_SoR, part_specific::part_v_erad, part_specific::part_v_hdist, part_specific::part_vrad_prime, R, RT_CK_DB_INTERNAL, RT_CK_RTI, rt_part_bbox(), rt_i::rti_tol, SMALL, soltab::st_aradius, soltab::st_bradius, soltab::st_center, soltab::st_dp, soltab::st_max, soltab::st_min, soltab::st_specific, X, Y, and Z.

Here is the call graph for this function:

void rt_part_print ( register const struct soltab stp)

Definition at line 408 of file part.c.

References bn_mat_print(), bu_log(), part_specific::part_int, part_specific::part_invRoS, part_specific::part_SoR, soltab::st_specific, and VPRINT.

Here is the call graph for this function:

int rt_part_shot ( struct soltab stp,
register struct xray rp,
struct application ap,
struct seg seghead 
)

Intersect a ray with a part. If an intersection occurs, a struct seg will be acquired and filled in.

Returns - 0 MISS >0 HIT

VJOIN1(hitp->hit_vpriv, pprime, t1, dprime);

VJOIN1(hitp->hit_vpriv, pprime, t2, dprime);

Definition at line 449 of file part.c.

References application::a_resource, BU_LIST_INSERT, if(), seg::l, out, part_specific::part_h_hdist, part_specific::part_hrad_prime, part_specific::part_int, part_specific::part_SoR, part_specific::part_v_hdist, part_specific::part_vrad_prime, xray::r_dir, xray::r_pt, RT_GET_SEG, RT_HIT_MAGIC, rt_hitsort(), RT_PARTICLE_SURF_BODY, RT_PARTICLE_SURF_HSPHERE, RT_PARTICLE_SURF_VSPHERE, soltab::st_specific, X, Y, Z, and ZERO.

Here is the call graph for this function:

void rt_part_norm ( register struct hit hitp,
struct soltab stp,
register struct xray rp 
)
void rt_part_curve ( register struct curvature cvp,
register struct hit hitp,
struct soltab stp 
)

Return the curvature of the particle. There are two cases: hitting a hemisphere, and hitting the cylinder.

Definition at line 789 of file part.c.

References bn_vec_ortho(), curvature::crv_c1, curvature::crv_c2, curvature::crv_pdir, hit::hit_normal, hit::hit_point, hit::hit_surfno, part_specific::part_h_erad, part_specific::part_int, part_specific::part_SoR, part_specific::part_v_erad, RT_PARTICLE_SURF_BODY, RT_PARTICLE_SURF_HSPHERE, RT_PARTICLE_SURF_VSPHERE, soltab::st_specific, and Z.

Here is the call graph for this function:

void rt_part_uv ( struct application ap,
struct soltab stp,
register struct hit hitp,
register struct uvcoord uvp 
)

For a hit on the surface of a particle, return the (u, v) coordinates of the hit point, 0 <= u, v <= 1. u = azimuth v = elevation along H

The 'u' coordinate wraps around the particle, once. The 'v' coordinate covers the 'height' of the particle, from V-r1 to (V+H)+r2.

hit_point has already been computed.

Definition at line 835 of file part.c.

References application::a_diverge, application::a_rbeam, bn_atan2(), hit::hit_dist, hit::hit_point, part_specific::part_h_erad, part_specific::part_int, part_specific::part_SoR, part_specific::part_v_erad, soltab::st_specific, uvcoord::uv_du, uvcoord::uv_dv, uvcoord::uv_u, uvcoord::uv_v, X, Y, and Z.

Here is the call graph for this function:

void rt_part_free ( register struct soltab stp)

Definition at line 874 of file part.c.

References BU_PUT, and soltab::st_specific.

HIDDEN void rt_part_hemisphere ( register point_t *  ov,
register fastf_t v,
fastf_t a,
fastf_t b,
fastf_t h 
)

Produce a crude approximation to a hemisphere, 8 points around the rim [0]..[7], 4 points around a midway latitude [8]..[11], and 1 point at the pole [12].

For the dome, connect up: 0 8 12 10 4 2 9 12 11 6

Definition at line 895 of file part.c.

References M_SQRT1_2.

Referenced by rt_part_plot().

int rt_part_plot ( struct bu_list vhead,
struct rt_db_internal ip,
const struct rt_tess_tol ttol,
const struct bn_tol tol,
const struct rt_view_info info 
)

Definition at line 921 of file part.c.

References bn_vec_perp(), BN_VLIST_LINE_DRAW, BN_VLIST_LINE_MOVE, BU_CK_LIST_HEAD, rt_db_internal::idb_ptr, RT_ADD_VLIST, RT_CK_DB_INTERNAL, rt_ell_16pts(), rt_part_hemisphere(), VSET, and X.

Here is the call graph for this function:

int rt_part_tess ( struct nmgregion **  r,
struct model *  m,
struct rt_db_internal ip,
const struct rt_tess_tol ttol,
const struct bn_tol tol 
)

Based upon the tesselator for the ellipsoid.

Break the particle into three parts: Upper hemisphere 0..nsegs H North middle cylinder nsegs..nsegs+1 lower hemisphere nsegs+1..nstrips-1 V South

Definition at line 1055 of file part.c.

References OSL::Strings::alpha, bn_mat_fromto(), bn_mat_inv(), bn_mat_mul(), bn_mat_trn(), bu_calloc(), bu_free(), BU_LIST_FIRST, BU_LIST_FOR, bu_log(), part_vert_strip::fu, rt_db_internal::idb_ptr, part_state::lower_invRinvS, part_state::lower_invRoS, M_PI, part_vert_strip::nfaces, nmg_cmface(), nmg_find_fu_of_vu(), nmg_fu_planeeqn(), nmg_mrsv(), nmg_region_a(), nmg_vertex_gv(), nmg_vertexuse_nv(), rt_tess_tol::norm, part_vert_strip::norms, part_vert_strip::nverts, part_vert_strip::nverts_per_strip, primitive_get_absolute_tolerance(), R, RT_CK_DB_INTERNAL, part_state::s, part_state::theta_tol, part_state::upper_invRinvS, part_state::upper_invRoS, part_vert_strip::vp, and VSET.

Here is the call graph for this function:

int rt_part_import4 ( struct rt_db_internal ip,
const struct bu_external ep,
register const fastf_t mat,
const struct db_i dbip 
)

Definition at line 1413 of file part.c.

References bn_mat_identity, BU_ALLOC, BU_CK_EXTERNAL, bu_cv_ntohd(), bu_free(), bu_log(), bu_external::ext_buf, ID_PARTICLE, rt_db_internal::idb_major_type, rt_db_internal::idb_meth, rt_db_internal::idb_ptr, if(), OBJ, RT_CK_DB_INTERNAL, RT_CK_DBI, RT_PART_INTERNAL_MAGIC, OSL::Strings::v, and VSETALL.

Here is the call graph for this function:

int rt_part_export4 ( struct bu_external ep,
const struct rt_db_internal ip,
double  local2mm,
const struct db_i dbip 
)

Definition at line 1502 of file part.c.

References bu_calloc(), BU_CK_EXTERNAL, bu_cv_htond(), bu_external::ext_buf, bu_external::ext_nbytes, ID_PARTICLE, rt_db_internal::idb_ptr, RT_CK_DB_INTERNAL, and RT_CK_DBI.

Here is the call graph for this function:

int rt_part_import5 ( struct rt_db_internal ip,
const struct bu_external ep,
register const fastf_t mat,
const struct db_i dbip 
)

Definition at line 1543 of file part.c.

References bn_mat_identity, BU_ALLOC, BU_ASSERT_LONG, BU_CK_EXTERNAL, bu_cv_ntohd(), bu_free(), bu_log(), bu_external::ext_buf, bu_external::ext_nbytes, ID_PARTICLE, rt_db_internal::idb_major_type, rt_db_internal::idb_meth, rt_db_internal::idb_ptr, OBJ, RT_CK_DB_INTERNAL, RT_CK_DBI, RT_PART_INTERNAL_MAGIC, SIZEOF_NETWORK_DOUBLE, and VSETALL.

Here is the call graph for this function:

int rt_part_export5 ( struct bu_external ep,
const struct rt_db_internal ip,
double  local2mm,
const struct db_i dbip 
)

Definition at line 1621 of file part.c.

References BU_CK_EXTERNAL, bu_cv_htond(), bu_malloc(), bu_external::ext_buf, bu_external::ext_nbytes, ID_PARTICLE, rt_db_internal::idb_ptr, RT_CK_DB_INTERNAL, RT_CK_DBI, and SIZEOF_NETWORK_DOUBLE.

Here is the call graph for this function:

int rt_part_describe ( struct bu_vls str,
const struct rt_db_internal ip,
int  verbose,
double  mm2local 
)

Make human-readable formatted presentation of this solid. First line describes type of solid. Additional lines are indented one tab, and give parameter values.

Definition at line 1660 of file part.c.

References bu_vls_strcat(), rt_db_internal::idb_ptr, X, Y, and Z.

Here is the call graph for this function:

void rt_part_ifree ( struct rt_db_internal ip)

Free the storage associated with the rt_db_internal version of this solid.

Definition at line 1734 of file part.c.

References bu_free(), rt_db_internal::idb_ptr, and RT_CK_DB_INTERNAL.

Here is the call graph for this function:

int rt_part_params ( struct pc_pc_set ps,
const struct rt_db_internal ip 
)

Definition at line 1744 of file part.c.

References RT_CK_DB_INTERNAL.

void rt_part_volume ( fastf_t vol,
const struct rt_db_internal ip 
)

Definition at line 1753 of file part.c.

References rt_db_internal::idb_ptr, and M_PI.

void rt_part_surf_area ( fastf_t area,
const struct rt_db_internal ip 
)

Definition at line 1776 of file part.c.

References rt_db_internal::idb_ptr, and M_PI.

Variable Documentation

const struct bu_structparse rt_part_parse[]
Initial value:
= {
{ "%f", 3, "V", bu_offsetofarray(struct rt_part_internal, part_V, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
{ "%f", 3, "H", bu_offsetofarray(struct rt_part_internal, part_H, fastf_t, X), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
{ "%f", 1, "r_v", bu_offsetof(struct rt_part_internal, part_vrad), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
{ "%f", 1, "r_h", bu_offsetof(struct rt_part_internal, part_hrad), BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
{ {'\0', '\0', '\0', '\0'}, 0, (char *)NULL, 0, BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
}
Definition: color.c:49
#define bu_offsetofarray(_t, _a, _d, _i)
Definition: parse.h:65
#define BU_STRUCTPARSE_FUNC_NULL
Definition: parse.h:153
#define bu_offsetof(_t, _m)
Definition: parse.h:64
double fastf_t
Definition: defines.h:300

Definition at line 215 of file part.c.