1 // Copyright (C) 2007-2013 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.
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 #include "HYDROGUI_SplitZonesTool.h"
25 #include <HYDROData_Polyline.h>
26 #include <HYDROData_Zone.h>
28 void printPath( const QString& thePathName,
29 const QPainterPath& thePath,
30 const QStringList& theZonesList = QStringList() )
32 printf( "%s ", qPrintable( thePathName ) );
33 if( !theZonesList.isEmpty() )
36 QStringListIterator anIter( theZonesList );
37 while( anIter.hasNext() )
38 printf( "%s ", qPrintable( anIter.next() ) );
41 printf( "(n=%d) :", thePath.elementCount() );
42 for( int i = 0, n = thePath.elementCount(); i < n; i++ )
44 const QPainterPath::Element anElement = thePath.elementAt( i );
45 switch( anElement.type )
47 case QPainterPath::MoveToElement:
48 printf( " M(%.0f,%.0f)", anElement.x, anElement.y );
50 case QPainterPath::LineToElement:
51 printf( " L(%.0f,%.0f)", anElement.x, anElement.y );
60 HYDROGUI_SplitZonesTool::SplitDataList
61 HYDROGUI_SplitZonesTool::SplitZones( const HYDROData_SequenceOfObjects& theZoneList,
62 const Handle(HYDROData_Polyline)& thePolyline )
64 SplitDataList anOutputSplitDataList;
66 // Preparation. Collect the zone paths to split.
67 SplitDataList anInputSplitDataList;
68 for( int anIndex = 1, aLength = theZoneList.Length(); anIndex <= aLength; anIndex++ )
70 Handle(HYDROData_Zone) aZone = Handle(HYDROData_Zone)::DownCast( theZoneList.Value( anIndex ) );
73 SplitData aSplitData( aZone->GetPainterPath(), aZone->GetName() );
74 anInputSplitDataList.append( aSplitData );
78 // Step 1. Split the paths.
80 SplitDataListIterator anInputIter( anInputSplitDataList );
81 while( anInputIter.hasNext() )
83 const SplitData& anInputSplitData = anInputIter.next();
84 if( anOutputSplitDataList.isEmpty() )
85 anOutputSplitDataList.append( anInputSplitData );
88 SplitDataList aSplitDataList;
90 SplitDataList aSrcSplitDataList;
91 aSrcSplitDataList.append( anInputSplitData );
93 SplitDataList aDestSplitDataList = anOutputSplitDataList;
94 anOutputSplitDataList.clear();
96 while( !aDestSplitDataList.isEmpty() )
98 SplitData aSrcSplitData = aSrcSplitDataList.last();
100 SplitData aDestSplitData = aDestSplitDataList.first();
101 aDestSplitDataList.pop_front();
103 SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
104 if( SplitTwoData( aSrcSplitData, aDestSplitData,
105 aData1Subtracted, aData2Subtracted, aDataIntersected ) )
106 anOutputSplitDataList.append( aDataIntersected );
107 anOutputSplitDataList.append( aData2Subtracted );
108 aSrcSplitDataList.append( aData1Subtracted );
111 if( !aSrcSplitDataList.isEmpty() )
112 anOutputSplitDataList.append( aSrcSplitDataList.last() );
116 // Step 2. Take into account the boundary polyline.
117 printf( "Step 2\n" );
118 if( !thePolyline.IsNull() )
120 const QPainterPath& aBoundaryPath = thePolyline->painterPath();
121 SplitData aBoundarySplitData( aBoundaryPath, "" );
123 SplitDataList aCutSplitDataList;
124 SplitDataListIterator anOutputIter( anOutputSplitDataList );
125 while( anOutputIter.hasNext() )
127 const SplitData& anOutputSplitData = anOutputIter.next();
129 SplitData aData1Subtracted, aData2Subtracted, aDataIntersected;
130 if( SplitTwoData( anOutputSplitData, aBoundarySplitData,
131 aData1Subtracted, aData2Subtracted, aDataIntersected ) )
132 aCutSplitDataList.append( aDataIntersected );
134 anOutputSplitDataList = aCutSplitDataList;
137 // Step 3. Extract the separate regions.
138 printf( "Step 3\n" );
139 SplitDataList anExtractedSplitDataList;
140 SplitDataListIterator anOutputIter( anOutputSplitDataList );
141 while( anOutputIter.hasNext() )
143 const SplitData& anOutputSplitData = anOutputIter.next();
144 anExtractedSplitDataList.append( ExtractSeparateData( anOutputSplitData ) );
146 return anExtractedSplitDataList;
149 bool HYDROGUI_SplitZonesTool::SplitTwoData( const SplitData& theData1,
150 const SplitData& theData2,
151 SplitData& theData1Subtracted,
152 SplitData& theData2Subtracted,
153 SplitData& theDataIntersected )
155 const QPainterPath& aPath1 = theData1.Path;
156 const QPainterPath& aPath2 = theData2.Path;
158 const QStringList& aZoneNames1 = theData1.ZoneNames;
159 const QStringList& aZoneNames2 = theData2.ZoneNames;
161 //printPath( "aPath1", aPath1, aZoneNames1 );
162 //printPath( "aPath2", aPath2, aZoneNames2 );
164 QPainterPath aPathIntersected = aPath1.intersected( aPath2 );
165 aPathIntersected.closeSubpath();
166 //printPath( "aPathIntersected", aPathIntersected );
167 if( aPathIntersected.isEmpty() )
169 theData1Subtracted = theData1;
170 theData2Subtracted = theData2;
174 QPainterPath aPath1Subtracted = aPath1.subtracted( aPath2 );
175 //printPath( "aPath1Subtracted", aPath1Subtracted );
176 theData1Subtracted = SplitData( aPath1Subtracted, aZoneNames1 );
178 QPainterPath aPath2Subtracted = aPath2.subtracted( aPath1 );
179 //printPath( "aPath2Subtracted", aPath2Subtracted );
180 theData2Subtracted = SplitData( aPath2Subtracted, aZoneNames2 );
182 theDataIntersected = SplitData( aPathIntersected, aZoneNames1 + aZoneNames2 );
187 HYDROGUI_SplitZonesTool::SplitDataList
188 HYDROGUI_SplitZonesTool::ExtractSeparateData( const SplitData& theData )
190 SplitDataList aSplitDataList;
192 const QPainterPath& aBasePath = theData.Path;
193 const QStringList& aBaseZoneNames = theData.ZoneNames;
195 QList<QPainterPath> aPathList;
196 for( int i = 0, n = aBasePath.elementCount(); i < n; i++ )
198 const QPainterPath::Element anElement = aBasePath.elementAt( i );
199 switch( anElement.type )
201 case QPainterPath::MoveToElement:
202 aPathList.append( QPainterPath( QPointF( anElement.x, anElement.y ) ) );
204 case QPainterPath::LineToElement:
205 if( !aPathList.isEmpty() )
207 QPainterPath& aPath = aPathList.last();
208 aPath.lineTo( anElement.x, anElement.y );
211 case QPainterPath::CurveToElement: // currently not supported
217 // check the hole case
218 if( aPathList.size() == 2 )
220 const QPainterPath& aPath1 = aPathList.first();
221 const QPainterPath& aPath2 = aPathList.last();
222 if( aPath1.contains( aPath2 ) || aPath2.contains( aPath1 ) )
224 aSplitDataList.append( theData );
225 return aSplitDataList;
229 QListIterator<QPainterPath> anIter( aPathList );
230 while( anIter.hasNext() )
232 QPainterPath aPath = anIter.next();
233 aPath.closeSubpath();
234 //printPath( "aPath", aPath );
235 aSplitDataList.append( SplitData( aPath, aBaseZoneNames ) );
237 return aSplitDataList;