moab
moab::RayIntersectSets Class Reference
Inheritance diagram for moab::RayIntersectSets:
moab::OrientedBoxTreeTool::Op

List of all members.

Public Member Functions

 RayIntersectSets (OrientedBoxTreeTool *tool_ptr, const double *ray_point, const double *unit_ray_dir, const double *nonneg_ray_length, const double *neg_ray_length, double tolerance, int min_tol_intersections, std::vector< double > &inters, std::vector< EntityHandle > &surfaces, std::vector< EntityHandle > &facts, EntityHandle *root_set, const EntityHandle *geom_volume, const Tag *sense_tag, const int *desired_orient, const std::vector< EntityHandle > *prev_facets, unsigned int *tmp_count)
virtual ErrorCode visit (EntityHandle node, int depth, bool &descend)
 Visit a node in the tree during a traversal.
virtual ErrorCode leaf (EntityHandle node)
 Process a leaf node during tree traversal.

Private Member Functions

void add_intersection (double t, EntityHandle facet)

Private Attributes

OrientedBoxTreeTooltool
const CartVect ray_origin
const CartVect ray_direction
const double * nonneg_ray_len
const double * neg_ray_len
const double tol
const int minTolInt
std::vector< double > & intersections
std::vector< EntityHandle > & sets
std::vector< EntityHandle > & facets
const EntityHandlerootSet
const EntityHandlegeomVol
const TagsenseTag
const int * desiredOrient
int * surfTriOrient
int surfTriOrient_val
const std::vector< EntityHandle > * prevFacets
unsigned int * raytri_test_count
EntityHandle lastSet
int lastSetDepth
std::vector< std::vector
< EntityHandle > > 
neighborhoods
std::vector< EntityHandleneighborhood

Detailed Description

Definition at line 980 of file OrientedBoxTreeTool.cpp.


Constructor & Destructor Documentation

moab::RayIntersectSets::RayIntersectSets ( OrientedBoxTreeTool tool_ptr,
const double *  ray_point,
const double *  unit_ray_dir,
const double *  nonneg_ray_length,
const double *  neg_ray_length,
double  tolerance,
int  min_tol_intersections,
std::vector< double > &  inters,
std::vector< EntityHandle > &  surfaces,
std::vector< EntityHandle > &  facts,
EntityHandle root_set,
const EntityHandle geom_volume,
const Tag sense_tag,
const int *  desired_orient,
const std::vector< EntityHandle > *  prev_facets,
unsigned int *  tmp_count 
) [inline]

Definition at line 1025 of file OrientedBoxTreeTool.cpp.

      : tool(tool_ptr),
        ray_origin(ray_point), ray_direction(unit_ray_dir),
        nonneg_ray_len(nonneg_ray_length), neg_ray_len(neg_ray_length), 
        tol(tolerance), minTolInt(min_tol_intersections),
        intersections(inters), sets(surfaces), facets(facts), 
        rootSet(root_set), geomVol(geom_volume), senseTag(sense_tag),
        desiredOrient(desired_orient), prevFacets(prev_facets),
        raytri_test_count(tmp_count), lastSet(0)
      {
    // specified orientation should be 1 or -1, indicating ray and surface
        // normal in the same or opposite directions, respectively.
        if(desiredOrient) {
          assert(1==*desiredOrient || -1==*desiredOrient);
          surfTriOrient = &surfTriOrient_val;
        } else {
          surfTriOrient = NULL;
        }

        // check the limits  
        if(nonneg_ray_len) {
          assert(0 <= *nonneg_ray_len);
        } 
        if(neg_ray_len) {
          assert(0 > *neg_ray_len);
        }

      }

Member Function Documentation

void moab::RayIntersectSets::add_intersection ( double  t,
EntityHandle  facet 
) [private]

Definition at line 1271 of file OrientedBoxTreeTool.cpp.

                                                                      {

  // Mode 1, detected by non-null neg_ray_len pointer
  // keep the closest nonneg intersection and one negative intersection, if closer
  if(neg_ray_len && nonneg_ray_len) {
    if(2 != intersections.size()) {
      intersections.resize(2,0);
      sets.resize(2,0);
      facets.resize(2,0);
      // must initialize this for comparison below
      intersections[0] = -std::numeric_limits<double>::max();
    }

    // negative case
    if(0.0>t) {
      intersections[0] = t;
      sets[0]          = lastSet;
      facets[0]        = facet;
      neg_ray_len      = &intersections[0];
    // nonnegative case
    } else {
      intersections[1] = t;
      sets[1]          = lastSet;
      facets[1]        = facet;
      nonneg_ray_len   = &intersections[1];
      // if the intersection is closer than the negative one, remove the negative one
      if(t < -(*neg_ray_len) ) {
        intersections[0] = -intersections[1];
        sets[0]          = 0;
        facets[0]        = 0;
        neg_ray_len      = &intersections[0]; 
      }
    }
    //    std::cout << "add_intersection: t = " << t << " neg_ray_len=" << *neg_ray_len
    //          << " nonneg_ray_len=" << *nonneg_ray_len << std::endl;
    return;
  }

  // ---------------------------------------------------------------------------
  // Mode 2
  // If minTolInt is less than zero, return all intersections
  if (minTolInt < 0 && t > -tol) {
    intersections.push_back(t);
    sets.push_back(lastSet);
    facets.push_back(facet);
    neighborhoods.push_back(neighborhood);
    return;
  }

    // Check if the 'len' pointer is pointing into the intersection
    // list.  If this is the case, then the list contains, at that
    // location, an intersection greater than the tolerance away from
    // the base point of the ray.
  int len_idx = -1;
  if (nonneg_ray_len && nonneg_ray_len >= &intersections[0] && 
      nonneg_ray_len < &intersections[0] + intersections.size())
    len_idx = nonneg_ray_len - &intersections[0];

    // If the intersection is within tol of the ray base point, we 
    // always add it to the list.
  if (t <= tol) {
      // If the list contains an intersection outside the tolerance...
    if (len_idx >= 0) {
        // If we no longer want an intersection outside the tolerance,
        // remove it.
      if ((int)intersections.size() >= minTolInt) {
        intersections[len_idx] = t;
        sets[len_idx] = lastSet;
        facets[len_idx] = facet;
          // From now on, we want only intersections within the tolerance,
          // so update length accordingly
        nonneg_ray_len = &tol;
      }
        // Otherwise appended to the list and update pointer
      else {
        intersections.push_back(t);
        sets.push_back(lastSet);
        facets.push_back(facet);
        nonneg_ray_len = &intersections[len_idx];
      }
    }
      // Otherwise just append it
    else {
      intersections.push_back(t);
      sets.push_back(lastSet);
      facets.push_back(facet);
        // If we have all the intersections we want, set
        // length such that we will only find further intersections
        // within the tolerance
      if ((int)intersections.size() >= minTolInt)
        nonneg_ray_len = &tol;
    }
  }
    // Otherwise the intersection is outside the tolerance
    // If we already have an intersection outside the tolerance and
    // this one is closer, replace the existing one with this one.
  else if (len_idx >= 0) {
    if (t <= *nonneg_ray_len) {
      intersections[len_idx] = t;
      sets[len_idx] = lastSet;
      facets[len_idx] = facet;
    }
  }
    // Otherwise if we want an intersection outside the tolerance
    // and don'thave one yet, add it.
  else if ((int)intersections.size() < minTolInt) {
    intersections.push_back( t );
    sets.push_back( lastSet );
    facets.push_back(facet);
      // update length.  this is currently the closest intersection, so
      // only want further intersections that are closer than this one.
    nonneg_ray_len = &intersections.back();
  }
}

Process a leaf node during tree traversal.

Implements moab::OrientedBoxTreeTool::Op.

Definition at line 1137 of file OrientedBoxTreeTool.cpp.

{
  assert(lastSet);
  if (!lastSet) // if no surface has been visited yet, something's messed up.
    return MB_FAILURE;
  
#ifndef MB_OBB_USE_VECTOR_QUERIES
  Range tris;
# ifdef MB_OBB_USE_TYPE_QUERIES
  ErrorCode rval = tool->get_moab_instance()->get_entities_by_type( node, MBTRI, tris );
# else
  ErrorCode rval = tool->get_moab_instance()->get_entities_by_handle( node, tris );
# endif
#else
  std::vector<EntityHandle> tris;
  ErrorCode rval = tool->get_moab_instance()->get_entities_by_handle( node, tris );
#endif
  assert(MB_SUCCESS == rval);
  if (MB_SUCCESS != rval)
    return rval;

#ifndef MB_OBB_USE_VECTOR_QUERIES
  for (Range::iterator t = tris.begin(); t != tris.end(); ++t)
#else
  for (std::vector<EntityHandle>::iterator t = tris.begin(); t != tris.end(); ++t)
#endif
  {
#ifndef MB_OBB_USE_TYPE_QUERIES
    if (TYPE_FROM_HANDLE(*t) != MBTRI)
      continue;
#endif
    
    const EntityHandle* conn;
    int num_conn;
    rval = tool->get_moab_instance()->get_connectivity( *t, conn, num_conn, true );
    assert(MB_SUCCESS == rval);
    if (MB_SUCCESS != rval)
      return rval;

    CartVect coords[3];
    rval = tool->get_moab_instance()->get_coords( conn, 3, coords[0].array() );
    assert(MB_SUCCESS == rval);
    if (MB_SUCCESS != rval)
      return rval;

    if( raytri_test_count ) *raytri_test_count += 1; 

    double int_dist;
    GeomUtil::intersection_type int_type = GeomUtil::NONE;
    // Note: tol is not used in the ray-tri test.
    if (GeomUtil::plucker_ray_tri_intersect( coords, ray_origin, ray_direction, tol, int_dist, 
                                     nonneg_ray_len, neg_ray_len, surfTriOrient, &int_type )) {
      // Do not accept intersections if they are in the vector of previously intersected
      // facets.
      if( prevFacets &&
      ((*prevFacets).end() != find((*prevFacets).begin(), (*prevFacets).end(), *t) ) ) continue;

      // Do not accept intersections if they are in the neighborhood of previous
      // intersections.
      bool same_neighborhood = false;
      for(unsigned i=0; i<neighborhoods.size(); ++i) {
        if( neighborhoods[i].end() != find(neighborhoods[i].begin(), 
                       neighborhoods[i].end(), *t ) ) {
          same_neighborhood = true;
          continue;
        }
      }
      if(same_neighborhood) continue;

      // Handle special case of edge/node intersection. Accept piercing 
      // intersections and reject glancing intersections.
      // The edge_node_intersection function needs to know surface sense wrt volume.
      // A less-robust implementation could work without sense information.
      // Would it ever be useful to accept a glancing intersection?
      if(GeomUtil::INTERIOR != int_type && rootSet && geomVol && senseTag) {
        // get triangles in the proximity of the intersection
        CartVect int_pt = ray_origin + int_dist*ray_direction;
    std::vector<EntityHandle> close_tris;
    std::vector<EntityHandle> close_surfs;
        rval = tool->sphere_intersect_triangles( int_pt.array(), tol, *rootSet,
                                             close_tris, &close_surfs );
        assert(MB_SUCCESS == rval);
        if(MB_SUCCESS != rval) return rval; 

        // for each surface, get the surf sense wrt parent volume
    std::vector<int> close_senses(close_surfs.size());
        for(unsigned i=0; i<close_surfs.size(); ++i) {
          EntityHandle vols[2];
          rval = tool->get_moab_instance()->tag_get_data( *senseTag, &lastSet, 1, vols );
          assert(MB_SUCCESS == rval);
          if(MB_SUCCESS != rval) return rval;
          if(vols[0] == vols[1]) {
            std::cerr << "error: surf has positive and negative sense wrt same volume" << std::endl;
            return MB_FAILURE;
          }
          if       (*geomVol == vols[0]) {
            close_senses[i] = 1;
          } else if(*geomVol == vols[1]) {
            close_senses[i] = -1;
          } else {
            return MB_FAILURE;
          }
        }

        neighborhood.clear();
    bool piercing = edge_node_intersect( *t, ray_direction, int_type, close_tris,
                                             close_senses, tool->get_moab_instance(), &neighborhood );
        if(!piercing) continue;

      } else {
        neighborhood.clear();
    neighborhood.push_back( *t );
      }      
     
        // NOTE: add_intersection may modify the 'neg_ray_len' and 'nonneg_ray_len'
        //       members, which will affect subsequent calls to ray_tri_intersect 
        //       in this loop.
      add_intersection( int_dist, *t );
    }
  }
  return MB_SUCCESS;
}
ErrorCode moab::RayIntersectSets::visit ( EntityHandle  node,
int  depth,
bool &  descend 
) [virtual]

Visit a node in the tree during a traversal.

This method is called for each node in the tree visited during a pre-order traversal.

Parameters:
nodeThe EntityHandle for the entity set for the tree node.
depthThe current depth in the tree.
descendOutput: if false, traversal will skip children of the current node, or if the current node is a leaf, the 'leaf' method will not be called.

Implements moab::OrientedBoxTreeTool::Op.

Definition at line 1076 of file OrientedBoxTreeTool.cpp.

{
  OrientedBox box;
  ErrorCode rval = tool->box( node, box );
  assert(MB_SUCCESS == rval);
  if (MB_SUCCESS != rval)
    return rval;
  
  descend = box.intersect_ray( ray_origin, ray_direction, tol, nonneg_ray_len, 
                               neg_ray_len );

  if (lastSet && depth <= lastSetDepth)
    lastSet = 0;

  if (descend && !lastSet) {
    Range tmp_sets;
    rval = tool->get_moab_instance()->get_entities_by_type( node, MBENTITYSET, tmp_sets );
    assert(MB_SUCCESS == rval);
    if (MB_SUCCESS != rval)
      return rval;
 
    if (!tmp_sets.empty()) {
      if (tmp_sets.size() > 1)
        return MB_FAILURE;
      lastSet = *tmp_sets.begin();
      lastSetDepth = depth;
      // Get desired orientation of surface wrt volume. Use this to return only 
      // exit or entrance intersections.
      if(geomVol && senseTag && desiredOrient && surfTriOrient) {
        if(1!=*desiredOrient && -1!=*desiredOrient) {
      std::cerr << "error: desired orientation must be 1 (forward) or -1 (reverse)" 
                    << std::endl;
        }
    EntityHandle vols[2];
    rval = tool->get_moab_instance()->tag_get_data( *senseTag, &lastSet, 1, vols );
    assert(MB_SUCCESS == rval);
    if(MB_SUCCESS != rval) return rval;
    if(vols[0] == vols[1]) {
      std::cerr << "error: surface has positive and negative sense wrt same volume" 
                    << std::endl;
      return MB_FAILURE;
    }
        // surfTriOrient will be used by plucker_ray_tri_intersect to avoid
        // intersections with wrong orientation.
    if       (*geomVol == vols[0]) {
      *surfTriOrient = *desiredOrient*1;
    } else if(*geomVol == vols[1]) {
      *surfTriOrient = *desiredOrient*(-1);
    } else {
      assert(false);
      return MB_FAILURE;
    }
      }
    }
  }
    
  return MB_SUCCESS;
}

Member Data Documentation

Definition at line 1004 of file OrientedBoxTreeTool.cpp.

Definition at line 997 of file OrientedBoxTreeTool.cpp.

Definition at line 1001 of file OrientedBoxTreeTool.cpp.

std::vector<double>& moab::RayIntersectSets::intersections [private]

Definition at line 995 of file OrientedBoxTreeTool.cpp.

Definition at line 1018 of file OrientedBoxTreeTool.cpp.

const int moab::RayIntersectSets::minTolInt [private]

Definition at line 992 of file OrientedBoxTreeTool.cpp.

const double* moab::RayIntersectSets::neg_ray_len [private]

Definition at line 988 of file OrientedBoxTreeTool.cpp.

Definition at line 1020 of file OrientedBoxTreeTool.cpp.

std::vector< std::vector<EntityHandle> > moab::RayIntersectSets::neighborhoods [private]

Definition at line 1019 of file OrientedBoxTreeTool.cpp.

const double* moab::RayIntersectSets::nonneg_ray_len [private]

Definition at line 987 of file OrientedBoxTreeTool.cpp.

const std::vector<EntityHandle>* moab::RayIntersectSets::prevFacets [private]

Definition at line 1012 of file OrientedBoxTreeTool.cpp.

Definition at line 986 of file OrientedBoxTreeTool.cpp.

Definition at line 985 of file OrientedBoxTreeTool.cpp.

Definition at line 1016 of file OrientedBoxTreeTool.cpp.

Definition at line 1000 of file OrientedBoxTreeTool.cpp.

Definition at line 1002 of file OrientedBoxTreeTool.cpp.

std::vector<EntityHandle>& moab::RayIntersectSets::sets [private]

Definition at line 996 of file OrientedBoxTreeTool.cpp.

Definition at line 1008 of file OrientedBoxTreeTool.cpp.

Definition at line 1009 of file OrientedBoxTreeTool.cpp.

const double moab::RayIntersectSets::tol [private]

Definition at line 989 of file OrientedBoxTreeTool.cpp.


The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines