From e989e0f3cdd230307b28ed0128a49978b27096ef Mon Sep 17 00:00:00 2001 From: asl Date: Mon, 29 Sep 2014 11:36:26 +0000 Subject: [PATCH] parametrization --- src/HYDROData/CMakeLists.txt | 2 + src/HYDROData/HYDROData_CalculationCase.cxx | 215 +++++++++++++------- src/HYDROData/HYDROData_CalculationCase.h | 38 +++- src/HYDROData/HYDROData_PriorityQueue.cxx | 182 +++++++++++++++++ src/HYDROData/HYDROData_PriorityQueue.h | 58 ++++++ src/HYDROData/HYDROData_Region.cxx | 28 ++- src/HYDROData/HYDROData_Region.h | 9 +- src/HYDROPy/HYDROData_CalculationCase.sip | 29 +++ 8 files changed, 475 insertions(+), 86 deletions(-) create mode 100644 src/HYDROData/HYDROData_PriorityQueue.cxx create mode 100644 src/HYDROData/HYDROData_PriorityQueue.h diff --git a/src/HYDROData/CMakeLists.txt b/src/HYDROData/CMakeLists.txt index e50e8589..ba36b327 100644 --- a/src/HYDROData/CMakeLists.txt +++ b/src/HYDROData/CMakeLists.txt @@ -29,6 +29,7 @@ set(PROJECT_HEADERS HYDROData_Pipes.h HYDROData_PolylineXY.h HYDROData_Polyline3D.h + HYDROData_PriorityQueue.h HYDROData_Profile.h HYDROData_ProfileUZ.h HYDROData_Projection.h @@ -74,6 +75,7 @@ set(PROJECT_SOURCES HYDROData_Pipes.cxx HYDROData_PolylineXY.cxx HYDROData_Polyline3D.cxx + HYDROData_PriorityQueue.cxx HYDROData_Profile.cxx HYDROData_ProfileUZ.cxx HYDROData_Projection.cxx diff --git a/src/HYDROData/HYDROData_CalculationCase.cxx b/src/HYDROData/HYDROData_CalculationCase.cxx index 509c2c5f..d878012a 100644 --- a/src/HYDROData/HYDROData_CalculationCase.cxx +++ b/src/HYDROData/HYDROData_CalculationCase.cxx @@ -8,11 +8,9 @@ #include "HYDROData_Iterator.h" #include "HYDROData_NaturalObject.h" #include "HYDROData_PolylineXY.h" -#include "HYDROData_SplitToZonesTool.h" #include "HYDROData_SplittedShapesGroup.h" #include "HYDROData_Region.h" #include "HYDROData_Tool.h" -#include "HYDROData_Zone.h" #include @@ -217,84 +215,132 @@ void HYDROData_CalculationCase::Update() HYDROData_SequenceOfObjects aGeomGroups = GetGeometryGroups(); - HYDROData_SplitToZonesTool::SplitDataList aSplitedObjects = + HYDROData_SplitToZonesTool::SplitDataList aSplitObjects = HYDROData_SplitToZonesTool::Split( aGeomObjects, aGeomGroups, aBoundaryPolyline ); - if ( aSplitedObjects.isEmpty() ) + if ( aSplitObjects.isEmpty() ) return; - QString aRegsPref = CALCULATION_REGIONS_PREF; - QString aZonesPref = CALCULATION_ZONES_PREF; + HYDROData_SplitToZonesTool::SplitDataList aZonesList, anEdgesList; - QMap aSplittedEdgesGroupsMap; + HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitObjects ); + while( anIter.hasNext() ) + { + const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next(); + if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone ) + aZonesList.append( aSplitData ); + else if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Edge ) + anEdgesList.append( aSplitData ); + } + + //CreateRegionsDef( aDocument, aZonesList ); + CreateRegionsAuto( aDocument, aZonesList ); + CreateEdgeGroupsDef( aDocument, anEdgesList ); +} +void HYDROData_CalculationCase::CreateRegionsDef( const Handle(HYDROData_Document)& theDoc, + const HYDROData_SplitToZonesTool::SplitDataList& theZones ) +{ // Create result regions for case, by default one zone for one region - HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedObjects ); + QString aRegsPref = CALCULATION_REGIONS_PREF; + QString aZonesPref = CALCULATION_ZONES_PREF; + + HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theZones ); while( anIter.hasNext() ) { const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next(); + // Create new region + Handle(HYDROData_Region) aRegion = addNewRegion( theDoc, aRegsPref ); - if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone ) - { - // Create new region - Handle(HYDROData_Region) aRegion = addNewRegion(); + // Add the zone for region + Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone( theDoc, aZonesPref, aSplitData.Face(), aSplitData.ObjectNames ); + } +} - QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref ); - aRegion->SetName( aRegionName ); +void HYDROData_CalculationCase::CreateRegionsAuto( const Handle(HYDROData_Document)& theDoc, + const HYDROData_SplitToZonesTool::SplitDataList& theZones ) +{ + QMap aRegionsMap; //object name to region + QString aZonesPref = CALCULATION_ZONES_PREF; + HYDROData_PriorityQueue aPr( this ); - // Add the zone for region - Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone(); + // 1. First we create a default region for each object included into the calculation case + HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects(); + for( int i=aGeomObjects.Lower(), n=aGeomObjects.Upper(); i<=n; i++ ) + { + Handle(HYDROData_Object) anObj = Handle(HYDROData_Object)::DownCast( aGeomObjects.Value( i ) ); + if( anObj.IsNull() ) + continue; + QString anObjName = anObj->GetName(); + QString aRegName = anObjName + "_reg"; + Handle(HYDROData_Region) aRegion = addNewRegion( theDoc, aRegName, false ); + aRegionsMap.insert( anObjName, aRegion ); + } - QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref ); - aRegionZone->SetName( aZoneName ); + // 2. Now for each zone it is necessary to determine the most priority object + // and assign to zone to corresponding region + HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theZones ); + while( anIter.hasNext() ) + { + const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next(); + HYDROData_Zone::MergeAltitudesType aMergeType; + Handle(HYDROData_Object) aRegObj = aPr.GetMostPriorityObject( aSplitData.ObjectNames, aMergeType ); + if( aRegObj.IsNull() ) + continue; + Handle(HYDROData_Region) aRegion = aRegionsMap[aRegObj->GetName()]; + if( aRegion.IsNull() ) + continue; + Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone( theDoc, aZonesPref, aSplitData.Face(), aSplitData.ObjectNames ); + switch( aMergeType ) + { + case HYDROData_Zone::Merge_ZMIN: + case HYDROData_Zone::Merge_ZMAX: + aRegionZone->SetMergeType( aMergeType ); + break; + case HYDROData_Zone::Merge_Object: + aRegionZone->SetMergeType( aMergeType ); + aRegionZone->RemoveMergeAltitude(); + aRegionZone->SetMergeAltitude( aRegObj->GetAltitudeObject() ); + break; + } + } - aRegionZone->SetShape( aSplitData.Face() ); + //TODO: inform if some regions remain empty +} - // Add the reference object for zone - for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i ) - { - const QString& anObjName = aSplitData.ObjectNames.at( i ); - - Handle(HYDROData_Object) aRefObject = - Handle(HYDROData_Object)::DownCast( aDocument->FindObjectByName( anObjName ) ); - if ( aRefObject.IsNull() ) - continue; +void HYDROData_CalculationCase::CreateEdgeGroupsDef( const Handle(HYDROData_Document)& theDoc, + const HYDROData_SplitToZonesTool::SplitDataList& theEdges ) +{ + QMap aSplittedEdgesGroupsMap; - aRegionZone->AddGeometryObject( aRefObject ); - } - } - else if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Edge ) - { - // Create new edges group - if ( aSplitData.ObjectNames.isEmpty() || aSplitData.Shape.IsNull() ) - continue; + HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theEdges ); + while( anIter.hasNext() ) + { + const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next(); + // Create new edges group + if ( aSplitData.ObjectNames.isEmpty() || aSplitData.Shape.IsNull() ) + continue; - QString anObjName = aSplitData.ObjectNames.first(); - if ( anObjName.isEmpty() ) - continue; + QString anObjName = aSplitData.ObjectNames.first(); + if ( anObjName.isEmpty() ) + continue; #ifdef DEB_CALCULATION - QString aStr = aSplitData.ObjectNames.join(" "); + QString aStr = aSplitData.ObjectNames.join(" "); cout << " CCase: Names = "<Object1->GetName() + " "; + aRule += ( anIt->Priority == LESS ? "<" : ">" ) + QString( " " ); + aRule += anIt->Object2->GetName() + " "; + + switch( anIt->MergeType ) + { + case HYDROData_Zone::Merge_UNKNOWN: + aRule += "unknown"; + break; + case HYDROData_Zone::Merge_ZMIN: + aRule += "zmin"; + break; + case HYDROData_Zone::Merge_ZMAX: + aRule += "zmax"; + break; + case HYDROData_Zone::Merge_Object: + aRule += "object"; + break; + } + aDump += aRule + "\n"; + } + return aDump; +} diff --git a/src/HYDROData/HYDROData_PriorityQueue.h b/src/HYDROData/HYDROData_PriorityQueue.h new file mode 100644 index 00000000..314f455b --- /dev/null +++ b/src/HYDROData/HYDROData_PriorityQueue.h @@ -0,0 +1,58 @@ + +#ifndef HYDROData_PriorityQueue_HeaderFile +#define HYDROData_PriorityQueue_HeaderFile + +#include +#include +#include + +class HYDROData_CalculationCase; + +enum HYDROData_PriorityType +{ + LESS, + GREATER, +}; + +struct HYDROData_CustomRule +{ + Handle(HYDROData_Object) Object1; + HYDROData_PriorityType Priority; + Handle(HYDROData_Object) Object2; + HYDROData_Zone::MergeAltitudesType MergeType; +}; + +typedef QList HYDROData_ListOfRules; + +class HYDROData_PriorityQueue +{ +public: + HYDROData_PriorityQueue( HYDROData_CalculationCase* ); + ~HYDROData_PriorityQueue(); + + Handle_HYDROData_Object GetMostPriorityObject( const QStringList& theZoneObjects, + HYDROData_Zone::MergeAltitudesType& theMergeType ) const; + + bool IsMorePriority( const Handle(HYDROData_Object)& theObj1, + const Handle(HYDROData_Object)& theObj2, + HYDROData_Zone::MergeAltitudesType& theMergeType ) const; + + static void ClearRules( TDF_Label& theRulesLabel ); + static void AddRule( TDF_Label& theRulesLabel, + const Handle(HYDROData_Object)& theObject1, + HYDROData_PriorityType thePriority, + const Handle(HYDROData_Object)& theObject2, + HYDROData_Zone::MergeAltitudesType theMergeType ); + static HYDROData_ListOfRules GetRules( const TDF_Label& theRulesLabel ); + static QString DumpRules( const TDF_Label& theRulesLab ); + +private: + typedef QMap MapNameToObject; + + HYDROData_SequenceOfObjects myGeomObjects; ///< the ordered list of objects (default priority) + MapNameToObject myNames; ///< the map of name to object + HYDROData_ListOfRules myRules; ///< the list of rules +}; + +#endif + diff --git a/src/HYDROData/HYDROData_Region.cxx b/src/HYDROData/HYDROData_Region.cxx index ac6a4f75..aad021e7 100644 --- a/src/HYDROData/HYDROData_Region.cxx +++ b/src/HYDROData/HYDROData_Region.cxx @@ -4,8 +4,10 @@ #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 @@ -74,6 +76,8 @@ HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone ) { + Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab ); + if ( theZone.IsNull() ) return false; @@ -85,7 +89,7 @@ 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(); + Handle(HYDROData_Zone) aNewZone = addNewZone( aDocument, "", TopoDS_Face(), QStringList() ); theZone->CopyTo( aNewZone ); // To prevent changing of stored shape @@ -133,7 +137,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(); @@ -141,6 +148,23 @@ 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_Object) aRefObject = + Handle(HYDROData_Object)::DownCast( theDoc->FindObjectByName( anObjName ) ); + if ( aRefObject.IsNull() ) + continue; + + aNewZone->AddGeometryObject( aRefObject ); + } + return aNewZone; } diff --git a/src/HYDROData/HYDROData_Region.h b/src/HYDROData/HYDROData_Region.h index 3307b324..a0714da1 100644 --- a/src/HYDROData/HYDROData_Region.h +++ b/src/HYDROData/HYDROData_Region.h @@ -8,8 +8,10 @@ DEFINE_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity) class Handle(HYDROData_Zone); - +class Handle(HYDROData_Document); class TopoDS_Shape; +class TopoDS_Face; +class QStringList; /**\class HYDROData_Region * \brief Regions are groups (lists) of zones, they can include one or several zones. @@ -97,7 +99,10 @@ protected: * Create new one reference zone for region on child label. * The new zone is added into the list of reference zones. */ - HYDRODATA_EXPORT virtual Handle(HYDROData_Zone) addNewZone(); + HYDRODATA_EXPORT virtual Handle(HYDROData_Zone) addNewZone( const Handle(HYDROData_Document)& theDoc, + const QString& thePrefix, + const TopoDS_Face& theFace, + const QStringList& theRefObjects ); protected: diff --git a/src/HYDROPy/HYDROData_CalculationCase.sip b/src/HYDROPy/HYDROData_CalculationCase.sip index 48a257f9..5b7c7f2c 100644 --- a/src/HYDROPy/HYDROData_CalculationCase.sip +++ b/src/HYDROPy/HYDROData_CalculationCase.sip @@ -22,8 +22,15 @@ %ExportedHeaderCode #include +#include %End +enum HYDROData_PriorityType +{ + LESS, + GREATER, +}; + class HYDROData_CalculationCase : public HYDROData_Entity { @@ -472,6 +479,28 @@ public: Py_END_ALLOW_THREADS %End + + void ClearRules(); + + void AddRule( HYDROData_Object theObject1, + HYDROData_PriorityType thePriority, + HYDROData_Object theObject2, + HYDROData_Zone::MergeAltitudesType theMergeType ) + [void ( const Handle_HYDROData_Object&, HYDROData_PriorityType, const Handle_HYDROData_Object&, HYDROData_Zone::MergeAltitudesType )]; + %MethodCode + Handle(HYDROData_Object) anObject1 = + Handle(HYDROData_Object)::DownCast( createHandle( a0 ) ); + Handle(HYDROData_Object) anObject2 = + Handle(HYDROData_Object)::DownCast( createHandle( a2 ) ); + + Py_BEGIN_ALLOW_THREADS + sipSelfWasArg ? sipCpp->HYDROData_CalculationCase::AddRule( anObject1, a1, anObject2, a3 ) : + sipCpp->AddRule( anObject1, a1, anObject2, a3 ); + Py_END_ALLOW_THREADS + %End + + QString DumpRules(); + protected: /** -- 2.39.2