From 9b2e81831312d30b25d80516be6d3398fb8ef6f9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me?= Date: Mon, 12 Oct 2020 16:04:05 +0200 Subject: [PATCH] Fix issues and add unitary test --- src/Events/Events_Listener.cpp | 1 - src/FeaturesAPI/FeaturesAPI.i | 4 +- src/FeaturesAPI/FeaturesAPI_Fillet.cpp | 93 +++-- src/FeaturesAPI/FeaturesAPI_Fillet.h | 16 +- src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp | 38 +- src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 2 + .../FeaturesPlugin_Validators.cpp | 56 +++ .../FeaturesPlugin_Validators.h | 16 + ...aturesPlugin_WidgetFilletMultiRadiuses.cpp | 385 +++++++++--------- ...FeaturesPlugin_WidgetFilletMultiRadiuses.h | 11 +- .../Test/TestFillet_MultiRadius.py | 182 +++++++++ src/FeaturesPlugin/fillet_widget.xml | 41 +- src/ModelAPI/ModelAPI_Events.cpp | 49 +++ src/ModelAPI/ModelAPI_Events.h | 53 +++ src/PythonAPI/model/features/__init__.py | 2 +- 15 files changed, 660 insertions(+), 289 deletions(-) create mode 100644 src/FeaturesPlugin/Test/TestFillet_MultiRadius.py diff --git a/src/Events/Events_Listener.cpp b/src/Events/Events_Listener.cpp index 593f26974..267e6db6b 100644 --- a/src/Events/Events_Listener.cpp +++ b/src/Events/Events_Listener.cpp @@ -34,7 +34,6 @@ void Events_Listener::groupWhileFlush(const std::shared_ptr& the std::shared_ptr aStored = std::dynamic_pointer_cast(aMyGroup->second); aStored->Join(aGroup); - //std::cout<<"Add to group "<eventID().eventText()<shape(); - } + } aPoints.push_back(aShape); } + myvalues()->setSize( aPoints.size() +2, 2 ); std::list::const_iterator aRowsRadiusIter = theRadius.begin(); - ModelAPI_AttributeTables::Value aVal; + ModelAPI_AttributeTables::Value aVal; aVal.myDouble = 0.0; - myvaluescurv()->setValue(aVal, 0, 0 ); - aVal.myDouble = aRowsRadiusIter->value(); - myvaluescurv()->setValue(aVal, 0, 1 ); + myvalues()->setValue(aVal, 0, 0 ); + aVal.myDouble = aRowsRadiusIter->value(); + myvalues()->setValue(aVal, 0, 1 ); aRowsRadiusIter++; int aRowIndex = 1; ListOfShape::const_iterator aPointsIt = aPoints.begin(); @@ -203,41 +204,43 @@ FeaturesAPI_Fillet2D::FeaturesAPI_Fillet2D(const std::shared_ptr aPntCurv = aCurve->project(aPnt); double res = (aPntCurv->distance(first) / taille); aVal.myDouble = res; - myvaluescurv()->setValue(aVal, aRowIndex, 0 ); - aVal.myDouble = aRowsRadiusIter->value(); - myvaluescurv()->setValue(aVal, aRowIndex, 1 ); + myvalues()->setValue(aVal, aRowIndex, 0 ); + aVal.myDouble = aRowsRadiusIter->value(); + myvalues()->setValue(aVal, aRowIndex, 1 ); aRowIndex++; } aVal.myDouble = 1.0; - myvaluescurv()->setValue(aVal, aRowIndex, 0 ); - aVal.myDouble = aRowsRadiusIter->value(); - myvaluescurv()->setValue(aVal, aRowIndex, 1 ); + myvalues()->setValue(aVal, aRowIndex, 0 ); + aVal.myDouble = aRowsRadiusIter->value(); + myvalues()->setValue(aVal, aRowIndex, 1 ); execIfBaseNotEmpty(); } } FeaturesAPI_Fillet2D::FeaturesAPI_Fillet2D(const std::shared_ptr& theFeature, - const ModelHighAPI_Selection & theedgeselected, + const std::list& theBaseObjects, const std::list& thepointCurvCood, const std::list& theRadius) : FeaturesAPI_Fillet(theFeature) { if (initialize()) { fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES(), mycreationMethod); - fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_BY_CURVILEAR_ABSCISSA(), mycreationMethodmulti); - fillAttribute(theedgeselected, edgeselected()); + fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_BY_CURVILEAR_ABSCISSA(), + mycreationMethodmulti); + fillAttribute(theBaseObjects, mybaseObjects); - int aRowIndex = 0; - myvaluescurv()->setSize( thepointCurvCood.size(), 2 ); - std::list::const_iterator aRowsCoodIter = thepointCurvCood.begin(); - std::list::const_iterator aRowsRadiusIter = theRadius.begin(); - for(; aRowsCoodIter != thepointCurvCood.end(); aRowsCoodIter++, aRowsRadiusIter++, aRowIndex++) { - ModelAPI_AttributeTables::Value aVal; + int aRowIndex = 0; + myvaluescurv()->setSize( thepointCurvCood.size(), 2 ); + std::list::const_iterator aRowsCoodIter = thepointCurvCood.begin(); + std::list::const_iterator aRowsRadiusIter = theRadius.begin(); + for(; aRowsCoodIter != thepointCurvCood.end(); + aRowsCoodIter++, aRowsRadiusIter++, aRowIndex++) { + ModelAPI_AttributeTables::Value aVal; aVal.myDouble = aRowsCoodIter->value(); myvaluescurv()->setValue(aVal, aRowIndex, 0 ); - aVal.myDouble = aRowsRadiusIter->value(); + aVal.myDouble = aRowsRadiusIter->value(); myvaluescurv()->setValue(aVal, aRowIndex, 1 ); - } + } execIfBaseNotEmpty(); } } @@ -255,7 +258,7 @@ void FeaturesAPI_Fillet2D::setBase(const std::list& theB } void FeaturesAPI_Fillet2D::setRadius(const ModelHighAPI_Double& theRadius) -{ +{ fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod); fillAttribute(theRadius, myradius); @@ -264,7 +267,7 @@ void FeaturesAPI_Fillet2D::setRadius(const ModelHighAPI_Double& theRadius) void FeaturesAPI_Fillet2D::setRadius(const ModelHighAPI_Double& theRadius1, const ModelHighAPI_Double& theRadius2) -{ +{ fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod); fillAttribute(theRadius1, mystartRadius); fillAttribute(theRadius2, myendRadius); @@ -279,48 +282,52 @@ void FeaturesAPI_Fillet2D::dump(ModelHighAPI_Dumper& theDumper) const AttributeSelectionListPtr anAttrObjects = aBase->selectionList(FeaturesPlugin_Fillet::OBJECT_LIST_ID()); - - if ( aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD())->value() + + if ( aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD())->value() == FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES() ) { AttributeSelectionPtr anAttrEdgeSelec = aBase->selection(FeaturesPlugin_Fillet::EDGE_SELECTED_ID()); - if( aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES())->value() + if( aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES())->value() == FeaturesPlugin_Fillet::CREATION_METHOD_BY_POINTS() ) - { + { + AttributeSelectionListPtr anAttrPoint = aBase->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); - AttributeTablesPtr anAttrTable = + AttributeTablesPtr anAttrTable = aBase->tables(FeaturesPlugin_Fillet::VALUES_ID()); - theDumper << aBase << " = model.addFillet(" << aDocName << ", " << anAttrEdgeSelec; - theDumper << ", " << anAttrPoint << ", "; + theDumper << aBase << " = model.addFilletMultiRadiusByPoints(" << aDocName; + theDumper << ", " << anAttrEdgeSelec; + theDumper << ", " << anAttrPoint ; theDumper<<", ["; for(int aRow = 0; aRow < myvalues()->rows(); aRow++) { - if (aRow != 0) + if (aRow != 0){ theDumper<<", "; + } theDumper<value(aRow, 1).myDouble; } theDumper<<"]"; }else{ - AttributeTablesPtr anAttrTable = + AttributeTablesPtr anAttrTable = aBase->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); - theDumper << aBase << " = model.addFillet(" << aDocName << ", " << anAttrEdgeSelec; + theDumper << aBase << " = model.addFilletMultiRadiusBycurvAbs(" << aDocName; + theDumper << ", " << anAttrObjects; theDumper << ", "; theDumper<<"["; - for(int aRow = 1; aRow < myvalues()->rows()-1; aRow++) { - if (aRow != 1) + for(int aRow = 0; aRow < myvaluescurv()->rows(); aRow++) { + if (aRow != 0) theDumper<<", "; - theDumper<value(aRow, 0).myDouble; + theDumper<value(aRow, 0).myDouble; } theDumper<<"],"; theDumper<<"["; - for(int aRow = 0; aRow < myvalues()->rows(); aRow++) { + for(int aRow = 0; aRow < myvaluescurv()->rows(); aRow++) { if (aRow != 0) theDumper<<", "; - theDumper<value(aRow, 1).myDouble; + theDumper<value(aRow, 1).myDouble; } theDumper<<"]"; } @@ -378,7 +385,7 @@ FilletPtr addFillet(const std::shared_ptr& thePart, return aFillet; } -FilletPtr addFillet(const std::shared_ptr& thePart, +FilletPtr addFilletMultiRadiusByPoints(const std::shared_ptr& thePart, const ModelHighAPI_Selection & theedgeselected, const std::list& thepoint, const std::list& theRadius, @@ -396,8 +403,8 @@ FilletPtr addFillet(const std::shared_ptr& thePart, return aFillet; } -FilletPtr addFillet(const std::shared_ptr& thePart, - const ModelHighAPI_Selection & theedgeselected, +FilletPtr addFilletMultiRadiusBycurvAbs(const std::shared_ptr& thePart, + const std::list& theBaseObjects, const std::list& thepointCurvCood, const std::list& theRadius, const bool keepSubResults) @@ -409,7 +416,7 @@ FilletPtr addFillet(const std::shared_ptr& thePart, FilletPtr aFillet; - aFillet.reset(new FeaturesAPI_Fillet2D(aFeature, theedgeselected, thepointCurvCood, theRadius)); + aFillet.reset(new FeaturesAPI_Fillet2D(aFeature, theBaseObjects, thepointCurvCood, theRadius)); return aFillet; } \ No newline at end of file diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.h b/src/FeaturesAPI/FeaturesAPI_Fillet.h index 258d6e8ee..367ec3523 100644 --- a/src/FeaturesAPI/FeaturesAPI_Fillet.h +++ b/src/FeaturesAPI/FeaturesAPI_Fillet.h @@ -137,11 +137,11 @@ public: const ModelHighAPI_Selection& theedgeselected, const std::list& thepoint, const std::list& theRadius); - + /// Constructor with values. FEATURESAPI_EXPORT explicit FeaturesAPI_Fillet2D(const std::shared_ptr& theFeature, - const ModelHighAPI_Selection& theedgeselected, + const std::list& theBaseObjects, const std::list& thepointCurvCood, const std::list& theRadius); /// Destructor. @@ -163,13 +163,13 @@ public: /** Base objects */, arraypointradiusbypoint, FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS(), ModelAPI_AttributeSelectionList, - /** Base objects */, + /** Base objects */, myvalues, FeaturesPlugin_Fillet::VALUES_ID(), ModelAPI_AttributeTables, /** table for methode multi-radiuses by point */, myvaluescurv, FeaturesPlugin_Fillet::VALUES_CURV_ID(), ModelAPI_AttributeTables, - /** table for methode multi-radiuses by curviliean coodinate */, + /** table for methode multi-radiuses by curviliean coodinate */, radius, FeaturesPlugin_Fillet::RADIUS_ID(), ModelAPI_AttributeDouble, /** Value of the fixed radius fillet */, @@ -213,7 +213,7 @@ FilletPtr addFillet(const std::shared_ptr& thePart, /// \ingroup CPPHighAPI /// \brief Create Fillet feature. FEATURESAPI_EXPORT -FilletPtr addFillet(const std::shared_ptr& thePart, +FilletPtr addFilletMultiRadiusByPoints(const std::shared_ptr& thePart, const ModelHighAPI_Selection & theedgeselected, const std::list& thepoint, const std::list& theRadius, @@ -223,10 +223,10 @@ FilletPtr addFillet(const std::shared_ptr& thePart, /// \ingroup CPPHighAPI /// \brief Create Fillet feature. FEATURESAPI_EXPORT -FilletPtr addFillet( const std::shared_ptr& thePart, - const ModelHighAPI_Selection & theedgeselected, +FilletPtr addFilletMultiRadiusBycurvAbs( const std::shared_ptr& thePart, + const std::list& theBaseObjects, const std::list& thepointCurvCood, const std::list& theRadius, const bool keepSubResults= false); - + #endif // FeaturesAPI_Fillet_H_ diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp index 79292632e..eb8794a03 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp @@ -76,6 +76,7 @@ void FeaturesPlugin_Fillet::initAttributes() data()->addAttribute(ARRAY_POINT_RADIUS_BY_POINTS(), ModelAPI_AttributeSelectionList::typeId()); data()->addAttribute(CREATION_METHOD_BY_POINTS(), ModelAPI_AttributeString::typeId()); + data()->addAttribute(CREATION_METHOD_BY_CURVILEAR_ABSCISSA(), ModelAPI_AttributeString::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_RADIUS_ID()); @@ -85,27 +86,53 @@ void FeaturesPlugin_Fillet::initAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHOD_MULTIPLES_RADIUSES()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHOD_BY_CURVILEAR_ABSCISSA()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHOD_BY_POINTS()); + tables(VALUES_ID())->setSize(2,2); + tables(VALUES_CURV_ID())->setSize(2,2); + ModelAPI_AttributeTables::Value aVar; + aVar.myDouble = 0.0; + tables(VALUES_ID())->setValue(aVar,0,0); + tables(VALUES_CURV_ID())->setValue(aVar,0,0); + aVar.myDouble = 1; + tables(VALUES_ID())->setValue(aVar,0,1); + tables(VALUES_CURV_ID())->setValue(aVar,0,1); + + tables(VALUES_ID())->setValue(aVar,1,0); + tables(VALUES_CURV_ID())->setValue(aVar,1,0); + aVar.myDouble = 2; + tables(VALUES_ID())->setValue(aVar,1,1); + tables(VALUES_CURV_ID())->setValue(aVar,1,1); initVersion(aSelectionList); } AttributePtr FeaturesPlugin_Fillet::objectsAttribute() -{ +{ return attribute(OBJECT_LIST_ID()); } void FeaturesPlugin_Fillet::attributeChanged(const std::string& theID) { if (theID == EDGE_SELECTED_ID() - && string(CREATION_METHOD())->value() == CREATION_METHOD_MULTIPLES_RADIUSES()) { - + && string(CREATION_METHOD())->value() == CREATION_METHOD_MULTIPLES_RADIUSES() + && string(CREATION_METHOD_MULTIPLES_RADIUSES())->value() == CREATION_METHOD_BY_POINTS()) { + AttributeSelectionPtr anEdges = std::dynamic_pointer_cast(attribute(EDGE_SELECTED_ID())); AttributeSelectionListPtr array = selectionList(OBJECT_LIST_ID()); if(array->isInitialized()) array->clear(); - array->append(anEdges->namingName() ); + array->append(anEdges->context(), anEdges->value()); // anEdges->namingName() ); + + } + if( theID == OBJECT_LIST_ID() && + !(string(CREATION_METHOD())->value() == CREATION_METHOD_MULTIPLES_RADIUSES() + && string(CREATION_METHOD_MULTIPLES_RADIUSES())->value() == CREATION_METHOD_BY_POINTS() ) ){ + + data()->selection(EDGE_SELECTED_ID())->setValue(ObjectPtr(),GeomShapePtr()); + } + + data()->execState(ModelAPI_StateMustBeUpdated); } const std::string& FeaturesPlugin_Fillet::modifiedShapePrefix() const @@ -128,8 +155,6 @@ GeomMakeShapePtr FeaturesPlugin_Fillet::performOperation(const GeomShapePtr& the std::shared_ptr aFilletBuilder; ListOfShape aFilletEdges = extractEdges(theEdges); - - std::cout << "coucou aCreationMethod->value() = " << aCreationMethod->value()<< std::endl; if ( aCreationMethod->value() == CREATION_METHOD_MULTIPLES_RADIUSES() ) { @@ -153,7 +178,6 @@ GeomMakeShapePtr FeaturesPlugin_Fillet::performOperation(const GeomShapePtr& the aVal = aTablesAttr->value(k, 1); radiuses.push_back(aVal.myDouble); } - aFilletBuilder.reset(new GeomAlgoAPI_Fillet(theSolid, aFilletEdges, coodCurv,radiuses)); }else diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index e68b35d69..92db78d53 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -112,6 +112,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorConcealedResult); aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection", new FeaturesPlugin_ValidatorFilletSelection); + aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelectionEdge", + new FeaturesPlugin_ValidatorFilletSelectionEdge); aFactory->registerValidator("FeaturesPlugin_ValidatorFillet1DSelection", new FeaturesPlugin_ValidatorFillet1DSelection); aFactory->registerValidator("FeaturesPlugin_ValidatorCircular", diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 9235d933e..2245dc5ce 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -971,7 +971,63 @@ bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAtt return true; } +//================================================================================================== +bool FeaturesPlugin_ValidatorFilletSelectionEdge::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributeSelectionPtr anAttrSelection = + std::dynamic_pointer_cast(theAttribute); + if(!anAttrSelection.get()) { +// LCOV_EXCL_START + theError = + "Error: Empty attribute selection."; + return false; +// LCOV_EXCL_STOP + } + + FeaturePtr aFeature = std::dynamic_pointer_cast(theAttribute->owner()); + // Check all selected entities are sub-shapes of single solid + GeomShapePtr aBaseSolid; + ResultPtr aContext = anAttrSelection->context(); + if(!aContext.get()) { + FeaturePtr aContFeat = anAttrSelection->contextFeature(); + if (!aContFeat.get() || !aContFeat->results().size() || + aContFeat->firstResult()->groupName() != ModelAPI_ResultBody::group()) { + theError = "Error: Empty selection context."; + return false; + } + if (aContFeat->results().size() == 1) + aContext = aContFeat->firstResult(); + else { + theError = "Error: Too many shapes selected."; + return false; + } + } + + ResultBodyPtr aContextOwner = ModelAPI_Tools::bodyOwner(aContext, true); + GeomShapePtr anOwner = aContext->shape(); + GeomShapePtr aTopLevelOwner = aContextOwner.get() ? aContextOwner->shape() : anOwner; + + if (!anOwner) { + theError = "Error: wrong feature is selected."; + return false; + } + + if (anOwner->shapeType() != GeomAPI_Shape::SOLID && + anOwner->shapeType() != GeomAPI_Shape::COMPSOLID) { + theError = "Error: Not all selected shapes are sub-shapes of solids."; + return false; + } + if (!aBaseSolid) + aBaseSolid = aTopLevelOwner; + else if (!aBaseSolid->isEqual(aTopLevelOwner)) { + theError = "Error: Sub-shapes of different solids have been selected."; + return false; + } + return true; +} //================================================================================================== bool FeaturesPlugin_ValidatorFillet1DSelection::isValid(const AttributePtr& theAttribute, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index 951d4c52f..619a4b520 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -188,6 +188,22 @@ public: Events_InfoMessage& theError) const; }; +/// \class FeaturesPlugin_ValidatorFilletSelectionEdge +/// \ingroup Validators +/// \brief Validates selection Edge for fillet operation with method multi radius. +class FeaturesPlugin_ValidatorFilletSelectionEdge: public ModelAPI_AttributeValidator +{ +public: + /// \return True if the attribute is valid. It checks whether the selection + /// is acceptable for boolean operation. + /// \param[in] theAttribute an attribute to check. + /// \param[in] theArguments a filter parameters. + /// \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + /// \class FeaturesPlugin_ValidatorFillet1DSelection /// \ingroup Validators /// \brief Validates selection for 1d-fillet operation. diff --git a/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.cpp b/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.cpp index 377873745..ff9e6856a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.cpp @@ -66,6 +66,38 @@ const char* MYFirstCol = "Shape"; const char* MYTrue = "True"; const char* MYFalse = "False"; +class TextFieldDoubleValidator : public QDoubleValidator { +public: + TextFieldDoubleValidator (QObject * parent = 0) : QDoubleValidator(parent) {} + TextFieldDoubleValidator (double bottom, double top, int decimals, QObject * parent) : + QDoubleValidator(bottom, top, decimals, parent) {} + + QValidator::State validate(QString & s, int & pos) const { + if (s.isEmpty() || s.startsWith("0.") || s == "0" ){//|| s.startsWith("-")) { + // allow empty field or minus sign + return QValidator::Intermediate; + } + // check length of decimal places + QChar point = locale().decimalPoint(); + if(s.indexOf(point) != -1) { + int lengthDecimals = s.length() - s.indexOf(point) - 1; + if (lengthDecimals > decimals()) { + return QValidator::Invalid; + } + } + + // check range of value + bool isNumber; + double value = locale().toDouble(s, &isNumber); + if (isNumber && bottom() <= value && value <= top()) { + return QValidator::Acceptable; + } + return QValidator::Invalid; + } + +}; + + DataArrayItemDelegate::DataArrayItemDelegate(bool theTypeMethode) : QStyledItemDelegate(), myTypeMethodePoint(theTypeMethode) @@ -90,13 +122,19 @@ QWidget* DataArrayItemDelegate::createEditor(QWidget* theParent, theOption, theIndex)); if (aLineEdt) { - if( theIndex.column() == 2 ) - aLineEdt->setValidator(new QDoubleValidator(0.0 , 10000.0, 6, aLineEdt)); - else - aLineEdt->setValidator(new QDoubleValidator(0.00001 , 0.9999, 6, aLineEdt)); + if( theIndex.column() == 1 ){ + TextFieldDoubleValidator* doubleVal = + new TextFieldDoubleValidator(0.00001 , 0.99, 6, aLineEdt); + doubleVal->setNotation(TextFieldDoubleValidator::StandardNotation); + aLineEdt->setValidator(doubleVal); + } + else{ + QDoubleValidator* doubleVal = new QDoubleValidator(0.0 , 10000.0, 6, aLineEdt); + doubleVal->setNotation(QDoubleValidator::StandardNotation); + aLineEdt->setValidator(doubleVal); + } aEditor = aLineEdt; } - } connect(aEditor, SIGNAL(textEdited(const QString&)), @@ -131,48 +169,49 @@ ModuleBase_WidgetSelector(theParent, theWorkshop, theData), myHeaderEditor(0), aRadiusesFrame->setFrameShape(QFrame::Box); aRadiusesFrame->setFrameStyle(QFrame::StyledPanel); QVBoxLayout* aRadiusesLayout = new QVBoxLayout(); - + myDataTbl = new QTableWidget(2, 3, aRadiusesFrame); myDelegate = new DataArrayItemDelegate(myTypeMethodeBypoint); - myDataTbl->installEventFilter(this); + //JL_CGLB myDataTbl->installEventFilter(this); myDataTbl->setItemDelegate(myDelegate); myDataTbl->verticalHeader()->hide(); myDataTbl->setRowHeight(0, 25); - myDataTbl->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); - + //JL_CGLB myDataTbl->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); + if(myTypeMethodeBypoint){ myfirstRowValue.push_back("Start extremity"); - myfirstRowValue.push_back("0"); - myfirstRowValue.push_back("0.5"); - myLastRowValue.push_back("End extremity"); - myLastRowValue.push_back("1"); - myLastRowValue.push_back("0.5"); + myfirstRowValue.push_back("0"); + myfirstRowValue.push_back("1"); + myLastRowValue.push_back("End extremity"); + myLastRowValue.push_back("1"); + myLastRowValue.push_back("2"); }else{ myfirstRowValue.push_back("0"); - myfirstRowValue.push_back("0"); - myfirstRowValue.push_back("1"); - myLastRowValue.push_back("1"); - myLastRowValue.push_back("1"); - myLastRowValue.push_back("2"); + myfirstRowValue.push_back("0"); + myfirstRowValue.push_back("1"); + myLastRowValue.push_back("1"); + myLastRowValue.push_back("1"); + myLastRowValue.push_back("2"); } - + if(myTypeMethodeBypoint) myDataTbl->hideColumn(1); else myDataTbl->hideColumn(0); - + QStringList aHeaders; aHeaders << "Point"; - aHeaders << "Curvilinear Abscissa"; + aHeaders << "Curvilinear \n Abscissa"; aHeaders << "Radius"; - + myDataTbl->setHorizontalHeaderLabels(aHeaders); - + //myDataTbl->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); + QTableWidgetItem* aItem; for(int j =0; j<3;j++) { @@ -188,8 +227,6 @@ ModuleBase_WidgetSelector(theParent, theWorkshop, theData), myHeaderEditor(0), connect(myDataTbl, SIGNAL(cellChanged(int, int)), SLOT(onTableEdited(int, int))); - myDataTbl->horizontalHeader()->viewport()->installEventFilter(this); - aRadiusesLayout->addWidget(myDataTbl); ///======================== @@ -212,7 +249,7 @@ ModuleBase_WidgetSelector(theParent, theWorkshop, theData), myHeaderEditor(0), font.setPointSize(12); myRemoveBtn->setFont(font); aBtnLayout->addWidget(myRemoveBtn); - + aRadiusesFrame->setLayout(aRadiusesLayout ) ; aMainLayout->addWidget(aRadiusesFrame); @@ -241,7 +278,6 @@ QIntList FeaturesPlugin_WidgetFilletMultiRadiuses::shapeTypes() const //********************************************************************************** void FeaturesPlugin_WidgetFilletMultiRadiuses::deactivate() { - ModuleBase_WidgetSelector::deactivate(); storeValueCustom(); } @@ -249,51 +285,7 @@ void FeaturesPlugin_WidgetFilletMultiRadiuses::deactivate() //********************************************************************************** bool FeaturesPlugin_WidgetFilletMultiRadiuses::eventFilter(QObject* theObject, QEvent* theEvent) { - QObject* aObject = 0; - - if (myDataTbl->horizontalHeader()->viewport() == theObject) { - aObject = theObject; - } - if (aObject) { - if (theEvent->type() == QEvent::MouseButtonDblClick) { - if (myHeaderEditor) { //delete previous editor - myHeaderEditor->deleteLater(); - myHeaderEditor = 0; - } - QMouseEvent* aMouseEvent = static_cast(theEvent); - QHeaderView* aHeader = static_cast(aObject->parent()); - QTableWidget* aTable = static_cast(aHeader->parentWidget()); - - int aShift = aTable->horizontalScrollBar()->value(); - int aPos = aMouseEvent->x(); - int aIndex = aHeader->logicalIndex(aHeader->visualIndexAt(aPos)); - if (aIndex > 0) { - QRect aRect; - aRect.setLeft(aHeader->sectionPosition(aIndex)); - aRect.setWidth(aHeader->sectionSize(aIndex)); - aRect.setTop(0); - aRect.setHeight(aHeader->height()); - aRect.adjust(1, 1, -1, -1); - aRect.translate(-aShift, 0); - - myHeaderEditor = new QLineEdit(aHeader->viewport()); - myHeaderEditor->move(aRect.topLeft()); - myHeaderEditor->resize(aRect.size()); - myHeaderEditor->setFrame(false); - QString aText = aHeader->model()-> - headerData(aIndex, aHeader->orientation()).toString(); - myHeaderEditor->setText(aText); - myHeaderEditor->setFocus(); - //myEditIndex = aIndex; //save for future use - myHeaderEditor->installEventFilter(this); //catch focus out event - //if user presses Enter it should close editor - connect(myHeaderEditor, SIGNAL(returnPressed()), aTable, SLOT(setFocus())); - myHeaderEditor->show(); - return true; - } - } - } else if (theEvent->type() == QEvent::FocusIn) { - + if (theEvent->type() == QEvent::FocusIn) { QTableWidget* aTable = dynamic_cast(theObject); if (aTable) { ModuleBase_IPropertyPanel* aPanel = myWorkshop->propertyPanel(); @@ -303,18 +295,13 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::eventFilter(QObject* theObject, Q } } else if (theEvent->type() == QEvent::Show ) { - - /* ModuleBase_IPropertyPanel* aPanel = myWorkshop->propertyPanel(); - if (aPanel->activeWidget() != this) { - aPanel->activateWidget(this, false); - }*/ DataPtr aData = myFeature->data(); if( myTypeMethodeBypoint ) aData->string(FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES()) ->setValue(FeaturesPlugin_Fillet::CREATION_METHOD_BY_POINTS() ); else aData->string(FeaturesPlugin_Fillet::CREATION_METHOD_MULTIPLES_RADIUSES()) - ->setValue(FeaturesPlugin_Fillet::CREATION_METHOD_BY_CURVILEAR_ABSCISSA() ); + ->setValue(FeaturesPlugin_Fillet::CREATION_METHOD_BY_CURVILEAR_ABSCISSA() ); } return ModuleBase_WidgetSelector::eventFilter(theObject, theEvent); } @@ -330,7 +317,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::storeValueCustom() if(myTypeMethodeBypoint) aTablesAttr = aData->tables(FeaturesPlugin_Fillet::VALUES_ID()); - else + else aTablesAttr = aData->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); // Store data- @@ -344,7 +331,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::storeValueCustom() QString aTblVal = myDataTbl->item(i, j+1)->text(); aTablesAttr->setValue( getValue( aTblVal ), i, j); } - } + } return true; } @@ -352,7 +339,6 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::storeValueCustom() //********************************************************************************** bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() { - if ( !mySetSelection) { mySetSelection = true; return false; @@ -361,17 +347,18 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() AttributeTablesPtr aTablesAttr; - if(myTypeMethodeBypoint) + if(myTypeMethodeBypoint){ aTablesAttr = aData->tables(FeaturesPlugin_Fillet::VALUES_ID()); - else + } + else{ aTablesAttr = aData->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); + } AttributeSelectionPtr anEdges = - std::dynamic_pointer_cast(aData->attribute(FeaturesPlugin_Fillet::EDGE_SELECTED_ID())); + std::dynamic_pointer_cast( + aData->attribute(FeaturesPlugin_Fillet::EDGE_SELECTED_ID())); - - - std::map> aValuesSort; + std::map> aValuesSort; double res; int aRows = 0; @@ -379,7 +366,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() if(myTypeMethodeBypoint) { if( !anEdges->isInitialized() ) - return; + return false; GeomEdgePtr anEdge = GeomEdgePtr(new GeomAPI_Edge( anEdges->value())); GeomPointPtr first = anEdge->firstPoint(); @@ -388,9 +375,10 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() std::shared_ptr aCurve(new GeomAPI_Curve(anEdges->value())); - // Load points - AttributeSelectionListPtr aSelectionListAttr = aData->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); - AttributeDoubleArrayPtr aArrayAttr; + // Load points + AttributeSelectionListPtr aSelectionListAttr = + aData->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); + AttributeDoubleArrayPtr aArrayAttr; ListOfShape aPoints; std::set aContexts; @@ -403,7 +391,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() if (!aShape.get()) { aShape = aContext->shape(); - } + } aPoints.push_back(aShape); } @@ -418,32 +406,32 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() QString aName = QString::fromStdWString(attsel->namingName()); QString aRad = findRadius( QString::number(res) ); if ( aValuesSort.find( res ) == aValuesSort.end() ) - aValuesSort[ res ] = std::make_pair(aName, aRad ); + aValuesSort[ res ] = std::make_pair(aName, aRad ); i++; - } - - res = 0.0; - aValuesSort[ res ] = std::make_pair (myfirstRowValue[0], findRadius( QString::number(res) )) ; + } + + res = 0.0; + aValuesSort[ res ] = std::make_pair (myfirstRowValue[0], findRadius( QString::number(res) )); res = 1.0; - aValuesSort[ res ] = std::make_pair (myLastRowValue[0], findRadius( QString::number(res) )) ; + aValuesSort[ res ] = std::make_pair (myLastRowValue[0], findRadius( QString::number(res) )); aRows = aValuesSort.size(); }else{ ModelAPI_AttributeTables::Value aVal; - if (aTablesAttr->isInitialized()){ - + if (aTablesAttr->isInitialized()){ for (int anIndex = 0; anIndex < aTablesAttr->rows(); ++anIndex) { aVal = aTablesAttr->value(anIndex,0); double curv = getValueText(aVal).toDouble(); - if ( aValuesSort.find( curv ) == aValuesSort.end() ) - aValuesSort[ curv ] = std::make_pair(getValueText(aVal), findRadius(getValueText(aVal))); + if ( aValuesSort.find( curv ) == aValuesSort.end() ) + aValuesSort[ curv ] = std::make_pair(getValueText(aVal), + findRadius(getValueText(aVal))); } - aRows = aTablesAttr->rows(); + aRows = aValuesSort.size(); }else{ - res = 0.0; - aValuesSort[ res ] = std::make_pair (myfirstRowValue[0], myfirstRowValue[2]) ; + res = 0.0; + aValuesSort[ res ] = std::make_pair (myfirstRowValue[0], myfirstRowValue[2]); res = 1.0; - aValuesSort[ res ] = std::make_pair (myLastRowValue[0], myLastRowValue[2]) ; + aValuesSort[ res ] = std::make_pair (myLastRowValue[0], myLastRowValue[2]); aRows = 2; } @@ -452,19 +440,20 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() QTableWidgetItem* aItem = 0; myDataTbl->blockSignals(true); aItem = myDataTbl->item( myDataTbl->rowCount() -1, 0 ); - aItem->setFlags(Qt::NoItemFlags | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); + aItem->setFlags(Qt::NoItemFlags + | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); aItem = myDataTbl->item( myDataTbl->rowCount() -1, 1 ); - aItem->setFlags(Qt::NoItemFlags | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); - + aItem->setFlags(Qt::NoItemFlags | Qt::ItemIsSelectable + | Qt::ItemIsEnabled | Qt::ItemIsEditable); myDataTbl->setRowCount(aRows); - - itValuesSort = aValuesSort.begin(); + + itValuesSort = aValuesSort.begin(); for (int k = 0; k < aRows; k++, ++itValuesSort ) { std::pair elem = itValuesSort->second; - QString aCurv = QString::number(itValuesSort->first); + QString aCurv = QString::number(itValuesSort->first); aItem = myDataTbl->item(k, 0); if (aItem) { @@ -480,7 +469,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() aItem = new QTableWidgetItem(aCurv); myDataTbl->setItem(k, 1, aItem); } - aItem = myDataTbl->item(k, 2); + aItem = myDataTbl->item(k, 2); if (aItem) { aItem->setText( elem.second); } else { @@ -493,7 +482,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() aItem = myDataTbl->item(myDataTbl->rowCount()-1, 1 ); aItem->setFlags(Qt::NoItemFlags | Qt::ItemIsEnabled ); myDataTbl->blockSignals(false); - + return true; } @@ -501,44 +490,38 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses::restoreValueCustom() //********************************************************************************** void FeaturesPlugin_WidgetFilletMultiRadiuses::onAdd() { - QModelIndex index = myDataTbl->currentIndex(); int i = index.row(); - if( i == -1 ) - return false; + if( i != -1 + && myDataTbl->currentItem()->isSelected() && myDataTbl->rowCount() >2 ) + { + myDataTbl->blockSignals(true); - if( !myDataTbl->currentItem()->isSelected() && myDataTbl->rowCount() >2 ) - return false; + if ( i == myDataTbl->rowCount() -1) + i = myDataTbl->rowCount() - 2; - myDataTbl->blockSignals(true); + if ( i == 0) + i = 1; + else + i= i+1; + myDataTbl->model()->insertRow(i); - if ( i == myDataTbl->rowCount() -1) - i = myDataTbl->rowCount() - 2; - - if ( i == 0) - i = 1; - else - i= i+1; - - - myDataTbl->model()->insertRow(i); - QTableWidgetItem* aItem =0; - - aItem = myDataTbl->item( i, 0 ); - aItem = new QTableWidgetItem( "New" ); - myDataTbl->setItem(i, 0, aItem); - aItem = new QTableWidgetItem(myfirstRowValue[1]); - myDataTbl->setItem(i, 1, aItem); - aItem = new QTableWidgetItem("-1"); - myDataTbl->setItem(i, 1, aItem); - aItem = new QTableWidgetItem(myfirstRowValue[2]); - myDataTbl->setItem(i, 2, aItem); - aItem = new QTableWidgetItem(myLastRowValue[2]); - myDataTbl->setItem(i, 2, aItem); - myDataTbl->blockSignals(false); - - emit valuesChanged(); - myDataTbl->setCurrentCell( i, 0); + QTableWidgetItem* aItem =0; + + aItem = myDataTbl->item( i, 0 ); + aItem = new QTableWidgetItem( "" ); + myDataTbl->setItem(i, 0, aItem); + + aItem = new QTableWidgetItem("0.1"); + myDataTbl->setItem(i, 1, aItem); + + aItem = new QTableWidgetItem("0.5"); + myDataTbl->setItem(i, 2, aItem); + myDataTbl->blockSignals(false); + + emit valuesChanged(); + myDataTbl->setCurrentCell( i, 0); + } } //********************************************************************************** @@ -546,63 +529,64 @@ void FeaturesPlugin_WidgetFilletMultiRadiuses::onRemove() { QModelIndex index = myDataTbl->currentIndex(); - if( !myDataTbl->currentItem()->isSelected() && myDataTbl->rowCount() >2 ) - return false; - - myDataTbl->blockSignals(true); - if (index.row() == -1 - || index.row() == 0 - || index.row() == myDataTbl->rowCount() -1) - return; - - if (myTypeMethodeBypoint) - { - QTableWidgetItem* aItem = 0; - - QString aName = myDataTbl->item( index.row() , 0 )->text(); - AttributeSelectionListPtr aSelList = - myFeature->data()->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); + if( myDataTbl->currentItem()->isSelected() && myDataTbl->rowCount() >2 + && index.row() != -1 + && index.row() != 0 + && index.row() != myDataTbl->rowCount() -1){ - AttributeSelectionPtr aAttr; - for (int i = 0; i < aSelList->size(); i++) { - aAttr = aSelList->value(i); - if( aName == QString::fromStdWString( aAttr->namingName()) ) - { - aSelList->remove({i}); - } + myDataTbl->blockSignals(true); + if (myTypeMethodeBypoint) + { + QString aName = myDataTbl->item( index.row() , 0 )->text(); + AttributeSelectionListPtr aSelList = + myFeature->data() + ->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); + + AttributeSelectionPtr aAttr; + for (int i = 0; i < aSelList->size(); i++) { + aAttr = aSelList->value(i); + if( aName == QString::fromStdWString( aAttr->namingName()) ) + { + aSelList->remove({i}); + } + } } - } - myDataTbl->model()->removeRow(index.row()); - myDataTbl->blockSignals(false); + myDataTbl->model()->removeRow(index.row()); + myDataTbl->blockSignals(false); - emit valuesChanged(); + emit valuesChanged(); + } } //********************************************************************************** void FeaturesPlugin_WidgetFilletMultiRadiuses::onTableEdited(int theRow, int theCol) { // Do not store here column of names - if (theCol == 0) - return; + if (theCol != 0 && myFeature.get()) + { - if (!myFeature.get()) - return; + if( theCol == 1 && myDataTbl->item(theRow, theCol)->text() == "0" ) { + myDataTbl->blockSignals(true); + myDataTbl->item(theRow, theCol)->setText("0.1"); + myDataTbl->blockSignals(false); + } - ModelAPI_AttributeTables::Value aVal = getValue(myDataTbl->item(theRow, theCol)->text()); + ModelAPI_AttributeTables::Value aVal = getValue(myDataTbl->item(theRow, theCol)->text()); - AttributeTablesPtr aTablesAttr; + AttributeTablesPtr aTablesAttr; - if(myTypeMethodeBypoint) - aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_ID()); - else - aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); + if(myTypeMethodeBypoint) + aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_ID()); + else + aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); - if (aTablesAttr->isInitialized()) - { - aTablesAttr->setValue(aVal,theRow, theCol - 1); - emit valuesChanged(); + if (aTablesAttr->isInitialized()) + { + aTablesAttr->setValue(aVal,theRow, theCol - 1); + emit valuesChanged(); + } } -} +} //********************************************************************************** bool FeaturesPlugin_WidgetFilletMultiRadiuses:: @@ -614,7 +598,6 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses:: //********************************************************************************** bool FeaturesPlugin_WidgetFilletMultiRadiuses::processEnter() { - return true; } @@ -626,27 +609,25 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses:: if ( theValues.size() > 1 || !myTypeMethodeBypoint || theValues.size() == 0 ) { mySetSelection = false; - return false; + return false; } QModelIndex index = myDataTbl->currentIndex(); if( index.row() == -1 ) { mySetSelection = false; - return false; + return false; } if( !myDataTbl->currentItem()->isSelected()){ mySetSelection = false; - return false; + return false; } - AttributeSelectionListPtr aSelList = myFeature->data()->selectionList(FeaturesPlugin_Fillet::ARRAY_POINT_RADIUS_BY_POINTS()); ResultPtr aResult; GeomShapePtr aShape; - int aNbData = 0; ModuleBase_ViewerPrsPtr aValue = theValues.first(); aResult = std::dynamic_pointer_cast(aValue->object()); aShape = aValue->shape(); @@ -655,7 +636,7 @@ bool FeaturesPlugin_WidgetFilletMultiRadiuses:: onRemove(); }else{ mySetSelection = false; - return false; + return false; } return true; @@ -683,7 +664,8 @@ QList> } //********************************************************************************** -ModelAPI_AttributeTables::Value FeaturesPlugin_WidgetFilletMultiRadiuses::getValue(QString theStrVal) const +ModelAPI_AttributeTables::Value + FeaturesPlugin_WidgetFilletMultiRadiuses::getValue(QString theStrVal) const { ModelAPI_AttributeTables::Value aVal; aVal.myDouble = theStrVal.toDouble(); @@ -697,9 +679,9 @@ QString FeaturesPlugin_WidgetFilletMultiRadiuses::findRadius(QString thename) co if(myTypeMethodeBypoint) aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_ID()); - else + else aTablesAttr = myFeature->data()->tables(FeaturesPlugin_Fillet::VALUES_CURV_ID()); - + for(int i = 0; i < aTablesAttr->rows(); ++i) { ModelAPI_AttributeTables::Value aVal = aTablesAttr->value( i, 0) ; @@ -713,7 +695,8 @@ QString FeaturesPlugin_WidgetFilletMultiRadiuses::findRadius(QString thename) co } //********************************************************************************** -QString FeaturesPlugin_WidgetFilletMultiRadiuses::getValueText(ModelAPI_AttributeTables::Value& theVal) const +QString FeaturesPlugin_WidgetFilletMultiRadiuses:: + getValueText(ModelAPI_AttributeTables::Value& theVal) const { return QString::number(theVal.myDouble); diff --git a/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.h b/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.h index 10eb4ad5f..2e2af1f38 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.h +++ b/src/FeaturesPlugin/FeaturesPlugin_WidgetFilletMultiRadiuses.h @@ -106,7 +106,6 @@ protected: /// \param theToValidate a validation of the values flag virtual bool setSelection(QList>& theValues, const bool theToValidate); - /// Return the attribute values wrapped in a list of viewer presentations /// \return a list of viewer presentations, which contains an attribute result and /// a shape. If the attribute do not uses the shape, it is empty @@ -140,7 +139,7 @@ private: /// \param theStrVal a string QString getValueText(ModelAPI_AttributeTables::Value& theVal) const; - /// Return a radii value from the name + /// Return a radii value from the name /// \param theStrVal a string QString findRadius(QString thename) const; @@ -153,14 +152,14 @@ private: /// Editor for table header QLineEdit* myHeaderEditor; - bool myTypeMethodeBypoint; + bool myTypeMethodeBypoint; - bool mySetSelection; + bool mySetSelection; DataArrayItemDelegate* myDelegate; - std::vector myfirstRowValue; - std::vector myLastRowValue; + std::vector myfirstRowValue; + std::vector myLastRowValue; }; diff --git a/src/FeaturesPlugin/Test/TestFillet_MultiRadius.py b/src/FeaturesPlugin/Test/TestFillet_MultiRadius.py new file mode 100644 index 000000000..e0e724c76 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestFillet_MultiRadius.py @@ -0,0 +1,182 @@ +# Copyright (C) 2014-2020 CEA/DEN, EDF R&D +# +# 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, or (at your option) any later version. +# +# 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 +# + +""" + TestFillet.py + Unit test of ... +""" +#========================================================================= +# Initialization of the test +#========================================================================= + +import salome + +import os +import math +from tempfile import TemporaryDirectory + +import GEOM +from ModelAPI import * +from salome.shaper import model +import SHAPERSTUDY +from salome.geom import geomBuilder +from GeomAPI import GeomAPI_Shape +from GeomAlgoAPI import * + +#import SALOMEDS + + +__updated__ = "2020-10-10" + +salome.salome_init(1) + +#========================================================================= +# Help functions +#========================================================================= +def removeFile(theFileName): + try: os.remove(theFileName) + except OSError: pass + assert not os.path.exists(theFileName), \ + "Can not remove file {0}".format(theFileName) + +#========================================================================= +# test Fillet on a solid with a constant radius +#========================================================================= +def testFillet_constant_radius_onsolids(): + + model.begin() + partSet = model.moduleDocument() + ### Create Part + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + + ### Create Box + Box_1 = model.addBox(Part_1_doc, 20, 30, 10) + + ### Create Fillet + Fillet_1 = model.addFillet(Part_1_doc, [model.selection("SOLID", "Box_1_1")], 2, keepSubResults = True) + + ### Create Export + Export_1 = model.exportToXAO(Part_1_doc, '/tmp/shaper_exp_cglb.xao', model.selection("SOLID", "Fillet_1_1"), 'XAO') + + model.end() + + # Check results + ### + ### GEOM component + ### + + geompy = geomBuilder.New() + + O = geompy.MakeVertex(0, 0, 0) + OX = geompy.MakeVectorDXDYDZ(1, 0, 0) + OY = geompy.MakeVectorDXDYDZ(0, 1, 0) + OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) + + # where we import the fillet from SHAPER and get its basic properties + (imported, Fillet_1_1, [], [], []) = geompy.ImportXAO("/tmp/shaper_exp_cglb.xao") + geompy.addToStudy( O, 'O' ) + geompy.addToStudy( OX, 'OX' ) + geompy.addToStudy( OY, 'OY' ) + geompy.addToStudy( OZ, 'OZ' ) + geompy.addToStudy( Fillet_1_1, 'Fillet_1_1' ) + + myDelta = 1e-6 + Props_shaper = geompy.BasicProperties(Fillet_1_1) + print("\nBasic Properties:") + print(" Wires length: ", Props_shaper[0]) + print(" Surface area: ", Props_shaper[1]) + print(" Volume : ", Props_shaper[2]) + + # where we build the same fillet in GEOM for comparison + Box_1 = geompy.MakeBoxDXDYDZ(20, 30, 10) + Fillet_1 = geompy.MakeFilletAll(Box_1, 2) + geompy.addToStudy( Box_1, 'Box_1' ) + geompy.addToStudy( Fillet_1, 'Fillet_1' ) + + Props_geom = geompy.BasicProperties(Fillet_1) + print("\nBasic Properties:") + print(" Wires length: ", Props_geom[0]) + print(" Surface area: ", Props_geom[1]) + print(" Volume : ", Props_geom[2]) + + aRefSurface = Props_geom[1] + aResSurface = Props_shaper[1] + assert (math.fabs(aResSurface - aRefSurface) < myDelta), "The surface is wrong: expected = {0}, real = {1}".format(aRefSurface, aResSurface) + + aRefVolume = Props_geom[2] + aResVolume = Props_shaper[2] + assert (math.fabs(aResVolume - aRefVolume) < myDelta), "The volume is wrong: expected = {0}, real = {1}".format(aRefVolume, aResVolume) + +#========================================================================= +# test Fillet on an edge with multiple radii identified by points +#========================================================================= +def testFillet_multiradii_bypoints(): + model.begin() + partSet = model.moduleDocument() + + ### Create Part + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + + ### Create Box + Box_1 = model.addBox(Part_1_doc, 10, 10, 10) + + ### Create 2 Points + Point_2 = model.addPoint(Part_1_doc, model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), 0.4, True, False) + Point_3 = model.addPoint(Part_1_doc, model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), 0.8, True, False) + + ### Create Fillet on an edge with 4 radii identified by points + Fillet_1 = model.addFilletMultiRadiusByPoints(Part_1_doc, model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), [model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Point_2")], [0.5, 2, 1, 2], keepSubResults = True) + + model.end() + +#========================================================================= +# test Fillet on an edge(s) or/and face(s) with multiple radii identified +# by curvilinear abscissa +#========================================================================= +def testFillet_multiradii_bycurvabs(): + model.begin() + partSet = model.moduleDocument() + + ### Create Part + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + + ### Create Box + Box_1 = model.addBox(Part_1_doc, 10, 10, 10) + + ### Create Fillet + Fillet_1 = model.addFilletMultiRadiusBycurvAbs(Part_1_doc, [model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]")], [0, 0.4, 0.7, 1],[1, 2, 0.5, 2], keepSubResults = True) + + ### Create Fillet + Fillet_2 = model.addFilletMultiRadiusBycurvAbs(Part_1_doc, [model.selection("FACE", "Box_1_1/Right")], [0, 0.5, 1],[1, 0.5, 1], keepSubResults = True) + + model.end() + +if __name__ == '__main__': + with TemporaryDirectory() as tmp_dir: + + testFillet_constant_radius_onsolids() + testFillet_multiradii_bypoints() + testFillet_multiradii_bycurvabs() + + #========================================================================= + # End of test + #========================================================================= diff --git a/src/FeaturesPlugin/fillet_widget.xml b/src/FeaturesPlugin/fillet_widget.xml index f63f540b6..766fb0cb4 100644 --- a/src/FeaturesPlugin/fillet_widget.xml +++ b/src/FeaturesPlugin/fillet_widget.xml @@ -56,25 +56,6 @@ tooltip="Fillet with multiple radiuses" icon="icons/Features/fillet_var_multiple_radiuses.png"> - - - - - - - - - @@ -94,6 +75,26 @@ + + + + + + + + + + diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp index cebf9ca79..7632dca2d 100644 --- a/src/ModelAPI/ModelAPI_Events.cpp +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -188,6 +188,55 @@ const std::string& ModelAPI_ParameterEvalMessage::error() const return myError; } +ModelAPI_BuildEvalMessage::ModelAPI_BuildEvalMessage( + const Events_ID theID, const void* theSender) + : Events_Message(theID, theSender), myIsProcessed(false) +{} + +ModelAPI_BuildEvalMessage::~ModelAPI_BuildEvalMessage() +{} + +FeaturePtr ModelAPI_BuildEvalMessage::parameter() const +{ + return myParam; +} + +void ModelAPI_BuildEvalMessage::setParameter(FeaturePtr theParam) +{ + myParam = theParam; +} + +void ModelAPI_BuildEvalMessage::setResults( + const std::list >& theParamsList, + const double theResult, const std::string& theError) +{ + myParamsList = theParamsList; + myResult = theResult; + myError = theError; + myIsProcessed = true; +} + +bool ModelAPI_BuildEvalMessage::isProcessed() +{ + return myIsProcessed; +} + +const std::list >& + ModelAPI_BuildEvalMessage::params() const +{ + return myParamsList; +} + +const double& ModelAPI_BuildEvalMessage::result() const +{ + return myResult; +} + +const std::string& ModelAPI_BuildEvalMessage::error() const +{ + return myError; +} + ModelAPI_ComputePositionsMessage::ModelAPI_ComputePositionsMessage( const Events_ID theID, const void* theSender) : Events_Message(theID, theSender) diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index fccf6e240..11a6aecc9 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -352,6 +352,59 @@ class ModelAPI_ParameterEvalMessage : public Events_Message MODELAPI_EXPORT const std::string& error() const; }; +class ModelAPI_BuildEvalMessage : public Events_Message +{ + FeaturePtr myParam; ///< parameters that should be evaluated + bool myIsProcessed; ///< true if results were set + /// result of processing, list of parameters in expression found + std::list > myParamsList; + double myResult; ///< result of processing, the computed value of the expression + std::string myError; ///< error of processing, empty if there is no error + + public: + /// Static. Returns EventID of the message. + MODELAPI_EXPORT static Events_ID& eventId() + { + static const char * MY_BUILD_EVALUATION_EVENT_ID("ParameterEvaluationRequest"); + static Events_ID anId = Events_Loop::eventByName(MY_BUILD_EVALUATION_EVENT_ID); + return anId; + } + + /// Useful method that creates and sends the event. + /// Returns the message, processed, with the resulting fields filled. + MODELAPI_EXPORT static std::shared_ptr + send(FeaturePtr theParameter, const void* theSender) + { + std::shared_ptr aMessage = + std::shared_ptr( + new ModelAPI_BuildEvalMessage(eventId(), theSender)); + aMessage->setParameter(theParameter); + Events_Loop::loop()->send(aMessage); + return aMessage; + } + + /// Creates an empty message + MODELAPI_EXPORT ModelAPI_BuildEvalMessage(const Events_ID theID, const void* theSender = 0); + /// The virtual destructor + MODELAPI_EXPORT virtual ~ModelAPI_BuildEvalMessage(); + + /// Returns a parameter stored in the message + MODELAPI_EXPORT FeaturePtr parameter() const; + /// Sets a parameter to the message + MODELAPI_EXPORT void setParameter(FeaturePtr theParam); + /// Sets the results of processing + MODELAPI_EXPORT void setResults( + const std::list >& theParamsList, + const double theResult, const std::string& theError); + /// Returns true if the expression is processed + MODELAPI_EXPORT bool isProcessed(); + /// Returns the results of processing: list of parameters found in the expression + MODELAPI_EXPORT const std::list >& params() const; + /// Returns the expression result + MODELAPI_EXPORT const double& result() const; + /// Returns the interpreter error (empty if no error) + MODELAPI_EXPORT const std::string& error() const; +}; /// Message to ask compute the positions of parameters in the expression class ModelAPI_ComputePositionsMessage : public Events_Message diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index 772dc05c2..035b5d31f 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -27,7 +27,7 @@ from FeaturesAPI import addPipe from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addSplit from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes from FeaturesAPI import addRecover -from FeaturesAPI import addFillet, addChamfer +from FeaturesAPI import addFillet,addFilletMultiRadiusBycurvAbs, addFilletMultiRadiusByPoints, addChamfer from FeaturesAPI import addFusionFaces from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle from FeaturesAPI import addRemoveResults -- 2.39.2