1/**
2 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 * storing and accessing finite element mesh data.
4 *
5 * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 * retains certain rights in this software.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 */1516#ifndef SWEPT_ELEMENT_DATA_HPP17#define SWEPT_ELEMENT_DATA_HPP1819//20// Class: SweptElementData21//22// Purpose: represent a rectangular element of mesh23//24// A SweptElement represents a rectangular element of mesh, including both vertices and25// elements, and the parametric space used to address that element. Vertex data,26// i.e. coordinates, may not be stored directly in the element, but the element returns27// information about the vertex handles of vertices in the element. Vertex and element28// handles associated with the element are each contiguous.2930#include"SequenceData.hpp"31#include"moab/HomXform.hpp"32#include"moab/CN.hpp"33#include"SweptVertexData.hpp"34#include"Internals.hpp"35#include"moab/Range.hpp"3637#include<vector>38#include<algorithm>3940namespace moab
41 {
4243classSweptElementData : public SequenceData
44 {
4546//! structure to hold references to bounding vertex blocks47classVertexDataRef48 {
49private:
50 HomCoord minmax[2];
51 HomXform xform, invXform;
52 SweptVertexData* srcSeq;
5354public:
55friendclassSweptElementData;
5657VertexDataRef( const HomCoord& min, const HomCoord& max, const HomXform& tmp_xform, SweptVertexData* this_seq );
5859boolcontains( const HomCoord& coords )const;
60 };
6162private:
63//! parameter min/max/stride, in homogeneous coords ijkh64 HomCoord elementParams[3];
6566//! difference between max and min params plus one (i.e. # VERTICES in67//! each parametric direction)68int dIJK[3];
6970//! difference between max and min params (i.e. # ELEMENTS in71//! each parametric direction)72int dIJKm1[3];
7374//! bare constructor, so compiler doesn't create one for me75SweptElementData();
7677//! list of bounding vertex blocks78 std::vector< VertexDataRef > vertexSeqRefs;
7980public:
81//! constructor82SweptElementData( EntityHandle start_handle,
83constint imin,
84constint jmin,
85constint kmin,
86constint imax,
87constint jmax,
88constint kmax,
89constint* Cq );
9091virtual ~SweptElementData();
9293//! get handle of vertex at homogeneous coords94inline EntityHandle get_vertex( const HomCoord& coords )const;
95inline EntityHandle get_vertex( int i, int j, int k )const
96 {
97returnget_vertex( HomCoord( i, j, k ) );
98 }
99100//! get handle of element at i, j, k101EntityHandle get_element( constint i, constint j, constint k )const;
102103//! get min params for this element104const HomCoord& min_params()const;
105106//! get max params for this element107const HomCoord& max_params()const;
108109//! get the number of vertices in each direction, inclusive110voidparam_extents( int& di, int& dj, int& dk )const;
111112//! given a handle, get the corresponding parameters113ErrorCode get_params( const EntityHandle ehandle, int& i, int& j, int& k )const;
114115//! convenience functions for parameter extents116inti_min()const
117 {
118return ( elementParams[0].hom_coord() )[0];
119 }
120intj_min()const
121 {
122return ( elementParams[0].hom_coord() )[1];
123 }
124intk_min()const
125 {
126return ( elementParams[0].hom_coord() )[2];
127 }
128inti_max()const
129 {
130return ( elementParams[1].hom_coord() )[0];
131 }
132intj_max()const
133 {
134return ( elementParams[1].hom_coord() )[1];
135 }
136intk_max()const
137 {
138return ( elementParams[1].hom_coord() )[2];
139 }
140141//! test the bounding vertex sequences and determine whether they fully142//! define the vertices covering this element block's parameter space143boolboundary_complete()const;
144145//! test whether this sequence contains these parameters146inlineboolcontains( const HomCoord& coords )const;
147148//! get connectivity of an entity given entity's parameters149inline ErrorCode get_params_connectivity( constint i,
150constint j,
151constint k,
152 std::vector< EntityHandle >& connectivity )const;
153154//! add a vertex seq ref to this element sequence;155//! if bb_input is true, bounding box (in eseq-local coords) of vseq being added156//! is input in bb_min and bb_max (allows partial sharing of vseq rather than the whole157//! vseq); if it's false, the whole vseq is referenced and the eseq-local coordinates158//! is computed from the transformed bounding box of the vseq159ErrorCode add_vsequence( SweptVertexData* vseq,
160const HomCoord& p1,
161const HomCoord& q1,
162const HomCoord& p2,
163const HomCoord& q2,
164const HomCoord& p3,
165const HomCoord& q3,
166bool bb_input = false,
167const HomCoord& bb_min = HomCoord::unitv[0],
168const HomCoord& bb_max = HomCoord::unitv[0] );
169170SequenceData* subset( EntityHandle start,
171 EntityHandle end,
172constint* sequence_data_sizes,
173constint* tag_data_sizes )const;
174175static EntityID calc_num_entities( EntityHandle start_handle, int irange, int jrange, int krange );
176177unsignedlongget_memory_use()const;
178 };
179180inline EntityHandle SweptElementData::get_element( constint i, constint j, constint k )const
181 {
182returnstart_handle() + ( i - i_min() ) + ( j - j_min() ) * dIJKm1[0] + ( k - k_min() ) * dIJKm1[0] * dIJKm1[1];
183 }
184185inlineconst HomCoord& SweptElementData::min_params()const
186 {
187return elementParams[0];
188 }
189190inlineconst HomCoord& SweptElementData::max_params()const
191 {
192return elementParams[1];
193 }
194195//! get the number of vertices in each direction, inclusive196inlinevoidSweptElementData::param_extents( int& di, int& dj, int& dk )const
197 {
198 di = dIJK[0];
199 dj = dIJK[1];
200 dk = dIJK[2];
201 }
202203inline ErrorCode SweptElementData::get_params( const EntityHandle ehandle, int& i, int& j, int& k )const
204 {
205if( TYPE_FROM_HANDLE( ehandle ) != TYPE_FROM_HANDLE( start_handle() ) ) return MB_FAILURE;
206207int hdiff = ehandle - start_handle();
208209// use double ?: test below because on some platforms, both sides of the : are210// evaluated, and if dIJKm1[1] is zero, that'll generate a divide-by-zero211 k = ( dIJKm1[1] > 0 ? hdiff / ( dIJKm1[1] > 0 ? dIJKm1[0] * dIJKm1[1] : 1 ) : 0 );
212 j = ( hdiff - ( k * dIJKm1[0] * dIJKm1[1] ) ) / dIJKm1[0];
213 i = hdiff % dIJKm1[0];
214215 k += elementParams[0].k();
216 j += elementParams[0].j();
217 i += elementParams[0].i();
218219return ( ehandle >= start_handle() && ehandle < start_handle() + size() && i >= i_min() && i <= i_max() &&
220 j >= j_min() && j <= j_max() && k >= k_min() && k <= k_max() )
221 ? MB_SUCCESS
222 : MB_FAILURE;
223 }
224225inlineboolSweptElementData::contains( const HomCoord& temp )const
226 {
227// upper bound is < instead of <= because element params max is one less228// than vertex params max229return ( temp >= elementParams[0] && temp < elementParams[1] );
230 }
231232inlinebool SweptElementData::VertexDataRef::contains( const HomCoord& coords ) const233 {
234return ( minmax[0] <= coords && minmax[1] >= coords );
235 }
236237inline SweptElementData::VertexDataRef::VertexDataRef( const HomCoord& this_min,
238const HomCoord& this_max,
239const HomXform& tmp_xform,
240 SweptVertexData* this_seq )
241 : xform( tmp_xform ), invXform( tmp_xform.inverse() ), srcSeq( this_seq )
242 {
243 minmax[0] = HomCoord( this_min );
244 minmax[1] = HomCoord( this_max );
245 }
246247inline EntityHandle SweptElementData::get_vertex( const HomCoord& coords )const
248 {
249assert( boundary_complete() );
250for( std::vector< VertexDataRef >::const_iterator it = vertexSeqRefs.begin(); it != vertexSeqRefs.end(); ++it )
251 {
252if( ( *it ).minmax[0] <= coords && ( *it ).minmax[1] >= coords )
253 {
254// first get the vertex block-local parameters255 HomCoord local_coords = coords / ( *it ).xform;
256257// now get the vertex handle for those coords258return ( *it ).srcSeq->get_vertex( local_coords );
259 }
260 }
261262// got here, it's an error263return0;
264 }
265266inline ErrorCode SweptElementData::add_vsequence( SweptVertexData* vseq,
267const HomCoord& p1,
268const HomCoord& q1,
269const HomCoord& p2,
270const HomCoord& q2,
271const HomCoord& p3,
272const HomCoord& q3,
273bool bb_input,
274const HomCoord& bb_min,
275const HomCoord& bb_max )
276 {
277// compute the transform given the vseq-local parameters and the mapping to278// this element sequence's parameters passed in minmax279 HomXform M;
280 M.three_pt_xform( p1, q1, p2, q2, p3, q3 );
281282// min and max in element seq's parameter system may not be same as those in283// vseq's system, so need to take min/max284285 HomCoord minmax[2];
286if( bb_input )
287 {
288 minmax[0] = bb_min;
289 minmax[1] = bb_max;
290 }
291else292 {
293 minmax[0] = vseq->min_params() * M;
294 minmax[1] = vseq->max_params() * M;
295 }
296297// check against other vseq's to make sure they don't overlap298for( std::vector< VertexDataRef >::const_iterator vsit = vertexSeqRefs.begin(); vsit != vertexSeqRefs.end();
299 ++vsit )
300if( ( *vsit ).contains( minmax[0] ) || ( *vsit ).contains( minmax[1] ) ) return MB_FAILURE;
301302HomCoord tmp_min( std::min( minmax[0].i(), minmax[1].i() ), std::min( minmax[0].j(), minmax[1].j() ),
303 std::min( minmax[0].k(), minmax[1].k() ) );
304HomCoord tmp_max( std::max( minmax[0].i(), minmax[1].i() ), std::max( minmax[0].j(), minmax[1].j() ),
305 std::max( minmax[0].k(), minmax[1].k() ) );
306307// set up a new vertex sequence reference308VertexDataRef tmp_seq_ref( tmp_min, tmp_max, M, vseq );
309310// add to the list311 vertexSeqRefs.push_back( tmp_seq_ref );
312313return MB_SUCCESS;
314 }
315316inline ErrorCode SweptElementData::get_params_connectivity( constint i,
317constint j,
318constint k,
319 std::vector< EntityHandle >& connectivity )const
320 {
321if( contains( HomCoord( i, j, k ) ) == false ) return MB_FAILURE;
322323 connectivity.push_back( get_vertex( i, j, k ) );
324 connectivity.push_back( get_vertex( i + 1, j, k ) );
325if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 2 ) return MB_SUCCESS;
326 connectivity.push_back( get_vertex( i + 1, j + 1, k ) );
327 connectivity.push_back( get_vertex( i, j + 1, k ) );
328if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 3 ) return MB_SUCCESS;
329 connectivity.push_back( get_vertex( i, j, k + 1 ) );
330 connectivity.push_back( get_vertex( i + 1, j, k + 1 ) );
331 connectivity.push_back( get_vertex( i + 1, j + 1, k + 1 ) );
332 connectivity.push_back( get_vertex( i, j + 1, k + 1 ) );
333return MB_SUCCESS;
334 }
335336 } // namespace moab337338#endif