X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FHYDROData%2FHYDROData_Region.cxx;h=0f47ed2a50be6d5535d179b5b4b8d11344d0b180;hb=58bb6b7459bebeeb089c9ed486c4683a8bae7288;hp=090171f9e8b09619801de27ad7976baa15c1c306;hpb=aa24041c7f0529a27ebde5b1d5c0c201c5581c54;p=modules%2Fhydro.git diff --git a/src/HYDROData/HYDROData_Region.cxx b/src/HYDROData/HYDROData_Region.cxx index 090171f9..0f47ed2a 100644 --- a/src/HYDROData/HYDROData_Region.cxx +++ b/src/HYDROData/HYDROData_Region.cxx @@ -1,33 +1,63 @@ +// Copyright (C) 2014-2015 EDF-R&D +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// #include "HYDROData_Region.h" #include "HYDROData_CalculationCase.h" #include "HYDROData_Document.h" #include "HYDROData_Iterator.h" +#include "HYDROData_Object.h" +#include "HYDROData_ShapesTool.h" #include "HYDROData_Zone.h" +#include "HYDROData_Tool.h" #include #include #include #include + +#include + #include +#include #include #include -#include + + #include #include + #include #include +#include -#define PYTHON_REGION_ID "KIND_REGION" +#include "Geom_Plane.hxx" +#include "gp_Pln.hxx" +#include "BRepTools_ReShape.hxx" + +//#define DEB_GET_REGION_SHAPE -IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity) IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity) HYDROData_Region::HYDROData_Region() - : HYDROData_Entity() + : HYDROData_Entity( Geom_2d ) { } @@ -35,35 +65,9 @@ HYDROData_Region::~HYDROData_Region() { } -QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const +bool HYDROData_Region::CanBeUpdated() const { - QStringList aResList; - - Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab ); - if ( aDocument.IsNull() ) - return aResList; - - QString aDocName = aDocument->GetDocPyName(); - QString aRegionName = GetName(); - - aResList << QString( "%1 = %2.CreateObject( %3 );" ) - .arg( aRegionName ).arg( aDocName ).arg( PYTHON_REGION_ID ); - aResList << QString( "%1.SetName( \"%2\" );" ) - .arg( aRegionName ).arg( aRegionName ); - aResList << QString( "" ); - - HYDROData_SequenceOfObjects aZones = GetZones(); - HYDROData_SequenceOfObjects::Iterator anIter( aZones ); - for ( ; anIter.More(); anIter.Next() ) - { - Handle(HYDROData_Zone) aRefZone = - Handle(HYDROData_Zone)::DownCast( anIter.Value() ); - if ( !aRefZone.IsNull() ) - setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" ); - } - aResList << QString( "" ); - - return aResList; + return false; } void HYDROData_Region::Remove() @@ -77,8 +81,25 @@ void HYDROData_Region::Remove() aFatherCalc->UpdateRegionsOrder(); } +bool HYDROData_Region::CanRemove() +{ + return false; +} + +HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const +{ + HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects(); + + HYDROData_SequenceOfObjects aSeqOfZones = GetZones(); + aResSeq.Append( aSeqOfZones ); + + return aResSeq; +} + bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone ) { + Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab ); + if ( theZone.IsNull() ) return false; @@ -90,8 +111,11 @@ bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone ) Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() ); if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab ) { - Handle(HYDROData_Zone) aNewZone = addNewZone(); - theZone->CopyTo( aNewZone ); + Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() ); + theZone->CopyTo( aNewZone, false ); + + // To prevent changing of stored shape + aNewZone->SetShape( theZone->GetShape() ); aFatherRegion->RemoveZone( theZone ); @@ -135,7 +159,10 @@ void HYDROData_Region::RemoveZones() myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true ); } -Handle(HYDROData_Zone) HYDROData_Region::addNewZone() +Handle(HYDROData_Zone) HYDROData_Region::addNewZone( const Handle(HYDROData_Document)& theDoc, + const QString& thePrefix, + const TopoDS_Face& theFace, + const QStringList& theRefObjects ) { TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild(); @@ -143,11 +170,92 @@ Handle(HYDROData_Zone) HYDROData_Region::addNewZone() Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) ); AddZone( aNewZone ); + QString aZoneName = HYDROData_Tool::GenerateObjectName( theDoc, thePrefix ); + aNewZone->SetName( aZoneName ); + + aNewZone->SetShape( theFace ); + + // Add the reference object for zone + for ( int i = 0, n = theRefObjects.length(); i < n; ++i ) + { + const QString& anObjName = theRefObjects.at( i ); + Handle(HYDROData_Entity) aRefObject = theDoc->FindObjectByName( anObjName ); + if ( aRefObject.IsNull() ) + continue; + + aNewZone->AddObject( aRefObject ); + } + return aNewZone; } -TopoDS_Shape HYDROData_Region::GetShape() const +void getUsedGroups( const TopoDS_Shape& theShape, + HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups, + HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups ) +{ +#ifdef DEB_GET_REGION_SHAPE + HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE ); +#endif + + TopTools_IndexedMapOfShape aMapOfSubShapes; + TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes ); + + HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups ); + for ( ; anIter.More(); anIter.Next() ) + { + HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue(); + if ( anOriGroupDef.Shapes.IsEmpty() ) + continue; + + for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i ) + { + TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i ); + + int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge ); + if ( aShapeIndex <= 0 ) + continue; + + anOriGroupDef.Shapes.Remove( i ); + --i; + + bool anIsAdded = false; + + HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups ); + for ( ; aUsedIter.More(); aUsedIter.Next() ) + { + HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue(); + if ( aUsedGroupDef.Name != anOriGroupDef.Name ) + continue; + + aUsedGroupDef.Shapes.Append( aGroupEdge ); + anIsAdded = true; + break; + } + + if ( !anIsAdded ) + { + HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef; + aUsedGroupDef.Name = anOriGroupDef.Name; + aUsedGroupDef.Shapes.Append( aGroupEdge ); + theUsedGroups.Append( aUsedGroupDef ); + } + } + } +} + + + +TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups, const TopTools_SequenceOfShape* IntSh ) const { + HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups; + HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups; + if ( theSeqOfGroups ) + aSeqOfGroups = *theSeqOfGroups; + +#ifdef DEB_GET_REGION_SHAPE + HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups ); +#endif + TopoDS_Shape aResShape; // Unite the region zones (each zone is a face) into one face (united face) @@ -158,74 +266,253 @@ TopoDS_Shape HYDROData_Region::GetShape() const HYDROData_SequenceOfObjects aZones = GetZones(); HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones ); - for ( ; aZoneIter.More(); aZoneIter.Next() ) { + TopTools_IndexedMapOfShape AllE; + TopTools_IndexedMapOfShape IE; //int edges + + for ( ; aZoneIter.More(); aZoneIter.Next() ) + { Handle(HYDROData_Zone) aZone = Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() ); - - if ( aZone.IsNull() ) { + if ( aZone.IsNull() ) continue; - } - TopoDS_Face aFace = TopoDS::Face( aZone->GetShape() ); - if ( !aFace.IsNull() ) { - aRegionFacesList.Append( aFace ); - } + TopoDS_Shape aZoneShape = aZone->GetShape(); + if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE ) + continue; + + TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape ); + aRegionFacesList.Append( aZoneFace ); + TopExp::MapShapes(aZoneFace, TopAbs_EDGE, AllE); // collect all edges + getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups ); } // zones iterator + + for (int i = 1; i <= IntSh->Length(); i++) + { + const TopoDS_Shape& CS = (*IntSh)(i); + if (AllE.Contains(CS)) + IE.Add(CS); + } - // Check number of faces - int aNbFaces = aRegionFacesList.Extent(); - if ( aNbFaces > 0 ) { - // The unite region face - TopoDS_Face aRegionFace; - - if ( aNbFaces == 1 ) { - aRegionFace = TopoDS::Face( aRegionFacesList.First() ); - } else { - // Fuse faces into one - TopoDS_Shape aFuseShape; - TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList ); - for ( ; aFaceIter.More(); aFaceIter.Next() ) { - if ( aFuseShape.IsNull() ) { - aFuseShape = aFaceIter.Value(); - } else { - BRepAlgoAPI_Fuse aFuse(aFuseShape, aFaceIter.Value()); - if ( !aFuse.IsDone() ) { - aFuseShape.Nullify(); - break; - } - aFuseShape = aFuse.Shape(); + if ( aRegionFacesList.IsEmpty() ) + return aResShape; + + TopoDS_Face aRegionFace; + + if ( aRegionFacesList.Extent() == 1 ) + { + aResShape = TopoDS::Face( aRegionFacesList.First() ); + } + else + { +#ifdef DEB_GET_REGION_SHAPE + HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups ); +#endif + + // Try to fuse all region faces into one common face + TopoDS_Shape aFuseShape; + TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList ); + for ( ; aFaceIter.More(); aFaceIter.Next() ) + { + if ( aFuseShape.IsNull() ) + { + aFuseShape = aFaceIter.Value(); + continue; + } + + BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() ); + if ( !aFuse.IsDone() ) + { + aFuseShape.Nullify(); + break; + } + + aFuseShape = aFuse.Shape(); + + //update history of internal edges + TopTools_IndexedMapOfShape DIE; + TopTools_ListOfShape newSh1, newSh2; + for (int i = 1; i <= IE.Extent(); i++) + { + const TopoDS_Shape& CSH = IE(i); + newSh1.Clear(); + newSh2.Clear(); + newSh1 = aFuse.Modified(CSH); + if (newSh1.IsEmpty()) + { + newSh2 = aFuse.Generated(CSH); + if (newSh2.IsEmpty()) + DIE.Add(CSH); + else + for (TopTools_ListIteratorOfListOfShape lt(newSh2); lt.More(); lt.Next()) + if (!lt.Value().IsNull()) + DIE.Add(lt.Value()); } - } // faces iterator - - // Check the result of fuse operation - if ( !aFuseShape.IsNull() ) { - ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape ); - anUnifier.Build(); - TopoDS_Shape anUnitedShape = anUnifier.Shape(); - - TopTools_IndexedMapOfShape aMapOfFaces; - TopExp::MapShapes( anUnitedShape, TopAbs_FACE, aMapOfFaces ); - if ( aMapOfFaces.Extent() == 1 ) { - aRegionFace = TopoDS::Face( aMapOfFaces(1) ); + else + { + for (TopTools_ListIteratorOfListOfShape lt(newSh1); lt.More(); lt.Next()) + if (!lt.Value().IsNull()) + DIE.Add(lt.Value()); } } + IE = DIE; + //update groups + HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse ); + } // faces iterator + +#ifdef DEB_GET_REGION_SHAPE + HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE ); +#endif + + BRep_Builder BB; + TopoDS_Face DF; + if (!IE.IsEmpty()) + { + //add dummy face to existing shell + //this face contains all internal edges + //USD algo will skip such edges and will not perform unifying through them + //(more than 2 faces are connected to one edge + non same domain surfaces) + TopoDS_Wire DW; + Handle_Geom_Plane DPl = new Geom_Plane(gp_Pln (gp_Pnt(0,0,0), gp_Dir(0,1,0))); //non same domain with the main surf + BB.MakeFace(DF, DPl, Precision::Confusion()); + BB.MakeWire(DW); + for (int i = 1; i <= IE.Extent(); i++) + BB.Add(DW, IE(i)); + BB.Add(DF, DW); + BB.Add(aFuseShape, DF); } - if ( !aRegionFace.IsNull() ) { // result shape is a face - aResShape = aRegionFace; - } else { // result shape is a shell - TopoDS_Shell aShell; - BRep_Builder aBuilder; - aBuilder.MakeShell( aShell ); + ShapeUpgrade_UnifySameDomain unif( aFuseShape ); + unif.Build(); + TopoDS_Shape anUnitedShape; + const TopoDS_Shape& out = unif.Shape(); + + HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &unif ); + + if (!IE.IsEmpty()) + { + //remove dummy face from shell; shell becomes valid + const TopoDS_Shape& NDF = unif.Generated(DF); + BRepTools_ReShape ReShaper; + ReShaper.Remove(NDF); + anUnitedShape = ReShaper.Apply(out); + HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &ReShaper ); + } + else + anUnitedShape = out; + + TopTools_SequenceOfShape aShapeFaces; + HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces ); + if ( aShapeFaces.Length() == 1 ) //it should be either face or compound of faces (?) + { + const TopoDS_Face& CF = TopoDS::Face( aShapeFaces.Value( 1 )); + aResShape = CF; + } + else + { + TopTools_SequenceOfShape aShapeShells; + HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_SHELL, aShapeShells ); + if (aShapeShells.Length() == 1) + aResShape = TopoDS::Shell(aShapeShells(1)); + else + aResShape = anUnitedShape; + } - TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList ); - for ( ; aFaceIter.More(); aFaceIter.Next() ) { - aBuilder.Add( aShell, aFaceIter.Value() ); + // Update the sequence of groups + if ( theSeqOfGroups ) + { + HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups ); + for ( ; aUsedIter.More(); aUsedIter.Next() ) + { + const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value(); + if ( aUsedGroupDef.Shapes.IsEmpty() ) + continue; + + HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups ); + for ( ; anOriIter.More(); anOriIter.Next() ) + { + HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue(); + if ( anOriGroupDef.Name != aUsedGroupDef.Name ) + continue; + + HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes ); + break; + } } - aResShape = aShell; + *theSeqOfGroups = aSeqOfGroups; } } - + return aResShape; } + +QStringList HYDROData_Region::DumpToPython( const QString& thePyScriptPath, + MapOfTreatedObjects& theTreatedObjects, + QString defRegName ) const +{ + QStringList aResList; + + // Find region + findPythonReferenceObject( aResList, defRegName ); + + // Add zones + HYDROData_SequenceOfObjects aZones = GetZones(); + HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones ); + for ( ; aZonesIter.More(); aZonesIter.Next() ) { + Handle(HYDROData_Zone) aZone = + Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() ); + if ( aZone.IsNull() ) { + continue; + } + + // find zone + aZone->findPythonReferenceObject( aResList ); + theTreatedObjects.insert( aZone->GetName(), aZone ); + + // set zone merge type + QString aMergeTypeStr; + HYDROData_Zone::MergeType aMergeType = aZone->GetMergeType(); + if ( aMergeType == HYDROData_Zone::Merge_ZMIN ) { + aMergeTypeStr = "HYDROData_Zone.Merge_ZMIN"; + } else if ( aMergeType == HYDROData_Zone::Merge_ZMAX ) { + aMergeTypeStr = "HYDROData_Zone.Merge_ZMAX"; + } else if ( aMergeType == HYDROData_Zone::Merge_Object ) { + aMergeTypeStr = "HYDROData_Zone.Merge_Object"; + } + + if ( !aMergeTypeStr.isEmpty() ) { + aResList << QString( "%1.SetMergeType( %2 )" ).arg( aZone->GetObjPyName() ).arg( aMergeTypeStr ); + } + if ( aMergeType == HYDROData_Zone::Merge_Object ) { + Handle(HYDROData_Entity) aMergeObject = aZone->GetMergeObject(); + if ( !aMergeObject.IsNull() ) { + aMergeObject->findPythonReferenceObject( aResList ); + aResList << QString( "%1.SetMergeObject( %2 )" ).arg( aZone->GetObjPyName() ) + .arg( aMergeObject->GetObjPyName() ); + } + } + // set color + QColor zoneColor = aZone->GetColor(Qt::darkBlue); + aResList << QString( "%1.SetColor( QColor( %2, %3, %4 ))" ) + .arg( aZone->GetObjPyName() ).arg( zoneColor.red() ).arg( zoneColor.green() ).arg( zoneColor.blue() ); + // add zone + setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aZone, "AddZone" ); + + } + + return aResList; +} + +bool HYDROData_Region::IsSubmersible() const +{ + HYDROData_SequenceOfObjects aZones = GetZones(); + HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones ); + for ( ; aZonesIter.More(); aZonesIter.Next() ) + { + Handle(HYDROData_Zone) aZone = + Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() ); + if ( !aZone->IsSubmersible() ) + return false; //if one of zones is not submersible the region is considered as not submersible + } + return true; +}