0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / BRepMesh / BRepMesh_FaceChecker.cxx
1 // Created on: 2016-07-04
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_FaceChecker.hxx>
17 #include <IMeshData_Wire.hxx>
18 #include <IMeshData_Edge.hxx>
19 #include <OSD_Parallel.hxx>
20 #include <BRepMesh_GeomTool.hxx>
21
22 namespace
23 {
24   const Standard_Real MaxTangentAngle = 5. * M_PI / 180.;
25
26   //! Functor to be used to fill segments and bounding box tree in parallel.
27   class SegmentsFiller
28   {
29   public:
30     //! Constructor.
31     SegmentsFiller(const IMeshData::IFaceHandle&                    theDFace,
32                    Handle(BRepMesh_FaceChecker::ArrayOfSegments)&   theWiresSegments,
33                    Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& theWiresBndBoxTree)
34       : myDFace(theDFace),
35         myWiresSegments(theWiresSegments),
36         myWiresBndBoxTree(theWiresBndBoxTree)
37     {
38       myWiresSegments   = new BRepMesh_FaceChecker::ArrayOfSegments   (0, myDFace->WiresNb() - 1);
39       myWiresBndBoxTree = new BRepMesh_FaceChecker::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1);
40     }
41
42     //! Performs initialization of wire with the given index.
43     void operator()(const Standard_Integer theWireIndex) const
44     {
45       const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex);
46
47       Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator();
48
49       Handle(BRepMesh_FaceChecker::Segments) aSegments = 
50         new BRepMesh_FaceChecker::Segments(aDWire->EdgesNb(), aTmpAlloc1);
51       Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1);
52
53       myWiresSegments  ->ChangeValue(theWireIndex) = aSegments;
54       myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree;
55
56       Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator();
57       IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2);
58
59       for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
60       {
61         // TODO: check 2d wire for consistency.
62
63         const IMeshData::IEdgePtr&      aDEdge  = aDWire->GetEdge(aEdgeIt);
64         const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
65
66         for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
67         {
68           gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1);
69           gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt);
70
71           Bnd_Box2d aBox;
72           aBox.Add(aPnt1);
73           aBox.Add(aPnt2);
74           aBox.Enlarge(Precision::Confusion());
75
76           aBndBoxTreeFiller.Add(aSegments->Size(), aBox);
77           aSegments->Append(BRepMesh_FaceChecker::Segment(aDEdge, &aPnt1, &aPnt2));
78         }
79       }
80
81       aBndBoxTreeFiller.Fill();
82     }
83
84   private:
85
86     SegmentsFiller (const SegmentsFiller& theOther);
87
88     void operator=(const SegmentsFiller& theOther);
89
90   private:
91
92     const IMeshData::IFaceHandle&                    myDFace;
93     Handle(BRepMesh_FaceChecker::ArrayOfSegments)&   myWiresSegments;
94     Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& myWiresBndBoxTree;
95   };
96
97   //! Selector.
98   //! Used to identify segments with overlapped bounding boxes.
99   class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector
100   {
101   public:
102     //! Constructor.
103     BndBox2dTreeSelector(const Standard_Real theTolerance)
104       : myMaxLoopSize(M_PI * theTolerance * theTolerance),
105         mySelfSegmentIndex(-1),
106         mySegment(0),
107         myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
108     {
109     }
110
111     //! Sets working set of segments.
112     void SetSegments(const Handle(BRepMesh_FaceChecker::Segments)& theSegments)
113     {
114       mySegments = theSegments;
115     }
116
117     //! Resets current selector.
118     void Reset(const BRepMesh_FaceChecker::Segment* theSegment,
119                const Standard_Integer               theSelfSegmentIndex)
120     {
121       myIndices.Clear();
122
123       mySelfSegmentIndex = theSelfSegmentIndex;
124       mySegment = theSegment;
125
126       myBox.SetVoid();
127       myBox.Add(*mySegment->Point1);
128       myBox.Add(*mySegment->Point2);
129       myBox.Enlarge(Precision::Confusion());
130     }
131
132     //! Indicates should the given box be rejected or not.
133     virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const
134     {
135       return myBox.IsOut(theBox);
136     }
137
138     //! Accepts segment with the given index in case if it fits conditions.
139     virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex)
140     {
141       const BRepMesh_FaceChecker::Segment& aSegment = mySegments->Value(theSegmentIndex);
142
143       gp_Pnt2d aIntPnt;
144       const BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
145         mySegment->Point1->XY(), mySegment->Point2->XY(),
146         aSegment.Point1->XY(), aSegment.Point2->XY(),
147         Standard_False, Standard_False, aIntPnt);
148
149       if (aIntStatus == BRepMesh_GeomTool::Cross)
150       {
151         const Standard_Real aAngle = gp_Vec2d(mySegment->Point1->XY(), mySegment->Point2->XY()).Angle(
152                                      gp_Vec2d(aSegment.Point1->XY(), aSegment.Point2->XY()));
153
154         if (Abs(aAngle) < MaxTangentAngle)
155         {
156           return Standard_False;
157         }
158
159         if (mySelfSegmentIndex != -1)
160         {
161           gp_XY aPrevVec;
162           Standard_Real aSumS = 0.;
163           const gp_XY& aRefPnt = aIntPnt.Coord();
164           for (Standard_Integer i = mySelfSegmentIndex; i < theSegmentIndex; ++i)
165           {
166             const BRepMesh_FaceChecker::Segment& aCurrSegment = mySegments->Value(i);
167             gp_XY aCurVec = aCurrSegment.Point2->XY() - aRefPnt;
168
169             if (aCurVec.SquareModulus() < gp::Resolution())
170               continue;
171
172             if (aPrevVec.SquareModulus() > gp::Resolution())
173               aSumS += aPrevVec ^ aCurVec;
174
175             aPrevVec = aCurVec;
176           }
177
178           if (Abs(aSumS / 2.) < myMaxLoopSize)
179           {
180             return Standard_False;
181           }
182         }
183
184         myIndices.Append(theSegmentIndex);
185         return Standard_True;
186       }
187
188       return Standard_False;
189     }
190
191     //! Returns indices of intersecting segments.
192     const IMeshData::VectorOfInteger& Indices() const
193     {
194       return myIndices;
195     }
196
197   private:
198
199     Standard_Real                          myMaxLoopSize;
200     Standard_Integer                       mySelfSegmentIndex;
201     Handle(BRepMesh_FaceChecker::Segments) mySegments;
202     const BRepMesh_FaceChecker::Segment*   mySegment;
203     Bnd_Box2d                              myBox;
204     IMeshData::VectorOfInteger             myIndices;
205   };
206 }
207
208 //=======================================================================
209 //function : Constructor
210 //purpose  : 
211 //=======================================================================
212 BRepMesh_FaceChecker::BRepMesh_FaceChecker(
213   const IMeshData::IFaceHandle& theFace,
214   const IMeshTools_Parameters&  theParameters)
215   : myDFace(theFace),
216     myParameters(theParameters)
217 {
218 }
219
220 //=======================================================================
221 //function : Destructor
222 //purpose  : 
223 //=======================================================================
224 BRepMesh_FaceChecker::~BRepMesh_FaceChecker()
225 {
226 }
227
228 //=======================================================================
229 //function : Perform
230 //purpose  : 
231 //=======================================================================
232 Standard_Boolean BRepMesh_FaceChecker::Perform()
233 {
234   myIntersectingEdges = new IMeshData::MapOfIEdgePtr;
235   collectSegments();
236
237   OSD_Parallel::For(0, myDFace->WiresNb(), *this, !isParallel());
238   collectResult();
239
240   myWiresBndBoxTree.Nullify();
241   myWiresSegments.Nullify();
242   myWiresIntersectingEdges.Nullify();
243   return myIntersectingEdges->IsEmpty();
244 }
245
246 //=======================================================================
247 //function : collectSegments
248 //purpose  : 
249 //=======================================================================
250 void BRepMesh_FaceChecker::collectSegments()
251 {
252   SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree);
253   OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel());
254
255   myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1);
256 }
257
258 //=======================================================================
259 //function : perform
260 //purpose  : 
261 //=======================================================================
262 void BRepMesh_FaceChecker::perform(const Standard_Integer theWireIndex) const
263 {
264   const Handle(Segments)&           aSegments1     = myWiresSegments->Value(theWireIndex);
265   Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myWiresIntersectingEdges->ChangeValue(theWireIndex);
266
267   // TODO: Tolerance is set to twice value of face deflection in order to fit regressions.
268   BndBox2dTreeSelector aSelector(2 * myDFace->GetDeflection());
269   for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt)
270   {
271     const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt);
272     const Handle(Segments)&                aSegments2 = myWiresSegments->Value(aWireIt);
273
274     aSelector.SetSegments(aSegments2);
275     for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt)
276     {
277       const BRepMesh_FaceChecker::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
278       aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1);
279       if (aBndBoxTree2->Select(aSelector) != 0)
280       {
281         if (aIntersections.IsNull())
282         {
283           aIntersections = new IMeshData::MapOfIEdgePtr;
284         }
285
286         aIntersections->Add(aSegment1.EdgePtr);
287
288         const IMeshData::VectorOfInteger& aSegments = aSelector.Indices();
289         for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt)
290         {
291           const BRepMesh_FaceChecker::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
292           aIntersections->Add(aSegment2.EdgePtr);
293         }
294       }
295     }
296   }
297 }
298
299 //=======================================================================
300 //function : collectResult
301 //purpose  : 
302 //=======================================================================
303 void BRepMesh_FaceChecker::collectResult()
304 {
305   for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
306   {
307     const Handle(IMeshData::MapOfIEdgePtr)& aEdges = myWiresIntersectingEdges->Value(aWireIt);
308     if (!aEdges.IsNull())
309     {
310       myIntersectingEdges->Unite(*aEdges);
311     }
312   }
313 }