Salome HOME
Feature 32: Image presentation in OCCViewer.
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_SplitZonesTool.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HYDROGUI_SplitZonesTool.h"
24
25 #include <HYDROData_Polyline.h>
26 #include <HYDROData_Zone.h>
27
28 #include <BRepAlgoAPI_Common.hxx>
29 #include <BRepAlgoAPI_Cut.hxx>
30 #include <BRepBuilderAPI_MakeFace.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Iterator.hxx>
34 #include <TopoDS_Wire.hxx>
35
36 TopoDS_Face HYDROGUI_SplitZonesTool::SplitData::Face() const
37 {
38   if( !Shape.IsNull() && Shape.ShapeType() == TopAbs_FACE )
39     return TopoDS::Face( Shape );
40   return TopoDS_Face();
41 }
42
43 HYDROGUI_SplitZonesTool::SplitDataList
44 HYDROGUI_SplitZonesTool::SplitZones( const HYDROData_SequenceOfObjects& theZoneList,
45                                      const Handle(HYDROData_Polyline)& thePolyline )
46 {
47   SplitDataList anOutputSplitDataList;
48
49   // Preparation. Collect the zone paths to split.
50   SplitDataList anInputSplitDataList;
51   for( int anIndex = 1, aLength = theZoneList.Length(); anIndex <= aLength; anIndex++ )
52   {
53     Handle(HYDROData_Zone) aZone = Handle(HYDROData_Zone)::DownCast( theZoneList.Value( anIndex ) );
54     if( !aZone.IsNull() )
55     {
56       SplitData aSplitData( aZone->Face(), aZone->GetName() );
57       anInputSplitDataList.append( aSplitData );
58     }
59   }
60
61   // Step 1. Split the paths.
62   SplitDataListIterator anInputIter( anInputSplitDataList );
63   while( anInputIter.hasNext() )
64   {
65     const SplitData& anInputSplitData = anInputIter.next();
66     if( anOutputSplitDataList.isEmpty() )
67       anOutputSplitDataList.append( anInputSplitData );
68     else
69     {
70       SplitDataList aSplitDataList;
71
72       SplitDataList aSrcSplitDataList;
73       aSrcSplitDataList.append( anInputSplitData );
74
75       SplitDataList aDestSplitDataList = anOutputSplitDataList;
76       anOutputSplitDataList.clear();
77
78       while( !aDestSplitDataList.isEmpty() )
79       {
80         SplitData aSrcSplitData = aSrcSplitDataList.last();
81
82         SplitData aDestSplitData = aDestSplitDataList.first();
83         aDestSplitDataList.pop_front();
84
85         SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
86         if( SplitTwoData( aSrcSplitData, aDestSplitData,
87                           aData1Subtracted, aData2Subtracted, aDataIntersected ) )
88           anOutputSplitDataList.append( aDataIntersected );
89         anOutputSplitDataList.append( aData2Subtracted );
90         aSrcSplitDataList.append( aData1Subtracted );
91       }
92
93       if( !aSrcSplitDataList.isEmpty() )
94         anOutputSplitDataList.append( aSrcSplitDataList.last() );
95     }
96   }
97
98   // Step 2. Take into account the boundary polyline.
99   if( !thePolyline.IsNull() )
100   {
101     const TopoDS_Wire& aWire = thePolyline->Wire();
102     if( !aWire.IsNull() )
103     {
104       BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
105       aMakeFace.Build();
106       if( aMakeFace.IsDone() )
107       {
108         SplitData aBoundarySplitData( aMakeFace.Face(), "" );
109
110         SplitDataList aCutSplitDataList;
111         SplitDataListIterator anOutputIter( anOutputSplitDataList );
112         while( anOutputIter.hasNext() )
113         {
114           const SplitData& anOutputSplitData = anOutputIter.next();
115
116           SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
117           if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
118                             aData1Subtracted, aData2Subtracted, aDataIntersected ) )
119             aCutSplitDataList.append( aDataIntersected );
120         }
121         anOutputSplitDataList = aCutSplitDataList;
122       }
123     }
124   }
125
126   // Step 3. Extract the separate regions.
127   SplitDataList anExtractedSplitDataList;
128   SplitDataListIterator anOutputIter( anOutputSplitDataList );
129   while( anOutputIter.hasNext() )
130   {
131     const SplitData& anOutputSplitData = anOutputIter.next();
132     anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
133   }
134   return anExtractedSplitDataList;
135 }
136
137 bool HYDROGUI_SplitZonesTool::SplitTwoData( const SplitData& theData1,
138                                             const SplitData& theData2,
139                                             SplitData& theData1Subtracted,
140                                             SplitData& theData2Subtracted,
141                                             SplitData& theDataIntersected )
142 {
143   const TopoDS_Shape& aShape1 = theData1.Shape;
144   const TopoDS_Shape& aShape2 = theData2.Shape;
145
146   const QStringList& aZoneNames1 = theData1.ZoneNames;
147   const QStringList& aZoneNames2 = theData2.ZoneNames;
148
149   BRepAlgoAPI_Common aCommon( aShape1, aShape2 );
150   TopoDS_Shape aCommonShape = aCommon.Shape();
151   if( aCommonShape.IsNull() )
152   {
153     theData1Subtracted = theData1;
154     theData2Subtracted = theData2;
155     return false;
156   }
157
158   BRepAlgoAPI_Cut aCut1( aShape1, aShape2 );
159   TopoDS_Shape aCut1Shape = aCut1.Shape();
160
161   BRepAlgoAPI_Cut aCut2( aShape2, aShape1 );
162   TopoDS_Shape aCut2Shape = aCut2.Shape();
163
164   theData1Subtracted = SplitData( aCut1Shape, aZoneNames1 );
165   theData2Subtracted = SplitData( aCut2Shape, aZoneNames2 );
166   theDataIntersected = SplitData( aCommonShape, aZoneNames1 + aZoneNames2 );
167
168   return true;
169 }
170
171 HYDROGUI_SplitZonesTool::SplitDataList
172 HYDROGUI_SplitZonesTool::ExtractSeparateData( const SplitData& theData )
173 {
174   SplitDataList aSplitDataList;
175   TopExp_Explorer anExp( theData.Shape, TopAbs_FACE );
176   for( ; anExp.More(); anExp.Next() )
177   {
178     TopoDS_Shape aShape = anExp.Current();
179     if( aShape.ShapeType() == TopAbs_FACE )
180     {
181       TopoDS_Face aFace = TopoDS::Face( aShape );
182       if( !aFace.IsNull() )
183       {
184         SplitData aSplitData( aFace, theData.ZoneNames );
185         aSplitDataList.append( aSplitData );
186       }
187     }
188   }
189   return aSplitDataList;
190 }