Files
create/src/Mod/Part/Gui/ViewProviderCurveNet.cpp
2025-11-11 13:49:01 +01:00

331 lines
12 KiB
C++

// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include <BRep_Tool.hxx>
#include <Geom_Curve.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <Inventor/events/SoKeyboardEvent.h>
#include <Inventor/events/SoLocation2Event.h>
#include <Inventor/events/SoMouseButtonEvent.h>
#include <Inventor/nodes/SoComplexity.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoLineSet.h>
#include <Inventor/nodes/SoLocateHighlight.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoTransform.h>
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Gui/Selection/SoFCSelection.h>
#include <Gui/View3DInventorViewer.h>
#include "ViewProviderCurveNet.h"
using namespace PartGui;
//**************************************************************************
// Construction/Destruction
PROPERTY_SOURCE(PartGui::ViewProviderCurveNet, PartGui::ViewProviderPart)
ViewProviderCurveNet::ViewProviderCurveNet()
{
LineWidth.setValue(4.0f);
PointSize.setValue(0.05f);
/*
hGrp = App::GetApplication().GetParameterGroupByPath("User
parameter:BaseApp/Preferences/Mod/Part");
fMeshDeviation = hGrp->GetFloat("MeshDeviation",0.2);
bNoPerVertexNormals = hGrp->GetBool("NoPerVertexNormals",false);
lHilightColor = hGrp->GetInt ("HilightColor",0);
bQualityNormals = hGrp->GetBool("QualityNormals",false);
*/
}
ViewProviderCurveNet::~ViewProviderCurveNet() = default;
void ViewProviderCurveNet::attach(App::DocumentObject* pcFeat)
{
// call parent attach method
ViewProviderGeometryObject::attach(pcFeat); // clazy:exclude=skipped-base-method
// setup the root and material for the edges
SoSeparator* ModeRoot = new SoSeparator();
EdgeRoot = new SoSeparator();
ModeRoot->addChild(EdgeRoot);
EdgeRoot->addChild(pcLineStyle);
EdgeRoot->addChild(pcLineMaterial);
// setup the root and material for the vertexes
VertexRoot = new SoSeparator();
ModeRoot->addChild(VertexRoot);
VertexRoot->addChild(pcPointMaterial);
SoComplexity* copl = new SoComplexity();
copl->value = (float)0.2;
VertexRoot->addChild(copl);
addDisplayMaskMode(ModeRoot, "Edge");
}
void ViewProviderCurveNet::updateData(const App::Property* prop)
{
Gui::ViewProviderGeometryObject::updateData(prop); // clazy:exclude=skipped-base-method
if (prop->is<Part::PropertyPartShape>()) {
TopoDS_Shape cShape = static_cast<const Part::PropertyPartShape*>(prop)->getValue();
if (cShape.IsNull()) {
return;
}
Gui::coinRemoveAllChildren(EdgeRoot);
Gui::coinRemoveAllChildren(VertexRoot);
try {
computeEdges(EdgeRoot, cShape);
computeVertices(VertexRoot, cShape);
}
catch (...) {
Base::Console()
.error("ViewProviderPart::create() Cannot compute Inventor representation for the actual shape");
}
}
}
void ViewProviderCurveNet::setDisplayMode(const char* ModeName)
{
if (strcmp("Edge", ModeName) == 0) {
setDisplayMaskMode("Edge");
}
ViewProviderGeometryObject::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderCurveNet::getDisplayModes() const
{
// get the modes of the father
std::vector<std::string> StrList;
// add your own modes
StrList.emplace_back("Edge");
return StrList;
}
// **********************************************************************************
bool ViewProviderCurveNet::setEdit(int)
{
bInEdit = true;
return true;
// getWidget()->setCursor( QCursor( 13 /*ArrowCursor*/) )
}
void ViewProviderCurveNet::unsetEdit(int)
{
bInEdit = false;
}
bool ViewProviderCurveNet::handleEvent(const SoEvent* const ev, Gui::View3DInventorViewer& Viewer)
{
SbVec3f point, norm;
// get the position of the mouse
const SbVec2s pos(ev->getPosition());
// Keyboard events
if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
const SoKeyboardEvent* ke = static_cast<const SoKeyboardEvent*>(ev);
switch (ke->getKey()) {
case SoKeyboardEvent::LEFT_ALT:
case SoKeyboardEvent::RIGHT_ALT:
case SoKeyboardEvent::LEFT_CONTROL:
case SoKeyboardEvent::RIGHT_CONTROL:
case SoKeyboardEvent::LEFT_SHIFT:
case SoKeyboardEvent::RIGHT_SHIFT:
break;
default:
break;
}
}
// switching the mouse buttons
if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
const SoMouseButtonEvent* const event = static_cast<const SoMouseButtonEvent*>(ev);
const int button = event->getButton();
const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
// which button pressed?
switch (button) {
case SoMouseButtonEvent::BUTTON1:
if (press) {
Base::Console().log("ViewProviderCurveNet::handleEvent() press left\n");
bool bIsNode = false;
for (const auto& It : NodeList) {
if (It.pcHighlight->isHighlighted()) {
bIsNode = true;
PointToMove = It;
break;
}
}
if (bIsNode) {
// set the provider in point move mode and remember the point
bMovePointMode = true;
// PointToMove = *It; ### Error 'It' is out of scope->move inside the loop
return true;
}
else if (Viewer.pickPoint(pos, point, norm)) {
Node n;
Base::Console().log("Picked(%f,%f,%f)\n", point[0], point[1], point[2]);
SoSeparator* TransRoot = new SoSeparator();
n.pcTransform = new SoTransform();
TransRoot->addChild(n.pcTransform);
n.pcTransform->translation.setValue(point);
n.pcHighlight = new Gui::SoFCSelection();
SoSphere* sphere = new SoSphere;
sphere->radius = (float)pcLineStyle->pointSize.getValue();
n.pcHighlight->addChild(sphere);
TransRoot->addChild(n.pcHighlight);
VertexRoot->addChild(TransRoot);
NodeList.push_back(n);
return true;
}
}
else // if(pressd)..
{
if (bMovePointMode) {
bMovePointMode = false;
return true;
}
}
break;
}
}
// Mouse Movement handling
if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) {
// const SoLocation2Event * const event = (const SoLocation2Event *) ev;
if (bMovePointMode && Viewer.pickPoint(pos, point, norm)) {
PointToMove.pcTransform->translation.setValue(point);
return true;
}
}
// event not processed
return false;
}
Standard_Boolean ViewProviderCurveNet::computeEdges(SoSeparator* root, const TopoDS_Shape& myShape)
{
unsigned long ulNbOfPoints = 50;
TopExp_Explorer ex;
SoSeparator* EdgeRoot = new SoSeparator();
root->addChild(EdgeRoot);
EdgeRoot->addChild(pcLineStyle);
EdgeRoot->addChild(pcLineMaterial);
for (ex.Init(myShape, TopAbs_EDGE); ex.More(); ex.Next()) {
// get the shape and mesh it
const TopoDS_Edge& aEdge = TopoDS::Edge(ex.Current());
Standard_Real fBegin, fEnd;
SbVec3f* vertices = new SbVec3f[ulNbOfPoints];
Handle(Geom_Curve) hCurve = BRep_Tool::Curve(aEdge, fBegin, fEnd);
float fLen = float(fEnd - fBegin);
for (unsigned long i = 0; i < ulNbOfPoints; i++) {
gp_Pnt gpPt = hCurve->Value(fBegin + (fLen * float(i)) / float(ulNbOfPoints - 1));
vertices[i].setValue((float)(gpPt.X()), (float)(gpPt.Y()), (float)(gpPt.Z()));
}
// define vertices
SoCoordinate3* coords = new SoCoordinate3;
coords->point.setValues(0, ulNbOfPoints, vertices);
EdgeRoot->addChild(coords);
// define the indexed face set
SoLocateHighlight* h = new SoLocateHighlight();
h->color.setValue((float)0.2, (float)0.5, (float)0.2);
SoLineSet* lineset = new SoLineSet;
h->addChild(lineset);
EdgeRoot->addChild(h);
}
return true;
}
Standard_Boolean ViewProviderCurveNet::computeVertices(SoSeparator* root, const TopoDS_Shape& myShape)
{
TopExp_Explorer ex;
SoSeparator* VertexRoot = new SoSeparator();
root->addChild(VertexRoot);
VertexRoot->addChild(pcPointMaterial);
SoComplexity* copl = new SoComplexity();
copl->value = (float)0.2;
VertexRoot->addChild(copl);
for (ex.Init(myShape, TopAbs_VERTEX); ex.More(); ex.Next()) {
// get the shape
const TopoDS_Vertex& aVertex = TopoDS::Vertex(ex.Current());
gp_Pnt gpPt = BRep_Tool::Pnt(aVertex);
SoSeparator* TransRoot = new SoSeparator();
SoTransform* Trans = new SoTransform();
TransRoot->addChild(Trans);
Trans->translation.setValue((float)(gpPt.X()), (float)(gpPt.Y()), (float)(gpPt.Z()));
SoLocateHighlight* h = new SoLocateHighlight();
h->color.setValue((float)0.2, (float)0.5, (float)0.2);
SoSphere* sphere = new SoSphere;
sphere->radius = (float)pcPointStyle->pointSize.getValue();
h->addChild(sphere);
TransRoot->addChild(h);
VertexRoot->addChild(TransRoot);
}
return true;
}