From 230aa46188ee46dfd4fe22e96a9a7f05518513a4 Mon Sep 17 00:00:00 2001 From: apl Date: Thu, 26 Dec 2013 06:19:13 +0000 Subject: [PATCH] 21854: Add persistent dimensions - Implementation of dimension dialogs, displaying, persistence. --- resources/CMakeLists.txt | 1 + resources/SalomeApp.xml.in | 9 + resources/managedimensions.png | Bin 0 -> 622 bytes src/EntityGUI/EntityGUI_3DSketcherDlg.cxx | 32 +- src/GEOMGUI/CMakeLists.txt | 2 + src/GEOMGUI/GEOM_Displayer.cxx | 195 ++- src/GEOMGUI/GEOM_Displayer.h | 10 + src/GEOMGUI/GEOM_images.ts | 4 + src/GEOMGUI/GEOM_msg_en.ts | 192 +++ src/GEOMGUI/GEOM_msg_fr.ts | 192 +++ src/GEOMGUI/GEOM_msg_ja.ts | 192 +++ src/GEOMGUI/GeometryGUI.cxx | 90 +- src/GEOMGUI/GeometryGUI_Operations.h | 1 + src/GEOMUtils/CMakeLists.txt | 6 + src/GEOMUtils/GEOMUtils_DimensionProperty.cxx | 918 +++++++++++++ src/GEOMUtils/GEOMUtils_DimensionProperty.hxx | 422 ++++++ src/MeasureGUI/CMakeLists.txt | 19 + src/MeasureGUI/MeasureGUI.cxx | 30 +- src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui | 83 ++ .../MeasureGUI_1TreeWidget_4Button_QTD.ui | 105 ++ src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui | 117 ++ src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui | 151 +++ src/MeasureGUI/MeasureGUI_AngleDlg.cxx | 30 +- .../MeasureGUI_CreateDimensionDlg.cxx | 950 +++++++++++++ .../MeasureGUI_CreateDimensionDlg.h | 258 ++++ .../MeasureGUI_DimensionCreateTool.cxx | 650 +++++++++ .../MeasureGUI_DimensionCreateTool.h | 106 ++ src/MeasureGUI/MeasureGUI_DimensionFilter.cxx | 192 +++ src/MeasureGUI/MeasureGUI_DimensionFilter.h | 80 ++ .../MeasureGUI_DimensionInteractor.cxx | 869 ++++++++++++ .../MeasureGUI_DimensionInteractor.h | 177 +++ .../MeasureGUI_ManageDimensionsDlg.cxx | 1183 +++++++++++++++++ .../MeasureGUI_ManageDimensionsDlg.h | 116 ++ src/MeasureGUI/MeasureGUI_Widgets.cxx | 57 + src/MeasureGUI/MeasureGUI_Widgets.h | 64 + src/OBJECT/CMakeLists.txt | 2 + src/OBJECT/GEOM_AISDimension.cxx | 141 ++ src/OBJECT/GEOM_AISDimension.hxx | 92 ++ src/OBJECT/GEOM_Constants.cxx | 9 + src/OBJECT/GEOM_Constants.h | 5 +- 40 files changed, 7675 insertions(+), 77 deletions(-) create mode 100644 resources/managedimensions.png create mode 100644 src/GEOMUtils/GEOMUtils_DimensionProperty.cxx create mode 100644 src/GEOMUtils/GEOMUtils_DimensionProperty.hxx create mode 100644 src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui create mode 100644 src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui create mode 100644 src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui create mode 100644 src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui create mode 100644 src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx create mode 100644 src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h create mode 100644 src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx create mode 100644 src/MeasureGUI/MeasureGUI_DimensionCreateTool.h create mode 100644 src/MeasureGUI/MeasureGUI_DimensionFilter.cxx create mode 100644 src/MeasureGUI/MeasureGUI_DimensionFilter.h create mode 100644 src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx create mode 100644 src/MeasureGUI/MeasureGUI_DimensionInteractor.h create mode 100644 src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx create mode 100644 src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h create mode 100755 src/OBJECT/GEOM_AISDimension.cxx create mode 100755 src/OBJECT/GEOM_AISDimension.hxx diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 7e9c9aa48..973310af6 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -107,6 +107,7 @@ SET( _res_files line.png line2points.png line2faces.png + managedimensions.png mindist.png mirrorPoint.png mirrorAxe.png diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index af5f33ef5..2fb47511b 100644 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -68,6 +68,15 @@ + + + + + + + + + diff --git a/resources/managedimensions.png b/resources/managedimensions.png new file mode 100644 index 0000000000000000000000000000000000000000..1600ecbed7bdfe071af877eb5b442bb8184aa161 GIT binary patch literal 622 zcmV-!0+IcRP)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00009 za7bBm000XP000XP0YJXtK>z>%8gxZibW?9;ba!ELWdKlNX>N2bPDNB8b~7$DE-^4L z^m3s900F*9L_t(IPpwqhPQpMG?Wg(V1MyGz5`I8ML8{^cA_Zg-SriZ`J0gmR;(}}9 zKV0YDwv%>J5)dajoh7#?r@iNl1OWdE9Qd3IB8eF|p!FSt`bUI{%g;wp8V6{dzuSZC z%`UA|T^}S`-q{EnpAo3Ng{k=RDG0@fLt5tse#rE9Xr1hA!AaA@31wLZ5k%PhiZXQy zsFPzVE>6Hx0 zHdEK|K(w~O37t+SEdNLxxF^E;y8>0Fj{Y4}cX6+&%joJ-9UsJXb&;x@6FM9YSYf}- z0Pcy9s~ZQQU{-gnsY{sDg)8e8LJ>rW1@i)5oCe#&MPPfl2ypOEnH3_5894N$C{%28 z8`t>(>vmsD3K}~;i?Ol5k`(OrNJ~nVx;@?4I2+)`rlg=3U$vwZ$&1W7dhF0Tcuv+) zt;WXL05^7nT?*<%^CDgfV(iSuR;pGX;%tEXutw@^Vu!}=qOrY99ZQMohH!b!LMVa= z@lvqFPH#lI$1SetArrowSize((theAngle * M_PI / 180) * (aLength/20)); - // - //SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - //int w = resMgr->integerValue("Geometry", "measures_line_width", 1); - //Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect(); - //asp->LineAspect()->SetWidth(w); - //anIO->Attributes()->SetAngleAspect(asp); - - // todo : port - - Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2, aPlane->Pln() ); + + Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( P1, P0, P2 ); anIO->SetCustomValue( theAngle ); diff --git a/src/GEOMGUI/CMakeLists.txt b/src/GEOMGUI/CMakeLists.txt index ed1bf4cf1..fa56d9185 100755 --- a/src/GEOMGUI/CMakeLists.txt +++ b/src/GEOMGUI/CMakeLists.txt @@ -38,6 +38,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/Material ${PROJECT_SOURCE_DIR}/src/GEOMClient ${PROJECT_SOURCE_DIR}/src/GEOMImpl + ${PROJECT_SOURCE_DIR}/src/GEOMUtils ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -56,6 +57,7 @@ SET(_link_LIBRARIES GEOMFiltersSelection Material GEOMImpl + GEOMUtils ${KERNEL_SALOMELocalTrace} ${KERNEL_SalomeDS} ${KERNEL_SalomeDSClient} diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 25ad93b5a..2ba012082 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -39,12 +39,16 @@ #include #include +#include #include #include #include #include #include +#include +#include + #include #include @@ -77,7 +81,12 @@ // OCCT Includes #include +#include +#include +#include +#include #include +#include #include #include #include @@ -520,8 +529,7 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, { if ( view->isVisible( theIO ) || ( checkActiveViewer && view == GetActiveView() ) ) { - Erase( theIO, true, false, view ); - Display( theIO, updateViewer, view ); + Redisplay( theIO, updateViewer, view ); } } } @@ -530,6 +538,27 @@ void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, } } +//================================================================= +/*! + * GEOM_Displayer::Redisplay + * Redisplay (erase and then display again) interactive object + * in the specified view + */ +//================================================================= +void GEOM_Displayer::Redisplay( const Handle(SALOME_InteractiveObject)& theIO, + const bool theUpdateViewer, + SALOME_View* theViewFrame ) +{ + SALOME_View* vf = theViewFrame ? theViewFrame : GetActiveView(); + if ( !vf ) + { + return; + } + + Erase( theIO, true, false, theViewFrame ); + Display( theIO, theUpdateViewer, theViewFrame ); +} + //================================================================= /*! * GEOM_Displayer::Display @@ -930,6 +959,144 @@ void GEOM_Displayer::updateActorProperties( GEOM_Actor* actor, bool create ) } } +//================================================================= +/*! + * GEOM_Displayer::updateDimensions + * Creates or renews dimension presentation for the IO. + */ +//================================================================= +void GEOM_Displayer::updateDimensions( const Handle(SALOME_InteractiveObject)& theIO, + SALOME_OCCPrs* thePrs, + const gp_Ax3& theShapeLCS ) +{ + SalomeApp_Study* aStudy = getStudy(); + if ( !aStudy ) + { + return; + } + + if ( theIO.IsNull() ) + { + return; + } + + SOCC_Prs* anOccPrs = dynamic_cast( thePrs ); + + AIS_ListOfInteractive aListOfIO; + + anOccPrs->GetObjects( aListOfIO ); + + AIS_ListIteratorOfListOfInteractive aIterateIO( aListOfIO ); + + // remove outdated presentations of dimensions + for ( ; aIterateIO.More(); aIterateIO.Next() ) + { + const Handle(AIS_InteractiveObject)& anIO = aIterateIO.Value(); + if ( !anIO->IsKind( STANDARD_TYPE( AIS_Dimension ) ) ) + { + continue; + } + + aListOfIO.Remove( aIterateIO ); + } + + // prepare dimension styling + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + QColor aQColor = aResMgr->colorValue ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) ); + int aLineWidth = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 ); + double aFontHeight = aResMgr->doubleValue ( "Geometry", "dimensions_font_height", 10 ); + double anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 ); + bool isUnitsShown = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false ); + QString aUnitsLength = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" ); + QString aUnitsAngle = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" ); + + // restore dimension presentation from saved attribute or property data + AIS_ListOfInteractive aRestoredDimensions; + + QVariant aProperty = aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + theIO->getEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ); + + GEOMUtils_DimensionProperty aRecords; + + if ( aProperty.isValid() && aProperty.canConvert() ) + { + aRecords = aProperty.value(); + } + else + { + aRecords.LoadFromAttribute( getStudy(), theIO->getEntry() ); + } + + // create up-to-date dimension presentations + for ( int aPrsIt = 0; aPrsIt < aRecords.GetNumber(); ++aPrsIt ) + { + if ( !aRecords.IsVisible( aPrsIt ) ) + { + continue; + } + + // init dimension by type + Handle(AIS_Dimension) aPrs; + switch( aRecords.GetType( aPrsIt ) ) + { + case GEOMUtils_DimensionProperty::DimensionType_Length : + { + Handle(GEOM_AISLength) aLength = new GEOM_AISLength( aPrsIt ); + aRecords.GetRecord( aPrsIt )->AsLength()->Update( aLength, theShapeLCS ); + aPrs = aLength; + break; + } + + case GEOMUtils_DimensionProperty::DimensionType_Diameter : + { + Handle(GEOM_AISDiameter) aDiam = new GEOM_AISDiameter( aPrsIt ); + aRecords.GetRecord( aPrsIt )->AsDiameter()->Update( aDiam, theShapeLCS ); + aPrs = aDiam; + break; + } + + case GEOMUtils_DimensionProperty::DimensionType_Angle : + { + Handle(GEOM_AISAngle) anAng = new GEOM_AISAngle( aPrsIt ); + aRecords.GetRecord( aPrsIt )->AsAngle()->Update( anAng, theShapeLCS ); + aPrs = anAng; + break; + } + } + + aPrs->SetOwner( theIO ); + + Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB ); + + Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); + + aStyle->SetCommonColor( aColor ); + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + aStyle->MakeText3d( Standard_True ); + aStyle->MakeTextShaded( Standard_True ); + aStyle->TextAspect()->SetHeight( aFontHeight ); + aStyle->ArrowAspect()->SetLength( anArrowLength ); + aStyle->LineAspect()->SetWidth( aLineWidth ); + aStyle->SetTextHorizontalPosition( aPrs->DimensionAspect()->TextHorizontalPosition() ); + aStyle->SetTextVerticalPosition( aPrs->DimensionAspect()->TextVerticalPosition() ); + aPrs->SetDimensionAspect( aStyle ); + aPrs->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 ); + + aListOfIO.Append( aPrs ); + } + + // update presentation + anOccPrs->Clear(); + + for ( aIterateIO.Initialize( aListOfIO ); aIterateIO.More(); aIterateIO.Next() ) + { + anOccPrs->AddObject( aIterateIO.Value() ); + } +} + //================================================================= /*! * GEOM_Displayer::Erase @@ -966,6 +1133,28 @@ void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList, UpdateViewer(); } +//================================================================= +/*! + * GEOM_Displayer::Redisplay + * Calls Redisplay() method for each object in the given list + */ +//================================================================= +void GEOM_Displayer::Redisplay( const SALOME_ListIO& theIOList, + const bool theUpdateViewer, + SALOME_View* theViewFrame ) +{ + SALOME_ListIteratorOfListIO anIter( theIOList ); + for ( ; anIter.More(); anIter.Next() ) + { + Redisplay( anIter.Value(), false, theViewFrame ); + } + + if ( theUpdateViewer ) + { + UpdateViewer(); + } +} + //================================================================= /*! * GEOM_Displayer::Update @@ -1096,6 +1285,8 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) AISShape->SetToUpdate(); } } + + updateDimensions( myIO, occPrs, GEOMUtils::GetPosition( myShape ) ); } } diff --git a/src/GEOMGUI/GEOM_Displayer.h b/src/GEOMGUI/GEOM_Displayer.h index 6d3f03216..4e8df530b 100644 --- a/src/GEOMGUI/GEOM_Displayer.h +++ b/src/GEOMGUI/GEOM_Displayer.h @@ -66,6 +66,7 @@ class SalomeApp_Study; class SalomeApp_Application; class SUIT_SelectionFilter; class Handle_GEOM_AISShape; +class gp_Ax3; //class SALOME_Selection; class GEOMGUI_EXPORT GEOM_Displayer : public LightApp_Displayer @@ -93,6 +94,10 @@ public: const bool updateViewer = true, const bool checkActiveViewer = true ); + void Redisplay ( const Handle(SALOME_InteractiveObject)& theIO, + const bool theUpdateViewer, + SALOME_View* theViewFrame ); + void Erase ( const Handle(SALOME_InteractiveObject)& theIO, const bool forced = false, const bool updateViewer = true, @@ -118,6 +123,10 @@ public: const bool updateViewer = true, const bool checkActiveViewer = true ); + void Redisplay ( const SALOME_ListIO& theIOList, + const bool theUpdateViewer, + SALOME_View* theViewFrame ); + /* build presentation accordint to the current viewer type*/ SALOME_Prs* BuildPrs ( GEOM::GEOM_Object_ptr ); SALOME_Prs* BuildPrs ( const TopoDS_Shape& ); @@ -226,6 +235,7 @@ protected: QColor colorFromResources( const QString&, const QColor& ); void updateShapeProperties( const Handle(GEOM_AISShape)&, bool ); void updateActorProperties( GEOM_Actor*, bool ); + void updateDimensions( const Handle(SALOME_InteractiveObject)&, SALOME_OCCPrs*, const gp_Ax3& ); PropMap getObjectProperties( SalomeApp_Study*, const QString&, SALOME_View* = 0 ); PropMap getDefaultPropertyMap(); diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 1e27166a6..467cc55de 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -1135,6 +1135,10 @@ ICO_MEASURE_ANGLE angle.png + + ICO_MANAGE_DIMENSIONS + managedimensions.png + ICO_POINT point2.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index a56f0efd8..8f02e9aba 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -3240,6 +3240,38 @@ Please, select face, shell or solid and try again PREF_AUTO_BRING_TO_FRONT Automatic bring to front + + PREF_DIMENSIONS + Dimensions (Measurements) + + + PREF_DIMENSIONS_COLOR + Color + + + PREF_DIMENSIONS_LINE_WIDTH + Line width + + + PREF_DIMENSIONS_FONT_HEIGHT + Font height + + + PREF_DIMENSIONS_ARROW_LENGTH + Length of arrows + + + PREF_DIMENSIONS_LENGTH_UNITS + Length measurement units + + + PREF_DIMENSIONS_ANGLE_UNITS + Angle measurement units + + + PREF_DIMENSIONS_SHOW_UNITS + Show units of measurement + PREF_ISOS Number of isolines @@ -4681,6 +4713,18 @@ Please, select face, shell or solid and try again STB_MEASURE_ANGLE Compute angle between two lines or linear edges + + TOP_MANAGE_DIMENSIONS + Manage dimensions + + + MEN_MANAGE_DIMENSIONS + Manage dimensions + + + STB_MANAGE_DIMENSIONS + Manage measurement dimensions of an object + TOP_POP_AUTO_COLOR Auto color @@ -6073,6 +6117,154 @@ Number of sketch points too small Z + + MeasureGUI_ManageDimensionsDlg + + MANAGE_DIMENSIONS_TITLE + Manage dimensions + + + OBJECT_LABEL + Object + + + DIMENSIONS_GROUP + Dimensions + + + ADD_BTN + Add + + + REMOVE_BTN + Remove + + + SHOW_ALL_BTN + Show all + + + HIDE_ALL_BTN + Hide all + + + DISTANCE_ITEM + Distance + + + DIAMETER_ITEM + Diameter + + + ANGLE_ITEM + Angle + + + WRN_TITLE_UNSAVED + Unsaved changes + + + WRN_MSG_UNSAVED + The unsaved changes will be lost. +Do you want to continue? + + + + MeasureGUI_CreateDimensionDlg + + CREATE_DIMENSION_TITLE + Add dimension + + + DIMENSIONS + Dimensions + + + LENGTH + Length + + + DIAMETER + Diameter + + + ANGLE + Angle + + + ARGUMENTS + Arguments + + + EDGE_LENGTH + Edge length + + + TWO_POINTS + Two points + + + PARALLEL_EDGES + Parallel edges + + + TWO_EDGES + Two edges + + + THREE_POINTS + Three points + + + EDGE + Edge + + + EDGE_1 + Edge 1 + + + EDGE_2 + Edge 2 + + + POINT_1 + Point 1 + + + POINT_2 + Point 2 + + + POINT_3 + Point 3 + + + OBJECT + Object + + + NAME_LENGTH + Length + + + NAME_DIAMETER + Diameter + + + NAME_ANGLE + Angle + + + WARNING_TITLE_CANNOT_CREATE_DIMENSION + Can not create dimension + + + WARNING_MSG_INVALID_ARGUMENTS + The dimension can not be created for the specified arguments. +Please specify suitable arguments. + + OperationGUI_ChamferDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 371635ac4..b0515a893 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -3242,6 +3242,38 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_AUTO_BRING_TO_FRONT Afficher au premier plan automatiquement + + PREF_DIMENSIONS + Dimensions (Measurements) + + + PREF_DIMENSIONS_COLOR + Color + + + PREF_DIMENSIONS_LINE_WIDTH + Line width + + + PREF_DIMENSIONS_FONT_HEIGHT + Font height + + + PREF_DIMENSIONS_ARROW_LENGTH + Length of arrows + + + PREF_DIMENSIONS_LENGTH_UNITS + Length measurement units + + + PREF_DIMENSIONS_ANGLE_UNITS + Angle measurement units + + + PREF_DIMENSIONS_SHOW_UNITS + Show units of measurement + PREF_ISOS Nombre d'isolignes @@ -4658,6 +4690,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_MEASURE_ANGLE Calculer l'angle entre deux lignes ou arêtes linéaires + + TOP_MANAGE_DIMENSIONS + Manage dimensions + + + MEN_MANAGE_DIMENSIONS + Manage dimensions + + + STB_MANAGE_DIMENSIONS + Manage measurement dimensions of an object + TOP_POP_AUTO_COLOR Couleur automatique @@ -6050,6 +6094,154 @@ Le nombre de points n'est pas suffisant Z + + MeasureGUI_ManageDimensionsDlg + + MANAGE_DIMENSIONS_TITLE + Manage dimensions + + + OBJECT_LABEL + Object + + + DIMENSIONS_GROUP + Dimensions + + + ADD_BTN + Add + + + REMOVE_BTN + Remove + + + SHOW_ALL_BTN + Show all + + + HIDE_ALL_BTN + Hide all + + + DISTANCE_ITEM + Distance + + + DIAMETER_ITEM + Diameter + + + ANGLE_ITEM + Angle + + + WRN_TITLE_UNSAVED + Unsaved changes + + + WRN_MSG_UNSAVED + The unsaved changes will be lost. +Do you want to continue? + + + + MeasureGUI_CreateDimensionDlg + + CREATE_DIMENSION_TITLE + Add dimension + + + DIMENSIONS + Dimensions + + + LENGTH + Length + + + DIAMETER + Diameter + + + ANGLE + Angle + + + ARGUMENTS + Arguments + + + EDGE_LENGTH + Edge length + + + TWO_POINTS + Two points + + + PARALLEL_EDGES + Parallel edges + + + TWO_EDGES + Two edges + + + THREE_POINTS + Three points + + + EDGE + Edge + + + EDGE_1 + Edge 1 + + + EDGE_2 + Edge 2 + + + POINT_1 + Point 1 + + + POINT_2 + Point 2 + + + POINT_3 + Point 3 + + + OBJECT + Object + + + NAME_LENGTH + Length + + + NAME_DIAMETER + Diameter + + + NAME_ANGLE + Angle + + + WARNING_TITLE_CANNOT_CREATE_DIMENSION + Can not create dimension + + + WARNING_MSG_INVALID_ARGUMENTS + The dimension can not be created for the specified arguments. +Please specify suitable arguments. + + OperationGUI_ChamferDlg diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 77b266efc..313d43c1d 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -3215,6 +3215,38 @@ PREF_AUTO_BRING_TO_FRONT PREF_AUTO_BRING_TO_FRONT + + PREF_DIMENSIONS + Dimensions (Measurements) + + + PREF_DIMENSIONS_COLOR + Color + + + PREF_DIMENSIONS_LINE_WIDTH + Line width + + + PREF_DIMENSIONS_FONT_HEIGHT + Font height + + + PREF_DIMENSIONS_ARROW_LENGTH + Length of arrows + + + PREF_DIMENSIONS_LENGTH_UNITS + Length measurement units + + + PREF_DIMENSIONS_ANGLE_UNITS + Angle measurement units + + + PREF_DIMENSIONS_SHOW_UNITS + Show units of measurement + PREF_ISOS PREF_ISOS @@ -4619,6 +4651,18 @@ STB_MEASURE_ANGLE 2つのラインまたはエッジ間の角度を計算 + + TOP_MANAGE_DIMENSIONS + Manage dimensions + + + MEN_MANAGE_DIMENSIONS + Manage dimensions + + + STB_MANAGE_DIMENSIONS + Manage measurement dimensions of an object + TOP_POP_AUTO_COLOR 自動色 @@ -5620,6 +5664,154 @@ Z + + MeasureGUI_ManageDimensionsDlg + + MANAGE_DIMENSIONS_TITLE + Manage dimensions + + + OBJECT_LABEL + Object + + + DIMENSIONS_GROUP + Dimensions + + + ADD_BTN + Add + + + REMOVE_BTN + Remove + + + SHOW_ALL_BTN + Show all + + + HIDE_ALL_BTN + Hide all + + + DISTANCE_ITEM + Distance + + + DIAMETER_ITEM + Diameter + + + ANGLE_ITEM + Angle + + + WRN_TITLE_UNSAVED + Unsaved changes + + + WRN_MSG_UNSAVED + The unsaved changes will be lost. +Do you want to continue? + + + + MeasureGUI_CreateDimensionDlg + + CREATE_DIMENSION_TITLE + Add dimension + + + DIMENSIONS + Dimensions + + + LENGTH + Length + + + DIAMETER + Diameter + + + ANGLE + Angle + + + ARGUMENTS + Arguments + + + EDGE_LENGTH + Edge length + + + TWO_POINTS + Two points + + + PARALLEL_EDGES + Parallel edges + + + TWO_EDGES + Two edges + + + THREE_POINTS + Three points + + + EDGE + Edge + + + EDGE_1 + Edge 1 + + + EDGE_2 + Edge 2 + + + POINT_1 + Point 1 + + + POINT_2 + Point 2 + + + POINT_3 + Point 3 + + + OBJECT + Object + + + NAME_LENGTH + Length + + + NAME_DIAMETER + Diameter + + + NAME_ANGLE + Angle + + + WARNING_TITLE_CANNOT_CREATE_DIMENSION + Can not create dimension + + + WARNING_MSG_INVALID_ARGUMENTS + The dimension can not be created for the specified arguments. +Please specify suitable arguments. + + OperationGUI_ChamferDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index bdf31b968..5e392c88f 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -633,6 +633,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam ) case GEOMOp::OpGetNonBlocks: // MENU MEASURE - Get NON BLOCKS case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS + case GEOMOp::OpManageDimensions: // MENU MEASURE - MANAGE DIMENSIONS libName = "MeasureGUI"; break; case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE @@ -1003,6 +1004,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpBoundingBox, "BND_BOX" ); createGeomAction( GEOMOp::OpMinDistance, "MIN_DIST" ); createGeomAction( GEOMOp::OpAngle, "MEASURE_ANGLE" ); + createGeomAction( GEOMOp::OpManageDimensions, "MANAGE_DIMENSIONS" ); createGeomAction( GEOMOp::OpTolerance, "TOLERANCE" ); createGeomAction( GEOMOp::OpWhatIs, "WHAT_IS" ); @@ -1261,9 +1263,10 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( separator(), measurId, -1 ); int dimId = createMenu( tr( "MEN_DIMENSIONS" ), measurId, -1 ); - createMenu( GEOMOp::OpBoundingBox, dimId, -1 ); - createMenu( GEOMOp::OpMinDistance, dimId, -1 ); - createMenu( GEOMOp::OpAngle, dimId, -1 ); + createMenu( GEOMOp::OpBoundingBox, dimId, -1 ); + createMenu( GEOMOp::OpMinDistance, dimId, -1 ); + createMenu( GEOMOp::OpAngle, dimId, -1 ); + createMenu( GEOMOp::OpManageDimensions, dimId, -1 ); createMenu( separator(), measurId, -1 ); createMenu( GEOMOp::OpTolerance, measurId, -1 ); @@ -2352,6 +2355,47 @@ void GeometryGUI::createPreferences() addPreference( tr( "PREF_AUTO_BRING_TO_FRONT" ), genGroup, LightApp_Preferences::Bool, "Geometry", "auto_bring_to_front" ); + int aDimGroupId = addPreference( tr( "PREF_DIMENSIONS" ), tabId ); + setPreferenceProperty( aDimGroupId, "columns", 2 ); + + addPreference( tr( "PREF_DIMENSIONS_COLOR" ), aDimGroupId, + LightApp_Preferences::Color, "Geometry", "dimensions_color" ); + + int aDimLineWidthId = addPreference( tr( "PREF_DIMENSIONS_LINE_WIDTH" ), aDimGroupId, + LightApp_Preferences::IntSpin, "Geometry", "dimensions_line_width" ); + + setPreferenceProperty( aDimLineWidthId, "min", 1 ); + setPreferenceProperty( aDimLineWidthId, "max", 5 ); + + addPreference( tr( "PREF_DIMENSIONS_FONT_HEIGHT" ), aDimGroupId, + LightApp_Preferences::DblSpin, "Geometry", "dimensions_font_height" ); + + addPreference( tr( "PREF_DIMENSIONS_ARROW_LENGTH" ), aDimGroupId, + LightApp_Preferences::IntSpin, "Geometry", "dimensions_arrow_length" ); + + int aLengthUnitsId = addPreference( tr( "PREF_DIMENSIONS_LENGTH_UNITS" ), aDimGroupId, + LightApp_Preferences::Selector, "Geometry", "dimensions_length_units" ); + + int anAngUnitsId = addPreference( tr( "PREF_DIMENSIONS_ANGLE_UNITS" ), aDimGroupId, + LightApp_Preferences::Selector, "Geometry", "dimensions_angle_units" ); + + addPreference( tr( "PREF_DIMENSIONS_SHOW_UNITS" ), aDimGroupId, + LightApp_Preferences::Bool, "Geometry", "dimensions_show_units" ); + + QStringList aListOfLengthUnits; + aListOfLengthUnits << "m"; + aListOfLengthUnits << "cm"; + aListOfLengthUnits << "mm"; + aListOfLengthUnits << "in."; + aListOfLengthUnits << "ft."; + + QStringList aListOfAngUnits; + aListOfAngUnits << "rad"; + aListOfAngUnits << "deg"; + + setPreferenceProperty( aLengthUnitsId, "strings", aListOfLengthUnits ); + setPreferenceProperty( anAngUnitsId, "strings", aListOfAngUnits ); + int isoGroup = addPreference( tr( "PREF_ISOS" ), tabId ); setPreferenceProperty( isoGroup, "columns", 2 ); int isoU = addPreference( tr( "PREF_ISOS_U" ), isoGroup, @@ -2561,6 +2605,46 @@ void GeometryGUI::preferencesChanged( const QString& section, const QString& par aDisplayer.UpdateColorScale( anIsRedisplayFieldSteps, true ); } } + else if ( param == QString("dimensions_color") || + param == QString("dimensions_line_width") || + param == QString("dimensions_font_height") || + param == QString("dimensions_arrow_length") || + param == QString("dimensions_show_units") || + param == QString("dimensions_length_units") || + param == QString("dimensions_angle_units") ) + { + SalomeApp_Application* anApp = getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + GEOM_Displayer aDisplayer( aStudy ); + + ViewManagerList aVMs; + anApp->viewManagers( OCCViewer_Viewer::Type(), aVMs ); + ViewManagerList::Iterator anIt = aVMs.begin(); + for ( ; anIt != aVMs.end(); ++anIt ) + { + SOCC_Viewer* aViewer = dynamic_cast( (*anIt)->getViewModel() ); + if ( !aViewer ) + { + continue; + } + + SALOME_ListIO aVisible; + aViewer->GetVisible( aVisible ); + aDisplayer.Redisplay( aVisible, false, aViewer ); + } + + aDisplayer.UpdateViewer(); + } } } diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 965e9e445..d04768985 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -188,6 +188,7 @@ namespace GEOMOp { OpPointCoordinates = 5011, // MENU MEASURES - POINT COORDINATES OpCheckSelfInters = 5012, // MENU MEASURES - CHECK SELF INTERSECTIONS OpGetNonBlocks = 5013, // MENU MEASURES - GET NON BLOCKS + OpManageDimensions = 5014, // MENU MEASURES - MANAGE DIMENSIONS // GroupGUI --------------------//-------------------------------- OpGroupCreate = 6000, // MENU GROUP - CREATE OpGroupEdit = 6001, // MENU GROUP - EDIT diff --git a/src/GEOMUtils/CMakeLists.txt b/src/GEOMUtils/CMakeLists.txt index 7402b7d54..49b348a47 100755 --- a/src/GEOMUtils/CMakeLists.txt +++ b/src/GEOMUtils/CMakeLists.txt @@ -30,6 +30,7 @@ INCLUDE_DIRECTORIES( # additional preprocessor / compiler flags ADD_DEFINITIONS( ${CAS_DEFINITIONS} + ${OMNIORB_DEFINITIONS} ) # libraries to link to @@ -40,7 +41,10 @@ SET(_link_LIBRARIES ${CAS_TKG3d} ${CAS_TKV3d} ${CAS_TKGeomBase} + ${GUI_SalomeApp} ${KERNEL_SALOMELocalTrace} + ${KERNEL_SalomeDS} + ${KERNEL_SalomeDSClient} ) # --- headers --- @@ -48,12 +52,14 @@ SET(_link_LIBRARIES SET(GEOMUtils_HEADERS GEOMUtils.hxx GEOMUtils_Hatcher.hxx + GEOMUtils_DimensionProperty.hxx ) # --- sources --- SET(GEOMUtils_SOURCES GEOMUtils.cxx GEOMUtils_Hatcher.cxx + GEOMUtils_DimensionProperty.cxx ) # --- rules --- diff --git a/src/GEOMUtils/GEOMUtils_DimensionProperty.cxx b/src/GEOMUtils/GEOMUtils_DimensionProperty.cxx new file mode 100644 index 000000000..e9089a6dd --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_DimensionProperty.cxx @@ -0,0 +1,918 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMUTILS : Utilities for Geometry component +// File : GEOMUtils_DimensionProperty.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// + +// GEOMUtils includes +#include "GEOMUtils_DimensionProperty.hxx" + +// OCCT includes +#include +#include + +//================================================================================= +// function : Length::Init +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Length::Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aFromLCS; + aFromLCS.SetTransformation( gp_Ax3(), theLCS ); + + FirstPoint = theIO->FirstPoint().Transformed( aFromLCS ); + SecondPoint = theIO->SecondPoint().Transformed( aFromLCS ); + Plane = theIO->GetPlane().Transformed( aFromLCS ); + Flyout = theIO->GetFlyout(); + TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); + TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); +} + +//================================================================================= +// function : Length::Update +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Length::Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aToLCS; + aToLCS.SetTransformation( theLCS, gp_Ax3() ); + + gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS ); + gp_Pnt aPoint2 = SecondPoint.Transformed( aToLCS ); + gp_Pln aPlane = Plane.Transformed( aToLCS ); + + theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPlane ); + theIO->SetFlyout( Flyout ); + + Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); + aStyle->SetTextHorizontalPosition( TextHPos ); + aStyle->SetTextVerticalPosition( TextVPos ); + theIO->SetDimensionAspect( aStyle ); +} + +//================================================================================= +// function : Length::operator == +// purpose : +//================================================================================= +bool GEOMUtils_DimensionProperty::Length::operator == (const Length& theOther) const +{ + if ( FirstPoint.X() != theOther.FirstPoint.X() + || FirstPoint.Y() != theOther.FirstPoint.Y() + || FirstPoint.Z() != theOther.FirstPoint.Z() + || SecondPoint.X() != theOther.SecondPoint.X() + || SecondPoint.Y() != theOther.SecondPoint.Y() + || SecondPoint.Z() != theOther.SecondPoint.Z() ) + { + return false; + } + + if ( Plane.Location().X() != theOther.Plane.Location().X() + || Plane.Location().Y() != theOther.Plane.Location().Y() + || Plane.Location().Z() != theOther.Plane.Location().Z() + || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X() + || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y() + || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() ) + { + return false; + } + + if ( Flyout != theOther.Flyout + || TextHPos != theOther.TextHPos + || TextVPos != theOther.TextVPos ) + { + return false; + } + + return true; +} + +//================================================================================= +// function : Diameter::Init +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Diameter::Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aFromLCS; + aFromLCS.SetTransformation( gp_Ax3(), theLCS ); + + Circle = theIO->Circle().Transformed( aFromLCS ); + Plane = theIO->GetPlane().Transformed( aFromLCS ); + Flyout = theIO->GetFlyout(); + TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); + TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); +} + +//================================================================================= +// function : Diameter::Update +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Diameter::Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aToLCS; + aToLCS.SetTransformation( theLCS, gp_Ax3() ); + + gp_Circ aCircle = Circle.Transformed( aToLCS ); + gp_Pln aPlane = Plane.Transformed( aToLCS ); + + Standard_Boolean isParallel = + aCircle.Axis().Direction().IsParallel( aPlane.Axis().Direction(), Precision::Angular() ); + + if ( isParallel ) + { + theIO->UnsetCustomPlane(); + theIO->SetMeasuredGeometry( aCircle ); + } + else + { + theIO->SetCustomPlane( aPlane ); + theIO->SetMeasuredGeometry( aCircle ); + } + + theIO->SetFlyout( Flyout ); + + Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); + aStyle->SetTextHorizontalPosition( TextHPos ); + aStyle->SetTextVerticalPosition( TextVPos ); + theIO->SetDimensionAspect( aStyle ); +} + +//================================================================================= +// function : Diameter::operator == +// purpose : +//================================================================================= +bool GEOMUtils_DimensionProperty::Diameter::operator == (const Diameter& theOther) const +{ + if ( Circle.Location().X() != theOther.Circle.Location().X() + || Circle.Location().Y() != theOther.Circle.Location().Y() + || Circle.Location().Z() != theOther.Circle.Location().Z() + || Circle.Axis().Direction().X() != theOther.Circle.Axis().Direction().X() + || Circle.Axis().Direction().Y() != theOther.Circle.Axis().Direction().Y() + || Circle.Axis().Direction().Z() != theOther.Circle.Axis().Direction().Z() + || Circle.XAxis().Direction().X() != theOther.Circle.XAxis().Direction().X() + || Circle.XAxis().Direction().Y() != theOther.Circle.XAxis().Direction().Y() + || Circle.XAxis().Direction().Z() != theOther.Circle.XAxis().Direction().Z() + || Circle.Radius() != theOther.Circle.Radius() ) + { + return false; + } + + if ( Plane.Location().X() != theOther.Plane.Location().X() + || Plane.Location().Y() != theOther.Plane.Location().Y() + || Plane.Location().Z() != theOther.Plane.Location().Z() + || Plane.Axis().Direction().X() != theOther.Plane.Axis().Direction().X() + || Plane.Axis().Direction().Y() != theOther.Plane.Axis().Direction().Y() + || Plane.Axis().Direction().Z() != theOther.Plane.Axis().Direction().Z() ) + { + return false; + } + + if ( Flyout != theOther.Flyout + || TextHPos != theOther.TextHPos + || TextVPos != theOther.TextVPos ) + { + return false; + } + + return true; +} + +//================================================================================= +// function : Angle::Init +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Angle::Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aFromLCS; + aFromLCS.SetTransformation( gp_Ax3(), theLCS ); + + FirstPoint = theIO->FirstPoint().Transformed( aFromLCS ); + SecondPoint = theIO->SecondPoint().Transformed( aFromLCS ); + CenterPoint = theIO->CenterPoint().Transformed( aFromLCS ); + Flyout = theIO->GetFlyout(); + TextHPos = theIO->DimensionAspect()->TextHorizontalPosition(); + TextVPos = theIO->DimensionAspect()->TextVerticalPosition(); +} + +//================================================================================= +// function : Angle::Update +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Angle::Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS ) +{ + gp_Trsf aToLCS; + aToLCS.SetTransformation( theLCS, gp_Ax3() ); + + gp_Pnt aPoint1 = FirstPoint.Transformed( aToLCS ); + gp_Pnt aPoint2 = CenterPoint.Transformed( aToLCS ); + gp_Pnt aPoint3 = SecondPoint.Transformed( aToLCS ); + + theIO->SetMeasuredGeometry( aPoint1, aPoint2, aPoint3 ); + theIO->SetFlyout( Flyout ); + + Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); + aStyle->SetTextHorizontalPosition( TextHPos ); + aStyle->SetTextVerticalPosition( TextVPos ); + theIO->SetDimensionAspect( aStyle ); +} + +//================================================================================= +// function : Angle::operator == +// purpose : +//================================================================================= +bool GEOMUtils_DimensionProperty::Angle::operator == (const Angle& theOther) const +{ + if ( FirstPoint.X() != theOther.FirstPoint.X() + || FirstPoint.Y() != theOther.FirstPoint.Y() + || FirstPoint.Z() != theOther.FirstPoint.Z() + || SecondPoint.X() != theOther.SecondPoint.X() + || SecondPoint.Y() != theOther.SecondPoint.Y() + || SecondPoint.Z() != theOther.SecondPoint.Z() + || CenterPoint.X() != theOther.CenterPoint.X() + || CenterPoint.Y() != theOther.CenterPoint.Y() + || CenterPoint.Z() != theOther.CenterPoint.Z() ) + { + return false; + } + + if ( Flyout != theOther.Flyout + || TextHPos != theOther.TextHPos + || TextVPos != theOther.TextVPos ) + { + return false; + } + + return true; +} + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +GEOMUtils_DimensionProperty::GEOMUtils_DimensionProperty() +{ +} + +//================================================================================= +// function : Copy constructor +// purpose : +//================================================================================= +GEOMUtils_DimensionProperty::GEOMUtils_DimensionProperty( const GEOMUtils_DimensionProperty& theOther ) +{ + const VectorOfVisibility& aOtherVis = theOther.myVisibility; + const VectorOfNames& aOtherNames = theOther.myNames; + const VectorOfRecords& aOtherRecords = theOther.myRecords; + + VectorOfVisibility::const_iterator aVisIt = aOtherVis.constBegin(); + VectorOfNames::const_iterator aNamesIt = aOtherNames.constBegin(); + VectorOfRecords::const_iterator aRecordIt = aOtherRecords.constBegin(); + for ( ; aRecordIt != aOtherRecords.constEnd(); ++aVisIt, ++aNamesIt, ++aRecordIt ) + { + RecordPtr aNewRecord; + const RecordPtr& aRecord = *aRecordIt; + switch( aRecord->Type() ) + { + case DimensionType_Length : + aNewRecord = RecordPtr( new Length( *aRecord->AsLength() ) ); + break; + + case DimensionType_Diameter : + aNewRecord = RecordPtr( new Diameter( *aRecord->AsDiameter() ) ); + break; + + case DimensionType_Angle : + aNewRecord = RecordPtr( new Angle( *aRecord->AsAngle() ) ); + break; + } + + myVisibility.append( *aVisIt ); + myNames.append( *aNamesIt ); + myRecords.append( aNewRecord ); + } +} + +//================================================================================= +// function : Destructor +// purpose : +//================================================================================= +GEOMUtils_DimensionProperty::~GEOMUtils_DimensionProperty() +{ +} + +//================================================================================= +// function : operator QVariant() +// purpose : +//================================================================================= +GEOMUtils_DimensionProperty::operator QVariant() +{ + QVariant aQVariant; + aQVariant.setValue( *this ); + return aQVariant; +} + +//================================================================================= +// function : operator == +// purpose : +//================================================================================= +bool GEOMUtils_DimensionProperty::operator == (const GEOMUtils_DimensionProperty& theOther) const +{ + if ( myVisibility.size() != theOther.myVisibility.size() + || myNames.size() != theOther.myNames.size() + || myRecords.size() != theOther.myRecords.size() ) + { + return false; + } + + for ( int it = 0; it < myRecords.size(); ++it ) + { + if ( myVisibility[it] != theOther.myVisibility[it] ) + { + return false; + } + + if ( myNames[it] != theOther.myNames[it] ) + { + return false; + } + + const RecordPtr& aRecord = myRecords[it]; + const RecordPtr& aOtherRecord = theOther.myRecords[it]; + if ( aRecord->Type() != aOtherRecord->Type() ) + { + return false; + } + + switch ( aRecord->Type() ) + { + case DimensionType_Length: + if ( (*aRecord->AsLength()) != (*aOtherRecord->AsLength()) ) + { + return false; + } + break; + + case DimensionType_Diameter: + if ( (*aRecord->AsDiameter()) != (*aOtherRecord->AsDiameter()) ) + { + return false; + } + break; + + case DimensionType_Angle: + if ( (*aRecord->AsAngle()) != (*aOtherRecord->AsAngle()) ) + { + return false; + } + break; + } + } + + return true; +} + +//================================================================================= +// function : GetNumber +// purpose : +//================================================================================= +int GEOMUtils_DimensionProperty::GetNumber() const +{ + return myRecords.size(); +} + +//================================================================================= +// function : AddRecord +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS ) +{ + RecordPtr aNewRecord; + + int aType = TypeFromIO( theIO ); + + switch ( aType ) + { + case DimensionType_Length : + { + Handle(AIS_LengthDimension) aLength = + Handle(AIS_LengthDimension)::DownCast( theIO ); + + aNewRecord = RecordPtr( new Length() ); + aNewRecord->AsLength()->Init( aLength, theLCS ); + break; + } + + case DimensionType_Diameter : + { + Handle(AIS_DiameterDimension) aDiam = + Handle(AIS_DiameterDimension)::DownCast( theIO ); + + aNewRecord = RecordPtr( new Diameter() ); + aNewRecord->AsDiameter()->Init( aDiam, theLCS ); + break; + } + + case DimensionType_Angle : + { + Handle(AIS_AngleDimension) anAngle = + Handle(AIS_AngleDimension)::DownCast( theIO ); + + aNewRecord = RecordPtr( new Angle() ); + aNewRecord->AsAngle()->Init( anAngle, theLCS ); + } + } + + myVisibility.append( true ); + myNames.append( QString() ); + myRecords.append( aNewRecord ); +} + +//================================================================================= +// function : AddRecord +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::AddRecord( const RecordPtr& theRecord ) +{ + myVisibility.append( true ); + myNames.append( QString() ); + myRecords.append( theRecord ); +} + +//================================================================================= +// function : RemoveRecord +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::RemoveRecord( const int theIndex ) +{ + myRecords.remove( theIndex ); +} + +//================================================================================= +// function : Clear +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::Clear() +{ + myRecords.clear(); +} + +//================================================================================= +// function : SetRecord +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::SetRecord( const int theIndex, + const Handle(AIS_Dimension)& theIO, + const gp_Ax3& theLCS ) +{ + int aType = TypeFromIO( theIO ); + + RecordPtr& aChangeRecord = myRecords[theIndex]; + + switch ( aType ) + { + case DimensionType_Length : + { + Handle(AIS_LengthDimension) aLength = + Handle(AIS_LengthDimension)::DownCast( theIO ); + + aChangeRecord = RecordPtr( new Length() ); + aChangeRecord->AsLength()->Init( aLength, theLCS ); + break; + } + + case DimensionType_Diameter : + { + Handle(AIS_DiameterDimension) aDiam = + Handle(AIS_DiameterDimension)::DownCast( theIO ); + + aChangeRecord = RecordPtr( new Diameter() ); + aChangeRecord->AsDiameter()->Init( aDiam, theLCS ); + break; + } + + case DimensionType_Angle : + { + Handle(AIS_AngleDimension) anAngle = + Handle(AIS_AngleDimension)::DownCast( theIO ); + + aChangeRecord = RecordPtr( new Angle() ); + aChangeRecord->AsAngle()->Init( anAngle, theLCS ); + } + } +} + +//================================================================================= +// function : SetRecord +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::SetRecord( const int theIndex, const RecordPtr& theRecord ) +{ + myRecords[theIndex] = theRecord; +} + +//================================================================================= +// function : GetRecord +// purpose : +//================================================================================= +const GEOMUtils_DimensionProperty::RecordPtr& GEOMUtils_DimensionProperty::GetRecord( const int theIndex ) const +{ + return myRecords[theIndex]; +} + +//================================================================================= +// function : IsVisible +// purpose : +//================================================================================= +bool GEOMUtils_DimensionProperty::IsVisible( const int theIndex ) const +{ + return myVisibility[theIndex]; +} + +//================================================================================= +// function : SetVisible +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::SetVisible( const int theIndex, const bool theIsVisible ) +{ + myVisibility[theIndex] = theIsVisible; +} + +//================================================================================= +// function : GetName +// purpose : +//================================================================================= +QString GEOMUtils_DimensionProperty::GetName( const int theIndex ) const +{ + return myNames[theIndex]; +} + +//================================================================================= +// function : SetName +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::SetName( const int theIndex, const QString &theName ) +{ + myNames[theIndex] = theName; +} + +//================================================================================= +// function : GetType +// purpose : +//================================================================================= +int GEOMUtils_DimensionProperty::GetType( const int theIndex ) const +{ + return myRecords[theIndex]->Type(); +} + +//================================================================================= +// function : LoadFromAttribute +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::LoadFromAttribute( SalomeApp_Study* theStudy, + const std::string& theEntry ) +{ + Clear(); + + _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry ); + if ( !aSObj ) + { + return; + } + + _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder(); + + _PTR(GenericAttribute) aSeekAtt; + _PTR(AttributeTableOfReal) aRecordsAtt; + + if ( !aSObj->FindAttribute( aSeekAtt, "AttributeTableOfReal" ) ) + { + return; + } + + aRecordsAtt = aSeekAtt; + + for ( int aRecordIt = 1; aRecordIt <= aRecordsAtt->GetNbColumns(); ++aRecordIt ) + { + std::vector aPacked = aRecordsAtt->GetColumn( aRecordIt ); + + RecordPtr aRecord; + + QString aName( aRecordsAtt->GetColumnTitle( aRecordIt ).c_str() ); + + // unpack records + int it = 0; + + // visibility [0] + bool isVisible = (bool) aPacked[it++]; + + // type [1] + int aType = (int) aPacked[it++]; + + switch (aType) + { + case DimensionType_Length : + { + Length* aLength = new Length; + + // custom plane [2,3,4,5] + Standard_Real A = (Standard_Real) aPacked[it++]; + Standard_Real B = (Standard_Real) aPacked[it++]; + Standard_Real C = (Standard_Real) aPacked[it++]; + Standard_Real D = (Standard_Real) aPacked[it++]; + aLength->Plane = gp_Pln( A, B, C, D ); + + // flyout size [6] + aLength->Flyout = (Standard_Real) aPacked[it++]; + + // text flags [7,8] + aLength->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; + aLength->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; + + // point 1 [9,10,11] + Standard_Real aFirstX = aPacked[it++]; + Standard_Real aFirstY = aPacked[it++]; + Standard_Real aFirstZ = aPacked[it++]; + aLength->FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ ); + + // point 2 [12,13,14] + Standard_Real aSecondX = aPacked[it++]; + Standard_Real aSecondY = aPacked[it++]; + Standard_Real aSecondZ = aPacked[it++]; + aLength->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ ); + + aRecord = RecordPtr( aLength ); + break; + } + + case DimensionType_Diameter : + { + Diameter* aDiam = new Diameter; + + // custom plane [2,3,4,5] + Standard_Real A = (Standard_Real) aPacked[it++]; + Standard_Real B = (Standard_Real) aPacked[it++]; + Standard_Real C = (Standard_Real) aPacked[it++]; + Standard_Real D = (Standard_Real) aPacked[it++]; + aDiam->Plane = gp_Pln( A, B, C, D ); + + // flyout size [6] + aDiam->Flyout = (Standard_Real) aPacked[it++]; + + // text flags [7,8] + aDiam->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; + aDiam->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; + + // circle location [9,10,11] + Standard_Real aLocX = (Standard_Real) aPacked[it++]; + Standard_Real aLocY = (Standard_Real) aPacked[it++]; + Standard_Real aLocZ = (Standard_Real) aPacked[it++]; + + // circle normal [12,13,14] + Standard_Real aNormX = (Standard_Real) aPacked[it++]; + Standard_Real aNormY = (Standard_Real) aPacked[it++]; + Standard_Real aNormZ = (Standard_Real) aPacked[it++]; + + // x-direction [15,16,17] + Standard_Real aXDirX = (Standard_Real) aPacked[it++]; + Standard_Real aXDirY = (Standard_Real) aPacked[it++]; + Standard_Real aXDirZ = (Standard_Real) aPacked[it++]; + + // radius [18] + Standard_Real aRadius = (Standard_Real) aPacked[it++]; + + gp_Ax2 anAx( gp_Pnt( aLocX, aLocY, aLocZ ), + gp_Dir( aNormX, aNormY, aNormZ ), + gp_Dir( aXDirX, aXDirY, aXDirZ ) ); + + aDiam->Circle = gp_Circ( anAx, aRadius ); + + aRecord = RecordPtr( aDiam ); + break; + } + + case DimensionType_Angle : + { + Angle* anAngle = new Angle; + + // flyout [2] + anAngle->Flyout = (Standard_Real) aPacked[it++]; + + // text flags [3,4] + anAngle->TextHPos = (Prs3d_DimensionTextHorizontalPosition)(int)aPacked[it++]; + anAngle->TextVPos = (Prs3d_DimensionTextVerticalPosition) (int)aPacked[it++]; + + // point 1 [5,6,7] + Standard_Real aFirstX = (Standard_Real) aPacked[it++]; + Standard_Real aFirstY = (Standard_Real) aPacked[it++]; + Standard_Real aFirstZ = (Standard_Real) aPacked[it++]; + + // point 2 [8,9,10] + Standard_Real aSecondX = (Standard_Real) aPacked[it++]; + Standard_Real aSecondY = (Standard_Real) aPacked[it++]; + Standard_Real aSecondZ = (Standard_Real) aPacked[it++]; + + // center [11,12,13] + Standard_Real aCenterX = (Standard_Real) aPacked[it++]; + Standard_Real aCenterY = (Standard_Real) aPacked[it++]; + Standard_Real aCenterZ = (Standard_Real) aPacked[it++]; + + // points point 1 [4-6], point 2 [7-9], center [10-12] + anAngle->FirstPoint = gp_Pnt( aFirstX, aFirstY, aFirstZ ); + anAngle->SecondPoint = gp_Pnt( aSecondX, aSecondY, aSecondZ ); + anAngle->CenterPoint = gp_Pnt( aCenterX, aCenterY, aCenterZ ); + + aRecord = RecordPtr( anAngle ); + break; + } + } + + myVisibility.append( isVisible ); + myNames.append( aName ); + myRecords.append( aRecord ); + } +} + +//================================================================================= +// function : SaveToAttribute +// purpose : +//================================================================================= +void GEOMUtils_DimensionProperty::SaveToAttribute( SalomeApp_Study *theStudy, + const std::string &theEntry ) +{ + _PTR(SObject) aSObj = theStudy->studyDS()->FindObjectID( theEntry ); + if ( !aSObj ) + { + return; + } + + _PTR(StudyBuilder) aBuilder = theStudy->studyDS()->NewBuilder(); + + _PTR(AttributeTableOfReal) aRecordsAtt; + + aRecordsAtt = aBuilder->FindOrCreateAttribute( aSObj, "AttributeTableOfReal" ); + aRecordsAtt->SetNbColumns( 0 ); + + for ( int it = 0; it < myRecords.size(); ++it ) + { + bool aVisibility = myVisibility[it]; + QString& aName = myNames[it]; + RecordPtr& aRecord = myRecords[it]; + + std::vector aPacked; + + // visibility [0] + aPacked.push_back( (double) aVisibility ); + + // type [1] + aPacked.push_back( (double) aRecord->Type() ); + + switch ( aRecord->Type() ) + { + case DimensionType_Length: + { + Length* aProps = aRecord->AsLength(); + + // custom plane [2,3,4,5] + Standard_Real A, B, C, D; + aProps->Plane.Coefficients( A, B, C, D ); + aPacked.push_back( (double) A ); + aPacked.push_back( (double) B ); + aPacked.push_back( (double) C ); + aPacked.push_back( (double) D ); + + // flyout size [6] + aPacked.push_back( (double) aProps->Flyout ); + + // text flags [7,8] + aPacked.push_back( (double) aProps->TextHPos ); + aPacked.push_back( (double) aProps->TextVPos ); + + // point 1 [9,10,11] + aPacked.push_back( (double) aProps->FirstPoint.X() ); + aPacked.push_back( (double) aProps->FirstPoint.Y() ); + aPacked.push_back( (double) aProps->FirstPoint.Z() ); + + // point 2 [12,13,14] + aPacked.push_back( (double) aProps->SecondPoint.X() ); + aPacked.push_back( (double) aProps->SecondPoint.Y() ); + aPacked.push_back( (double) aProps->SecondPoint.Z() ); + break; + } + + case DimensionType_Diameter: + { + Diameter* aProps = aRecord->AsDiameter(); + + // custom plane [2,3,4,5] + Standard_Real A, B, C, D; + aProps->Plane.Coefficients( A, B, C, D ); + aPacked.push_back( (double) A ); + aPacked.push_back( (double) B ); + aPacked.push_back( (double) C ); + aPacked.push_back( (double) D ); + + // flyout size [6] + aPacked.push_back( (double) aProps->Flyout ); + + // text flags [7,8] + aPacked.push_back( (double) aProps->TextHPos ); + aPacked.push_back( (double) aProps->TextVPos ); + + // circle location [9,10,11] + aPacked.push_back( (double) aProps->Circle.Location().X() ); + aPacked.push_back( (double) aProps->Circle.Location().Y() ); + aPacked.push_back( (double) aProps->Circle.Location().Z() ); + + // circle normal [12,13,14] + aPacked.push_back( (double) aProps->Circle.Axis().Direction().X() ); + aPacked.push_back( (double) aProps->Circle.Axis().Direction().Y() ); + aPacked.push_back( (double) aProps->Circle.Axis().Direction().Z() ); + + // x-direction [15,16,17] + aPacked.push_back( (double) aProps->Circle.XAxis().Direction().X() ); + aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Y() ); + aPacked.push_back( (double) aProps->Circle.XAxis().Direction().Z() ); + + // radius [18] + aPacked.push_back( (double) aProps->Circle.Radius() ); + break; + } + + case DimensionType_Angle: + { + Angle* aProps = aRecord->AsAngle(); + + // flyout [2] + aPacked.push_back( (double) aProps->Flyout ); + + // text flags [3,4] + aPacked.push_back( (double) aProps->TextHPos ); + aPacked.push_back( (double) aProps->TextVPos ); + + // point 1 [5,6,7] + aPacked.push_back( (double) aProps->FirstPoint.X() ); + aPacked.push_back( (double) aProps->FirstPoint.Y() ); + aPacked.push_back( (double) aProps->FirstPoint.Z() ); + + // point 2 [8,9,10] + aPacked.push_back( (double) aProps->SecondPoint.X() ); + aPacked.push_back( (double) aProps->SecondPoint.Y() ); + aPacked.push_back( (double) aProps->SecondPoint.Z() ); + + // center [11,12,13] + aPacked.push_back( (double) aProps->CenterPoint.X() ); + aPacked.push_back( (double) aProps->CenterPoint.Y() ); + aPacked.push_back( (double) aProps->CenterPoint.Z() ); + break; + } + } + + aRecordsAtt->AddColumn( aPacked ); + aRecordsAtt->SetColumnTitle( it + 1, aName.toStdString() ); + } +} + +//================================================================================= +// function : TypeFromIO +// purpose : +//================================================================================= +int GEOMUtils_DimensionProperty::TypeFromIO( const Handle(AIS_Dimension)& theIO ) const +{ + if ( theIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) ) + { + return DimensionType_Length; + } + + if ( theIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) ) + { + return DimensionType_Diameter; + } + + if ( theIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) ) + { + return DimensionType_Angle; + } + + Standard_ProgramError::Raise( "unsupported dimension type" ); + + return 0; +} diff --git a/src/GEOMUtils/GEOMUtils_DimensionProperty.hxx b/src/GEOMUtils/GEOMUtils_DimensionProperty.hxx new file mode 100644 index 000000000..32b7adcb4 --- /dev/null +++ b/src/GEOMUtils/GEOMUtils_DimensionProperty.hxx @@ -0,0 +1,422 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMUTILS : Utilities for Geometry component +// File : GEOMUtils_DimensionProperty.hxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// + +#ifndef GEOMUTILS_DIMENSIONPROPERTY_HXX +#define GEOMUTILS_DIMENSIONPROPERTY_HXX + +// SUIT includes +#include + +// OCCT includes +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! + * \brief Utility class to unpack/pack dimension presentations as object property of study. + * + * Dimension presentations are store in relative coordinate system (LCS). + * To ensure that dimension is bound to the equal shape irrespectively of its location + * transformation. + * + * The record is a list of qvariant, containing packed dimension properties and its attributes: + * (name);(is_visible);(dimension type);(dimension property list); + * + * The following packing scheme is used to store dimension data: + * Length: (plane)[0-3] (flyout)[4] (text flags)[5-6] (p1)[7-9] (pnt2)[10-12] + * Diam: (plane)[0-3] (flyout)[4] (text flags)[5-6] (circle loc, xdir, ydir, rad)[7-16] + * Angle: (flyout)[0] (text flags)[1-2] (p1)[3-5] (p2)[6-8] (center)[9-11] + */ +class Standard_EXPORT GEOMUtils_DimensionProperty +{ +public: + + /*! + * \brief Type of packed presentation. + */ + enum DimensionType + { + DimensionType_Length, + DimensionType_Diameter, + DimensionType_Angle + }; + + /*! + * \brief Base class for pointer-optimized records storing. + */ + struct Length; + struct Diameter; + struct Angle; + struct Record + { + public: + Record( const DimensionType theType ) + : myType( theType ) + {} + + DimensionType Type() const + { + return myType; + } + + Length* AsLength() { return static_cast( this ); } + Diameter* AsDiameter() { return static_cast( this ); } + Angle* AsAngle() { return static_cast( this ); } + + private: + DimensionType myType; + }; + + /*! + * \brief Declaration of properties for length dimensions. + */ + struct Standard_EXPORT Length : public Record + { + Length() : + Record( DimensionType_Length ), + FirstPoint( gp::Origin() ), + SecondPoint( gp::Origin() ), + Plane( gp::XOY() ), + Flyout( 0.0 ), + TextHPos( Prs3d_DTHP_Fit ), + TextVPos( Prs3d_DTVP_Center ) + {} + + Length( const Length& theOther ) : + Record( DimensionType_Length ), + FirstPoint( theOther.FirstPoint ), + SecondPoint( theOther.SecondPoint ), + Plane( theOther.Plane ), + Flyout( theOther.Flyout ), + TextHPos( theOther.TextHPos ), + TextVPos( theOther.TextVPos ) + {} + + ~Length() {} + + /*! + * \brief Inits property fields from the passed length object. + * \param theIO [in] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Init( const Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Updates length object properties from the fields. + * \param theIO [in/out] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Update( Handle(AIS_LengthDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Overload comparsion. + */ + bool operator == (const Length &theOther) const; + bool operator != (const Length &theOther) const { return !(operator == (theOther)); } + + gp_Pnt FirstPoint; + gp_Pnt SecondPoint; + gp_Pln Plane; + double Flyout; + Prs3d_DimensionTextHorizontalPosition TextHPos; + Prs3d_DimensionTextVerticalPosition TextVPos; + }; + + /*! + * \brief Declaration of properties for diameter dimensions. + */ + struct Standard_EXPORT Diameter : public Record + { + Diameter() : + Record( DimensionType_Diameter ), + Plane( gp::XOY() ), + Flyout( 0.0 ), + TextHPos( Prs3d_DTHP_Fit ), + TextVPos( Prs3d_DTVP_Center ) + {} + + Diameter( const Diameter& theOther ) : + Record( DimensionType_Diameter ), + Circle( theOther.Circle ), + Plane( theOther.Plane ), + Flyout( theOther.Flyout ), + TextHPos( theOther.TextHPos ), + TextVPos( theOther.TextVPos ) + {} + + ~Diameter() {} + + /*! + * \brief Inits property fields from the passed length object. + * \param theIO [in] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Init( const Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Updates length object properties from the fields. + * \param theIO [in/out] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Update( Handle(AIS_DiameterDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Overload comparsion. + */ + bool operator == (const Diameter &theOther) const; + bool operator != (const Diameter &theOther) const { return !(operator == (theOther)); } + + gp_Circ Circle; + gp_Pln Plane; + double Flyout; + Prs3d_DimensionTextHorizontalPosition TextHPos; + Prs3d_DimensionTextVerticalPosition TextVPos; + }; + + /*! + * \brief Declaration of properties for angle dimensions. + */ + struct Standard_EXPORT Angle : public Record + { + Angle() : + Record( DimensionType_Angle ), + FirstPoint( gp::Origin() ), + SecondPoint( gp::Origin() ), + CenterPoint( gp::Origin() ), + Flyout( 0.0 ), + TextHPos( Prs3d_DTHP_Fit ), + TextVPos( Prs3d_DTVP_Center ) + {} + + Angle( const Angle& theOther ) : + Record( DimensionType_Angle ), + FirstPoint( theOther.FirstPoint ), + SecondPoint( theOther.SecondPoint ), + CenterPoint( theOther.CenterPoint ), + Flyout( theOther.Flyout ), + TextHPos( theOther.TextHPos ), + TextVPos( theOther.TextVPos ) + {} + + ~Angle() {} + + /*! + * \brief Inits property fields from the passed length object. + * \param theIO [in] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Init( const Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Updates length object properties from the fields. + * \param theIO [in/out] the interactive presentation. + * \param theLCS [in] the local coordiante system of parent object. + */ + void Update( Handle(AIS_AngleDimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Overload comparsion. + */ + bool operator == (const Angle &theOther) const; + bool operator != (const Angle &theOther) const { return !(operator == (theOther)); } + + gp_Pnt FirstPoint; + gp_Pnt SecondPoint; + gp_Pnt CenterPoint; + double Flyout; + Prs3d_DimensionTextHorizontalPosition TextHPos; + Prs3d_DimensionTextVerticalPosition TextVPos; + }; + + typedef QSharedPointer RecordPtr; + +public: + + /*! + * \brief Constructor. Inits empty property. + */ + GEOMUtils_DimensionProperty(); + + /*! + * \brief Copy constructor. + */ + GEOMUtils_DimensionProperty( const GEOMUtils_DimensionProperty& theOther ); + + /*! + * \brief Destructor. + */ + ~GEOMUtils_DimensionProperty(); + + /*! + * \brief Overload QVariant cast operator. + */ + operator QVariant(); + + /*! + * \brief Overload comparsion. + */ + bool operator == (const GEOMUtils_DimensionProperty &theOther) const; + +public: + + /*! + * \brief Returns number of dimension records. + */ + int GetNumber() const; + + /*! + * \brief Adds new record for the passed interactive object. Convenience method. + * \param theIO [in] the interactive dimension to append as new record. + * \param theLCS [in] the local coordinate system of parent object. + */ + void AddRecord( const Handle(AIS_Dimension)& theIO, const gp_Ax3& theLCS ); + + /*! + * \brief Adds new dimension record. + * \param theRecord [in] the record to add. + */ + void AddRecord( const RecordPtr& theRecord ); + + /*! + * \brief Update dimension record data. + * \param theIndex [in] the index of the record. + * \param theIO [in] the interactive dimension to update properties. + * \param theLCS [in] the local coordinate system of parent object. + */ + void SetRecord( const int theIndex, + const Handle(AIS_Dimension)& theIO, + const gp_Ax3& theLCS ); + + /*! + * \brief Update dimension record data. + * \param theIndex [in] the index of the dimension record. + * \param theRecord [in] the record to replace with. + */ + void SetRecord( const int theIndex, const RecordPtr& theRecord ); + + /*! + * \brief Access record by index. + * \param theIndex [in] the index of the dimension record. + */ + const RecordPtr& GetRecord( const int theIndex ) const; + + /*! + * \brief Removes record by its index. + * \param theIndex [in] the index of dimension record. + */ + void RemoveRecord( const int theIndex ); + + /*! + * \brief Clears property data. + */ + void Clear(); + +public: + + /*! + * \brief Returns visibility state of dimension record by its index. + * + * \param theIndex [in] the index of the dimension record. + */ + bool IsVisible( const int theIndex ) const; + + /*! + * \brief Changes visibility state of the dimension record. + * + * \param theIndex [in] the index of the dimension record. + * \param theIsVisible [in] the new visibility state. + */ + void SetVisible( const int theIndex, const bool theIsVisible ); + + /*! + * \brief Returns name of dimension record by its index. + * + * \param theIndex [in] the index of the dimension record. + */ + QString GetName( const int theIndex ) const; + + /*! + * \brief Changes name of dimension record. + * + * \param theIndex [in] the index of the dimension record. + * \param theName [in] the new name. + */ + void SetName( const int theIndex, const QString& theName ); + + /*! + * \brief Returns dimension type. + */ + int GetType( const int theIndex ) const; + +public: + + /*! + * \brief Loads properties data from attribute "AttributeTableOfReal". + * \param theStudy [in] the study. + * \param theEntry [in] the entry of GEOM object to operate with. + */ + void LoadFromAttribute( SalomeApp_Study* theStudy, const std::string& theEntry ); + + /*! + * \brief Saves properties data to attribute "AttributeTableOfReal". + * \param theStudy [in] the study. + * \param theEntry [in] the entry of GEOM object to operate with. + */ + void SaveToAttribute( SalomeApp_Study* theStudy, const std::string& theEntry ); + +private: + + /*! + * \brief Determines dimension type code. + */ + int TypeFromIO( const Handle(AIS_Dimension)& theIO ) const; + +private: + + typedef QVector VectorOfVisibility; + typedef QVector VectorOfNames; + typedef QVector VectorOfRecords; + +private: + + VectorOfVisibility myVisibility; + VectorOfNames myNames; + VectorOfRecords myRecords; +}; + +Q_DECLARE_METATYPE(GEOMUtils_DimensionProperty); + +#endif diff --git a/src/MeasureGUI/CMakeLists.txt b/src/MeasureGUI/CMakeLists.txt index 809520ee8..2c6a39430 100755 --- a/src/MeasureGUI/CMakeLists.txt +++ b/src/MeasureGUI/CMakeLists.txt @@ -41,6 +41,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/DlgRef ${PROJECT_BINARY_DIR}/src/DlgRef ${PROJECT_SOURCE_DIR}/src/GEOMAlgo + ${PROJECT_SOURCE_DIR}/src/GEOMUtils ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) @@ -55,6 +56,7 @@ ADD_DEFINITIONS( # libraries to link to SET(_link_LIBRARIES GEOMBase + GEOMUtils ) # --- resources --- @@ -67,7 +69,11 @@ SET(_uic_files MeasureGUI_1Sel1TextView_QTD.ui MeasureGUI_1Sel3LineEdit_QTD.ui MeasureGUI_1Sel6LineEdit_QTD.ui + MeasureGUI_1Sel_Frame_QTD.ui + MeasureGUI_1TreeWidget_4Button_QTD.ui MeasureGUI_2Sel1LineEdit_QTD.ui + MeasureGUI_2Sel_Frame_QTD.ui + MeasureGUI_3Sel_Frame_QTD.ui MeasureGUI_SkeletonBox_QTD.ui ) @@ -91,6 +97,11 @@ SET(MeasureGUI_HEADERS MeasureGUI_GetNonBlocksDlg.h MeasureGUI_CheckSelfIntersectionsDlg.h MeasureGUI_PointDlg.h + MeasureGUI_ManageDimensionsDlg.h + MeasureGUI_CreateDimensionDlg.h + MeasureGUI_DimensionCreateTool.h + MeasureGUI_DimensionInteractor.h + MeasureGUI_DimensionFilter.h ) # header files / to be processed by moc @@ -111,6 +122,9 @@ SET(_moc_HEADERS MeasureGUI_GetNonBlocksDlg.h MeasureGUI_CheckSelfIntersectionsDlg.h MeasureGUI_PointDlg.h + MeasureGUI_ManageDimensionsDlg.h + MeasureGUI_CreateDimensionDlg.h + MeasureGUI_DimensionInteractor.h ) # header files / uic wrappings @@ -139,6 +153,11 @@ SET(MeasureGUI_SOURCES MeasureGUI_GetNonBlocksDlg.cxx MeasureGUI_CheckSelfIntersectionsDlg.cxx MeasureGUI_PointDlg.cxx + MeasureGUI_ManageDimensionsDlg.cxx + MeasureGUI_CreateDimensionDlg.cxx + MeasureGUI_DimensionCreateTool.cxx + MeasureGUI_DimensionInteractor.cxx + MeasureGUI_DimensionFilter.cxx ${_moc_SOURCES} ${_uic_files} ) diff --git a/src/MeasureGUI/MeasureGUI.cxx b/src/MeasureGUI/MeasureGUI.cxx index 435a92a9f..e079e74bc 100644 --- a/src/MeasureGUI/MeasureGUI.cxx +++ b/src/MeasureGUI/MeasureGUI.cxx @@ -31,20 +31,21 @@ #include #include -#include "MeasureGUI_PropertiesDlg.h" // Method PROPERTIES -#include "MeasureGUI_CenterMassDlg.h" // Method CENTER MASS -#include "MeasureGUI_NormaleDlg.h" // Method NORMALE -#include "MeasureGUI_InertiaDlg.h" // Method INERTIA -#include "MeasureGUI_BndBoxDlg.h" // Method BNDBOX -#include "MeasureGUI_DistanceDlg.h" // Method DISTANCE -#include "MeasureGUI_AngleDlg.h" // Method ANGLE -#include "MeasureGUI_MaxToleranceDlg.h" // Method MAXTOLERANCE -#include "MeasureGUI_WhatisDlg.h" // Method WHATIS -#include "MeasureGUI_CheckShapeDlg.h" // Method CHECKSHAPE -#include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND -#include "MeasureGUI_GetNonBlocksDlg.h" // Method GET NON BLOCKS +#include "MeasureGUI_PropertiesDlg.h" // Method PROPERTIES +#include "MeasureGUI_CenterMassDlg.h" // Method CENTER MASS +#include "MeasureGUI_NormaleDlg.h" // Method NORMALE +#include "MeasureGUI_InertiaDlg.h" // Method INERTIA +#include "MeasureGUI_BndBoxDlg.h" // Method BNDBOX +#include "MeasureGUI_DistanceDlg.h" // Method DISTANCE +#include "MeasureGUI_AngleDlg.h" // Method ANGLE +#include "MeasureGUI_MaxToleranceDlg.h" // Method MAXTOLERANCE +#include "MeasureGUI_WhatisDlg.h" // Method WHATIS +#include "MeasureGUI_CheckShapeDlg.h" // Method CHECKSHAPE +#include "MeasureGUI_CheckCompoundOfBlocksDlg.h" // Method CHECKCOMPOUND +#include "MeasureGUI_GetNonBlocksDlg.h" // Method GET NON BLOCKS #include "MeasureGUI_CheckSelfIntersectionsDlg.h" // Method CHECK SELF INTERSCTIONS -#include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES +#include "MeasureGUI_PointDlg.h" // Method POINTCOORDINATES +#include "MeasureGUI_ManageDimensionsDlg.h" // Method MANAGEDIMENSIONS #include @@ -120,6 +121,9 @@ bool MeasureGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpPointCoordinates: dlg = new MeasureGUI_PointDlg( getGeometryGUI(), parent ); break; // POINT COORDINATES + case GEOMOp::OpManageDimensions: + dlg = new MeasureGUI_ManageDimensionsDlg( getGeometryGUI(), parent ); + break; // MANAGE DIMENSIONS default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); break; diff --git a/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui new file mode 100644 index 000000000..3d46ee146 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_1Sel_Frame_QTD.ui @@ -0,0 +1,83 @@ + + + MeasureGUI_1Sel_Frame_QTD + + + + 0 + 0 + 155 + 45 + + + + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 9 + + + 6 + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TL1 + + + false + + + + + + + + + + qPixmapFromMimeSource + + PushButton1 + LineEdit1 + + + + diff --git a/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui b/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui new file mode 100644 index 000000000..5aa2cbb23 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_1TreeWidget_4Button_QTD.ui @@ -0,0 +1,105 @@ + + + MeasureGUI_1TreeWidget_4Button_QTD + + + + 0 + 0 + 341 + 450 + + + + + 0 + 0 + + + + + + + + 0 + + + 6 + + + + + + 9 + + + 6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + qPixmapFromMimeSource + + + diff --git a/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui new file mode 100644 index 000000000..76cd89d1f --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_2Sel_Frame_QTD.ui @@ -0,0 +1,117 @@ + + + MeasureGUI_2Sel_Frame_QTD + + + + 0 + 0 + 156 + 74 + + + + + 0 + 0 + + + + + + + + 0 + + + 6 + + + + + + 9 + + + 6 + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TL1 + + + false + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TL2 + + + false + + + + + + + + + + + + + qPixmapFromMimeSource + + PushButton1 + LineEdit1 + PushButton2 + LineEdit2 + + + + diff --git a/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui b/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui new file mode 100644 index 000000000..3d2787b7c --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_3Sel_Frame_QTD.ui @@ -0,0 +1,151 @@ + + + MeasureGUI_3Sel_Frame_QTD + + + + 0 + 0 + 156 + 103 + + + + + 0 + 0 + + + + + + + + 0 + + + 6 + + + + + + 9 + + + 6 + + + + + + + + + 0 + 0 + + + + TL1 + + + false + + + + + + + + 0 + 0 + + + + TL2 + + + false + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TL3 + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + qPixmapFromMimeSource + + PushButton1 + LineEdit1 + PushButton2 + LineEdit2 + PushButton3 + LineEdit3 + + + + diff --git a/src/MeasureGUI/MeasureGUI_AngleDlg.cxx b/src/MeasureGUI/MeasureGUI_AngleDlg.cxx index afb373a9d..df482d067 100644 --- a/src/MeasureGUI/MeasureGUI_AngleDlg.cxx +++ b/src/MeasureGUI/MeasureGUI_AngleDlg.cxx @@ -320,34 +320,7 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs() TopoDS_Edge anEdge1 = TopoDS::Edge(S1); TopoDS_Edge anEdge2 = TopoDS::Edge(S2); - // Build a plane for angle dimension presentation {P11, P12, P3} - TopoDS_Vertex V11, V12, V21, V22; - TopExp::Vertices(anEdge1, V11, V12); - TopExp::Vertices(anEdge2, V21, V22); - - gp_Pnt aP11 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge1)); - gp_Pnt aP12 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge1)); - - gp_Pnt aP21 = BRep_Tool::Pnt(TopExp::FirstVertex(anEdge2)); - gp_Pnt aP22 = BRep_Tool::Pnt(TopExp::LastVertex (anEdge2)); - - // *P3 - // \ - // \ - // *P22 - // / - // / - // P11 / P12 - // *-----/----------* - // \ / - // \ / - // *P21 - gp_Pnt aP3 (aP22.XYZ() + aP11.XYZ() - aP21.XYZ()); - - gce_MakePln gce_MP(aP11, aP12, aP3); - Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value()); - - Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2, aPlane->Pln() ); + Handle(AIS_AngleDimension) anIO = new AIS_AngleDimension( anEdge1, anEdge2 ); Handle(Prs3d_DimensionAspect) aDimensionStyle = new Prs3d_DimensionAspect; @@ -356,6 +329,7 @@ SALOME_Prs* MeasureGUI_AngleDlg::buildPrs() Standard_Boolean isInfinite1,isInfinite2; Handle(Geom_Curve) extCurv; Standard_Integer extShape; + Handle(Geom_Plane) aPlane; if (AIS::ComputeGeometry(anEdge1, anEdge2, extShape, diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx new file mode 100644 index 000000000..378535acf --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.cxx @@ -0,0 +1,950 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_CreateDimensionDlg.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_CreateDimensionDlg.h" +#include "MeasureGUI_DimensionCreateTool.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_CreateDimensionDlg::MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr& theObj, + GeometryGUI* theGUI, + QWidget* theParent ) +: GEOMBase_Skeleton( theGUI, theParent ), + myParentObj( theObj ), + myEditingViewer( NULL ) +{ + setWindowTitle( tr( "CREATE_DIMENSION_TITLE" ) ); + + // init "dimension type" radio buttons + QAbstractButton* aTypeButtonLength = mainFrame()->RadioButton1; + QAbstractButton* aTypeButtonDiameter = mainFrame()->RadioButton2; + QAbstractButton* aTypeButtonAngle = mainFrame()->RadioButton3; + + mainFrame()->GroupConstructors->setTitle( tr( "DIMENSIONS" ) ); + aTypeButtonDiameter->setText( tr( "DIAMETER" ) ); + aTypeButtonLength->setText( tr( "LENGTH" ) ); + aTypeButtonAngle->setText( tr( "ANGLE" ) ); + + // construct "arguments" pane + QGroupBox* aGroupArgs = new QGroupBox( tr( "ARGUMENTS" ), centralWidget() ); + QVBoxLayout* aGroupArgsLayout = new QVBoxLayout( aGroupArgs ); + + myLengthArgs = new LengthPane ( centralWidget() ); + myDiameterArgs = new DiameterPane( centralWidget() ); + myAngleArgs = new AnglePane ( centralWidget() ); + + // connect selector pane signals + connect( myLengthArgs, SIGNAL( StartSelection( const QList& ) ), + SLOT( OnStartSelection( const QList& ) ) ); + connect( myDiameterArgs, SIGNAL( StartSelection( const QList& ) ), + SLOT( OnStartSelection( const QList& ) ) ); + connect( myAngleArgs, SIGNAL( StartSelection( const QList& ) ), + SLOT( OnStartSelection( const QList& ) ) ); + + connect( myLengthArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) ); + connect( myDiameterArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection() ) ); + connect( myAngleArgs, SIGNAL( StopSelection() ), SLOT( OnStopSelection( ) ) ); + + connect( myLengthArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) ); + connect( myDiameterArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) ); + connect( myAngleArgs, SIGNAL( SelectionDone() ), SLOT( OnSelectionDone() ) ); + + aGroupArgsLayout->addWidget( myLengthArgs ); + aGroupArgsLayout->addWidget( myDiameterArgs ); + aGroupArgsLayout->addWidget( myAngleArgs ); + + // construct main layout + QVBoxLayout* aCustomWidLayout = new QVBoxLayout( centralWidget() ); + aCustomWidLayout->setMargin( 0 ); + aCustomWidLayout->setSpacing( 6 ); + aCustomWidLayout->addWidget( aGroupArgs ); + + // add visibility rules for structural widgets + connect( aTypeButtonLength, SIGNAL( toggled(bool) ), myLengthArgs, SLOT( setVisible(bool) ) ); + connect( aTypeButtonDiameter, SIGNAL( toggled(bool) ), myDiameterArgs, SLOT( setVisible(bool) ) ); + connect( aTypeButtonAngle, SIGNAL( toggled(bool) ), myAngleArgs, SLOT( setVisible(bool) ) ); + + // signals and slots connections + connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); + connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); + + // map functional signals + myRBGroup->setId( aTypeButtonLength, TypeButtonID_Length ); + myRBGroup->setId( aTypeButtonDiameter, TypeButtonID_Diameter ); + myRBGroup->setId( aTypeButtonAngle, TypeButtonID_Angle ); + + connect( this, SIGNAL( constructorsClicked( int ) ), SLOT( ConstructTypeChanged( int ) ) ); + connect( myLengthArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) ); + connect( myDiameterArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) ); + connect( myAngleArgs, SIGNAL( TabChanged() ), SLOT( OnArgumentTabChanged() ) ); + + myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ); + + Init(); +} + +//================================================================================= +// function : Destructor +// purpose : +//================================================================================= +MeasureGUI_CreateDimensionDlg::~MeasureGUI_CreateDimensionDlg() +{ +} + +//================================================================================= +// function : ActiveArgs +// purpose : +//================================================================================= +MeasureGUI_CreateDimensionDlg::BaseSelectorPane* MeasureGUI_CreateDimensionDlg::ActiveArgs() +{ + switch ( getConstructorId() ) + { + case TypeButtonID_Length : return myLengthArgs; + case TypeButtonID_Diameter : return myDiameterArgs; + case TypeButtonID_Angle : return myAngleArgs; + default: + return NULL; + } +} + +//================================================================================= +// function : GenerateName +// purpose : +//================================================================================= +QString MeasureGUI_CreateDimensionDlg::GenerateName( const QString& thePrefix ) +{ + QRegExp anExtractIds( "^" + thePrefix + "_([0-9]+)$" ); + + QSet anOccupiedIds; + + GEOMUtils_DimensionProperty aProp = + getStudy()->getObjectProperty( GEOM::sharedPropertiesId(), + myParentObj->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + // get names and convert to QStrings to perform index matching + for( int anIt = 0; anIt < aProp.GetNumber(); ++anIt ) + { + if ( anExtractIds.indexIn( aProp.GetName( anIt ) ) == -1 ) + { + continue; + } + + anOccupiedIds.insert( anExtractIds.cap( 1 ).toInt() ); + } + + int aSearchId = 1; + while ( true ) + { + if ( !anOccupiedIds.contains( aSearchId ) ) + { + break; + } + + aSearchId++; + } + + return QString( thePrefix + "_%1" ).arg( aSearchId ); +} + +//================================================================================= +// function : ConstructTypeChanged +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::ConstructTypeChanged( int theType ) +{ + ActiveArgs()->Reset(); + + updateGeometry(); + + QString aName; + switch ( theType ) + { + case TypeButtonID_Length : aName = GenerateName( tr("NAME_LENGTH") ); break; + case TypeButtonID_Diameter : aName = GenerateName( tr("NAME_DIAMETER") ); break; + case TypeButtonID_Angle : aName = GenerateName( tr("NAME_ANGLE") ); break; + } + + myMainFrame->ResultName->setText( aName ); + + StopLocalEditing(); + erasePreview(); + + updateGeometry(); + resize( minimumSizeHint() ); +} + +//================================================================================= +// function : OnArgumentTabChanged +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::OnArgumentTabChanged() +{ + StopLocalEditing(); + erasePreview(); +} + +//================================================================================= +// function : OnStartSelection +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::OnStartSelection( const QList& theModes ) +{ + OnStopSelection(); + + StopLocalEditing(); + + QList::const_iterator aModeIt = theModes.constBegin(); + for ( ; aModeIt != theModes.constEnd(); ++aModeIt ) + { + localSelection( myParentObj.get(), *aModeIt ); + } + + mySelectionModes = theModes; + + connect( myGeomGUI->getApp()->selectionMgr(), + SIGNAL( currentSelectionChanged() ), + SLOT( SelectionIntoArgument() ) ); +} + +//================================================================================= +// function : OnStopSelection +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::OnStopSelection() +{ + globalSelection(); + + disconnect( myGeomGUI->getApp()->selectionMgr(), + SIGNAL( currentSelectionChanged() ), + this, + SLOT( SelectionIntoArgument() ) ); +} + +//================================================================================= +// function : SelectionIntoArgument +// purpose : Handle model selection by active selector pane +//================================================================================= +void MeasureGUI_CreateDimensionDlg::SelectionIntoArgument() +{ + LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelection; + aSelectionMgr->selectedObjects( aSelection ); + + if ( aSelection.Extent() != 1 ) + { + ActiveArgs()->SelectionIntoArguments( GEOM::GeomObjPtr() ); + return; + } + + StopLocalEditing(); + + erasePreview(); + + ActiveArgs()->SelectionIntoArguments( getSelected( mySelectionModes ) ); +} + +//================================================================================= +// function : OnSelectionDone +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::OnSelectionDone() +{ + // create new dimension presentation + myDimension = CreateDimension(); + + if ( myDimension.IsNull() ) + { + // can not create preview, repeat selection + SUIT_MessageBox::warning( this, + tr( "WARNING_TITLE_CANNOT_CREATE_DIMENSION" ), + tr( "WARNING_MSG_INVALID_ARGUMENTS" ) ); + + ActiveArgs()->Reset(); + + return; + } + + // show preview of dimension object + SUIT_ViewWindow* aViewWindow = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); + + SOCC_Prs* aSalomePrs = dynamic_cast( ( (SOCC_Viewer*)( aViewWindow->getViewManager()->getViewModel() ) )->CreatePrs( 0 ) ); + + aSalomePrs->AddObject( myDimension ); + + displayPreview( aSalomePrs ); + + StartLocalEditing(); +} + +//================================================================================= +// function : ClickOnOk +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + if ( ClickOnApply() ) + { + ClickOnCancel(); + } +} + +//================================================================================= +// function : ClickOnApply +// purpose : +//================================================================================= +bool MeasureGUI_CreateDimensionDlg::ClickOnApply() +{ + StopLocalEditing(); + + if ( !AddDimensionToOwner() ) + { + return false; + } + + redisplay( myParentObj.get() ); + + if ( !isApplyAndClose() ) + { + Init(); + } + + return true; +} + +//================================================================================= +// function : StartLocalEditing +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::StartLocalEditing() +{ + StopLocalEditing(); + + myDimensionInteractor->Enable(); + + if ( myDimension.IsNull() ) + { + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + + SUIT_ViewManager* aViewMgr = anApp->activeViewManager(); + + if ( aViewMgr->getType() != OCCViewer_Viewer::Type() ) + { + return; + } + + SOCC_Viewer* anOCCViewer = dynamic_cast( aViewMgr->getViewModel() ); + + myEditingViewer = anOCCViewer; + if ( !myEditingViewer ) + { + return; + } + + Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext(); + Handle(V3d_Viewer) aViewer3d = myEditingViewer->getViewer3d(); + + aViewer3d->AddZLayer( myEditingLayer ); + + anAISContext->OpenLocalContext( Standard_False, Standard_False ); + anAISContext->Load( myDimension, AIS_DSM_All ); + anAISContext->SetZLayer( myDimension, myEditingLayer ); + anAISContext->Activate( myDimension, AIS_DSM_Line ); + anAISContext->Activate( myDimension, AIS_DSM_Text ); +} + +//================================================================================= +// function : StopLocalEditing +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::StopLocalEditing() +{ + myDimensionInteractor->Disable(); + + if ( !myEditingViewer ) + { + return; + } + + Handle(AIS_InteractiveContext) anAISContext = myEditingViewer->getAISContext(); + Handle(V3d_Viewer) aViewer3d = myEditingViewer->getViewer3d(); + + aViewer3d->RemoveZLayer( myEditingLayer ); + anAISContext->CloseLocalContext(); + + myEditingViewer = NULL; +} + +//================================================================================= +// function : Init +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::Init() +{ + StopLocalEditing(); + + erasePreview(); + + myDiameterArgs->setVisible( false ); + myAngleArgs ->setVisible( false ); + myLengthArgs ->setVisible( true ); + myLengthArgs->Reset(); + + myRBGroup->button( TypeButtonID_Length )->click(); +} + +//================================================================================= +// function : CreateDimensionPrs +// purpose : +//================================================================================= +Handle(AIS_Dimension) MeasureGUI_CreateDimensionDlg::CreateDimension() +{ + Handle(AIS_Dimension) aDimensionIO; + + // prepare dimension styling + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + QColor aQColor = aResMgr->colorValue ( "Geometry", "dimensions_color", QColor( 0, 255, 0 ) ); + int aLineWidth = aResMgr->integerValue( "Geometry", "dimensions_line_width", 1 ); + double aFontHeight = aResMgr->doubleValue ( "Geometry", "dimensions_font_height", 10 ); + double anArrowLength = aResMgr->doubleValue ( "Geometry", "dimensions_arrow_length", 5 ); + bool isUnitsShown = aResMgr->booleanValue( "Geometry", "dimensions_show_units", false ); + QString aUnitsLength = aResMgr->stringValue ( "Geometry", "dimensions_length_units", "m" ); + QString aUnitsAngle = aResMgr->stringValue ( "Geometry", "dimensions_angle_units", "deg" ); + + MeasureGUI_DimensionCreateTool aTool( myGeomGUI ); + + switch ( getConstructorId() ) + { + // create length dimension + case TypeButtonID_Length : + { + LengthPane* aLengthPane = qobject_cast( ActiveArgs() ); + + switch (aLengthPane->ActiveTab()) + { + case LengthPane::TabID_SingleEdge: + { + const GEOM::GeomObjPtr& anEdge = aLengthPane->GetSingleEdge(); + + aDimensionIO = aTool.LengthOnEdge( anEdge ); + break; + } + + case LengthPane::TabID_TwoPoints: + { + const GEOM::GeomObjPtr& aPoint1 = aLengthPane->GetPoint1(); + const GEOM::GeomObjPtr& aPoint2 = aLengthPane->GetPoint2(); + + aDimensionIO = aTool.LengthByPoints( aPoint1, aPoint2 ); + break; + } + + case LengthPane::TabID_ParallelEdges: + { + const GEOM::GeomObjPtr& anEdge1 = aLengthPane->GetEdge1(); + const GEOM::GeomObjPtr& anEdge2 = aLengthPane->GetEdge2(); + + aDimensionIO = aTool.LengthByParallelEdges( anEdge1, anEdge2 ); + break; + } + } + } + break; + + // create diameter dimension + case TypeButtonID_Diameter : + { + DiameterPane* aDiameterPane = qobject_cast( ActiveArgs() ); + + const GEOM::GeomObjPtr& aShape = aDiameterPane->GetShape(); + + aDimensionIO = aTool.Diameter( aShape ); + break; + } + + // create angle dimension + case TypeButtonID_Angle : + { + AnglePane* anAnglePane = qobject_cast( ActiveArgs() ); + + switch (ActiveArgs()->ActiveTab()) + { + case AnglePane::TabID_TwoEdges: + { + const GEOM::GeomObjPtr& anEdge1 = anAnglePane->GetEdge1(); + const GEOM::GeomObjPtr& anEdge2 = anAnglePane->GetEdge2(); + + aDimensionIO = aTool.AngleByTwoEdges( anEdge1, anEdge2 ); + break; + } + + case AnglePane::TabID_ThreePoints: + { + const GEOM::GeomObjPtr& aPoint1 = anAnglePane->GetPoint1(); + const GEOM::GeomObjPtr& aPoint2 = anAnglePane->GetPoint2(); + const GEOM::GeomObjPtr& aPoint3 = anAnglePane->GetPoint3(); + + aDimensionIO = aTool.AngleByThreePoints( aPoint1, aPoint2, aPoint3 ); + break; + } + } + break; + } + } + + if ( aDimensionIO.IsNull() ) + { + return NULL; + } + + Quantity_Color aColor( aQColor.redF(), aQColor.greenF(), aQColor.blueF(), Quantity_TOC_RGB ); + + Handle(Prs3d_DimensionAspect) aStyle = new Prs3d_DimensionAspect(); + + aStyle->SetCommonColor( aColor ); + aStyle->MakeUnitsDisplayed( (Standard_Boolean) isUnitsShown ); + aStyle->MakeText3d( Standard_True ); + aStyle->MakeTextShaded( Standard_True ); + aStyle->TextAspect()->SetHeight( aFontHeight ); + aStyle->ArrowAspect()->SetLength( anArrowLength ); + aStyle->LineAspect()->SetWidth( aLineWidth ); + aDimensionIO->SetDimensionAspect( aStyle ); + aDimensionIO->SetPolygonOffsets( Aspect_POM_Fill, -1.0, -1.0 ); + + return aDimensionIO; +} + +//================================================================================= +// class : AddDimensionToOwner +// purpose : +//================================================================================= +bool MeasureGUI_CreateDimensionDlg::AddDimensionToOwner() +{ + if ( myDimension.IsNull() ) + { + return false; + } + + gp_Ax3 aLCS; + TopoDS_Shape anParentSh; + if ( GEOMBase::GetShape( myParentObj.get(), anParentSh ) ) + { + aLCS = GEOMUtils::GetPosition( anParentSh ); + } + + QString aName = getNewObjectName(); + + SalomeApp_Study* aStudy = getStudy(); + + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myParentObj->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + // append new dimension record to data + aProp.AddRecord( myDimension, aLCS ); + aProp.SetName( aProp.GetNumber() - 1, aName ); + aProp.SetVisible( aProp.GetNumber() - 1, true ); + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myParentObj->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); + + return true; +} + +/* ------------------------------------------------------------------------------* + * * + * Argument shape selector layout * + * * + * ------------------------------------------------------------------------------*/ + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::LengthPane +// purpose : Constructor +//================================================================================= +MeasureGUI_CreateDimensionDlg::LengthPane::LengthPane( QWidget* theParent ) +: BaseSelectorPane( theParent ) +{ + myTabs = new QTabWidget( this ); + mySingleEdgeSelectors = new MeasureGUI_1Sel_Frame( this ); + myTwoPointsSelectors = new MeasureGUI_2Sel_Frame( this ); + myParallelEdgesSelectors = new MeasureGUI_2Sel_Frame( this ); + + myTabs->addTab( mySingleEdgeSelectors, MeasureGUI_CreateDimensionDlg::tr( "EDGE_LENGTH" ) ); + myTabs->addTab( myTwoPointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "TWO_POINTS" ) ); + myTabs->addTab( myParallelEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "PARALLEL_EDGES" ) ); + + mySingleEdgeSelectors->PushButton1->setIcon( mySelectorIcon ); + mySingleEdgeSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE" ) ); + mySingleEdgeSelectors->LineEdit1->setReadOnly( true ); + + myTwoPointsSelectors->PushButton1->setIcon( mySelectorIcon ); + myTwoPointsSelectors->PushButton2->setIcon( mySelectorIcon ); + myTwoPointsSelectors->TextLabel1->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) ); + myTwoPointsSelectors->TextLabel2->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) ); + myTwoPointsSelectors->LineEdit1->setReadOnly( true ); + myTwoPointsSelectors->LineEdit2->setReadOnly( true ); + + myParallelEdgesSelectors->PushButton1->setIcon( mySelectorIcon ); + myParallelEdgesSelectors->PushButton2->setIcon( mySelectorIcon ); + myParallelEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) ); + myParallelEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) ); + myParallelEdgesSelectors->LineEdit1->setReadOnly( true ); + myParallelEdgesSelectors->LineEdit2->setReadOnly( true ); + + QVBoxLayout* aLayout = new QVBoxLayout( this ); + + aLayout->setMargin( 0 ); + aLayout->addWidget( myTabs ); + + SelectionModes anEdgeModes; + SelectionModes aPointModes; + anEdgeModes << TopAbs_EDGE; + aPointModes << TopAbs_VERTEX; + + SetTabWidget( myTabs ); + RegisterSelector( mySingleEdgeSelectors->LineEdit1, mySingleEdgeSelectors->PushButton1, anEdgeModes, TabID_SingleEdge ); + RegisterSelector( myTwoPointsSelectors->LineEdit1, myTwoPointsSelectors->PushButton1, aPointModes, TabID_TwoPoints ); + RegisterSelector( myTwoPointsSelectors->LineEdit2, myTwoPointsSelectors->PushButton2, aPointModes, TabID_TwoPoints ); + RegisterSelector( myParallelEdgesSelectors->LineEdit1, myParallelEdgesSelectors->PushButton1, anEdgeModes, TabID_ParallelEdges ); + RegisterSelector( myParallelEdgesSelectors->LineEdit2, myParallelEdgesSelectors->PushButton2, anEdgeModes, TabID_ParallelEdges ); +} + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::DiameterPane +// purpose : Constructor +//================================================================================= +MeasureGUI_CreateDimensionDlg::DiameterPane::DiameterPane( QWidget* theParent ) +: BaseSelectorPane( theParent ) +{ + myShapeSelector = new MeasureGUI_1Sel_Frame( this ); + myShapeSelector->PushButton1->setIcon( mySelectorIcon ); + myShapeSelector->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "OBJECT" ) ); + + QVBoxLayout* aLayout = new QVBoxLayout( this ); + + aLayout->setMargin( 0 ); + aLayout->addWidget( myShapeSelector ); + + SelectionModes aDiamModes; + aDiamModes << TopAbs_SHAPE + << TopAbs_FACE + << TopAbs_EDGE; + + RegisterSelector( myShapeSelector->LineEdit1, myShapeSelector->PushButton1, aDiamModes ); +} + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::AnglePane +// purpose : Constructor +//================================================================================= +MeasureGUI_CreateDimensionDlg::AnglePane::AnglePane( QWidget* theParent ) +: BaseSelectorPane( theParent ) +{ + myTabs = new QTabWidget( this ); + myTwoEdgesSelectors = new MeasureGUI_2Sel_Frame( this ); + myThreePointsSelectors = new MeasureGUI_3Sel_Frame( this ); + + myTabs->addTab( myTwoEdgesSelectors, MeasureGUI_CreateDimensionDlg::tr( "TWO_EDGES" ) ); + myTabs->addTab( myThreePointsSelectors, MeasureGUI_CreateDimensionDlg::tr( "THREE_POINTS" ) ); + + myTwoEdgesSelectors->PushButton1->setIcon( mySelectorIcon ); + myTwoEdgesSelectors->PushButton2->setIcon( mySelectorIcon ); + myTwoEdgesSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_1" ) ); + myTwoEdgesSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "EDGE_2" ) ); + + myThreePointsSelectors->PushButton1->setIcon( mySelectorIcon ); + myThreePointsSelectors->PushButton2->setIcon( mySelectorIcon ); + myThreePointsSelectors->PushButton3->setIcon( mySelectorIcon ); + myThreePointsSelectors->TextLabel1 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_1" ) ); + myThreePointsSelectors->TextLabel2 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_2" ) ); + myThreePointsSelectors->TextLabel3 ->setText( MeasureGUI_CreateDimensionDlg::tr( "POINT_3" ) ); + + QVBoxLayout* aLayout = new QVBoxLayout( this ); + + aLayout->setMargin( 0 ); + aLayout->addWidget( myTabs ); + + SelectionModes anEdgeModes; + SelectionModes aPointModes; + anEdgeModes << TopAbs_EDGE; + aPointModes << TopAbs_VERTEX; + + SetTabWidget( myTabs ); + RegisterSelector( myTwoEdgesSelectors->LineEdit1, myTwoEdgesSelectors->PushButton1, anEdgeModes, TabID_TwoEdges ); + RegisterSelector( myTwoEdgesSelectors->LineEdit2, myTwoEdgesSelectors->PushButton2, anEdgeModes, TabID_TwoEdges ); + RegisterSelector( myThreePointsSelectors->LineEdit1, myThreePointsSelectors->PushButton1, aPointModes, TabID_ThreePoints ); + RegisterSelector( myThreePointsSelectors->LineEdit2, myThreePointsSelectors->PushButton2, aPointModes, TabID_ThreePoints ); + RegisterSelector( myThreePointsSelectors->LineEdit3, myThreePointsSelectors->PushButton3, aPointModes, TabID_ThreePoints ); +} + +/* ------------------------------------------------------------------------------* + * * + * Argument shape selection logics * + * * + * ------------------------------------------------------------------------------*/ + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::BaseSelectorPane +// purpose : Constructor +//================================================================================= +MeasureGUI_CreateDimensionDlg::BaseSelectorPane::BaseSelectorPane( QWidget* theParent ) +: QWidget( theParent ), + myTabs( NULL ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + mySelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ); +} + +//================================================================================= +// function : BaseSelectorPane::Reset +// purpose : Reset selector line edits and controls +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::Reset( bool theOpenDefaultTab ) +{ + if ( theOpenDefaultTab && myTabs ) + { + myTabs->setCurrentIndex( 0 ); + } + + QMap>::iterator aTabsIt = mySelectors.begin(); + for ( ; aTabsIt != mySelectors.end(); ++aTabsIt ) + { + QList& aSelectors = *aTabsIt; + QList::iterator aSelectorIt = aSelectors.begin(); + for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt ) + { + QLineEdit* aSelector = *aSelectorIt; + aSelector->clear(); + mySelectedShapes[aSelector] = GEOM::GeomObjPtr(); + } + } + + QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first(); + + mySelectionButtons[aFirstSelector]->click(); +} + +//================================================================================= +// function : BaseSelectorPane::ActiveTab +// purpose : Returns active tab +//================================================================================= +int MeasureGUI_CreateDimensionDlg::BaseSelectorPane::ActiveTab() const +{ + return myTabs != NULL ? myTabs->currentIndex() : 0; +} + +//================================================================================= +// function : BaseSelectorPane::SelectionIntoArgument +// purpose : Populates current selector +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected ) +{ + if ( theSelected.isNull() ) + { + myCurrentSelector->clear(); + mySelectedShapes[myCurrentSelector] = GEOM::GeomObjPtr(); + return; + } + + QString aName = GEOMBase::GetName( theSelected.get() ); + + myCurrentSelector->setText( aName ); + + mySelectedShapes[myCurrentSelector] = theSelected; + + // find next empty selector (iterate to the last) + QList& aCurrentSelectors = mySelectors[ ActiveTab() ]; + int aCurrentPos = aCurrentSelectors.indexOf( myCurrentSelector ); + int aSelectorIt = aCurrentPos + 1; + for ( ; aSelectorIt != aCurrentSelectors.size(); ++aSelectorIt ) + { + QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt]; + if ( mySelectedShapes[aNextSelector].isNull() ) + { + mySelectionButtons[aNextSelector]->click(); + return; + } + } + + // find next empty selector (itearte from the first) + aSelectorIt = 0; + for ( ; aSelectorIt != aCurrentPos; ++aSelectorIt ) + { + QLineEdit* aNextSelector = aCurrentSelectors[aSelectorIt]; + if ( mySelectedShapes[aNextSelector].isNull() ) + { + mySelectionButtons[aNextSelector]->click(); + return; + } + } + + // stop selector switching + myCurrentSelector->setEnabled( false ); + mySelectionButtons[myCurrentSelector]->setDown( false ); + + // every selector is populated - construct presentation + emit StopSelection(); + emit SelectionDone(); +} + +//================================================================================= +// function : BaseSelectorPane::GetSelection +// purpose : +//================================================================================= +GEOM::GeomObjPtr MeasureGUI_CreateDimensionDlg::BaseSelectorPane::GetSelection( QLineEdit* theSelector ) const +{ + return mySelectedShapes[theSelector]; +} + +//================================================================================= +// function : BaseSelectorPane::OnSelectorClicked +// purpose : Handle activation of selector controls pair {edit, button} +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnSelectorClicked() +{ + // clicked "selector" button + QAbstractButton* aSender = qobject_cast( sender() ); + if ( !aSender ) + { + return; + } + + // get "selector" controls on the active tab + QList& aCurrentSelectors = mySelectors[ ActiveTab() ]; + + // iterate over controls on the tab and process them + for ( int aSelectorIt = 0; aSelectorIt < aCurrentSelectors.size(); ++aSelectorIt ) + { + QLineEdit* aSelector = aCurrentSelectors[aSelectorIt]; + QPushButton* aButton = mySelectionButtons[aSelector]; + + bool isClickedOnes = (aButton == aSender); + + aSelector->setEnabled( isClickedOnes ); + + if ( isClickedOnes ) + { + myCurrentSelector = aSelector; + myCurrentSelector->setFocus(); + } + + aButton->setDown( isClickedOnes ); + } + + emit StartSelection( mySelectionModes[myCurrentSelector] ); +} + +//================================================================================= +// function : BaseSelectorPane::OnTabChanged +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::OnTabChanged() +{ + QList& aSelectors = mySelectors[ ActiveTab() ]; + QList::iterator aSelectorIt = aSelectors.begin(); + for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt ) + { + QLineEdit* aSelector = *aSelectorIt; + + aSelector->clear(); + + mySelectedShapes[aSelector] = GEOM::GeomObjPtr(); + } + + QLineEdit* aFirstSelector = mySelectors[ ActiveTab() ].first(); + + mySelectionButtons[aFirstSelector]->click(); + + emit TabChanged(); +} + +//================================================================================= +// function : BaseSelectorPane::SetTabWidget +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::SetTabWidget( QTabWidget* theTabs ) +{ + myTabs = theTabs; + connect( myTabs, SIGNAL( currentChanged( int ) ), this, SLOT( OnTabChanged() ) ); +} + +//================================================================================= +// function : BaseSelectorPane::RegisterSelector +// purpose : +//================================================================================= +void MeasureGUI_CreateDimensionDlg::BaseSelectorPane::RegisterSelector( QLineEdit* theSelectorEdit, + QPushButton* theSelectorButton, + const SelectionModes& theSelectorModes, + const int theTab ) +{ + if ( !mySelectors.contains( theTab ) ) + { + mySelectors.insert( theTab, QList() ); + } + mySelectors[theTab].append( theSelectorEdit ); + + mySelectionButtons[theSelectorEdit] = theSelectorButton; + mySelectionModes [theSelectorEdit] = theSelectorModes; + + connect( theSelectorButton, SIGNAL( clicked() ), this, SLOT( OnSelectorClicked() ) ); +} diff --git a/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h new file mode 100644 index 000000000..321276edd --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_CreateDimensionDlg.h @@ -0,0 +1,258 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_CreateDimensionDlg.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_CREATEDIMENSIONDLG_H +#define MEASUREGUI_CREATEDIMENSIONDLG_H + +#include "MeasureGUI_Widgets.h" +#include "MeasureGUI_DimensionInteractor.h" + +// GEOM includes +#include +#include + +// SUIT includes +#include + +// OCCT includes +#include +#include + +class MeasureGUI_1Sel_Frame; +class MeasureGUI_2Sel_Frame; +class MeasureGUI_3Sel_Frame; +class QAbstractButton; +class QTabWidget; +class Bnd_Box; +class SOCC_Prs; + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg +// purpose : Dialog invoked from MeasureGUI_ManageDimensionDlg for +// creating dimension presentations for the passed onwer object. +// Does not use operation logics. +//================================================================================= +class MeasureGUI_CreateDimensionDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + + class BaseSelectorPane; + class LengthPane; + class DiameterPane; + class AnglePane; + +public: + // Enumerate dimension type radio buttons + enum TypeButtonID + { + TypeButtonID_Length = 0, + TypeButtonID_Diameter = 1, + TypeButtonID_Angle = 2 + }; + +public: + MeasureGUI_CreateDimensionDlg( const GEOM::GeomObjPtr&, GeometryGUI*, QWidget* ); + ~MeasureGUI_CreateDimensionDlg(); + +public: + Handle(AIS_Dimension) GetCreatedDimension() { return myDimension; } + +public: + void Init(); + +/* User event logics */ +protected slots: + void ConstructTypeChanged( int theType ); + void OnArgumentTabChanged(); + void OnStartSelection( const QList& theModes ); + void OnStopSelection(); + void SelectionIntoArgument(); + void OnSelectionDone(); + void ClickOnOk(); + bool ClickOnApply(); + +/* Commands */ +protected: + void StartLocalEditing(); + void StopLocalEditing(); + +/* Construction of preview and interaction */ +protected: + Handle(AIS_Dimension) CreateDimension(); + GEOM::GeomObjPtr GetTopLevel( const GEOM::GeomObjPtr& theObject ); + bool AddDimensionToOwner(); + +private: + BaseSelectorPane* ActiveArgs(); + +private: + QString GenerateName( const QString& thePrefix ); + +private: + GEOM::GeomObjPtr myParentObj; + LengthPane* myLengthArgs; + DiameterPane* myDiameterArgs; + AnglePane* myAngleArgs; + QList mySelectionModes; + MeasureGUI_DimensionInteractor* myDimensionInteractor; + Handle(AIS_Dimension) myDimension; + SOCC_Viewer* myEditingViewer; + int myEditingLayer; +}; + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::BaseSelectorPane +// purpose : Base selector pane handles events of switching the selector controls +// and changing argument tabs +//================================================================================= +class MeasureGUI_CreateDimensionDlg::BaseSelectorPane : public QWidget +{ + Q_OBJECT + +public: + typedef QList SelectionModes; + +public: + BaseSelectorPane( QWidget* theParent ); + +signals: + void StartSelection( const QList& theModes ); + void StopSelection(); + void SelectionDone(); + void TabChanged(); + +public: + void Reset( bool theOpenDefaultTab = false ); + int ActiveTab() const; + void SelectionIntoArguments( const GEOM::GeomObjPtr& theSelected ); + GEOM::GeomObjPtr GetSelection( QLineEdit* theSelector ) const; + +public slots: + void OnSelectorClicked(); + void OnTabChanged(); + +protected: + void SetTabWidget( QTabWidget* theTabs ); + + /* Register geometry selector controls at base level to provide + automatic handling of button clicks, selector switching and + sending start selection events to dialog. + - theSelectorEdit : line edit control with selected geometry name. + - theSelectorButton: selector activation button. + - theSelectorModes : shape selection modes allowed for the selection. + - theTab : the tab index on which the controls are located. */ + void RegisterSelector( QLineEdit* theSelectorEdit, + QPushButton* theSelectorButton, + const SelectionModes& theSelectorModes, + const int theTab = 0 ); + +protected: + QTabWidget* myTabs; + QMap> mySelectors; + QMap mySelectionButtons; + QMap mySelectionModes; + QMap mySelectedShapes; + QPixmap mySelectorIcon; + QLineEdit* myCurrentSelector; +}; + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::LengthPane +// purpose : Layout for length arguments pane +//================================================================================= +class MeasureGUI_CreateDimensionDlg::LengthPane : public BaseSelectorPane +{ + Q_OBJECT + +public: + enum TabID + { + TabID_SingleEdge, + TabID_TwoPoints, + TabID_ParallelEdges + }; + +public: + LengthPane( QWidget* theParent ); + GEOM::GeomObjPtr GetSingleEdge() const { return GetSelection( mySingleEdgeSelectors->LineEdit1 ); } + GEOM::GeomObjPtr GetPoint1() const { return GetSelection( myTwoPointsSelectors->LineEdit1 ); } + GEOM::GeomObjPtr GetPoint2() const { return GetSelection( myTwoPointsSelectors->LineEdit2 ); } + GEOM::GeomObjPtr GetEdge1() const { return GetSelection( myParallelEdgesSelectors->LineEdit1 ); } + GEOM::GeomObjPtr GetEdge2() const { return GetSelection( myParallelEdgesSelectors->LineEdit2 ); } + +private: + QTabWidget* myTabs; + MeasureGUI_1Sel_Frame* mySingleEdgeSelectors; + MeasureGUI_2Sel_Frame* myTwoPointsSelectors; + MeasureGUI_2Sel_Frame* myParallelEdgesSelectors; +}; + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::DiameterPane +// purpose : Layout for diameter arguments pane +//================================================================================= +class MeasureGUI_CreateDimensionDlg::DiameterPane : public BaseSelectorPane +{ + Q_OBJECT + +public: + DiameterPane( QWidget* theParent ); + GEOM::GeomObjPtr GetShape() const { return GetSelection( myShapeSelector->LineEdit1 ); } + +private: + MeasureGUI_1Sel_Frame* myShapeSelector; +}; + +//================================================================================= +// class : MeasureGUI_CreateDimensionDlg::AnglePane +// purpose : Layout for angle arguments pane +//================================================================================= +class MeasureGUI_CreateDimensionDlg::AnglePane : public BaseSelectorPane +{ + Q_OBJECT + +public: + enum TabID + { + TabID_TwoEdges, + TabID_ThreePoints + }; + +public: + AnglePane( QWidget* theParent ); + GEOM::GeomObjPtr GetEdge1() const { return GetSelection( myTwoEdgesSelectors->LineEdit1 ); } + GEOM::GeomObjPtr GetEdge2() const { return GetSelection( myTwoEdgesSelectors->LineEdit2 ); } + GEOM::GeomObjPtr GetPoint1() const { return GetSelection( myThreePointsSelectors->LineEdit1 ); } + GEOM::GeomObjPtr GetPoint2() const { return GetSelection( myThreePointsSelectors->LineEdit2 ); } + GEOM::GeomObjPtr GetPoint3() const { return GetSelection( myThreePointsSelectors->LineEdit3 ); } + +private: + QTabWidget* myTabs; + MeasureGUI_2Sel_Frame* myTwoEdgesSelectors; + MeasureGUI_3Sel_Frame* myThreePointsSelectors; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx new file mode 100644 index 000000000..c32d0c9ca --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.cxx @@ -0,0 +1,650 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionCreateTool.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_DimensionCreateTool.h" + +// GEOM includes +#include + +// GUI includes +#include + +// SUIT includes +#include +#include +#include +#include + +// OCCT includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_DimensionCreateTool::MeasureGUI_DimensionCreateTool( GeometryGUI* theGeomGUI ) +: myGeomGUI( theGeomGUI ) +{ +} + +//================================================================================= +// function : LengthOnEdge +// purpose : +//================================================================================= +Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthOnEdge( const GEOM::GeomObjPtr& theEdge ) +{ + /* ---------------------------------------------------------------- * + * get the edge and parent shape * + * ---------------------------------------------------------------- */ + + TopoDS_Shape aShapeEdge; + TopoDS_Shape aShapeMain; + if ( !GEOMBase::GetShape( theEdge.get(), aShapeEdge ) ) + { + return NULL; + } + if ( !GEOMBase::GetShape( GetMainShape( theEdge ).get(), aShapeMain ) ) + { + return NULL; + } + + /* ------------------------------------------------- */ + /* check the input geometry */ + /* ------------------------------------------------- */ + + TopoDS_Edge anEdge = TopoDS::Edge( aShapeEdge ); + + TopoDS_Vertex aVertex1; + TopoDS_Vertex aVertex2; + TopExp::Vertices( anEdge, aVertex1, aVertex2 ); + + gp_Pnt aPnt1 = BRep_Tool::Pnt( aVertex1 ); + gp_Pnt aPnt2 = BRep_Tool::Pnt( aVertex2 ); + if ( aPnt1.Distance( aPnt2 ) <= Precision::Confusion() ) + { + return NULL; + } + + /* ------------------------------------------------- * + * compose list of possible flyout directions * + * ------------------------------------------------- */ + + Bnd_Box aBnd; + BRepBndLib::AddClose( aShapeMain, aBnd ); + + TColgp_SequenceOfDir aSeqOfFlyout; + ChooseLengthFlyoutsFromShape( aSeqOfFlyout, anEdge, aShapeMain ); + ChooseLengthFlyoutsFromBnd( aSeqOfFlyout, aPnt1, aPnt2, aBnd ); + if ( aSeqOfFlyout.IsEmpty() ) + { + return NULL; + } + + gp_Dir aPointDir = gce_MakeDir( aPnt1, aPnt2 ); + + // make planes for dimension presentation according to flyout directions + NCollection_Sequence aSeqOfPlanes; + for ( Standard_Integer aFlyoutIt = 1; aFlyoutIt <= aSeqOfFlyout.Length(); ++aFlyoutIt ) + { + gp_Pln aPlane( aPnt1, aPointDir ^ aSeqOfFlyout.Value( aFlyoutIt ) ); + aSeqOfPlanes.Append( aPlane ); + } + + /* --------------------------------------------------------------------- * + * select best matching dimension plane for view projection * + * --------------------------------------------------------------------- */ + + OCCViewer_ViewWindow* anActiveView = NULL; + + if ( myGeomGUI != NULL ) + { + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + OCCViewer_ViewManager* aViewMgr = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false ); + if ( aViewMgr ) + { + anActiveView = (OCCViewer_ViewWindow*) aViewMgr->getActiveView(); + } + } + } + + gp_Pln aChoosenPlane = anActiveView + ? SelectPlaneForProjection( aSeqOfPlanes, anActiveView->getViewPort()->getView() ) + : aSeqOfPlanes.First(); + + /* ------------------------------------------------------------------------------------ * + * construct interactive presentation * + * ------------------------------------------------------------------------------------ */ + + Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension( anEdge, aChoosenPlane ); + if ( !aDimension->IsValid() ) + { + return NULL; + } + + return aDimension; +} + +//================================================================================= +// function : LengthByPoints +// purpose : +//================================================================================= +Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByPoints( const GEOM::GeomObjPtr& thePoint1, + const GEOM::GeomObjPtr& thePoint2 ) +{ + TopoDS_Shape aFirstSh; + if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) ) + { + return NULL; + } + + TopoDS_Shape aSecondSh; + if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) ) + { + return NULL; + } + + TopoDS_Vertex aFirstVertex = TopoDS::Vertex( aFirstSh ); + TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh ); + + gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex ); + gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex ); + + gp_Vec aDir( aPnt1, aPnt2 ); + gp_Dir aUnitVecs[] = { gp::DZ(), gp::DY(), gp::DX() }; + int aUnitVecIt = 0; + for ( ; aUnitVecIt < 3; ++aUnitVecIt ) + { + if ( aDir.Dot( aUnitVecs[aUnitVecIt] ) <= 0.5 ) + { + break; + } + } + + gp_Pnt aPnt3 = aPnt2.Translated( aUnitVecs[aUnitVecIt] ); + + GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 ); + Handle(Geom_Plane) aPlane = aMkPlane.Value(); + + // check whether it is possible to compute valid dimension + Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstVertex, aSecondVertex, aPlane->Pln() ); + + if ( !aDimension->IsValid() ) + { + return NULL; + } + + return aDimension; +} + +//================================================================================= +// function : LengthByParallelEdges +// purpose : +//================================================================================= +Handle(AIS_LengthDimension) MeasureGUI_DimensionCreateTool::LengthByParallelEdges( const GEOM::GeomObjPtr& theEdge1, + const GEOM::GeomObjPtr& theEdge2 ) +{ + TopoDS_Shape aFirstSh; + if ( !GEOMBase::GetShape( theEdge1.operator ->(), aFirstSh ) ) + { + return NULL; + } + + TopoDS_Shape aSecondSh; + if ( !GEOMBase::GetShape( theEdge2.operator ->(), aSecondSh ) ) + { + return NULL; + } + + TopoDS_Edge aFirstEdge = TopoDS::Edge( aFirstSh ); + TopoDS_Edge aSecondEdge = TopoDS::Edge( aSecondSh ); + + // Build plane through three points + BRepAdaptor_Curve aCurve1( aFirstEdge ); + BRepAdaptor_Curve aCurve2( aSecondEdge ); + + gp_Pnt aPnt1 = aCurve1.Value( 0.1 ); + gp_Pnt aPnt2 = aCurve1.Value( 0.9 ); + gp_Pnt aPnt3 = aCurve2.Value( 0.5 ); + + GC_MakePlane aMkPlane( aPnt1, aPnt2, aPnt3 ); + Handle(Geom_Plane) aPlane = aMkPlane.Value(); + + // check whether it is possible to compute valid dimension + Handle(AIS_LengthDimension) aDimension = new AIS_LengthDimension ( aFirstEdge, aSecondEdge, aPlane->Pln() ); + + if ( !aDimension->IsValid() ) + { + return NULL; + } + + return aDimension; +} + +//================================================================================= +// function : Diameter +// purpose : +//================================================================================= +Handle(AIS_DiameterDimension) MeasureGUI_DimensionCreateTool::Diameter( const GEOM::GeomObjPtr& theShape ) +{ + TopoDS_Shape aShape; + if ( !GEOMBase::GetShape( theShape.operator ->(), aShape ) ) + { + return NULL; + } + + if ( aShape.ShapeType() != TopAbs_EDGE && + aShape.ShapeType() != TopAbs_FACE && + aShape.ShapeType() != TopAbs_WIRE ) + { + return NULL; + } + + // check whether it is possible to compute dimension on the passed geometry + Handle(AIS_DiameterDimension) aDimension = new AIS_DiameterDimension( aShape ); + + if ( !aDimension->IsValid() ) + { + return NULL; + } + + return aDimension; +} + +//================================================================================= +// function : AngleByTwoEdges +// purpose : +//================================================================================= +Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByTwoEdges( const GEOM::GeomObjPtr& theEdge1, + const GEOM::GeomObjPtr& theEdge2 ) +{ + /* --------------------------------------------------- */ + /* get construction and parent shapes */ + /* --------------------------------------------------- */ + + TopoDS_Shape aShapeEdge1; + TopoDS_Shape aShapeMain1; + if ( !GEOMBase::GetShape( theEdge1.get(), aShapeEdge1 ) ) + { + return NULL; + } + if ( !GEOMBase::GetShape( GetMainShape( theEdge1 ).get(), aShapeMain1 ) ) + { + return NULL; + } + + TopoDS_Shape aShapeEdge2; + TopoDS_Shape aShapeMain2; + if ( !GEOMBase::GetShape( theEdge2.get(), aShapeEdge2 ) ) + { + return NULL; + } + if ( !GEOMBase::GetShape( GetMainShape( theEdge2 ).get(), aShapeMain2 ) ) + { + return NULL; + } + + /* ---------------------------------------------------- */ + /* check construction edges */ + /* ---------------------------------------------------- */ + + TopoDS_Edge aFirstEdge = TopoDS::Edge( aShapeEdge1 ); + TopoDS_Edge aSecondEdge = TopoDS::Edge( aShapeEdge2 ); + + // check whether it is possible to compute dimension on the passed edges + Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aFirstEdge, aSecondEdge ); + + if ( !aDimension->IsValid() ) + { + return NULL; + } + + const gp_Pnt& aFirstPoint = aDimension->FirstPoint(); + const gp_Pnt& aSecondPoint = aDimension->SecondPoint(); + const gp_Pnt& aCenterPoint = aDimension->CenterPoint(); + + gp_Vec aVec1( aCenterPoint, aFirstPoint ); + gp_Vec aVec2( aCenterPoint, aSecondPoint ); + + Standard_Real anAngle = aVec2.AngleWithRef( aVec1, aDimension->GetPlane().Axis().Direction() ); + + if ( anAngle < 0.0 ) + { + aDimension = new AIS_AngleDimension( aSecondPoint, aCenterPoint, aFirstPoint ); + } + + return aDimension; +} + +//================================================================================= +// function : AngleByThreePoints +// purpose : +//================================================================================= +Handle(AIS_AngleDimension) MeasureGUI_DimensionCreateTool::AngleByThreePoints( const GEOM::GeomObjPtr& thePoint1, + const GEOM::GeomObjPtr& thePoint2, + const GEOM::GeomObjPtr& thePoint3 ) +{ + TopoDS_Shape aFirstSh; + if ( !GEOMBase::GetShape( thePoint1.operator ->(), aFirstSh ) ) + { + return NULL; + } + + TopoDS_Shape aSecondSh; + if ( !GEOMBase::GetShape( thePoint2.operator ->(), aSecondSh ) ) + { + return NULL; + } + + TopoDS_Shape aThirdSh; + if ( !GEOMBase::GetShape( thePoint3.operator ->(), aThirdSh ) ) + { + return NULL; + } + + TopoDS_Vertex aFirstVertex = TopoDS::Vertex( aFirstSh ); + TopoDS_Vertex aSecondVertex = TopoDS::Vertex( aSecondSh ); + TopoDS_Vertex aThirdVertex = TopoDS::Vertex( aThirdSh ); + + gp_Pnt aPnt1 = BRep_Tool::Pnt( aFirstVertex ); + gp_Pnt aPnt2 = BRep_Tool::Pnt( aSecondVertex ); + gp_Pnt aPnt3 = BRep_Tool::Pnt( aThirdVertex ); + + // check whether it is possible to compute dimension on the passed points + Handle(AIS_AngleDimension) aDimension = new AIS_AngleDimension( aPnt1, aPnt2, aPnt3 ); + + if ( !aDimension->IsValid() ) + { + return NULL; + } + + return aDimension; +} + +//================================================================================= +// function : ChooseLengthFlyoutsFromShape +// purpose : +//================================================================================= +void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs, + const TopoDS_Vertex& theVertex1, + const TopoDS_Vertex& theVertex2, + const TopoDS_Shape& theShape ) +{ +} + +//================================================================================= +// function : ChooseLengthFlyoutsFromShape +// purpose : +//================================================================================= +void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir& theDirs, + const TopoDS_Edge& theEdge, + const TopoDS_Shape& theShape ) +{ + TopTools_IndexedDataMapOfShapeListOfShape aRelationMap; + TopExp::MapShapesAndAncestors( theShape, TopAbs_EDGE, TopAbs_FACE, aRelationMap ); + const TopTools_ListOfShape& aRelatedFaces = aRelationMap.FindFromKey( theEdge ); + + // get face side directions + gp_Dir aSideDir; + if ( aRelatedFaces.Extent() > 0 && GetFaceSide( TopoDS::Face( aRelatedFaces.First() ), theEdge, aSideDir ) ) + { + theDirs.Append( aSideDir ); + } + if ( aRelatedFaces.Extent() > 1 && GetFaceSide( TopoDS::Face( aRelatedFaces.Last() ), theEdge, aSideDir ) ) + { + theDirs.Append( aSideDir ); + } + + // get average direction in case of two non-sharp angled faces + if ( theDirs.Length() == 2 ) + { + const gp_Dir& aDir1 = theDirs.First(); + const gp_Dir& aDir2 = theDirs.Last(); + Standard_Boolean isSame = aDir1.IsParallel( aDir2, Precision::Angular() ); + if ( !isSame ) + { + gp_Dir aReferenceDir = aDir1 ^ aDir2; + // compute angle between face sides [0 - 2PI] + Standard_Real aDirAngle = aDir1.AngleWithRef( aDir2, aReferenceDir ); + if ( aDirAngle < 0 ) + { + aDirAngle = ( M_PI * 2.0 ) - aDirAngle; + } + + // non-sharp angle, use averaged direction + if ( aDirAngle > M_PI ) + { + theDirs.Clear(); + theDirs.Append( aDir1.Rotated( gp_Ax1( gp::Origin(), aReferenceDir ), aDirAngle * 0.5 ) ); + } + } + } +} + +//================================================================================= +// function : ChooseLengthFlyoutsFromBnd +// purpose : +//================================================================================= +void MeasureGUI_DimensionCreateTool::ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir& theDirs, + const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2, + const Bnd_Box& theBnd ) +{ + // compose a list of axis-aligned planes for lying-in flyouts + NCollection_Sequence anAAPlanes; + + // the axis-aligned planes for flyouts are built from + // three points (P1, P2, and P1 translated in orthogonal + // direction dx, dy, dz) + gp_Dir anAxes[3] = { gp::DX(), gp::DY(), gp::DZ() }; + + for ( int anIt = 0; anIt < 3; ++anIt ) + { + const gp_Dir& anAxisDir = anAxes[anIt]; + gp_Pnt aPnt3 = thePnt1.Translated( gp_Vec( anAxisDir ) ); + gce_MakePln aMakePlane( thePnt1, thePnt2, aPnt3 ); + if ( !aMakePlane.IsDone() ) + { + continue; + } + + anAAPlanes.Append( aMakePlane.Value() ); + } + + // find out what is the closest direction outside of the bounding box + NCollection_Sequence::Iterator aPlaneIt( anAAPlanes ); + + gp_Dir aPointDir = gce_MakeDir( thePnt1, thePnt2 ); + + for ( ; aPlaneIt.More(); aPlaneIt.Next() ) + { + const gp_Pln& aPlane = aPlaneIt.Value(); + + // transform bounding box to orthogonal coordiantes relative to + // dimension points P1, P2 (x-axis) and plane direction (z-axis), + // where y coordinates will correspond to flyout direction against + // the dimension point line + gp_Ax3 aFlyoutSpace( thePnt1, aPlane.Axis().Direction(), aPointDir ); + + gp_Trsf aRelativeTransform; + aRelativeTransform.SetTransformation( gp_Ax3(), aFlyoutSpace ); + Bnd_Box aRelativeBounds = theBnd.Transformed( aRelativeTransform ); + + Standard_Real aXmin, aXmax, aYmin, aYmax, aZmin, aZmax; + aRelativeBounds.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax ); + + gp_Dir aPosFlyout = aPlane.Axis().Direction() ^ aPointDir; + gp_Dir aNegFlyout = aPosFlyout.Reversed(); + + // select positive or negative flyout + theDirs.Append( Abs( aYmax ) < Abs( aYmin ) ? aPosFlyout : aNegFlyout ); + } +} + +//================================================================================= +// function : SelectPlaneForProjection +// purpose : Select best matching plane in current view projection +//================================================================================= +gp_Pln MeasureGUI_DimensionCreateTool::SelectPlaneForProjection( const NCollection_Sequence& thePlanes, + const Handle(V3d_View)& theView ) +{ + Quantity_Parameter U[3]; + Quantity_Parameter N[3]; + theView->Up( U[0], U[1], U[2] ); + theView->Proj( N[0], N[1], N[2] ); + + gp_Dir aViewN( (Standard_Real)N[0], (Standard_Real)N[1], (Standard_Real)N[2] ); + gp_Dir aViewU( (Standard_Real)U[0], (Standard_Real)U[1], (Standard_Real)U[2] ); + + gp_Pln aBestPlane = thePlanes.First(); + + Standard_Real aBestDotProduct = RealFirst(); + + for ( Standard_Integer aPlnIt = 1; aPlnIt <= thePlanes.Length(); ++aPlnIt ) + { + const gp_Pln& aPlane = thePlanes.Value( aPlnIt ); + + Standard_Real aDotProduct = Abs( aPlane.Axis().Direction() * aViewN ); + + // preferred plane is "view parallel" + if ( aDotProduct <= aBestDotProduct ) + { + continue; + } + + aBestPlane = aPlane; + + aBestDotProduct = aDotProduct; + } + + return aBestPlane; +} + +//================================================================================= +// function : GetMainShape +// purpose : +//================================================================================= +GEOM::GeomObjPtr MeasureGUI_DimensionCreateTool::GetMainShape( const GEOM::GeomObjPtr& theShape ) +{ + // iterate over top-level objects to search for main shape + GEOM::GeomObjPtr aMainShapeIt = theShape; + while ( !aMainShapeIt->IsMainShape() ) + { + aMainShapeIt = aMainShapeIt->GetMainShape(); + } + return aMainShapeIt; +} + +//================================================================================= +// function : GetFaceSide +// purpose : +//================================================================================= +bool MeasureGUI_DimensionCreateTool::GetFaceSide( const TopoDS_Face& theFace, const TopoDS_Edge& theEdge, gp_Dir& theDir ) +{ + // get correctly oriented edge from main shape + TopoDS_Edge anEdgeFromFace; + TopExp_Explorer anExplorer( theFace.Oriented( TopAbs_FORWARD ), TopAbs_EDGE ); + for ( ; anExplorer.More(); anExplorer.Next() ) + { + TopoDS_Edge aCurrentEdge = TopoDS::Edge( anExplorer.Current() ); + if ( theEdge.IsSame( aCurrentEdge ) ) + { + anEdgeFromFace = aCurrentEdge; + break; + } + } + + if ( anEdgeFromFace.IsNull() ) + { + return false; + } + + // check out the direction of face extensions from its boundaries at the edge location + // made assumption here that for any linear bounding edge the + // normals are same on the whole length of that edge + Handle(Geom_Surface) aSurface = BRep_Tool::Surface( theFace ); + if ( aSurface.IsNull() || !aSurface->IsKind( STANDARD_TYPE(Geom_ElementarySurface) ) ) + { + return false; + } + + BRepAdaptor_Curve aSurfCurve( anEdgeFromFace, theFace ); + if ( !aSurfCurve.IsCurveOnSurface() ) + { + return false; + } + + Standard_Real aHalfRange = ( aSurfCurve.FirstParameter() + aSurfCurve.LastParameter() ) / 2.0; + + gp_Pnt aPoint = aSurfCurve.Value( aHalfRange ); + + Standard_Real aPointU = 0.0; + Standard_Real aPointV = 0.0; + GeomLib_Tool::Parameters( aSurface, aPoint, Precision::Confusion(), aPointU, aPointV ); + + gp_Dir aNorm; + if ( GeomLib::NormEstim( aSurface, gp_Pnt2d( aPointU, aPointV ), Precision::Confusion(), aNorm ) > 1 ) + { + return false; + } + + gp_Vec aTangent = aSurfCurve.DN( aHalfRange, 1 ); + if ( aTangent.Magnitude() < Precision::Confusion() ) + { + return false; + } + + TopAbs_Orientation anEdgeOrientation = anEdgeFromFace.Orientation(); + if ( anEdgeOrientation == TopAbs_REVERSED ) + { + aTangent.Reverse(); + } + + theDir = gp_Dir( aTangent ) ^ aNorm; + return true; +} diff --git a/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h new file mode 100644 index 000000000..978aaa915 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionCreateTool.h @@ -0,0 +1,106 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionCreateTool.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_DIMENSIONCREATETOOL_H +#define MEASUREGUI_DIMENSIONCREATETOOL_H + +// GEOM includes +#include +#include + +// OCCT includes +#include +#include +#include +#include +#include +#include +#include +#include + +//================================================================================= +// class : MeasureGUI_DimensionCreateTool +// purpose : +//================================================================================= +class MeasureGUI_DimensionCreateTool +{ +public: + MeasureGUI_DimensionCreateTool( GeometryGUI* ); + +/* construction methods */ +public: + Handle(AIS_LengthDimension) LengthOnEdge( const GEOM::GeomObjPtr& ); + + Handle(AIS_LengthDimension) LengthByPoints( const GEOM::GeomObjPtr&, + const GEOM::GeomObjPtr& ); + + Handle(AIS_LengthDimension) LengthByParallelEdges( const GEOM::GeomObjPtr&, + const GEOM::GeomObjPtr& ); + + Handle(AIS_DiameterDimension) Diameter( const GEOM::GeomObjPtr& ); + + Handle(AIS_AngleDimension) AngleByTwoEdges( const GEOM::GeomObjPtr&, + const GEOM::GeomObjPtr& ); + + Handle(AIS_AngleDimension) AngleByThreePoints( const GEOM::GeomObjPtr&, + const GEOM::GeomObjPtr&, + const GEOM::GeomObjPtr& ); + +/* selecting flyout direction for length dimensions */ +protected: + + void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&, + const TopoDS_Vertex&, + const TopoDS_Vertex&, + const TopoDS_Shape& ); + + void ChooseLengthFlyoutsFromShape( TColgp_SequenceOfDir&, + const TopoDS_Edge&, + const TopoDS_Shape& ); + + void ChooseLengthFlyoutsFromBnd( TColgp_SequenceOfDir&, + const gp_Pnt&, + const gp_Pnt&, + const Bnd_Box& ); + +/* selecting best flyout direction taking into account view projection */ +protected: + + gp_Pln SelectPlaneForProjection( const NCollection_Sequence&, + const Handle(V3d_View)& ); + +/* utility */ +protected: + GEOM::GeomObjPtr GetMainShape( const GEOM::GeomObjPtr& ); + bool GetFaceSide( const TopoDS_Face&, + const TopoDS_Edge&, + gp_Dir& ); + +private: + GeometryGUI* myGeomGUI; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx b/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx new file mode 100644 index 000000000..b5abe2886 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionFilter.cxx @@ -0,0 +1,192 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionFilter.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_DimensionFilter.h" + +// GEOM includes +#include + +// SALOME includes +#include + +IMPLEMENT_STANDARD_HANDLE (MeasureGUI_DimensionFilter, SelectMgr_Filter) +IMPLEMENT_STANDARD_RTTIEXT(MeasureGUI_DimensionFilter, SelectMgr_Filter) + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO ) +: SelectMgr_Filter(), + myFilterIO( theIO ), + myFilterEntry(), + myFilterId( 0 ), + myIsFilterIO( Standard_True ), + myIsFilterEntry( Standard_False ), + myIsFilterId( Standard_False ) +{ +} + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const int theId ) +: SelectMgr_Filter(), + myFilterIO(), + myFilterEntry(), + myFilterId( theId ), + myIsFilterIO( Standard_False ), + myIsFilterEntry( Standard_False ), + myIsFilterId( Standard_True ) +{ +} + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry ) +: SelectMgr_Filter(), + myFilterIO( NULL ), + myFilterEntry( theEntry ), + myFilterId( 0 ), + myIsFilterIO( Standard_False ), + myIsFilterEntry( Standard_True ), + myIsFilterId( Standard_False ) +{ +} + +//======================================================================= +// function : Constructor +// purpose : +//======================================================================= +MeasureGUI_DimensionFilter::MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId ) +: SelectMgr_Filter(), + myFilterIO( NULL ), + myFilterEntry( theEntry ), + myFilterId( theId ), + myIsFilterIO( Standard_False ), + myIsFilterEntry( Standard_True ), + myIsFilterId( Standard_True ) +{ +} + +//======================================================================= +// function : SetFilterIO +// purpose : +//======================================================================= +void MeasureGUI_DimensionFilter::SetFilterIO( const Handle(AIS_InteractiveObject)& theIO ) +{ + myFilterIO = theIO; + myIsFilterIO = Standard_True; +} + +//======================================================================= +// function : SetFilterEntry +// purpose : +//======================================================================= +void MeasureGUI_DimensionFilter::SetFilterEntry( const std::string& theEntry ) +{ + myFilterEntry = theEntry; + myIsFilterEntry = Standard_True; +} + +//======================================================================= +// function : SetFilterId +// purpose : +//======================================================================= +void MeasureGUI_DimensionFilter::SetFilterId( const int theId ) +{ + myFilterId = theId; + myIsFilterId = Standard_True; +} + +//======================================================================= +// function : IsOk +// purpose : +//======================================================================= +Standard_Boolean MeasureGUI_DimensionFilter::IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const +{ + Handle(AIS_InteractiveObject) anAIS = Handle(AIS_InteractiveObject)::DownCast( theEntity->Selectable() ); + + if ( anAIS.IsNull() || !anAIS->HasOwner() ) + { + return Standard_False; + } + + if ( !anAIS->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) + && !anAIS->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) + && !anAIS->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) ) + { + return Standard_False; + } + + if ( myIsFilterIO ) + { + if ( anAIS != myFilterIO ) + { + return Standard_False; + } + } + + if ( myIsFilterEntry ) + { + Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast( anAIS->GetOwner() ); + if ( anIO.IsNull() ) + { + return Standard_False; + } + + if ( std::string( anIO->getEntry() ) != myFilterEntry ) + { + return Standard_False; + } + } + + if ( myIsFilterId ) + { + Handle(GEOM_AISLength) aLength = Handle(GEOM_AISLength)::DownCast( anAIS ); + if ( !aLength.IsNull() && aLength->GetId() != myFilterId ) + { + return Standard_False; + } + + Handle(GEOM_AISDiameter) aDiameter = Handle(GEOM_AISDiameter)::DownCast( anAIS ); + if ( !aDiameter.IsNull() && aDiameter->GetId() != myFilterId ) + { + return Standard_False; + } + + Handle(GEOM_AISAngle) anAngle = Handle(GEOM_AISAngle)::DownCast( anAIS ); + if ( !anAngle.IsNull() && anAngle->GetId() != myFilterId ) + { + return Standard_False; + } + } + + return Standard_True; +} diff --git a/src/MeasureGUI/MeasureGUI_DimensionFilter.h b/src/MeasureGUI/MeasureGUI_DimensionFilter.h new file mode 100644 index 000000000..89071a8b2 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionFilter.h @@ -0,0 +1,80 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionFilter.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_DIMENSIONFILTER_H +#define MEASUREGUI_DIMENSIONFILTER_H + +// GEOM includes +#include + +// OCCT includes +#include +#include +#include + +DEFINE_STANDARD_HANDLE(MeasureGUI_DimensionFilter, SelectMgr_Filter) + +//===================================================================================== +// class : MeasureGUI_DimensionFilter +// purpose : OCC viewer filter for selecting dimensions displayed as part of +// presentation of particular GEOM object by its entry (owner of dimension). +//===================================================================================== +class MeasureGUI_DimensionFilter : public SelectMgr_Filter +{ +public: + + DEFINE_STANDARD_RTTI(MeasureGUI_DimensionFilter); + +public: + Standard_EXPORT MeasureGUI_DimensionFilter( const Handle(AIS_InteractiveObject)& theIO ); + Standard_EXPORT MeasureGUI_DimensionFilter( const int theId ); + Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry ); + Standard_EXPORT MeasureGUI_DimensionFilter( const std::string& theEntry, const int theId ); + + Standard_EXPORT void SetFilterIO( const Handle(AIS_InteractiveObject)& theIO ); + Standard_EXPORT void SetFilterEntry( const std::string& theEntry ); + Standard_EXPORT void SetFilterId( const int theId ); + + Standard_Boolean IsFilterIO() const { return myIsFilterIO; } + Standard_Boolean IsFilterEntry() const { return myIsFilterEntry; } + Standard_Boolean IsFilterId() const { return myIsFilterId; } + + void UnsetFilterIO() { myIsFilterIO = Standard_False; } + void UnsetFilterEntry() { myIsFilterEntry = Standard_False; } + void UnsetFilterId() { myIsFilterId = Standard_False; } + + Standard_EXPORT virtual Standard_Boolean IsOk( const Handle(SelectMgr_EntityOwner)& theEntity ) const; + +private: + Handle(AIS_InteractiveObject) myFilterIO; + std::string myFilterEntry; + int myFilterId; + Standard_Boolean myIsFilterIO; + Standard_Boolean myIsFilterEntry; + Standard_Boolean myIsFilterId; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx new file mode 100644 index 000000000..48b9dbda4 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionInteractor.cxx @@ -0,0 +1,869 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionInteractor.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_DimensionInteractor.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_DimensionInteractor::MeasureGUI_DimensionInteractor( GeometryGUI* theGUI, + QObject* theParent ) +: QObject( theParent ), + myGeomGUI( theGUI ), + myIsEnabled( false ), + myVM( NULL ), + myViewer( NULL ), + myOperation( Operation_None ) +{ +} + +//================================================================================= +// function : Deactivate +// purpose : +//================================================================================= +MeasureGUI_DimensionInteractor::~MeasureGUI_DimensionInteractor() +{ + Disable(); +} + +//================================================================================= +// function : Enable +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::Enable() +{ + if ( myIsEnabled ) + { + return; + } + + myIsEnabled = true; + + // install event filtering on viewer windows + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + myVM = (OCCViewer_ViewManager*) anApp->getViewManager( OCCViewer_Viewer::Type(), false ); + myViewer = (OCCViewer_Viewer*) myVM->getViewModel(); + if ( !myVM || !myViewer ) + { + return; + } + + connect( myVM, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), SLOT( OnViewCreated( SUIT_ViewWindow* ) ) ); + connect( myVM, SIGNAL( deleteView ( SUIT_ViewWindow* ) ), SLOT( OnViewRemoved( SUIT_ViewWindow* ) ) ); + + QVector aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + ConnectView( *aViewIt ); + } +} + +//================================================================================= +// function : Disable +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::Disable() +{ + if ( !myIsEnabled ) + { + return; + } + + myIsEnabled = false; + + // remove event filtering from viewer windows + QVector aViews = myVM->getViews(); + QVector::iterator aViewIt = aViews.begin(); + for ( ; aViewIt != aViews.end(); ++aViewIt ) + { + DisconnectView( *aViewIt ); + } +} + +//================================================================================= +// function : GetOperation +// purpose : +//================================================================================= +MeasureGUI_DimensionInteractor::Operation + MeasureGUI_DimensionInteractor::GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity, + const Qt::MouseButtons theButtons, + const Qt::KeyboardModifiers theKeys ) +{ + if ( ( theButtons & Qt::LeftButton ) == 0 ) + { + return Operation_None; + } + + Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast( theEntity ); + if ( anOwner.IsNull() ) + { + return Operation_None; + } + + Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance + + switch ( anOwner->SelectionMode() ) + { + case AIS_DSM_Line : + { + if ( ( theKeys & Qt::ControlModifier ) == 0 ) + { + return Operation_MoveFlyoutInPlane; + } + + // "free moving" is only available for length and diameter + if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) + && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) ) + { + return Operation_None; + } + + return Operation_MoveFlyoutFree; + } + + case AIS_DSM_Text : return Operation_MoveText; + default : return Operation_None; + } +} + +//================================================================================= +// function : StartOperation +// purpose : +//================================================================================= +bool MeasureGUI_DimensionInteractor::StartOperation( const Operation theOp, + const Handle(V3d_View)& theView, + const int theX, + const int theY ) +{ + Standard_Real anAngTolerance = M_PI / 30.0; // 6 degree tolerance + + switch ( theOp ) + { + case Operation_MoveFlyoutInPlane : + case Operation_MoveText : + { + // operation can be started if the plane in which the flyout + // or text moved is not completely orthogonal to the screen + gp_Pln aPlane = myInteractedIO->GetPlane(); + gp_Lin aProj = Projection( theView, theX, theY ); + Standard_Real aCrossAng = aProj.Direction().Angle( aPlane.Axis().Direction() ); + return Abs( M_PI * 0.5 - aCrossAng ) > anAngTolerance; + } + + case Operation_MoveFlyoutFree : + { + // operation can be started only for linear dimensions + if ( !myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) + && !myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) ) + { + return false; + } + + // determine whether the rotation operation is frontal or side + gp_Pnt aFirstPoint; + gp_Pnt aSecondPoint; + + // get first and second point from which the flyout line is normally extended + Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO ); + if ( !aLength.IsNull() ) + { + aFirstPoint = aLength->FirstPoint(); + aSecondPoint = aLength->SecondPoint(); + } + + Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO ); + if ( !aDiameter.IsNull() ) + { + const gp_Pnt& aCenter = aDiameter->Circle().Location(); + aFirstPoint = aDiameter->AnchorPoint(); + aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 ); + } + + gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint ); + gp_Pln aPlane = myInteractedIO->GetPlane(); + gp_Dir aPlaneN = aPlane.Axis().Direction(); + gp_Lin aProj = Projection( theView, theX, theY ); + + const gp_Dir& aProjDir = aProj.Direction(); + + // can turn only if looking from side + if ( aProjDir.IsParallel( aPlaneN, anAngTolerance ) || + aProjDir.IsNormal( aBaseDir, anAngTolerance ) ) + { + return false; + } + + bool isProjected = false; + gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected ); + if ( !isProjected ) + { + return false; + } + + gp_Vec aPointVector( aFirstPoint, aPointOnPlane ); + gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) ); + myFreeMovePlane = gp_Pln( aPointOnBase, aBaseDir ); + + return true; + } + + default: + return false; + } +} + +//================================================================================= +// function : MoveFlyoutFree +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::MoveFlyoutFree( const Handle(V3d_View)& theView, + const int theX, + const int theY ) +{ + // project point onto dimension plane + bool isProjected = false; + gp_Pln aPlane = myFreeMovePlane; + gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected ); + if ( !isProjected ) + { + return; + } + + gp_Pnt aFirstPoint; + gp_Pnt aSecondPoint; + + // get first and second point from which the flyout line is normally extended + Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO ); + if ( !aLength.IsNull() ) + { + aFirstPoint = aLength->FirstPoint(); + aSecondPoint = aLength->SecondPoint(); + } + + Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO ); + if ( !aDiameter.IsNull() ) + { + const gp_Pnt& aCenter = aDiameter->Circle().Location(); + aFirstPoint = aDiameter->AnchorPoint(); + aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 ); + } + + gp_Vec aPointVector( aFirstPoint, aPointOnPlane ); + gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint ); + gp_Pnt aPointOnBase = gp_Pnt( aFirstPoint.XYZ() + aBaseDir.XYZ() * aPointVector.Dot( aBaseDir ) ); + + // snapping tolerance + Quantity_Length aSize[2]; + theView->Size( aSize[0], aSize[1] ); + Standard_Real aSnapTolerance = 1e-2 * Max( aSize[0], aSize[1] ); + + gp_Dir aFlyoutDir = gce_MakeDir( aPointOnBase, aPointOnPlane ); + + // snapping to planes + NCollection_Sequence aSnapPlanes; + + if ( aPointOnPlane.Distance( aPointOnBase ) > aSnapTolerance ) + { + if ( !aBaseDir.IsParallel( gp::DZ(), Precision::Angular() ) ) + { + aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DZ().Crossed( aBaseDir ) ) ); + } + if ( !aBaseDir.IsParallel( gp::DX(), Precision::Angular() ) ) + { + aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DX().Crossed( aBaseDir ) ) ); + } + if ( !aBaseDir.IsParallel( gp::DY(), Precision::Angular() ) ) + { + aSnapPlanes.Append( gp_Pln( aFirstPoint, gp::DY().Crossed( aBaseDir ) ) ); + } + } + + // snap "drag proj" to Flyout plane, relative XOY, YOZ, ZOX planes + NCollection_Sequence::Iterator aSnapIt( aSnapPlanes ); + + for ( ; aSnapIt.More(); aSnapIt.Next() ) + { + const gp_Pln& aSnapPln = aSnapIt.Value(); + + // project direction into plane + gp_Vec aPlaneDir = gp_Vec( aSnapPln.Axis().Direction() ); + gp_Vec aFlyoutProj = gp_Vec( aFlyoutDir ) - aPlaneDir * gp_Vec( aFlyoutDir ).Dot( aPlaneDir ); + + // snapping is not applicable + if ( aSnapPln.Contains( gp_Lin( aFirstPoint, aFlyoutDir ), Precision::Confusion(), Precision::Angular() ) ) + { + continue; + } + if ( Abs( gp_Vec( aPointOnBase, aPointOnPlane ).Dot( aPlaneDir ) ) > aSnapTolerance ) + { + continue; + } + if ( aFlyoutProj.Magnitude() <= Precision::Confusion() ) + { + continue; + } + + aFlyoutDir = gp_Dir( aFlyoutProj ); + + break; + } + + Standard_Real aNewFlyout = aPointOnPlane.Distance( aPointOnBase ); + + if ( aNewFlyout <= Precision::Confusion() ) + { + myInteractedIO->SetFlyout( 0.0 ); + myViewer->getAISContext()->Redisplay( myInteractedIO ); + return; + } + + gp_Pln aNewPlane = gp_Pln( aFirstPoint, aBaseDir.Crossed( aFlyoutDir ) ); + + myInteractedIO->SetFlyout( aNewFlyout ); + myInteractedIO->SetCustomPlane( aNewPlane ); + + myViewer->getAISContext()->Redisplay( myInteractedIO ); +} + +//================================================================================= +// function : MoveFlyoutInPlane +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::MoveFlyoutInPlane( const Handle(V3d_View)& theView, + const int theX, + const int theY ) +{ + // project point onto dimension plane + bool isProjected = false; + gp_Pln aPlane = myInteractedIO->GetPlane(); + gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected ); + if ( !isProjected ) + { + return; + } + + const gp_Dir& aPlaneN = aPlane.Axis().Direction(); + + // new flyout value + Standard_Real aFlyout = 0.0; + + // extend flyout of linear dimension + if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) + || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) ) + { + gp_Pnt aFirstPoint; + gp_Pnt aSecondPoint; + + // get first and second point from which the flyout line is normally extended + Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO ); + if ( !aLength.IsNull() ) + { + aFirstPoint = aLength->FirstPoint(); + aSecondPoint = aLength->SecondPoint(); + } + + Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO ); + if ( !aDiameter.IsNull() ) + { + const gp_Pnt& aCenter = aDiameter->Circle().Location(); + aFirstPoint = aDiameter->AnchorPoint(); + aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 ); + } + + gp_Lin aBaseLine( aFirstPoint, gce_MakeDir( aFirstPoint, aSecondPoint ) ); + + // check if the negative value is expected + gp_Dir aPositiveDir = aPlaneN.Crossed( aBaseLine.Direction() ); + gp_Dir aPointDir = gce_MakeDir( aBaseLine.Location(), aPointOnPlane ); + Standard_Boolean isPositive = aPointDir.Dot( aPositiveDir ) > 0; + + aFlyout = isPositive + ? aBaseLine.Distance( aPointOnPlane ) + : -aBaseLine.Distance( aPointOnPlane ); + } + + // exten flyout of angular dimension + if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) ) + { + Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO ); + + const gp_Pnt& aCenterPoint = anAngle->CenterPoint(); + const gp_Pnt& aFirstPoint = anAngle->FirstPoint(); + const gp_Pnt& aSecondPoint = anAngle->SecondPoint(); + + gp_Dir aFirstDir = gce_MakeDir( aCenterPoint, aFirstPoint ); + gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint ); + + Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir ); + + // p1 center p2 + // \ dir / + // the direction are: \ | / + // first \|/ second + // dir c dir + // + + gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 ); + + gp_Dir aPointDir = gce_MakeDir( aCenterPoint, aPointOnPlane ); + + Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0; + + Standard_Real aPointAngle = aPointDir.AngleWithRef( aCenterDir, aPlaneN ); + if ( !isPositive ) + { + aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) ); + } + + gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane ); + + // calculate flyout for each separate case of point location + if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir + { + aFlyout = aPointVec.Dot( aFirstDir ); + } + else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir + { + aFlyout = aPointVec.Dot( aSecondDir ); + } + else // between first and second direction + { + aFlyout = isPositive + ? aPointVec.Magnitude() + : -aPointVec.Magnitude(); + } + } + + myInteractedIO->SetFlyout( aFlyout ); + + myViewer->getAISContext()->Redisplay( myInteractedIO ); +} + +//================================================================================= +// function : MoveText +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::MoveText( const Handle(V3d_View)& theView, + const int theX, + const int theY ) +{ + // project point onto dimension plane + bool isProjected = false; + gp_Pln aPlane = myInteractedIO->GetPlane(); + gp_Pnt aPointOnPlane = ProjectPlane( theView, theX, theY, aPlane, isProjected ); + if ( !isProjected ) + { + return; + } + + const gp_Dir& aPlaneN = aPlane.Axis().Direction(); + + Prs3d_DimensionTextHorizontalPosition aHPos = myInteractedIO->DimensionAspect()->TextHorizontalPosition(); + Prs3d_DimensionTextVerticalPosition aVPos = myInteractedIO->DimensionAspect()->TextVerticalPosition(); + + Standard_Real aHeight = myInteractedIO->DimensionAspect()->TextAspect()->Height() * 0.5; + + // move text of linear dimension + if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_LengthDimension ) ) + || myInteractedIO->IsKind( STANDARD_TYPE( AIS_DiameterDimension ) ) ) + { + gp_Pnt aFirstPoint; + gp_Pnt aSecondPoint; + + // get first and second point from which the flyout line is normally extended + Handle(AIS_LengthDimension) aLength = Handle(AIS_LengthDimension)::DownCast( myInteractedIO ); + if ( !aLength.IsNull() ) + { + aFirstPoint = aLength->FirstPoint(); + aSecondPoint = aLength->SecondPoint(); + } + + Handle(AIS_DiameterDimension) aDiameter = Handle(AIS_DiameterDimension)::DownCast( myInteractedIO ); + if ( !aDiameter.IsNull() ) + { + const gp_Pnt& aCenter = aDiameter->Circle().Location(); + aFirstPoint = aDiameter->AnchorPoint(); + aSecondPoint = gp_Pnt( aFirstPoint.XYZ() + gp_Vec( aFirstPoint, aCenter ).XYZ() * 2.0 ); + } + + // get flyout line + Standard_Real aFlyout = myInteractedIO->GetFlyout(); + gp_Dir aBaseDir = gce_MakeDir( aFirstPoint, aSecondPoint ); + gp_Dir aFlyoutDir = aFlyout >= 0.0 + ? aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) ) + : -aPlaneN.Crossed( gce_MakeDir( aFirstPoint, aSecondPoint ) ); + gp_Vec aFlyoutTranslate = gp_Vec( aFlyoutDir ) * Abs( myInteractedIO->GetFlyout() ); + gp_Lin aFlyoutLine = gp_Lin( aFirstPoint, aBaseDir ).Translated( aFlyoutTranslate ); + + // check if positive or negative offset along flyout line + gp_Vec aFlyout2Point = gp_Vec( aFlyoutLine.Location(), aPointOnPlane ); + + Standard_Real aPosY = aFlyout2Point.Dot( aFlyoutDir ); + Standard_Real aPosX = aFlyout2Point.Dot( aFlyoutLine.Direction() ); + + if ( aPosX < 0.0 ) + { + aHPos = Prs3d_DTHP_Left; + } + else if ( aPosX > aFirstPoint.Distance( aSecondPoint ) ) + { + aHPos = Prs3d_DTHP_Right; + } + else + { + aHPos = Prs3d_DTHP_Center; + } + + if ( aPosY > aHeight ) + { + aVPos = Prs3d_DTVP_Above; + } + else if ( aPosY < -aHeight ) + { + aVPos = Prs3d_DTVP_Below; + } + else + { + aVPos = Prs3d_DTVP_Center; + } + } + + // move text of angular dimension + if ( myInteractedIO->IsKind( STANDARD_TYPE( AIS_AngleDimension ) ) ) + { + Handle(AIS_AngleDimension) anAngle = Handle(AIS_AngleDimension)::DownCast( myInteractedIO ); + + const gp_Pnt& aCenterPoint = anAngle->CenterPoint(); + const gp_Pnt& aFirstPoint = anAngle->FirstPoint(); + const gp_Pnt& aSecondPoint = anAngle->SecondPoint(); + + gp_Dir aFirstDir = gce_MakeDir( aCenterPoint, aFirstPoint ); + gp_Dir aSecondDir = gce_MakeDir( aCenterPoint, aSecondPoint ); + + Standard_Real aDirAngle = aFirstDir.Angle( aSecondDir ); + + // p1 center p2 + // \ dir / + // the direction are: \ | / + // first \|/ second + // dir c dir + // + + gp_Dir aCenterDir = aFirstDir.Rotated( gp_Ax1( aCenterPoint, aPlaneN ), -aDirAngle * 0.5 ); + + gp_Dir aPointDir = gce_MakeDir( aCenterPoint, aPointOnPlane ); + + Standard_Boolean isPositive = aPointDir.Dot( aCenterDir ) > 0; + + Standard_Real aPointAngle = aPointDir.AngleWithRef( aCenterDir, aPlaneN ); + if ( !isPositive ) + { + aPointAngle = ( M_PI - Abs( aPointAngle ) ) * ( -Sign( 1.0, aPointAngle ) ); + } + + gp_Vec aPointVec = gp_Vec( aCenterPoint, aPointOnPlane ); + + Standard_Real aPosY = 0.0; + + // the point should lie within the dimension flyout area + if ( isPositive && aPointVec.Dot( aFirstDir ) < 0.0 + || !isPositive && aPointVec.Dot( aFirstDir ) > 0.0 ) + { + return; + } + + // calculate flyout for each separate case of point location + if ( aPointAngle < -aDirAngle * 0.5 ) // outside of second dir + { + aHPos = Prs3d_DTHP_Left; + aPosY = Abs( aPointVec.Dot( aFirstDir ) ) - Abs( myInteractedIO->GetFlyout() ); + } + else if ( aPointAngle > aDirAngle * 0.5 ) // outside of first dir + { + aHPos = Prs3d_DTHP_Right; + aPosY = Abs( aPointVec.Dot( aSecondDir ) ) - Abs( myInteractedIO->GetFlyout() ); + } + else // between first and second direction + { + aHPos = Prs3d_DTHP_Center; + aPosY = Abs( aPointVec.Magnitude() ) - Abs( myInteractedIO->GetFlyout() ); + } + + if ( aPosY > aHeight ) + { + aVPos = Prs3d_DTVP_Above; + } + else if ( aPosY < -aHeight ) + { + aVPos = Prs3d_DTVP_Below; + } + else + { + aVPos = Prs3d_DTVP_Center; + } + } + + myInteractedIO->DimensionAspect()->SetTextVerticalPosition( aVPos ); + myInteractedIO->DimensionAspect()->SetTextHorizontalPosition( aHPos ); + myInteractedIO->SetToUpdate(); + + myViewer->getAISContext()->Redisplay( myInteractedIO ); +} + +//================================================================================= +// function : eventFilter +// purpose : +//================================================================================= +bool MeasureGUI_DimensionInteractor::eventFilter( QObject* theObject, QEvent* theEvent ) +{ + OCCViewer_ViewPort3d* aViewPort = (OCCViewer_ViewPort3d*) theObject; + + Handle(V3d_View) aView3d = aViewPort->getView(); + + switch ( theEvent->type() ) + { + // check whether it is the "dimension modify" operation or not. + case QEvent::MouseButtonPress : + { + Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + QMouseEvent* aMouseEv = dynamic_cast( theEvent ); + + // init detection + anAISContext->MoveTo( aMouseEv->x(), aMouseEv->y(), aView3d ); + if ( !anAISContext->HasDetected() ) + { + return false; + } + + // check that there is only one detected entity + anAISContext->InitDetected(); + if ( anAISContext->MoreDetected() ) + { + return false; + } + + Handle(SelectMgr_EntityOwner) aDetectedOwner = anAISContext->DetectedOwner(); + + myInteractedIO = Handle(AIS_Dimension)::DownCast( aDetectedOwner->Selectable() ); + + // try to start operation for the detected entity + Operation aStartOp = GetOperation( aDetectedOwner, aMouseEv->buttons(), aMouseEv->modifiers() ); + if ( aStartOp == Operation_None ) + { + return false; + } + + if ( !StartOperation( aStartOp, aView3d, aMouseEv->x(), aMouseEv->y() ) ) + { + return false; + } + + myOperation = aStartOp; + + mySelection.Clear(); + + for ( anAISContext->InitSelected(); anAISContext->MoreSelected(); anAISContext->NextSelected() ) + { + mySelection.Append( anAISContext->SelectedOwner() ); + } + + anAISContext->ClearSelected( Standard_False ); + anAISContext->AddOrRemoveSelected( aDetectedOwner ); + + emit InteractionStarted( myInteractedIO ); + + return true; + } + + // stop event processing on mouse release + case QEvent::MouseButtonRelease : + { + if ( myOperation != Operation_None ) + { + Handle(AIS_InteractiveContext) anAISContext = myViewer->getAISContext(); + + anAISContext->ClearSelected( Standard_False ); + SeqOfOwners::Iterator anIt( mySelection ); + for( ; anIt.More(); anIt.Next() ) + { + anAISContext->AddOrRemoveSelected( anIt.Value(), Standard_False ); + } + + anAISContext->UpdateCurrentViewer(); + + mySelection.Clear(); + + myOperation = Operation_None; + + emit InteractionFinished( myInteractedIO ); + + return true; + } + + return false; + } + + // perform operation + case QEvent::MouseMove : + { + QMouseEvent* aMouseEv = (QMouseEvent*) theEvent; + switch( myOperation ) + { + case Operation_MoveFlyoutFree : MoveFlyoutFree ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true; + case Operation_MoveFlyoutInPlane : MoveFlyoutInPlane( aView3d, aMouseEv->x(), aMouseEv->y() ); return true; + case Operation_MoveText : MoveText ( aView3d, aMouseEv->x(), aMouseEv->y() ); return true; + default : return false; + } + } + + default: return false; + } +} + +//================================================================================= +// function : ConnectView +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::ConnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->installEventFilter( this ); +} + +//================================================================================= +// function : DisconnectView +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::DisconnectView( SUIT_ViewWindow* theView ) +{ + ( (OCCViewer_ViewWindow*) theView )->getViewPort()->removeEventFilter( this ); +} + +//================================================================================= +// function : Projection +// purpose : +//================================================================================= +gp_Lin MeasureGUI_DimensionInteractor::Projection( const Handle(V3d_View)& theView, + const int theMouseX, + const int theMouseY ) +{ + Standard_Real P[3], D[3]; + theView->ConvertWithProj( theMouseX, theMouseY, P[0], P[1], P[2], D[0], D[1], D[2] ); + return gp_Lin( gp_Pnt( P[0], P[1], P[2] ), gp_Dir( D[0], D[1], D[2] ) ); +} + +//================================================================================= +// function : ProjectPlane +// purpose : +//================================================================================= +gp_Pnt MeasureGUI_DimensionInteractor::ProjectPlane( const Handle(V3d_View)& theView, + const int theMouseX, + const int theMouseY, + const gp_Pln& thePlane, + bool& theIsDone ) +{ + gp_Lin aProjection = Projection( theView, theMouseX, theMouseY ); + + Handle(Geom_Line) aCrossLine = new Geom_Line( aProjection ); + Handle(Geom_Plane) aCrossPlane = new Geom_Plane( thePlane ); + + GeomAPI_IntCS aFindCross( aCrossLine, aCrossPlane ); + if ( !aFindCross.IsDone() || aFindCross.NbPoints() == 0 ) + { + theIsDone = false; + return gp::Origin(); + } + + theIsDone = true; + return aFindCross.Point( 1 ); +} + +//================================================================================= +// function : SensitivityTolerance +// purpose : +//================================================================================= +Standard_Real MeasureGUI_DimensionInteractor::SensitivityTolerance( const Handle(V3d_View)& theView ) +{ + // snapping tolerance + Quantity_Length aSize[2]; + theView->Size( aSize[0], aSize[1] ); + return 1e-2 * Max( aSize[0], aSize[1] ); +} + +//================================================================================= +// function : OnViewCreated +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::OnViewCreated( SUIT_ViewWindow* theView ) +{ + ConnectView( theView ); +} + +//================================================================================= +// function : OnViewRemoved +// purpose : +//================================================================================= +void MeasureGUI_DimensionInteractor::OnViewRemoved( SUIT_ViewWindow* theView ) +{ + DisconnectView( theView ); +} diff --git a/src/MeasureGUI/MeasureGUI_DimensionInteractor.h b/src/MeasureGUI/MeasureGUI_DimensionInteractor.h new file mode 100644 index 000000000..4ed77c29d --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_DimensionInteractor.h @@ -0,0 +1,177 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_DimensionEditor.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_DIMENSIONINTERACTOR_H +#define MEASUREGUI_DIMENSIONINTERACTOR_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +class OCCViewer_ViewManager; +class OCCViewer_Viewer; +class SUIT_ViewWindow; +class Handle(V3d_View); + +//================================================================================= +// class : MeasureGUI_DimensionInteractor +// purpose : Interactive editor of dimension presentations +//================================================================================= +class MeasureGUI_DimensionInteractor : public QObject +{ + Q_OBJECT + +public: + enum Operation + { + Operation_MoveFlyoutFree, + Operation_MoveFlyoutInPlane, + Operation_MoveText, + Operation_None + }; + +public: + MeasureGUI_DimensionInteractor( GeometryGUI*, QObject* ); + ~MeasureGUI_DimensionInteractor(); + +public: + void Enable(); + void Disable(); + +protected: + /*! + * \brief Identify interactive operation by picked entity and pressed buttons with modifiers + * + * \param theEntity [in] the picked entity. + * \param theButtons [in] the mouse buttons. + * \param theKeys [in] the keyboard modifiers. + */ + Operation GetOperation( const Handle(SelectMgr_EntityOwner)& theEntity, + const Qt::MouseButtons theButtons, + const Qt::KeyboardModifiers theKeys ); + + /*! + * \brief Prepare for interactive operation. + * + * \param theOp [in] the operation. + * \param theView [in] the interacted view. + * \param theX [in] the mouse position x. + * \param theY [in] the mouse position y. + * \return TRUE if operation can be started. + */ + bool StartOperation( const Operation theOperation, + const Handle(V3d_View)& theView, + const int theX, + const int theY ); + + /*! + * \brief Perform "Operation_MoveFlyoutFree". + * Modify flyout of interactive dimension so as the flyout follows + * the mouse by its length and orientation. + * + * \param theView [in] the interacted view. + * \param theX [in] the mouse position x. + * \param theY [in] the mouse position y. + */ + void MoveFlyoutFree( const Handle(V3d_View)& theView, const int theX, const int theY ); + + /*! + * \brief Perform "Operation_MoveFlyoutInPlane". + * Modify flyout of interactive dimension so as the flyout is extended + * to the mouse point location in the presentation plane. + * + * \param theView [in] the interacted view. + * \param theX [in] the mouse position x. + * \param theY [in] the mouse position y. + */ + void MoveFlyoutInPlane( const Handle(V3d_View)& theView, const int theX, const int theY ); + + /*! + * \brief Perform "Operation_MoveText". + * Modify text of interactive dimension so as the text is moved to its fixed positions. + * + * \param theView [in] the interacted view. + * \param theX [in] the mouse position x. + * \param theY [in] the mouse position y. + */ + void MoveText( const Handle(V3d_View)& theView, const int theX, const int theY ); + +signals: + void InteractionStarted( Handle_AIS_InteractiveObject theIO ); + void InteractionFinished( Handle_AIS_InteractiveObject theIO ); + +protected: + void ConnectView( SUIT_ViewWindow* ); + void DisconnectView( SUIT_ViewWindow* ); + gp_Lin Projection( const Handle(V3d_View)&, const int, const int ); + gp_Pnt ProjectPlane( const Handle(V3d_View)&, + const int, + const int, + const gp_Pln&, + bool& ); + Standard_Real SensitivityTolerance( const Handle(V3d_View)& ); + +protected: + /*! + * \brief Process events from OCC viewer prior to their coming into the base viewer class. + * + * It handles the events coming to viewport and identifies whether the events correspond to + * interactive operation on dimension. If yes, the operation is performed within the + * interactor class and events are "accepted". Otherwise, the events are passed to + * viewer subroutines. + * + * The method manages internal workflow related to starting and stopping interactive + * operations to modify the presentations which were passed for this interactor class. + * + */ + virtual bool eventFilter( QObject*, QEvent* ); + +protected slots: + void OnViewCreated( SUIT_ViewWindow* ); + void OnViewRemoved( SUIT_ViewWindow* ); + +private: + typedef NCollection_Sequence SeqOfOwners; + +private: + GeometryGUI* myGeomGUI; + bool myIsEnabled; + OCCViewer_ViewManager* myVM; + OCCViewer_Viewer* myViewer; + Operation myOperation; + bool myOperationStarted; + gp_Pln myFreeMovePlane; + Handle(AIS_Dimension) myInteractedIO; + SeqOfOwners mySelection; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx new file mode 100644 index 000000000..a07241728 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.cxx @@ -0,0 +1,1183 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_ManageDimensionsDlg.cxx +// Author : Anton POLETAEV, Open CASCADE S.A.S. + +#include "MeasureGUI_ManageDimensionsDlg.h" +#include "MeasureGUI_CreateDimensionDlg.h" +#include "MeasureGUI_DimensionFilter.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +MeasureGUI_ManageDimensionsDlg::MeasureGUI_ManageDimensionsDlg( GeometryGUI* theGUI, QWidget* theParent ) +: GEOMBase_Skeleton( theGUI, theParent ), + myOperatedViewer( NULL ), + myCurrentSelection( Selection_None ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + QPixmap aSelectorIcon = aResMgr->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ); + + setWindowTitle( tr( "MANAGE_DIMENSIONS_TITLE" ) ); + + mainFrame()->GroupConstructors->setVisible( false ); + mainFrame()->GroupBoxName->setVisible( false ); + + // construct object selector pane + myObjectSelector = new DlgRef_1Sel( centralWidget() ); + myObjectSelector->TextLabel1->setText( tr( "OBJECT_LABEL" ) ); + myObjectSelector->LineEdit1->setReadOnly( true ); + myObjectSelector->PushButton1->setIcon( aSelectorIcon ); + myObjectSelector->PushButton1->setCheckable( true ); + + // construct dimension list view pane + myDimensionView = new MeasureGUI_1TreeWidget_4Button( centralWidget() ); + myDimensionView->GroupBox->setTitle( tr( "DIMENSIONS_GROUP" ) ); + myDimensionView->PushButton1->setText( tr( "ADD_BTN" ) ); + myDimensionView->PushButton2->setText( tr( "REMOVE_BTN" ) ); + myDimensionView->PushButton3->setText( tr( "SHOW_ALL_BTN" ) ); + myDimensionView->PushButton4->setText( tr( "HIDE_ALL_BTN" ) ); + myDimensionView->TreeWidget->setMinimumHeight( 250 ); + myDimensionView->setEnabled( false ); + + connect( myDimensionView->PushButton1, SIGNAL( clicked() ), SLOT( OnAdd() ) ); + connect( myDimensionView->PushButton2, SIGNAL( clicked() ), SLOT( OnRemove() ) ); + connect( myDimensionView->PushButton3, SIGNAL( clicked() ), SLOT( OnShowAll() ) ); + connect( myDimensionView->PushButton4, SIGNAL( clicked() ), SLOT( OnHideAll() ) ); + connect( myDimensionView->TreeWidget, + SIGNAL( itemChanged( QTreeWidgetItem*, int ) ), + SLOT( OnChangeItem( QTreeWidgetItem* ) ) ); + connect( myDimensionView->TreeWidget, + SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ), + SLOT( OnSelectItem() ) ); + + // populate tree with top-level items + myDimensionView->TreeWidget->setHeaderItem( new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( QString() ) ) ); + + // construct main frame layout + QVBoxLayout* aMainLayout = new QVBoxLayout( centralWidget() ); + aMainLayout->setMargin( 0 ); + aMainLayout->addWidget( myObjectSelector, 0 ); + aMainLayout->addWidget( myDimensionView, 1 ); + + // signals and slots connections + connect( myObjectSelector->PushButton1, SIGNAL( clicked() ), SLOT( StartObjectSelection() ) ); + connect( buttonOk(), SIGNAL( clicked() ), SLOT( ClickOnOk() ) ); + connect( buttonApply(), SIGNAL( clicked() ), SLOT( ClickOnApply() ) ); + + connect( this, SIGNAL( finished( int ) ), SLOT( OnFinish() ) ); + + myDimensionInteractor = new MeasureGUI_DimensionInteractor( theGUI, theParent ), + + SelectionIntoArgument( Selection_Object ); + + if ( myEditObject.isNull() ) + { + myObjectSelector->PushButton1->click(); + } +} + +//================================================================================= +// function : Destructor +// purpose : +//================================================================================= +MeasureGUI_ManageDimensionsDlg::~MeasureGUI_ManageDimensionsDlg() +{ + StopSelection(); +} + +//================================================================================= +// function : StartSelection +// purpose : Starts specific selection +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::StartSelection( const Selection theSelection ) +{ + StopSelection(); + + myCurrentSelection = theSelection; + + if ( theSelection == Selection_Object && WarnUnsaved() ) + { + /* ----------------------------------------------- * + * selection of object * + * ------------------------------------------------ */ + + globalSelection( GEOM_ALLSHAPES ); + connect( myGeomGUI->getApp()->selectionMgr(), + SIGNAL( currentSelectionChanged() ), + this, + SLOT( OnSelection() ) ); + } + else if ( theSelection == Selection_Dimension && !myEditObject.isNull() ) + { + /* ----------------------------------------------- * + * selection of dimension * + * ------------------------------------------------ */ + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SUIT_ViewManager* aViewMgr = anApp->activeViewManager(); + if ( aViewMgr->getType() != SOCC_Viewer::Type() ) + { + return; + } + + myOperatedViewer = dynamic_cast( aViewMgr->getViewModel() ); + + globalSelection(); + + Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext(); + + anAISContext->ClearCurrents( Standard_False ); + anAISContext->ClearSelected( Standard_False ); + anAISContext->OpenLocalContext( Standard_True, Standard_False ); + + Handle(MeasureGUI_DimensionFilter) aFilter = new MeasureGUI_DimensionFilter( myEditObject->GetStudyEntry() ); + + anAISContext->AddFilter( aFilter ); + + LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr(); + + QList aSelectors; + aSelectionMgr->selectors( aSelectors ); + QList::iterator aSelectorIt = aSelectors.begin(); + for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt ) + { + SUIT_Selector* aSelector = *aSelectorIt; + + GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast( aSelector ); + if ( !aGeomSelector ) + { + continue; + } + + aGeomSelector->setEnabled( false ); + } + + connect( myOperatedViewer, + SIGNAL( selectionChanged() ), + this, + SLOT( OnSelection() ) ); + + myDimensionInteractor->Enable(); + + connect( myDimensionInteractor, + SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ), + this, + SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) ); + + anAISContext->UpdateCurrentViewer(); + } +} + +//================================================================================= +// function : StopObjectSelection +// purpose : Stops specific selection +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::StopSelection() +{ + if ( myCurrentSelection == Selection_Object ) + { + /* ----------------------------------------------- * + * selection of object * + * ------------------------------------------------ */ + + myObjectSelector->PushButton1->setChecked( false ); + disconnect( myGeomGUI->getApp()->selectionMgr(), + SIGNAL( currentSelectionChanged() ), + this, + SLOT( OnSelection() ) ); + } + else if ( myCurrentSelection == Selection_Dimension && myOperatedViewer ) + { + /* ----------------------------------------------- * + * selection of dimension * + * ------------------------------------------------ */ + + Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext(); + + anAISContext->CloseLocalContext(); + + LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr(); + + QList aSelectors; + aSelectionMgr->selectors( aSelectors ); + QList::iterator aSelectorIt = aSelectors.begin(); + for ( ; aSelectorIt != aSelectors.end(); ++aSelectorIt ) + { + SUIT_Selector* aSelector = *aSelectorIt; + + GEOMGUI_OCCSelector* aGeomSelector = dynamic_cast( aSelector ); + if ( !aGeomSelector ) + { + continue; + } + + aGeomSelector->setEnabled( true ); + } + + disconnect( myOperatedViewer, + SIGNAL( selectionChanged() ), + this, + SLOT( OnSelection() ) ); + + myDimensionInteractor->Disable(); + + disconnect( myDimensionInteractor, + SIGNAL( InteractionFinished( Handle_AIS_InteractiveObject ) ), + this, + SLOT( OnInteractionFinished( Handle_AIS_InteractiveObject ) ) ); + } + + myCurrentSelection = Selection_None; + + globalSelection(); +} + +//================================================================================= +// function : OnSelection +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnSelection() +{ + SelectionIntoArgument( myCurrentSelection ); +} + +//================================================================================= +// function : SelectionIntoArgument +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::SelectionIntoArgument( const Selection theSelection ) +{ + if ( theSelection == Selection_Object ) + { + /* ----------------------------------------------- * + * selection of object * + * ------------------------------------------------ */ + + LightApp_SelectionMgr* aSelectionMgr = myGeomGUI->getApp()->selectionMgr(); + SALOME_ListIO aSelection; + aSelectionMgr->selectedObjects( aSelection ); + + GEOM::GeomObjPtr aSelected; + + if ( aSelection.Extent() == 1 ) + { + aSelected = GEOMBase::ConvertIOinGEOMObject( aSelection.First() ); + } + + SetEditObject( aSelected ); + StartSelection( Selection_Dimension ); + } + else if ( theSelection == Selection_Dimension && myOperatedViewer ) + { + /* ----------------------------------------------- * + * selection of dimension * + * ------------------------------------------------ */ + + QTreeWidget* aDimensionList = myDimensionView->TreeWidget; + + Handle(AIS_InteractiveContext) anAISContext = myOperatedViewer->getAISContext(); + + // non-single selection is prohibited + if ( anAISContext->NbSelected() != 1 ) + { + aDimensionList->setCurrentIndex( QModelIndex() ); + return; + } + + anAISContext->InitSelected(); + + Handle(AIS_InteractiveObject) anAIS; + + if ( anAISContext->HasOpenedContext() ) + { + Handle(SelectMgr_EntityOwner) anAISOwner = anAISContext->SelectedOwner(); + anAIS = Handle(AIS_InteractiveObject)::DownCast( anAISOwner->Selectable() ); + } + else + { + anAIS = anAISContext->Current(); + } + + int aDimensionId = IdFromPrs( anAIS ); + + SelectInList( aDimensionId ); + + if ( aDimensionId >= 0 ) + { + SelectInViewer( myOperatedViewer, aDimensionId ); + } + } +} + +//================================================================================= +// function : OnAdd +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnAdd() +{ + QWidget* aParent = qobject_cast( this->parent() ); + + this->Suspend(); + + MeasureGUI_CreateDimensionDlg* aCreateDlg = new MeasureGUI_CreateDimensionDlg( myEditObject, myGeomGUI, aParent ); + + connect( aCreateDlg, SIGNAL( finished( int ) ), this, SLOT( Resume() ) ); + + // this is necessary as the GEOMBase_Helper switches selection mode on destruction + connect( aCreateDlg, SIGNAL( destroyed( QObject* ) ), this, SLOT( Resume() ) ); + + aCreateDlg->updateGeometry(); + aCreateDlg->resize( aCreateDlg->minimumSizeHint() ); + aCreateDlg->show(); +} + +//================================================================================= +// function : OnRemove +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnRemove() +{ + int aDimensionId = IdFromItem( myDimensionView->TreeWidget->currentItem() ); + if ( aDimensionId < 0 ) + { + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + aProp.RemoveRecord( aDimensionId ); + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); + + PopulateList(); + + RedisplayObject(); +} + +//================================================================================= +// function : OnChangeItem +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnChangeItem( QTreeWidgetItem* theItem ) +{ + int aDimensionId = IdFromItem( theItem ); + if ( aDimensionId < 0 ) + { + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + // change property data + bool isAnythingChanged = false; + + QString aName = theItem->text( 0 ); + if ( aProp.GetName( aDimensionId ) != aName ) + { + isAnythingChanged = true; + aProp.SetName( aDimensionId, aName ); + } + + bool isVisible = theItem->checkState( 0 ) == Qt::Checked; + if ( aProp.IsVisible( aDimensionId ) != isVisible ) + { + isAnythingChanged = true; + aProp.SetVisible( aDimensionId, isVisible ); + } + + // store property data + if ( !isAnythingChanged ) + { + return; + } + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); + + RedisplayObject(); +} + +//================================================================================= +// function : OnSelectItem +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnSelectItem() +{ + if ( !myOperatedViewer ) + { + return; + } + + QTreeWidgetItem* aSelectedItem = myDimensionView->TreeWidget->currentItem(); + + SelectInViewer( myOperatedViewer, IdFromItem( aSelectedItem ) ); +} + +//================================================================================= +// function : OnShowAll +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnShowAll() +{ + // read propety data + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + QTreeWidget* aDimensionList = myDimensionView->TreeWidget; + + bool isBlocked = aDimensionList->blockSignals( true ); + + for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt ) + { + aProp.SetVisible( anIt, true ); + } + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); + + PopulateList(); + + RedisplayObject(); + + aDimensionList->blockSignals( isBlocked ); +} + +//================================================================================= +// function : OnHideAll +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnHideAll() +{ + // read propety data + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + QTreeWidget* aDimensionList = myDimensionView->TreeWidget; + + bool isBlocked = aDimensionList->blockSignals( true ); + + for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt ) + { + aProp.SetVisible( anIt, false ); + } + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); + + PopulateList(); + + RedisplayObject(); + + aDimensionList->blockSignals( isBlocked ); +} + +//================================================================================= +// function : OnInteractionFinished +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnInteractionFinished( Handle(AIS_InteractiveObject) theIO ) +{ + // update property data + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + gp_Ax3 aLCS; + TopoDS_Shape anParentSh; + if ( GEOMBase::GetShape( myEditObject.get(), anParentSh ) ) + { + aLCS = GEOMUtils::GetPosition( anParentSh ); + } + + int aDimensionId = IdFromPrs( theIO ); + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + aProp.SetRecord( aDimensionId, Handle(AIS_Dimension)::DownCast( theIO ), aLCS ); + + // store modified property data + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + aProp ); +} + +//================================================================================= +// function : Suspend +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::Suspend() +{ + StopSelection(); + hide(); +} + +//================================================================================= +// function : Suspend +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::Resume() +{ + this->show(); + if ( !myEditObject.isNull() ) + { + PopulateList(); + StartSelection( Selection_Dimension ); + } +} + +//================================================================================= +// function : ClickOnOk +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::ClickOnOk() +{ + setIsApplyAndClose( true ); + if ( ClickOnApply() ) + { + ClickOnCancel(); + } +} + +//================================================================================= +// function : ClickOnCancel +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::ClickOnCancel() +{ + if ( !WarnUnsaved() ) + { + return; + } + + GEOMBase_Skeleton::ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply +// purpose : +//================================================================================= +bool MeasureGUI_ManageDimensionsDlg::ClickOnApply() +{ + if ( myEditObject.isNull() ) + { + return true; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return true; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return true; + } + + mySavedPropertyState = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + mySavedPropertyState.SaveToAttribute( aStudy, myEditObject->GetStudyEntry() ); + + return true; +} + +//================================================================================= +// function : OnFinish +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::OnFinish() +{ + if ( myEditObject.isNull() ) + { + GEOMBase_Skeleton::ClickOnCancel(); + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + GEOMBase_Skeleton::ClickOnCancel(); + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + GEOMBase_Skeleton::ClickOnCancel(); + return; + } + + // reset preview property state + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ); + + redisplay( myEditObject.get() ); +} + +//================================================================================= +// function : SetEditObject +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::SetEditObject( const GEOM::GeomObjPtr& theObj ) +{ + RestoreState(); + + QString aName = GEOMBase::GetName( theObj.get() ); + + myObjectSelector->LineEdit1->setText( aName ); + + myEditObject = theObj; + + if ( myEditObject.isNull() ) + { + myDimensionView->setEnabled( false ); + + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SUIT_ViewManager* aViewMgr = anApp->activeViewManager(); + if ( aViewMgr->getType() != SOCC_Viewer::Type() ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + mySavedPropertyState.LoadFromAttribute( getStudy(), myEditObject->GetStudyEntry() ); + + // set property state for preview + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + mySavedPropertyState ); + + PopulateList(); + + myDimensionView->setEnabled( true ); +} + +//================================================================================= +// function : RestoreState +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::RestoreState() +{ + if ( myEditObject.isNull() ) + { + return; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + QString aEntry = myEditObject->GetStudyEntry(); + + // reset preview property state + aStudy->setObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ); + + RedisplayObject(); +} + +//================================================================================= +// function : PopulateList +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::PopulateList() +{ + QTreeWidget* aListView = myDimensionView->TreeWidget; + + // clear list completely if object is null + if ( myEditObject.isNull() ) + { + aListView->clear(); + return; + } + + // clear only groups data if object is ok + QTreeWidgetItem* aDistanceGroupItem = aListView->topLevelItem( GroupItem_Distance ); + QTreeWidgetItem* aDiameterGroupItem = aListView->topLevelItem( GroupItem_Diameter ); + QTreeWidgetItem* anAngleGroupItem = aListView->topLevelItem( GroupItem_Angle ); + + // create group items if not exist yet + if ( !aDistanceGroupItem || !aDiameterGroupItem || !anAngleGroupItem ) + { + aDistanceGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DISTANCE_ITEM" ) ) ); + aDiameterGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "DIAMETER_ITEM" ) ) ); + anAngleGroupItem = new QTreeWidgetItem( (QTreeWidget*)NULL, QStringList( tr( "ANGLE_ITEM" ) ) ); + + aListView->clear(); + + aListView->addTopLevelItem( aDistanceGroupItem ); + aListView->addTopLevelItem( aDiameterGroupItem ); + aListView->addTopLevelItem( anAngleGroupItem ); + aListView->expandAll(); + } + + qDeleteAll( aDistanceGroupItem->takeChildren() ); + qDeleteAll( aDiameterGroupItem->takeChildren() ); + qDeleteAll( anAngleGroupItem->takeChildren() ); + + // collect all groupped items + QList aDistItems; + QList aDiamItems; + QList anAngItems; + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return; + } + + QString aEntry = myEditObject->GetStudyEntry(); + + // get property data to change + GEOMUtils_DimensionProperty aProp = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + // read dimension records from property + for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt ) + { + QString aName = aProp.GetName( anIt ); + bool isVisible = aProp.IsVisible( anIt ); + int aType = aProp.GetType( anIt ); + + QTreeWidgetItem* anItem = new QTreeWidgetItem; + anItem->setText( 0, aName ); + anItem->setCheckState( 0, isVisible ? Qt::Checked : Qt::Unchecked ); + anItem->setData( 0, Qt::UserRole, anIt ); + anItem->setFlags( Qt::ItemIsUserCheckable + | Qt::ItemIsSelectable + | Qt::ItemIsEditable + | Qt::ItemIsEnabled ); + + switch ( aType ) + { + case GEOMUtils_DimensionProperty::DimensionType_Length : aDistItems << anItem; break; + case GEOMUtils_DimensionProperty::DimensionType_Diameter : aDiamItems << anItem; break; + case GEOMUtils_DimensionProperty::DimensionType_Angle : anAngItems << anItem; break; + } + } + + aDistanceGroupItem->addChildren( aDistItems ); + aDiameterGroupItem->addChildren( aDiamItems ); + anAngleGroupItem->addChildren( anAngItems ); + + aListView->setItemHidden( aDistanceGroupItem, aDistItems.isEmpty() ); + aListView->setItemHidden( aDiameterGroupItem, aDiamItems.isEmpty() ); + aListView->setItemHidden( anAngleGroupItem, anAngItems.isEmpty() ); +} + +//================================================================================= +// function : WarnUnsaved +// purpose : +//================================================================================= +bool MeasureGUI_ManageDimensionsDlg::WarnUnsaved() +{ + if ( myEditObject.isNull() ) + { + return true; + } + + SalomeApp_Application* anApp = myGeomGUI->getApp(); + if ( !anApp ) + { + return true; + } + + SalomeApp_Study* aStudy = dynamic_cast( anApp->activeStudy() ); + if ( !aStudy ) + { + return true; + } + + GEOMUtils_DimensionProperty aCurrentState = + aStudy->getObjectProperty( GEOM::sharedPropertiesId(), + myEditObject->GetStudyEntry(), + GEOM::propertyName( GEOM::Dimensions ), + QVariant() ) + .value(); + + if ( aCurrentState == mySavedPropertyState ) + { + return true; + } + + int aResponse = SUIT_MessageBox::warning( this, + tr( "WRN_TITLE_UNSAVED" ), + tr( "WRN_MSG_UNSAVED" ), + QMessageBox::Ok, + QMessageBox::Cancel ); + + return aResponse == QMessageBox::Ok; +} + +//================================================================================= +// function : IdFromItem +// purpose : +//================================================================================= +int MeasureGUI_ManageDimensionsDlg::IdFromItem( QTreeWidgetItem* theItem ) +{ + if ( !theItem ) + { + return -1; + } + + bool isIdOK = false; + const int anId = theItem->data( 0, Qt::UserRole ).toInt( &isIdOK ); + + return isIdOK ? anId : -1; +} + +//================================================================================= +// function : IdFromPrs +// purpose : +//================================================================================= +int MeasureGUI_ManageDimensionsDlg::IdFromPrs( const Handle(AIS_InteractiveObject)& theAIS ) +{ + Handle(SALOME_InteractiveObject) anIO = Handle(SALOME_InteractiveObject)::DownCast( theAIS->GetOwner() ); + + if ( anIO.IsNull() ) + { + return -1; + } + + QString anIOEntry = anIO->getEntry(); + QString anEditEntry = myEditObject->GetStudyEntry(); + if ( anIOEntry != anEditEntry ) + { + return -1; + } + + Handle(GEOM_AISLength) aLength = Handle(GEOM_AISLength)::DownCast( theAIS ); + if ( !aLength.IsNull() ) + { + return aLength->GetId(); + } + + Handle(GEOM_AISDiameter) aDiameter = Handle(GEOM_AISDiameter)::DownCast( theAIS ); + if ( !aDiameter.IsNull() ) + { + return aDiameter->GetId(); + } + + Handle(GEOM_AISAngle) anAngle = Handle(GEOM_AISAngle)::DownCast( theAIS ); + if ( !anAngle.IsNull() ) + { + return anAngle->GetId(); + } + + return -1; +} + +//================================================================================= +// function : SelectInList +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::SelectInList( const Handle(AIS_InteractiveObject)& theIO ) +{ + SelectInList( IdFromPrs( theIO ) ); +} + +//================================================================================= +// function : SelectInList +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::SelectInList( const int theId ) +{ + QTreeWidget* aListOfDimension = myDimensionView->TreeWidget; + + QAbstractItemModel* aModel = aListOfDimension->model(); + QModelIndexList aIndexes = aModel->match( aModel->index(0, 0), + Qt::UserRole, + QVariant( theId ), + -1, Qt::MatchRecursive ); + + if ( aIndexes.isEmpty() ) + { + aListOfDimension->setCurrentIndex( QModelIndex() ); + return; + } + + bool isBlocked = aListOfDimension->blockSignals( true ); + aListOfDimension->setCurrentIndex( aIndexes.first() ); + aListOfDimension->blockSignals( isBlocked ); +} + +//================================================================================= +// function : SelectInViewer +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::SelectInViewer( SOCC_Viewer* theViewer, const int theId ) +{ + Handle(AIS_InteractiveContext) anAISContext = theViewer->getAISContext(); + if ( anAISContext.IsNull() ) + { + return; + } + + Standard_Boolean isLocal = anAISContext->HasOpenedContext(); + if ( isLocal ) + { + anAISContext->ClearSelected( Standard_False ); + } + else + { + anAISContext->ClearCurrents( Standard_False ); + } + + SOCC_Prs* aPrs = dynamic_cast( theViewer->CreatePrs( myEditObject->GetStudyEntry() ) ); + + AIS_ListOfInteractive aListOfIO; + aPrs->GetObjects( aListOfIO ); + + AIS_ListIteratorOfListOfInteractive anIt( aListOfIO ); + for ( ; anIt.More(); anIt.Next() ) + { + const Handle(AIS_InteractiveObject)& anIO = anIt.Value(); + if ( IdFromPrs( anIO ) != theId ) + { + if ( isLocal ) + { + anAISContext->Deactivate( anIO, AIS_DSM_Line ); + anAISContext->Deactivate( anIO, AIS_DSM_Text ); + } + continue; + } + + if ( isLocal ) + { + anAISContext->AddOrRemoveSelected( anIO, Standard_False ); + anAISContext->Activate( anIO, AIS_DSM_Line ); + anAISContext->Activate( anIO, AIS_DSM_Text ); + } + else + { + anAISContext->AddOrRemoveCurrentObject( anIO, Standard_False ); + } + + anAISContext->UpdateCurrentViewer(); + } +} + +//================================================================================= +// function : RedisplayObject +// purpose : +//================================================================================= +void MeasureGUI_ManageDimensionsDlg::RedisplayObject() +{ + redisplay( myEditObject.get() ); + + if ( !myOperatedViewer ) + { + return; + } + + QTreeWidgetItem* aSelectedItem = myDimensionView->TreeWidget->currentItem(); + if ( !aSelectedItem ) + { + return; + } + + StartSelection( myCurrentSelection ); + + SelectInViewer( myOperatedViewer, IdFromItem( aSelectedItem ) ); +} diff --git a/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h new file mode 100644 index 000000000..c6d2d70c8 --- /dev/null +++ b/src/MeasureGUI/MeasureGUI_ManageDimensionsDlg.h @@ -0,0 +1,116 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM GEOMGUI : GUI for Geometry component +// File : MeasureGUI_ManageDimensionsDlg.h +// Author : Anton POLETAEV, Open CASCADE S.A.S. +// +#ifndef MEASUREGUI_MANAGEDIMENSIONSDLG_H +#define MEASUREGUI_MANAGEDIMENSIONSDLG_H + +#include +#include "MeasureGUI_DimensionInteractor.h" +#include "MeasureGUI_Widgets.h" +#include + +class DlgRef_1Sel; +class QTreeWidget; +class QPushButton; +class SOCC_Viewer; + +//================================================================================= +// class : MeasureGUI_ManageDimensionsDlg +// purpose : The dialog provides interactive management of measurement +// dimension presentations and the "dimension" property state of +// GEOM shape objects. +//================================================================================= +class MeasureGUI_ManageDimensionsDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + MeasureGUI_ManageDimensionsDlg( GeometryGUI*, QWidget* ); + ~MeasureGUI_ManageDimensionsDlg(); + +protected: + enum Selection + { + Selection_None, + Selection_Object, + Selection_Dimension + }; + +/* User event logics */ +protected slots: + void StartObjectSelection() { StartSelection( Selection_Object ); } + void StartSelection( const Selection theSelection ); + void StopSelection(); + void OnSelection(); + void SelectionIntoArgument( const Selection theSelection ); + void OnAdd(); + void OnRemove(); + void OnChangeItem( QTreeWidgetItem* theItem ); + void OnSelectItem(); + void OnShowAll(); + void OnHideAll(); + void OnInteractionFinished( Handle_AIS_InteractiveObject theIO ); + void Suspend(); + void Resume(); + void ClickOnOk(); + virtual void ClickOnCancel(); + bool ClickOnApply(); + void OnFinish(); + +/* Utils */ +private: + void SetEditObject( const GEOM::GeomObjPtr& ); + void RestoreState(); + void PopulateList(); + bool WarnUnsaved(); + int IdFromItem( QTreeWidgetItem* theItem ); + int IdFromPrs( const Handle(AIS_InteractiveObject)& theAIS ); + void SelectInList( const Handle(AIS_InteractiveObject)& theIO ); + void SelectInList( const int theId ); + void SelectInViewer( SOCC_Viewer* theViewer, const int theId ); + void RedisplayObject(); + +private: + enum GroupItems + { + GroupItem_Distance = 0, + GroupItem_Diameter = 1, + GroupItem_Angle = 2 + }; + +private: + GEOM::GeomObjPtr myEditObject; + +private: + DlgRef_1Sel* myObjectSelector; + MeasureGUI_1TreeWidget_4Button* myDimensionView; + MeasureGUI_DimensionInteractor* myDimensionInteractor; + GEOMUtils_DimensionProperty mySavedPropertyState; + SOCC_Viewer* myOperatedViewer; + Selection myCurrentSelection; +}; + +#endif diff --git a/src/MeasureGUI/MeasureGUI_Widgets.cxx b/src/MeasureGUI/MeasureGUI_Widgets.cxx index c9fb4ad5c..de83d236a 100644 --- a/src/MeasureGUI/MeasureGUI_Widgets.cxx +++ b/src/MeasureGUI/MeasureGUI_Widgets.cxx @@ -107,6 +107,34 @@ MeasureGUI_1Sel6LineEdit::~MeasureGUI_1Sel6LineEdit() { } +////////////////////////////////////////// +// MeasureGUI_1Sel_Frame +////////////////////////////////////////// + +MeasureGUI_1Sel_Frame::MeasureGUI_1Sel_Frame( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); +} + +MeasureGUI_1Sel_Frame::~MeasureGUI_1Sel_Frame() +{ +} + +////////////////////////////////////////// +// MeasureGUI_1TreeWidget_4Button +////////////////////////////////////////// + +MeasureGUI_1TreeWidget_4Button::MeasureGUI_1TreeWidget_4Button( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); +} + +MeasureGUI_1TreeWidget_4Button::~MeasureGUI_1TreeWidget_4Button() +{ +} + ////////////////////////////////////////// // MeasureGUI_2Sel1LineEdit ////////////////////////////////////////// @@ -121,6 +149,35 @@ MeasureGUI_2Sel1LineEdit::~MeasureGUI_2Sel1LineEdit() { } +////////////////////////////////////////// +// MeasureGUI_2Sel_Frame +////////////////////////////////////////// + +MeasureGUI_2Sel_Frame::MeasureGUI_2Sel_Frame( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); +} + +MeasureGUI_2Sel_Frame::~MeasureGUI_2Sel_Frame() +{ +} + + +////////////////////////////////////////// +// MeasureGUI_3Sel_Frame +////////////////////////////////////////// + +MeasureGUI_3Sel_Frame::MeasureGUI_3Sel_Frame( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); +} + +MeasureGUI_3Sel_Frame::~MeasureGUI_3Sel_Frame() +{ +} + ////////////////////////////////////////// // MeasureGUI_SkeletonBox ////////////////////////////////////////// diff --git a/src/MeasureGUI/MeasureGUI_Widgets.h b/src/MeasureGUI/MeasureGUI_Widgets.h index c90e33841..b96201529 100644 --- a/src/MeasureGUI/MeasureGUI_Widgets.h +++ b/src/MeasureGUI/MeasureGUI_Widgets.h @@ -119,6 +119,38 @@ public: ~MeasureGUI_1Sel6LineEdit(); }; +////////////////////////////////////////// +// MeasureGUI_1Sel_Frame +////////////////////////////////////////// + +#include "ui_MeasureGUI_1Sel_Frame_QTD.h" + +class MeasureGUI_1Sel_Frame : public QWidget, + public Ui::MeasureGUI_1Sel_Frame_QTD +{ + Q_OBJECT + +public: + MeasureGUI_1Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 ); + ~MeasureGUI_1Sel_Frame(); +}; + +////////////////////////////////////////// +// MeasureGUI_1TreeWidget_4Buttons +////////////////////////////////////////// + +#include "ui_MeasureGUI_1TreeWidget_4Button_QTD.h" + +class MeasureGUI_1TreeWidget_4Button : public QWidget, + public Ui::MeasureGUI_1TreeWidget_4Button_QTD +{ + Q_OBJECT + +public: + MeasureGUI_1TreeWidget_4Button( QWidget* = 0, Qt::WindowFlags = 0 ); + ~MeasureGUI_1TreeWidget_4Button(); +}; + ////////////////////////////////////////// // MeasureGUI_2Sel1LineEdit ////////////////////////////////////////// @@ -135,6 +167,38 @@ public: ~MeasureGUI_2Sel1LineEdit(); }; +////////////////////////////////////////// +// MeasureGUI_2Sel_Frame +////////////////////////////////////////// + +#include "ui_MeasureGUI_2Sel_Frame_QTD.h" + +class MeasureGUI_2Sel_Frame : public QWidget, + public Ui::MeasureGUI_2Sel_Frame_QTD +{ + Q_OBJECT + +public: + MeasureGUI_2Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 ); + ~MeasureGUI_2Sel_Frame(); +}; + +////////////////////////////////////////// +// MeasureGUI_3Sel_Frame +////////////////////////////////////////// + +#include "ui_MeasureGUI_3Sel_Frame_QTD.h" + +class MeasureGUI_3Sel_Frame : public QWidget, + public Ui::MeasureGUI_3Sel_Frame_QTD +{ + Q_OBJECT + +public: + MeasureGUI_3Sel_Frame( QWidget* = 0, Qt::WindowFlags = 0 ); + ~MeasureGUI_3Sel_Frame(); +}; + ////////////////////////////////////////// // MeasureGUI_SkeletonBox ////////////////////////////////////////// diff --git a/src/OBJECT/CMakeLists.txt b/src/OBJECT/CMakeLists.txt index 7f8ac53dd..ea4cd46af 100755 --- a/src/OBJECT/CMakeLists.txt +++ b/src/OBJECT/CMakeLists.txt @@ -86,6 +86,7 @@ SET(OBJECT_HEADERS GEOM_PainterPolyDataMapper.h GEOM_DeviceActor.h GEOM_Constants.h + GEOM_AISDimension.hxx ) # --- sources --- @@ -102,6 +103,7 @@ SET(OBJECT_SOURCES GEOM_PainterPolyDataMapper.cxx GEOM_DeviceActor.cxx GEOM_Constants.cxx + GEOM_AISDimension.cxx ) # --- rules --- diff --git a/src/OBJECT/GEOM_AISDimension.cxx b/src/OBJECT/GEOM_AISDimension.cxx new file mode 100755 index 000000000..80ba58149 --- /dev/null +++ b/src/OBJECT/GEOM_AISDimension.cxx @@ -0,0 +1,141 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM OBJECT : interactive object for Geometry entities visualization +// File : GEOM_AISDimension.cxx +// Module : GEOM + +#include "GEOM_AISDimension.hxx" + +IMPLEMENT_STANDARD_HANDLE (GEOM_AISLength, AIS_LengthDimension) +IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISLength, AIS_LengthDimension) +IMPLEMENT_STANDARD_HANDLE (GEOM_AISDiameter, AIS_DiameterDimension) +IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISDiameter, AIS_DiameterDimension) +IMPLEMENT_STANDARD_HANDLE (GEOM_AISAngle, AIS_AngleDimension) +IMPLEMENT_STANDARD_RTTIEXT(GEOM_AISAngle, AIS_AngleDimension) + +/* ****************************************************************************** * + * * + * GEOM_AISLength * + * * + * ****************************************************************************** */ + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +GEOM_AISLength::GEOM_AISLength( const Standard_Integer theId ) +: AIS_LengthDimension( gp::Origin(), + gp::Origin(), + gp_Pln( gp::XOY() ) ), + myId( theId ) +{ +} + +//================================================================================= +// function : GetId +// purpose : +//================================================================================= +Standard_Integer GEOM_AISLength::GetId() const +{ + return myId; +} + +//================================================================================= +// function : SetId +// purpose : +//================================================================================= +void GEOM_AISLength::SetId( const Standard_Integer theId ) +{ + myId = theId; +} + + +/* ****************************************************************************** * + * * + * GEOM_AISDiameter * + * * + * ****************************************************************************** */ + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +GEOM_AISDiameter::GEOM_AISDiameter( const Standard_Integer theId ) +: AIS_DiameterDimension( gp_Circ() ), + myId( theId ) +{ +} + +//================================================================================= +// function : GetId +// purpose : +//================================================================================= +Standard_Integer GEOM_AISDiameter::GetId() const +{ + return myId; +} + +//================================================================================= +// function : SetId +// purpose : +//================================================================================= +void GEOM_AISDiameter::SetId( const Standard_Integer theId ) +{ + myId = theId; +} + +/* ****************************************************************************** * + * * + * GEOM_AISAngle * + * * + * ****************************************************************************** */ + +//================================================================================= +// function : Constructor +// purpose : +//================================================================================= +GEOM_AISAngle::GEOM_AISAngle( const Standard_Integer theId ) +: AIS_AngleDimension( gp::Origin(), + gp::Origin(), + gp::Origin() ), + myId( theId ) +{ +} + +//================================================================================= +// function : GetId +// purpose : +//================================================================================= +Standard_Integer GEOM_AISAngle::GetId() const +{ + return myId; +} + +//================================================================================= +// function : SetId +// purpose : +//================================================================================= +void GEOM_AISAngle::SetId( const Standard_Integer theId ) +{ + myId = theId; +} diff --git a/src/OBJECT/GEOM_AISDimension.hxx b/src/OBJECT/GEOM_AISDimension.hxx new file mode 100755 index 000000000..e85fe5ed9 --- /dev/null +++ b/src/OBJECT/GEOM_AISDimension.hxx @@ -0,0 +1,92 @@ +// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// GEOM OBJECT : interactive object for Geometry entities visualization +// File : GEOM_AISDimension.hxx +// Module : GEOM +// +#ifndef GEOM_AISDimension_HeaderFile +#define GEOM_AISDimension_HeaderFile + +#include +#include +#include + +DEFINE_STANDARD_HANDLE(GEOM_AISLength, AIS_LengthDimension) +DEFINE_STANDARD_HANDLE(GEOM_AISDiameter, AIS_DiameterDimension) +DEFINE_STANDARD_HANDLE(GEOM_AISAngle, AIS_AngleDimension) + +//================================================================================= +// class : GEOM_AISLength +// purpose : presentation of length dimension property +//================================================================================= +class GEOM_AISLength : public AIS_LengthDimension +{ +public: + DEFINE_STANDARD_RTTI(GEOM_AISLength) + +public: + Standard_EXPORT GEOM_AISLength( const Standard_Integer theId ); + Standard_EXPORT Standard_Integer GetId() const; + Standard_EXPORT void SetId( const Standard_Integer theId ); + +private: + Standard_Integer myId; +}; + +//================================================================================= +// class : GEOM_AISDiameter +// purpose : presentation of diameter dimension property +//================================================================================= +class GEOM_AISDiameter : public AIS_DiameterDimension +{ +public: + DEFINE_STANDARD_RTTI(GEOM_AISDiameter) + +public: + Standard_EXPORT GEOM_AISDiameter( const Standard_Integer theId ); + Standard_EXPORT Standard_Integer GetId() const; + Standard_EXPORT void SetId( const Standard_Integer theId ); + +private: + Standard_Integer myId; +}; + +//================================================================================= +// class : GEOM_AISAngle +// purpose : presentation of angle dimension property +//================================================================================= +class GEOM_AISAngle : public AIS_AngleDimension +{ +public: + DEFINE_STANDARD_RTTI(GEOM_AISAngle) + +public: + Standard_EXPORT GEOM_AISAngle( const Standard_Integer theId ); + Standard_EXPORT Standard_Integer GetId() const; + Standard_EXPORT void SetId( const Standard_Integer theId ); + +private: + Standard_Integer myId; +}; + +#endif diff --git a/src/OBJECT/GEOM_Constants.cxx b/src/OBJECT/GEOM_Constants.cxx index 95a5840c2..0afd2f258 100644 --- a/src/OBJECT/GEOM_Constants.cxx +++ b/src/OBJECT/GEOM_Constants.cxx @@ -95,8 +95,17 @@ namespace GEOM "IsosColor", // - // outlines color "OutlineColor", // - + // dimensions + "Dimensions" }; return ( type >= GEOM::Visibility && type <= GEOM::LastProperty ) ? names[type] : QString(); } + /*! + \brief Id used for storing properties of objects in study shared between viewers. + */ + int sharedPropertiesId() + { + return INT_MIN; + } } // namespace GEOM diff --git a/src/OBJECT/GEOM_Constants.h b/src/OBJECT/GEOM_Constants.h index 19b0c514f..c166e3a0d 100644 --- a/src/OBJECT/GEOM_Constants.h +++ b/src/OBJECT/GEOM_Constants.h @@ -54,7 +54,8 @@ namespace GEOM PointColor, IsosColor, OutlineColor, - LastProperty = OutlineColor, + Dimensions, + LastProperty = Dimensions, }; GEOM_OBJECT_EXPORT double minDeflection(); @@ -63,6 +64,8 @@ namespace GEOM GEOM_OBJECT_EXPORT QString subSectionSeparator(); GEOM_OBJECT_EXPORT QString propertyName( Property ); + + GEOM_OBJECT_EXPORT int sharedPropertiesId(); } -- 2.39.2