X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_LandCoverMap.cxx;h=c582b16fcc4143a2842f97b97fa89f57f3de270b;hb=a95289fabbb6fbf6f32c06207422c65aafd5bd65;hp=a429e381ae43931784e002cf925fac6169926e8a;hpb=8bc58b696dd7feff7d22965b4bad946e6c2c1458;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_LandCoverMap.cxx b/src/HYDROData/HYDROData_LandCoverMap.cxx index a429e381..c582b16f 100644 --- a/src/HYDROData/HYDROData_LandCoverMap.cxx +++ b/src/HYDROData/HYDROData_LandCoverMap.cxx @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #include #include @@ -31,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -40,14 +42,36 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include #include +#include + +#define _DEVDEBUG_ +#include "HYDRO_trace.hxx" const char TELEMAC_FORMAT = 'f'; const int TELEMAC_PRECISION = 3; @@ -56,24 +80,20 @@ const int TELEMAC_PRECISION = 3; IMPLEMENT_STANDARD_HANDLE(HYDROData_LandCoverMap, HYDROData_Entity) IMPLEMENT_STANDARD_RTTIEXT(HYDROData_LandCoverMap, HYDROData_Entity) -class HYDROData_MapOfFaceToStricklerType : public NCollection_IndexedDataMap -{ -}; - /** Constructor @param theMap the land cover map to iterate through */ -HYDROData_LandCoverMap::Iterator::Iterator( const HYDROData_LandCoverMap& theMap ) +HYDROData_LandCoverMap::Explorer::Explorer( const HYDROData_LandCoverMap& theMap ) { Init( theMap ); } -HYDROData_LandCoverMap::Iterator::Iterator( const Handle( HYDROData_LandCoverMap )& theMap ) +HYDROData_LandCoverMap::Explorer::Explorer( const Handle( HYDROData_LandCoverMap )& theMap ) { if( theMap.IsNull() ) { - myIterator = 0; + myExplorer = 0; myIndex = -1; } else @@ -84,13 +104,16 @@ HYDROData_LandCoverMap::Iterator::Iterator( const Handle( HYDROData_LandCoverMap Initialize the iterator @param theMap the land cover map to iterate through */ -void HYDROData_LandCoverMap::Iterator::Init( const HYDROData_LandCoverMap& theMap ) +void HYDROData_LandCoverMap::Explorer::Init( const HYDROData_LandCoverMap& theMap ) { TopoDS_Shape aShape = theMap.GetShape(); if( aShape.IsNull() ) - myIterator = 0; + myExplorer = 0; else - myIterator = new TopoDS_Iterator( aShape ); + { + myExplorer = new TopExp_Explorer(); + myExplorer->Init( aShape, TopAbs_FACE ); + } theMap.myLab.FindChild( DataTag_Types ).FindAttribute( TDataStd_ExtStringArray::GetID(), myArray ); if( myArray.IsNull() ) @@ -102,16 +125,16 @@ void HYDROData_LandCoverMap::Iterator::Init( const HYDROData_LandCoverMap& theMa /** Destructor */ -HYDROData_LandCoverMap::Iterator::~Iterator() +HYDROData_LandCoverMap::Explorer::~Explorer() { - delete myIterator; + delete myExplorer; } /** Return the current 0-based index of the iterator @return the current index */ -int HYDROData_LandCoverMap::Iterator::Index() const +int HYDROData_LandCoverMap::Explorer::Index() const { if( myArray.IsNull() ) return -1; @@ -123,19 +146,19 @@ int HYDROData_LandCoverMap::Iterator::Index() const Return if the iterator has more elements @return if the iterator has more elements */ -bool HYDROData_LandCoverMap::Iterator::More() const +bool HYDROData_LandCoverMap::Explorer::More() const { - return !myArray.IsNull() && myIterator && myIterator->More(); + return !myArray.IsNull() && myExplorer && myExplorer->More(); } /** Move iterator to the next element */ -void HYDROData_LandCoverMap::Iterator::Next() +void HYDROData_LandCoverMap::Explorer::Next() { - if( myIterator ) + if( myExplorer ) { - myIterator->Next(); + myExplorer->Next(); myIndex++; } } @@ -144,10 +167,10 @@ void HYDROData_LandCoverMap::Iterator::Next() Get the current land cover (face) @return the land cover's face */ -TopoDS_Face HYDROData_LandCoverMap::Iterator::Face() const +TopoDS_Face HYDROData_LandCoverMap::Explorer::Face() const { - if( myIterator ) - return TopoDS::Face( myIterator->Value() ); + if( myExplorer ) + return TopoDS::Face( myExplorer->Current() ); else return TopoDS_Face(); } @@ -156,7 +179,7 @@ TopoDS_Face HYDROData_LandCoverMap::Iterator::Face() const Get the current land cover's Strickler type @return the land cover's Strickler type */ -QString HYDROData_LandCoverMap::Iterator::StricklerType() const +QString HYDROData_LandCoverMap::Explorer::StricklerType() const { if( myArray.IsNull() || myIndex < myArray->Lower() || myIndex > myArray->Upper() ) return ""; @@ -168,7 +191,7 @@ QString HYDROData_LandCoverMap::Iterator::StricklerType() const Set the Strickler type for the current land cover @param theType the Strickler type */ -void HYDROData_LandCoverMap::Iterator::SetStricklerType( const QString& theType ) +void HYDROData_LandCoverMap::Explorer::SetStricklerType( const QString& theType ) { if( myArray.IsNull() || myIndex < myArray->Lower() || myIndex > myArray->Upper() ) return; @@ -200,6 +223,24 @@ const ObjectKind HYDROData_LandCoverMap::GetKind() const return KIND_LAND_COVER_MAP; } +int HYDROData_LandCoverMap::GetLCCount() const +{ + Explorer anIt( *this ); + int i = 0; + for( ; anIt.More(); anIt.Next() ) + i++; + return i; +} + +bool HYDROData_LandCoverMap::IsEmpty() const +{ + Explorer anIt( *this ); + if ( !anIt.More() ) + return true; + else + return false; +} + /** Load attributes from DBF File /// @@ -225,14 +266,18 @@ HYDROData_LandCoverMap::DBFStatus HYDROData_LandCoverMap::ImportDBF( const QStri aDBFImporter.DBF_GetAttributeList(FieldNameIndex, theAttrV ); bool allOK = true; - Iterator anIt( *this ); + Explorer anIt( *this ); for( ; anIt.More(); anIt.Next() ) { int CurIndex = anIt.Index(); - HYDROData_ShapeFile::DBF_AttrValue AValue = theAttrV[theIndices[CurIndex]]; - int StricklerTypesInd = theDBFValues.indexOf(QString(AValue.myStrVal)); + int anIndex = CurIndex; + if( !theIndices.isEmpty() ) + anIndex = theIndices[CurIndex]; + + HYDROData_ShapeFile::DBF_AttrValue AValue = theAttrV[anIndex]; + int StricklerTypesInd = theDBFValues.indexOf( QString( AValue.myStrVal ) ); if ( StricklerTypesInd != -1) - anIt.SetStricklerType(theStricklerTypes[StricklerTypesInd]); + anIt.SetStricklerType( theStricklerTypes[StricklerTypesInd] ); else allOK = false; } @@ -251,9 +296,11 @@ void HYDROData_LandCoverMap::ExportDBF( const QString& theDBFFileName, const QStringList& theDBFValues, const QStringList& theStricklerTypes) const { + if (theDBFValues.size() != theStricklerTypes.size()) + return; HYDROData_ShapeFile anExporter; std::vector theAttrV; - Iterator anIt( *this ); + Explorer anIt( *this ); for( ; anIt.More(); anIt.Next() ) { QString CurST = anIt.StricklerType(); @@ -269,8 +316,8 @@ void HYDROData_LandCoverMap::ExportDBF( const QString& theDBFFileName, else aCurAttrV.myIsNull = true; } - - anExporter.DBF_WriteFieldAndValues(theDBFFileName, theFieldName, HYDROData_ShapeFile::DBF_FieldType_String, theAttrV, true); + //use actual str value; not the raw value + anExporter.DBF_WriteFieldAndValues(theDBFFileName, theFieldName, HYDROData_ShapeFile::DBF_FieldType_String, theAttrV, false); } @@ -318,19 +365,26 @@ bool EdgeDiscretization( const TopoDS_Edge& theEdge, @param theFileName the name of file @return if the export is successful */ -bool HYDROData_LandCoverMap::ExportTelemac( const QString& theFileName, Standard_Real theDeflection ) const +bool HYDROData_LandCoverMap::ExportTelemac( const QString& theFileName, + double theDeflection, + const Handle(HYDROData_StricklerTable)& theTable ) const { TopoDS_Shape aLandCoverMapShape = GetShape(); TopTools_ListOfShape aListOfFaces; - TopExp_Explorer anExp( aLandCoverMapShape, TopAbs_FACE ); - for( ; anExp.More(); anExp.Next() ) - aListOfFaces.Append( anExp.Current() ); + Explorer anIt( *this ); + QMap aTypesMap; + for( ; anIt.More(); anIt.Next() ) + { + aListOfFaces.Append( anIt.Face() ); + aTypesMap.insert( anIt.Face().TShape(), anIt.StricklerType() ); + } - TopoDS_Shape aShape = MergeFaces( aListOfFaces, false ); + TopoDS_Shape aShape = MergeFaces( aListOfFaces, false, NULL ); NCollection_IndexedMap aVerticesMap; NCollection_IndexedDataMap< TopoDS_Edge, QList > anEdgesMap; - NCollection_IndexedDataMap< TopoDS_Face, QList > aFacesMap; + typedef QPair< QString, QList > FaceData; + NCollection_IndexedDataMap< TopoDS_Face, FaceData > aFacesMap; // add into the map all edges existing in the shell TopExp_Explorer anExp1( aShape, TopAbs_EDGE ); @@ -355,7 +409,11 @@ bool HYDROData_LandCoverMap::ExportTelemac( const QString& theFileName, Standard int anEdgeId = anEdgesMap.FindIndex( anEdge ); anEdgesIdsList.append( anEdgeId ); } - aFacesMap.Add( aFace, anEdgesIdsList ); + + FaceData aData; + aData.first = aTypesMap[aFace.TShape()]; + aData.second = anEdgesIdsList; + aFacesMap.Add( aFace, aData ); } QFile aFile( theFileName ); @@ -389,10 +447,14 @@ bool HYDROData_LandCoverMap::ExportTelemac( const QString& theFileName, Standard aStream << "\n"; aStream << "# faces\n"; - NCollection_IndexedDataMap< TopoDS_Face, QList >::Iterator anIt3( aFacesMap ); + NCollection_IndexedDataMap< TopoDS_Face, FaceData >::Iterator anIt3( aFacesMap ); for( ; anIt3.More(); anIt3.Next() ) { - QList anEdgesIds = anIt3.Value(); + QString aType = anIt3.Value().first; + double aCoeff = theTable->Get( aType, 0.0 ); + QList anEdgesIds = anIt3.Value().second; + //aStream << "\"" << aType << "\" "; + aStream << QString::number( aCoeff, TELEMAC_FORMAT, TELEMAC_PRECISION ) << " "; foreach( int anId, anEdgesIds ) aStream << anId << " "; aStream << "\n"; @@ -415,10 +477,34 @@ bool HYDROData_LandCoverMap::Add( const Handle( HYDROData_Object )& theObject, c return false; TopoDS_Shape aShape = theObject->GetTopShape(); - if( aShape.ShapeType()!=TopAbs_FACE ) + TopoDS_Face aFace; + + if( aShape.ShapeType() ==TopAbs_FACE ) + { + aFace = TopoDS::Face(aShape); + } + else if ( aShape.ShapeType() ==TopAbs_COMPOUND ) + { + TopoDS_Iterator It(aShape); + for (; It.More(); It.Next()) + if (It.Value().ShapeType() == TopAbs_FACE) + { + aFace = TopoDS::Face(It.Value()); + break; + } + } + + if (aFace.IsNull()) + return false; + return LocalPartition( aFace, theType ); +} + +bool HYDROData_LandCoverMap::Add( const TopoDS_Wire& theWire, const QString& theType ) +{ + if( !theWire.Closed() ) return false; - TopoDS_Face aFace = TopoDS::Face( aShape ); + TopoDS_Face aFace = BRepBuilderAPI_MakeFace( theWire, Standard_True ).Face(); return LocalPartition( aFace, theType ); } @@ -434,15 +520,22 @@ bool HYDROData_LandCoverMap::Add( const Handle( HYDROData_PolylineXY )& thePolyl return false; TopoDS_Shape aShape = thePolyline->GetShape(); - if( aShape.ShapeType()!=TopAbs_WIRE ) - return false; + if( aShape.ShapeType()==TopAbs_WIRE ) + return Add( TopoDS::Wire( aShape ), theType ); - TopoDS_Wire aWire = TopoDS::Wire( aShape ); - if( !aWire.Closed() ) - return false; + if( aShape.ShapeType()==TopAbs_COMPOUND ) + { + TopExp_Explorer anExp( aShape, TopAbs_WIRE ); + for( ; anExp.More(); anExp.Next() ) + { + TopoDS_Wire aPart = TopoDS::Wire( anExp.Current() ); + if( !Add( aPart, theType ) ) + return false; + } + return true; + } - TopoDS_Face aFace = BRepBuilderAPI_MakeFace( aWire, Standard_True ).Face(); - return LocalPartition( aFace, theType ); + return false; } /** @@ -473,11 +566,14 @@ bool HYDROData_LandCoverMap::Remove( const TopTools_ListOfShape& theFacesToRemov aFacesToRemove.Add( TopoDS::Face( aShape ), "" ); } - Iterator anIt( *this ); + Explorer anIt( *this ); for( ; anIt.More(); anIt.Next() ) if( !aFacesToRemove.Contains( anIt.Face() ) ) aNewFaces.Add( anIt.Face(), anIt.StricklerType() ); + if ( aNewFaces.IsEmpty() ) + return false; + StoreLandCovers( aNewFaces ); return true; } @@ -493,9 +589,23 @@ bool HYDROData_LandCoverMap::Split( const Handle( HYDROData_PolylineXY )& thePol return false; TopoDS_Shape aShape = thePolyline->GetShape(); - return LocalPartition( aShape, "" ); + return Split( aShape ); } + +/** + Split the land cover map by the given polyline + @param theShape the tool polyline to split the land cover map + @return if the removing is successful +*/ +bool HYDROData_LandCoverMap::Split( const TopoDS_Shape& theShape ) +{ + int aNbCL = GetLCCount(); + bool aResult = LocalPartition( theShape, "" ); + return aResult && aNbCL != GetLCCount(); +} + + /** Merge the given faces in the land cover @param theFaces the faces to merge in the land cover map @@ -505,21 +615,39 @@ bool HYDROData_LandCoverMap::Split( const Handle( HYDROData_PolylineXY )& thePol bool HYDROData_LandCoverMap::Merge( const TopTools_ListOfShape& theFaces, const QString& theType ) { // 1. to fuse the faces into the new face - TopoDS_Shape aMergedFace = MergeFaces( theFaces, true ); - if( aMergedFace.ShapeType()==TopAbs_FACE ) - { + TopoDS_Shape aMergedFace = MergeFaces( theFaces, true, NULL ); + bool aStat = true; + if( !aMergedFace.IsNull() ) + { // 2. to remove the merged faces from the current map Remove( theFaces ); - - // 3. to add the face into the map - return LocalPartition( TopoDS::Face( aMergedFace ), theType ); + TopExp_Explorer Exp(aMergedFace, TopAbs_FACE); + for( ; Exp.More(); Exp.Next() ) + { + const TopoDS_Face& aCF = TopoDS::Face(Exp.Current()); + // 3. to add the face into the map + aStat = aStat && LocalPartition( aCF, theType ); + } } - return false; + else + aStat = false; + return aStat; } +/** + Merge the given faces into the shell/face + @param theFaces the faces to merge + @param IsToUnify if the common edges should be removed (fused) + @param theTolerance the operation's tolerance + @return result shape (face or shell) +*/ + TopoDS_Shape HYDROData_LandCoverMap::MergeFaces( const TopTools_ListOfShape& theFaces, - bool IsToUnify, double theTolerance ) + bool IsToUnify, + TopTools_IndexedDataMapOfShapeListOfShape* theShHistory, + double theTolerance) { + //DEBTRACE("MergeFaces"); int anError; TopTools_ListIteratorOfListOfShape anIt; BOPCol_ListOfShape aLC; @@ -553,6 +681,19 @@ TopoDS_Shape HYDROData_LandCoverMap::MergeFaces( const TopTools_ListOfShape& the const TopoDS_Shape& aMergedShape = anAlgo.Shape(); + // retrieve history of modifications + if (theShHistory) + { + theShHistory->Clear(); + anIt.Initialize(theFaces); + for( ; anIt.More(); anIt.Next() ) + { + const TopTools_ListOfShape aMLS = anAlgo.Modified( anIt.Value() ); + theShHistory->Add(anIt.Value(), aMLS); + } + } + // + BRep_Builder aBuilder; TopoDS_Shell aShell; aBuilder.MakeShell( aShell ); @@ -582,16 +723,56 @@ TopoDS_Shape HYDROData_LandCoverMap::MergeFaces( const TopTools_ListOfShape& the aResult = aShell; anExplorer.Init( aResult, TopAbs_FACE ); - int i = 0; + int n = 0; TopoDS_Face anOneFace; - for( ; anExplorer.More(); anExplorer.Next(), i++ ) + for( ; anExplorer.More(); anExplorer.Next(), n++ ) anOneFace = TopoDS::Face( anExplorer.Current() ); - if( i == 1 ) + if (n == 1) aResult = anOneFace; + else if (aResult.ShapeType() == TopAbs_SHELL) + { + BRepCheck_Shell aBCS(TopoDS::Shell(aResult)); + if (aBCS.Status().First() != BRepCheck_NoError) + { + ShapeFix_Shell aFixer; + aFixer.FixFaceOrientation(TopoDS::Shell(aResult), 1); + aResult = aFixer.Shape(); + } + } return aResult; } +/** + Change Strickler type for the list of faces to the given one + @param theFaces the faces to change type + @param theType the Strickler type for the given land cover(s) + @return if the change type operation is successful +*/ +bool HYDROData_LandCoverMap::ChangeType( const TopTools_ListOfShape& theFaces, const QString& theType ) +{ + HYDROData_MapOfFaceToStricklerType aFacesToChangeType; + TopTools_ListIteratorOfListOfShape aFIt( theFaces ); + for( ; aFIt.More(); aFIt.Next() ) + { + TopoDS_Shape aShape = aFIt.Value(); + if( aShape.ShapeType()==TopAbs_FACE ) + aFacesToChangeType.Add( TopoDS::Face( aShape ), "" ); + } + + int aNbChanges = 0; + Explorer anIt( *this ); + for( ; anIt.More(); anIt.Next() ) + if( aFacesToChangeType.Contains( anIt.Face() ) ) + { + anIt.SetStricklerType( theType ); + aNbChanges++; + } + if ( aNbChanges != theFaces.Extent() ) + return false; + + return true; +} /** Get the shape of the land cover map @@ -601,6 +782,26 @@ TopoDS_Shape HYDROData_LandCoverMap::GetShape() const return HYDROData_Entity::GetShape( DataTag_Shape ); } +/** + Get Strickler type of the given land cover + @param theLandCover the land cover to get Strickler type of + @return name of Strickler type +*/ +QString HYDROData_LandCoverMap::StricklerType( const TopoDS_Face& theLandCover ) const +{ + QString aType = ""; + + Explorer anIt( *this ); + for( ; anIt.More(); anIt.Next() ) + if( anIt.Face().IsEqual( theLandCover) ) + { + aType = anIt.StricklerType(); + break; + } + + return aType; +} + /** Set the shape of the land cover map @param theShape the new shape for the land cover map @@ -626,11 +827,12 @@ bool HYDROData_LandCoverMap::LocalPartition( const TopoDS_Shape& theNewShape, co HYDROData_MapOfFaceToStricklerType aNewFaces; // add faces to shapes list - Iterator anIt( *this ); + Explorer anIt( *this ); for( ; anIt.More(); anIt.Next() ) aShapesList.Append( anIt.Face() ); aShapesList.Append( theNewShape ); + //DEBTRACE("theNewType " << theNewType); if( aShapesList.Size()==1 && theNewShape.ShapeType()==TopAbs_FACE ) { aNewFaces.Add( TopoDS::Face( theNewShape ), theNewType ); @@ -658,16 +860,19 @@ bool HYDROData_LandCoverMap::LocalPartition( const TopoDS_Shape& theNewShape, co if( anError ) return false; + //std::cout << "History:" << std::endl; // analysis of the history // a. to fill map of shapes which come from the new face - NCollection_IndexedMap aShapesFromNewFace; - //std::cout << "new: " << theNewShape << " " << theNewType << std::endl; + NCollection_IndexedMap aShapesFromNewFace; + //std::cout << "from NEW " << theNewShape << ":" << theNewType << std::endl; TopTools_ListOfShape aModified = aBuilder.Modified( theNewShape ); TopTools_ListIteratorOfListOfShape aMIt( aModified ); for( ; aMIt.More(); aMIt.Next() ) { //std::cout << " " << aMIt.Value() << std::endl; - aShapesFromNewFace.Add( aMIt.Value() ); + //DEBTRACE(aMIt.Value()); + int aKey = (int)(uintptr_t)aMIt.Value().TShape().operator->(); + aShapesFromNewFace.Add( aKey ); } // b. to fill map of parts except parts from new face @@ -675,26 +880,40 @@ bool HYDROData_LandCoverMap::LocalPartition( const TopoDS_Shape& theNewShape, co for( ; anIt.More(); anIt.Next() ) { QString aSType = anIt.StricklerType(); - //std::cout << anIt.Face() << " " << anIt.StricklerType() << std::endl; + //DEBTRACE(anIt.StricklerType() << " " << anIt.Face()); + //std::cout << "from " << anIt.Face() << ": " << anIt.StricklerType() << std::endl; TopTools_ListOfShape aModified = aBuilder.Modified( anIt.Face() ); + // + if( aModified.Extent() == 0 ) + aModified.Append( anIt.Face() ); + //DEBTRACE(anIt.StricklerType() << " " << anIt.Face()); + TopTools_ListIteratorOfListOfShape aMIt( aModified ); for( ; aMIt.More(); aMIt.Next() ) { TopoDS_Shape aShape = aMIt.Value(); bool isFace = aShape.ShapeType()==TopAbs_FACE; - bool isAlsoFromNew = aShapesFromNewFace.Contains( aShape ); + int aKey = (int)(uintptr_t)aShape.TShape().operator->(); + bool isAlsoFromNew = aShapesFromNewFace.Contains( aKey ); //std::cout << " " << aShape << " " << isAlsoFromNew << std::endl; if( isFace && !isAlsoFromNew ) aNewFaces.Add( TopoDS::Face( aShape ), aSType ); } + //DEBTRACE(anIt.StricklerType() << " " << anIt.Face()); } - // c. add the new shape if it is face with its type if( theNewShape.ShapeType()==TopAbs_FACE ) aNewFaces.Add( TopoDS::Face( theNewShape ), theNewType ); + //DEBTRACE(theNewShape << " " << theNewType); // convert map of shape to type to compound and list of types StoreLandCovers( aNewFaces ); + +// anIt.Init( *this ); +// for( ; anIt.More(); anIt.Next() ) +// { +// DEBTRACE(anIt.StricklerType() << " " << anIt.Face()); +// } return true; } @@ -704,29 +923,129 @@ bool HYDROData_LandCoverMap::LocalPartition( const TopoDS_Shape& theNewShape, co */ void HYDROData_LandCoverMap::StoreLandCovers( const HYDROData_MapOfFaceToStricklerType& theMap ) { - TopoDS_Shell aShell; - BRep_Builder aShellBuilder; - aShellBuilder.MakeShell( aShell ); - aShell.Closed( Standard_False ); TopTools_ListOfShape aListOfFaces; - int n = theMap.Size(); - Handle( TDataStd_ExtStringArray ) aTypes = - TDataStd_ExtStringArray::Set( myLab.FindChild( DataTag_Types ), 0, n-1, Standard_True ); - HYDROData_MapOfFaceToStricklerType::Iterator aNFIt( theMap ); - for( int i=0; aNFIt.More(); aNFIt.Next(), i++ ) + //DEBTRACE("theMap.Extent() " << theMap.Extent()); + for( int i = 1; i <= theMap.Extent(); i++ ) { - TopoDS_Face aFace = aNFIt.Key(); - if (aFace.IsNull()) + TopoDS_Face aFace = theMap.FindKey(i); + if( aFace.IsNull() ) continue; - QString aType = aNFIt.Value(); - aShellBuilder.Add( aShell, aFace ); aListOfFaces.Append(aFace); - aTypes->SetValue( i, HYDROData_Tool::toExtString( aType ) ); } - TopoDS_Shape aMF = MergeFaces(aListOfFaces, false); - SetShape( aListOfFaces.Extent() < 2 ? aShell : MergeFaces(aListOfFaces, false)); + TopTools_IndexedDataMapOfShapeListOfShape ShHistory; + ShHistory.Clear(); + + TopoDS_Shape aResult; + if( aListOfFaces.Extent() == 1 ) + aResult = aListOfFaces.First(); + else if( aListOfFaces.Extent() > 1 ) + aResult = MergeFaces( aListOfFaces, false, &ShHistory ); + + //remove internal edges + //if nothing changes => the result shape should be the same + //hence the map will be empty + + NCollection_IndexedDataMap ShF2FHistory; + RemoveInternal(aResult, &ShF2FHistory); + + //one face => mark as unchanged + if( aListOfFaces.Extent() == 1 ) + ShHistory.Add(aResult, TopTools_ListOfShape()); + + NCollection_IndexedDataMap aChF2ST; + QStringList aSTypes; + // + for( int i = 1; i <= theMap.Extent(); i++ ) + { + TopoDS_Face aFF = theMap.FindKey(i); + //DEBTRACE(" --- " << aFF); + if( aFF.IsNull() ) + continue; + //DEBTRACE(ShHistory.IsEmpty()); + //DEBTRACE(aFF.Checked()); + TopTools_ListOfShape aLS; + try + { + aLS = ShHistory.FindFromKey(aFF); //TODO: bug to fix. Observed on an incomplete split of a face + } + catch (...) + { + DEBTRACE("TODO: bug to fix. Observed on an incomplete split of a face"); + //continue; // No, keep aLS empty and propagate the type of the original face + } + if (aLS.IsEmpty()) + { + //DEBTRACE("--- aLS.IsEmpty()"); + QString aSType = theMap.FindFromKey(aFF); + //DEBTRACE(" --- " << aSType.toStdString()); + if (ShF2FHistory.Contains(aFF)) + { + //DEBTRACE("ShF2FHistory.FindFromKey(aFF) " << ShF2FHistory.FindFromKey(aFF)); + aChF2ST.Add(ShF2FHistory.FindFromKey(aFF), aSType); + } + else + { + //DEBTRACE("aFF " << aFF); + aChF2ST.Add(aFF, aSType); + } + } + else + { + //DEBTRACE("--- !aLS.IsEmpty()"); + TopTools_ListIteratorOfListOfShape anIt(aLS); + for (; anIt.More(); anIt.Next()) + { + QString aSType = theMap.FindFromKey(aFF); + //DEBTRACE(" --- " << aSType.toStdString()); + const TopoDS_Face& aMF = TopoDS::Face(anIt.Value()); + //if (ShF2FHistory.Contains(aFF)) + if (ShF2FHistory.Contains(aMF)) + { + //DEBTRACE("ShF2FHistory.FindFromKey(aMF) " << ShF2FHistory.FindFromKey(aFF)); + aChF2ST.Add(ShF2FHistory.FindFromKey(aMF), aSType); + } + else + { + //DEBTRACE("aMF " << aMF); + aChF2ST.Add(aMF, aSType); + } + } + } + } + // + SetShape( aResult ); + // + //Explorer Exp(*this); + TopExp_Explorer FExp(aResult, TopAbs_FACE); + for( ; FExp.More(); FExp.Next() ) + { + TopoDS_Face aFace = TopoDS::Face(FExp.Current()); + QString aST = ""; + if (aChF2ST.Contains(aFace)) + aST = aChF2ST.FindFromKey(aFace); + //DEBTRACE("aFace " << aFace << " aST " << aST.toStdString()); + aSTypes << aST; + } + + Handle( TDataStd_ExtStringArray ) aTypes = TDataStd_ExtStringArray::Set( myLab.FindChild( DataTag_Types ), 0, aSTypes.size() - 1, Standard_True ); + int k = 0; + foreach (QString aST, aSTypes) + { + //DEBTRACE("aST " << aST.toStdString()); + aTypes->SetValue( k, HYDROData_Tool::toExtString( aST ) ); + k++; + } + +} + +/** + Checks that object has 2D presentation. Reimlemented to retun true. +*/ +bool HYDROData_LandCoverMap::IsHas2dPrs() const +{ + return true; } /** @@ -738,7 +1057,7 @@ void HYDROData_LandCoverMap::StoreLandCovers( const HYDROData_MapOfFaceToStrickl TopoDS_Face HYDROData_LandCoverMap::FindByPoint( const gp_Pnt2d& thePoint, QString& theType ) const { //TODO: some more optimal algorithm - Iterator anIt( *this ); + Explorer anIt( *this ); for( ; anIt.More(); anIt.Next() ) if( HYDROData_Tool::ComputePointState( thePoint.XY(), anIt.Face() ) == TopAbs_IN ) { @@ -750,26 +1069,227 @@ TopoDS_Face HYDROData_LandCoverMap::FindByPoint( const gp_Pnt2d& thePoint, QStri return TopoDS_Face(); } +void Dump( const QString& theName, const QStringList& theList, QStringList& theLines ) +{ + theLines.append( QString( "%1 = QStringList()" ).arg( theName ) ); + foreach( QString anItem, theList ) + theLines.append( QString( "%1.append( u\"%2\" )" ).arg( theName ).arg( anItem ) ); +} + /** Dump to Python @param theTreatedObjects the map of treated objects */ -QStringList HYDROData_LandCoverMap::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const +QStringList HYDROData_LandCoverMap::DumpToPython( const QString& thePyScriptPath, + MapOfTreatedObjects& theTreatedObjects ) const { QStringList aResList = dumpObjectCreation( theTreatedObjects ); QString aName = GetObjPyName(); - //Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis(); - //setPythonReferenceObject( theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" ); + QString aShpFileName = thePyScriptPath; + aShpFileName.replace( ".py", ".shp" ); + QString aDbfFileName = thePyScriptPath; + aDbfFileName.replace( ".py", ".dbf" ); + + ExportSHP( aShpFileName, true, 0.1 ); + + QString anAttr = "CODE_06"; //TODO: some custom choice + QStringList anAttrValues, aTypes; + HYDROData_Document::Document( myLab )->CollectQGISValues( anAttr, anAttrValues, aTypes ); + ExportDBF( aDbfFileName, anAttr, anAttrValues, aTypes ); - //HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles(); - //for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; ++i ) - //{ - //const Handle(HYDROData_Entity) aProfile = aSeqOfProfiles.Value( i ); - //setPythonReferenceObject( theTreatedObjects, aResList, aProfile, "AddProfile" ); - //} + aResList << QString( "%1.ImportSHP( '%2' )" ). + arg( aName ).arg( QFileInfo( aShpFileName ).fileName() ); - //TODO + Dump( "attr_values", anAttrValues, aResList ); + Dump( "types", aTypes, aResList ); + aResList << QString( "%1.ImportDBF( '%2', '%3', attr_values, types )" ). + arg( aName ).arg( QFileInfo( aDbfFileName ).fileName() ).arg( anAttr ); return aResList; } + +void HYDROData_LandCoverMap::RemoveInternal(TopoDS_Shape& ShToRebuild, NCollection_IndexedDataMap* aF2FReplace) +{ + //DEBTRACE("RemoveInternal"); + //Shape must be topologically correct + TopExp_Explorer anExpF(ShToRebuild, TopAbs_FACE); + // + for(; anExpF.More(); anExpF.Next() ) + { + TopoDS_Face CurFace = TopoDS::Face(anExpF.Current()); + // + TopExp_Explorer anExp(CurFace, TopAbs_EDGE); + TopTools_ListOfShape anEdgesToRemove; + // + for(; anExp.More(); anExp.Next() ) + { + TopoDS_Edge CurEdge = TopoDS::Edge(anExp.Current()); + if (CurEdge.Orientation() == TopAbs_INTERNAL) + anEdgesToRemove.Append(CurEdge); + } + // + if (!anEdgesToRemove.IsEmpty()) + { + Handle_ShapeBuild_ReShape aReshape = new ShapeBuild_ReShape(); + TopoDS_Shape OutF = aReshape->Apply(CurFace); + TopTools_ListIteratorOfListOfShape aIt(anEdgesToRemove); + for (; aIt.More(); aIt.Next()) + aReshape->Remove(aIt.Value()); + OutF = aReshape->Apply(CurFace); + + Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; + sfs->Init(OutF); + sfs->Perform(); + OutF = sfs->Shape(); + aF2FReplace->Add(CurFace, TopoDS::Face(OutF)); + } + } + // + Handle_ShapeBuild_ReShape anExtReshape = new ShapeBuild_ReShape(); + for (int i = 1; i <= aF2FReplace->Extent(); i++) + { + TopoDS_Face aFK = aF2FReplace->FindKey(i); + TopoDS_Face aFV = aF2FReplace->FindFromIndex(i); + anExtReshape->Replace(aFK, aFV); + ShToRebuild = anExtReshape->Apply(ShToRebuild); + } +// for (int i = 1; i <= aF2FReplace->Extent(); i++) +// { +// DEBTRACE("aF2FReplace key,value " << aF2FReplace->FindKey(i) << " " << aF2FReplace->FindFromIndex(i)); +// } + +} + +void HYDROData_LandCoverMap::SetTransparency( double theTransparency ) +{ + SetDouble( DataTag_Transparency, theTransparency ); +} + +double HYDROData_LandCoverMap::GetTransparency() const +{ + return GetDouble( DataTag_Transparency, 0.5 ); +} + +bool HYDROData_LandCoverMap::ImportSHP( const QString& theSHPFileName, + const QList& theIndices ) +{ + HYDROData_ShapeFile anImporter; + QStringList aPolyList; + TopTools_SequenceOfShape aFaces; + int aSHapeType = -1; + int Stat = anImporter.ImportPolygons(HYDROData_Document::Document(1), theSHPFileName, aPolyList, aFaces, aSHapeType); + // + if (Stat != 1) + return false; + // + HYDROData_MapOfFaceToStricklerType aMapFace2ST; + int maxInd = *std::max_element(theIndices.begin(), theIndices.end()); + if (maxInd > aPolyList.length()) + return false; + // + if (theIndices.empty()) + { + //import all shapes + for ( int i = 1; i <=aFaces.Length(); i++ ) + { + TopoDS_Shape aShape = aFaces(i); + if ( aShape.IsNull() ) + continue; + aMapFace2ST.Add( TopoDS::Face( aShape ), "" ); + } + } + else + { + //import given indices + foreach ( int Ind, theIndices ) + { + TopoDS_Shape aShape = aFaces(Ind + 1); + if ( aShape.IsNull() ) + continue; + aMapFace2ST.Add( TopoDS::Face( aShape ), "" ); + } + } + // + StoreLandCovers(aMapFace2ST); + return true; +} + +bool HYDROData_LandCoverMap::ExportSHP( const QString& theSHPFileName, bool bUseDiscr, double theDefl) const +{ + HYDROData_ShapeFile anExporter; + QStringList aList; + anExporter.Export(HYDROData_Document::Document(1), theSHPFileName, this, aList, bUseDiscr, theDefl ); + if (aList.empty()) + return true; + else + return false; +} + +bool HYDROData_LandCoverMap::CheckLinear() +{ + TopoDS_Shape InpShape = GetShape(); + TopExp_Explorer anEdgeEx(InpShape, TopAbs_EDGE); + for (; anEdgeEx.More(); anEdgeEx.Next()) + { + TopoDS_Edge E = TopoDS::Edge(anEdgeEx.Current()); + double aFP, aLP; + Handle_Geom_Curve aCur = BRep_Tool::Curve(E, aFP, aLP); + Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aCur); + if (aLine.IsNull()) + { + Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur); + if (!aTC.IsNull()) + { + Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aTC->BasisCurve()); + if (aLine.IsNull()) + return false; + } + else + return false; + } + } + return true; +} + +void HYDROData_LandCoverMap::UpdateLocalCS( double theDx, double theDy ) +{ + TopoDS_Shape aShape = GetShape(); + TopoDS_Shape aLocatedShape = HYDROData_ShapesTool::Translated( aShape, theDx, theDy, 0 ); + SetShape( aLocatedShape ); +} + +void HYDROData_LandCoverMap::ClassifyPoints( const std::vector& thePoints, std::vector >& theTypes ) const +{ + HYDROData_LCM_FaceClassifier FC(this); + FC.Classify(thePoints, theTypes, NULL); +} + +void HYDROData_LandCoverMap::ClassifyPoints( const std::vector& thePoints, + Handle(HYDROData_StricklerTable) theTable, + std::vector& theCoeffs, double DefValue, bool UseMax ) const +{ + std::vector > Types; + HYDROData_LCM_FaceClassifier FC(this); + FC.Classify(thePoints, Types, NULL); + theCoeffs.resize(thePoints.size()); + for (size_t i = 0; i < Types.size(); i++) + { + const std::set& SStr = Types[i]; + if (SStr.empty()) + theCoeffs[i] = DefValue; + else + { + std::set::const_iterator it; + std::vector C1(SStr.size()); + for (it = SStr.begin(); it != SStr.end(); ++it) + C1.push_back(theTable->Get( *it, DefValue )); + double Val; + if (UseMax) + Val = *(std::max_element( C1.begin(), C1.end() ) ); + else + Val = *(std::min_element( C1.begin(), C1.end() ) ); + theCoeffs[i] = Val; + } + } +}