MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 }