Merge pull request #704 from wwmayer/Curveonmesh
project polyline on mesh and create edge
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include <Base/Console.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Language/Translator.h>
|
||||
#include "CurveOnMesh.h"
|
||||
#include "Workbench.h"
|
||||
|
||||
// use a different name to CreateCommand()
|
||||
@@ -79,7 +80,8 @@ PyMOD_INIT_FUNC(MeshPartGui)
|
||||
|
||||
// instantiating the commands
|
||||
CreateMeshPartCommands();
|
||||
MeshPartGui::Workbench::init();
|
||||
MeshPartGui::Workbench ::init();
|
||||
MeshPartGui::ViewProviderCurveOnMesh ::init();
|
||||
|
||||
// add resources and reloads the translators
|
||||
loadMeshPartResource();
|
||||
|
||||
@@ -33,12 +33,15 @@ set(MeshPartGui_LIBS
|
||||
)
|
||||
|
||||
set(MeshPartGui_MOC_HDRS
|
||||
CurveOnMesh.h
|
||||
TaskCurveOnMesh.h
|
||||
Tessellation.h
|
||||
)
|
||||
fc_wrap_cpp(MeshPartGui_MOC_SRCS ${MeshPartGui_MOC_HDRS})
|
||||
SOURCE_GROUP("Moc" FILES ${MeshPartGui_MOC_SRCS})
|
||||
|
||||
set(MeshPartGui_UIC_SRCS
|
||||
TaskCurveOnMesh.ui
|
||||
Tessellation.ui
|
||||
)
|
||||
|
||||
@@ -55,9 +58,14 @@ SET(MeshPartGui_SRCS
|
||||
${MeshPartGui_UIC_HDRS}
|
||||
AppMeshPartGui.cpp
|
||||
Command.cpp
|
||||
CurveOnMesh.cpp
|
||||
CurveOnMesh.h
|
||||
Resources/MeshPart.qrc
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
TaskCurveOnMesh.ui
|
||||
TaskCurveOnMesh.cpp
|
||||
TaskCurveOnMesh.h
|
||||
Tessellation.ui
|
||||
Tessellation.cpp
|
||||
Tessellation.h
|
||||
|
||||
@@ -29,12 +29,18 @@
|
||||
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/FileDialog.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include "Tessellation.h"
|
||||
#include "TaskCurveOnMesh.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -230,6 +236,43 @@ bool CmdMeshPartSection::isActive(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
DEF_STD_CMD_A(CmdMeshPartCurveOnMesh)
|
||||
|
||||
CmdMeshPartCurveOnMesh::CmdMeshPartCurveOnMesh()
|
||||
: Command("MeshPart_CurveOnMesh")
|
||||
{
|
||||
sAppModule = "MeshPart";
|
||||
sGroup = QT_TR_NOOP("Mesh");
|
||||
sMenuText = QT_TR_NOOP("Curve on mesh...");
|
||||
sToolTipText = QT_TR_NOOP("Curve on mesh");
|
||||
sWhatsThis = "MeshPart_CurveOnMesh";
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
||||
void CmdMeshPartCurveOnMesh::activated(int)
|
||||
{
|
||||
Gui::Document* doc = getActiveGuiDocument();
|
||||
std::list<Gui::MDIView*> mdis = doc->getMDIViewsOfType(Gui::View3DInventor::getClassTypeId());
|
||||
if (mdis.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::Control().showDialog(new MeshPartGui::TaskCurveOnMesh(static_cast<Gui::View3DInventor*>(mdis.front())));
|
||||
}
|
||||
|
||||
bool CmdMeshPartCurveOnMesh::isActive(void)
|
||||
{
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
|
||||
// Check for the selected mesh feature (all Mesh types)
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
if (doc && doc->countObjectsOfType(Mesh::Feature::getClassTypeId()) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CreateMeshPartCommands(void)
|
||||
{
|
||||
@@ -237,4 +280,5 @@ void CreateMeshPartCommands(void)
|
||||
rcCmdMgr.addCommand(new CmdMeshPartMesher());
|
||||
rcCmdMgr.addCommand(new CmdMeshPartTrimByPlane());
|
||||
rcCmdMgr.addCommand(new CmdMeshPartSection());
|
||||
rcCmdMgr.addCommand(new CmdMeshPartCurveOnMesh());
|
||||
}
|
||||
|
||||
616
src/Mod/MeshPart/Gui/CurveOnMesh.cpp
Normal file
616
src/Mod/MeshPart/Gui/CurveOnMesh.cpp
Normal file
@@ -0,0 +1,616 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2017 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <QMenu>
|
||||
# include <QPointer>
|
||||
# include <QStatusBar>
|
||||
# include <QTimer>
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/actions/SoSearchAction.h>
|
||||
# include <Inventor/details/SoFaceDetail.h>
|
||||
# include <Inventor/details/SoLineDetail.h>
|
||||
# include <Inventor/details/SoPointDetail.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoDrawStyle.h>
|
||||
# include <Inventor/nodes/SoPickStyle.h>
|
||||
# include <Inventor/nodes/SoLineSet.h>
|
||||
# include <Inventor/nodes/SoPointSet.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
#endif
|
||||
|
||||
#include "CurveOnMesh.h"
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/Utilities.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Mod/Mesh/App/Core/Algorithm.h>
|
||||
#include <Mod/Mesh/App/Core/Grid.h>
|
||||
#include <Mod/Mesh/App/Core/MeshKernel.h>
|
||||
#include <Mod/Mesh/App/Core/Projection.h>
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
#include <Mod/Mesh/Gui/ViewProvider.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
#ifndef HAVE_ACOSH
|
||||
#define HAVE_ACOSH
|
||||
#endif
|
||||
#ifndef HAVE_ASINH
|
||||
#define HAVE_ASINH
|
||||
#endif
|
||||
#ifndef HAVE_ATANH
|
||||
#define HAVE_ATANH
|
||||
#endif
|
||||
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <TColgp_Array1OfPnt.hxx>
|
||||
#include <GeomAPI_PointsToBSpline.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <Poly_Polygon3D.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
|
||||
/* XPM */
|
||||
static const char *cursor_curveonmesh[]={
|
||||
"32 32 3 1",
|
||||
"+ c white",
|
||||
"# c red",
|
||||
". c None",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"......+.........................",
|
||||
"................................",
|
||||
"+++++...+++++...................",
|
||||
"................................",
|
||||
"......+...............###.......",
|
||||
"......+...............#.#.......",
|
||||
"......+...............###.......",
|
||||
"......+..............#..#.......",
|
||||
"......+.............#....#......",
|
||||
"....................#.+..#......",
|
||||
"..................+#+..+..#...+.",
|
||||
"................++#.....+.#..+..",
|
||||
"......+........+..#......++#+...",
|
||||
".......+......+..#.........#....",
|
||||
"........++..++..#..........###..",
|
||||
"..........++....#..........#.#..",
|
||||
"......#........#...........###..",
|
||||
".......#......#.................",
|
||||
"........#.....#.................",
|
||||
".........#...#..................",
|
||||
"..........###...................",
|
||||
"..........#.#...................",
|
||||
"..........###...................",
|
||||
"................................",
|
||||
"................................",
|
||||
"................................",
|
||||
"................................",
|
||||
"................................"};
|
||||
|
||||
using namespace MeshPartGui;
|
||||
|
||||
PROPERTY_SOURCE(MeshPartGui::ViewProviderCurveOnMesh, Gui::ViewProviderDocumentObject)
|
||||
|
||||
ViewProviderCurveOnMesh::ViewProviderCurveOnMesh()
|
||||
{
|
||||
// the lines
|
||||
pcCoords = new SoCoordinate3;
|
||||
pcCoords->ref();
|
||||
pcCoords->point.setNum(0);
|
||||
|
||||
pcLinesStyle = new SoDrawStyle;
|
||||
pcLinesStyle->style = SoDrawStyle::LINES;
|
||||
pcLinesStyle->lineWidth = 3;
|
||||
pcLinesStyle->ref();
|
||||
|
||||
SoGroup* pcLineRoot = new SoSeparator();
|
||||
pcLineRoot->addChild(pcLinesStyle);
|
||||
SoBaseColor * linecol = new SoBaseColor;
|
||||
linecol->rgb.setValue(1.0f, 1.0f, 0.0f);
|
||||
pcLineRoot->addChild(linecol);
|
||||
pcLineRoot->addChild(pcCoords);
|
||||
pcLineRoot->addChild(new SoLineSet);
|
||||
|
||||
// the nodes
|
||||
pcNodes = new SoCoordinate3;
|
||||
pcNodes->ref();
|
||||
pcNodes->point.setNum(0);
|
||||
|
||||
pcPointStyle = new SoDrawStyle;
|
||||
pcPointStyle->style = SoDrawStyle::POINTS;
|
||||
pcPointStyle->pointSize = 15;
|
||||
pcPointStyle->ref();
|
||||
|
||||
SoGroup* pcPointRoot = new SoSeparator();
|
||||
pcPointRoot->addChild(pcPointStyle);
|
||||
SoBaseColor * pointcol = new SoBaseColor;
|
||||
pointcol->rgb.setValue(1.0f, 0.5f, 0.0f);
|
||||
pcPointRoot->addChild(pointcol);
|
||||
pcPointRoot->addChild(pcNodes);
|
||||
pcPointRoot->addChild(new SoPointSet);
|
||||
|
||||
SoGroup* group = new SoGroup;
|
||||
group->addChild(pcLineRoot);
|
||||
group->addChild(pcPointRoot);
|
||||
addDisplayMaskMode(group, "Point");
|
||||
}
|
||||
|
||||
ViewProviderCurveOnMesh::~ViewProviderCurveOnMesh()
|
||||
{
|
||||
pcCoords->unref();
|
||||
pcLinesStyle->unref();
|
||||
pcNodes->unref();
|
||||
pcPointStyle->unref();
|
||||
}
|
||||
|
||||
void ViewProviderCurveOnMesh::setDisplayMode(const char* ModeName)
|
||||
{
|
||||
setDisplayMaskMode(ModeName);
|
||||
ViewProviderDocumentObject::setDisplayMode(ModeName);
|
||||
}
|
||||
|
||||
void ViewProviderCurveOnMesh::addVertex(const SbVec3f& v)
|
||||
{
|
||||
int num = pcNodes->point.getNum();
|
||||
pcNodes->point.set1Value(num, v);
|
||||
}
|
||||
|
||||
void ViewProviderCurveOnMesh::clearVertex()
|
||||
{
|
||||
pcNodes->point.setNum(0);
|
||||
}
|
||||
|
||||
void ViewProviderCurveOnMesh::setPoints(const std::vector<SbVec3f>& pts)
|
||||
{
|
||||
pcCoords->point.setNum(pts.size());
|
||||
SbVec3f* coords = pcCoords->point.startEditing();
|
||||
int index = 0;
|
||||
for (std::vector<SbVec3f>::const_iterator it = pts.begin(); it != pts.end(); ++it) {
|
||||
coords[index] = *it;
|
||||
index++;
|
||||
}
|
||||
pcCoords->point.finishEditing();
|
||||
}
|
||||
|
||||
void ViewProviderCurveOnMesh::clearPoints()
|
||||
{
|
||||
pcCoords->point.setNum(0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
class CurveOnMeshHandler::Private
|
||||
{
|
||||
public:
|
||||
struct PickedPoint
|
||||
{
|
||||
unsigned long facet;
|
||||
SbVec3f point;
|
||||
SbVec3f normal;
|
||||
};
|
||||
|
||||
struct ApproxPar
|
||||
{
|
||||
double weight1;
|
||||
double weight2;
|
||||
double weight3;
|
||||
double tol3d;
|
||||
int maxDegree;
|
||||
GeomAbs_Shape cont;
|
||||
|
||||
ApproxPar() {
|
||||
weight1 = 0.2;
|
||||
weight2 = 0.4;
|
||||
weight3 = 0.2;
|
||||
tol3d = 1.0e-2;
|
||||
maxDegree = 5;
|
||||
cont = GeomAbs_C2;
|
||||
}
|
||||
};
|
||||
Private()
|
||||
: wireClosed(false)
|
||||
, distance(1.0)
|
||||
, cosAngle(0.7071) // 45 degree
|
||||
, curve(new ViewProviderCurveOnMesh)
|
||||
, mesh(0)
|
||||
, grid(0)
|
||||
, kernel(0)
|
||||
, viewer(0)
|
||||
, editcursor(QPixmap(cursor_curveonmesh), 7, 7)
|
||||
{
|
||||
}
|
||||
~Private()
|
||||
{
|
||||
delete curve;
|
||||
delete grid;
|
||||
}
|
||||
static void vertexCallback(void * ud, SoEventCallback * n);
|
||||
std::vector<SbVec3f> convert(const std::vector<Base::Vector3f>& points) const
|
||||
{
|
||||
std::vector<SbVec3f> pts;
|
||||
pts.reserve(points.size());
|
||||
for (auto it = points.begin(); it != points.end(); ++it) {
|
||||
pts.push_back(Base::convertTo<SbVec3f>(*it));
|
||||
}
|
||||
return pts;
|
||||
}
|
||||
void createGrid()
|
||||
{
|
||||
Mesh::Feature* mf = static_cast<Mesh::Feature*>(mesh->getObject());
|
||||
const Mesh::MeshObject& meshObject = mf->Mesh.getValue();
|
||||
MeshCore::MeshAlgorithm alg(meshObject.getKernel());
|
||||
float fAvgLen = alg.GetAverageEdgeLength();
|
||||
grid = new MeshCore::MeshFacetGrid(meshObject.getKernel(), 5.0f * fAvgLen);
|
||||
kernel = &meshObject;
|
||||
}
|
||||
bool projectLineOnMesh(const PickedPoint& pick)
|
||||
{
|
||||
PickedPoint last = pickedPoints.back();
|
||||
std::vector<Base::Vector3f> polyline;
|
||||
|
||||
MeshCore::MeshProjection meshProjection(kernel->getKernel());
|
||||
Base::Vector3f v1 = Base::convertTo<Base::Vector3f>(last.point);
|
||||
Base::Vector3f v2 = Base::convertTo<Base::Vector3f>(pick.point);
|
||||
Base::Vector3f vd = Base::convertTo<Base::Vector3f>(viewer->getViewer()->getViewDirection());
|
||||
if (meshProjection.projectLineOnMesh(*grid, v1, last.facet, v2, pick.facet, vd, polyline)) {
|
||||
if (polyline.size() > 1) {
|
||||
if (cutLines.empty()) {
|
||||
cutLines.push_back(polyline);
|
||||
}
|
||||
else {
|
||||
SbVec3f dir1;
|
||||
SbVec3f dir2 = pick.point - last.point;
|
||||
dir2.normalize();
|
||||
std::size_t num = pickedPoints.size();
|
||||
if (num >= 2) {
|
||||
dir1 = pickedPoints[num-1].point - pickedPoints[num-2].point;
|
||||
dir1.normalize();
|
||||
}
|
||||
|
||||
// if the angle between two line segments is greater than the angle
|
||||
// split the curve in this position
|
||||
if (dir1.dot(dir2) < cosAngle) {
|
||||
cutLines.push_back(polyline);
|
||||
}
|
||||
else {
|
||||
std::vector<Base::Vector3f>& segm = cutLines.back();
|
||||
segm.insert(segm.end(), polyline.begin()+1, polyline.end());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<PickedPoint> pickedPoints;
|
||||
std::list<std::vector<Base::Vector3f> > cutLines;
|
||||
bool wireClosed;
|
||||
double distance;
|
||||
double cosAngle;
|
||||
ViewProviderCurveOnMesh* curve;
|
||||
Gui::ViewProviderDocumentObject* mesh;
|
||||
MeshCore::MeshFacetGrid* grid;
|
||||
Base::Reference<const Mesh::MeshObject> kernel;
|
||||
QPointer<Gui::View3DInventor> viewer;
|
||||
QCursor editcursor;
|
||||
ApproxPar par;
|
||||
};
|
||||
|
||||
CurveOnMeshHandler::CurveOnMeshHandler(QObject* parent)
|
||||
: QObject(parent), d_ptr(new Private)
|
||||
{
|
||||
}
|
||||
|
||||
CurveOnMeshHandler::~CurveOnMeshHandler()
|
||||
{
|
||||
disableCallback();
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::setParameters(int maxDegree, GeomAbs_Shape cont, double tol3d, double angle)
|
||||
{
|
||||
d_ptr->par.maxDegree = maxDegree;
|
||||
d_ptr->par.cont = cont;
|
||||
d_ptr->par.tol3d = tol3d;
|
||||
d_ptr->cosAngle = cos(angle);
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::onContextMenu()
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Create"), this, SLOT(onCreate()));
|
||||
if (!d_ptr->wireClosed && d_ptr->pickedPoints.size() >= 3) {
|
||||
menu.addAction(tr("Close wire"), this, SLOT(onCloseWire()));
|
||||
}
|
||||
menu.addAction(tr("Clear"), this, SLOT(onClear()));
|
||||
menu.addAction(tr("Cancel"), this, SLOT(onCancel()));
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::onCreate()
|
||||
{
|
||||
for (auto it = d_ptr->cutLines.begin(); it != d_ptr->cutLines.end(); ++it) {
|
||||
std::vector<SbVec3f> segm = d_ptr->convert(*it);
|
||||
Handle(Geom_BSplineCurve) spline = approximateSpline(segm);
|
||||
if (!spline.IsNull())
|
||||
displaySpline(spline);
|
||||
}
|
||||
|
||||
d_ptr->curve->clearVertex();
|
||||
d_ptr->curve->clearPoints();
|
||||
|
||||
d_ptr->pickedPoints.clear();
|
||||
d_ptr->cutLines.clear();
|
||||
d_ptr->wireClosed = false;
|
||||
|
||||
disableCallback();
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::onCloseWire()
|
||||
{
|
||||
if (d_ptr->wireClosed || d_ptr->pickedPoints.size() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
closeWire();
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::onClear()
|
||||
{
|
||||
d_ptr->curve->clearVertex();
|
||||
d_ptr->curve->clearPoints();
|
||||
|
||||
d_ptr->pickedPoints.clear();
|
||||
d_ptr->cutLines.clear();
|
||||
d_ptr->wireClosed = false;
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::onCancel()
|
||||
{
|
||||
d_ptr->curve->clearVertex();
|
||||
d_ptr->curve->clearPoints();
|
||||
|
||||
d_ptr->pickedPoints.clear();
|
||||
d_ptr->cutLines.clear();
|
||||
d_ptr->wireClosed = false;
|
||||
|
||||
disableCallback();
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::enableCallback(Gui::View3DInventor* v)
|
||||
{
|
||||
if (v && !d_ptr->viewer) {
|
||||
d_ptr->viewer = v;
|
||||
Gui::View3DInventorViewer* view3d = d_ptr->viewer->getViewer();
|
||||
view3d->addEventCallback(SoEvent::getClassTypeId(), Private::vertexCallback, this);
|
||||
view3d->addViewProvider(d_ptr->curve);
|
||||
view3d->setEditing(true);
|
||||
|
||||
view3d->setEditingCursor(d_ptr->editcursor);
|
||||
|
||||
d_ptr->curve->setDisplayMode("Point");
|
||||
}
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::disableCallback()
|
||||
{
|
||||
if (d_ptr->viewer) {
|
||||
Gui::View3DInventorViewer* view3d = d_ptr->viewer->getViewer();
|
||||
view3d->setEditing(false);
|
||||
view3d->removeViewProvider(d_ptr->curve);
|
||||
view3d->removeEventCallback(SoEvent::getClassTypeId(), Private::vertexCallback, this);
|
||||
}
|
||||
d_ptr->viewer = 0;
|
||||
}
|
||||
|
||||
std::vector<SbVec3f> CurveOnMeshHandler::getVertexes() const
|
||||
{
|
||||
std::vector<SbVec3f> pts;
|
||||
pts.reserve(d_ptr->pickedPoints.size());
|
||||
for (std::vector<Private::PickedPoint>::const_iterator it = d_ptr->pickedPoints.begin(); it != d_ptr->pickedPoints.end(); ++it)
|
||||
pts.push_back(it->point);
|
||||
return pts;
|
||||
}
|
||||
|
||||
std::vector<SbVec3f> CurveOnMeshHandler::getPoints() const
|
||||
{
|
||||
std::vector<SbVec3f> pts;
|
||||
for (auto it = d_ptr->cutLines.begin(); it != d_ptr->cutLines.end(); ++it) {
|
||||
std::vector<SbVec3f> segm = d_ptr->convert(*it);
|
||||
pts.insert(pts.end(), segm.begin(), segm.end());
|
||||
}
|
||||
return pts;
|
||||
}
|
||||
|
||||
Handle(Geom_BSplineCurve) CurveOnMeshHandler::approximateSpline(const std::vector<SbVec3f>& points)
|
||||
{
|
||||
TColgp_Array1OfPnt pnts(1,points.size());
|
||||
Standard_Integer index = 1;
|
||||
for (std::vector<SbVec3f>::const_iterator it = points.begin(); it != points.end(); ++it) {
|
||||
float x,y,z;
|
||||
it->getValue(x,y,z);
|
||||
pnts(index++) = gp_Pnt(x,y,z);
|
||||
}
|
||||
|
||||
try {
|
||||
//GeomAPI_PointsToBSpline fit(pnts, 1, 2, GeomAbs_C0, 1.0e-3);
|
||||
//GeomAPI_PointsToBSpline fit(pnts, d_ptr->par.weight1, d_ptr->par.weight2, d_ptr->par.weight3,
|
||||
// d_ptr->par.maxDegree, d_ptr->par.cont, d_ptr->par.tol3d);
|
||||
GeomAPI_PointsToBSpline fit(pnts, 1, d_ptr->par.maxDegree, d_ptr->par.cont, d_ptr->par.tol3d);
|
||||
Handle(Geom_BSplineCurve) spline = fit.Curve();
|
||||
return spline;
|
||||
}
|
||||
catch (...) {
|
||||
return Handle(Geom_BSplineCurve)();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::approximateEdge(const TopoDS_Edge& edge, double tolerance)
|
||||
{
|
||||
BRepMesh_IncrementalMesh(edge, tolerance);
|
||||
TopLoc_Location loc;
|
||||
Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(edge, loc);
|
||||
if (!aPoly.IsNull()) {
|
||||
int numNodes = aPoly->NbNodes();
|
||||
const TColgp_Array1OfPnt& aNodes = aPoly->Nodes();
|
||||
std::vector<SbVec3f> pts;
|
||||
pts.reserve(numNodes);
|
||||
for (int i=aNodes.Lower(); i<=aNodes.Upper(); i++) {
|
||||
const gp_Pnt& p = aNodes.Value(i);
|
||||
pts.push_back(SbVec3f(static_cast<float>(p.X()),
|
||||
static_cast<float>(p.Y()),
|
||||
static_cast<float>(p.Z())));
|
||||
}
|
||||
|
||||
d_ptr->curve->setPoints(pts);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::displaySpline(const Handle(Geom_BSplineCurve)& spline)
|
||||
{
|
||||
if (d_ptr->viewer) {
|
||||
double u = spline->FirstParameter();
|
||||
double v = spline->LastParameter();
|
||||
BRepBuilderAPI_MakeEdge mkBuilder(spline, u, v);
|
||||
TopoDS_Edge edge = mkBuilder.Edge();
|
||||
|
||||
Gui::View3DInventorViewer* view3d = d_ptr->viewer->getViewer();
|
||||
App::Document* doc = view3d->getDocument()->getDocument();
|
||||
Part::Feature* part = static_cast<Part::Feature*>(doc->addObject("Part::Spline", "Spline"));
|
||||
part->Shape.setValue(edge);
|
||||
}
|
||||
}
|
||||
|
||||
bool CurveOnMeshHandler::tryCloseWire(const SbVec3f& p) const
|
||||
{
|
||||
if (d_ptr->pickedPoints.size() >= 3) {
|
||||
Private::PickedPoint first = d_ptr->pickedPoints.front();
|
||||
// if the distance of the first and last points is small enough (~1mm)
|
||||
// the curve can be closed.
|
||||
float len = (first.point - p).length();
|
||||
if (len < d_ptr->distance) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::closeWire()
|
||||
{
|
||||
Private::PickedPoint pick = d_ptr->pickedPoints.front();
|
||||
if (d_ptr->projectLineOnMesh(pick)) {
|
||||
d_ptr->curve->setPoints(getPoints());
|
||||
d_ptr->wireClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveOnMeshHandler::Private::vertexCallback(void * ud, SoEventCallback * n)
|
||||
{
|
||||
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
|
||||
const SoEvent* ev = n->getEvent();
|
||||
if (ev->getTypeId() == SoMouseButtonEvent::getClassTypeId()) {
|
||||
// set as handled
|
||||
n->setHandled();
|
||||
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ev);
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
|
||||
const SoPickedPoint * pp = n->getPickedPoint();
|
||||
if (pp) {
|
||||
CurveOnMeshHandler* self = static_cast<CurveOnMeshHandler*>(ud);
|
||||
if (!self->d_ptr->wireClosed) {
|
||||
Gui::ViewProvider* vp = static_cast<Gui::ViewProvider*>(view->getViewProviderByPath(pp->getPath()));
|
||||
if (vp && vp->getTypeId().isDerivedFrom(MeshGui::ViewProviderMesh::getClassTypeId())) {
|
||||
MeshGui::ViewProviderMesh* mesh = static_cast<MeshGui::ViewProviderMesh*>(vp);
|
||||
const SoDetail* detail = pp->getDetail();
|
||||
if (detail && detail->getTypeId() == SoFaceDetail::getClassTypeId()) {
|
||||
// get the mesh and build a grid
|
||||
if (!self->d_ptr->mesh) {
|
||||
self->d_ptr->mesh = mesh;
|
||||
self->d_ptr->createGrid();
|
||||
}
|
||||
else if (self->d_ptr->mesh != mesh) {
|
||||
Gui::getMainWindow()->statusBar()->showMessage(
|
||||
tr("Wrong mesh picked"));
|
||||
return;
|
||||
}
|
||||
|
||||
const SbVec3f& p = pp->getPoint();
|
||||
const SbVec3f& n = pp->getNormal();
|
||||
|
||||
Private::PickedPoint pick;
|
||||
pick.facet = static_cast<const SoFaceDetail*>(detail)->getFaceIndex();
|
||||
pick.point = p;
|
||||
pick.normal = n;
|
||||
|
||||
if (self->d_ptr->pickedPoints.empty()) {
|
||||
self->d_ptr->pickedPoints.push_back(pick);
|
||||
self->d_ptr->curve->addVertex(p);
|
||||
}
|
||||
else {
|
||||
// check to auto-complete the curve
|
||||
if (self->tryCloseWire(p)) {
|
||||
self->closeWire();
|
||||
}
|
||||
else if (self->d_ptr->projectLineOnMesh(pick)) {
|
||||
self->d_ptr->curve->setPoints(self->getPoints());
|
||||
self->d_ptr->pickedPoints.push_back(pick);
|
||||
self->d_ptr->curve->addVertex(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// try to 'complete' the curve
|
||||
else if (vp && vp->getTypeId().isDerivedFrom(ViewProviderCurveOnMesh::getClassTypeId())) {
|
||||
const SbVec3f& p = pp->getPoint();
|
||||
if (self->tryCloseWire(p)) {
|
||||
self->closeWire();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Gui::getMainWindow()->statusBar()->showMessage(
|
||||
tr("No point was picked"));
|
||||
}
|
||||
}
|
||||
else if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) {
|
||||
CurveOnMeshHandler* self = static_cast<CurveOnMeshHandler*>(ud);
|
||||
QTimer::singleShot(100, self, SLOT(onContextMenu()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_CurveOnMesh.cpp"
|
||||
99
src/Mod/MeshPart/Gui/CurveOnMesh.h
Normal file
99
src/Mod/MeshPart/Gui/CurveOnMesh.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2017 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MESHPARTGUI_CURVEONMESH_H
|
||||
#define MESHPARTGUI_CURVEONMESH_H
|
||||
|
||||
#include <QObject>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <GeomAbs_Shape.hxx>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
#include <memory>
|
||||
|
||||
class SbVec3f;
|
||||
class SoCoordinate3;
|
||||
class SoDrawStyle;
|
||||
class TopoDS_Edge;
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventor;
|
||||
class ViewProvider;
|
||||
}
|
||||
|
||||
namespace MeshPartGui
|
||||
{
|
||||
|
||||
class ViewProviderCurveOnMesh : public Gui::ViewProviderDocumentObject
|
||||
{
|
||||
PROPERTY_HEADER(MeshPartGui::ViewProviderCurveOnMesh);
|
||||
|
||||
public:
|
||||
ViewProviderCurveOnMesh();
|
||||
virtual ~ViewProviderCurveOnMesh();
|
||||
void addVertex(const SbVec3f&);
|
||||
void clearVertex();
|
||||
void setPoints(const std::vector<SbVec3f>&);
|
||||
void clearPoints();
|
||||
void setDisplayMode(const char* ModeName);
|
||||
|
||||
private:
|
||||
SoCoordinate3 * pcCoords;
|
||||
SoCoordinate3 * pcNodes;
|
||||
SoDrawStyle * pcPointStyle;
|
||||
SoDrawStyle * pcLinesStyle;
|
||||
};
|
||||
|
||||
class CurveOnMeshHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CurveOnMeshHandler(QObject* parent = 0);
|
||||
~CurveOnMeshHandler();
|
||||
void setParameters(int maxDegree, GeomAbs_Shape cont, double tol3d, double angle);
|
||||
void enableCallback(Gui::View3DInventor* viewer);
|
||||
void disableCallback();
|
||||
|
||||
private:
|
||||
Handle(Geom_BSplineCurve) approximateSpline(const std::vector<SbVec3f>& points);
|
||||
void approximateEdge(const TopoDS_Edge&, double tolerance);
|
||||
void displaySpline(const Handle(Geom_BSplineCurve)&);
|
||||
std::vector<SbVec3f> getPoints() const;
|
||||
std::vector<SbVec3f> getVertexes() const;
|
||||
void closeWire();
|
||||
bool tryCloseWire(const SbVec3f&) const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onContextMenu();
|
||||
void onCreate();
|
||||
void onClear();
|
||||
void onCancel();
|
||||
void onCloseWire();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d_ptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MESHPARTGUI_CURVEONMESH_H
|
||||
@@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable : 4005)
|
||||
# pragma warning(disable : 4290)
|
||||
# pragma warning(disable : 4275)
|
||||
#endif
|
||||
|
||||
118
src/Mod/MeshPart/Gui/TaskCurveOnMesh.cpp
Normal file
118
src/Mod/MeshPart/Gui/TaskCurveOnMesh.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2017 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 "PreCompiled.h"
|
||||
|
||||
|
||||
#include "TaskCurveOnMesh.h"
|
||||
#include "ui_TaskCurveOnMesh.h"
|
||||
#include "CurveOnMesh.h"
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
||||
|
||||
using namespace MeshPartGui;
|
||||
|
||||
CurveOnMeshWidget::CurveOnMeshWidget(Gui::View3DInventor* view, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui_TaskCurveOnMesh())
|
||||
, myCurveHandler(new CurveOnMeshHandler(this))
|
||||
, myView(view)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setup();
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroys the object and frees any allocated resources
|
||||
*/
|
||||
CurveOnMeshWidget::~CurveOnMeshWidget()
|
||||
{
|
||||
// no need to delete child widgets, Qt does it all for us
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CurveOnMeshWidget::setup()
|
||||
{
|
||||
ui->meshTolerance->setValue(0.2);
|
||||
ui->continuity->addItem(QString::fromLatin1("C0"), static_cast<int>(GeomAbs_C0));
|
||||
ui->continuity->addItem(QString::fromLatin1("C1"), static_cast<int>(GeomAbs_C1));
|
||||
ui->continuity->addItem(QString::fromLatin1("C2"), static_cast<int>(GeomAbs_C2));
|
||||
ui->continuity->addItem(QString::fromLatin1("C3"), static_cast<int>(GeomAbs_C3));
|
||||
ui->continuity->setCurrentIndex(2);
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
ui->maxDegree->addItem(QString::number(i+1));
|
||||
ui->maxDegree->setCurrentIndex(4);
|
||||
}
|
||||
|
||||
void CurveOnMeshWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
else {
|
||||
QWidget::changeEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveOnMeshWidget::on_startButton_clicked()
|
||||
{
|
||||
int cont = ui->continuity->itemData(ui->continuity->currentIndex()).toInt();
|
||||
myCurveHandler->setParameters(ui->maxDegree->currentIndex(),
|
||||
static_cast<GeomAbs_Shape>(cont),
|
||||
ui->meshTolerance->value(),
|
||||
ui->splitAngle->value().getValue());
|
||||
myCurveHandler->enableCallback(myView);
|
||||
}
|
||||
|
||||
void CurveOnMeshWidget::reject()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TaskCurveOnMesh::TaskCurveOnMesh(Gui::View3DInventor* view)
|
||||
{
|
||||
widget = new CurveOnMeshWidget(view);
|
||||
taskbox = new Gui::TaskView::TaskBox(
|
||||
QPixmap(),
|
||||
widget->windowTitle(), true, 0);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskCurveOnMesh::~TaskCurveOnMesh()
|
||||
{
|
||||
// automatically deleted in the sub-class
|
||||
}
|
||||
|
||||
bool TaskCurveOnMesh::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "moc_TaskCurveOnMesh.cpp"
|
||||
84
src/Mod/MeshPart/Gui/TaskCurveOnMesh.h
Normal file
84
src/Mod/MeshPart/Gui/TaskCurveOnMesh.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2017 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MESHPART_GUI_TASKCURVEONMESH_H
|
||||
#define MESHPART_GUI_TASKCURVEONMESH_H
|
||||
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
#include <QPointer>
|
||||
|
||||
namespace Gui {
|
||||
class View3DInventor;
|
||||
}
|
||||
|
||||
namespace MeshPartGui
|
||||
{
|
||||
|
||||
class Ui_TaskCurveOnMesh;
|
||||
class CurveOnMeshHandler;
|
||||
|
||||
class CurveOnMeshWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CurveOnMeshWidget(Gui::View3DInventor* view, QWidget* parent=0);
|
||||
~CurveOnMeshWidget();
|
||||
|
||||
void reject();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
void setup();
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_startButton_clicked();
|
||||
|
||||
private:
|
||||
Ui_TaskCurveOnMesh* ui;
|
||||
CurveOnMeshHandler* myCurveHandler;
|
||||
QPointer<Gui::View3DInventor> myView;
|
||||
};
|
||||
|
||||
class TaskCurveOnMesh : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TaskCurveOnMesh(Gui::View3DInventor* view);
|
||||
~TaskCurveOnMesh();
|
||||
|
||||
public:
|
||||
bool reject();
|
||||
|
||||
virtual QDialogButtonBox::StandardButtons getStandardButtons() const
|
||||
{ return QDialogButtonBox::Close; }
|
||||
|
||||
private:
|
||||
CurveOnMeshWidget* widget;
|
||||
Gui::TaskView::TaskBox* taskbox;
|
||||
};
|
||||
|
||||
} //namespace MeshPartGui
|
||||
|
||||
#endif // MESHPART_GUI_TASKCURVEONMESH_H
|
||||
168
src/Mod/MeshPart/Gui/TaskCurveOnMesh.ui
Normal file
168
src/Mod/MeshPart/Gui/TaskCurveOnMesh.ui
Normal file
@@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MeshPartGui::TaskCurveOnMesh</class>
|
||||
<widget class="QWidget" name="MeshPartGui::TaskCurveOnMesh">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>313</width>
|
||||
<height>247</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Curve on mesh</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Wire</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Snap tolerance to vertexes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox">
|
||||
<property name="suffix">
|
||||
<string> px</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Split threshold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="splitAngle">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">deg</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>45.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Spline Approximation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Tolerance to mesh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="meshTolerance">
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Continuity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Maximum curve degree</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="maxDegree">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="continuity">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="startButton">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>211</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>spinBox</tabstop>
|
||||
<tabstop>splitAngle</tabstop>
|
||||
<tabstop>meshTolerance</tabstop>
|
||||
<tabstop>continuity</tabstop>
|
||||
<tabstop>maxDegree</tabstop>
|
||||
<tabstop>startButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -180,10 +180,45 @@ void CmdSurfaceGeomFillSurface::activated(int iMsg)
|
||||
doCommand(Doc, "Gui.ActiveDocument.setEdit('%s',0)", FeatName.c_str());
|
||||
}
|
||||
|
||||
|
||||
DEF_STD_CMD_A(CmdSurfaceCurveOnMesh)
|
||||
|
||||
CmdSurfaceCurveOnMesh::CmdSurfaceCurveOnMesh()
|
||||
: Command("Surface_CurveOnMesh")
|
||||
{
|
||||
sAppModule = "MeshPart";
|
||||
sGroup = QT_TR_NOOP("Surface");
|
||||
sMenuText = QT_TR_NOOP("Curve on mesh...");
|
||||
sToolTipText = QT_TR_NOOP("Curve on mesh");
|
||||
sWhatsThis = "Surface_CurveOnMesh";
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
||||
void CmdSurfaceCurveOnMesh::activated(int)
|
||||
{
|
||||
doCommand(Doc,"import MeshPartGui, FreeCADGui\n"
|
||||
"FreeCADGui.runCommand('MeshPart_CurveOnMesh')\n");
|
||||
}
|
||||
|
||||
bool CmdSurfaceCurveOnMesh::isActive(void)
|
||||
{
|
||||
if (Gui::Control().activeDialog())
|
||||
return false;
|
||||
|
||||
// Check for the selected mesh feature (all Mesh types)
|
||||
Base::Type meshType = Base::Type::fromName("Mesh::Feature");
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
if (doc && doc->countObjectsOfType(meshType) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CreateSurfaceCommands(void)
|
||||
{
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
/* rcCmdMgr.addCommand(new CmdSurfaceFilling());
|
||||
rcCmdMgr.addCommand(new CmdSurfaceCut());*/
|
||||
rcCmdMgr.addCommand(new CmdSurfaceGeomFillSurface());
|
||||
rcCmdMgr.addCommand(new CmdSurfaceCurveOnMesh());
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ void ViewProviderGeomFillSurface::highlightReferences(bool on)
|
||||
|
||||
for (auto jt : it.second) {
|
||||
std::size_t idx = static_cast<std::size_t>(std::stoi(jt.substr(4)) - 1);
|
||||
assert (idx >= 0 && idx < colors.size());
|
||||
assert (idx < colors.size());
|
||||
colors[idx] = App::Color(1.0,0.0,1.0); // magenta
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
Gui::MenuItem* surface = new Gui::MenuItem;
|
||||
root->insertItem( item, surface );
|
||||
surface->setCommand("Surface");
|
||||
*surface << "Surface_GeomFillSurface";
|
||||
*surface << "Surface_CurveOnMesh"
|
||||
<< "Surface_GeomFillSurface";
|
||||
/* *surface << "Surface_Filling";
|
||||
*surface << "Surface_Cut";*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user