1 #include "moab/Interface.hpp"
2 #include "moab/BoundBox.hpp"
3
4
5 #include "moab/IntxMesh/IntxUtils.hpp"
6
7 namespace moab
8 {
9 ErrorCode BoundBox::update( Interface& iface, const Range& elems, bool spherical, double radius )
10 {
11 ErrorCode rval;
12 bMin = CartVect( HUGE_VAL );
13 bMax = CartVect( -HUGE_VAL );
14
15 CartVect coords;
16 EntityHandle const *conn = NULL, *conn2 = NULL;
17 int len = 0, len2 = 0;
18 Range::const_iterator i;
19 CartVect coordverts[27];
20
21
22 const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
23 for( i = elems.begin(); i != elem_begin; ++i )
24 {
25 rval = iface.get_coords( &*i, 1, coords.array() );
26 if( MB_SUCCESS != rval ) return rval;
27 update_min( coords.array() );
28 update_max( coords.array() );
29 }
30
31
32 const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
33 std::vector< EntityHandle > dum_vector;
34 for( i = elem_begin; i != poly_begin; ++i )
35 {
36 rval = iface.get_connectivity( *i, conn, len, true, &dum_vector );
37 if( MB_SUCCESS != rval ) return rval;
38
39 rval = iface.get_coords( conn, len, &( coordverts[0][0] ) );
40 if( MB_SUCCESS != rval ) return rval;
41 for( int j = 0; j < len; ++j )
42 {
43 update_min( coordverts[j].array() );
44 update_max( coordverts[j].array() );
45 }
46
47
48 if( spherical ) update_box_spherical_elem( coordverts, len, radius );
49 }
50
51
52 const Range::const_iterator set_begin = elems.lower_bound( MBENTITYSET, poly_begin );
53 for( i = poly_begin; i != set_begin; ++i )
54 {
55 rval = iface.get_connectivity( *i, conn, len, true );
56 if( MB_SUCCESS != rval ) return rval;
57
58 for( int j = 0; j < len; ++j )
59 {
60 rval = iface.get_connectivity( conn[j], conn2, len2 );
61 if( MB_SUCCESS != rval ) return rval;
62 rval = iface.get_coords( conn2, len2, &( coordverts[0][0] ) );
63 if( MB_SUCCESS != rval ) return rval;
64 for( int k = 0; k < len2; ++k )
65 {
66 update_min( coordverts[k].array() );
67 update_max( coordverts[k].array() );
68 }
69 }
70 }
71
72
73 BoundBox box;
74 for( i = set_begin; i != elems.end(); ++i )
75 {
76 Range tmp_elems;
77 rval = iface.get_entities_by_handle( *i, tmp_elems );
78 if( MB_SUCCESS != rval ) return rval;
79 rval = box.update( iface, tmp_elems, spherical, radius );
80 if( MB_SUCCESS != rval ) return rval;
81
82 update( box );
83 }
84
85 return MB_SUCCESS;
86 }
87 void BoundBox::update_box_spherical_elem( const CartVect* verts, int len, double R )
88 {
89
90 int plane = -1;
91 CartVect pos;
92 IntxUtils::decide_gnomonic_plane( verts[0], plane );
93 double in_plane_positions[20];
94 for( int i = 0; i < len && i < 10; i++ )
95 IntxUtils::gnomonic_projection( verts[i], R, plane, in_plane_positions[2 * i], in_plane_positions[2 * i + 1] );
96
97
98 double oriented_area2 = 0;
99
100
101 for( int i = 0; i < len; i++ )
102 {
103 int i1 = ( i + 1 ) % len;
104
105 double ax = in_plane_positions[2 * i], ay = in_plane_positions[2 * i + 1];
106 double bx = in_plane_positions[2 * i1], by = in_plane_positions[2 * i1 + 1];
107 if( ay * by < 0 )
108 {
109 double alfa = ay / ( ay - by );
110 double xintx = ax + alfa * ( bx - ax );
111 IntxUtils::reverse_gnomonic_projection( xintx, 0, R, plane, pos );
112 update_min( pos.array() );
113 update_max( pos.array() );
114 }
115 if( ax * bx < 0 )
116 {
117 double alfa = ax / ( ax - bx );
118 double yintx = ay + alfa * ( by - ay );
119 IntxUtils::reverse_gnomonic_projection( 0, yintx, R, plane, pos );
120 update_min( pos.array() );
121 update_max( pos.array() );
122 }
123 oriented_area2 += ( ax * by - ay * bx );
124 }
125 if( fabs( oriented_area2 ) > R * R * 1.e-6 )
126 {
127 IntxUtils::reverse_gnomonic_projection( 0, 0, R, plane, pos );
128 update_min( pos.array() );
129 update_max( pos.array() );
130 }
131 }
132 }