Merge pull request #704 from wwmayer/Curveonmesh

project polyline on mesh and create edge
This commit is contained in:
wwmayer
2017-04-20 07:32:38 +02:00
committed by GitHub
12 changed files with 1179 additions and 3 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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());
}

View 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"

View 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

View File

@@ -44,6 +44,7 @@
#endif
#ifdef _MSC_VER
# pragma warning(disable : 4005)
# pragma warning(disable : 4290)
# pragma warning(disable : 4275)
#endif

View 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"

View 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

View 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>

View File

@@ -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());
}

View File

@@ -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
}

View File

@@ -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";*/