0705c13cf033df8af2b511496a4a276432b38c10
[occt.git] / src / BRepMesh / BRepMesh_ShapeVisitor.cxx
1 // Created on: 2016-04-07
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_ShapeVisitor.hxx>
17 #include <TopoDS.hxx>
18 #include <TopoDS_Edge.hxx>
19 #include <TopoDS_Face.hxx>
20 #include <TopoDS_Wire.hxx>
21 #include <TopoDS_Vertex.hxx>
22 #include <TopExp.hxx>
23 #include <ShapeAnalysis.hxx>
24 #include <TopExp_Explorer.hxx>
25 #include <IMeshData_Edge.hxx>
26 #include <IMeshData_Wire.hxx>
27 #include <IMeshData_Face.hxx>
28 #include <ShapeAnalysis_Wire.hxx>
29 #include <ShapeAnalysis_WireOrder.hxx>
30 #include <ShapeExtend_WireData.hxx>
31 #include <Precision.hxx>
32 #include <IMeshData_Status.hxx>
33 #include <IMeshTools_Context.hxx>
34 #include <BRepTools.hxx>
35
36 //=======================================================================
37 // Function: Constructor
38 // Purpose : 
39 //=======================================================================
40 BRepMesh_ShapeVisitor::BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel)
41 : myModel (theModel),
42   myDEdgeMap(1, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
43 {
44 }
45
46 //=======================================================================
47 // Function: Destructor
48 // Purpose : 
49 //=======================================================================
50 BRepMesh_ShapeVisitor::~BRepMesh_ShapeVisitor ()
51 {
52 }
53
54 //=======================================================================
55 // Function: Visit (edge)
56 // Purpose : 
57 //=======================================================================
58 void BRepMesh_ShapeVisitor::Visit(const TopoDS_Edge& theEdge)
59 {
60   if (!myDEdgeMap.IsBound (theEdge))
61   {
62     myModel->AddEdge (theEdge);
63     myDEdgeMap.Bind  (theEdge, myModel->EdgesNb () - 1);
64   }
65 }
66
67 //=======================================================================
68 // Function: Visit (face)
69 // Purpose : 
70 //=======================================================================
71 void BRepMesh_ShapeVisitor::Visit (const TopoDS_Face& theFace)
72 {
73   BRepTools::Update(theFace);
74   const IMeshData::IFaceHandle& aDFace = myModel->AddFace (theFace);
75
76   // Outer wire should always be the first in the model. 
77   TopoDS_Wire aOuterWire = ShapeAnalysis::OuterWire (theFace);
78   if (!addWire (aOuterWire, aDFace))
79   {
80     aDFace->SetStatus (IMeshData_Failure);
81     return;
82   }
83   
84   TopExp_Explorer aWireIt (theFace, TopAbs_WIRE);
85   for (; aWireIt.More (); aWireIt.Next ())
86   {
87     const TopoDS_Wire& aWire = TopoDS::Wire (aWireIt.Current ());
88     if (aWire.IsSame(aOuterWire))
89     {
90       continue;
91     }
92
93     if (!addWire (aWire, aDFace))
94     {
95       // If there is a failure on internal wire, just skip it.
96       // The most significant is an outer wire.
97       aDFace->SetStatus (IMeshData_UnorientedWire);
98     }
99   }
100 }
101
102 //=======================================================================
103 // Function: addWire
104 // Purpose : 
105 //=======================================================================
106 Standard_Boolean BRepMesh_ShapeVisitor::addWire (
107   const TopoDS_Wire&            theWire,
108   const IMeshData::IFaceHandle& theDFace)
109 {
110   if (theWire.IsNull())
111   {
112     return Standard_False;
113   }
114
115   Handle(ShapeExtend_WireData) aWireData = new ShapeExtend_WireData(theWire, Standard_True, Standard_False);
116   ShapeAnalysis_Wire aWireTool (aWireData, theDFace->GetFace (), Precision::Confusion ());
117
118   ShapeAnalysis_WireOrder aOrderTool;
119   aWireTool.CheckOrder (aOrderTool, Standard_True, Standard_False);
120   if (aWireTool.LastCheckStatus(ShapeExtend_FAIL))
121   {
122     return Standard_False;
123   }
124
125   if (aWireTool.LastCheckStatus(ShapeExtend_DONE3))
126   {
127     theDFace->SetStatus(IMeshData_UnorientedWire);
128   }
129
130   const Standard_Integer aEdgesNb = aOrderTool.NbEdges ();
131   if (aEdgesNb != aWireData->NbEdges())
132   {
133     return Standard_False;
134   }
135
136   const IMeshData::IWireHandle& aDWire = theDFace->AddWire (theWire, aEdgesNb);
137   for (Standard_Integer i = 1; i <= aEdgesNb; ++i)
138   {
139     const Standard_Integer aEdgeIndex = aOrderTool.Ordered (i);
140     const TopoDS_Edge& aEdge = aWireData->Edge (aEdgeIndex);
141     if (aEdge.Orientation() != TopAbs_EXTERNAL)
142     {
143       const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (myDEdgeMap.Find (aEdge));
144
145       aDEdge->AddPCurve (theDFace.get(), aEdge.Orientation());
146       aDWire->AddEdge   (aDEdge.get(),   aEdge.Orientation());
147     }
148   }
149
150   return Standard_True;
151 }