Add algorithm to show direction of edges.
Two view windows
+The viewer is able to show direction of edges of objects.
+
+.. figure:: /images/edges_directions.png
+ :align: center
+
+ Showing the edges direction
+
The description of OCC 3D Viewer architecture and functionality is provided in GUI module user's guide in chapter **OCC 3D Viewer**.
.. _parameter_usage:
// trim: need to redisplay or set color in the python script
if (myObject && (theAttr->attributeType() == "Point2D" || theAttr->id() == "Color" ||
theAttr->id() == "Transparency" || theAttr->id() == "Deflection" ||
- theAttr->id() == "Iso_lines" || theAttr->id() == "Show_Iso_lines")) {
+ theAttr->id() == "Iso_lines" || theAttr->id() == "Show_Iso_lines" ||
+ theAttr->id() == "Show_Edges_direction")) {
static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
}
aData->addAttribute(ISO_LINES_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false);
aData->addAttribute(SHOW_ISO_LINES_ID(), ModelAPI_AttributeBoolean::typeId())->
setIsArgument(false);
+ aData->addAttribute(SHOW_EDGES_DIRECTION_ID(), ModelAPI_AttributeBoolean::typeId())->
+ setIsArgument(false);
}
bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
return MY_SHOW_ISO_LINES_ID;
}
+ /// Reference to the transparency of the result.
+ /// The double value is used. The value is in [0, 1] range
+ inline static const std::string& SHOW_EDGES_DIRECTION_ID()
+ {
+ static const std::string MY_SHOW_EDGES_DIRECTION_ID("Show_Edges_direction");
+ return MY_SHOW_EDGES_DIRECTION_ID;
+ }
+
/// Returns true if the result is concealed from the data tree (referenced by other objects)
MODELAPI_EXPORT virtual bool isConcealed();
return false;
}
+//******************************************************
+void showEdgesDirection(std::shared_ptr<ModelAPI_Result> theResult, bool theShow)
+{
+ if (!theResult.get())
+ return;
+
+ AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_EDGES_DIRECTION_ID());
+ if (aAttr.get() != NULL) {
+ aAttr->setValue(theShow);
+ }
+}
+
+//******************************************************
+bool isShowEdgesDirection(std::shared_ptr<ModelAPI_Result> theResult)
+{
+ if (!theResult.get())
+ return false;
+
+ AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::SHOW_EDGES_DIRECTION_ID());
+ if (aAttr.get() != NULL) {
+ return aAttr->value();
+ }
+ return false;
+}
+
//**************************************************************
void setTransparency(ResultPtr theResult, double theTransparency)
{
MODELAPI_EXPORT bool isShownIsoLines(std::shared_ptr<ModelAPI_Result> theResult);
+/*! Set visibility of edges direction
+* \param[in] theResult a result object
+* \param[in] theShow is a visibility flag
+*/
+MODELAPI_EXPORT void showEdgesDirection(std::shared_ptr<ModelAPI_Result> theResult, bool theShow);
+
+MODELAPI_EXPORT bool isShowEdgesDirection(std::shared_ptr<ModelAPI_Result> theResult);
+
/*! Returns current transparency in the given result
* \param theResult a result object
* \return a transparency value or -1 if it was not defined
ModuleBase_ParamSpinBox.h
ModuleBase_Preferences.h
ModuleBase_ResultPrs.h
+ ModuleBase_ArrowPrs.h
ModuleBase_SelectionValidator.h
ModuleBase_ToolBox.h
ModuleBase_Tools.h
ModuleBase_ParamSpinBox.cpp
ModuleBase_Preferences.cpp
ModuleBase_ResultPrs.cpp
+ ModuleBase_ArrowPrs.cpp
ModuleBase_ToolBox.cpp
ModuleBase_Tools.cpp
ModuleBase_ViewerFilters.cpp
--- /dev/null
+// Copyright (C) 2014-2022 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "ModuleBase_ArrowPrs.h"
+
+#include <Prs3d_ArrowAspect.hxx>
+
+#include <Events_Loop.h>
+#include <ModelAPI_Events.h>
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <Prs3d_Arrow.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopExp.hxx>
+
+
+IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_ArrowPrs, AIS_InteractiveContext)
+
+
+ModuleBase_ArrowPrs::ModuleBase_ArrowPrs(const Handle(V3d_Viewer)& theViewer,
+ const GeomEdgePtr& theEdge)
+ : AIS_InteractiveContext(theViewer),
+ myEdge(theEdge)
+{
+}
+
+//********************************************************************
+void ModuleBase_ArrowPrs::DrawArrow(const Handle(Prs3d_Presentation)& thePrs,
+ Quantity_Color theColor)
+{
+ Handle(Prs3d_Drawer) aDrawer = myDefaultDrawer;
+ Handle(Prs3d_ArrowAspect) anArrowAspect = aDrawer->ArrowAspect();
+
+ Handle(Graphic3d_AspectLine3d) PtA = anArrowAspect->Aspect();
+ PtA->SetColor(theColor);
+
+ Handle(Graphic3d_Group) TheGroup = thePrs->CurrentGroup();
+ TheGroup->SetPrimitivesAspect(PtA);
+
+ TopoDS_Vertex aV1, aV2;
+ TopoDS_Edge anEdgeE = myEdge->impl<TopoDS_Edge>();
+ anEdgeE.Orientation(TopAbs_FORWARD);
+ if (anEdgeE.IsNull()) return;
+
+ TopExp::Vertices(anEdgeE, aV1, aV2);
+ gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
+ gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
+
+ double fp, lp;
+ gp_Vec aDirVec;
+ Handle(Geom_Curve) C = BRep_Tool::Curve(anEdgeE, fp, lp);
+
+ if (C.IsNull()) return;
+
+ if (anEdgeE.Orientation() == TopAbs_FORWARD)
+ C->D1(lp, aP2, aDirVec);
+ else {
+ C->D1(fp, aP1, aDirVec);
+ aP2 = aP1;
+ }
+
+ GeomAdaptor_Curve aAdC;
+ aAdC.Load(C, fp, lp);
+ Standard_Real aDist = GCPnts_AbscissaPoint::Length(aAdC, fp, lp);
+
+ if (aDist > gp::Resolution()) {
+ gp_Dir aDir;
+ if (anEdgeE.Orientation() == TopAbs_FORWARD)
+ aDir = aDirVec;
+ else
+ aDir = -aDirVec;
+
+ TopoDS_Vertex aVertex;
+ BRep_Builder aB;
+ aB.MakeVertex(aVertex, aP2, Precision::Confusion());
+ Prs3d_Arrow::Draw(TheGroup, aP2, aDir, M_PI / 180. * 5., aDist / 10.);
+ }
+}
+
+//********************************************************************
+bool ModuleBase_ArrowPrs::Comparator::operator()(const std::shared_ptr<GeomAPI_Edge>& theEdge1,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge2) const
+{
+ const TopoDS_Edge& aShape1 = theEdge1->impl<TopoDS_Edge>();
+ const TopoDS_Edge& aShape2 = theEdge2->impl<TopoDS_Edge>();
+ bool isLess = aShape1.TShape() < aShape2.TShape();
+ if (aShape1.TShape() == aShape2.TShape()) {
+ Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast());
+ Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast());
+ isLess = aHash1 < aHash2;
+ }
+ return isLess;
+}
--- /dev/null
+// Copyright (C) 2014-2022 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef ModuleBase_ArrowPrs_H
+#define ModuleBase_ArrowPrs_H
+
+#include <ModuleBase.h>
+#include <GeomAPI_Edge.h>
+#include <AIS_InteractiveContext.hxx>
+
+#include <map>
+
+DEFINE_STANDARD_HANDLE(ModuleBase_ArrowPrs, AIS_InteractiveContext)
+
+/**
+* \ingroup GUI
+* A presentation class for displaying a direction of edge
+*/
+
+class ModuleBase_ArrowPrs : public AIS_InteractiveContext
+{
+public:
+ /// Constructor
+ /// \param theViewer a viewer which theEdge is displaying.
+ /// \param theEdge an edge whose direction to display.
+ Standard_EXPORT ModuleBase_ArrowPrs(const Handle(V3d_Viewer)& theViewer,
+ const GeomEdgePtr& theEdge);
+
+ /// Returns an edge shape
+ GeomEdgePtr Edge() const { return myEdge; }
+
+ /// Draw arrow that represent direction of the edge.
+ Standard_EXPORT void DrawArrow(const Handle(Prs3d_Presentation)& thePrs, Quantity_Color theColor);
+
+ /// \brief Compare addresses of edges
+ class Comparator
+ {
+ public:
+ /// Return \c true if the address of the first edge is less than the address of the second
+ MODULEBASE_EXPORT
+ bool operator ()(const std::shared_ptr<GeomAPI_Edge>& theEdge1,
+ const std::shared_ptr<GeomAPI_Edge>& theEdge2) const;
+ };
+
+ DEFINE_STANDARD_RTTIEXT(ModuleBase_ArrowPrs, AIS_InteractiveContext)
+
+private:
+
+ /// The edge whose direction to display.
+ GeomEdgePtr myEdge;
+};
+
+typedef std::pair<GeomEdgePtr, Handle(ModuleBase_ArrowPrs)> EdgeDirection;
+typedef std::map<GeomEdgePtr, Handle(ModuleBase_ArrowPrs), ModuleBase_ArrowPrs::Comparator> EdgesDirectionMap;
+
+#endif
\ No newline at end of file
#include <StdPrs_ShadedShape.hxx>
#include <StdSelect_BRepSelectionTool.hxx>
#include <TColStd_ListIteratorOfListOfInteger.hxx>
+#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Builder.hxx>
// change deviation coefficient to provide more precise circle
try {
AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
+ AddRemoveEdgesDir(GetContext()->CurrentViewer());
}
catch (...) {
return;
myUIsoAspect->SetNumber(aIsoValues[0]);
myVIsoAspect->SetNumber(aIsoValues[1]);
}
+
+bool ModuleBase_ResultPrs::AddRemoveEdgesDir(const Handle(V3d_Viewer)& theViewer)
+{
+ bool isShow = ModelAPI_Tools::isShowEdgesDirection(myResult);
+ if (isShow) {
+ std::list<GeomShapePtr> aSubEdges = myResult->shape()->subShapes(GeomAPI_Shape::EDGE);
+
+ for (auto anEdgeIter = aSubEdges.begin(); anEdgeIter != aSubEdges.end(); ++anEdgeIter) {
+ GeomEdgePtr anEdgePtr = (*anEdgeIter)->edge();
+ if (myEdgesDirection.find(anEdgePtr) != myEdgesDirection.end()) {
+ myEdgesDirection.at(anEdgePtr)->DrawArrow(Presentation(), Quantity_NOC_BLACK);
+ }
+ else {
+ Handle(ModuleBase_ArrowPrs) anArrowPrs = new ModuleBase_ArrowPrs(theViewer, anEdgePtr);
+ myEdgesDirection.insert(EdgeDirection(anEdgePtr, anArrowPrs));
+ anArrowPrs->DrawArrow(Presentation(), Quantity_NOC_BLACK);
+ }
+ }
+ }
+ else
+ myEdgesDirection.clear();
+
+ GetContext()->UpdateCurrentViewer();
+ return isShow;
+}
+
+Standard_EXPORT void ModuleBase_ResultPrs::UpdateEdgesDir()
+{
+ TopoDS_Shape aSelectedShape = GetContext()->SelectedShape();
+ for (auto anEdgeDir = myEdgesDirection.begin(); anEdgeDir != myEdgesDirection.end(); ++anEdgeDir) {
+ TopoDS_Edge anEdge = anEdgeDir->first->impl<TopoDS_Edge>();
+ bool isSelect = false;
+ TopExp_Explorer Exp(aSelectedShape, TopAbs_EDGE);
+ for (; Exp.More(); Exp.Next()) {
+ if (TopoDS::Edge(Exp.Current()).IsSame(anEdge)) {
+ isSelect = true;
+ break;
+ }
+ }
+ if(isSelect)
+ anEdgeDir->second->DrawArrow(Presentation(), Quantity_NOC_WHITE);
+ else
+ anEdgeDir->second->DrawArrow(Presentation(), Quantity_NOC_BLACK);
+ }
+ GetContext()->UpdateCurrentViewer();
+}
#include "ModuleBase.h"
+#include "ModuleBase_ArrowPrs.h"
+
#include <ModelAPI_Result.h>
#include <ModelAPI_ResultField.h>
Standard_EXPORT void updateIsoLines();
+ Standard_EXPORT bool AddRemoveEdgesDir(const Handle(V3d_Viewer)& theViewer);
+
+ Standard_EXPORT void UpdateEdgesDir();
+
DEFINE_STANDARD_RTTIEXT(ModuleBase_ResultPrs, ViewerData_AISShape)
protected:
Handle(Prs3d_IsoAspect) myUIsoAspect;
Handle(Prs3d_IsoAspect) myVIsoAspect;
+
+
+ EdgesDirectionMap myEdgesDirection;
};
aDesktop);
addAction("ISOLINES_CMD", anAction);
+ anAction = ModuleBase_Tools::createAction(QIcon(), tr("Show edges direction"), aDesktop);
+ anAction->setCheckable(true);
+ addAction("SHOW_EDGES_DIRECTION_CMD", anAction);
+
anAction = ModuleBase_Tools::createAction(QIcon(), tr("Show Isos"), aDesktop);
anAction->setCheckable(true);
addAction("SHOW_ISOLINES_CMD", anAction);
action("WIREFRAME_CMD")->setEnabled(true);
action("SHADING_CMD")->setEnabled(true);
}
+ action("SHOW_EDGES_DIRECTION_CMD")->setEnabled(true);
+ action("SHOW_EDGES_DIRECTION_CMD")->setChecked(ModelAPI_Tools::isShowEdgesDirection(aResult));
action("SHOW_ISOLINES_CMD")->setEnabled(true);
action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
action("ISOLINES_CMD")->setEnabled(true);
action("SHOW_ONLY_CMD")->setEnabled(true);
action("SHADING_CMD")->setEnabled(true);
action("WIREFRAME_CMD")->setEnabled(true);
+ action("SHOW_EDGES_DIRECTION_CMD")->setEnabled(true);
action("SHOW_ISOLINES_CMD")->setEnabled(true);
action("ISOLINES_CMD")->setEnabled(true);
}
if (aPrsList.size() == 1) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObject);
if (aResult.get()) {
+ action("SHOW_EDGES_DIRECTION_CMD")->setEnabled(true);
+ action("SHOW_EDGES_DIRECTION_CMD")->setChecked(
+ ModelAPI_Tools::isShowEdgesDirection(aResult));
action("SHOW_ISOLINES_CMD")->setEnabled(true);
action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
}
aList.clear();
aList.append(action("WIREFRAME_CMD"));
aList.append(action("SHADING_CMD"));
+ aList.append(action("SHOW_EDGES_DIRECTION_CMD"));
aList.append(mySeparator1); // this separator is not shown as this action is added after show only
// qt list container contains only one instance of the same action
aList.append(action("SHOW_CMD"));
aList.clear();
aList.append(action("WIREFRAME_CMD"));
aList.append(action("SHADING_CMD"));
+ aList.append(action("SHOW_EDGES_DIRECTION_CMD"));
aList.append(mySeparator2);
aList.append(action("COLOR_CMD"));
aList.append(action("DEFLECTION_CMD"));
} else if (aSelected > 1) {
anActions.append(action("WIREFRAME_CMD"));
anActions.append(action("SHADING_CMD"));
+ anActions.append(action("SHOW_EDGES_DIRECTION_CMD"));
anActions.append(mySeparator1);
anActions.append(action("SHOW_CMD"));
anActions.append(action("HIDE_CMD"));
// Set Iso-Lines
Handle(ModuleBase_ResultPrs) aResPrs = Handle(ModuleBase_ResultPrs)::DownCast(aAISIO);
- if (!aResPrs.IsNull())
+ if (!aResPrs.IsNull()) {
aResPrs->updateIsoLines();
+ aResPrs->AddRemoveEdgesDir(AISContext()->CurrentViewer());
+ }
}
//myWorkshop->module()->storeSelection();
QList<ModuleBase_ViewerPrsPtr> aPresentations;
QList<ModuleBase_ViewerPrsPtr> aToRemove;
+ Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
+ if (!aContext.IsNull()) {
+ AIS_ListOfInteractive aListOfObjects;
+ aContext->DisplayedObjects(aListOfObjects);
+ for (auto anObject = aListOfObjects.begin(); anObject != aListOfObjects.end(); ++anObject) {
+ Handle(ModuleBase_ResultPrs) aResPrs = Handle(ModuleBase_ResultPrs)::DownCast(*anObject);
+ if(aResPrs.get())
+ aResPrs->UpdateEdgesDir();
+ }
+ }
+
switch (thePlace) {
case Browser:
getSelectedInBrowser(aPresentations);
aSelectedIds.append((size_t)anOwner.get());
fillPresentation(aPrs, anOwner);
-
+ AISObjectPtr anAISObject = myWorkshop->displayer()->getAISObject(aPrs->object());
+ Handle(ModuleBase_ResultPrs) aResPrs = Handle(ModuleBase_ResultPrs)::DownCast(anAISObject->
+ impl<Handle(AIS_InteractiveObject)>());
+ aResPrs->UpdateEdgesDir();
if (!thePresentations.contains(aPrs)) // TODO: check whether the presentation in a list
thePresentations.append(aPrs);
}
} else if (theId == "SET_VIEW_INVERTEDNORMAL_CMD") {
setNormalView(true);
}
+ else if (theId == "SHOW_EDGES_DIRECTION_CMD") {
+ foreach(ObjectPtr aObj, anObjects) {
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ if (aResult.get())
+ ModelAPI_Tools::showEdgesDirection(aResult, !ModelAPI_Tools::isShowEdgesDirection(aResult));
+ }
+ mySelector->clearSelection();
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ }
#ifdef TINSPECTOR
else if (theId == "TINSPECTOR_VIEW") {
std::shared_ptr<Model_Session> aSession =
<source>Recover</source>
<translation>Récupérer</translation>
</message>
+ <message>
+ <source>Show edges direction</source>
+ <translation>Afficher la direction des bords</translation>
+ </message>
</context>
<context>
<name>XGUI_DataTree</name>