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>
24 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
25 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
27 #define PYTHON_CALCULATION_ID "KIND_CALCULATION"
29 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
30 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
32 HYDROData_CalculationCase::HYDROData_CalculationCase()
37 HYDROData_CalculationCase::~HYDROData_CalculationCase()
41 void HYDROData_CalculationCase::SetName( const QString& theName )
43 QString anOldCaseName = GetName();
44 if ( anOldCaseName != theName )
46 HYDROData_SequenceOfObjects aRegions = GetRegions();
48 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
49 for ( ; anIter.More(); anIter.Next() )
51 Handle(HYDROData_Region) aRegion =
52 Handle(HYDROData_Region)::DownCast( anIter.Value() );
53 if ( aRegion.IsNull() )
56 QString aRegionName = aRegion->GetName();
57 if ( aRegionName.startsWith( anOldCaseName ) )
59 aRegionName.replace( anOldCaseName, theName );
60 aRegion->SetName( aRegionName );
63 HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
64 HYDROData_SequenceOfObjects::Iterator anIter( aZones );
65 for ( ; anIter.More(); anIter.Next() )
67 Handle(HYDROData_Zone) aRegZone =
68 Handle(HYDROData_Zone)::DownCast( anIter.Value() );
69 if ( aRegZone.IsNull() )
72 QString aRegionZoneName = aRegZone->GetName();
73 if ( aRegionZoneName.startsWith( anOldCaseName ) )
75 aRegionZoneName.replace( anOldCaseName, theName );
76 aRegZone->SetName( aRegionZoneName );
82 HYDROData_Entity::SetName( theName );
85 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
89 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
90 if ( aDocument.IsNull() )
93 QString aDocName = aDocument->GetDocPyName();
94 QString aCalculName = GetName();
96 aResList << QString( "%1 = %2.CreateObject( %3 );" )
97 .arg( aCalculName ).arg( aDocName ).arg( PYTHON_CALCULATION_ID );
98 aResList << QString( "%1.SetName( \"%2\" );" )
99 .arg( aCalculName ).arg( aCalculName );
100 aResList << QString( "" );
102 HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
103 HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
104 for ( ; anIter.More(); anIter.Next() )
106 Handle(HYDROData_Object) aRefGeomObj =
107 Handle(HYDROData_Object)::DownCast( anIter.Value() );
108 if ( !aRefGeomObj.IsNull() )
109 setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
111 aResList << QString( "" );
113 aResList << QString( "%1.SplitGeometryObjects();" ).arg( aCalculName );
114 aResList << QString( "" );
116 // Now we restore the regions and zones order
117 HYDROData_SequenceOfObjects aRegions = GetRegions();
118 anIter.Init( aRegions );
119 for ( ; anIter.More(); anIter.Next() )
121 Handle(HYDROData_Region) aRegion =
122 Handle(HYDROData_Region)::DownCast( anIter.Value() );
123 if ( aRegion.IsNull() )
126 QString aRegionName = aRegion->GetName();
133 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetAllReferenceObjects() const
135 HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
137 Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
138 if ( !aBoundaryPolyline.IsNull() )
139 aResSeq.Append( aBoundaryPolyline );
141 HYDROData_SequenceOfObjects aSeqOfRegions = GetRegions();
142 aResSeq.Append( aSeqOfRegions );
147 void HYDROData_CalculationCase::Update()
149 HYDROData_Entity::Update();
151 // At first we remove previously created regions
154 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
155 if ( aDocument.IsNull() )
158 Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
159 HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
160 if ( aGeomObjects.IsEmpty() )
163 HYDROData_SplitToZonesTool::SplitDataList aSplitedZones =
164 HYDROData_SplitToZonesTool::SplitToZones( aGeomObjects, aBoundaryPolyline );
165 if ( aSplitedZones.isEmpty() )
168 QString aRegsPref = CALCULATION_REGIONS_PREF;
169 QString aZonesPref = CALCULATION_ZONES_PREF;
171 // Create result regions for case, by default one zone for one region
172 HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedZones );
173 while( anIter.hasNext() )
175 const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
178 Handle(HYDROData_Region) aRegion = addNewRegion();
180 QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
181 aRegion->SetName( aRegionName );
183 // Add the zone for region
184 Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone();
186 QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref );
187 aRegionZone->SetName( aZoneName );
189 aRegionZone->SetShape( aSplitData.Face() );
191 // Add the reference object for zone
192 for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i )
194 const QString& anObjName = aSplitData.ObjectNames.at( i );
196 Handle(HYDROData_Object) aRefObject = Handle(HYDROData_Object)::DownCast(
197 HYDROData_Tool::FindObjectByName( aDocument, anObjName ) );
198 if ( aRefObject.IsNull() )
201 aRegionZone->AddGeometryObject( aRefObject );
206 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
208 if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
209 return false; // Wrong type of object
211 if ( HasReference( theObject, DataTag_GeometryObject ) )
212 return false; // Object is already in reference list
214 AddReferenceObject( theObject, DataTag_GeometryObject );
216 // Indicate model of the need to update zones splitting
222 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
224 return GetReferenceObjects( DataTag_GeometryObject );
227 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
229 if ( theObject.IsNull() )
232 RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
234 // Indicate model of the need to update zones splitting
238 void HYDROData_CalculationCase::RemoveGeometryObjects()
240 ClearReferenceObjects( DataTag_GeometryObject );
242 // Indicate model of the need to update zones splitting
246 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
248 Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
250 SetReferenceObject( thePolyline, DataTag_Polyline );
252 // Indicate model of the need to update zones splitting
253 SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
256 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
258 return Handle(HYDROData_PolylineXY)::DownCast(
259 GetReferenceObject( DataTag_Polyline ) );
262 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
264 Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
266 ClearReferenceObjects( DataTag_Polyline );
268 // Indicate model of the need to update zones splitting
269 SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
272 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
274 Handle(HYDROData_Region) aNewRegion = addNewRegion();
275 if ( aNewRegion.IsNull() )
278 // Generate new name for new region
279 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
280 if ( !aDocument.IsNull() )
282 QString aRegsPref = CALCULATION_REGIONS_PREF;
284 QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
285 aNewRegion->SetName( aNewRegionName );
288 aNewRegion->AddZone( theZone );
293 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
295 if ( theRegion.IsNull() )
298 if ( HasReference( theRegion, DataTag_Region ) )
299 return false; // Object is already in reference list
301 // Move the region from other calculation
302 Handle(HYDROData_CalculationCase) aFatherCalc =
303 Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
304 if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
306 Handle(HYDROData_Region) aNewRegion = addNewRegion();
307 theRegion->CopyTo( aNewRegion );
309 aFatherCalc->RemoveRegion( theRegion );
311 theRegion->SetLabel( aNewRegion->Label() );
315 AddReferenceObject( theRegion, DataTag_Region );
321 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
323 return GetReferenceObjects( DataTag_Region );
326 void HYDROData_CalculationCase::UpdateRegionsOrder()
328 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
329 if ( aDocument.IsNull() )
332 HYDROData_SequenceOfObjects aRegions = GetRegions();
334 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
335 for ( ; anIter.More(); anIter.Next() )
337 Handle(HYDROData_Region) aRegion =
338 Handle(HYDROData_Region)::DownCast( anIter.Value() );
339 if ( aRegion.IsNull() )
342 aRegion->SetName( "" );
345 QString aRegsPref = CALCULATION_REGIONS_PREF;
347 anIter.Init( aRegions );
348 for ( ; anIter.More(); anIter.Next() )
350 Handle(HYDROData_Region) aRegion =
351 Handle(HYDROData_Region)::DownCast( anIter.Value() );
352 if ( aRegion.IsNull() )
355 QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
356 aRegion->SetName( aRegionName );
360 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
362 if ( theRegion.IsNull() )
365 RemoveReferenceObject( theRegion->Label(), DataTag_Region );
367 // Remove region from data model
368 Handle(HYDROData_CalculationCase) aFatherCalc =
369 Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
370 if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
374 void HYDROData_CalculationCase::RemoveRegions()
376 ClearReferenceObjects( DataTag_Region );
377 myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes( true );
380 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
382 TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
384 Handle(HYDROData_Region) aNewRegion =
385 Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
386 AddRegion( aNewRegion );
391 TopoDS_Shell HYDROData_CalculationCase::GetShell()
395 TopTools_ListOfShape aFacesList;
397 // Make shell containing all region shapes
398 BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
400 HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
401 HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
402 for ( ; aRegionIter.More(); aRegionIter.Next() ) {
403 Handle(HYDROData_Region) aRegion =
404 Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
405 if( aRegion.IsNull() ) {
409 TopoDS_Shape aRegionShape = aRegion->GetShape();
410 if( !aRegionShape.IsNull() ) {
411 if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
412 TopoDS_Face aFace = TopoDS::Face( aRegionShape );
413 if ( !aFace.IsNull() ) {
414 aFacesList.Append( aFace );
415 aSewing.Add( aFace );
418 TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
419 for ( ; anExp.More(); anExp.Next() ) {
420 TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
421 if ( !aFace.IsNull() ) {
422 aFacesList.Append( aFace );
423 aSewing.Add( aFace );
428 } // regions iterator
431 TopoDS_Shape aSewedShape = aSewing.SewedShape();
433 if ( !aSewedShape.IsNull() )
435 if ( aSewedShape.ShapeType() == TopAbs_FACE && aCaseRegions.Length() ==1 ) {
436 // create shell from one face
437 BRep_Builder aBuilder;
438 aBuilder.MakeShell( aShell );
439 aBuilder.Add( aShell, aSewedShape);
441 TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
442 Standard_Integer aNbOfShells = 0;
443 for ( ; anExpShells.More(); anExpShells.Next() ) {
444 aShell = TopoDS::Shell( anExpShells.Current() );
448 if ( aNbOfShells != 1 ) {
450 BRep_Builder aBuilder;
451 aBuilder.MakeShell( aShell );
453 TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
454 for ( ; anExpFaces.More(); anExpFaces.Next() ) {
455 TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
456 if ( !aFace.IsNull() ) {
457 aBuilder.Add( aShell, aFace );
464 if ( !aShell.IsNull() ) {
465 TopTools_IndexedMapOfShape aMapOfFaces;
466 TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
467 if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
469 BRep_Builder aBuilder;
470 aBuilder.MakeShell( aShell );
472 TopTools_ListIteratorOfListOfShape anIter( aFacesList );
473 for ( ; anIter.More(); anIter.Next() ) {
474 TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
475 aBuilder.Add( aShell, aFace );
482 BRep_Builder aBuilder;
483 aBuilder.MakeShell( aShell );
485 // Make shell containing all region shapes
486 HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
487 HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
488 for ( ; aRegionIter.More(); aRegionIter.Next() ) {
489 Handle(HYDROData_Region) aRegion =
490 Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
491 if( aRegion.IsNull() ) {
495 TopoDS_Shape aRegionShape = aRegion->GetShape();
497 // Add shape (face or shell) corresponding to the region into the shell
498 if( !aRegionShape.IsNull() ) {
499 if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
500 aBuilder.Add( aShell, aRegionShape );
502 TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
503 for( ; anExp.More(); anExp.Next() ) {
504 TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
505 if( !aFace.IsNull() ) {
506 aBuilder.Add( aShell, aFace );
511 } // regions iterator
514 // Nullify shell if it is empty
515 if ( !aShell.IsNull() && !TopoDS_Iterator(aShell).More() ) {
522 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
524 double aResAltitude = HYDROData_Bathymetry::GetInvalidAltitude();
526 Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint );
527 if ( aZone.IsNull() )
530 HYDROData_Zone::MergeBathymetriesType aZoneMergeType = aZone->GetMergeType();
531 if ( !aZone->IsMergingNeed() )
533 aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
535 else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
540 if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
542 Handle(HYDROData_Bathymetry) aMergeBathymetry = aZone->GetMergeBathymetry();
543 if ( !aMergeBathymetry.IsNull() )
544 aResAltitude = aMergeBathymetry->GetAltitudeForPoint( thePoint );
548 HYDROData_SequenceOfObjects aZoneObjects = aZone->GetGeometryObjects();
549 HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
550 for ( ; anIter.More(); anIter.Next() )
552 Handle(HYDROData_Object) aZoneObj =
553 Handle(HYDROData_Object)::DownCast( anIter.Value() );
554 if ( aZoneObj.IsNull() )
557 Handle(HYDROData_Bathymetry) anObjBathymetry = aZoneObj->GetBathymetry();
558 if ( anObjBathymetry.IsNull() )
561 double aPointAltitude = anObjBathymetry->GetAltitudeForPoint( thePoint );
562 if ( ValuesEquals( aPointAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) )
565 if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
567 aResAltitude = aPointAltitude;
570 else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
572 if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
573 aResAltitude > aPointAltitude )
575 aResAltitude = aPointAltitude;
578 else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
580 if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
581 aResAltitude < aPointAltitude )
583 aResAltitude = aPointAltitude;
592 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint ) const
594 Handle(HYDROData_Zone) aResZone;
596 HYDROData_SequenceOfObjects aRegions = GetRegions();
598 HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
599 for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
601 Handle(HYDROData_Region) aRegion =
602 Handle(HYDROData_Region)::DownCast( anIter.Value() );
603 if ( aRegion.IsNull() )
606 HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
607 HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
608 for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
610 Handle(HYDROData_Zone) aRegZone =
611 Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
612 if ( aRegZone.IsNull() )
615 PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
616 if ( aPointRelation != POINT_OUT )
617 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 // TODO: classify the point position relative to zone
637 // POINT_OUT - point is out of zone face
638 // POINT_IN - point is inside of zone face
639 // POINT_ON - point is on the edge of zone face