Add rectangular and circular construction grids.
return anInnerPoint;
double aUMin, aUMax, aVMin, aVMax;
- optimalBounds(aFace, aUMin, aUMax, aVMin, aVMax);
+ ::optimalBounds(aFace, aUMin, aUMax, aVMin, aVMax);
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
if (aSurf.IsNull())
return anInnerPoint;
}
+bool GeomAPI_Face::optimalBounds(double& theUMin, double& theUMax,
+ double& theVMin, double& theVMax) const
+{
+ const TopoDS_Face& aFace = impl<TopoDS_Face>();
+ if (aFace.IsNull())
+ return false;
+
+ ::optimalBounds(aFace, theUMin, theUMax, theVMin, theVMax);
+ return true;
+}
// ================== Auxiliary functions ========================
optimalBounds(theFace, TopoDS::Edge(anExp.Current()), aBB);
aBB.Get(theUMin, theVMin, theUMax, theVMax);
-}
+}
\ No newline at end of file
/// Returns torus if the face is based on the toroidal surface
GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Torus> getTorus() const;
- /// Return inner point in the face
+ /// Returns inner point in the face
GEOMAPI_EXPORT virtual std::shared_ptr<GeomAPI_Pnt> middlePoint() const;
+
+ /// Returns bounding box in UV-space.
+ GEOMAPI_EXPORT virtual bool optimalBounds(
+ double& theUMin, double& theUMax,
+ double& theVMin, double& theVMax
+ ) const;
};
//! Pointer on attribute object
class GeomAPI_Pnt;
class GeomAPI_Dir;
class GeomAPI_Lin;
+class gp_Pln;
/**\class GeomAPI_Pln
* \ingroup DataModel
- * \brief 3D point defined by three coordinates
+ * \Plane in 3D place, defined by normal, center and x-direction.
*/
class GeomAPI_Pln : public GeomAPI_Interface
public:
/// Creation of plane by the axis placement
GEOMAPI_EXPORT
- GeomAPI_Pln(const std::shared_ptr<GeomAPI_Ax3>& theAxis);
+ GeomAPI_Pln(const std::shared_ptr<GeomAPI_Ax3>& theAxes);
/// Creation of plane by the point and normal
GEOMAPI_EXPORT
return aRes;
}
+//==================================================================================================
+/*static*/ std::shared_ptr<GeomAPI_Face> GeomAlgoAPI_FaceBuilder::planarRectangularFace(
+ const gp_Ax3& theCS, double theWidth, double theHeight, double theOffsetX, double theOffsetY
+) {
+ const gp_Pln plane = gp_Pln(theCS);
+ BRepBuilderAPI_MakeFace faceBuilder(
+ plane,
+ theOffsetX - theWidth/2 , theOffsetX + theWidth/2,
+ theOffsetY - theHeight/2, theOffsetY + theHeight/2
+ );
+
+ std::shared_ptr<GeomAPI_Face> res(new GeomAPI_Face());
+ res->setImpl(new TopoDS_Face(faceBuilder.Face()));
+ return res;
+}
+
//==================================================================================================
std::shared_ptr<GeomAPI_Face> GeomAlgoAPI_FaceBuilder::planarFaceByThreeVertices(
const std::shared_ptr<GeomAPI_Vertex> theVertex1,
class GeomAPI_Pln;
class GeomAPI_Pnt;
class GeomAPI_Vertex;
+class gp_Ax3;
/// \class GeomAlgoAPI_FaceBuilder
/// \ingroup DataAlgo
{
public:
/// Creates square planar face by given point of the center,
- /// normal to the plane and size of square
+ /// normal to the plane and size of square.
static std::shared_ptr<GeomAPI_Face> squareFace(const std::shared_ptr<GeomAPI_Pnt> theCenter,
const std::shared_ptr<GeomAPI_Dir> theNormal,
const double theSize);
/// Creates square planar face by given point of the center,
- /// normal to the plane and size of square
+ /// normal to the plane and size of square.
static std::shared_ptr<GeomAPI_Face> squareFace(const std::shared_ptr<GeomAPI_Pln> thePlane,
const double theSize);
static std::shared_ptr<GeomAPI_Face> planarFace(const std::shared_ptr<GeomAPI_Pnt> theCenter,
const std::shared_ptr<GeomAPI_Dir> theNormal);
- /// Creates a planar face by given plane, left lower point and size.
+ /// Creates a planar face by given plane, left lower point and size. Does not take into account X & Y directions of thePlane!
static std::shared_ptr<GeomAPI_Face> planarFace(const std::shared_ptr<GeomAPI_Pln> thePlane,
const double theX, const double theY,
const double theWidth, const double theHeight);
+ /*! \brief Creates rectangular planar face, with normal, X and Y directions as of theCS. */
+ static std::shared_ptr<GeomAPI_Face> planarRectangularFace(
+ const gp_Ax3& theCS,
+ double theWidth, double theHeight,
+ double theOffsetX = 0, double theOffsetY = 0
+ );
+
/// Creates a planar face by three vertices.
static std::shared_ptr<GeomAPI_Face> planarFaceByThreeVertices(
const std::shared_ptr<GeomAPI_Vertex> theVertex1,
ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
const Config_WidgetAPI* theData)
: QWidget(theParent),
- myWidgetValidator(0),
+ myWidgetValidator(nullptr),
myState(Stored),
myIsEditing(false),
myIsValueStateBlocked(false),
/**\class ModuleBase_ModelWidget
* \ingroup GUI
- * \brief An abstract custom widget class. This class realization is assumed
+ * \brief An abstract custom widget class. This class realization is assumed
* to create some controls.
* The controls values modification should send signal about values change.
*
{ return true; }
/// Returns widget validator, by default it is NULL. To be created in a child if necessary
- ModuleBase_WidgetValidator* widgetValidator() { return myWidgetValidator; }
+ ModuleBase_WidgetValidator* widgetValidator() { return myWidgetValidator.get(); }
/// Restore value from attribute data to the widget's control.
/// Emits signals before and after store
protected:
/// own validator, by default it is zero
- ModuleBase_WidgetValidator* myWidgetValidator;
+ std::unique_ptr<ModuleBase_WidgetValidator> myWidgetValidator;
/// The attribute name of the model feature
std::string myAttributeID;
PartSet_IconFactory.cpp
PartSet_MenuMgr.cpp
PartSet_Module.cpp
+ PartSet_MouseProcessor.cpp
PartSet_OperationPrs.cpp
PartSet_OverconstraintListener.cpp
PartSet_PreviewPlanes.cpp
CompositeFeaturePtr aSketch = mySketchMgr->activeSketch();
if (aSketch.get()) {
ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
- if (PartSet_SketcherMgr::isSketchOperation(anOperation) &&
- mySketchMgr->previewSketchPlane()->isDisplayed())
- mySketchMgr->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
+ if (PartSet_SketcherMgr::isSketchOperation(anOperation)) {
+ mySketchMgr->previewSketchPlane()->setAllUsingSketch(aSketch);
+ }
}
}
else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_FEATURE_LICENSE_VALID)) {
--- /dev/null
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// 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 "PartSet_MouseProcessor.h"
+
+#include "ModuleBase_IViewWindow.h"
+#include "ModuleBase_IWorkshop.h"
+#include "ModuleBase_IViewer.h"
+#include "PartSet_Module.h"
+#include "PartSet_PreviewSketchPlane.h"
+#include "ModelAPI_CompositeFeature.h"
+#include <gp_Pnt.hxx>
+#include <Aspect_Grid.hxx>
+#include <QPoint>
+#include <PartSet_Tools.h>
+
+
+/// @brief
+/// During drawing of a line on a sketch, a crash happens if coordinates (theX, theY), returned by \ref PartSet_MouseProcessor::convertPointToLocal,
+/// coincide with on-sketch plane coordinates of the closest grid node. What exactly causes this odd behaviour remains unknown.
+/// The crash is manifested on all supported Linux OSes, except Debian 11 and, maybe, 12.
+/// Even on problematic OSes, the crash does not happen if a debugger (at least LLDB) is attached to Salome with Shaper being compiled in Debug mode.
+double slightlyChangeVal(double theVal)
+{
+ static const double eps = 1e-5;
+
+ if (std::abs(theVal) > 1)
+ return (1 + eps) * theVal;
+ else
+ return theVal + eps;
+}
+
+
+bool PartSet_MouseProcessor::convertPointToLocal(
+ ModuleBase_IWorkshop* theWorkshop,
+ const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
+ ModuleBase_IViewWindow* theWindow,
+ const QPoint& theEventPos,
+ double& theX, double& theY,
+ bool theHighlight,
+ bool theAddOffset
+) const {
+ ModuleBase_IViewer* const viewer = theWorkshop->viewer();
+ if (!viewer)
+ return false;
+
+ const auto aV3dViewer = viewer->v3dViewer();
+ const PartSet_Module* module = dynamic_cast<PartSet_Module*>(theWorkshop->module());
+ if (!module)
+ return false;
+
+ const Handle(V3d_View) view = theWindow->v3dView();
+
+ PartSet_PreviewSketchPlane* previewPlane = module->sketchMgr()->previewSketchPlane();
+ if (!aV3dViewer || !aV3dViewer->Grid()->IsActive() || previewPlane->getGridSnappingMode() == PartSet_PreviewSketchPlane::GridSnappingMode::Off) {
+ const gp_Pnt mousePoint = PartSet_Tools::convertClickToPoint(theEventPos, view);
+ PartSet_Tools::convertTo2D(mousePoint, theSketch, view, theX, theY);
+ return true;
+ }
+ else {
+ double closestGridPointX, closestGridPointY, closestGridPointZ;
+ view->ConvertToGrid(theEventPos.x(), theEventPos.y(), closestGridPointX, closestGridPointY, closestGridPointZ);
+ const gp_Pnt gridPoint = gp_Pnt(closestGridPointX, closestGridPointY, closestGridPointZ);
+
+ if (previewPlane->getGridSnappingMode() == PartSet_PreviewSketchPlane::GridSnappingMode::SnapAnyway) {
+ PartSet_Tools::convertTo2D(gridPoint, theSketch, view, theX, theY);
+
+ if (theAddOffset) {
+ theX = slightlyChangeVal(theX);
+ theY = slightlyChangeVal(theY);
+ }
+
+ if (theHighlight) {
+ view->Viewer()->ShowGridEcho(view, Graphic3d_Vertex(closestGridPointX, closestGridPointY, closestGridPointZ));
+ view->Viewer()->SetGridEcho(true);
+ view->RedrawImmediate();
+ }
+ else {
+ view->Viewer()->SetGridEcho(false);
+ view->RedrawImmediate();
+ }
+
+ return true;
+ }
+ else /* aPreviewPlane->getGridSnappingMode() == PartSet_PreviewSketchPlane::GridSnappingMode::SnapInProximity */ {
+ Standard_Integer aClosestPX, aClosestPY; // Unit is pixel.
+ view->Convert(closestGridPointX, closestGridPointY, closestGridPointZ, aClosestPX, aClosestPY);
+ const int squareDistanceP = std::pow(aClosestPX - theEventPos.x(), 2) + std::pow(aClosestPY - theEventPos.y(), 2);
+ static const int THRESHOLD = std::pow(PartSet_PreviewSketchPlane::SNAP_PROXIMITY_P, 2);
+
+ if (squareDistanceP > THRESHOLD) {
+ const gp_Pnt mousePoint = PartSet_Tools::convertClickToPoint(theEventPos, view);
+ PartSet_Tools::convertTo2D(mousePoint, theSketch, view, theX, theY);
+ view->Viewer()->SetGridEcho(false);
+ view->RedrawImmediate();
+ }
+ else {
+ PartSet_Tools::convertTo2D(gridPoint, theSketch, view, theX, theY);
+
+ if (theAddOffset) {
+ theX = slightlyChangeVal(theX);
+ theY = slightlyChangeVal(theY);
+ }
+
+ view->Viewer()->ShowGridEcho(view, Graphic3d_Vertex(closestGridPointX, closestGridPointY, closestGridPointZ));
+ view->Viewer()->SetGridEcho(true);
+ view->RedrawImmediate();
+ }
+ return true;
+ }
+ }
+}
\ No newline at end of file
class ModuleBase_IViewWindow;
class ModuleBase_ViewerPrs;
+class ModuleBase_IWorkshop;
+class ModelAPI_CompositeFeature;
class QMouseEvent;
+class QPoint;
-/**
- * This is an interface to allow processing of mouse events. Implementation of necessary methods
-* should be done in a child.
-*/
+/** Interface for mouse events processing. */
class PartSet_MouseProcessor
{
public:
virtual void setPreSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& thePreSelected,
ModuleBase_IViewWindow* theWnd,
QMouseEvent* theEvent) {}
+
+ protected:
+ /// \brief Converts position of mouse cursor to local coordinates on sketch plane.
+ /// Snaps on-sketch-plane-coordinates to closest construction grid node.
+ /// \param theEventPos is position of mouse cursor.
+ /// \param theX and \param theY are local coordinates on sketch plane.
+ /// \param theHighlight If point is snapped, hightlight grid point.
+ /// \param theAddOffset If true, serves as a remedy for odd crash during drawing of a line on a sketch.
+ /// \return true on success.
+ virtual bool convertPointToLocal(
+ ModuleBase_IWorkshop* theWorkshop,
+ const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch, // Passing by reference is intentionally.
+ ModuleBase_IViewWindow* theWindow,
+ const QPoint& theEventPos,
+ double& theX, double& theY,
+ bool theHighlight = false,
+ bool theAddOffset = false
+ ) const;
};
#endif
//
#include "PartSet_PreviewSketchPlane.h"
+#include "PartSet_SketcherMgr.h"
#include "PartSet_Tools.h"
#include <ModuleBase_IWorkshop.h>
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_CompositeFeature.h>
-#include <ModelAPI_Tools.h>
#include <GeomAPI_AISObject.h>
-#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Face.h>
#include <XGUI_Tools.h>
#include <XGUI_Displayer.h>
#include <SketchPlugin_Sketch.h>
#include <SketchPlugin_SketchEntity.h>
-#include <BRepBndLib.hxx>
-
-PartSet_PreviewSketchPlane::PartSet_PreviewSketchPlane()
- : myPreviewIsDisplayed(false), mySizeOfView(0), myIsUseSizeOfView(false)
+#include <ModuleBase_IViewer.h>
+#include <Aspect_Grid.hxx>
+#include <Geom_Plane.hxx>
+#include <AIS_PlaneTrihedron.hxx>
+#include <Quantity_Color.hxx>
+
+#include <gp_Pnt.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Trsf.hxx>
+#include <gp_Ax2d.hxx>
+#include <gp_Trsf2d.hxx>
+#include <gp_Pnt2d.hxx>
+#include <gp_Dir2d.hxx>
+
+#include <cmath>
+#include <algorithm>
+#include <limits>
+#include <QString>
+
+#define PI 3.14159265358979323846
+
+#ifdef SKETCH_ACCESSORY_DBG
+#include <iostream>
+#include <sstream>
+#include <string>
+const std::string PREFIX = "PreviewSketchPlane: ";
+const std::wstring WPREFIX = L"PreviewSketchPlane: ";
+#endif
+/*static*/ bool PartSet_PreviewSketchPlane::SketchAccessoryDbg(const QString& theString)
{
+#ifdef SKETCH_ACCESSORY_DBG
+ std::wcout << WPREFIX << theString.toStdWString() << std::endl;
+ return true;
+#else
+ return false;
+#endif
}
-
-void PartSet_PreviewSketchPlane::eraseSketchPlane(ModuleBase_IWorkshop* theWorkshop,
- const bool isClearPlane)
+/*static*/ bool PartSet_PreviewSketchPlane::SketchAccessoryDbg(const char* src)
{
- if (myPreviewIsDisplayed) {
- XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
- aDisp->eraseAIS(myPlane, false);
- myPreviewIsDisplayed = false;
- }
- if (isClearPlane) clearPlanePreview();
+#ifdef SKETCH_ACCESSORY_DBG
+ std::wcout << WPREFIX << std::wstring(src, src + strlen(src)) << std::endl;
+ return true;
+#else
+ return false;
+#endif;
}
-
-void PartSet_PreviewSketchPlane::displaySketchPlane(ModuleBase_IWorkshop* theWorkshop)
+/*static*/ bool PartSet_PreviewSketchPlane::SketchAccessoryDbg(const char* theCSDescription, const gp_Ax3& theCS)
{
- if (myPlane.get() && (!myPreviewIsDisplayed)) {
- XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
- aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
- myPreviewIsDisplayed = true;
- }
+#ifdef SKETCH_ACCESSORY_DBG
+ std::stringstream s;
+ s << PREFIX << theCSDescription << "\n";
+ theCS.DumpJson(s);
+ s << "\n";
+ PartSet_PreviewSketchPlane::SketchAccessoryDbg(QString::fromStdString(s.str()));
+ return true;
+#else
+ return false;
+#endif
+}
+/*static*/ bool PartSet_PreviewSketchPlane::SketchAccessoryDbg(const char* theCSDescription, const gp_Pnt& thePnt)
+{
+#ifdef SKETCH_ACCESSORY_DBG
+ std::stringstream s;
+ s << PREFIX << theCSDescription;
+ thePnt.DumpJson(s);
+ s << "\n";
+ PartSet_PreviewSketchPlane::SketchAccessoryDbg(QString::fromStdString(s.str()));
+ return true;
+#else
+ return false;
+#endif
+}
+/*static*/ bool PartSet_PreviewSketchPlane::SketchAccessoryDbg(const char* theCSDescription, const gp_Trsf& theMatrix)
+{
+#ifdef SKETCH_ACCESSORY_DBG
+ std::stringstream s;
+ s << PREFIX << theCSDescription << "\n";
+ theMatrix.DumpJson(s);
+ s << "\n";
+ PartSet_PreviewSketchPlane::SketchAccessoryDbg(QString::fromStdString(s.str()));
+ return true;
+#else
+ return false;
+#endif
}
-void PartSet_PreviewSketchPlane::clearPlanePreview()
+PartSet_PreviewSketchPlane::PartSet_PreviewSketchPlane(PartSet_SketcherMgr* theManager)
+ : mySketcherMgr(theManager), myValid(false),
+ mySketchDimensions(0, 0), mySketchDefaultSize(0),
+ myShowTrihedron(false), myTrihedron(new AIS_PlaneTrihedron(new Geom_Plane(1, 0, 0, 0))),
+ myShowSubstrate(false), mySubstrate(nullptr),
+ myGridType(PartSet_Tools::SketchPlaneGridType::No), myGridDrawMode(Aspect_GridDrawMode::Aspect_GDM_Lines),
+ mySnappingMode(GridSnappingMode::SnapAnyway),
+ myRectangularGridSteps(1, 1), myCircularGridRadialStep(1)
{
- myPlane = std::shared_ptr<GeomAPI_AISObject>();
- myShape = std::shared_ptr<GeomAPI_Shape>();
+ myTrihedron->SetXLabel("X'");
+ myTrihedron->SetYLabel("Y'");
+ myTrihedron->SetColor(Quantity_Color(Quantity_NameOfColor::Quantity_NOC_MAGENTA)); // The color does not coincide with colors of world axes.
}
-
-void PartSet_PreviewSketchPlane::createSketchPlane(const CompositeFeaturePtr& theSketch,
- ModuleBase_IWorkshop* theWorkshop)
+void PartSet_PreviewSketchPlane::savePreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const
{
- // plane is visualized only if sketch plane is filled
- if (!PartSet_Tools::sketchPlane(theSketch).get())
+ if (!theSketch || !this->isValid())
return;
- AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
- (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
- if (!aSelAttr)
+ PartSet_Tools::sketchPlaneAxesEnabled(theSketch)->setValue(myShowTrihedron);
+ PartSet_Tools::sketchPlaneSubstrateEnabled(theSketch)->setValue(myShowSubstrate);
+ PartSet_Tools::setSketchPlaneGridType(theSketch, myGridType);
+
+ saveRectangularGridPreferencesIntoSketchData(theSketch);
+}
+
+void PartSet_PreviewSketchPlane::saveRectangularGridPreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const
+{
+ if (!theSketch || !this->isValid())
return;
- if (myShape.get() && myShape->isSame(aSelAttr->value()) && myPlane.get())
+ PartSet_Tools::sketchPlaneRectangularGridStepX(theSketch)->setValue(myRectangularGridSteps.first);
+ PartSet_Tools::sketchPlaneRectangularGridStepY(theSketch)->setValue(myRectangularGridSteps.second);
+
+ PartSet_Tools::sketchPlaneRectangularGridOffsetAngle(theSketch)->setValue(myRectangularGridOffsetAngle);
+ PartSet_Tools::sketchPlaneRectangularGridOffsetX(theSketch)->setValue(myRectangularGridTransOffset.first);
+ PartSet_Tools::sketchPlaneRectangularGridOffsetY(theSketch)->setValue(myRectangularGridTransOffset.second);
+}
+
+void PartSet_PreviewSketchPlane::saveCircularGridPreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const
+{
+ if (!theSketch || !this->isValid())
return;
- XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
- if (myPreviewIsDisplayed) {
- aDisp->eraseAIS(myPlane, false);
- }
-
- // Create Preview
- // selected linear face parameters
- myShape = aSelAttr->value();
- // this case is needed by constructing sketch on a plane, where result shape is equal
- // to context result, therefore value() returns NULL and we should use shape of context.
- if (!myShape.get() && aSelAttr->context().get())
- myShape = aSelAttr->context()->shape();
-
- if (!myShape.get()) {
- // Create Preview for default planes
- std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
- theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
-
- double aFaceSize = myIsUseSizeOfView ? mySizeOfView
- : Config_PropManager::real(SKETCH_TAB_NAME, "planes_size");
- if (aFaceSize <= Precision::Confusion())
- aFaceSize = 200; // Set default value
-
- myShape = GeomAlgoAPI_FaceBuilder::squareFace(
- myViewCentralPoint.get() ? myViewCentralPoint : anOrigin->pnt(), aNormal->dir(), aFaceSize);
- }
- else if (myIsUseSizeOfView && (mySizeOfView > 0)) {
- std::shared_ptr<GeomAPI_Face> aFace(new GeomAPI_Face(myShape));
- std::shared_ptr<GeomAPI_Pln> aPlane = aFace->getPlane();
- if (aPlane.get()) {
- double anA, aB, aC, aD;
- aPlane->coefficients(anA, aB, aC, aD);
- std::shared_ptr<GeomAPI_Dir> aNormDir(new GeomAPI_Dir(anA, aB, aC));
- std::shared_ptr<GeomAPI_XYZ> aCoords = aNormDir->xyz();
- std::shared_ptr<GeomAPI_XYZ> aZero(new GeomAPI_XYZ(0, 0, 0));
- aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero));
- std::shared_ptr<GeomAPI_Pnt> anOrigPnt(new GeomAPI_Pnt(aCoords));
- myShape = GeomAlgoAPI_FaceBuilder::squareFace(
- myViewCentralPoint.get() ? myViewCentralPoint : anOrigPnt, aNormDir, mySizeOfView);
- }
- }
- myPlane = createPreviewPlane();
+ PartSet_Tools::sketchPlaneCircularGridStepR(theSketch)->setValue(myCircularGridRadialStep);
+ PartSet_Tools::sketchPlaneCircularGridNumOfAngSegments(theSketch)->setValue(myCircularGridNumOfAngularSections);
- aDisp->displayAIS(myPlane, false/*load object in selection*/, 1/*shaded*/, false);
- myPreviewIsDisplayed = true;
+ PartSet_Tools::sketchPlaneCircularGridOffsetAngle(theSketch)->setValue(myCircularGridOffsetAngle);
+ PartSet_Tools::sketchPlaneCircularGridOffsetX(theSketch)->setValue(myCircularGridTransOffset.first);
+ PartSet_Tools::sketchPlaneCircularGridOffsetY(theSketch)->setValue(myCircularGridTransOffset.second);
}
-double maximumSize(double theXmin, double theYmin, double theZmin,
- double theXmax, double theYmax, double theZmax)
+void PartSet_PreviewSketchPlane::setCSAndSize(const gp_Ax3& theCS, double theSize)
{
- double aSize = fabs(theXmax - theXmin);
- double aSizeToCompare = fabs(theYmax - theYmin);
- if (aSizeToCompare > aSize)
- aSize = aSizeToCompare;
- aSizeToCompare = fabs(theZmax - theZmin);
- if (aSizeToCompare > aSize)
- aSize = aSizeToCompare;
+ SketchAccessoryDbg("setCSAndSize(_)");
- return aSize;
+ mySketchCS = theCS;
+ mySketchDefaultSize = std::abs(theSize);
+ mySketchDimensions.first = mySketchDefaultSize;
+ mySketchDimensions.second = mySketchDefaultSize;
+
+ configureTrihedron();
+
+ if (!mySubstrate)
+ initSubstrate(nullptr);
+ else {
+ const auto face = GeomAlgoAPI_FaceBuilder::planarRectangularFace(mySketchCS, mySketchDimensions.first, mySketchDimensions.second);
+ mySubstrate->createShape(face);
+ }
+
+ reconfigureGrid();
+ myValid = true;
}
-bool PartSet_PreviewSketchPlane::getDefaultSizeOfView(
- const CompositeFeaturePtr& theSketch, double& theSizeOfView,
- std::shared_ptr<GeomAPI_Pnt>& theCentralPnt)
+bool PartSet_PreviewSketchPlane::setAllUsingSketch(std::shared_ptr<ModelAPI_CompositeFeature> theSketch)
{
- if (!PartSet_Tools::sketchPlane(theSketch).get())
+ SketchAccessoryDbg("setAllUsingSketch(theSketch)");
+
+ if (!theSketch || !PartSet_Tools::sketchPlane(theSketch)) {
+ SketchAccessoryDbg("invalid sketch - nullptr or normal/center is undefined.");
+ setInvalid();
return false;
+ }
- AttributeSelectionPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
- (theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
+ bool sketchIsBlank = false;
+ const auto aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theSketch->data()->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
if (aSelAttr) {
- myShape = aSelAttr->value();
- // this case is needed by constructing sketch on a plane, where result shape is equal
- // to context result, therefore value() returns NULL and we should use shape of context.
- if (!myShape.get() && aSelAttr->context().get())
- myShape = aSelAttr->context()->shape();
+ std::shared_ptr<GeomAPI_Shape> sketchShape;
+ if (aSelAttr->value()) {
+ sketchShape = aSelAttr->value();
+ SketchAccessoryDbg("aSelAttr->value()");
+ }
+ else if (aSelAttr->context()) {
+ sketchShape = aSelAttr->context()->shape();
+ SketchAccessoryDbg("aSelAttr->context()->shape()");
+ }
+
+ if (!sketchShape) {
+ sketchIsBlank = true;
+ }
+ else {
+ if (!sketchShape->isPlanar()) {
+ SketchAccessoryDbg("invalid sketch - shape is not planar.");
+ setInvalid();
+ return false;
+ }
+ const std::shared_ptr<GeomAPI_Face> sketchFace = sketchShape->face();
+ if (!sketchFace) {
+ SketchAccessoryDbg("invalid sketch - shape is not face.");
+ setInvalid();
+ return false;
+ }
+
+ { // Define CS as one at the center (Uc, Vc) of parametric domain.
+ // If the planar surface is non-convex, the center of parametric domain may
+ // lay outside of the surface. If X'(U, V) or Y'(U, V) are non-linear,
+ // X(Uc, Vc), Y(Uc, Vc) or its 1st derivative may not be defined.
+ // But:
+ // 1) The sketch widget only accepts Planes to start sketch.
+ // 2) The set of planar surfaces, being used in the app, does not include those described above.
+ double UMax, UMin, VMax, VMin;
+ const bool success = sketchFace->optimalBounds(UMin, UMax, VMin, VMax);
+ if (!success) {
+ SketchAccessoryDbg("Can't get sketch CS: UV-domain is undefined.");
+ setInvalid();
+ return false;
+ }
+
+ // X' and Y' directions and sketch center in the sketch->data() are not coincide with
+ // ones of the surface the sketch is started on.
+ const auto sketchFaceCS = PartSet_Tools::getWorldCSAt(*sketchFace, (UMin+UMax)/2, (VMin+VMax)/2);
+ if (!sketchFaceCS.first) {
+ SketchAccessoryDbg("Can't get sketch CS: sketch face is not 1-differentiable as function of U and V at the center of UV-domain.");
+ setInvalid();
+ return false;
+ }
+
+ mySketchCS = sketchFaceCS.second;
+ }
+
+ mySketchDefaultSize = PartSet_Tools::sketchPlaneDefaultSize(theSketch)->value();
+
+ { // Calculate sketch dimensions.
+ // The only purpose of converting from UV to X'Y' during calculation of sketch dimensions
+ // is to take into account scale factor or if the a non-orthogonal transformation is applied (if it even possible).
+ const auto sketchFaceBox = PartSet_Tools::getBBoxAtCS(*sketchFace, mySketchCS);
+ if (!sketchFaceBox.first) {
+ SketchAccessoryDbg("Can't find bounding box for sketch face.");
+ setInvalid();
+ mySketchDimensions.first = getDefaultSize();
+ mySketchDimensions.second = getDefaultSize();
+ }
+ else {
+ // Here X and Y are X' and Y', and Z is sketch normal.
+ double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
+ sketchFaceBox.second.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+
+ mySketchDimensions.first = std::abs(Xmax - Xmin);
+ mySketchDimensions.second = std::abs(Ymax - Ymin);
+ }
+ }
+
+ if (!mySubstrate)
+ initSubstrate(sketchFace);
+ else
+ mySubstrate->createShape(sketchFace);
+
+#ifdef SKETCH_ACCESSORY_DBG
+ auto sketchCS = gp_Ax3();
+ {
+ const auto aData = theSketch->data();
+ const auto aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ const auto aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ const auto aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+ try {
+ sketchCS = gp_Ax3(aC->pnt()->impl<gp_Pnt>(), aX->dir()->impl<gp_Dir>(), aNorm->dir()->impl<gp_Dir>());
+ }
+ catch(...) {
+ SketchAccessoryDbg("Sketch data contains invalid basis.");
+ }
+ }
+
+ SketchAccessoryDbg("Sketch CS (sketch data):", sketchCS);
+ SketchAccessoryDbg("Sketch face CS:", mySketchCS);
+ SketchAccessoryDbg(QString("Sketch dimensions: ") + QString::number(mySketchDimensions.first) + ", " + QString::number(mySketchDimensions.second));
+#endif
+ }
+ }
+
+ if (sketchIsBlank) {
+ SketchAccessoryDbg(QString("setAllUsingSketch(theSketch). Empty sketch"));
+ try
+ {
+ const auto sketchOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID())
+ );
+
+ const auto sketchNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())
+ );
+
+ const auto sketchXDirection = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::DIRX_ID())
+ );
+
+ mySketchCS.SetLocation(sketchOrigin->pnt()->impl<gp_Pnt>());
+
+ const gp_Dir normal = sketchNormal->dir()->impl<gp_Dir>();
+ mySketchCS.SetDirection(normal);
+ // Chi is synonym for X'.
+ const gp_Dir chiDirection = sketchXDirection->dir()->impl<gp_Dir>();
+ mySketchCS.SetXDirection(chiDirection);
+
+ mySketchDefaultSize = PartSet_Tools::sketchPlaneDefaultSize(theSketch)->value();
+ const double defaultSize = getDefaultSize();
+ mySketchDimensions.first = defaultSize;
+ mySketchDimensions.second = defaultSize;
+ }
+ catch(...) {
+ SketchAccessoryDbg("Invalid basis in sketch data.");
+ setInvalid();
+ return false;
+ }
}
- if (myShape.get())
+ configureTrihedron();
+
+ if (sketchIsBlank) {
+ if (!mySubstrate)
+ initSubstrate(nullptr);
+ else {
+ const auto face = GeomAlgoAPI_FaceBuilder::planarRectangularFace(mySketchCS, mySketchDimensions.first, mySketchDimensions.second);
+ mySubstrate->createShape(face);
+ }
+ }
+
+ myValid = true;
+ showAxes(PartSet_Tools::sketchPlaneAxesEnabled(theSketch)->value());
+ showSubstrate(PartSet_Tools::sketchPlaneSubstrateEnabled(theSketch)->value());
+ reconfigureGridUsingSketch(theSketch);
+ return true;
+}
+
+bool PartSet_PreviewSketchPlane::reconfigureGrid()
+{
+ return reconfigureGridUsingSketch(nullptr);
+}
+
+bool PartSet_PreviewSketchPlane::reconfigureGridUsingSketch(std::shared_ptr<ModelAPI_CompositeFeature> theSketch)
+{
+ static const auto MARKER_COLOR = Quantity_Color(Quantity_NameOfColor::Quantity_NOC_TOMATO);
+ static const auto MARKER_SIZE = 2.0;
+ static const opencascade::handle<Graphic3d_AspectMarker3d> MARKER = new Graphic3d_AspectMarker3d(Aspect_TypeOfMarker::Aspect_TOM_BALL, MARKER_COLOR, MARKER_SIZE);
+ static const double MARGINS = 1.005; // Makes grid surface bigger to display marginal grid lines.
+
+ if (!isValid())
+ return myGridType == PartSet_Tools::SketchPlaneGridType::No;
+
+ const auto aV3DViewer = getV3DViewer();
+ if (!aV3DViewer) {
+ SketchAccessoryDbg("can't retrieve V3d_Viewer to configure grid.");
return false;
+ }
- Bnd_Box aBox;
- int aNumberOfSubs = theSketch->numberOfSubs();
- for (int aSubFeatureId = 0; aSubFeatureId < aNumberOfSubs; aSubFeatureId++) {
- FeaturePtr aFeature = theSketch->subFeature(aSubFeatureId);
- if (!aFeature.get())
- continue;
-
- std::list<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::const_iterator aResultIt;
- for (aResultIt = aResults.begin(); aResultIt != aResults.end(); ++aResultIt) {
- ResultPtr aResult = *aResultIt;
- std::shared_ptr<GeomAPI_Shape> aShapePtr = aResult->shape();
- if (aShapePtr.get()) {
- TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
- if (aShape.IsNull())
- continue;
- BRepBndLib::Add(aShape, aBox);
- }
+ const auto dimensions = getDimensions();
+
+ if (theSketch) {
+ { // Rectangular grid.
+ const double stepXAttrVal = PartSet_Tools::sketchPlaneRectangularGridStepX(theSketch)->value();
+ myRectangularGridSteps.first = stepXAttrVal < 0 ? dimensions.first / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE : stepXAttrVal;
+
+ const double stepYAttrVal = PartSet_Tools::sketchPlaneRectangularGridStepY(theSketch)->value();
+ myRectangularGridSteps.second = stepYAttrVal < 0 ? dimensions.second / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE : stepYAttrVal;
+
+ myRectangularGridTransOffset.first = PartSet_Tools::sketchPlaneRectangularGridOffsetX(theSketch)->value();
+ myRectangularGridTransOffset.second = PartSet_Tools::sketchPlaneRectangularGridOffsetY(theSketch)->value();
+ myRectangularGridOffsetAngle = PartSet_Tools::sketchPlaneRectangularGridOffsetAngle(theSketch)->value();
+ }
+
+ { // Circular grid
+ myCircularGridTransOffset.first = PartSet_Tools::sketchPlaneCircularGridOffsetX(theSketch)->value();
+ myCircularGridTransOffset.second = PartSet_Tools::sketchPlaneCircularGridOffsetY(theSketch)->value();
+ myCircularGridOffsetAngle = PartSet_Tools::sketchPlaneCircularGridOffsetAngle(theSketch)->value();
+
+ const double stepRAttrVal = PartSet_Tools::sketchPlaneCircularGridStepR(theSketch)->value();
+ myCircularGridRadialStep = stepRAttrVal < 0 ?
+ std::min(dimensions.first, dimensions.second) / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE * 2 :
+ stepRAttrVal;
+
+ const int aNAS = PartSet_Tools::sketchPlaneCircularGridNumOfAngSegments(theSketch)->value();
+ myCircularGridNumOfAngularSections = aNAS <= 0 ? PartSet_PreviewSketchPlane::DEFAULT_NUM_OF_ANGULAR_SECTIONS : aNAS;
+ }
+
+ myGridType = PartSet_Tools::getSketchPlaneGridType(theSketch);
+ }
+
+ aV3DViewer->SetGridEcho(MARKER);
+
+ if (myGridType == PartSet_Tools::SketchPlaneGridType::Rectangular) {
+ static const double MAX = std::numeric_limits<double>::max();
+
+ auto steps = myRectangularGridSteps;
+ if (steps.first <= Precision::Confusion())
+ steps.first = MAX;
+
+ if (steps.second <= Precision::Confusion())
+ steps.second = MAX;
+
+ // Chi and Upsilon are synonyms for X' and Y'.
+ const double offsetChi = steps.first < MAX ? std::remainder(myRectangularGridTransOffset.first , steps.first) : myRectangularGridTransOffset.first;
+ const double offsetUpsilon = steps.second < MAX ? std::remainder(myRectangularGridTransOffset.second, steps.second) : myRectangularGridTransOffset.second;
+ const double offsetAngleRad = myRectangularGridOffsetAngle * PI / 180;
+
+ aV3DViewer->SetPrivilegedPlane(mySketchCS);
+ aV3DViewer->SetRectangularGridValues(offsetChi, offsetUpsilon, steps.first, steps.second, offsetAngleRad);
+#define V3DVIEWER_RECTANGULAR_GRID_OFFSET_BUGS
+#ifdef V3DVIEWER_RECTANGULAR_GRID_OFFSET_BUGS
+ /*
+ How grid offsets should work? Imagine an invisible rectangular frame - only those elements of the the grid must be visible,
+ which are inside of the frame.
+ If an offset is adjusted, the frame remains intact and stays in place, but elements of the grid are shifted/rotated
+ appropriate to the offset direction and value.
+ The dimensions of the frame are ones of 2D bounding box of the sketch face.
+
+ V3d_Viewer::SetRectangularGridGraphicValues adjusts grid elements' position, but also translates/rotates the frame of the grid!
+ Following equations enlarge grid dimensions, so that the entire surface of the 2D BBox is covered with grid.
+ */
+
+ const auto outerDims = PartSet_PreviewSketchPlane::dimsOfRectangleFittingRectangle(
+ dimensions.first, dimensions.second, -offsetAngleRad, offsetChi, offsetUpsilon
+ );
+
+ aV3DViewer->SetRectangularGridGraphicValues(outerDims.first / 2 * MARGINS, outerDims.second / 2 * MARGINS, 0);
+
+ {
+ const int chiDim = outerDims.first / 2 * MARGINS / steps.first >= 1 ? 1 : 0;
+ const int upsilonDim = outerDims.second / 2 * MARGINS / steps.second >= 1 ? 1 : 0;
+ myRectangularGridDimOfNodeSpace = chiDim + upsilonDim;
+ }
+#else
+ aV3DViewer->SetRectangularGridGraphicValues(dimensions.first / 2 * MARGINS, dimensions.second / 2 * MARGINS, 0);
+
+ {
+ const int chiDim = dimensions.first / 2 * MARGINS / steps.first >= 1 ? 1 : 0;
+ const int upsilonDim = dimensions.second / 2 * MARGINS / steps.second >= 1 ? 1 : 0;
+ myRectangularGridDimOfNodeSpace = chiDim + upsilonDim;
+ }
+#endif
+ }
+ else if (myGridType == PartSet_Tools::SketchPlaneGridType::Circular) {
+ const int& aNAS = myCircularGridNumOfAngularSections;
+ const int divisionNumber = aNAS == 1 ? 0 : aNAS / 2 + aNAS % 2; // V3d_Viewer::SetCircularGridValues is weird.
+
+ aV3DViewer->SetPrivilegedPlane(mySketchCS);
+ aV3DViewer->SetCircularGridValues(
+ myCircularGridTransOffset.first, myCircularGridTransOffset.second,
+ myCircularGridRadialStep > Precision::Confusion() ? myCircularGridRadialStep : std::numeric_limits<double>::max(),
+ divisionNumber,
+ myCircularGridOffsetAngle * PI / 180
+ );
+
+ /* Circles of circular grid are not circles, but regular polygons and cover less surface than circles. */
+ const double R = getCircularGridRaduis(dimensions);
+ int numOfEdges = aNAS < 12 ? 12 : aNAS + aNAS % 2;
+ const double polyR = R / std::cos(PI / numOfEdges) * MARGINS;
+ aV3DViewer->SetCircularGridGraphicValues(polyR, 0);
+
+ {
+ const int angularDim = divisionNumber > 2 ? 2 : 1;
+ const int radialDim = myCircularGridRadialStep > Precision::Confusion() && polyR / myCircularGridRadialStep >=1 ? 1 : 0;
+ myRectangularGridDimOfNodeSpace = angularDim * radialDim;
}
}
- if (aBox.IsVoid())
- return 0;
- double aXmin, aXmax, anYmin, anYmax, aZmin, aZmax;
- aBox.Get(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
+ if (theSketch) {
+ if (myGridType == PartSet_Tools::SketchPlaneGridType::No)
+ aV3DViewer->DeactivateGrid();
+ else {
+ Aspect_GridType type = myGridType == PartSet_Tools::SketchPlaneGridType::Rectangular ?
+ Aspect_GridType::Aspect_GT_Rectangular : Aspect_GridType::Aspect_GT_Circular;
- theSizeOfView = maximumSize(aXmin, anYmin, aZmin, aXmax, anYmax, aZmax);
- if (theSizeOfView > 0) {
- gp_Pnt aCentre(aXmax-fabs(aXmax-aXmin)/2., anYmax-fabs(anYmax-anYmin)/2.,
- aZmax - fabs(aZmax-aZmin)/2.);
- theCentralPnt = std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(),
- aCentre.Z()));
+ aV3DViewer->ActivateGrid(type, myGridDrawMode);
+ }
}
+
+ return true;
+}
+
+bool PartSet_PreviewSketchPlane::showAxes(bool theShow)
+{
+ if (!isValid())
+ return !theShow;
+
+ XGUI_Displayer* const displayer = mySketcherMgr->workshop()->displayer();
+ if (theShow)
+ displayer->displayAIS(myTrihedron, false /*load object in selection*/, 1 /*shaded*/, false /*update viewer*/);
+ else
+ displayer->eraseAIS(myTrihedron, false /*update viewer*/);
+
+ myShowTrihedron = theShow;
return true;
}
-void PartSet_PreviewSketchPlane::setSizeOfView(double theSizeOfView, bool isUseSizeOfView,
- const std::shared_ptr<GeomAPI_Pnt>& theCentralPoint)
+bool PartSet_PreviewSketchPlane::showSubstrate(bool theShow)
{
- mySizeOfView = theSizeOfView;
- myIsUseSizeOfView = isUseSizeOfView;
+ if (!isValid())
+ return !theShow;
- myViewCentralPoint = theCentralPoint;
+ XGUI_Displayer* const displayer = mySketcherMgr->workshop()->displayer();
+ if (theShow)
+ displayer->displayAIS(mySubstrate, false /*load object in selection*/, 1 /*shaded*/, false /*update viewer*/);
+ else
+ displayer->eraseAIS(mySubstrate, false /*update viewer*/);
+
+ myShowSubstrate = theShow;
+ return true;
}
-AISObjectPtr PartSet_PreviewSketchPlane::createPreviewPlane()
+bool PartSet_PreviewSketchPlane::setGridType(PartSet_Tools::SketchPlaneGridType::Enum theType)
{
- if (myPlane.get()) {
- myPlane->createShape(myShape);
- return myPlane;
+ if (!isValid())
+ return theType == PartSet_Tools::SketchPlaneGridType::No;
+
+ const auto aV3DViewer = getV3DViewer();
+ if (!aV3DViewer) {
+ SketchAccessoryDbg("can't retrieve V3d_Viewer to show/hide grid.");
+ return false;
}
+
+ myGridType = theType;
+ reconfigureGrid();
+
+ if (myGridType == PartSet_Tools::SketchPlaneGridType::No)
+ aV3DViewer->DeactivateGrid();
else {
- AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
- aAIS->createShape(myShape);
- std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
- if (aColor.size() == 3)
- aAIS->setColor(aColor[0], aColor[1], aColor[2]);
- aAIS->setTransparensy(0.8);
-
- int aDispMode = 1; // shading
- Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
- if (!anAISIO.IsNull()) {
- //anAISIO->SetInfiniteState(Standard_True);
- anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
- anAISIO->SetDisplayMode(aDispMode);
+ Aspect_GridType type = myGridType == PartSet_Tools::SketchPlaneGridType::Rectangular ?
+ Aspect_GridType::Aspect_GT_Rectangular : Aspect_GridType::Aspect_GT_Circular;
+
+ aV3DViewer->ActivateGrid(type, myGridDrawMode);
+ }
+
+ return true;
+}
+
+void PartSet_PreviewSketchPlane::hideAll()
+{
+ showAxes(false);
+ showSubstrate(false);
+ setGridType(PartSet_Tools::SketchPlaneGridType::No);
+}
+
+std::pair<double, double> PartSet_PreviewSketchPlane::getDimensions() const
+{
+ const double defaultSize = getDefaultSize();
+ // Chi and Upsilon are synonyms for X' and Y'.
+ const bool chiSizeOk = mySketchDimensions.first > Precision::Confusion();
+ const bool upsilonSizeOk = mySketchDimensions.second > Precision::Confusion();
+
+ return std::pair<double, double>(
+ chiSizeOk ? mySketchDimensions.first : upsilonSizeOk ? mySketchDimensions.second : defaultSize,
+ upsilonSizeOk ? mySketchDimensions.second : chiSizeOk ? mySketchDimensions.first : defaultSize
+ );
+}
+
+void PartSet_PreviewSketchPlane::resetRectangularGrid()
+{
+ const auto dimensions = getDimensions();
+ myRectangularGridSteps.first = dimensions.first / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE;
+ myRectangularGridSteps.second = dimensions.second / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE;
+ myRectangularGridOffsetAngle = 0;
+ myRectangularGridTransOffset.first = 0;
+ myRectangularGridTransOffset.second = 0;
+}
+
+void PartSet_PreviewSketchPlane::setRectangularGridStepX(double theStepX)
+{
+ myRectangularGridSteps.first = theStepX;
+}
+
+void PartSet_PreviewSketchPlane::setRectangularGridStepY(double theStepY)
+{
+ myRectangularGridSteps.second = theStepY;
+}
+
+std::pair<std::pair<double, double>, double> PartSet_PreviewSketchPlane::getRectangularGridOffsets() const
+{
+ return std::pair<std::pair<double, double>, double>(myRectangularGridTransOffset, myRectangularGridOffsetAngle);
+}
+
+void PartSet_PreviewSketchPlane::setRectangularGridOffsetX(double theOffsetX)
+{
+ myRectangularGridTransOffset.first = theOffsetX;
+}
+
+void PartSet_PreviewSketchPlane::setRectangularGridOffsetY(double theOffsetY)
+{
+ myRectangularGridTransOffset.second = theOffsetY;
+}
+
+void PartSet_PreviewSketchPlane::setRectangularGridOffsetA(double theOffsetAngle)
+{
+ myRectangularGridOffsetAngle = theOffsetAngle;
+}
+
+void PartSet_PreviewSketchPlane::resetCircularGrid()
+{
+ const auto d = getDimensions();
+ double R = std::sqrt(std::pow(d.first, 2) + std::pow(d.second, 2)) / 2;
+
+ myCircularGridRadialStep = R / PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE;
+ myCircularGridNumOfAngularSections = PartSet_PreviewSketchPlane::DEFAULT_NUM_OF_ANGULAR_SECTIONS;
+ myCircularGridOffsetAngle = 0;
+ myCircularGridTransOffset.first = 0;
+ myCircularGridTransOffset.second = 0;
+}
+
+void PartSet_PreviewSketchPlane::setCircularGridRadialStep(double theStep)
+{
+ myCircularGridRadialStep = theStep;
+}
+
+void PartSet_PreviewSketchPlane::setCircularGridNumOfAngularSegments(int theNum)
+{
+ myCircularGridNumOfAngularSections = theNum;
+}
+
+std::pair<double, int> PartSet_PreviewSketchPlane::getCircularGrid_dR_and_NAS() const
+{
+ return std::pair<double, int>(myCircularGridRadialStep, myCircularGridNumOfAngularSections);
+}
+
+void PartSet_PreviewSketchPlane::setCircularGridOffsetX(double theOffset)
+{
+ myCircularGridTransOffset.first = theOffset;
+}
+
+void PartSet_PreviewSketchPlane::setCircularGridOffsetY(double theOffset)
+{
+ myCircularGridTransOffset.second = theOffset;
+}
+
+void PartSet_PreviewSketchPlane::setCircularGridOffsetA(double theOffset)
+{
+ myCircularGridOffsetAngle = theOffset;
+}
+
+std::pair<std::pair<double, double>, double> PartSet_PreviewSketchPlane::getCircularGridOffsets() const
+{
+ return std::pair<std::pair<double, double>, double>(myCircularGridTransOffset, myCircularGridOffsetAngle);
+}
+
+void PartSet_PreviewSketchPlane::configureTrihedron()
+{
+ const opencascade::handle<Geom_Plane> aGeom_Plane = new Geom_Plane(mySketchCS);
+ const auto dimensions = getDimensions();
+ myTrihedron->SetComponent(aGeom_Plane);
+ myTrihedron->SetLength(std::min(dimensions.first, dimensions.second) / 2);
+}
+
+void PartSet_PreviewSketchPlane::initSubstrate(std::shared_ptr<GeomAPI_Face> theFace)
+{
+ if (!theFace) {
+ const auto dimensions = getDimensions();
+ theFace = GeomAlgoAPI_FaceBuilder::planarRectangularFace(mySketchCS, dimensions.first, dimensions.second);
+ }
+
+ AISObjectPtr aAIS = AISObjectPtr(new GeomAPI_AISObject());
+ aAIS->createShape(theFace);
+ std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_preview_plane");
+ if (aColor.size() == 3)
+ aAIS->setColor(aColor[0], aColor[1], aColor[2]);
+
+ aAIS->setTransparensy(0.8);
+
+ int aDispMode = 1; // shading
+ Handle(AIS_InteractiveObject) anAISIO = aAIS->impl<Handle(AIS_InteractiveObject)>();
+ if (!anAISIO.IsNull()) {
+ anAISIO->Attributes()->SetFaceBoundaryDraw( Standard_True );
+ anAISIO->SetDisplayMode(aDispMode);
+ }
+ mySubstrate = std::move(aAIS);
+}
+
+opencascade::handle<V3d_Viewer> PartSet_PreviewSketchPlane::getV3DViewer() const
+{
+ const ModuleBase_IViewer* const viewer = mySketcherMgr->workshop()->salomeViewer();
+ if (!viewer)
+ return nullptr;
+
+ return viewer->v3dViewer();
+}
+
+bool PartSet_PreviewSketchPlane::isValid() const
+{
+ return myValid;
+}
+
+void PartSet_PreviewSketchPlane::setInvalid()
+{
+ myValid = false;
+
+ XGUI_Displayer* const displayer = mySketcherMgr->workshop()->displayer();
+
+ displayer->eraseAIS(myTrihedron, false /*update viewer*/);
+ myShowTrihedron = false;
+
+ if (mySubstrate && myShowSubstrate) {
+ displayer->eraseAIS(mySubstrate, false /*update viewer*/);
+ myShowSubstrate = false;
+ }
+
+ if (myGridType != PartSet_Tools::SketchPlaneGridType::No) {
+ ModuleBase_IViewer* aViewer = mySketcherMgr->workshop()->salomeViewer();
+ const auto aV3DViewer = getV3DViewer();
+ if (aV3DViewer) {
+ aV3DViewer->DeactivateGrid();
+ myGridType = PartSet_Tools::SketchPlaneGridType::No;
}
- return aAIS;
+ else {
+ SketchAccessoryDbg("can't retrieve V3d_Viewer to deactivate grid.");
+ }
+ }
+}
+
+double PartSet_PreviewSketchPlane::getDefaultSize() const {
+ const double defaultSize = mySketchDefaultSize;
+ if (defaultSize <= Precision::Confusion())
+ return PartSet_PreviewSketchPlane::defaultSketchSize();
+
+ return defaultSize;
+}
+
+double PartSet_PreviewSketchPlane::getCircularGridRaduis(const std::pair<double, double>& theBBox2Dimensions) const
+{
+ // Find big enough R to cover entire 2D-bounding of sketch face.
+ const double& Cx = myCircularGridTransOffset.first;
+ const double& Cy = myCircularGridTransOffset.second;
+ const double& W = theBBox2Dimensions.first / 2;
+ const double& H = theBBox2Dimensions.second / 2;
+
+ /* Distances from center of circular grid to vertices of sketch face 2D rectangular box. */
+ double squareDistances[4];
+ squareDistances[0] = std::pow(Cx - W, 2) + std::pow(Cy - H, 2);
+ squareDistances[1] = std::pow(Cx + W, 2) + std::pow(Cy - H, 2);
+ squareDistances[2] = std::pow(Cx - W, 2) + std::pow(Cy + H, 2);
+ squareDistances[3] = std::pow(Cx + W, 2) + std::pow(Cy + H, 2);
+ double R2 = squareDistances[3];
+ for (int i = 0; i < 3; i++) {
+ if (squareDistances[i] > R2)
+ R2 = squareDistances[i];
}
+
+ return std::sqrt(R2);
}
+
+/*static*/ double PartSet_PreviewSketchPlane::defaultSketchSize()
+{
+ const double defaultSize = Config_PropManager::real(SKETCH_TAB_NAME, "planes_size");
+ if (defaultSize <= Precision::Confusion())
+ return PartSet_PreviewSketchPlane::DEFAULT_SKETCH_SIZE;
+
+ return defaultSize;
+}
+
+/*static*/ const double PartSet_PreviewSketchPlane::DEFAULT_SKETCH_SIZE = 200;
+/*static*/ const double PartSet_PreviewSketchPlane::DEFAULT_RELATIVE_STEP_INVERSE = 20;
+/*static*/ const int PartSet_PreviewSketchPlane::DEFAULT_NUM_OF_ANGULAR_SECTIONS = 18;
+/*static*/ const int PartSet_PreviewSketchPlane::SNAP_PROXIMITY_P = 10;
+
+/*static*/ std::pair<double, double> PartSet_PreviewSketchPlane::dimsOfRectangleFittingRectangle(
+ double wInner, double hInner, double a, double cX, double cY
+) {
+ const auto center = gp_Pnt2d(cX, cY);
+ const auto dirX = gp_Dir2d(std::cos(a), std::sin(a));
+ const gp_Ax2d csOuter = gp_Ax2d(center, dirX);
+
+ gp_Pnt2d vertexInner[4] =
+ {gp_Pnt2d(-wInner/2, -hInner/2), gp_Pnt2d(-wInner/2, hInner/2), gp_Pnt2d(wInner/2, -hInner/2), gp_Pnt2d(wInner/2, hInner/2)};
+
+ gp_Trsf2d trsf;
+ trsf.SetTransformation(csOuter);
+
+ double maxXP = 0, minXN = 0, maxYP = 0, minYN = 0;
+ for (int i = 0; i < 4; i++) {
+ vertexInner[i].Transform(trsf);
+ const auto& v = vertexInner[i];
+ if (v.X() > maxXP)
+ maxXP = v.X();
+ else if (v.X() < minXN)
+ minXN = v.X();
+
+ if (v.Y() > maxYP)
+ maxYP = v.Y();
+ else if (v.Y() < minYN)
+ minYN = v.Y();
+ }
+ return std::pair<double, double>(std::max(maxXP, -minXN) * 2, std::max(maxYP, -minYN) * 2);
+}
\ No newline at end of file
#ifndef PartSet_PreviewSketchPlane_H
#define PartSet_PreviewSketchPlane_H
-#include <GeomAPI_Pnt.h>
+#include <memory>
+#include <utility>
+#include <Standard_Handle.hxx>
+#include <Aspect_GridType.hxx>
+#include <Aspect_GridDrawMode.hxx>
+#include <ModelAPI_CompositeFeature.h>
+#include <gp_Ax3.hxx>
-class GeomAPI_AISObject;
-class GeomAPI_Shape;
+#include "PartSet_Tools.h"
-class ModuleBase_IWorkshop;
+class PartSet_SketcherMgr;
class ModelAPI_CompositeFeature;
+class GeomAPI_AISObject;
+class GeomAPI_Face;
+class AIS_PlaneTrihedron;
+class V3d_Viewer;
+class QString;
+class gp_Trsf;
-#include <memory>
+// #define SKETCH_ACCESSORY_DBG;
/**
* \class PartSet_PreviewSketchPlane
* \ingroup Modules
-* A class to show/hide sketch preview plane
+* Visualization of 2D-bluebrint' accessories: translucent rectangular substrate, basis axes, grid.
+* All methods do not modify sketch data, unless otherwise is stated.
*/
class PartSet_PreviewSketchPlane
{
public:
- /// Constructor
- PartSet_PreviewSketchPlane();
-
- ~PartSet_PreviewSketchPlane() {};
-
- /// Erase preview planes
- /// \param theWorkshop the application workshop
- /// \param isClearPlane flag whether the plane, origin and normal should be nullified
- void eraseSketchPlane(ModuleBase_IWorkshop* theWorkshop, const bool isClearPlane = true);
-
- /// Show preview planes
- /// \param theSketch source sketch to initialize plane
- /// \param theWorkshop the application workshop
- void createSketchPlane(const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
- ModuleBase_IWorkshop* theWorkshop);
-
- /// Returns bounding box size covered the sketch sub-elements.
- /// If the sketch uses extenal face, it will not have default size and returns false.
- /// \param theSketch sources sketch
- /// \param [out] theSizeOfView maximum value in X, Y or Z direction
- /// \param theCentralPoint central point of the sketch sub features
- /// \return boolean value
- bool getDefaultSizeOfView(const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
- double& theSizeOfView,
- std::shared_ptr<GeomAPI_Pnt>& theCentralPnt);
-
- /// Returns whether custom size of view is set
- /// \return boolean value
- bool isUseSizeOfView() const { return myIsUseSizeOfView; }
-
- /// Sets the size of default created face
- /// \param theSizeOfView value
- /// \param isUseSizeOfView state whether the size should be used
- void setSizeOfView(double theSizeOfView, bool isUseSizeOfView,
- const std::shared_ptr<GeomAPI_Pnt>& theCentralPoint = std::shared_ptr<GeomAPI_Pnt>());
-
- /// Returns True if the plane preview is already created
- bool isPlaneCreated() const {
- return myPlane.get();
- }
-
- /// Returns current state of the plane preview visibility
- bool isDisplayed() const { return myPreviewIsDisplayed; }
-
- /// Displays preview planes
- /// \param theWorkshop the application workshop
- void displaySketchPlane(ModuleBase_IWorkshop* theWorkshop);
-
- /// Nullyfies current plane preview object.
- /// Important: Before call of this function the plane has to be erased from viewer
- void clearPlanePreview();
+ inline static bool SketchAccessoryDbg()
+ {
+#ifdef SKETCH_ACCESSORY_DBG
+ return true;
+#else
+ return false;
+#endif
+ };
+
+ static bool SketchAccessoryDbg(const QString& theString);
+ static bool SketchAccessoryDbg(const char* theString);
+ static bool SketchAccessoryDbg(const char* theCSDescription, const gp_Ax3& theCS);
+ static bool SketchAccessoryDbg(const char* theCSDescription, const gp_Pnt& thePoint);
+ static bool SketchAccessoryDbg(const char* theCSDescription, const gp_Trsf& theMatrix);
+
+ enum GridSnappingMode {
+ Off,
+ SnapAnyway,
+ SnapInProximity
+ };
+
+ /*! \param theManager must not be nullptr. */
+ PartSet_PreviewSketchPlane(PartSet_SketcherMgr* theManager);
+ PartSet_PreviewSketchPlane(const PartSet_PreviewSketchPlane&) = delete;
+ PartSet_PreviewSketchPlane& operator=(const PartSet_PreviewSketchPlane&) = delete;
+ ~PartSet_PreviewSketchPlane() = default;
+
+ void savePreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const;
+ void saveRectangularGridPreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const;
+ void saveCircularGridPreferencesIntoSketchData(std::shared_ptr<ModelAPI_CompositeFeature> theSketch) const;
+
+ /*! \brief Updates CS (coordinate system), dimensions and accessories' configuration. */
+ void setCSAndSize(const gp_Ax3& theCS, double theSize);
+
+ /*! \brief Updates CS (coordinate system), dimensions and accessories' configuration.
+ Updates visibility of accessories - visibility preferences are also retrieved from theSketch data.
+ If sketch data contains unitialized grid steps, the method assigns default ones.
+ For rectangular grid default step is a fraction of corresponding dimension.
+ \returns true, on success (if theSketch is valid). */
+ bool setAllUsingSketch(std::shared_ptr<ModelAPI_CompositeFeature> theSketch);
+
+ /*! \brief Call it, after any preference of grid, except grid type, is changed using methods of this instance.
+ Updates grid configuration. Does not affect visibility of grid.
+ \returns true, if grid is successfuly configured. */
+ bool reconfigureGrid();
+
+ /*! \brief Call it, after any preference of grid is changed in theSketch data directly.
+ Updates grid configuration. Updates grid visibility - preference is also retrieved from theSketch data.
+ If sketch data contains unitialized grid steps, the method assigns default ones.
+ For rectangular grid default step is a fraction of corresponding dimension.
+ \returns true, if grid is successfuly configured. */
+ bool reconfigureGridUsingSketch(std::shared_ptr<ModelAPI_CompositeFeature> theSketch);
+
+ /*! \returns true on success. */
+ bool showAxes(bool theShow);
+ /*! \returns true on success. */
+ bool showSubstrate(bool theShow);
+ /*! \brief Changes grid type and reconfigures grid. Shows grid, if theType != SketchPlaneGridType::No.
+ \returns true on success. */
+ bool setGridType(PartSet_Tools::SketchPlaneGridType::Enum theType);
+
+ PartSet_Tools::SketchPlaneGridType::Enum getGridType() const { return myGridType; }
+
+ /*! \brief Hides all accessories. */
+ void hideAll();
+
+ /*! \brief Substrate dimensions. Substrate dimension coincides with one of the sketch face, if the latter is non-zero. */
+ std::pair<double, double> getDimensions() const;
+
+ bool isShowAxes() const { return myShowTrihedron; }
+ bool isShowSubstrate() const { return myShowSubstrate; }
+ bool isShowGrid() const { return myGridType != PartSet_Tools::SketchPlaneGridType::No; }
+
+ GridSnappingMode getGridSnappingMode() const { return mySnappingMode; };
+ void setGridSnappingMode(GridSnappingMode theMode) { mySnappingMode = theMode; };
+
+ /*! \brief Sets default steps and zero offsets. */
+ void resetRectangularGrid();
+
+ void setRectangularGridStepX(double theStepX);
+ void setRectangularGridStepY(double theStepY);
+ std::pair<double, double> getRectangularGridSteps() const { return myRectangularGridSteps; }
+
+ void setRectangularGridOffsetX(double theOffsetX);
+ void setRectangularGridOffsetY(double theOffsetY);
+ void setRectangularGridOffsetA(double theOffsetAngle);
+ std::pair<std::pair<double, double>, double> getRectangularGridOffsets() const;
+ int getRectangularGridDimOfNodeSpace() const { return myRectangularGridDimOfNodeSpace; }
+
+ /*! \brief Sets default steps and zero offsets. */
+ void resetCircularGrid();
+
+ void setCircularGridRadialStep(double theStep);
+ void setCircularGridNumOfAngularSegments(int theNum);
+ std::pair<double, int> getCircularGrid_dR_and_NAS() const;
+
+ void setCircularGridOffsetX(double theOffset);
+ void setCircularGridOffsetY(double theOffset);
+ void setCircularGridOffsetA(double theOffset);
+ std::pair<std::pair<double, double>, double> getCircularGridOffsets() const;
+ int getCircularGridDimOfNodeSpace() const { return myCircularGridDimOfNodeSpace; }
private:
- /// Create a square face by parameters
- std::shared_ptr<GeomAPI_AISObject> createPreviewPlane();
+ void configureTrihedron();
+ void initSubstrate(std::shared_ptr<GeomAPI_Face> theFace);
+
+ opencascade::handle<V3d_Viewer> getV3DViewer() const;
+ bool isValid() const;
+ void setInvalid();
+
+ /*! \returns Default size from sketch data (if > 0), or the default size from Config_PropManager (if > 0), or DEFAULT_SKETCH_SIZE. */
+ double getDefaultSize() const;
+
+ double getCircularGridRaduis(const std::pair<double, double>& theBBox2Dimensions) const;
+
+ /*! \returns Dimensions of outer rectangle, center of which is shifted from center of inner rectangle by (cX, cY);
+ outer rectangle is rotated by angle (counterclockwise is positive) relative to inner one. */
+ static std::pair<double, double> dimsOfRectangleFittingRectangle(double wInner, double hInner, double angle, double cX, double cY);
+
+public:
+ /*! \returns Default size from Config_PropManager (if > 0), or DEFAULT_SKETCH_SIZE. */
+ static double defaultSketchSize();
+
+ static const double DEFAULT_RELATIVE_STEP_INVERSE;
+ static const int DEFAULT_NUM_OF_ANGULAR_SECTIONS;
+ static const int SNAP_PROXIMITY_P; /// Distance [pixel], at which snapping to grid engages in SnapInProximity mode.
private:
- bool myPreviewIsDisplayed;
- std::shared_ptr<GeomAPI_AISObject> myPlane; //! visualized presentation
- std::shared_ptr<GeomAPI_Shape> myShape; //! current shape to be displayed
- std::shared_ptr<GeomAPI_Pnt> myViewCentralPoint; //! central point of the default view
-
- double mySizeOfView; //! size that should be used by creating a default face
- bool myIsUseSizeOfView; //! state if the size is custom or from preferences
- std::shared_ptr<GeomAPI_Pnt> myViewOrigin; //! origin point of sketch if default view is used
+ /** Is used to create default substrate, if plane size is 0 both in the sketch data and in Config_PropManager. */
+ static const double DEFAULT_SKETCH_SIZE;
+
+ const PartSet_SketcherMgr* const mySketcherMgr;
+
+ bool myValid;
+ gp_Ax3 mySketchCS;
+ std::pair<double, double> mySketchDimensions; // Width and height of sketch bounding box, aligned with sketch axes.
+ double mySketchDefaultSize;
+
+ bool myShowTrihedron;
+ opencascade::handle<AIS_PlaneTrihedron> myTrihedron; // Visualization of sketch axes and origin.
+
+ bool myShowSubstrate;
+ std::shared_ptr<GeomAPI_AISObject> mySubstrate; // Translucent substrate.
+
+ PartSet_Tools::SketchPlaneGridType::Enum myGridType;
+ Aspect_GridDrawMode myGridDrawMode;
+ GridSnappingMode mySnappingMode;
+
+ std::pair<double, double> myRectangularGridSteps;
+ std::pair<double, double> myRectangularGridTransOffset;
+ double myRectangularGridOffsetAngle;
+ int myRectangularGridDimOfNodeSpace; // Minimal dimension of space which can fit displayed grid nodes.
+
+ double myCircularGridRadialStep;
+ int myCircularGridNumOfAngularSections;
+ std::pair<double, double> myCircularGridTransOffset;
+ double myCircularGridOffsetAngle;
+ int myCircularGridDimOfNodeSpace; // Minimal dimension of space which can fit displayed grid nodes.
};
#endif
\ No newline at end of file
myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
myIsConstraintsShown[PartSet_Tools::Expressions] = false;
- mySketchPlane = new PartSet_PreviewSketchPlane();
+ mySketchPlane = new PartSet_PreviewSketchPlane(this);
registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop));
registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter());
bool aWasDragging = myIsDragging;
myIsDragging = false;
- if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) {
+ if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
return;
- }
+
// if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
- if (!myIsMouseOverViewProcessed) {
+ if (!myIsMouseOverViewProcessed)
return;
- }
ModuleBase_OperationFeature* aOp =
dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
myNoDragMoving = !myNoDragMoving;
else
myNoDragMoving = false;
+
if (myNoDragMoving)
return;
else {
+ ModuleBase_OperationFeature* aOp =
+ dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
+
+ bool isEditing = false;
+ if (aOp) {
+ isEditing = aOp->isEditOperation();
+ bool aStartNoDragOperation = !aViewer->canDragByMouse() && isEditing;
+ if (aStartNoDragOperation || myNoDragMoving) {
+ // Process edit operation without dragging
+ if (myCurrentSelection.size() > 0)
+ myNoDragMoving = !myNoDragMoving;
+ else
+ myNoDragMoving = false;
+ if (myNoDragMoving)
+ return;
+ else {
+ restoreSelection(myCurrentSelection);
+ myCurrentSelection.clear();
+ }
+ }
+ else {
+ if (isNestedSketchOperation(aOp)) {
+ // Only for sketcher operations
+ if (aWasDragging) {
+ if (myDragDone) {
+ /// the previous selection is lost by mouse release in the viewer(Select method), but
+ /// it is still stored in myCurrentSelection. So, it is possible to restore selection
+ /// It is important for drag(edit with mouse) of sketch entities.
+ restoreSelection(myCurrentSelection);
+ myCurrentSelection.clear();
+ }
+ }
+ }
+ }
+ }
restoreSelection(myCurrentSelection);
myCurrentSelection.clear();
}
ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+
if (aProcessor) {
ModuleBase_ISelection* aSelection = aWorkshop->selection();
QList<ModuleBase_ViewerPrsPtr> aPreSelected = aSelection->getHighlighted();
QString aOpId = aOp->id();
if (aOpId == "Sketch")
return;
+
QPoint aPnt(theEvent->x(), theEvent->y());
anActiveWidget = getActiveWidget();
if ((aPnt == myMousePoint) && anActiveWidget) {
XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {
+
#ifdef DRAGGING_DEBUG
QTime t;
t.start();
// presentation. These widgets correct the feature attribute according to the mouse position
ModuleBase_ModelWidget* anActiveWidget = myModule->activeWidget();
PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
- if (aProcessor)
+ if (aProcessor) {
aProcessor->mouseMoved(theWnd, theEvent);
+ }
if (!myIsMouseOverViewProcessed) {
myIsMouseOverViewProcessed = true;
// mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
// deselected). This flag should be restored in the slot, processed the mouse release signal.
ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
- if (!aCurrentOperation)
+ if (!aCurrentOperation) {
return;
- if (isSketchOperation(aCurrentOperation))
+ }
+ if (isSketchOperation(aCurrentOperation)) {
return; // No edit operation activated
+ }
#ifdef DRAGGING_DEBUG
QTime t;
}
}
}
+
// the modified state of the current operation should be updated if there are features, which
// were changed here
if (isModified) {
// Display all sketcher sub-Objects
myCurrentSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFOperation->feature());
- double aSizeOfView = 0;
- std::shared_ptr<GeomAPI_Pnt> aCentralPoint;
- // Reset size of view from previous launches
- mySketchPlane->setSizeOfView(aSizeOfView, false, aCentralPoint);
- if (aFOperation->isEditOperation() &&
- mySketchPlane->getDefaultSizeOfView(myCurrentSketch, aSizeOfView, aCentralPoint)) {
- mySketchPlane->setSizeOfView(aSizeOfView, true, aCentralPoint);
- }
+ if (aFOperation->isEditOperation())
+ mySketchPlane->setAllUsingSketch(myCurrentSketch);
- mySketchPlane->createSketchPlane(myCurrentSketch, myModule->workshop());
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
// Hide sketcher result
XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
// The sketch was aborted
myCurrentSketch = CompositeFeaturePtr();
- mySketchPlane->eraseSketchPlane(myModule->workshop());
+ mySketchPlane->hideAll();
// Erase all sketcher objects
QObjectPtrList aObjects = aDisplayer->displayedObjects();
myCurrentSketch->setDisplayed(true);
myCurrentSketch = CompositeFeaturePtr();
- mySketchPlane->eraseSketchPlane(myModule->workshop());
+ mySketchPlane->hideAll();
Events_Loop::loop()->flush(aDispEvent);
}
std::vector<int> colorOfObject(const ObjectPtr& theObject,
const FeaturePtr& aFeature, bool isConstruction) const;
+ friend class PartSet_PreviewSketchPlane;
+
private:
PartSet_Module* myModule;
PartSet_PreviewSketchPlane* mySketchPlane; // display/erase sketch plane on start/stop sketch
#include <ModelAPI_Data.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Session.h>
#include <V3d_View.hxx>
#include <gp_Pln.hxx>
+#include <gp_Vec.hxx>
+#include <gp_Dir.hxx>
#include <gp_Circ.hxx>
#include <ProjLib.hxx>
#include <ElSLib.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
+#include <TopoDS_Face.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <AIS_InteractiveObject.hxx>
anOrigin->reset();
}
+std::pair<bool, gp_Ax3> PartSet_Tools::getWorldCSAt(const GeomAPI_Face& theFace, double U, double V)
+{
+ auto res = std::pair<bool, gp_Ax3>(false, gp_Ax3());
+ try {
+ const TopoDS_Face& face = theFace.impl<TopoDS_Face>();
+ if (face.IsNull())
+ return res;
+
+ const opencascade::handle<Geom_Surface> surface = BRep_Tool::Surface(face);
+ if (surface.IsNull())
+ return res;
+
+ gp_Pnt origin;
+ gp_Vec dirX;
+ gp_Vec dirY;
+ surface->D1(U, V, origin, dirX, dirY);
+ const gp_Vec normal = dirX.Crossed(dirY);
+
+ res.second = gp_Ax3(origin, gp_Dir(normal), gp_Dir(dirX));
+ res.first = true;
+ return res;
+ }
+ catch (...) {
+ return res;
+ }
+}
+
+std::pair<bool, gp_Pnt> PartSet_Tools::getWorldPointByUV(const GeomAPI_Face& theFace, double U, double V)
+{
+ auto res = std::pair<bool, gp_Pnt>(false, gp_Pnt());
+ try {
+ const TopoDS_Face& face = theFace.impl<TopoDS_Face>();
+ if (face.IsNull())
+ return res;
+
+ const opencascade::handle<Geom_Surface> surface = BRep_Tool::Surface(face);
+ if (surface.IsNull())
+ return res;
+
+ res.second = surface->Value(U, V);
+ res.first = true;
+ return res;
+ }
+ catch (...) {
+ return res;
+ }
+}
+
+std::pair<bool, Bnd_Box> PartSet_Tools::getBBoxAtCS(const GeomAPI_Shape& theShape, const gp_Ax3 theCS)
+{
+ auto res = std::pair<bool, Bnd_Box>(false, Bnd_Box());
+
+ { // Get BBox if theShape is GeomAPI_Pln, which has linear dependency of X and Y on U and V.
+ const auto face = theShape.face();
+ if (face) {
+ const auto plane = face->getPlane();
+ if (plane) {
+ try {
+ double UMax, UMin, VMax, VMin = 0;
+ face->optimalBounds(UMin, UMax, VMin, VMax);
+ std::pair<double, double> UVPairs[4];
+ UVPairs[0] = std::pair<double, double>(UMin, VMin);
+ UVPairs[1] = std::pair<double, double>(UMax, VMin);
+ UVPairs[2] = std::pair<double, double>(UMin, VMax);
+ UVPairs[3] = std::pair<double, double>(UMax, VMax);
+
+ gp_Pnt points[4];
+ bool success = true;
+ for (int idx = 0; idx < 4; idx++) {
+ std::tie(success, points[idx]) = getWorldPointByUV(*face, UVPairs[idx].first, UVPairs[idx].second);
+ if (!success)
+ return res;
+ }
+
+ gp_Trsf trsf;
+ trsf.SetTransformation(theCS);
+ for (int idx = 0; idx < 4; idx++) {
+ res.second.Add(points[idx].Transformed(trsf));
+ }
+ res.first = true;
+ return res;
+ }
+ catch(...) {
+ return res;
+ }
+ } // If Pln.
+ } // If Face.
+ } // If theShape is GeomAPI_Pln.
+
+ { // TODO Fill aligned (oriented) bounding box instead of tranforming unaligned one.
+ double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax = 0;
+ const bool success = theShape.computeSize(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+ if (!success)
+ return res;
+
+ res.second.Update(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
+
+ gp_Trsf trsf;
+ trsf.SetTransformation(theCS);
+ res.second = res.second.Transformed(trsf);
+
+ return res;
+ }
+
+ return res;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneDefaultSize(CompositeFeaturePtr theSketch)
+{
+ auto aSize = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::DEFAULT_SIZE_ID())
+ );
+
+ if (!aSize) {
+ aSize = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::DEFAULT_SIZE_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aSize->setIsArgument(false);
+ aSize->setValue(0);
+ }
+
+ return aSize;
+}
+
+std::shared_ptr<ModelAPI_AttributeBoolean> PartSet_Tools::sketchPlaneAxesEnabled(CompositeFeaturePtr theSketch)
+{
+ auto isEnabled = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::AXES_ENABLED_ID())
+ );
+
+ if (!isEnabled) {
+ isEnabled = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::AXES_ENABLED_ID(),
+ ModelAPI_AttributeBoolean::typeId()
+ ));
+
+ isEnabled->setIsArgument(false);
+ isEnabled->setValue(true);
+ }
+
+ return isEnabled;
+}
+
+std::shared_ptr<ModelAPI_AttributeBoolean> PartSet_Tools::sketchPlaneSubstrateEnabled(CompositeFeaturePtr theSketch)
+{
+ auto isEnabled = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::SUBSTRATE_ENABLED_ID())
+ );
+
+ if (!isEnabled) {
+ isEnabled = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::SUBSTRATE_ENABLED_ID(),
+ ModelAPI_AttributeBoolean::typeId()
+ ));
+
+ isEnabled->setIsArgument(false);
+ isEnabled->setValue(true);
+ }
+
+ return isEnabled;
+}
+
+std::shared_ptr<ModelAPI_AttributeString> PartSet_Tools::sketchPlaneGridType(CompositeFeaturePtr theSketch)
+{
+ auto gridType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CONSTRUCTION_GRID_TYPE_ID())
+ );
+
+ if (!gridType) {
+ gridType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CONSTRUCTION_GRID_TYPE_ID(),
+ ModelAPI_AttributeString::typeId()
+ ));
+
+ gridType->setIsArgument(false);
+ gridType->setValue(PartSet_Tools::SketchPlaneGridType::toString(PartSet_Tools::SketchPlaneGridType::No));
+ }
+
+ return gridType;
+}
+
+std::string PartSet_Tools::SketchPlaneGridType::toString(Enum iType)
+{
+ if (iType >= SketchPlaneGridType::STRINGS.size())
+ return SketchPlaneGridType::STRINGS[0];
+
+ return SketchPlaneGridType::STRINGS[iType];
+}
+
+PartSet_Tools::SketchPlaneGridType::Enum PartSet_Tools::SketchPlaneGridType::fromString(const std::string& iTypeString)
+{
+ for (int i = 0; i < SketchPlaneGridType::STRINGS.size(); i++) {
+ if (SketchPlaneGridType::STRINGS[i] == iTypeString) {
+ return SketchPlaneGridType::Enum(i);
+ }
+ }
+ return SketchPlaneGridType::Enum::No;
+}
+
+const std::array<std::string, 3> PartSet_Tools::SketchPlaneGridType::STRINGS = {"", "Rectangular", "Circular"};
+
+void PartSet_Tools::setSketchPlaneGridType(CompositeFeaturePtr theSketch, PartSet_Tools::SketchPlaneGridType::Enum theType)
+{
+ PartSet_Tools::sketchPlaneGridType(theSketch)->setValue(PartSet_Tools::SketchPlaneGridType::toString(theType));
+}
+
+PartSet_Tools::SketchPlaneGridType::Enum PartSet_Tools::getSketchPlaneGridType(CompositeFeaturePtr theSketch)
+{
+ return PartSet_Tools::SketchPlaneGridType::fromString(PartSet_Tools::sketchPlaneGridType(theSketch)->value());
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneRectangularGridStepX(CompositeFeaturePtr theSketch) {
+ auto aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_STEP_X_ID())
+ );
+
+ if (!aStep) {
+ aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_STEP_X_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aStep->setIsArgument(false);
+ aStep->setValue(-1);
+ }
+
+ return aStep;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneRectangularGridStepY(CompositeFeaturePtr theSketch) {
+ auto aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_STEP_Y_ID())
+ );
+
+ if (!aStep) {
+ aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_STEP_Y_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aStep->setIsArgument(false);
+ aStep->setValue(-1);
+ }
+
+ return aStep;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneRectangularGridOffsetAngle(CompositeFeaturePtr theSketch)
+{
+ auto aAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID())
+ );
+
+ if (!aAngle) {
+ aAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aAngle->setIsArgument(false);
+ aAngle->setValue(0);
+ }
+
+ return aAngle;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneRectangularGridOffsetX(CompositeFeaturePtr theSketch) {
+ auto aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_X_ID())
+ );
+
+ if (!aShift) {
+ aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_X_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aShift->setIsArgument(false);
+ aShift->setValue(0);
+ }
+
+ return aShift;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneRectangularGridOffsetY(CompositeFeaturePtr theSketch) {
+ auto aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_Y_ID())
+ );
+
+ if (!aShift) {
+ aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::RECTANGULAR_CONSTRUCTION_GRID_OFFSET_Y_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aShift->setIsArgument(false);
+ aShift->setValue(0);
+ }
+
+ return aShift;
+}
+
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneCircularGridStepR(CompositeFeaturePtr theSketch)
+{
+ auto aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_STEP_R_ID())
+ );
+
+ if (!aStep) {
+ aStep = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_STEP_R_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aStep->setIsArgument(false);
+ aStep->setValue(-1);
+ }
+
+ return aStep;
+}
+
+std::shared_ptr<ModelAPI_AttributeInteger> PartSet_Tools::sketchPlaneCircularGridNumOfAngSegments(CompositeFeaturePtr theSketch)
+{
+ auto num = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_NUM_OF_ANG_SEGMENTS_ID())
+ );
+
+ if (!num) {
+ num = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_NUM_OF_ANG_SEGMENTS_ID(),
+ ModelAPI_AttributeInteger::typeId()
+ ));
+
+ num->setIsArgument(false);
+ num->setValue(-1);
+ }
+
+ return num;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneCircularGridOffsetAngle(CompositeFeaturePtr theSketch)
+{
+ auto aAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID())
+ );
+
+ if (!aAngle) {
+ aAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aAngle->setIsArgument(false);
+ aAngle->setValue(0);
+ }
+
+ return aAngle;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneCircularGridOffsetX(CompositeFeaturePtr theSketch) {
+ auto aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_X_ID())
+ );
+
+ if (!aShift) {
+ aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_X_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aShift->setIsArgument(false);
+ aShift->setValue(0);
+ }
+
+ return aShift;
+}
+
+std::shared_ptr<ModelAPI_AttributeDouble> PartSet_Tools::sketchPlaneCircularGridOffsetY(CompositeFeaturePtr theSketch) {
+ auto aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ theSketch->data()->attribute(SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_Y_ID())
+ );
+
+ if (!aShift) {
+ aShift = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theSketch->data()->addAttribute(
+ SketchPlugin_Sketch::CIRCULAR_CONSTRUCTION_GRID_OFFSET_Y_ID(),
+ ModelAPI_AttributeDouble::typeId()
+ ));
+
+ aShift->setIsArgument(false);
+ aShift->setValue(0);
+ }
+
+ return aShift;
+}
+
std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(std::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
CompositeFeaturePtr theSketch)
{
#include "PartSet.h"
#include <gp_Pnt.hxx>
+#include <gp_Ax3.hxx>
+#include <Bnd_Box.hxx>
#include <QPoint>
#include <QList>
#include <TopoDS_Shape.hxx>
#include <memory>
+#include <string>
+#include <array>
+#include <utility>
class V3d_View;
class ModuleBase_IViewWindow;
class ModuleBase_IWorkshop;
class GeomDataAPI_Point2D;
class GeomAPI_Shape;
+class GeomAPI_Face;
class GeomAPI_Pln;
class GeomAPI_Pnt2d;
class GeomAPI_Pnt;
/// \return API object of geom plane
static void nullifySketchPlane(CompositeFeaturePtr theSketch);
+ /*! \returns Basis of theFace' surface, defined in world CS, at point, which corresponds to point (U, V) in parametric space. */
+ static std::pair<bool, gp_Ax3> getWorldCSAt(const GeomAPI_Face& theFace, double U, double V);
+
+ /*! \returns Point, defined in world CS, which corresponds to point (U, V) in parametric space. */
+ static std::pair<bool, gp_Pnt> getWorldPointByUV(const GeomAPI_Face& theFace, double U, double V);
+
+ /*! \brief Fills bounding box, which is aligned according to theCS.
+ Returns the smallest possible box only for GeomAPI_Plns, for other shapes
+ returns unaligned transformed bounding box (so its dimensions are bigger than the smallest)!
+ \returns true on success. */
+ static std::pair<bool, Bnd_Box> getBBoxAtCS(const GeomAPI_Shape& theShape, const gp_Ax3 theCS);
+
+ /// @returns 0, if the plane was initialized on a feature. Result is never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneDefaultSize(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeBoolean> sketchPlaneAxesEnabled(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeBoolean> sketchPlaneSubstrateEnabled(CompositeFeaturePtr theSketch);
+
+ /// @returns empty string, if construction grid is disabled. Result is never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeString> sketchPlaneGridType(CompositeFeaturePtr theSketch);
+
+ class SketchPlaneGridType {
+ public:
+ typedef enum {
+ No,
+ Rectangular,
+ Circular
+ } Enum;
+
+ static std::string toString(Enum iType);
+ static Enum fromString(const std::string& iTypeString);
+
+ private:
+ static const std::array<std::string, 3> STRINGS;
+ };
+
+ static void setSketchPlaneGridType(CompositeFeaturePtr theSketch, SketchPlaneGridType::Enum theType);
+ static SketchPlaneGridType::Enum getSketchPlaneGridType(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneRectangularGridStepX(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneRectangularGridStepY(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneRectangularGridOffsetAngle(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneRectangularGridOffsetX(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneRectangularGridOffsetY(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneCircularGridStepR(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeInteger> sketchPlaneCircularGridNumOfAngSegments(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneCircularGridOffsetAngle(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneCircularGridOffsetX(CompositeFeaturePtr theSketch);
+
+ /// @returns never nullptr.
+ static std::shared_ptr<ModelAPI_AttributeDouble> sketchPlaneCircularGridOffsetY(CompositeFeaturePtr theSketch);
+
+
/// Create a point 3D on a basis of point 2D and sketch feature
/// \param thePoint2D a point on a sketch
/// \param theSketch a sketch feature
myScrollArea->setWidget(aContainer);
- myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop);
+ myWidgetValidator.reset(new ModuleBase_WidgetValidator(this, myWorkshop));
myExternalObjectMgr = new PartSet_ExternalObjectsMgr(theData->getProperty("use_external"),
theData->getProperty("can_create_external"), true);
}
if (myFinished || isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditActive())
return;
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
+ double aX = 0, aY = 0; // Coords at sketch plane.
+ bool success = convertPointToLocal(
+ myWorkshop,
+ mySketch,
+ theWindow,
+ theEvent->pos(),
+ aX, aY,
+ true
+ );
+
+ if (!success)
+ return;
- double aX = 0, aY = 0;
- PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, aY);
if (myState != ModifiedInViewer)
storeCurentValue();
// we need to block the value state change
const Config_WidgetAPI* theData)
: PartSet_WidgetPoint2D(theParent, theWorkshop, theData)
{
- myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop);
+ myWidgetValidator.reset(new ModuleBase_WidgetValidator(this, myWorkshop));
}
bool PartSet_WidgetPoint2DFlyout::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
#include <QMouseEvent>
#include <QApplication>
+#include <Aspect_Grid.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRep_Tool.hxx>
aLayout->addWidget(myGroupBox);
setLayout(aLayout);
- myWidgetValidator = new ModuleBase_WidgetValidator(this, myWorkshop);
+ myWidgetValidator.reset(new ModuleBase_WidgetValidator(this, myWorkshop));
myExternalObjectMgr = new PartSet_ExternalObjectsMgr(theData->getProperty("use_external"),
theData->getProperty("can_create_external"), true);
}
return;
ModuleBase_ISelection* aSelection = myWorkshop->selection();
- Handle(V3d_View) aView = theWindow->v3dView();
QList<ModuleBase_ViewerPrsPtr> aList = aSelection->getSelected(ModuleBase_ISelection::Viewer);
ModuleBase_ViewerPrsPtr aFirstValue =
GeomShapePtr aShape = aFirstValue->shape();
if (aShape.get() && aShape->shapeType() == GeomAPI_Shape::VERTEX) {
const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
+ Handle(V3d_View) aView = theWindow->v3dView();
GeomPnt2dPtr aPnt = PartSet_Tools::getPnt2d(aView, aTDShape, mySketch);
aX = aPnt->x();
aY = aPnt->y();
}
}
if (!aHasPoint) {
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
- PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY);
+ bool success = convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, false);
+ if (!success)
+ return;
}
processSelection(aFirstValue, aX, aY);
}
}
}
else {
+
if (!isFeatureContainsPoint(myFeature, theX, theY)) {
double aX = 0, aY = 0;
bool anOrphanPoint = isOrphanPoint(aSelectedFeature, mySketch, aX, aY);
if (isEditingMode() || aModule->sketchReentranceMgr()->isInternalEditActive())
return;
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
+ double aX = 0, aY = 0; // Coords at sketch plane.
+ bool success = convertPointToLocal(myWorkshop, mySketch, theWindow, theEvent->pos(), aX, aY, true, true);
+ if (!success)
+ return;
- double aX = 0, aY = 0;
- PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, aY);
if (myState != ModifiedInViewer)
storeCurentValue();
// we need to block the value state change
/// Create a coincidence constraint between the attribute and the parameter object
/// \theObject a result object
- /// \return true if succed
+ /// \return true if succeed
bool setConstraintToObject(const ObjectPtr& theObject);
/// Process selected value
/// \param theY Y coordinate of clicked point
void processSelection(const ModuleBase_ViewerPrsPtr& theValue, double theX, double theY);
-
public:
/// Returns if the feature is an orphan point, circle or an arc. Returns true if it
/// has no a coincident to other lines. It processes point, circle and arc features
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_ResultConstruction.h>
void PartSet_WidgetSketchCreator::activateSelectionControl()
{
- // reset previously set size of view needed on restart extrusion after Sketch
- if (myModule->sketchMgr()->previewSketchPlane()->isUseSizeOfView())
- myModule->sketchMgr()->previewSketchPlane()->setSizeOfView(0, false);
-
// we need to call activate here as the widget has no focus accepted controls
// if these controls are added here, activate will happens automatically after focusIn()
XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
}
aSketchStarted = true;
// Set View size if a plane is selected
- if (myPreviewPlanes->isPreviewDisplayed() &&
- myPreviewPlanes->isPreviewShape(aValue->shape())) {
+ if (myPreviewPlanes->isPreviewDisplayed() && myPreviewPlanes->isPreviewShape(aValue->shape())) {
// set default plane size
- bool isSetSizeOfView = false;
- double aSizeOfView = 0;
- QString aSizeOfViewStr = mySizeOfView->text();
- if (!aSizeOfViewStr.isEmpty()) {
- aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
- if (isSetSizeOfView && aSizeOfView <= 0) {
- isSetSizeOfView = false;
- }
- }
- if (isSetSizeOfView)
- myModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, true);
+ bool isValidSizeInput = true;
+ double aSizeOfView = mySizeOfView->text().toDouble(&isValidSizeInput);
+ if (aSizeOfView <= 0 || !isValidSizeInput)
+ aSizeOfView = PartSet_PreviewSketchPlane::defaultSketchSize();
+
+ const auto sketch = myModule->sketchMgr()->activeSketch();
+ if (sketch)
+ PartSet_Tools::sketchPlaneDefaultSize(sketch)->setValue(aSizeOfView);
+
+ myModule->sketchMgr()->previewSketchPlane()->setAllUsingSketch(sketch);
}
// manually deactivation because the widget was not activated as has no focus acceptin controls
deactivate();
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeBoolean.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Events.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QCheckBox>
+#include <QComboBox>
#include <QGroupBox>
#include <QPushButton>
#include <QLineEdit>
#include <QDoubleValidator>
+#include <QDoubleSpinBox>
#include <QDialog>
#include <QTimer>
+#include <QToolTip>
+#include <QRect>
+
+#include <limits>
+#include <iostream>
+#include <cmath>
+#include <utility>
+
#ifdef WIN32
#pragma warning(disable : 4456) // for nested foreach
#define DBL_MAX 1.7976931348623158e+308
#endif
+
PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
- ModuleBase_IWorkshop* theWorkshop,
- const Config_WidgetAPI* theData,
- const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints)
-: ModuleBase_WidgetValidated(theParent, theWorkshop, theData), myOpenTransaction(false),
-myIsSelection(false)
+ ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData,
+ const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints
+) : ModuleBase_WidgetValidated(theParent, theWorkshop, theData),
+ mySketchDataIsModified(false), myOpenTransaction(false), myIsSelection(false)
{
QVBoxLayout* aLayout = new QVBoxLayout(this);
ModuleBase_Tools::zeroMargins(aLayout);
myStackWidget->addWidget(aFirstWgt);
- // Define widget for sketch manmagement
+ // Define widget for sketch management
QWidget* aSecondWgt = new QWidget(this);
aLayout = new QVBoxLayout(aSecondWgt);
ModuleBase_Tools::zeroMargins(aLayout);
- QGroupBox* aViewBox = new QGroupBox(tr("Sketcher plane"), this);
- QGridLayout* aViewLayout = new QGridLayout(aViewBox);
+ { // Sketch view controls.
+ mySketchViewGroupBox = new QGroupBox(tr("Sketcher plane"), this);
+ QGridLayout* aViewLayout = new QGridLayout(mySketchViewGroupBox);
- myViewInverted = new QCheckBox(tr("Reversed"), aViewBox);
- aViewLayout->addWidget(myViewInverted, 0, 0);
+ PartSet_Module* const aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ PartSet_PreviewSketchPlane* const aPreviewPlane = aModule->sketchMgr()->previewSketchPlane();
+ const CompositeFeaturePtr sketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
- // Sketch plane visibility
- myViewVisible = new QCheckBox(tr("Visible"), aViewBox);
- PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
- PartSet_PreviewSketchPlane* aPreviewPlane = aModule->sketchMgr()->previewSketchPlane();
- if (aPreviewPlane->isPlaneCreated())
- // init with current state
- myViewVisible->setChecked(aPreviewPlane->isDisplayed());
- else
- // true by default (at start of sketch creation)
- myViewVisible->setChecked(true);
+ { // Reverse flag.
+ myViewInverted = new QCheckBox(tr("Reversed"), mySketchViewGroupBox);
+ aViewLayout->addWidget(myViewInverted, 0, 0);
+ }
+
+ { // Sketch axes visibility.
+ myAxesVisibleCheckBox = new QCheckBox(tr("Axes"), mySketchViewGroupBox);
+ myAxesVisibleCheckBox->setChecked(sketch ? PartSet_Tools::sketchPlaneAxesEnabled(sketch)->value() : false);
+
+ aViewLayout->addWidget(myAxesVisibleCheckBox, 0, 1);
+ connect(myAxesVisibleCheckBox, SIGNAL(toggled(bool)), this, SLOT(onShowAxes(bool)));
+ }
- aViewLayout->addWidget(myViewVisible, 0, 1, Qt::AlignRight);
- connect(myViewVisible, SIGNAL(toggled(bool)), this, SLOT(onShowViewPlane(bool)));
+ { // Sketch substrate-plane visibility.
+ mySubstrateVisibleCheckBox = new QCheckBox(tr("Substrate"), mySketchViewGroupBox);
+ mySubstrateVisibleCheckBox->setChecked(sketch ? PartSet_Tools::sketchPlaneSubstrateEnabled(sketch)->value() : false);
- QPushButton* aSetViewBtn =
- new QPushButton(QIcon(":icons/plane_view.png"), tr("Set plane view"), aViewBox);
- connect(aSetViewBtn, SIGNAL(clicked(bool)), this, SLOT(onSetPlaneView()));
- aViewLayout->addWidget(aSetViewBtn, 1, 0, 1, 2);
+ aViewLayout->addWidget(mySubstrateVisibleCheckBox, 0, 2);
+ connect(mySubstrateVisibleCheckBox, SIGNAL(toggled(bool)), this, SLOT(onShowSubstrate(bool)));
+ }
+
+ {
+ QPushButton* aSetViewBtn = new QPushButton(QIcon(":icons/plane_view.png"), tr("Set plane view"), mySketchViewGroupBox);
+ connect(aSetViewBtn, SIGNAL(clicked(bool)), this, SLOT(onSetPlaneView()));
+ aViewLayout->addWidget(aSetViewBtn, 1, 0, 1, 3);
+ }
+
+ { // Sketch construction grid.
+ QGroupBox* aCGBox = new QGroupBox(tr("Construction grid"), this);
+ QGridLayout* aCGLayout = new QGridLayout(aCGBox);
+
+ {
+ myGridTypeComboBox = new QComboBox(aCGBox);
+ myGridTypeComboBox->addItem(tr("Disabled"), PartSet_Tools::SketchPlaneGridType::No);
+ myGridTypeComboBox->addItem(tr("Rectangular"), PartSet_Tools::SketchPlaneGridType::Rectangular);
+ myGridTypeComboBox->addItem(tr("Circular"), PartSet_Tools::SketchPlaneGridType::Circular);
+ myGridTypeComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myGridTypeComboBox->setCurrentIndex(0);
+ if (sketch) {
+ const int idx = myGridTypeComboBox->findData(PartSet_Tools::getSketchPlaneGridType(sketch));
+ if (idx != -1)
+ myGridTypeComboBox->setCurrentIndex(idx);
+ }
+
+ aCGLayout->addWidget(myGridTypeComboBox, 0, 0);
+ connect(myGridTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onGridTypeChanged(int)));
+ }
+
+ {
+ myGridSnappingModeComboBox = new QComboBox(aCGBox);
+ myGridSnappingModeComboBox->addItem(tr("Don't snap"), PartSet_PreviewSketchPlane::GridSnappingMode::Off);
+ myGridSnappingModeComboBox->addItem(tr("Snap anyway"), PartSet_PreviewSketchPlane::GridSnappingMode::SnapAnyway);
+ myGridSnappingModeComboBox->addItem(tr("Snap in proximity"), PartSet_PreviewSketchPlane::GridSnappingMode::SnapInProximity);
+ myGridSnappingModeComboBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myGridSnappingModeComboBox->setCurrentIndex(int(aPreviewPlane->getGridSnappingMode()));
+
+ aCGLayout->addWidget(myGridSnappingModeComboBox, 0, 1);
+ connect(myGridSnappingModeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onGridSnappingModeChanged(int)));
+ }
+
+ {
+ const auto widgetGrouper = new QWidget(aCGBox);
+ aCGLayout->addWidget(widgetGrouper, 1, 0, 1, 2);
+ const auto grouperLayout = new QVBoxLayout(widgetGrouper);
+
+ const auto currentGridType = myGridTypeComboBox->currentData();
+
+ myWidgetRectangularGrid = new PartSet_WidgetSketchRectangularGrid(aCGBox, this);
+ grouperLayout->addWidget(myWidgetRectangularGrid);
+ myWidgetRectangularGrid->setVisible(currentGridType == PartSet_Tools::SketchPlaneGridType::Rectangular);
+
+ myWidgetCircularGrid = new PartSet_WidgetSketchCircularGrid(aCGBox, this);
+ grouperLayout->addWidget(myWidgetCircularGrid);
+ myWidgetCircularGrid->setVisible(currentGridType == PartSet_Tools::SketchPlaneGridType::Circular);
+ }
+
+ aViewLayout->addWidget(aCGBox, 2, 0, 1, 3);
+ } // Sketch construction grid.
+
+ aLayout->addWidget(mySketchViewGroupBox);
+
+ aPreviewPlane->setAllUsingSketch(sketch);
+ reconfigureSketchViewWidgets();
+ } // View box.
- aLayout->addWidget(aViewBox);
QMap<PartSet_Tools::ConstraintVisibleState, QString> aStates;
aStates[PartSet_Tools::Geometrical] = tr("Show geometrical constraints");
myPreviewPlanes = new PartSet_PreviewPlanes();
}
-PartSet_WidgetSketchLabel::~PartSet_WidgetSketchLabel()
-{
+void PartSet_WidgetSketchLabel::setFeature(
+ const FeaturePtr& theFeature,
+ const bool theToStoreValue,
+ const bool isUpdateFlushed
+) {
+ ModuleBase_WidgetValidated::setFeature(theFeature, theToStoreValue, isUpdateFlushed);
+ PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ const CompositeFeaturePtr sketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ aModule->sketchMgr()->previewSketchPlane()->setAllUsingSketch(sketch);
+ reconfigureSketchViewWidgets();
}
bool PartSet_WidgetSketchLabel::setSelection(QList<ModuleBase_ViewerPrsPtr>& theValues,
// 1. hide main planes if they have been displayed and display sketch preview plane
myPreviewPlanes->erasePreviewPlanes(myWorkshop);
- QString aSizeOfViewStr = mySizeOfView->text();
- bool isSetSizeOfView = false;
- double aSizeOfView = 0;
- if (!aSizeOfViewStr.isEmpty()) {
- aSizeOfView = aSizeOfViewStr.toDouble(&isSetSizeOfView);
- if (isSetSizeOfView && aSizeOfView <= 0) {
- isSetSizeOfView = false;
- }
- }
+ bool isValidSizeInput = true;
+ double aSizeOfView = mySizeOfView->text().toDouble(&isValidSizeInput);
+ if (aSizeOfView <= 0 || !isValidSizeInput)
+ aSizeOfView = PartSet_PreviewSketchPlane::defaultSketchSize();
+
PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
if (aModule) {
- CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
- aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, isSetSizeOfView);
- if (myViewVisible->isChecked())
- aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
- else
- aModule->sketchMgr()->previewSketchPlane()->clearPlanePreview();
+ CompositeFeaturePtr sketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ PartSet_Tools::sketchPlaneDefaultSize(sketch)->setValue(aSizeOfView);
+ aModule->sketchMgr()->previewSketchPlane()->setAllUsingSketch(sketch);
}
+ reconfigureSketchViewWidgets();
+
// 2. if the planes were displayed, change the view projection
std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
if (aRotate) {
myWorkshop->viewer()->setViewProjection(aXYZ.X(), aXYZ.Y(), aXYZ.Z(), aTwist);
}
- if (isSetSizeOfView && aSizeOfView > 0) {
- Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
- if (!aView3d.IsNull()) {
- Bnd_Box aBndBox;
- double aHalfSize = aSizeOfView/2.0;
- aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
- aView3d->FitAll(aBndBox, 0.01, false);
- }
+
+ Handle(V3d_View) aView3d = myWorkshop->viewer()->activeView();
+ if (!aView3d.IsNull()) {
+ Bnd_Box aBndBox;
+ double aHalfSize = aSizeOfView/2.0;
+ aBndBox.Update(-aHalfSize, -aHalfSize, -aHalfSize, aHalfSize, aHalfSize, aHalfSize);
+ aView3d->FitAll(aBndBox, 0.01, false);
}
+
if (myOpenTransaction) {
SessionPtr aMgr = ModelAPI_Session::get();
aMgr->finishOperation();
}
+void PartSet_WidgetSketchLabel::onShowDOF()
+{
+ CompositeFeaturePtr aCompFeature =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ if (aCompFeature.get()) {
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS);
+ ModelAPI_EventCreator::get()->sendUpdated(aCompFeature, anEvent);
+ Events_Loop::loop()->flush(anEvent);
+
+ // Transfer focus to the current viewport for correct processing of a key event
+ QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
+ if (aViewPort)
+ aViewPort->setFocus();
+ }
+}
+
+
void PartSet_WidgetSketchLabel::onShowPanel()
{
//if (mySizeOfViewWidget->isVisible()) {
}
}
+void PartSet_WidgetSketchLabel::onShowAxes(bool toShow)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneAxesEnabled(sketch)->setValue(toShow);
+ mySketchDataIsModified = true;
+ }
+
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ PartSet_PreviewSketchPlane* const previewPlane = module->sketchMgr()->previewSketchPlane();
+ previewPlane->showAxes(toShow);
+ myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchLabel::onShowSubstrate(bool toShow)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneSubstrateEnabled(sketch)->setValue(toShow);
+ mySketchDataIsModified = true;
+ }
+
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ PartSet_PreviewSketchPlane* const previewPlane = module->sketchMgr()->previewSketchPlane();
+ previewPlane->showSubstrate(toShow);
+ myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchLabel::onGridTypeChanged(int theComboBoxIdx) {
+ (void)theComboBoxIdx;
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ const auto previewPlane = module->sketchMgr()->previewSketchPlane();
+ const auto gridType = PartSet_Tools::SketchPlaneGridType::Enum(myGridTypeComboBox->currentData().toInt());
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(feature());
+ if (sketch) {
+ PartSet_Tools::setSketchPlaneGridType(sketch, gridType);
+ mySketchDataIsModified = true;
+ }
+
+ previewPlane->setGridType(gridType);
+ myGridSnappingModeComboBox->setEnabled(gridType != PartSet_Tools::SketchPlaneGridType::No);
+ myWidgetRectangularGrid->setVisible(gridType == PartSet_Tools::SketchPlaneGridType::Rectangular);
+ myWidgetCircularGrid->setVisible(gridType == PartSet_Tools::SketchPlaneGridType::Circular);
+ myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchLabel::onGridSnappingModeChanged(int theModeIdx) {
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ PartSet_PreviewSketchPlane* const previewPlane = module->sketchMgr()->previewSketchPlane();
+ previewPlane->setGridSnappingMode(static_cast<PartSet_PreviewSketchPlane::GridSnappingMode>(theModeIdx));
+}
+
+void PartSet_WidgetSketchLabel::reconfigureSketchViewWidgets()
+{
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ if (module) {
+ const PartSet_PreviewSketchPlane* const previewPlane = module->sketchMgr()->previewSketchPlane();
+
+ myAxesVisibleCheckBox->setChecked(previewPlane->isShowAxes());
+ mySubstrateVisibleCheckBox->setChecked(previewPlane->isShowSubstrate());
+
+ const auto gridType = previewPlane->getGridType();
+ const int gridTypeIdx = myGridTypeComboBox->findData(gridType);
+ myGridTypeComboBox->setCurrentIndex(gridTypeIdx != -1 ? gridTypeIdx : 0);
+ myWidgetRectangularGrid->setVisible(gridType == PartSet_Tools::SketchPlaneGridType::Rectangular);
+ myWidgetRectangularGrid->recongifure();
+ myWidgetCircularGrid->setVisible(gridType == PartSet_Tools::SketchPlaneGridType::Circular);
+ myWidgetCircularGrid->recongifure();
+
+ myGridSnappingModeComboBox->setEnabled(gridType != PartSet_Tools::SketchPlaneGridType::No);
+ myGridSnappingModeComboBox->setCurrentIndex(int(previewPlane->getGridSnappingMode()));
+
+ mySketchViewGroupBox->setEnabled(true);
+ }
+ else {
+ mySketchViewGroupBox->setEnabled(false);
+
+ myAxesVisibleCheckBox->setChecked(false);
+ mySubstrateVisibleCheckBox->setChecked(false);
+
+ myGridTypeComboBox->setCurrentIndex(0);
+ myWidgetRectangularGrid->setVisible(false);
+ myWidgetRectangularGrid->recongifure();
+ myWidgetCircularGrid->setVisible(false);
+ myWidgetCircularGrid->recongifure();
+
+ myGridSnappingModeComboBox->setEnabled(false);
+ }
+
+ mySketchDataIsModified = false;
+ myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchLabel::saveSketchViewPreferenceToSkethData()
+{
+ const auto module = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ if (!module)
+ return;
+
+ const PartSet_PreviewSketchPlane* const previewPlane = module->sketchMgr()->previewSketchPlane();
+ const auto sketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ previewPlane->savePreferencesIntoSketchData(sketch);
+ mySketchDataIsModified = false;
+}
+
void PartSet_WidgetSketchLabel::deactivate()
{
QWidget* aTopWidget = window();
}
}
-
//******************************************************
QList<ModuleBase_ViewerPrsPtr> PartSet_WidgetSketchLabel::findCircularEdgesInPlane()
{
myShowPoints->blockSignals(aBlock);
}
+bool PartSet_WidgetSketchLabel::storeValueCustom()
+{
+ if (mySketchDataIsModified)
+ saveSketchViewPreferenceToSkethData();
+
+ return true;
+}
+
bool PartSet_WidgetSketchLabel::restoreValueCustom()
{
if (myFeature.get()) {
myShowDOFBtn->setEnabled(true);
}
}
+
+ PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ if (aModule)
+ aModule->sketchMgr()->previewSketchPlane()->setAllUsingSketch(aSketch);
+
+ reconfigureSketchViewWidgets();
}
else {
myDoFLabel->setText("");
return true;
}
-
-void PartSet_WidgetSketchLabel::onShowDOF()
-{
- CompositeFeaturePtr aCompFeature =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
- if (aCompFeature.get()) {
- static const Events_ID anEvent = Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS);
- ModelAPI_EventCreator::get()->sendUpdated(aCompFeature, anEvent);
- Events_Loop::loop()->flush(anEvent);
-
- // Transfer focus to the current viewport for correct processing of a key event
- QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
- if (aViewPort)
- aViewPort->setFocus();
- }
-}
-
bool PartSet_WidgetSketchLabel::eventFilter(QObject* theObj, QEvent* theEvent)
{
if (theObj == window()) {
return ModuleBase_WidgetValidated::eventFilter(theObj, theEvent);
}
-void PartSet_WidgetSketchLabel::onShowViewPlane(bool toShow)
+
+PitchSpinBox::PitchSpinBox(QWidget* theParent) : QDoubleSpinBox(theParent)
{
- PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
- PartSet_PreviewSketchPlane* aPreviewPlane = aModule->sketchMgr()->previewSketchPlane();
- if (toShow) {
- CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
- if (aPreviewPlane->isPlaneCreated())
- aPreviewPlane->displaySketchPlane(myWorkshop);
- else
- aPreviewPlane->createSketchPlane(aSketch, myWorkshop);
+ setRange(std::pow(10, -PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_TRANS), std::numeric_limits<double>::max());
+ setDecimals(PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_TRANS);
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ setMinimumWidth(PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH);
+ myPrevVal = 1;
+
+ connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged()));
+ connect(this, SIGNAL(editingFinished()), this, SLOT(onEditingFinished()));
+}
+
+void PitchSpinBox::setValue(double theVal)
+{
+ myPrevVal = theVal;
+ QDoubleSpinBox::setValue(theVal);
+}
+
+void PitchSpinBox::onTextChanged()
+{
+ if (value() <= Precision::Confusion())
+ return;
+
+ setSingleStep(PartSet_WidgetSketchGrid::reasonablePitchIncrement(value()));
+ emit valueSet(value());
+}
+
+void PitchSpinBox::onEditingFinished()
+{
+ if (value() <= Precision::Confusion()) {
+ QDoubleSpinBox::setValue(myPrevVal);
}
else {
- aPreviewPlane->eraseSketchPlane(myWorkshop, false);
+ myPrevVal = value();
+ emit valueSet(value());
}
- myWorkshop->viewer()->update();
}
+
+
+PartSet_WidgetSketchGrid::PartSet_WidgetSketchGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel)
+: QWidget(theParent), mySketchLabel(theSketchLabel), myPreviewPlane(nullptr)
+{
+ static const double MAX_DOUBLE = std::numeric_limits<double>::max();
+ static const double MIN_DOUBLE = std::numeric_limits<double>::lowest();
+
+ myResetButton = new QPushButton(tr("Reset"), this);
+ myResetButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myResetButton->setToolTip(tr("Set default pitches and zero offsets."));
+
+ const auto offsetAngleLabel = new QLabel(this);
+ offsetAngleLabel->setText(tr("Offset angle,°"));
+
+ myOffsetAngleSpinBox = new QDoubleSpinBox(this);
+ myOffsetAngleSpinBox->setRange(-180, 180);
+ myOffsetAngleSpinBox->setDecimals(PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_ROTAT);
+ myOffsetAngleSpinBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myOffsetAngleSpinBox->setMinimumWidth(PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH);
+
+ const auto offsetXLabel = new QLabel(this);
+ offsetXLabel->setText(tr("Offset") + " X'");
+
+ myOffsetXSpinBox = new QDoubleSpinBox(this);
+ myOffsetXSpinBox->setRange(MIN_DOUBLE, MAX_DOUBLE);
+ myOffsetXSpinBox->setDecimals(PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_TRANS);
+ myOffsetXSpinBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myOffsetXSpinBox->setMinimumWidth(PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH);
+
+ const auto offsetYLabel = new QLabel(this);
+ offsetYLabel->setText(tr("Offset") + " Y'");
+
+ myOffsetYSpinBox = new QDoubleSpinBox(this);
+ myOffsetYSpinBox->setRange(MIN_DOUBLE, MAX_DOUBLE);
+ myOffsetYSpinBox->setDecimals(PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_TRANS);
+ myOffsetYSpinBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myOffsetYSpinBox->setMinimumWidth(PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH);
+
+ myLayout = new QGridLayout(this);
+ myLayout->addWidget(myResetButton , 2, 0);
+ myLayout->addWidget(offsetAngleLabel, 3, 0);
+ myLayout->addWidget(offsetXLabel , 3, 1);
+ myLayout->addWidget(offsetYLabel , 3, 2);
+ myLayout->addWidget(myOffsetAngleSpinBox, 4, 0);
+ myLayout->addWidget(myOffsetXSpinBox , 4, 1);
+ myLayout->addWidget(myOffsetYSpinBox , 4, 2);
+
+ connect(myResetButton, SIGNAL(clicked(bool)), this, SLOT(onResetClicked()));
+ connect(myOffsetAngleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onOffsetAngleChanged(double)));
+ connect(myOffsetXSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onOffsetXChanged(double)));
+ connect(myOffsetYSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onOffsetYChanged(double)));
+
+ setEnabled(false);
+}
+
+/*static*/ double PartSet_WidgetSketchGrid::clampValue(double theValue, double theIntervalWidth)
+{
+ theValue = std::remainder(theValue, theIntervalWidth);
+ if (theValue > theIntervalWidth/2)
+ theValue = theValue - theIntervalWidth;
+ else if (theValue <= -theIntervalWidth/2)
+ theValue = theIntervalWidth + theValue;
+
+ return theValue;
+}
+
+/*static*/ double PartSet_WidgetSketchGrid::reasonableOffsetIncrement(double theStep)
+{
+ const double stepTenth = theStep / 10;
+ if (std::abs(stepTenth) < Precision::Confusion())
+ return 0;
+
+ return std::pow(10, std::floor(std::log10(stepTenth)));
+}
+
+/*static*/ double PartSet_WidgetSketchGrid::reasonablePitchIncrement(double theStep)
+{
+ return PartSet_WidgetSketchGrid::reasonableOffsetIncrement(theStep);
+}
+
+void PartSet_WidgetSketchGrid::retrieveSketchAndPlane()
+{
+ const auto module = dynamic_cast<PartSet_Module*>(mySketchLabel->myWorkshop->module());
+ if (!module)
+ myPreviewPlane = nullptr;
+ else
+ myPreviewPlane = module->sketchMgr()->previewSketchPlane();
+}
+
+/*static*/ const int PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_TRANS = 3;
+/*static*/ const int PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_ROTAT = 4; // Fits angular second.
+/*static*/ const int PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH = 80;
+
+
+PartSet_WidgetSketchRectangularGrid::PartSet_WidgetSketchRectangularGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel)
+: PartSet_WidgetSketchGrid(theParent, theSketchLabel)
+{
+ static const double MAX_DOUBLE = std::numeric_limits<double>::max();
+ static const double MIN_DOUBLE = std::numeric_limits<double>::min();
+
+ const auto stepXLabel = new QLabel(this);
+ stepXLabel->setText(tr("Pitch") + " X'");
+
+ myStepXSpinBox = new PitchSpinBox(this);
+
+ const auto stepYLabel = new QLabel(this);
+ stepYLabel->setText(tr("Pitch") + " Y'");
+
+ myStepYSpinBox = new PitchSpinBox(this);
+
+ myLayout->addWidget(stepXLabel , 1, 1);
+ myLayout->addWidget(stepYLabel , 1, 2);
+ myLayout->addWidget(myStepXSpinBox, 2, 1);
+ myLayout->addWidget(myStepYSpinBox, 2, 2);
+
+ connect(myStepXSpinBox, SIGNAL(valueSet(double)), this, SLOT(onStepXSet(double)));
+ connect(myStepYSpinBox, SIGNAL(valueSet(double)), this, SLOT(onStepYSet(double)));
+}
+
+void PartSet_WidgetSketchRectangularGrid::recongifure()
+{
+ retrieveSketchAndPlane();
+
+ if (myPreviewPlane) {
+ const auto steps = myPreviewPlane->getRectangularGridSteps();
+ myStepXSpinBox->setValue(steps.first);
+ myStepYSpinBox->setValue(steps.second);
+
+ const auto offsets = myPreviewPlane->getRectangularGridOffsets();
+ myOffsetAngleSpinBox->setValue(PartSet_WidgetSketchGrid::clampValue(offsets.second, 360));
+ myOffsetXSpinBox->setValue(offsets.first.first);
+ myOffsetYSpinBox->setValue(offsets.first.second);
+
+ setEnabled(true);
+ }
+ else {
+ setEnabled(false);
+
+ myStepXSpinBox->setValue(0);
+ myStepYSpinBox->setValue(0);
+ myOffsetAngleSpinBox->setValue(0);
+ myOffsetXSpinBox->setValue(0);
+ myOffsetYSpinBox->setValue(0);
+ }
+}
+
+void PartSet_WidgetSketchRectangularGrid::onStepXSet(double theStep)
+{
+ myOffsetXSpinBox->setSingleStep(PartSet_WidgetSketchGrid::reasonableOffsetIncrement(theStep));
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->myFeature);
+ if (sketch) {
+ PartSet_Tools::sketchPlaneRectangularGridStepX(sketch)->setValue(theStep);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setRectangularGridStepX(theStep);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchRectangularGrid::onStepYSet(double theStep)
+{
+ myOffsetYSpinBox->setSingleStep(PartSet_WidgetSketchGrid::reasonableOffsetIncrement(theStep));
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->myFeature);
+ if (sketch) {
+ PartSet_Tools::sketchPlaneRectangularGridStepY(sketch)->setValue(theStep);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setRectangularGridStepY(theStep);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchRectangularGrid::onResetClicked()
+{
+ if (!myPreviewPlane)
+ return;
+
+ myPreviewPlane->resetRectangularGrid();
+ recongifure();
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ myPreviewPlane->saveRectangularGridPreferencesIntoSketchData(sketch);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ mySketchLabel->myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchRectangularGrid::onOffsetAngleChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneRectangularGridOffsetAngle(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setRectangularGridOffsetA(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchRectangularGrid::onOffsetXChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneRectangularGridOffsetX(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setRectangularGridOffsetX(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchRectangularGrid::onOffsetYChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneRectangularGridOffsetY(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setRectangularGridOffsetY(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+
+PartSet_WidgetSketchCircularGrid::PartSet_WidgetSketchCircularGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel)
+: PartSet_WidgetSketchGrid(theParent, theSketchLabel)
+{
+ static const double MAX_DOUBLE = std::numeric_limits<double>::max();
+ static const double MIN_DOUBLE = std::numeric_limits<double>::min();
+
+ const auto stepRLabel = new QLabel(this);
+ stepRLabel->setText(tr("Pitch") + " R");
+
+ myStepRSpinBox = new PitchSpinBox(this);
+
+ const auto aNASLabel = new QLabel(this);
+ aNASLabel->setText(tr("Num of angular segments"));
+
+ myNASSpinBox = new QSpinBox(this);
+ myNASSpinBox->setRange(2, std::numeric_limits<int>::max());
+ myNASSpinBox->setSingleStep(2);
+ myNASSpinBox->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
+ myNASSpinBox->setToolTip(tr("Even numbers only."));
+ myNASSpinBox->setMinimumWidth(PartSet_WidgetSketchGrid::SPIN_BOX_MIN_WIDTH);
+
+ myLayout->addWidget(stepRLabel , 1, 1);
+ myLayout->addWidget(aNASLabel , 1, 2);
+ myLayout->addWidget(myStepRSpinBox, 2, 1);
+ myLayout->addWidget(myNASSpinBox , 2, 2);
+
+ connect(myStepRSpinBox, SIGNAL(valueSet(double)), this, SLOT(onStepRChanged(double)));
+ connect(myNASSpinBox, SIGNAL(valueChanged(int)), this, SLOT(onNumOfAngularSegmentsChanged(int)));
+}
+
+void PartSet_WidgetSketchCircularGrid::recongifure()
+{
+ retrieveSketchAndPlane();
+
+ if (myPreviewPlane) {
+ const auto stepAndNum = myPreviewPlane->getCircularGrid_dR_and_NAS();
+ myStepRSpinBox->setValue(stepAndNum.first);
+ myNASSpinBox->setValue(stepAndNum.second);
+ updateSegmentsToolTip();
+
+ const auto offsets = myPreviewPlane->getCircularGridOffsets();
+ myOffsetAngleSpinBox->setValue(PartSet_WidgetSketchGrid::clampValue(offsets.second, 360));
+ myOffsetXSpinBox->setValue(offsets.first.first);
+ myOffsetYSpinBox->setValue(offsets.first.second);
+
+ setEnabled(true);
+ }
+ else {
+ setEnabled(false);
+
+ myStepRSpinBox->setValue(0);
+ myNASSpinBox->setValue(1);
+ updateSegmentsToolTip();
+ myOffsetAngleSpinBox->setValue(0);
+ myOffsetXSpinBox->setValue(0);
+ myOffsetYSpinBox->setValue(0);
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::onStepRChanged(double theStep)
+{
+ const double increment = PartSet_WidgetSketchGrid::reasonableOffsetIncrement(theStep);
+ myOffsetXSpinBox->setSingleStep(increment);
+ myOffsetYSpinBox->setSingleStep(increment);
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->myFeature);
+ if (sketch) {
+ PartSet_Tools::sketchPlaneCircularGridStepR(sketch)->setValue(theStep);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setCircularGridRadialStep(theStep);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::onNumOfAngularSegmentsChanged(int theNum)
+{
+ theNum = theNum + theNum % 2;
+ myNASSpinBox->setValue(theNum);
+ updateSegmentsToolTip();
+
+ const double increment = PartSet_WidgetSketchGrid::reasonableOffsetIncrement(double(360)/theNum);
+ myOffsetAngleSpinBox->setSingleStep(increment);
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->myFeature);
+ if (sketch) {
+ PartSet_Tools::sketchPlaneCircularGridNumOfAngSegments(sketch)->setValue(theNum);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setCircularGridNumOfAngularSegments(theNum);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::onResetClicked()
+{
+ if (!myPreviewPlane)
+ return;
+
+ myPreviewPlane->resetCircularGrid();
+ recongifure();
+
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ myPreviewPlane->saveCircularGridPreferencesIntoSketchData(sketch);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ mySketchLabel->myWorkshop->viewer()->update();
+}
+
+void PartSet_WidgetSketchCircularGrid::onOffsetAngleChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneCircularGridOffsetAngle(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setCircularGridOffsetA(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::onOffsetXChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneCircularGridOffsetX(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setCircularGridOffsetX(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::onOffsetYChanged(double theOffset)
+{
+ const auto sketch = std::static_pointer_cast<ModelAPI_CompositeFeature>(mySketchLabel->feature());
+ if (sketch) {
+ PartSet_Tools::sketchPlaneCircularGridOffsetY(sketch)->setValue(theOffset);
+ mySketchLabel->mySketchDataIsModified = true;
+ }
+
+ if (myPreviewPlane) {
+ myPreviewPlane->setCircularGridOffsetY(theOffset);
+ myPreviewPlane->reconfigureGrid();
+ mySketchLabel->myWorkshop->viewer()->update();
+ }
+}
+
+void PartSet_WidgetSketchCircularGrid::updateSegmentsToolTip()
+{
+ const int N = myNASSpinBox->value();
+ QString toolTip = tr("Even numbers only.") + "\nAngle " + QString::number(180 - double(N-2)/N * 180, 'f', PartSet_WidgetSketchGrid::NUM_OF_DECIMAL_DIGITS_ROTAT) + "°";
+ myNASSpinBox->setToolTip(toolTip);
+}
\ No newline at end of file
#define PartSet_WidgetSketchLabel_H
#include "PartSet.h"
-
#include "PartSet_Tools.h"
#include <ModuleBase_WidgetValidated.h>
#include <TopoDS_Shape.hxx>
#include <QStackedWidget>
+#include <QDoubleSpinBox>
#include <QMap>
class PartSet_PreviewPlanes;
+class PartSet_PreviewSketchPlane;
-class QLabel;
class XGUI_OperationMgr;
class XGUI_Workshop;
class QCheckBox;
-class QStackedWidget;
+class QComboBox;
+class QDialog;
+class QSpinBox;
+class QGroupBox;
+class QLabel;
class QLineEdit;
class QPushButton;
-class QDialog;
+class QStackedWidget;
+class QGridLayout;
+
+class PartSet_WidgetSketchLabel;
+class ModelAPI_CompositeFeature;
+
+
+class PartSet_WidgetSketchRectangularGrid;
+class PartSet_WidgetSketchCircularGrid;
+
/**
* \ingroup Modules
-* A model widget implementation for a label which provides specific behaviour
+* A model widget implementation for a label which provides specific behaviour
* for sketcher starting and launching operations
*/
class PARTSET_EXPORT PartSet_WidgetSketchLabel : public ModuleBase_WidgetValidated
const Config_WidgetAPI* theData,
const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints);
- virtual ~PartSet_WidgetSketchLabel();
+ virtual ~PartSet_WidgetSketchLabel() = default;
+
+ virtual void setFeature(
+ const FeaturePtr& theFeature,
+ const bool theToStoreValue = false,
+ const bool isUpdateFlushed = true
+ );
+
+ virtual bool isModified() const { return mySketchDataIsModified; }
/// Set the given wrapped value to the current widget
/// This value should be processed in the widget according to the needs
/// Saves the internal parameters to the given feature
/// \return True in success
- virtual bool storeValueCustom()
- {
- return true;
- }
+ virtual bool storeValueCustom();
virtual bool restoreValueCustom();
virtual bool eventFilter(QObject* theObj, QEvent* theEvent);
private slots:
- /// A slot called on set sketch plane view
+ /// Called on set sketch plane view
void onSetPlaneView();
/// Emits signal about check box state changed with information about ConstraintVisibleState
/// \param theOn a flag show constraints or not
void onShowConstraint(bool theOn);
- /// A a slot called on "Change sketch plane" check box toggele
+ /// Called on "Change sketch plane" button is clicked.
void onChangePlane();
- /// A a slot called on "Show remaining DOFs" check box toggele
+ /// Called on "Show remaining DOFs" button is clicked.
void onShowDOF();
- /// A a slot called on changing the panel visibility
+ /// Called on changing the panel visibility
void onShowPanel();
- /// A slot which is called on "Visible" plane checkbox toggle
- void onShowViewPlane(bool);
+ void onShowAxes(bool);
+ void onShowSubstrate(bool);
+
+ void onGridTypeChanged(int);
+ void onGridSnappingModeChanged(int);
+
+ /*! \brief Must be called after PartSet_PreviewSketchPlane is configured. */
+ void reconfigureSketchViewWidgets();
+
+ void saveSketchViewPreferenceToSkethData();
private:
/// Set sketch plane by shape
/**
* Returns list of presentations which have displayed shapes with circular edges
- * (circles, arcs) which are in pane of of the given sketch
+ * (circles, arcs) which are in plane of of the given sketch
* \param theSketch - the sketch
*/
QList<ModuleBase_ViewerPrsPtr> findCircularEdgesInPlane();
/// class to show/hide preview planes
PartSet_PreviewPlanes* myPreviewPlanes;
+ bool mySketchDataIsModified;
+ QGroupBox* mySketchViewGroupBox;
+
QCheckBox* myViewInverted;
- QCheckBox* myViewVisible;
+ QCheckBox* myAxesVisibleCheckBox; // Local sketch axes.
+ QCheckBox* mySubstrateVisibleCheckBox;
+
+ QComboBox* myGridTypeComboBox;
+ QComboBox* myGridSnappingModeComboBox;
+
+ friend class PartSet_WidgetSketchGrid;
+ friend class PartSet_WidgetSketchRectangularGrid;
+ friend class PartSet_WidgetSketchCircularGrid;
+ PartSet_WidgetSketchRectangularGrid* myWidgetRectangularGrid;
+ PartSet_WidgetSketchCircularGrid* myWidgetCircularGrid;
+
QCheckBox* myRemoveExternal;
QCheckBox* myShowPoints;
QCheckBox* myAutoConstraints;
GeomPlanePtr myTmpPlane;
};
+
+class PARTSET_EXPORT PitchSpinBox : public QDoubleSpinBox
+{
+ Q_OBJECT
+public:
+ PitchSpinBox(QWidget* theParent);
+ ~PitchSpinBox() = default;
+
+ void setValue(double theVal);
+
+signals:
+ void valueSet(double theVal);
+
+private slots:
+ virtual void onTextChanged();
+ virtual void onEditingFinished();
+
+private:
+ double myPrevVal;
+};
+
+
+class PARTSET_EXPORT PartSet_WidgetSketchGrid : public QWidget
+{
+ Q_OBJECT
+public:
+/*! \param theSketchLabel must not be nullptr. */
+ PartSet_WidgetSketchGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel);
+ virtual ~PartSet_WidgetSketchGrid() = default;
+
+ virtual void recongifure() = 0;
+
+protected slots:
+ virtual void onResetClicked() = 0;
+ virtual void onOffsetAngleChanged(double theOffset) = 0;
+ virtual void onOffsetXChanged(double theOffset) = 0;
+ virtual void onOffsetYChanged(double theOffset) = 0;
+
+protected:
+ /*! \returns Modulo of theValue in (-theIntervalWidth/2; theIntervalWidth/2]. */
+ static double clampValue(double theValue, double theIntervalWidth);
+
+ /*! \returns Reasonable increment for offset spinbox for given grid pitch. */
+ static double reasonableOffsetIncrement(double theStep);
+
+ /*! \returns Reasonable increment for pitch spinbox for given grid pitch. */
+ static double reasonablePitchIncrement(double theStep);
+
+ void retrieveSketchAndPlane();
+
+protected:
+ /** Num of digits in fractional part of translational values. */
+ static const int NUM_OF_DECIMAL_DIGITS_TRANS;
+
+ /** Num of digits in fractional part of rotational values. */
+ static const int NUM_OF_DECIMAL_DIGITS_ROTAT;
+
+ static const int SPIN_BOX_MIN_WIDTH;
+
+protected:
+ PartSet_WidgetSketchLabel* const mySketchLabel;
+ PartSet_PreviewSketchPlane* myPreviewPlane;
+
+ QGridLayout* myLayout;
+
+ QPushButton* myResetButton;
+
+ QDoubleSpinBox* myOffsetXSpinBox;
+ QDoubleSpinBox* myOffsetYSpinBox;
+ QDoubleSpinBox* myOffsetAngleSpinBox;
+
+ friend class PitchSpinBox;
+};
+
+
+class PARTSET_EXPORT PartSet_WidgetSketchRectangularGrid : public PartSet_WidgetSketchGrid
+{
+ Q_OBJECT
+public:
+ /*! \param theSketchLabel must not be nullptr. */
+ PartSet_WidgetSketchRectangularGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel);
+ virtual ~PartSet_WidgetSketchRectangularGrid() = default;
+
+ /*! \brief Must be called after PartSet_PreviewSketchPlane is configured. */
+ virtual void recongifure();
+
+private slots:
+ void onStepXSet(double theStep);
+ void onStepYSet(double theStep);
+
+protected slots:
+ virtual void onResetClicked();
+ virtual void onOffsetAngleChanged(double theOffset);
+ virtual void onOffsetXChanged(double theOffset);
+ virtual void onOffsetYChanged(double theOffset);
+
+private:
+ PitchSpinBox* myStepXSpinBox;
+ PitchSpinBox* myStepYSpinBox;
+};
+
+
+class PARTSET_EXPORT PartSet_WidgetSketchCircularGrid : public PartSet_WidgetSketchGrid
+{
+ Q_OBJECT
+public:
+ /*! \param theSketchLabel must not be nullptr. */
+ PartSet_WidgetSketchCircularGrid(QWidget* theParent, PartSet_WidgetSketchLabel* theSketchLabel);
+ virtual ~PartSet_WidgetSketchCircularGrid() = default;
+
+ /*! \brief Must be called after PartSet_PreviewSketchPlane is configured. */
+ virtual void recongifure();
+
+private slots:
+ void onStepRChanged(double theStep);
+ void onNumOfAngularSegmentsChanged(int theNum);
+
+protected slots:
+ virtual void onResetClicked();
+ virtual void onOffsetAngleChanged(double theOffset);
+ virtual void onOffsetXChanged(double theOffset);
+ virtual void onOffsetYChanged(double theOffset);
+
+private:
+ void updateSegmentsToolTip();
+
+ PitchSpinBox* myStepRSpinBox;
+ QSpinBox* myNASSpinBox;
+};
+
#endif
Erreur : %1</translation>
</message>
</context>
+<context>
+ <name>PartSet_WidgetSketchGrid</name>
+ <message>
+ <source>Reset</source>
+ <translation>Réinitialiser</translation>
+ </message>
+ <message>
+ <source>Set default pitches and zero offsets.</source>
+ <translation>Définissez le pas par défaut et les offsets zéro.</translation>
+ </message>
+ <message>
+ <source>Offset angle,°</source>
+ <translation>Offset angulaire,°</translation>
+ </message>
+ <message>
+ <source>Offset</source>
+ <translation>Offset</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetSketchRectangularGrid</name>
+ <message>
+ <source>Pitch</source>
+ <translation>Pas</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetSketchCircularGrid</name>
+ <message>
+ <source>Pitch</source>
+ <translation>Pas</translation>
+ </message>
+ <message>
+ <source>Num of angular segments</source>
+ <translation>Nombre de segments angulaires</translation>
+ </message>
+ <message>
+ <source>Even numbers only.</source>
+ <translation>Chiffres pairs uniquement.</translation>
+ </message>
+</context>
<context>
<name>PartSet_WidgetSketchLabel</name>
<message>
<source>Reversed</source>
<translation>Renversé</translation>
</message>
+ <message>
+ <source>Axes</source>
+ <translation>Axes</translation>
+ </message>
+ <message>
+ <source>Substrate</source>
+ <translation>Substrat</translation>
+ </message>
<message>
<source>Set plane view</source>
<translation>Définir la vue plane</translation>
</message>
+ <message>
+ <source>Construction grid</source>
+ <translation>Grille de construction</translation>
+ </message>
+ <message>
+ <source>Disabled</source>
+ <translation>Désactivé</translation>
+ </message>
+ <message>
+ <source>Rectangular</source>
+ <translation>Rectangulaire</translation>
+ </message>
+ <message>
+ <source>Circular</source>
+ <translation>Circulaire</translation>
+ </message>
+ <message>
+ <source>Don't snap</source>
+ <translation>Ne t'accroche pas</translation>
+ </message>
+ <message>
+ <source>Snap anyway</source>
+ <translation>Pour s'accrocher quand même</translation>
+ </message>
+ <message>
+ <source>Snap in proximity</source>
+ <translation>Pour s'accrocher à proximité</translation>
+ </message>
<message>
<source>Show geometrical constraints</source>
<translation>Afficher les contraintes géométriques</translation>
static const std::string MY_NORM_ID("Norm");
return MY_NORM_ID;
}
+
+ /// Size of a skectch, if it has just been created on a default plane.
+ inline static const std::string& DEFAULT_SIZE_ID()
+ {
+ static const std::string MY_DEFAULT_SIZE_ID_ID("DefaultSize");
+ return MY_DEFAULT_SIZE_ID_ID;
+ }
+
+ inline static const std::string& AXES_ENABLED_ID()
+ {
+ static const std::string MY_AXES_ENABLED_ID("AxesEnabled");
+ return MY_AXES_ENABLED_ID;
+ }
+
+ inline static const std::string& SUBSTRATE_ENABLED_ID()
+ {
+ static const std::string MY_SUBSTRATE_ENABLED_ID("SubstrateEnabled");
+ return MY_SUBSTRATE_ENABLED_ID;
+ }
+
+ inline static const std::string& CONSTRUCTION_GRID_TYPE_ID()
+ {
+ static const std::string MY_CONSTRUCTION_GRID_TYPE_ID("GridType");
+ return MY_CONSTRUCTION_GRID_TYPE_ID;
+ }
+
+ inline static const std::string& RECTANGULAR_CONSTRUCTION_GRID_STEP_X_ID()
+ {
+ static const std::string MY_RECTANGULAR_CONSTRUCTION_GRID_STEP_X_ID("RectangularGridStepX");
+ return MY_RECTANGULAR_CONSTRUCTION_GRID_STEP_X_ID;
+ }
+ inline static const std::string& RECTANGULAR_CONSTRUCTION_GRID_STEP_Y_ID()
+ {
+ static const std::string MY_RECTANGULAR_CONSTRUCTION_GRID_STEP_Y_ID("RectangularGridStepY");
+ return MY_RECTANGULAR_CONSTRUCTION_GRID_STEP_Y_ID;
+ }
+ inline static const std::string& RECTANGULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID()
+ {
+ static const std::string MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID("RectangularGridOffsetAngle");
+ return MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID;
+ }
+ inline static const std::string& RECTANGULAR_CONSTRUCTION_GRID_OFFSET_X_ID()
+ {
+ static const std::string MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_X_ID("RectangularGridOffsetX");
+ return MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_X_ID;
+ }
+ inline static const std::string& RECTANGULAR_CONSTRUCTION_GRID_OFFSET_Y_ID()
+ {
+ static const std::string MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_Y_ID("RectangularGridOffsetY");
+ return MY_RECTANGULAR_CONSTRUCTION_GRID_OFFSET_Y_ID;
+ }
+
+ inline static const std::string& CIRCULAR_CONSTRUCTION_GRID_STEP_R_ID()
+ {
+ static const std::string MY_CIRCULAR_CONSTRUCTION_GRID_STEP_R_ID("CircularGridStepR");
+ return MY_CIRCULAR_CONSTRUCTION_GRID_STEP_R_ID;
+ }
+ inline static const std::string& CIRCULAR_CONSTRUCTION_GRID_NUM_OF_ANG_SEGMENTS_ID()
+ {
+ static const std::string MY_CIRCULAR_CONSTRUCTION_GRID_NUM_OF_ANG_SEGMENTS_ID("CircularGridNumOfAnularSegments");
+ return MY_CIRCULAR_CONSTRUCTION_GRID_NUM_OF_ANG_SEGMENTS_ID;
+ }
+ inline static const std::string& CIRCULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID()
+ {
+ static const std::string MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID("CircularGridOffsetAngle");
+ return MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_ANGLE_ID;
+ }
+ inline static const std::string& CIRCULAR_CONSTRUCTION_GRID_OFFSET_X_ID()
+ {
+ static const std::string MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_X_ID("CircularGridOffsetX");
+ return MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_X_ID;
+ }
+ inline static const std::string& CIRCULAR_CONSTRUCTION_GRID_OFFSET_Y_ID()
+ {
+ static const std::string MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_Y_ID("CircularGridOffsetY");
+ return MY_CIRCULAR_CONSTRUCTION_GRID_OFFSET_Y_ID;
+ }
+
/// All features of this sketch (list of references)
inline static const std::string& FEATURES_ID()
{
//**************************************************************
bool XGUI_Displayer::displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes,
const Standard_Integer theDisplayMode, bool theUpdateViewer)
+{
+ Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
+ return displayAIS(anAISIO, toActivateInSelectionModes, theDisplayMode, theUpdateViewer);
+}
+
+bool XGUI_Displayer::displayAIS(Handle(AIS_InteractiveObject) theAISIO, const bool toActivateInSelectionModes,
+ const Standard_Integer theDisplayMode, bool theUpdateViewer)
{
bool aDisplayed = false;
Handle(AIS_InteractiveContext) aContext = AISContext();
- Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
- if (!aContext.IsNull() && !anAISIO.IsNull()) {
- aContext->Display(anAISIO, theDisplayMode, 0, false/*update viewer*/, AIS_DS_Displayed);
+ if (!aContext.IsNull() && !theAISIO.IsNull()) {
+ aContext->Display(theAISIO, theDisplayMode, 0, false/*update viewer*/, AIS_DS_Displayed);
#ifdef TINSPECTOR
- if (getCallBack()) getCallBack()->Display(anAISIO);
+ if (getCallBack()) getCallBack()->Display(theAISIO);
#endif
aDisplayed = true;
- aContext->Deactivate(anAISIO);
+ aContext->Deactivate(theAISIO);
#ifdef TINSPECTOR
- if (getCallBack()) getCallBack()->Deactivate(anAISIO);
+ if (getCallBack()) getCallBack()->Deactivate(theAISIO);
#endif
- aContext->Load(anAISIO);
+ aContext->Load(theAISIO);
#ifdef TINSPECTOR
- if (getCallBack()) getCallBack()->Load(anAISIO);
+ if (getCallBack()) getCallBack()->Load(theAISIO);
#endif
if (toActivateInSelectionModes)
- myWorkshop->selectionActivate()->activateOnDisplay(anAISIO, theUpdateViewer);
+ myWorkshop->selectionActivate()->activateOnDisplay(theAISIO, theUpdateViewer);
if (theUpdateViewer)
updateViewer();
return aErased;
}
+//**************************************************************
+bool XGUI_Displayer::eraseAIS(Handle(AIS_InteractiveObject) theAISIO, const bool theUpdateViewer)
+{
+ bool aErased = false;
+ Handle(AIS_InteractiveContext) aContext = AISContext();
+ if (!aContext.IsNull()) {
+ if (!theAISIO.IsNull() && aContext->IsDisplayed(theAISIO)) {
+ aContext->Remove(theAISIO, false/*update viewer*/);
+ #ifdef TINSPECTOR
+ if (getCallBack()) getCallBack()->Remove(theAISIO);
+ #endif
+ aErased = true;
+ }
+ }
+ if (aErased && theUpdateViewer)
+ updateViewer();
+ return aErased;
+}
+
//**************************************************************
void XGUI_Displayer::setDisplayMode(ObjectPtr theObject, DisplayMode theMode, bool theUpdateViewer)
{
bool displayAIS(AISObjectPtr theAIS, const bool toActivateInSelectionModes,
const Standard_Integer theDisplayMode = 0, bool theUpdateViewer = true);
+ /// Display the given AISIO.
+ /// This object is not added to the displayer internal map of objects
+ /// So, it can not be obtained from displayer. This is just a wrap method of OCC display in
+ /// order to perform the display with correct flags.
+ /// \param theAISIO is an object to display
+ /// \param toActivateInSelectionModes boolean value whether the presentation should be
+ /// activated in the current selection modes
+ /// \param theDisplayMode mode how the presentation should be displayed
+ /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
+ /// \return true if the object visibility state is changed
+ bool displayAIS(Handle(AIS_InteractiveObject) theAISIO, const bool toActivateInSelectionModes,
+ const Standard_Integer theDisplayMode = 0, bool theUpdateViewer = true);
+
/// Redisplay the shape if it was displayed
/// \param theObject an object instance
/// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
/// \return true if the object visibility state is changed
bool eraseAIS(AISObjectPtr theAIS, const bool theUpdateViewer = true);
+ /// Erase the given AISIO displayed by corresponded display method
+ /// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
+ /// \return true if the object visibility state is changed
+ bool eraseAIS(Handle(AIS_InteractiveObject) theAISIO, const bool theUpdateViewer = true);
+
/// Erase all presentations
/// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
/// \return true if the object visibility state is changed