4 #define _USE_MATH_DEFINES
54 intersections.push_back( std::numeric_limits< double >::max() );
67 double abs_dist = fabs( dist );
77 search_win.first = &
pos;
78 search_win.second = &
neg;
167 const std::vector< EntityHandle >& close_tris,
168 const std::vector< int >& close_senses,
170 std::vector< EntityHandle >* neighborhood_tris = 0 );
177 const double ray_point[3],
178 const double ray_dir[3],
180 int min_tolerance_intersections,
183 const Tag* sense_tag,
184 const int* desired_orient,
185 const std::vector< EntityHandle >* prev_facets )
216 std::cerr <<
"error: desired orientation must be 1 (forward) or -1 (reverse)" << std::endl;
222 if( vols[0] == vols[1] )
224 std::cerr <<
"error: surface has positive and negative sense wrt same volume" << std::endl;
249 return (
prevFacets && ( ( *prevFacets ).end() != find( ( *prevFacets ).begin(), ( *prevFacets ).end(), tri ) ) );
254 bool same_neighborhood =
false;
259 same_neighborhood =
true;
263 return same_neighborhood;
281 const std::vector< EntityHandle >& close_tris,
282 const std::vector< int >& close_senses,
284 std::vector< EntityHandle >* neighborhood_tris )
292 if( 3 != len )
return false;
295 std::vector< EntityHandle > adj_tris;
296 std::vector< int > adj_senses;
312 for(
unsigned i = 0; i < close_tris.size(); ++i )
316 if( 3 != len )
return false;
318 if( node == con[0] || node == con[1] || node == con[2] )
320 adj_tris.push_back( close_tris[i] );
321 adj_senses.push_back( close_senses[i] );
324 if( adj_tris.empty() )
326 std::cerr <<
"error: no tris are adjacent to the node" << std::endl;
353 for(
unsigned i = 0; i < close_tris.size(); ++i )
357 if( 3 != len )
return false;
360 if( ( endpts[0] == con[0] && endpts[1] == con[1] ) || ( endpts[0] == con[1] && endpts[1] == con[0] ) ||
361 ( endpts[0] == con[1] && endpts[1] == con[2] ) || ( endpts[0] == con[2] && endpts[1] == con[1] ) ||
362 ( endpts[0] == con[2] && endpts[1] == con[0] ) || ( endpts[0] == con[0] && endpts[1] == con[2] ) )
364 adj_tris.push_back( close_tris[i] );
365 adj_senses.push_back( close_senses[i] );
369 if( 2 != adj_tris.size() )
371 std::cerr <<
"error: edge of a manifold must be topologically adjacent to exactly 2 tris" << std::endl;
372 MBI->list_entities( endpts, 2 );
378 std::cerr <<
"error: special case not an node/edge intersection" << std::endl;
384 if( neighborhood_tris ) ( *neighborhood_tris ).assign( adj_tris.begin(), adj_tris.end() );
391 for(
unsigned i = 0; i < adj_tris.size(); ++i )
395 if( 3 != len )
return false;
401 CartVect v0 = coords[1] - coords[0];
402 CartVect v1 = coords[2] - coords[0];
403 CartVect norm = adj_senses[i] * ( v0 * v1 );
404 double dot_prod = norm % ray_dir;
407 if( 0 == sign && 0 != dot_prod )
417 if( 0 != sign && 0 > sign * dot_prod )
return false;
448 std::vector< EntityHandle > close_tris;
449 std::vector< int > close_senses;
475 sets.push_back( set );
476 facets.push_back( facet );
520 if( dist < -*( search_win.second ) )
540 if( search_win.second && search_win.first )
554 if( minTolInt < 0 && dist > -
tol )
566 if( search_win.first && search_win.first >= &
intersections[0] &&
584 search_win.first = &
tol;
606 else if( len_idx >= 0 )
608 if( dist <= *search_win.first )
627 bool p_rootSets_vector,
628 bool restore_rootSets,
630 double overlap_thickness,
631 double numerical_precision )
632 :
verbose( false ), owns_gtt( true )
652 double overlap_thickness,
653 double numerical_precision )
654 :
verbose( false ), owns_gtt( false )
703 if( prev_facets.size() > 1 )
705 prev_facets[0] = prev_facets.back();
706 prev_facets.resize( 1 );
712 if( prev_facets.size() ) prev_facets.pop_back();
717 if( prev_facets.size() > 0 )
719 last_facet_hit = prev_facets.back();
730 return std::find( prev_facets.begin(), prev_facets.end(), ent ) != prev_facets.end();
735 prev_facets.push_back( ent );
739 const double point[3],
742 double& next_surf_dist,
744 double user_dist_limit,
760 std::cout <<
"ray_fire:"
761 <<
" xyz=" << point[0] <<
" " << point[1] <<
" " << point[2] <<
" uvw=" << dir[0] <<
" " << dir[1] <<
" "
762 << dir[2] <<
" entity_handle=" << volume << std::endl;
765 const double huge_val = std::numeric_limits< double >::max();
766 double dist_limit = huge_val;
767 if( user_dist_limit > 0 ) dist_limit = user_dist_limit;
770 std::vector< double > dists;
771 std::vector< EntityHandle > surfs;
772 std::vector< EntityHandle > facets;
789 double nonneg_ray_len = dist_limit;
793 if( nonneg_ray_len < -neg_ray_len ) nonneg_ray_len = -neg_ray_len;
794 if( 0 > nonneg_ray_len || 0 <= neg_ray_len )
796 MB_SET_ERR( MB_FAILURE,
"Incorrect ray length provided" );
800 const int min_tolerance_intersections = 0;
805 &root, &volume, &
senseTag, &ray_orientation,
810 search_win, int_reg_ctxt, stats );
822 std::cout <<
" next_surf=0 dist=(undef)" << std::endl;
830 if( 2 != dists.size() || 2 != facets.size() )
832 MB_SET_ERR( MB_FAILURE,
"Incorrect number of facets/distances" );
834 if( 0.0 < dists[0] || 0.0 > dists[1] )
836 MB_SET_ERR( MB_FAILURE,
"Invalid intersection distance signs" );
841 if( ( 0 != facets[0] && 0 != facets[1] ) && ( -dists[0] > dists[1] ) )
843 MB_SET_ERR( MB_FAILURE,
"Invalid intersection distance values" );
852 std::vector< EntityHandle > vols;
855 if( 2 != vols.size() )
857 MB_SET_ERR( MB_FAILURE,
"Invaid number of parent volumes found" );
859 if( vols.front() == volume )
861 nx_vol = vols.back();
865 nx_vol = vols.front();
873 if( 1 == result ) exit_idx = 0;
877 if( -1 == exit_idx && 0 != facets[1] ) exit_idx = 1;
884 std::cout <<
"next surf hit = 0, dist = (undef)" << std::endl;
890 next_surf = surfs[exit_idx];
891 next_surf_dist = ( 0 > dists[exit_idx] ? 0 : dists[exit_idx] );
895 history->
prev_facets.push_back( facets[exit_idx] );
899 if( 0 > dists[exit_idx] )
901 std::cout <<
" OVERLAP track length=" << dists[exit_idx] << std::endl;
903 std::cout <<
" next_surf = " << next_surf
904 <<
", dist = " << next_surf_dist <<
" new_pt=";
905 for(
int i = 0; i < 3; ++i )
907 std::cout << point[i] + dir[i] * next_surf_dist <<
" ";
909 std::cout << std::endl;
939 std::vector< double > dists;
940 std::vector< EntityHandle > surfs;
941 std::vector< EntityHandle > facets;
942 std::vector< int > dirs;
945 double u = 0, v = 0, w = 0;
950 v = uvw[1], w = uvw[2];
953 if( u == 0 && v == 0 && w == 0 )
958 const double magnitude = sqrt( u * u + v * v + w * w );
964 const double ray_direction[] = { u, v, w };
967 const double large = 1e15;
968 double ray_length = large;
973 int min_tolerance_intersections;
976 min_tolerance_intersections = -1;
981 min_tolerance_intersections = 1;
987 min_tolerance_intersections, &root, &volume, &
senseTag, NULL,
992 ray_direction, search_win, int_reg_ctxt );
MB_CHK_SET_ERR( rval,
"Ray fire query failed" );
997 dirs.resize( dists.size() );
998 for(
unsigned i = 0; i < dists.size(); ++i )
1007 for(
unsigned i = 0; i < dirs.size(); ++i )
1011 else if( 0 == dirs[i] )
1013 else if( -1 == dirs[i] )
1015 std::cout <<
"direction==tangent" << std::endl;
1020 MB_SET_ERR( MB_FAILURE,
"Error: unknown direction" );
1044 int smallest = std::min_element( dists.begin(), dists.end() ) - dists.begin();
1045 if( 1 == dirs[smallest] )
1047 else if( 0 == dirs[smallest] )
1049 else if( -1 == dirs[smallest] )
1053 std::cerr <<
"direction==tangent" << std::endl;
1058 MB_SET_ERR( MB_FAILURE,
"Error: unknown direction" );
1064 std::cout <<
"pt_in_vol: result=" << result <<
" xyz=" << xyz[0] <<
" " << xyz[1] <<
" " << xyz[2] <<
" uvw=" << u
1065 <<
" " << v <<
" " << w <<
" vol_id=" << volume
1084 if( point[0] > maxpt[0] || point[0] < minpt[0] )
1089 if( point[1] > maxpt[1] || point[1] < minpt[1] )
1094 if( point[2] > maxpt[2] || point[2] < minpt[2] )
1105 const double xyz[3],
1106 const double uvw[3],
1132 rval =
boundary_case( volume, dir, uvw[0], uvw[1], uvw[2], facet_out, surface );
MB_CHK_SET_ERR( rval,
"Failed to resolve the boundary case" );
1145 std::vector< EntityHandle > surfs;
1146 std::vector< int > senses;
1152 senses.resize( surfs.size() );
1155 for(
unsigned i = 0; i < surfs.size(); ++i )
1160 double surf_area = 0.0, face_area;
1168 surf_area += face_area;
1171 sum += senses[i] * surf_area;
1174 result = fabs(
sum ) > 2.0 * M_PI;
1190 rval =
point_in_box( ic_handle, xyz, ic_result );
MB_CHK_SET_ERR( rval,
"Failed to check implicit complement for containment" );
1191 if( ic_result == 0 )
1198 if( !global_surf_tree_root )
1224 const double huge_val = std::numeric_limits< double >::max();
1225 double pos_ray_len = huge_val;
1226 double neg_ray_len = -huge_val;
1229 std::vector< double > dists;
1230 std::vector< EntityHandle > surfs;
1231 std::vector< EntityHandle > facets;
1237 xyz, uvw.
array(), search_win, find_vol_reg_ctxt );
MB_CHK_SET_ERR( rval,
"Failed in global tree ray fire" );
1240 if( surfs.size() == 0 || surfs[0] == 0 )
1254 parent_vols[0] = fwd_vol;
1255 parent_vols[1] = bwd_vol;
1258 std::vector< EntityHandle > conn;
1264 CartVect normal = ( coords[1] - coords[0] ) * ( coords[2] - coords[0] );
1275 double dot_prod = uvw % normal;
1276 int idx = dot_prod > 0.0 ? 0 : 1;
1278 if( dot_prod == 0.0 )
1280 std::cerr <<
"Tangent dot product in find_volume. Shouldn't be here." << std::endl;
1285 volume = parent_vols[idx];
1300 for( it = all_vols.
begin(); it != all_vols.
end(); it++ )
1314 const double coords[3],
1328 closest_surface );
MB_CHK_SET_ERR( rval,
"Failed to get the closest intersection to location" );
1330 result = ( point - nearest ).
length();
1339 std::vector< EntityHandle > surfaces;
1353 std::vector< int > senses( surfaces.size() );
1356 for(
unsigned i = 0; i < surfaces.size(); ++i )
1359 if( !senses[i] )
continue;
1367 std::cout <<
"WARNING: Surface " << surfaces[i]
1368 <<
" contains non-triangle elements. Volume calculation may be incorrect." << std::endl;
1374 double surf_sum = 0.0;
1383 MB_SET_ERR( MB_FAILURE,
"Incorrect connectivity length for triangle" );
1385 rval =
MBI->
get_coords( conn, 3, coords[0].array() );
MB_CHK_SET_ERR( rval,
"Failed to get the coordinates of the current triangle's vertices" );
1387 coords[1] -= coords[0];
1388 coords[2] -= coords[0];
1389 surf_sum += ( coords[0] % ( coords[1] * coords[2] ) );
1391 result += senses[i] * surf_sum;
1406 std::cout <<
"WARNING: Surface " << surface
1407 <<
" contains non-triangle elements. Area calculation may be incorrect." << std::endl;
1422 MB_SET_ERR( MB_FAILURE,
"Incorrect connectivity length for triangle" );
1424 rval =
MBI->
get_coords( conn, 3, coords[0].array() );
MB_CHK_SET_ERR( rval,
"Failed to get the current triangle's vertex coordinates" );
1427 CartVect v1 = coords[1] - coords[0];
1428 CartVect v2 = coords[2] - coords[0];
1437 const double in_pt[3],
1444 std::vector< EntityHandle > facets;
1447 if( !history || ( history->
prev_facets.size() == 0 ) )
1460 for(
unsigned i = 0; i < facets.size(); ++i )
1465 MB_SET_ERR( MB_FAILURE,
"Incorrect connectivity length for triangle" );
1470 coords[1] -= coords[0];
1471 coords[2] -= coords[0];
1472 normal += coords[1] * coords[2];
1499 if( u <= 1.0 && v <= 1.0 && w <= 1.0 )
1502 const CartVect ray_vector( u, v, w );
1510 MB_SET_ERR( MB_FAILURE,
"Incorrect connectivity length for triangle" );
1517 coords[1] -= coords[0];
1518 coords[2] -= coords[0];
1519 normal = sense_out * ( coords[1] * coords[2] );
1521 double sense = ray_vector % normal;
1527 else if( sense > 0.0 )
1531 else if( sense == 0.0 )
1538 MB_SET_ERR( MB_FAILURE,
"Failed to resolve boundary case" );
1571 std::vector< CartVect > coords_dynamic;
1573 if( (
unsigned)len > (
sizeof( coords_static ) /
sizeof( coords_static[0] ) ) )
1575 coords_dynamic.resize( len );
1576 coords = &coords_dynamic[0];
1583 CartVect norm( 0.0 ), v1, v0 = coords[1] - coords[0];
1584 for(
int i = 2; i < len; ++i )
1586 v1 = coords[i] - coords[0];
1594 CartVect r, n1, n2, b, a = coords[len - 1] - coords[0];
1595 for(
int i = 0; i < len; ++i )
1597 r = coords[i] - point;
1598 b = coords[( i + 1 ) % len] - coords[i];
1601 s = ( n1 % n2 ) / ( n1.length() * n2.
length() );
1602 ang = s <= -1.0 ? M_PI : s >= 1.0 ? 0.0 : acos( s );
1603 s = ( b * a ) % norm;
1604 area += s > 0.0 ? M_PI - ang : M_PI + ang;
1608 area -= M_PI * ( len - 2 );
1609 if( ( norm % r ) > 0 ) area = -area;
1616 if( new_thickness < 0 || new_thickness > 100 )
1618 std::cerr <<
"Invalid overlap_thickness = " << new_thickness << std::endl;
1630 if( new_precision <= 0 || new_precision > 1 )