MOAB: Mesh Oriented datABase  (version 5.4.1)
PlanarDomain.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2004 Sandia Corporation and Argonne National
00005     Laboratory.  Under the terms of Contract DE-AC04-94AL85000
00006     with Sandia Corporation, the U.S. Government retains certain
00007     rights in this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     [email protected], [email protected], [email protected],
00024     [email protected], [email protected], [email protected],
00025     [email protected]
00026 
00027   ***************************************************************** */
00028 #include "PlanarDomain.hpp"
00029 #include "MsqError.hpp"
00030 #include "MsqVertex.hpp"
00031 #include "DomainUtil.hpp"
00032 
00033 #include <algorithm>
00034 
00035 MBMesquite::PlanarDomain::~PlanarDomain() {}
00036 
00037 void MBMesquite::PlanarDomain::set_plane( const MBMesquite::Vector3D& normal, const MBMesquite::Vector3D& point )
00038 {
00039     mNormal = normal;
00040     mNormal.normalize();
00041     mCoeff = -( mNormal % point );
00042 }
00043 
00044 void MBMesquite::PlanarDomain::snap_to( MBMesquite::Mesh::VertexHandle /*entity_handle*/, Vector3D& coordinate ) const
00045 {
00046     coordinate -= mNormal * ( mNormal % coordinate + mCoeff );
00047 }
00048 
00049 void MBMesquite::PlanarDomain::vertex_normal_at( MBMesquite::Mesh::VertexHandle /*entity_handle*/,
00050                                                  MBMesquite::Vector3D& coordinate ) const
00051 {
00052     coordinate = mNormal;
00053 }
00054 
00055 void MBMesquite::PlanarDomain::element_normal_at( MBMesquite::Mesh::ElementHandle /*entity_handle*/,
00056                                                   MBMesquite::Vector3D& coordinate ) const
00057 {
00058     coordinate = mNormal;
00059 }
00060 
00061 void MBMesquite::PlanarDomain::vertex_normal_at( const MBMesquite::Mesh::VertexHandle*,
00062                                                  Vector3D coords[],
00063                                                  unsigned count,
00064                                                  MBMesquite::MsqError& ) const
00065 {
00066     for( unsigned i = 0; i < count; ++i )
00067         coords[i] = mNormal;
00068 }
00069 
00070 void MBMesquite::PlanarDomain::closest_point( MBMesquite::Mesh::VertexHandle,
00071                                               const MBMesquite::Vector3D& position,
00072                                               MBMesquite::Vector3D& closest,
00073                                               MBMesquite::Vector3D& normal,
00074                                               MBMesquite::MsqError& ) const
00075 {
00076     normal  = mNormal;
00077     closest = position - mNormal * ( mNormal % position + mCoeff );
00078 }
00079 
00080 void MBMesquite::PlanarDomain::domain_DoF( const Mesh::VertexHandle*,
00081                                            unsigned short* dof_array,
00082                                            size_t num_vertices,
00083                                            MsqError& ) const
00084 {
00085     std::fill( dof_array, dof_array + num_vertices, 2 );
00086 }
00087 
00088 void MBMesquite::PlanarDomain::flip()
00089 {
00090     mNormal = -mNormal;
00091     mCoeff  = -mCoeff;
00092 }
00093 
00094 void MBMesquite::PlanarDomain::fit_vertices( Mesh* mesh, MsqError& err, double epsilon )
00095 {
00096     // Our goal here is to consider only the boundary (fixed) vertices
00097     // when calculating the plane.  If for some reason the user wants
00098     // to snap a not-quite-planar mesh to a plane during optimization,
00099     // if possible we want to start with the plane containing the fixed
00100     // vertices, as those won't get snapped.  If no vertices are fixed,
00101     // then treat them all as fixed for the purpose calculating the plane
00102     // (consider them all.)
00103 
00104     std::vector< Mesh::VertexHandle > verts, fixed;
00105     mesh->get_all_vertices( verts, err );MSQ_ERRRTN( err );
00106     DomainUtil::get_fixed_vertices( mesh, arrptr( verts ), verts.size(), fixed, err );MSQ_ERRRTN( err );
00107 
00108     bool do_all_verts = true;
00109     if( fixed.size() > 2 )
00110     {
00111         do_all_verts = false;
00112         fit_vertices( mesh, arrptr( fixed ), fixed.size(), err, epsilon );
00113 
00114         // if we failed with only the fixed vertices, try again with all of the
00115         // vertices
00116         if( err )
00117         {
00118             err.clear();
00119             do_all_verts = true;
00120         }
00121     }
00122 
00123     if( do_all_verts )
00124     {
00125         fit_vertices( mesh, arrptr( verts ), verts.size(), err, epsilon );MSQ_ERRRTN( err );
00126     }
00127 
00128     // now count inverted elements
00129     size_t inverted_count = 0, total_count = 0;
00130     std::vector< Mesh::ElementHandle > elems;
00131     std::vector< size_t > junk;
00132     std::vector< MsqVertex > coords;
00133     mesh->get_all_elements( elems, err );MSQ_ERRRTN( err );
00134     for( size_t i = 0; i < elems.size(); ++i )
00135     {
00136 
00137         EntityTopology type;
00138         mesh->elements_get_topologies( &elems[i], &type, 1, err );
00139         if( TopologyInfo::dimension( type ) != 2 ) continue;
00140 
00141         verts.clear();
00142         mesh->elements_get_attached_vertices( arrptr( elems ), 1, verts, junk, err );MSQ_ERRRTN( err );
00143         if( verts.size() < 3 ) continue;
00144 
00145         coords.resize( verts.size() );
00146         mesh->vertices_get_coordinates( arrptr( verts ), arrptr( coords ), 3, err );MSQ_ERRRTN( err );
00147         Vector3D n = ( coords[1] - coords[0] ) * ( coords[2] - coords[0] );
00148         ++total_count;
00149         if( n % mNormal < 0.0 ) ++inverted_count;
00150     }
00151 
00152     // if most elements are inverted, flip normal
00153     if( 2 * inverted_count > total_count ) this->flip();
00154 }
00155 
00156 void MBMesquite::PlanarDomain::fit_vertices( MBMesquite::Mesh* mesh,
00157                                              const MBMesquite::Mesh::VertexHandle* verts,
00158                                              size_t num_verts,
00159                                              MBMesquite::MsqError& err,
00160                                              double epsilon )
00161 {
00162     std::vector< MsqVertex > coords( num_verts );
00163     mesh->vertices_get_coordinates( verts, arrptr( coords ), num_verts, err );MSQ_ERRRTN( err );
00164 
00165     if( epsilon <= 0.0 ) epsilon = DomainUtil::default_tolerance( arrptr( coords ), num_verts );
00166 
00167     Vector3D pts[3];
00168     if( !DomainUtil::non_colinear_vertices( arrptr( coords ), num_verts, pts, epsilon ) )
00169     {
00170         MSQ_SETERR( err )( "All vertices are colinear", MsqError::INVALID_MESH );
00171         return;
00172     }
00173 
00174     this->set_plane( ( pts[1] - pts[0] ) * ( pts[2] - pts[0] ), pts[0] );
00175 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines