+ 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)
+ // If the zones can't be united into the single face - unite them into shell
+
+ // Collect the list of region faces
+ TopTools_ListOfShape aRegionFacesList;
+
+ HYDROData_SequenceOfObjects aZones = GetZones();
+ HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
+ 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() )
+ continue;
+
+ 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);
+ }
+
+ 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());
+ }
+ 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
+
+ aFuseShape = HYDROData_Tool::RebuildCmp(aFuseShape);
+
+ 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);
+ }
+
+ ShapeUpgrade_UnifySameDomain unif( aFuseShape, Standard_False, Standard_True, Standard_False );
+ 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;
+ }
+
+ // 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;
+ }
+ }
+
+ *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;
+}