2 #include "HYDROData_CalculationCase.h"
4 #include "HYDROData_ArtificialObject.h"
5 #include "HYDROData_Bathymetry.h"
6 #include "HYDROData_Document.h"
7 #include "HYDROData_Iterator.h"
8 #include "HYDROData_NaturalObject.h"
9 #include "HYDROData_PolylineXY.h"
10 #include "HYDROData_SplitToZonesTool.h"
11 #include "HYDROData_Region.h"
12 #include "HYDROData_Tool.h"
13 #include "HYDROData_Zone.h"
16 #include <TopoDS_Shell.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRepBuilderAPI_Sewing.hxx>
19 #include <TopExp_Explorer.hxx>
21 #include <TopTools_ListOfShape.hxx>
22 #include <TopTools_ListIteratorOfListOfShape.hxx>
23 #include <BRepTopAdaptor_FClass2d.hxx>
25 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
26 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
28 #define PYTHON_CALCULATION_ID "KIND_CALCULATION"
30 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
31 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
33 HYDROData_CalculationCase::HYDROData_CalculationCase()
38 HYDROData_CalculationCase::~HYDROData_CalculationCase()
42 void HYDROData_CalculationCase::SetName( const QString& theName )
44 QString anOldCaseName = GetName();
45 if ( anOldCaseName != theName )
47 HYDROData_SequenceOfObjects aRegions = GetRegions();
49 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
50 for ( ; anIter.More(); anIter.Next() )
52 Handle(HYDROData_Region) aRegion =
53 Handle(HYDROData_Region)::DownCast( anIter.Value() );
54 if ( aRegion.IsNull() )
57 QString aRegionName = aRegion->GetName();
58 if ( aRegionName.startsWith( anOldCaseName ) )
60 aRegionName.replace( anOldCaseName, theName );
61 aRegion->SetName( aRegionName );
64 HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
65 HYDROData_SequenceOfObjects::Iterator anIter( aZones );
66 for ( ; anIter.More(); anIter.Next() )
68 Handle(HYDROData_Zone) aRegZone =
69 Handle(HYDROData_Zone)::DownCast( anIter.Value() );
70 if ( aRegZone.IsNull() )
73 QString aRegionZoneName = aRegZone->GetName();
74 if ( aRegionZoneName.startsWith( anOldCaseName ) )
76 aRegionZoneName.replace( anOldCaseName, theName );
77 aRegZone->SetName( aRegionZoneName );
83 HYDROData_Entity::SetName( theName );
86 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
90 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
91 if ( aDocument.IsNull() )
94 QString aDocName = aDocument->GetDocPyName();
95 QString aCalculName = GetName();
97 aResList << QString( "%1 = %2.CreateObject( %3 );" )
98 .arg( aCalculName ).arg( aDocName ).arg( PYTHON_CALCULATION_ID );
99 aResList << QString( "%1.SetName( \"%2\" );" )
100 .arg( aCalculName ).arg( aCalculName );
101 aResList << QString( "" );
103 HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
104 HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
105 for ( ; anIter.More(); anIter.Next() )
107 Handle(HYDROData_Object) aRefGeomObj =
108 Handle(HYDROData_Object)::DownCast( anIter.Value() );
109 if ( !aRefGeomObj.IsNull() )
110 setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
112 aResList << QString( "" );
114 aResList << QString( "%1.SplitGeometryObjects();" ).arg( aCalculName );
115 aResList << QString( "" );
117 // Now we restore the regions and zones order
118 HYDROData_SequenceOfObjects aRegions = GetRegions();
119 anIter.Init( aRegions );
120 for ( ; anIter.More(); anIter.Next() )
122 Handle(HYDROData_Region) aRegion =
123 Handle(HYDROData_Region)::DownCast( anIter.Value() );
124 if ( aRegion.IsNull() )
127 QString aRegionName = aRegion->GetName();
134 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetAllReferenceObjects() const
136 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
138 Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
139 if ( !aBoundaryPolyline.IsNull() )
140 aResSeq.Append( aBoundaryPolyline );
142 HYDROData_SequenceOfObjects aSeqOfRegions = GetRegions();
143 aResSeq.Append( aSeqOfRegions );
148 void HYDROData_CalculationCase::Update()
150 HYDROData_Entity::Update();
152 // At first we remove previously created regions
155 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
156 if ( aDocument.IsNull() )
159 Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
160 HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
161 if ( aGeomObjects.IsEmpty() )
164 HYDROData_SplitToZonesTool::SplitDataList aSplitedZones =
165 HYDROData_SplitToZonesTool::SplitToZones( aGeomObjects, aBoundaryPolyline );
166 if ( aSplitedZones.isEmpty() )
169 QString aRegsPref = CALCULATION_REGIONS_PREF;
170 QString aZonesPref = CALCULATION_ZONES_PREF;
172 // Create result regions for case, by default one zone for one region
173 HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedZones );
174 while( anIter.hasNext() )
176 const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
179 Handle(HYDROData_Region) aRegion = addNewRegion();
181 QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
182 aRegion->SetName( aRegionName );
184 // Add the zone for region
185 Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone();
187 QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref );
188 aRegionZone->SetName( aZoneName );
190 aRegionZone->SetShape( aSplitData.Face() );
192 // Add the reference object for zone
193 for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i )
195 const QString& anObjName = aSplitData.ObjectNames.at( i );
197 Handle(HYDROData_Object) aRefObject = Handle(HYDROData_Object)::DownCast(
198 HYDROData_Tool::FindObjectByName( aDocument, anObjName ) );
199 if ( aRefObject.IsNull() )
202 aRegionZone->AddGeometryObject( aRefObject );
207 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
209 if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
210 return false; // Wrong type of object
212 if ( HasReference( theObject, DataTag_GeometryObject ) )
213 return false; // Object is already in reference list
215 AddReferenceObject( theObject, DataTag_GeometryObject );
217 // Indicate model of the need to update zones splitting
223 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
225 return GetReferenceObjects( DataTag_GeometryObject );
228 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
230 if ( theObject.IsNull() )
233 RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
235 // Indicate model of the need to update zones splitting
239 void HYDROData_CalculationCase::RemoveGeometryObjects()
241 ClearReferenceObjects( DataTag_GeometryObject );
243 // Indicate model of the need to update zones splitting
247 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
249 Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
251 SetReferenceObject( thePolyline, DataTag_Polyline );
253 // Indicate model of the need to update zones splitting
254 SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
257 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
259 return Handle(HYDROData_PolylineXY)::DownCast(
260 GetReferenceObject( DataTag_Polyline ) );
263 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
265 Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
267 ClearReferenceObjects( DataTag_Polyline );
269 // Indicate model of the need to update zones splitting
270 SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
273 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
275 Handle(HYDROData_Region) aNewRegion = addNewRegion();
276 if ( aNewRegion.IsNull() )
279 // Generate new name for new region
280 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
281 if ( !aDocument.IsNull() )
283 QString aRegsPref = CALCULATION_REGIONS_PREF;
285 QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
286 aNewRegion->SetName( aNewRegionName );
289 aNewRegion->AddZone( theZone );
294 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
296 if ( theRegion.IsNull() )
299 if ( HasReference( theRegion, DataTag_Region ) )
300 return false; // Object is already in reference list
302 // Move the region from other calculation
303 Handle(HYDROData_CalculationCase) aFatherCalc =
304 Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
305 if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
307 Handle(HYDROData_Region) aNewRegion = addNewRegion();
308 theRegion->CopyTo( aNewRegion );
310 aFatherCalc->RemoveRegion( theRegion );
312 theRegion->SetLabel( aNewRegion->Label() );
316 AddReferenceObject( theRegion, DataTag_Region );
322 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
324 return GetReferenceObjects( DataTag_Region );
327 void HYDROData_CalculationCase::UpdateRegionsOrder()
329 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
330 if ( aDocument.IsNull() )
333 HYDROData_SequenceOfObjects aRegions = GetRegions();
335 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
336 for ( ; anIter.More(); anIter.Next() )
338 Handle(HYDROData_Region) aRegion =
339 Handle(HYDROData_Region)::DownCast( anIter.Value() );
340 if ( aRegion.IsNull() )
343 aRegion->SetName( "" );
346 QString aRegsPref = CALCULATION_REGIONS_PREF;
348 anIter.Init( aRegions );
349 for ( ; anIter.More(); anIter.Next() )
351 Handle(HYDROData_Region) aRegion =
352 Handle(HYDROData_Region)::DownCast( anIter.Value() );
353 if ( aRegion.IsNull() )
356 QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
357 aRegion->SetName( aRegionName );
361 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
363 if ( theRegion.IsNull() )
366 RemoveReferenceObject( theRegion->Label(), DataTag_Region );
368 // Remove region from data model
369 Handle(HYDROData_CalculationCase) aFatherCalc =
370 Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
371 if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
375 void HYDROData_CalculationCase::RemoveRegions()
377 ClearReferenceObjects( DataTag_Region );
378 myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes( true );
381 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
383 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
385 Handle(HYDROData_Region) aNewRegion =
386 Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
387 AddRegion( aNewRegion );
392 TopoDS_Shell HYDROData_CalculationCase::GetShell()
396 TopTools_ListOfShape aFacesList;
398 // Make shell containing all region shapes
399 BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
401 HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
402 HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
403 for ( ; aRegionIter.More(); aRegionIter.Next() ) {
404 Handle(HYDROData_Region) aRegion =
405 Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
406 if( aRegion.IsNull() ) {
410 TopoDS_Shape aRegionShape = aRegion->GetShape();
411 if( !aRegionShape.IsNull() ) {
412 if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
413 TopoDS_Face aFace = TopoDS::Face( aRegionShape );
414 if ( !aFace.IsNull() ) {
415 aFacesList.Append( aFace );
416 aSewing.Add( aFace );
419 TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
420 for ( ; anExp.More(); anExp.Next() ) {
421 TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
422 if ( !aFace.IsNull() ) {
423 aFacesList.Append( aFace );
424 aSewing.Add( aFace );
429 } // regions iterator
432 TopoDS_Shape aSewedShape = aSewing.SewedShape();
434 if ( !aSewedShape.IsNull() )
436 if ( aSewedShape.ShapeType() == TopAbs_FACE && aCaseRegions.Length() ==1 ) {
437 // create shell from one face
438 BRep_Builder aBuilder;
439 aBuilder.MakeShell( aShell );
440 aBuilder.Add( aShell, aSewedShape);
442 TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
443 Standard_Integer aNbOfShells = 0;
444 for ( ; anExpShells.More(); anExpShells.Next() ) {
445 aShell = TopoDS::Shell( anExpShells.Current() );
449 if ( aNbOfShells != 1 ) {
451 BRep_Builder aBuilder;
452 aBuilder.MakeShell( aShell );
454 TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
455 for ( ; anExpFaces.More(); anExpFaces.Next() ) {
456 TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
457 if ( !aFace.IsNull() ) {
458 aBuilder.Add( aShell, aFace );
465 if ( !aShell.IsNull() ) {
466 TopTools_IndexedMapOfShape aMapOfFaces;
467 TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
468 if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
470 BRep_Builder aBuilder;
471 aBuilder.MakeShell( aShell );
473 TopTools_ListIteratorOfListOfShape anIter( aFacesList );
474 for ( ; anIter.More(); anIter.Next() ) {
475 TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
476 aBuilder.Add( aShell, aFace );
483 BRep_Builder aBuilder;
484 aBuilder.MakeShell( aShell );
486 // Make shell containing all region shapes
487 HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
488 HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
489 for ( ; aRegionIter.More(); aRegionIter.Next() ) {
490 Handle(HYDROData_Region) aRegion =
491 Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
492 if( aRegion.IsNull() ) {
496 TopoDS_Shape aRegionShape = aRegion->GetShape();
498 // Add shape (face or shell) corresponding to the region into the shell
499 if( !aRegionShape.IsNull() ) {
500 if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
501 aBuilder.Add( aShell, aRegionShape );
503 TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
504 for( ; anExp.More(); anExp.Next() ) {
505 TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
506 if( !aFace.IsNull() ) {
507 aBuilder.Add( aShell, aFace );
512 } // regions iterator
515 // Nullify shell if it is empty
516 if ( !aShell.IsNull() && !TopoDS_Iterator(aShell).More() ) {
523 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
525 double aResAltitude = HYDROData_Bathymetry::GetInvalidAltitude();
527 Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint );
528 if ( aZone.IsNull() )
531 HYDROData_Zone::MergeBathymetriesType aZoneMergeType = aZone->GetMergeType();
532 if ( !aZone->IsMergingNeed() )
534 aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
536 else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
541 if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
543 Handle(HYDROData_Bathymetry) aMergeBathymetry = aZone->GetMergeBathymetry();
544 if ( !aMergeBathymetry.IsNull() )
545 aResAltitude = aMergeBathymetry->GetAltitudeForPoint( thePoint );
549 HYDROData_SequenceOfObjects aZoneObjects = aZone->GetGeometryObjects();
550 HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
551 for ( ; anIter.More(); anIter.Next() )
553 Handle(HYDROData_Object) aZoneObj =
554 Handle(HYDROData_Object)::DownCast( anIter.Value() );
555 if ( aZoneObj.IsNull() )
558 Handle(HYDROData_Bathymetry) anObjBathymetry = aZoneObj->GetBathymetry();
559 if ( anObjBathymetry.IsNull() )
562 double aPointAltitude = anObjBathymetry->GetAltitudeForPoint( thePoint );
563 if ( ValuesEquals( aPointAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) )
566 if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
568 aResAltitude = aPointAltitude;
571 else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
573 if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
574 aResAltitude > aPointAltitude )
576 aResAltitude = aPointAltitude;
579 else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
581 if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
582 aResAltitude < aPointAltitude )
584 aResAltitude = aPointAltitude;
593 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint ) const
595 Handle(HYDROData_Zone) aResZone;
597 HYDROData_SequenceOfObjects aRegions = GetRegions();
599 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
600 for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
602 Handle(HYDROData_Region) aRegion =
603 Handle(HYDROData_Region)::DownCast( anIter.Value() );
604 if ( aRegion.IsNull() )
607 HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
608 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
609 for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
611 Handle(HYDROData_Zone) aRegZone =
612 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
613 if ( aRegZone.IsNull() )
616 PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
617 if ( aPointRelation != POINT_OUT )
618 aResZone = aRegZone; // We found the desired zone
624 HYDROData_CalculationCase::PointClassification HYDROData_CalculationCase::GetPointClassification(
625 const gp_XY& thePoint,
626 const Handle(HYDROData_Zone)& theZone ) const
628 PointClassification aRes = POINT_OUT;
629 if ( theZone.IsNull() )
632 TopoDS_Face aZoneFace = TopoDS::Face( theZone->GetShape() );
633 if ( aZoneFace.IsNull() )
636 BRepTopAdaptor_FClass2d aClassifier( aZoneFace, Precision::Confusion() );
637 TopAbs_State State = aClassifier.Perform( gp_Pnt2d(thePoint), Standard_False );
638 if (State == TopAbs_OUT)
640 else if(State == TopAbs_IN)
642 else if(State == TopAbs_ON)