MBErrorCode build_obbs(moab::OrientedBoxTreeTool *obbTree, MBRange &surfs, MBRange &volumes)
{
  MBErrorCode rval = MB_SUCCESS;

  for (MBRange::iterator i = surfs.begin(); i != surfs.end(); ++i) {
    MBEntityHandle root;
    MBRange tris;
    rval = MBI()->get_entities_by_dimension( *i, 2, tris );
    if (MB_SUCCESS != rval)
      return rval;
    if (tris.empty())
      std::cerr << "WARNING: Surface " << *i << " has no facets." << std::endl;
    rval = obbTree->build( tris, root );
    if (MB_SUCCESS != rval)
      return rval;

    #pragma omp critical
    rval = MBI()->add_entities( root, &*i, 1 );
    if (MB_SUCCESS != rval)
      return rval;
  }

  return MB_SUCCESS;
}
Exemple #2
0
  /* Accepts a range of inverted tris. Refacets affected surface so that no tris
     are inverted. */
  MBErrorCode remove_inverted_tris(MBTag normal_tag, MBRange tris, const bool debug ) {
      
    MBErrorCode result;
    bool failures_occur = false;
    while(!tris.empty()) {

      /* Get a group of triangles to re-facet. They must be adjacent to each other
	 and in the same surface. */
      MBRange tris_to_refacet;
      tris_to_refacet.insert( tris.front() );
      MBRange surf_set;
      result = MBI()->get_adjacencies( tris_to_refacet, 4, false, surf_set );
      assert(MB_SUCCESS == result);
      if(1 != surf_set.size()) {
	std::cout << "remove_inverted_tris: tri is in " << surf_set.size() 
                  << " surfaces" << std::endl;
        return MB_FAILURE;
      }

      // get all tris in the surface
      MBRange surf_tris;
      result = MBI()->get_entities_by_type( surf_set.front(), MBTRI, surf_tris );
      assert(MB_SUCCESS == result); 

      /* Find all of the adjacent inverted triangles of the same surface. Keep
	 searching until a search returns no new triangles. */
      bool search_again = true;
      while(search_again) {

        // Here edges are being created. Remember to delete them. Outside of this
        // function. Skinning gets bogged down if unused MBEdges (from other 
        // surfaces) accumulate.
        MBRange tri_edges;
        result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges,
                                         MBInterface::UNION );
        assert(MB_SUCCESS == result);
        MBRange connected_tris;
        result = MBI()->get_adjacencies( tri_edges, 2, false, connected_tris, 
                                         MBInterface::UNION );
        assert(MB_SUCCESS == result);
        result = MBI()->delete_entities( tri_edges );
        assert(MB_SUCCESS == result);
        MBRange tris_to_refacet2 = intersect( tris_to_refacet, connected_tris );
        tris_to_refacet2 = intersect( tris_to_refacet, surf_tris );

        if(tris_to_refacet.size() == tris_to_refacet2.size()) search_again = false;
        tris_to_refacet.swap( tris_to_refacet2 );
      }

      // Remove the inverted tris that will be refaceted.
      tris = subtract( tris, tris_to_refacet );

        // do edges already exist?
	MBRange temp;
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());


      // keep enlarging patch until we have tried to refacet the entire surface
      int counter=0;
      while(true) {
        // do edges already exist?
	temp.clear();
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());


        counter++;
        // Only try enlarging each patch a few times
        if(48 == counter) {
          failures_occur = true;
	  if(debug) std::cout << "remove_inverted_tris: ear clipping failed, counter="
		              << counter << std::endl;
	  break;
        }
        // THIS PROVIDES A BAD EXIT. MUST FIX

        // get the edges of the patch of inverted tris
	MBRange tri_edges;
	result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges,
                                         MBInterface::UNION );
	assert(MB_SUCCESS == result);

	// get all adjacent tris to the patch of inverted tris in the surface
	MBRange adj_tris;
	result = MBI()->get_adjacencies( tri_edges, 2, false, adj_tris, 
                                         MBInterface::UNION );
	assert(MB_SUCCESS == result);
        result = MBI()->delete_entities( tri_edges );
        assert(MB_SUCCESS == result);
	tris_to_refacet = intersect( surf_tris, adj_tris );
        if(tris_to_refacet.empty()) continue;
	//gen::print_triangles( tris_to_refacet );    
	
	// get an area-weighted normal of the adj_tris
	MBCartVect plane_normal(0,0,0);
	//for(unsigned int i=0; i<tris_to_refacet.size(); i++) {
	for(MBRange::iterator i=tris_to_refacet.begin(); i!=tris_to_refacet.end(); i++) {
	  MBCartVect norm;
	  result = MBI()->tag_get_data( normal_tag, &(*i), 1, &norm);
	  assert(MB_SUCCESS == result);
	  double area;
          result = gen::triangle_area( *i, area );
          assert(MB_SUCCESS == result);
	  if(debug) std::cout << "norm=" << norm << " area=" << area << std::endl;
	  //plane_normal += norm*area;
	  plane_normal += norm;
	}
	plane_normal.normalize();

        // do edges already exist?
	temp.clear();
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());
 
	// skin the tris
	MBRange unordered_edges;
	//MBSkinner tool(MBI());
	//result = tool.find_skin( tris_to_refacet, 1, unordered_edges, false );
	result = gen::find_skin( tris_to_refacet, 1, unordered_edges, false );
	assert(MB_SUCCESS == result);
        if(unordered_edges.empty()) {
        // do edges already exist?
          MBRange temp;
          result = MBI()->get_entities_by_type(0, MBEDGE, temp );
          assert(MB_SUCCESS == result);
          if(!temp.empty()) MBI()->list_entities( temp );
	  assert(temp.empty());
          continue;
        }

	//std::cout << "remove_inverted_tris: surf_id=" 
	//  << gen::geom_id_by_handle(surf_set.front()) << std::endl;
	//result = MBI()->list_entities( tris_to_refacet );
	//assert(MB_SUCCESS == result);

	// assemble into a polygon
	std::vector<MBEntityHandle> polygon_of_verts;
	result = arc::order_verts_by_edge( unordered_edges, polygon_of_verts );
	if(debug) gen::print_loop( polygon_of_verts ); 
	//assert(MB_SUCCESS == result);
	if(MB_SUCCESS != result) {
	  if(debug) std::cout << "remove_inverted_tris: couldn't order polygon by edge" << std::endl;
	  return MB_FAILURE;
	}

        // remember to remove edges
        result = MBI()->delete_entities( unordered_edges );
        assert(MB_SUCCESS == result);

	// remove the duplicate endpt
	polygon_of_verts.pop_back();

	// the polygon should have at least 3 verts
	if(3 > polygon_of_verts.size()) {
	  if(debug) std::cout << "remove_inverted_tris: polygon has too few points" << std::endl;
	  return MB_FAILURE;
	}

	// orient the polygon with the triangles (could be backwards)
	// get the first adjacent tri
	MBEntityHandle edge[2] = { polygon_of_verts[0], polygon_of_verts[1] };
	MBRange one_tri;
	result = MBI()->get_adjacencies( edge, 2, 2, false, one_tri );
	assert(MB_SUCCESS == result);
	one_tri = intersect( tris_to_refacet, one_tri );
	assert(1 == one_tri.size());
	const MBEntityHandle *conn;
	int n_conn;
	result = MBI()->get_connectivity( one_tri.front(), conn, n_conn );
	assert(MB_SUCCESS == result);
	assert(3 == n_conn);
	if( (edge[0]==conn[1] && edge[1]==conn[0]) ||
	    (edge[0]==conn[2] && edge[1]==conn[1]) ||
	    (edge[0]==conn[0] && edge[1]==conn[2]) ) {
	  reverse( polygon_of_verts.begin(), polygon_of_verts.end() );
	  if(debug) std::cout << "remove_inverted_tris: polygon reversed" << std::endl;
	}

	/* facet the polygon. Returns MB_FAILURE if it fails to facet the polygon. */
	MBRange new_tris;
	result = gen::ear_clip_polygon( polygon_of_verts, plane_normal, new_tris );

        // break if the refaceting is successful
	if(MB_SUCCESS == result) {
          // summarize tri area
          for(MBRange::iterator i=new_tris.begin(); i!=new_tris.end(); i++) {
            double area;
            result = gen::triangle_area( *i, area );
            assert(MB_SUCCESS == result);
	    if(debug) std::cout << "  new tri area=" << area << std::endl;
          }

  	  // check the new normals
	  std::vector<MBCartVect> new_normals;
	  result = gen::triangle_normals( new_tris, new_normals );
	  if(MB_SUCCESS != result) return result;

	  // test the new triangles
	  std::vector<int> inverted_tri_indices;
	  std::vector<MBCartVect> normals ( new_normals.size(), plane_normal );
	  result = zip::test_normals( normals, new_normals, inverted_tri_indices );
	  assert(MB_SUCCESS == result);
	  if(inverted_tri_indices.empty()) {
  	    // remove the tris that were re-faceted
            tris = subtract( tris, tris_to_refacet );
  	    result = MBI()->remove_entities( surf_set.front(), tris_to_refacet );
	    assert(MB_SUCCESS == result);
	    result = MBI()->delete_entities( tris_to_refacet ); 
	    assert(MB_SUCCESS == result);

	    // add the new tris to the surf set
	    result = MBI()->add_entities( surf_set.front(), new_tris );
	    assert(MB_SUCCESS == result);

            // put the new normals on the new tris
            result = gen::save_normals( new_tris, normal_tag );
            assert(MB_SUCCESS == result);
	    if(debug) std::cout << "remove_inverted_tris: success fixing a patch" << std::endl;
            break;
          }
        }

        // remember to delete the tris that were created from the failed ear clipping
        else {
          result = MBI()->delete_entities( new_tris );
          assert(MB_SUCCESS == result);
        }

        // If the entire surface could not be ear clipped, give up
        if (tris_to_refacet.size() == surf_tris.size()) {
	  if(debug) std::cout << "remove_inverted_tris: ear clipping entire surface failed"
			    << std::endl;
	  return MB_FAILURE;
	}

      } // loop until the entire surface has attempted to be refaceted
    }   // loop over each patch of inverted tris
   
    if(failures_occur) {
      if(debug) std::cout << "remove_inverted_facets: at least one failure occured" << std::endl;
      return MB_FAILURE;
    } else {
      return MB_SUCCESS;
    }
  }