X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_LandCoverMap.cxx;h=969ce6d077423bc7f159fe8fedc31d29dfa19c82;hb=670039d7a5d25b1da51956b668f212756d31a86e;hp=449c443e57a404c5e0db173570de386dc22f87ef;hpb=40025264ffe3c9de3de7b8f20da4cc73b1ad3f14;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_LandCoverMap.cxx b/src/HYDROData/HYDROData_LandCoverMap.cxx index 449c443e..969ce6d0 100644 --- a/src/HYDROData/HYDROData_LandCoverMap.cxx +++ b/src/HYDROData/HYDROData_LandCoverMap.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -40,10 +39,18 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include + #include #include @@ -56,24 +63,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 +87,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 +108,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 +129,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 +150,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 +162,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 +174,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 +206,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 /// @@ -208,10 +232,12 @@ HYDROData_LandCoverMap::DBFStatus HYDROData_LandCoverMap::ImportDBF( const QStri const QString& theFieldName, const QStringList& theDBFValues, const QStringList& theStricklerTypes, - QMap theIndices ) + const QList& theIndices ) { + if (theDBFValues.size() != theStricklerTypes.size()) + return DBFStatus_DIFF_SIZE_ERROR; HYDROData_ShapeFile aDBFImporter; - if (aDBFImporter.DBF_OpenDBF(theDBFFileName)) + if (!aDBFImporter.DBF_OpenDBF(theDBFFileName)) return DBFStatus_OPEN_FILE_ERROR; //cant open file QStringList FieldList = aDBFImporter.DBF_GetFieldList(); @@ -223,14 +249,14 @@ 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)); if ( StricklerTypesInd != -1) - anIt.SetStricklerType(theDBFValues[StricklerTypesInd]); + anIt.SetStricklerType(theStricklerTypes[StricklerTypesInd]); else allOK = false; } @@ -249,9 +275,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(); @@ -267,8 +295,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); } @@ -420,6 +448,15 @@ bool HYDROData_LandCoverMap::Add( const Handle( HYDROData_Object )& theObject, c return LocalPartition( aFace, theType ); } +bool HYDROData_LandCoverMap::Add( const TopoDS_Wire& theWire, const QString& theType ) +{ + if( !theWire.Closed() ) + return false; + + TopoDS_Face aFace = BRepBuilderAPI_MakeFace( theWire, Standard_True ).Face(); + return LocalPartition( aFace, theType ); +} + /** Add a new polyline as land cover @param thePolyline the polyline to add as land cover @@ -432,15 +469,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; } /** @@ -471,11 +515,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; } @@ -491,9 +538,21 @@ 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 ) +{ + return LocalPartition( theShape, "" ); } + /** Merge the given faces in the land cover @param theFaces the faces to merge in the land cover map @@ -504,7 +563,7 @@ bool HYDROData_LandCoverMap::Merge( const TopTools_ListOfShape& theFaces, const { // 1. to fuse the faces into the new face TopoDS_Shape aMergedFace = MergeFaces( theFaces, true ); - if( aMergedFace.ShapeType()==TopAbs_FACE ) + if( !aMergedFace.IsNull() && aMergedFace.ShapeType()==TopAbs_FACE ) { // 2. to remove the merged faces from the current map Remove( theFaces ); @@ -515,6 +574,13 @@ bool HYDROData_LandCoverMap::Merge( const TopTools_ListOfShape& theFaces, const return false; } +/** + 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 ) { @@ -523,7 +589,11 @@ TopoDS_Shape HYDROData_LandCoverMap::MergeFaces( const TopTools_ListOfShape& the BOPCol_ListOfShape aLC; anIt.Initialize(theFaces); for( ; anIt.More(); anIt.Next() ) + { + if (anIt.Value().ShapeType() != TopAbs_FACE) + return TopoDS_Shape(); aLC.Append( anIt.Value() ); + } BOPAlgo_PaveFiller aPF; aPF.SetArguments( aLC ); @@ -576,17 +646,58 @@ 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 */ @@ -595,6 +706,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 @@ -620,7 +751,7 @@ 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 ); @@ -652,16 +783,18 @@ 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() ); + int aKey = (int)(uintptr_t)aMIt.Value().TShape().operator->(); + aShapesFromNewFace.Add( aKey ); } // b. to fill map of parts except parts from new face @@ -669,14 +802,18 @@ 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; + //std::cout << "from " << anIt.Face() << ": " << anIt.StricklerType() << std::endl; TopTools_ListOfShape aModified = aBuilder.Modified( anIt.Face() ); + if( aModified.Extent() == 0 ) + aModified.Append( 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 ); @@ -698,23 +835,40 @@ bool HYDROData_LandCoverMap::LocalPartition( const TopoDS_Shape& theNewShape, co */ void HYDROData_LandCoverMap::StoreLandCovers( const HYDROData_MapOfFaceToStricklerType& theMap ) { - TopoDS_Compound aCompound; - BRep_Builder aCompoundBuilder; - aCompoundBuilder.MakeCompound( aCompound ); + 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++ ) { TopoDS_Face aFace = aNFIt.Key(); + if( aFace.IsNull() ) + continue; QString aType = aNFIt.Value(); - aCompoundBuilder.Add( aCompound, aFace ); + aListOfFaces.Append(aFace); aTypes->SetValue( i, HYDROData_Tool::toExtString( aType ) ); } - SetShape( aCompound ); + TopoDS_Shape aResult; + if( aListOfFaces.Extent() == 1 ) + { + /*TopoDS_Shell aShell; + BRep_Builder aShellBuilder; + aShellBuilder.MakeShell( aShell ); + aShell.Closed( Standard_False ); + aShellBuilder.Add( aShell, aListOfFaces.First() );*/ + aResult = aListOfFaces.First(); //aShell; + } + else if( aListOfFaces.Extent() > 1 ) + aResult = MergeFaces( aListOfFaces, false ); + + //remove internal edges + aResult = RemoveInternal(aResult); + SetShape( aResult ); } /** @@ -726,7 +880,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 ) { @@ -737,3 +891,54 @@ TopoDS_Face HYDROData_LandCoverMap::FindByPoint( const gp_Pnt2d& thePoint, QStri theType = ""; return TopoDS_Face(); } + +/** + Dump to Python + @param theTreatedObjects the map of treated objects +*/ +QStringList HYDROData_LandCoverMap::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const +{ + QStringList aResList = dumpObjectCreation( theTreatedObjects ); + QString aName = GetObjPyName(); + + //Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis(); + //setPythonReferenceObject( theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" ); + + //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" ); + //} + + //TODO + + return aResList; +} + +TopoDS_Shape HYDROData_LandCoverMap::RemoveInternal(const TopoDS_Shape& InSh) +{ + //Shape must be topologically correct + TopExp_Explorer anExp(InSh, 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); + } + + Handle_ShapeBuild_ReShape aReshape = new ShapeBuild_ReShape(); + TopoDS_Shape OutSh = aReshape->Apply(InSh); + TopTools_ListIteratorOfListOfShape aIt(anEdgesToRemove); + for (; aIt.More(); aIt.Next()) + aReshape->Remove(aIt.Value()); + OutSh = aReshape->Apply(InSh); + + Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape; + sfs->Init(OutSh); + sfs->Perform(); + return sfs->Shape(); + +}