From: lucasjerome Date: Fri, 5 Mar 2021 14:32:26 +0000 (+0100) Subject: First implementation of polyline in Sketcher X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=9bc4cb12d55a72442284b22cef29ba6f7215d14c;p=modules%2Fshaper.git First implementation of polyline in Sketcher --- diff --git a/src/PartSet/CMakeLists.txt b/src/PartSet/CMakeLists.txt index d158d3470..6e27b6b61 100644 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@ -62,6 +62,7 @@ SET(PROJECT_HEADERS PartSet_TreeNodes.h PartSet_FieldStepPrs.h PartSet_WidgetBSplinePoints.h + PartSet_WidgetPolylinePoints.h PartSet_BSplineWidget.h ) @@ -81,6 +82,7 @@ SET(PROJECT_MOC_HEADERS PartSet_WidgetSketchCreator.h PartSet_WidgetSketchLabel.h PartSet_WidgetBSplinePoints.h + PartSet_WidgetPolylinePoints.h PartSet_ExternalPointsMgr.h PartSet_BSplineWidget.h ) @@ -116,6 +118,7 @@ SET(PROJECT_SOURCES PartSet_TreeNodes.cpp PartSet_FieldStepPrs.cpp PartSet_WidgetBSplinePoints.cpp + PartSet_WidgetPolylinePoints.cpp PartSet_BSplineWidget.cpp ) diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index c6a6197c3..82e6c7496 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -23,6 +23,7 @@ #include "PartSet_Tools.h" #include "PartSet_PreviewPlanes.h" #include "PartSet_WidgetBSplinePoints.h" +#include "PartSet_WidgetPolylinePoints.h" #include "PartSet_WidgetPoint2d.h" #include "PartSet_WidgetPoint2DFlyout.h" #include "PartSet_WidgetShapeSelector.h" @@ -927,6 +928,13 @@ ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& th aBSplineWgt->setSketch(mySketchMgr->activeSketch()); aWgt = aBSplineWgt; } + else if (theType == "sketch-polyline_selector") { + PartSet_WidgetPolylinePoints* aBSplineWgt = + new PartSet_WidgetPolylinePoints(theParent, aWorkshop, theWidgetApi); + aBSplineWgt->setSketch(mySketchMgr->activeSketch()); + aWgt = aBSplineWgt; + } + else if (theType == WDG_DOUBLEVALUE_EDITOR) { aWgt = new PartSet_WidgetEditor(theParent, aWorkshop, theWidgetApi); } else if (theType == "export_file_selector") { diff --git a/src/PartSet/PartSet_WidgetPolylinePoints.cpp b/src/PartSet/PartSet_WidgetPolylinePoints.cpp new file mode 100644 index 000000000..44371b754 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPolylinePoints.cpp @@ -0,0 +1,462 @@ +// Copyright (C) 2019-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 +// + +#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 + +#include + +#include +#include +#include +#include +#include + +static const double MaxCoordinate = 1e12; + +static bool IsPointCreated = false; + +PartSet_WidgetPolylinePoints::PartSet_WidgetPolylinePoints(QWidget* theParent, + ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData) +: ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop), + myValueIsCashed(false), myIsFeatureVisibleInCash(true), + myXValueInCash(0), myYValueInCash(0), myFinished(false) +{ + QVBoxLayout* aMainLayout = new QVBoxLayout(this); + ModuleBase_Tools::zeroMargins(aMainLayout); + + // the control should accept the focus, so the boolean flag is corrected to be true + myIsObligatory = true; + QString aPageName = translate(theData->getProperty(CONTAINER_PAGE_NAME)); + myBox = new QGroupBox(aPageName, theParent); + myBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + myBox->setFlat(false); + aMainLayout->addWidget(myBox); + + theData->getBooleanAttribute(DOUBLE_WDG_ACCEPT_EXPRESSIONS, true); + + QVBoxLayout* aLayout = new QVBoxLayout(myBox); + ModuleBase_Tools::adjustMargins(aLayout); + + myScrollArea = new QScrollArea(myBox); + myScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + myScrollArea->setWidgetResizable(true); + myScrollArea->setFrameStyle(QFrame::NoFrame); + aLayout->addWidget(myScrollArea); + + QWidget* aContainer = new QWidget(myScrollArea); + QVBoxLayout* aBoxLay = new QVBoxLayout(aContainer); + aBoxLay->setContentsMargins(0, 0, 0, 0); + + myGroupBox = new QWidget(aContainer); + QGridLayout* aGroupLay = new QGridLayout(myGroupBox); + ModuleBase_Tools::adjustMargins(aGroupLay); + aGroupLay->setSpacing(4); + aGroupLay->setColumnStretch(1, 1); + createNextPoint(); + aBoxLay->addWidget(myGroupBox); + aBoxLay->addStretch(1); + + myScrollArea->setWidget(aContainer); + + myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop); + +} + +void PartSet_WidgetPolylinePoints::createNextPoint() +{ + storeCurentValue(); + + QGridLayout* aGroupLay = dynamic_cast(myGroupBox->layout()); + int row = (int)myXSpin.size(); + + QString aPoleStr = translate("Point %1"); + aPoleStr = aPoleStr.arg(myXSpin.size() + 1); + + QGroupBox* aPoleGroupBox = new QGroupBox(aPoleStr, myGroupBox); + QGridLayout* aPoleLay = new QGridLayout(aPoleGroupBox); + ModuleBase_Tools::adjustMargins(aPoleLay); + aPoleLay->setSpacing(2); + aPoleLay->setColumnStretch(1, 1); + + myXSpin.push_back(new ModuleBase_LabelValue(aPoleGroupBox, tr("X"))); + aPoleLay->addWidget(myXSpin.back(), 0, 1); + myYSpin.push_back(new ModuleBase_LabelValue(aPoleGroupBox, tr("Y"))); + aPoleLay->addWidget(myYSpin.back(), 1, 1); + + aGroupLay->addWidget(aPoleGroupBox, row, 1); + IsPointCreated = true; +} + +void PartSet_WidgetPolylinePoints::removeLastPoint() +{ + QGridLayout* aGroupLay = dynamic_cast(myGroupBox->layout()); + QWidget* aXSpin = myXSpin.back(); + QWidget* aYSpin = myYSpin.back(); + QWidget* aBox = myXSpin.back()->parentWidget(); + myYSpin.pop_back(); + myXSpin.pop_back(); + + aGroupLay->removeWidget(aXSpin); + aGroupLay->removeWidget(aYSpin); + aGroupLay->removeWidget(aBox); + + aBox->deleteLater(); + + // update polyline feature attributes + storeValueCustom(); +} + + +PartSet_WidgetPolylinePoints::~PartSet_WidgetPolylinePoints() +{ +} + +bool PartSet_WidgetPolylinePoints::setPoint(double theX, double theY) +{ + if (fabs(theX) >= MaxCoordinate || fabs(theY) >= MaxCoordinate) + return false; + + myXSpin.back()->setValue(theX); + myYSpin.back()->setValue(theY); + + storeValue(); + return true; +} + +void PartSet_WidgetPolylinePoints::storePoints() const +{ + + std::shared_ptr aData = myFeature->data(); + AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + + int aSize = (int)myXSpin.size(); + aPointArray->setSize(aSize); + + std::vector::const_iterator aXIt = myXSpin.begin(); + std::vector::const_iterator aYIt = myYSpin.begin(); + for (int anIndex = 0; aXIt != myXSpin.end() && aYIt != myYSpin.end(); ++anIndex, ++aXIt, ++aYIt) + aPointArray->setPnt(anIndex, (*aXIt)->value(), (*aYIt)->value()); + +} + +bool PartSet_WidgetPolylinePoints::storeValueCustom() +{ + std::shared_ptr aData = myFeature->data(); + if (!aData || !aData->isValid()) // can be on abort of sketcher element + return false; + AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + + PartSet_WidgetPolylinePoints* that = (PartSet_WidgetPolylinePoints*) this; + bool isBlocked = that->blockSignals(true); + bool isImmutable = aPointArray->setImmutable(true); + + if (myFeature->isMacro()) { + // Moving points of macro-features has been processed directly (without solver) + storePoints(); + updateObject(myFeature); + + } else { + if (!aPointArray->isInitialized()) { + storePoints(); + } + std::shared_ptr aMessage( + new ModelAPI_ObjectMovedMessage(this)); + aMessage->setMovedAttribute(aPointArray, aPointArray->size() - 1); + aMessage->setOriginalPosition(aPointArray->pnt(aPointArray->size() - 1)); + aMessage->setCurrentPosition(myXSpin.back()->value(), myYSpin.back()->value()); + Events_Loop::loop()->send(aMessage); + } + + aPointArray->setImmutable(isImmutable); + that->blockSignals(isBlocked); + + return true; +} + +bool PartSet_WidgetPolylinePoints::restoreValueCustom() +{ + + std::shared_ptr aData = myFeature->data(); + AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast( + aData->attribute(attributeID())); + + if (aPointArray->isInitialized()) { + while ((int)myXSpin.size() < aPointArray->size()) + createNextPoint(); + + std::vector::iterator aXIt = myXSpin.begin(); + std::vector::iterator aYIt = myYSpin.begin(); + for (int anIndex = 0; aXIt != myXSpin.end() && aYIt != myYSpin.end(); + ++anIndex, ++aXIt, ++aYIt) { + GeomPnt2dPtr aPoint = aPointArray->pnt(anIndex); + (*aXIt)->setValue(aPoint->x()); + (*aYIt)->setValue(aPoint->y()); + } + } + else { + if (myXSpin.empty()) + createNextPoint(); + + myXSpin.back()->setValue(0.0); + myYSpin.back()->setValue(0.0); + } + + return true; +} + +static void storeArray(const std::vector& theLabels, + std::vector& theValues) +{ + theValues.clear(); + theValues.reserve(theLabels.size()); + for (std::vector::const_iterator anIt = theLabels.begin(); + anIt != theLabels.end(); ++anIt) + theValues.push_back((*anIt)->value()); +} + +void PartSet_WidgetPolylinePoints::storeCurentValue() +{ + myValueIsCashed = true; + myIsFeatureVisibleInCash = XGUI_Displayer::isVisible( + XGUI_Tools::workshop(myWorkshop)->displayer(), myFeature); + + storeArray(myXSpin, myXValueInCash); + storeArray(myYSpin, myYValueInCash); +} + +static void restoreArray(std::vector& theCacheValues, + std::vector& theLabels) +{ + std::vector::iterator aCIt = theCacheValues.begin(); + std::vector::iterator anIt = theLabels.begin(); + for (; anIt != theLabels.end(); ++anIt) { + if (aCIt != theCacheValues.end()) + (*anIt)->setValue(*aCIt++); + else + (*anIt)->setValue(0.0); + } + theCacheValues.clear(); +} + +bool PartSet_WidgetPolylinePoints::restoreCurentValue() +{ + bool aRestoredAndHidden = true; + + bool isVisible = myIsFeatureVisibleInCash; + + myValueIsCashed = false; + myIsFeatureVisibleInCash = true; + // fill the control widgets by the cashed value + restoreArray(myXValueInCash, myXSpin); + restoreArray(myYValueInCash, myYSpin); + + // store value to the model + storeValueCustom(); + if (isVisible) { + setValueState(Stored); + aRestoredAndHidden = false; + } + else + aRestoredAndHidden = true; + + return aRestoredAndHidden; +} + +QList PartSet_WidgetPolylinePoints::getControls() const +{ + QList aControls; + aControls.append(myScrollArea); + return aControls; +} + +void PartSet_WidgetPolylinePoints::selectionModes(int& theModuleSelectionModes, QIntList& theModes) +{ + theModuleSelectionModes = -1; + theModes << TopAbs_VERTEX; +} + +void PartSet_WidgetPolylinePoints::deactivate() +{ + // the value of the control should be stored to model if it was not + // initialized yet. It is important when we leave this control by Tab key. + // It should not be performed by the widget activation as the preview + // is visualized with default value. Line point is moved to origin. + AttributePtr anAttribute = myFeature->data()->attribute(attributeID()); + if (anAttribute && !anAttribute->isInitialized()) + storeValue(); + + ModuleBase_ModelWidget::deactivate(); +} + +void PartSet_WidgetPolylinePoints::mouseReleased(ModuleBase_IViewWindow* theWindow, + QMouseEvent* theEvent) +{ + // the contex menu release by the right button should not be processed by this widget + if (theEvent->button() != Qt::LeftButton) + return; + + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + Handle(V3d_View) aView = theWindow->v3dView(); + + QList aList = aSelection->getSelected(ModuleBase_ISelection::Viewer); + ModuleBase_ViewerPrsPtr aFirstValue = + aList.size() > 0 ? aList.first() : ModuleBase_ViewerPrsPtr(); + if (!aFirstValue.get() && myPreSelected.get()) { + aFirstValue = myPreSelected; + } + + TopoDS_Shape aSelectedShape; + ObjectPtr aSelectedObject; + + // if we have selection and use it + if (aFirstValue.get() && aFirstValue->shape().get()) { + GeomShapePtr aGeomShape = aFirstValue->shape(); + aSelectedShape = aGeomShape->impl(); + aSelectedObject = aFirstValue->object(); + + FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(aSelectedObject); + std::shared_ptr aSPFeature; + if (aSelectedFeature.get()) + aSPFeature = std::dynamic_pointer_cast(aSelectedFeature); + + bool isSketchExternalFeature = aSPFeature.get() && aSPFeature->isExternal(); + if ((!aSPFeature && !aSelectedShape.IsNull()) || isSketchExternalFeature) { + ObjectPtr aFixedObject = + PartSet_Tools::findFixedObjectByExternal(aSelectedShape, aSelectedObject, mySketch); + if (aFixedObject) + aSelectedObject = aFixedObject; + else if (!isSketchExternalFeature) { + FeaturePtr aCreatedFeature; + aSelectedObject = PartSet_Tools::createFixedObjectByExternal( + aGeomShape, aSelectedObject, mySketch, false, aCreatedFeature); + } + } + } + // The selection could be a center of an external circular object + else if (aFirstValue.get() && (!aFirstValue->interactive().IsNull())) { + Handle(PartSet_CenterPrs) aAIS = + Handle(PartSet_CenterPrs)::DownCast(aFirstValue->interactive()); + if (!aAIS.IsNull()) { + gp_Pnt aPntComp = aAIS->Component()->Pnt(); + GeomVertexPtr aVertPtr(new GeomAPI_Vertex(aPntComp.X(), aPntComp.Y(), aPntComp.Z())); + aSelectedShape = aVertPtr->impl(); + + aSelectedObject = + PartSet_Tools::findFixedObjectByExternal(aSelectedShape, aAIS->object(), mySketch); + if (!aSelectedObject.get()) + { + FeaturePtr aCreatedFeature; + aSelectedObject = PartSet_Tools::createFixedByExternalCenter(aAIS->object(), aAIS->edge(), + aAIS->centerType(), mySketch, false, aCreatedFeature); + } + } + } + + GeomPnt2dPtr aSelectedPoint = PartSet_Tools::getPnt2d(aView, aSelectedShape, mySketch); + if (!aSelectedPoint) { + aSelectedPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch); + setValueState(Stored); // in case of edge selection, Apply state should also be updated + } + // next pole of B-spline + createNextPoint(); +} + +void PartSet_WidgetPolylinePoints::mouseMoved(ModuleBase_IViewWindow* theWindow, + QMouseEvent* theEvent) +{ + PartSet_Module* aModule = dynamic_cast(myWorkshop->module()); + + if (myFinished || isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditActive()) + return; + + gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); + + double aX = 0, aY = 0; + PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, aY); + if (myState != ModifiedInViewer) + storeCurentValue(); + + setPoint(aX, aY); + + if (IsPointCreated) { + QPoint aPnt = myGroupBox->geometry().bottomLeft(); + myScrollArea->ensureVisible(aPnt.x(), aPnt.y()); + IsPointCreated = false; + } +} + + +bool PartSet_WidgetPolylinePoints::processEscape() +{ + bool isProcessed = !isEditingMode(); + if (isProcessed) { + // remove widgets corrsponding to the last pole/weight of B-spline + removeLastPoint(); + myFinished = true; + + emit focusOutWidget(this); + } + return isProcessed; +} + +bool PartSet_WidgetPolylinePoints::useSelectedShapes() const +{ + return true; +} + + + diff --git a/src/PartSet/PartSet_WidgetPolylinePoints.h b/src/PartSet/PartSet_WidgetPolylinePoints.h new file mode 100644 index 000000000..bde911df6 --- /dev/null +++ b/src/PartSet/PartSet_WidgetPolylinePoints.h @@ -0,0 +1,152 @@ +// Copyright (C) 2019-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 +// + +#ifndef PartSet_WidgetPolylinePoints_H +#define PartSet_WidgetPolylinePoints_H + +#include "PartSet.h" +#include "PartSet_MouseProcessor.h" + +#include + +#include + +class GeomAPI_Pnt2d; +class ModelAPI_CompositeFeature; +class ModuleBase_LabelValue; +class PartSet_ExternalObjectsMgr; +class QGroupBox; +class QScrollArea; + +/**\class PartSet_WidgetPolylinePoints + * \ingroup Modules + * \brief Implementation of model widget to provide widget to input a list of 2D points + * of polyline + * In XML can be defined as following: + * \code + * + * \endcode + */ +class PARTSET_EXPORT PartSet_WidgetPolylinePoints : public ModuleBase_ModelWidget, + public PartSet_MouseProcessor +{ +Q_OBJECT +public: + /// Constructor + /// \param theParent the parent object + /// \param theWorkshop a current workshop + /// \param theData the widget configuation. The attribute of the model widget is obtained from + PartSet_WidgetPolylinePoints(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, + const Config_WidgetAPI* theData); + /// Destructor + virtual ~PartSet_WidgetPolylinePoints(); + + /// Fills given container with selection modes if the widget has it + /// \param [out] theModuleSelectionModes module additional modes, -1 means all default modes + /// \param theModes [out] a container of modes + virtual void selectionModes(int& theModuleSelectionModes, QIntList& theModes); + + /// Fills the attribute with the value of the selected owner + /// \param thePrs a selected owner + bool setSelectionCustom(const std::shared_ptr& theValue); + + /// Returns list of widget controls + /// \return a control list + virtual QList getControls() const; + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + /// \returns the sketch instance + std::shared_ptr sketch() const { return mySketch; } + + /// Set sketch instance + void setSketch(std::shared_ptr theSketch) { mySketch = theSketch; } + + /// Fill the widget values by given point + /// \param theX the X coordinate + /// \param theY the Y coordinate + /// \returns True in case of success + bool setPoint(double theX, double theY); + + /// Returns true if the event is processed. + virtual bool processEscape(); + + /// Returns true if the attribute can be changed using the selected shapes in the viewer + /// and creating a coincidence constraint to them. This control use them. + virtual bool useSelectedShapes() const; + + /// Processing the mouse move event in the viewer + /// \param theWindow a view window + /// \param theEvent a mouse event + virtual void mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent); + + /// Processing the mouse release event in the viewer + /// \param theWindow a view window + /// \param theEvent a mouse event + virtual void mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent); + +protected: + /// Saves the internal parameters to the given feature + /// \return True in success + virtual bool storeValueCustom(); + + /// Restore value from attribute data to the widget's control + virtual bool restoreValueCustom(); + + /// Store current value in cashed value + void storeCurentValue(); + + /// Restore cashed value in the model attribute + /// \return boolean state if the restored feature shoud be hidden + bool restoreCurentValue(); + +private: + /// Create labels for the next B-spline point + void createNextPoint(); + /// Remove labels for the last B-spline point + void removeLastPoint(); + + /// Save polyline points to corresponding attributes + void storePoints() const; + +protected: + ModuleBase_IWorkshop* myWorkshop; ///< workshop + +private: + QGroupBox* myBox; + QWidget* myGroupBox; ///< the parent group box for all intenal widgets + QScrollArea* myScrollArea; + std::vector myXSpin; ///< the label for the X coordinate + std::vector myYSpin; ///< the label for the Y coordinate + + /// value used as selection in mouse release method + std::shared_ptr myPreSelected; + + /// it is important during restart operation + CompositeFeaturePtr mySketch; + + bool myValueIsCashed; /// boolean state if the value is cashed during value state change + bool myIsFeatureVisibleInCash; /// boolean value if the feature was visible when cash if filled + std::vector myXValueInCash; /// the cashed X value during value state change + std::vector myYValueInCash; /// the cashed Y value during value state change + + bool myFinished; /// \c true if building the polyline is finished (escape pressed) +}; +#endif diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 3fcc4e389..b39e86b7c 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -56,6 +56,7 @@ SET(PROJECT_HEADERS SketchPlugin_Feature.h SketchPlugin_IntersectionPoint.h SketchPlugin_Line.h + SketchPlugin_Polyline.h SketchPlugin_MacroArc.h SketchPlugin_MacroArcReentrantMessage.h SketchPlugin_MacroBSpline.h @@ -112,6 +113,7 @@ SET(PROJECT_SOURCES SketchPlugin_Feature.cpp SketchPlugin_IntersectionPoint.cpp SketchPlugin_Line.cpp + SketchPlugin_Polyline.cpp SketchPlugin_MacroArc.cpp SketchPlugin_MacroBSpline.cpp SketchPlugin_MacroCircle.cpp diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index b71ff3c37..f2c944083 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -155,6 +156,8 @@ SketchPlugin_Plugin::SketchPlugin_Plugin() new SketchPlugin_MultiRotationAngleValidator); aFactory->registerValidator("SketchPlugin_BSplineValidator", new SketchPlugin_BSplineValidator); + aFactory->registerValidator("SketchPlugin_PolylineValidator", + new SketchPlugin_PolylineValidator); aFactory->registerValidator("SketchPlugin_CurveFittingValidator", new SketchPlugin_CurveFittingValidator); @@ -279,6 +282,8 @@ FeaturePtr SketchPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new SketchPlugin_EllipticArc); } else if (theFeatureID == SketchPlugin_MacroEllipticArc::ID()) { return FeaturePtr(new SketchPlugin_MacroEllipticArc); + } else if (theFeatureID == SketchPlugin_Polyline::ID()) { + return FeaturePtr(new SketchPlugin_Polyline); } else if (theFeatureID == SketchPlugin_CurveFitting::ID()) { return FeaturePtr(new SketchPlugin_CurveFitting); } else if (theFeatureID == SketchPlugin_SketchDrawer::ID()) { @@ -362,6 +367,7 @@ std::shared_ptr SketchPlugin_Plugin aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_MacroEllipticArc::ID(), aHasSketchPlane); + aMsg->setState(SketchPlugin_Polyline::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane); aMsg->setState(SketchPlugin_CurveFitting::ID(), aHasSketchPlane); diff --git a/src/SketchPlugin/SketchPlugin_Polyline.cpp b/src/SketchPlugin/SketchPlugin_Polyline.cpp new file mode 100644 index 000000000..c73fd7a79 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_Polyline.cpp @@ -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 +// + +#include "SketchPlugin_Polyline.h" + +#include "SketchPlugin_Line.h" +#include "SketchPlugin_Sketch.h" + +#include "SketchPlugin_ConstraintCoincidence.h" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +SketchPlugin_Polyline::SketchPlugin_Polyline() + : SketchPlugin_SketchEntity() +{} + +void SketchPlugin_Polyline::initAttributes() +{ + SketchPlugin_SketchEntity::initAttributes(); +} + +void SketchPlugin_Polyline::initDerivedClassAttributes() +{ + + data()->addAttribute(POINTS_ID(), GeomDataAPI_Point2DArray::typeId()); + +} + +void SketchPlugin_Polyline::execute() +{ + createLineFeature(); +} + +void SketchPlugin_Polyline::createLineFeature() +{ + AttributePoint2DArrayPtr aPointsArray = + std::dynamic_pointer_cast(attribute(POINTS_ID())); + + getAISObject(AISObjectPtr()); + + if (aPointsArray->isInitialized()) + { + FeaturePtr aLastline; + FeaturePtr aFirstline; + // collect points + for (int anIndex = 1; anIndex < aPointsArray->size(); ++anIndex) { + + FeaturePtr aLine = sketch()->addFeature(SketchPlugin_Line::ID()); + if (anIndex ==1) { + aFirstline = aLine; + } + std::shared_ptr aStartA = std::dynamic_pointer_cast( + aLine->attribute(SketchPlugin_Line::START_ID())); + + aStartA->setValue(aPointsArray->pnt(anIndex-1)); + + std::shared_ptr aEndA = std::dynamic_pointer_cast( + aLine->attribute(SketchPlugin_Line::END_ID())); + + aEndA->setValue(aPointsArray->pnt(anIndex)); + + aLine->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue( + boolean(AUXILIARY_ID())->value()); + + if (aLastline) { + // Initialize new line with first point equal to end of previous + std::shared_ptr aSFData = aLastline->data(); + std::shared_ptr aSPoint = + std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aNFData = aLine->data(); + std::shared_ptr aNPoint = + std::dynamic_pointer_cast( + aNFData->attribute(SketchPlugin_Line::START_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + SketchPlugin_ConstraintCoincidence::createCoincidenceFeature(sketch(), aSPoint, aNPoint); + } + + aLine->execute(); + aLastline = aLine; + } + // Initialize new line with first point equal to end of previous + std::shared_ptr aSFData = aLastline->data(); + std::shared_ptr aSPoint = + std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aNFData = aFirstline->data(); + std::shared_ptr aNPoint = + std::dynamic_pointer_cast( + aNFData->attribute(SketchPlugin_Line::START_ID())); + + double aDistance = aSPoint->pnt()->distance(aNPoint->pnt()); + if (aDistance < 1) { + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + SketchPlugin_ConstraintCoincidence::createCoincidenceFeature(sketch(), aSPoint, aNPoint); + } + } +} + +const std::string& SketchPlugin_Polyline::getKind() +{ + static std::string MY_KIND = SketchPlugin_Polyline::ID(); + return MY_KIND; +} + +void SketchPlugin_Polyline::attributeChanged(const std::string& theID) { +} + +AISObjectPtr SketchPlugin_Polyline::getAISObject(AISObjectPtr thePrevious) +{ + + SketchPlugin_Sketch* aSketch = sketch(); + if (!aSketch) + return AISObjectPtr(); + + AttributePoint2DArrayPtr aPointsArray = + std::dynamic_pointer_cast(attribute(POINTS_ID())); + + if (aPointsArray->size() < 2) + return AISObjectPtr(); + + std::list aShapes; + + // convert points to vertices + std::list aPoles3D; + for (int anIndex = 0; anIndex < aPointsArray->size()-1; ++anIndex) { + + GeomPnt2dPtr aPoint1 = aPointsArray->pnt(anIndex); + GeomPnt2dPtr aPoint2 = aPointsArray->pnt(anIndex + 1); + GeomPointPtr aPole3D1 = aSketch->to3D(aPoint1->x(), aPoint1->y()); + GeomPointPtr aPole3D2 = aSketch->to3D(aPoint2->x(), aPoint2->y()); + aShapes.push_back(GeomAlgoAPI_PointBuilder::vertex(aPole3D1)); + + GeomShapePtr anEdge = + GeomAlgoAPI_EdgeBuilder::line(aPole3D1, aPole3D2); + if (anEdge) + aShapes.push_back(anEdge); + + } + + GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + + AISObjectPtr anAIS = thePrevious; + if (!anAIS) + anAIS.reset(new GeomAPI_AISObject()); + anAIS->createShape(aCompound); + + // Modify attributes + SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value()); + + return anAIS; +} \ No newline at end of file diff --git a/src/SketchPlugin/SketchPlugin_Polyline.h b/src/SketchPlugin/SketchPlugin_Polyline.h new file mode 100644 index 000000000..7decbf441 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_Polyline.h @@ -0,0 +1,89 @@ +// 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 +// + +#ifndef SketchPlugin_Polyline_H_ +#define SketchPlugin_Polyline_H_ + +#include + +#include "SketchPlugin.h" +#include +#include +#include + +#include + +class GeomAPI_Pnt2d; + +/**\class SketchPlugin_Polyline + * \ingroup Plugins + * \brief Feature for creation of polyline in PartSet. + */ +class SketchPlugin_Polyline : public SketchPlugin_SketchEntity, + public GeomAPI_IPresentable +{ + public: + /// Arc feature kind + inline static const std::string& ID() + { + static const std::string SKETCH_LINE_ID("SketchPolyline"); + return SKETCH_LINE_ID; + } + + /// list of polyline points + inline static const std::string& POINTS_ID() + { + static const std::string ID("points"); + return ID; + } + + /// Returns the kind of a feature + SKETCHPLUGIN_EXPORT virtual const std::string& getKind(); + + /// Request for initialization of data model of the feature: adding all attributes + virtual void initAttributes(); + + /// Creates a new part document if needed + SKETCHPLUGIN_EXPORT virtual void execute(); + + /// Reimplemented from ModelAPI_Feature::isMacro(). + /// \returns true + SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;}; + + SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;}; + + /// Called on change of any argument-attribute of this object + SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Returns the AIS preview + virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); + + /// Use plugin manager for features creation + SketchPlugin_Polyline(); + +private: + + void createLineFeature(); + +protected: + /// \brief Initializes attributes of derived class. + virtual void initDerivedClassAttributes(); +}; + +#endif diff --git a/src/SketchPlugin/SketchPlugin_Validators.cpp b/src/SketchPlugin/SketchPlugin_Validators.cpp index 18c9f81c2..ed7f110df 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.cpp +++ b/src/SketchPlugin/SketchPlugin_Validators.cpp @@ -1966,6 +1966,18 @@ bool SketchPlugin_BSplineValidator::isValid(const AttributePtr& theAttribute, return true; } +bool SketchPlugin_PolylineValidator::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + AttributePoint2DArrayPtr aPolesArray = + std::dynamic_pointer_cast(theAttribute); + if (!aPolesArray) + return false; + + return true; +} + bool SketchPlugin_CurveFittingValidator::isValid(const FeaturePtr& theFeature, const std::list& theArguments, Events_InfoMessage& theError) const diff --git a/src/SketchPlugin/SketchPlugin_Validators.h b/src/SketchPlugin/SketchPlugin_Validators.h index 01c1f4f3a..7409dafd0 100644 --- a/src/SketchPlugin/SketchPlugin_Validators.h +++ b/src/SketchPlugin/SketchPlugin_Validators.h @@ -546,6 +546,21 @@ class SketchPlugin_BSplineValidator : public ModelAPI_AttributeValidator Events_InfoMessage& theError) const; }; +/**\class SketchPlugin_PolylineValidator + * \ingroup Validators + * \brief Validator for checking points of polyline. + */ +class SketchPlugin_PolylineValidator : public ModelAPI_AttributeValidator +{ + //! returns true if attribute is valid + //! \param theAttribute the checked attribute + //! \param theArguments arguments of the attribute + //! \param theError error message + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; + /**\class SketchPlugin_CurveFittingValidator * \ingroup Validators * \brief Validator for the selected vertices for the curve fitting feature. diff --git a/src/SketchPlugin/icons/polyline.png b/src/SketchPlugin/icons/polyline.png new file mode 100644 index 000000000..8ed9356e7 Binary files /dev/null and b/src/SketchPlugin/icons/polyline.png differ diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 824e6281b..411884a64 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -3,7 +3,7 @@ + + + + + + +