1 // Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : StdMeshers_BlockRenumber.cxx
24 // Author : Edward AGAPOV, OCC
27 #include "StdMeshers_BlockRenumber.hxx"
29 #include <SMDS_EdgePosition.hxx>
30 #include <SMDS_FacePosition.hxx>
31 #include <SMESHDS_Mesh.hxx>
32 #include <SMESHDS_SubMesh.hxx>
33 #include <SMESH_Algo.hxx>
34 #include <SMESH_Mesh.hxx>
35 #include <SMESH_MesherHelper.hxx>
36 #include <SMESH_TryCatch.hxx>
37 #include <SMESH_BoostTxtArchive.hxx>
39 #include <BRep_Tool.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopTools_MapOfShape.hxx>
44 #include <boost/archive/text_oarchive.hpp>
46 //=============================================================================
50 //=============================================================================
52 StdMeshers_BlockRenumber::StdMeshers_BlockRenumber(int hypId, SMESH_Gen * gen)
53 :SMESH_Hypothesis(hypId, gen)
55 _name = "BlockRenumber";
56 _param_algo_dim = 3; // is used by StdMeshers_Hexa_3D and StdMeshers_CompositeHexa_3D
59 //================================================================================
61 * \brief Set local CS of blocks
63 //================================================================================
65 void StdMeshers_BlockRenumber::SetBlocksOrientation( std::vector< StdMeshers_BlockCS > & blockCS )
67 if ( _blockCS != blockCS )
69 NotifySubMeshesHypothesisModification();
70 _blockCS.swap( blockCS );
71 _solids2vertices.Clear();
75 //================================================================================
77 * Return true and vertices if block orientation is defined for a given solid
79 //================================================================================
81 bool StdMeshers_BlockRenumber::IsSolidIncluded( SMESH_Mesh& mesh,
82 const TopoDS_Shape& solid,
83 TopoDS_Vertex& vertex000,
84 TopoDS_Vertex& vertex001 ) const
90 if ( _solids2vertices.IsEmpty() )
92 StdMeshers_BlockRenumber* me = const_cast<StdMeshers_BlockRenumber*>(this);
93 for ( StdMeshers_BlockCS& bcs : me->_blockCS )
95 TopoDS_Shape so = mesh.GetShapeByEntry( bcs._solid );
96 TopoDS_Shape s000 = mesh.GetShapeByEntry( bcs._vertex000 );
97 TopoDS_Shape s001 = mesh.GetShapeByEntry( bcs._vertex001 );
98 TopoDS_Vertex v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s000 );
99 TopoDS_Vertex v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( so, s001 );
100 if ( !v000.IsNull() && !v001.IsNull() )
102 me->_solids2vertices.Bind( so, std::make_pair( v000, v001 ));
103 if ( so.IsSame( solid ))
112 else if ( !solid.IsNull() )
114 if (( result = _solids2vertices.IsBound( solid )))
116 auto vvPairPtr = _solids2vertices.Seek( solid );
117 vertex000 = vvPairPtr->first;
118 vertex001 = vvPairPtr->second;
124 //=======================================================================
125 //function : CheckHypothesis
127 //=======================================================================
129 SMESH_ComputeErrorPtr StdMeshers_BlockRenumber::CheckHypothesis(SMESH_Mesh& aMesh,
130 const TopoDS_Shape& /*shape*/) const
132 SMESH_Comment errorTxt;
133 for ( size_t i = 0; i < _blockCS.size() && errorTxt.empty(); ++i )
135 TopoDS_Shape solid = aMesh.GetShapeByEntry( _blockCS[i]._solid );
136 TopoDS_Shape v000 = aMesh.GetShapeByEntry( _blockCS[i]._vertex000 );
137 TopoDS_Shape v001 = aMesh.GetShapeByEntry( _blockCS[i]._vertex001 );
138 v000 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v000 );
139 v001 = StdMeshers_RenumberHelper::GetVertexAtPoint( solid, v001 );
141 if ( solid.IsNull() || solid.ShapeType() != TopAbs_SOLID )
142 errorTxt << "Can't find a SOLID by entry '" << _blockCS[i]._solid << "'";
143 else if ( v000.IsNull() || v000.ShapeType() != TopAbs_VERTEX )
144 errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex000 << "'";
145 else if ( v001.IsNull() || v001.ShapeType() != TopAbs_VERTEX )
146 errorTxt << "Can't find a VERTEX by entry '" << _blockCS[i]._vertex001 << "'";
147 else if ( !SMESH_MesherHelper::IsSubShape( v000, solid ))
148 errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '"
149 << _blockCS[i]._solid << "'";
150 else if ( !SMESH_MesherHelper::IsSubShape( v001, solid ))
151 errorTxt << "VERTEX '" << _blockCS[i]._vertex001 << "' does not belong to SOLID '"
152 << _blockCS[i]._solid << "'";
153 else if ( SMESH_MesherHelper::Count( solid, TopAbs_VERTEX, true ) == 8 &&
154 SMESH_MesherHelper::GetCommonAncestor( v000, v001, aMesh, TopAbs_EDGE ).IsNull() )
155 errorTxt << "Vertices '" << _blockCS[i]._vertex000 << "' and '" << _blockCS[i]._vertex001
156 << "' are not connected by an edge";
159 SMESH_ComputeErrorPtr error;
160 if ( !errorTxt.empty() )
162 error = SMESH_ComputeError::New( COMPERR_BAD_PARMETERS,
163 SMESH_Comment("Renumber hypothesis: ") << errorTxt );
168 //=======================================================================
169 //function : StdMeshers_RenumberHelper
170 //purpose : constructor
171 //=======================================================================
173 StdMeshers_RenumberHelper::StdMeshers_RenumberHelper( SMESH_Mesh& mesh,
174 const StdMeshers_BlockRenumber* hyp)
175 : _mesh( &mesh ), _hyp( hyp ), _newOldNodes( 2, nullptr )
179 //=======================================================================
180 //function : GetVertex000
181 //purpose : Find default vertex at (0,0,0) local position
182 //=======================================================================
184 TopoDS_Vertex StdMeshers_RenumberHelper::GetVertex000( const TopTools_MapOfShape& cornerVertices )
187 if ( cornerVertices.Extent() < 8 )
188 return TopoDS_Vertex();
190 double minVal = DBL_MAX, minX = DBL_MAX, val;
191 for ( auto it = cornerVertices.cbegin(); it != cornerVertices.cend(); ++it )
193 gp_Pnt P = BRep_Tool::Pnt( TopoDS::Vertex( *it ));
194 val = P.X() + P.Y() + P.Z();
195 if ( val < minVal || ( val == minVal && P.X() < minX ))
197 v000 = TopoDS::Vertex( *it );
205 //=======================================================================
206 //function : GetVertexAtPoint
207 //purpose : Return the VERTEX of solid at given point
208 //=======================================================================
210 TopoDS_Vertex StdMeshers_RenumberHelper::GetVertexAtPoint( const TopoDS_Shape& solid,
211 const TopoDS_Shape& point )
213 if ( !solid.IsNull() && !point.IsNull() && point.ShapeType() == TopAbs_VERTEX )
215 gp_Pnt p = BRep_Tool::Pnt( TopoDS::Vertex( point ));
216 double tol = Precision::Confusion();
217 for ( TopExp_Explorer exp( solid, TopAbs_VERTEX ); exp.More(); exp.Next() )
219 const TopoDS_Vertex& v = TopoDS::Vertex( exp.Current() );
220 if ( v.IsSame( point ) || p.IsEqual( BRep_Tool::Pnt( v ), tol ))
224 return TopoDS_Vertex();
227 //================================================================================
229 * Create a copy of an old node and remember this couple of nodes for replacement
231 //================================================================================
233 void StdMeshers_RenumberHelper::AddReplacingNode( const SMDS_MeshNode* & oldNode )
235 SMESHDS_Mesh* mesh = _mesh->GetMeshDS();
236 SMESH_NodeXYZ oldXYZ = oldNode;
237 SMDS_MeshNode* newNode = mesh->AddNode( oldXYZ.X(), oldXYZ.Y(), oldXYZ.Z() );
238 _newOldNodes.front() = newNode;
239 _newOldNodes.back() = oldNode;
240 _nodesToMerge.push_back( _newOldNodes );
243 int shapeID = oldXYZ->GetShapeID();
244 const TopoDS_Shape& shape = mesh->IndexToShape( shapeID );
245 if ( !shape.IsNull() )
246 switch ( shape.ShapeType() )
249 if ( SMDS_FacePositionPtr pos = oldXYZ->GetPosition() )
250 mesh->SetNodeOnFace( newNode, shapeID, pos->GetUParameter(), pos->GetVParameter() );
253 if ( SMDS_EdgePositionPtr pos = oldXYZ->GetPosition() )
254 mesh->SetNodeOnEdge( newNode, shapeID, pos->GetUParameter() );
257 mesh->SetNodeOnVertex( newNode, shapeID );
260 mesh->SetNodeInVolume( newNode, shapeID );
264 //================================================================================
266 * Replace old nodes by new ones
268 //================================================================================
270 void StdMeshers_RenumberHelper::DoReplaceNodes()
272 SMESH_MeshEditor( _mesh ).MergeNodes( _nodesToMerge );
275 //=============================================================================
279 //=============================================================================
281 ostream & StdMeshers_BlockRenumber::SaveTo(ostream & save)
283 boost::archive::text_oarchive archive( save );
289 //=============================================================================
293 //=============================================================================
295 istream & StdMeshers_BlockRenumber::LoadFrom(istream & load)
299 SMESHUtils::BoostTxtArchive( load ) >> *this;
301 SMESH_CATCH( SMESH::doNothing );
307 namespace serialization {
309 //=======================================================================
310 //function : serialize
311 //purpose : serialize StdMeshers_BlockCS
312 //=======================================================================
314 template<class Archive>
315 void serialize(Archive & ar, StdMeshers_BlockCS & blockCS, const unsigned int /*version*/)
318 ar & blockCS._vertex000;
319 ar & blockCS._vertex001;
322 } // namespace serialization