0025113: Mesh - Progress indication and user break functionality for BRepMesh component
[occt.git] / src / BRepMesh / BRepMesh_FaceDiscret.cxx
1 // Created on: 2016-04-19
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <BRepMesh_FaceDiscret.hxx>
17 #include <IMeshData_Model.hxx>
18 #include <IMeshData_Face.hxx>
19 #include <IMeshData_Wire.hxx>
20 #include <IMeshData_Edge.hxx>
21 #include <IMeshTools_MeshAlgo.hxx>
22 #include <OSD_Parallel.hxx>
23
24 //=======================================================================
25 // Function: Constructor
26 // Purpose : 
27 //=======================================================================
28 BRepMesh_FaceDiscret::BRepMesh_FaceDiscret(
29   const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory)
30   : myAlgoFactory(theAlgoFactory)
31 {
32 }
33
34 //=======================================================================
35 // Function: Destructor
36 // Purpose : 
37 //=======================================================================
38 BRepMesh_FaceDiscret::~BRepMesh_FaceDiscret()
39 {
40 }
41
42 //! Auxiliary functor for parallel processing of Faces.
43 class BRepMesh_FaceDiscret::FaceListFunctor
44 {
45 public:
46   FaceListFunctor (BRepMesh_FaceDiscret* theAlgo,
47                    const Message_ProgressRange& theRange)
48   : myAlgo (theAlgo),
49     myScope (theRange, "Face Discret", theAlgo->myModel->FacesNb())
50   {
51     myRanges.reserve (theAlgo->myModel->FacesNb());
52     for (Standard_Integer aFaceIter = 0; aFaceIter < theAlgo->myModel->FacesNb(); ++aFaceIter)
53     {
54       myRanges.push_back (myScope.Next());
55     }
56   }
57
58   void operator() (const Standard_Integer theFaceIndex) const
59   {
60     if (!myScope.More())
61     {
62       return;
63     }
64     Message_ProgressScope aFaceScope(myRanges[theFaceIndex], NULL, 1);
65     myAlgo->process(theFaceIndex, aFaceScope.Next());
66   }
67
68 private:
69   mutable BRepMesh_FaceDiscret* myAlgo;
70   Message_ProgressScope myScope;
71   std::vector<Message_ProgressRange> myRanges;
72 };
73
74 //=======================================================================
75 // Function: Perform
76 // Purpose : 
77 //=======================================================================
78 Standard_Boolean BRepMesh_FaceDiscret::performInternal(
79   const Handle(IMeshData_Model)& theModel,
80   const IMeshTools_Parameters&   theParameters,
81   const Message_ProgressRange&   theRange)
82 {
83   myModel      = theModel;
84   myParameters = theParameters;
85   if (myModel.IsNull())
86   {
87     return Standard_False;
88   }
89
90   FaceListFunctor aFunctor(this, theRange);
91   OSD_Parallel::For(0, myModel->FacesNb(), aFunctor, !(myParameters.InParallel && myModel->FacesNb() > 1));
92   if (!theRange.More())
93   {
94     return Standard_False;
95   }
96
97   myModel.Nullify(); // Do not hold link to model.
98   return Standard_True;
99 }
100
101 //=======================================================================
102 // Function: process
103 // Purpose : 
104 //=======================================================================
105 void BRepMesh_FaceDiscret::process(const Standard_Integer theFaceIndex, 
106                                    const Message_ProgressRange& theRange) const
107 {
108   const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
109   if (aDFace->IsSet(IMeshData_Failure) ||
110       aDFace->IsSet(IMeshData_Reused))
111   {
112     return;
113   }
114
115   try
116   {
117     OCC_CATCH_SIGNALS
118
119     Handle(IMeshTools_MeshAlgo) aMeshingAlgo = 
120       myAlgoFactory->GetAlgo(aDFace->GetSurface()->GetType(), myParameters);
121   
122     if (aMeshingAlgo.IsNull())
123     {
124       aDFace->SetStatus(IMeshData_Failure);
125       return;
126     }
127   
128     if (!theRange.More())
129     {
130       aDFace->SetStatus (IMeshData_UserBreak);
131       return;
132     }
133     aMeshingAlgo->Perform(aDFace, myParameters, theRange);
134   }
135   catch (Standard_Failure const&)
136   {
137     aDFace->SetStatus (IMeshData_Failure);
138   }
139 }