FreeCAD/src/Mod/MeshPart/Gui/Tessellation.cpp
2015-07-01 13:02:29 +02:00

369 lines
14 KiB
C++

/***************************************************************************
* Copyright (c) 2010 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 <TopExp_Explorer.hxx>
# include <QMessageBox>
#endif
#include "Tessellation.h"
#include "ui_Tessellation.h"
#include <Base/Console.h>
#include <Base/Exception.h>
#include <App/Application.h>
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Selection.h>
#include <Gui/ViewProvider.h>
#include <Gui/WaitCursor.h>
#include <Mod/Part/App/PartFeature.h>
using namespace MeshPartGui;
/* TRANSLATOR MeshPartGui::Tessellation */
Tessellation::Tessellation(QWidget* parent)
: QWidget(parent), ui(new Ui_Tessellation)
{
ui->setupUi(this);
buttonGroup = new QButtonGroup(this);
buttonGroup->addButton(ui->radioButtonStandard, 0);
buttonGroup->addButton(ui->radioButtonMefisto, 1);
buttonGroup->addButton(ui->radioButtonNetgen, 2);
connect(buttonGroup, SIGNAL(buttonClicked(int)),
this, SLOT(meshingMethod(int)));
ui->spinSurfaceDeviation->setMaximum(INT_MAX);
ui->spinMaximumEdgeLength->setMaximum(INT_MAX);
// set the standard method
ui->radioButtonStandard->setChecked(true);
ui->comboFineness->setCurrentIndex(2);
on_comboFineness_currentIndexChanged(2);
#if !defined (HAVE_MEFISTO)
ui->radioButtonMefisto->setDisabled(true);
#else
ui->radioButtonMefisto->setChecked(true);
#endif
#if !defined (HAVE_NETGEN)
ui->radioButtonNetgen->setDisabled(true);
#else
ui->radioButtonNetgen->setChecked(true);
#endif
Gui::Command::doCommand(Gui::Command::Doc, "import Mesh");
try {
Gui::Command::doCommand(Gui::Command::Doc, "import MeshPart");
}
catch(...) {
ui->radioButtonNetgen->setDisabled(true);
ui->radioButtonMefisto->setDisabled(true);
ui->radioButtonStandard->setChecked(true);
}
meshingMethod(buttonGroup->checkedId());
findShapes();
}
Tessellation::~Tessellation()
{
}
void Tessellation::meshingMethod(int id)
{
ui->stackedWidget->setCurrentIndex(id);
}
void Tessellation::on_comboFineness_currentIndexChanged(int index)
{
if (index == 5) {
ui->doubleGrading->setEnabled(true);
ui->spinEdgeElements->setEnabled(true);
ui->spinCurvatureElements->setEnabled(true);
}
else {
ui->doubleGrading->setEnabled(false);
ui->spinEdgeElements->setEnabled(false);
ui->spinCurvatureElements->setEnabled(false);
}
switch (index) {
case 0: // Very coarse
ui->doubleGrading->setValue(0.7);
ui->spinEdgeElements->setValue(0.3);
ui->spinCurvatureElements->setValue(1.0);
break;
case 1: // Coarse
ui->doubleGrading->setValue(0.5);
ui->spinEdgeElements->setValue(0.5);
ui->spinCurvatureElements->setValue(1.5);
break;
case 2: // Moderate
ui->doubleGrading->setValue(0.3);
ui->spinEdgeElements->setValue(1.0);
ui->spinCurvatureElements->setValue(2.0);
break;
case 3: // Fine
ui->doubleGrading->setValue(0.2);
ui->spinEdgeElements->setValue(2.0);
ui->spinCurvatureElements->setValue(3.0);
break;
case 4: // Very fine
ui->doubleGrading->setValue(0.1);
ui->spinEdgeElements->setValue(3.0);
ui->spinCurvatureElements->setValue(5.0);
break;
default:
break;
}
}
void Tessellation::on_checkSecondOrder_toggled(bool on)
{
if (on)
ui->checkQuadDominated->setChecked(false);
}
void Tessellation::on_checkQuadDominated_toggled(bool on)
{
if (on)
ui->checkSecondOrder->setChecked(false);
}
void Tessellation::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
int index = ui->comboFineness->currentIndex();
ui->retranslateUi(this);
ui->comboFineness->setCurrentIndex(index);
}
QWidget::changeEvent(e);
}
void Tessellation::findShapes()
{
App::Document* activeDoc = App::GetApplication().getActiveDocument();
if (!activeDoc) return;
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
if (!activeGui) return;
this->document = QString::fromAscii(activeDoc->getName());
std::vector<Part::Feature*> objs = activeDoc->getObjectsOfType<Part::Feature>();
double edgeLen = 0;
bool foundSelection = false;
for (std::vector<Part::Feature*>::iterator it = objs.begin(); it!=objs.end(); ++it) {
const TopoDS_Shape& shape = (*it)->Shape.getValue();
if (shape.IsNull()) continue;
bool hasfaces = false;
TopExp_Explorer xp(shape,TopAbs_FACE);
while (xp.More()) {
hasfaces = true;
break;
}
if (hasfaces) {
Base::BoundBox3d bbox = (*it)->Shape.getBoundingBox();
edgeLen = std::max<double>(edgeLen, bbox.LengthX());
edgeLen = std::max<double>(edgeLen, bbox.LengthY());
edgeLen = std::max<double>(edgeLen, bbox.LengthZ());
QString label = QString::fromUtf8((*it)->Label.getValue());
QString name = QString::fromAscii((*it)->getNameInDocument());
QTreeWidgetItem* child = new QTreeWidgetItem();
child->setText(0, label);
child->setToolTip(0, label);
child->setData(0, Qt::UserRole, name);
Gui::ViewProvider* vp = activeGui->getViewProvider(*it);
if (vp) child->setIcon(0, vp->getIcon());
ui->treeWidget->addTopLevelItem(child);
if (Gui::Selection().isSelected(*it)) {
child->setSelected(true);
foundSelection = true;
}
}
}
ui->spinMaximumEdgeLength->setValue(edgeLen/10);
if (foundSelection)
ui->treeWidget->hide();
}
bool Tessellation::accept()
{
if (ui->treeWidget->selectedItems().isEmpty()) {
QMessageBox::critical(this, windowTitle(),
tr("Select a shape for meshing, first."));
return false;
}
App::Document* activeDoc = App::GetApplication().getDocument((const char*)this->document.toAscii());
if (!activeDoc) {
QMessageBox::critical(this, windowTitle(),
tr("No such document '%1'.").arg(this->document));
return false;
}
try {
QString shape, label;
Gui::WaitCursor wc;
int method = buttonGroup->checkedId();
activeDoc->openTransaction("Meshing");
QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems();
std::vector<Part::Feature*> shapes = Gui::Selection().getObjectsOfType<Part::Feature>();
for (QList<QTreeWidgetItem *>::iterator it = items.begin(); it != items.end(); ++it) {
shape = (*it)->data(0, Qt::UserRole).toString();
label = (*it)->text(0);
QString cmd;
if (method == 0) { // Standard
double devFace = ui->spinSurfaceDeviation->value();
cmd = QString::fromAscii(
"__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__mesh__.Mesh=Mesh.Mesh(__doc__.getObject(\"%2\").Shape.tessellate(%3))\n"
"__mesh__.Label=\"%4 (Meshed)\"\n"
"__mesh__.ViewObject.CreaseAngle=25.0\n"
"del __doc__, __mesh__\n")
.arg(this->document)
.arg(shape)
.arg(devFace)
.arg(label);
}
else if (method == 1) { // Mefisto
double maxEdge = ui->spinMaximumEdgeLength->value();
if (!ui->spinMaximumEdgeLength->isEnabled())
maxEdge = 0;
cmd = QString::fromAscii(
"__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,MaxLength=%3)\n"
"__mesh__.Label=\"%4 (Meshed)\"\n"
"__mesh__.ViewObject.CreaseAngle=25.0\n"
"del __doc__, __mesh__\n")
.arg(this->document)
.arg(shape)
.arg(maxEdge)
.arg(label);
}
else if (method == 2) { // Netgen
int fineness = ui->comboFineness->currentIndex();
double growthRate = ui->doubleGrading->value();
double nbSegPerEdge = ui->spinEdgeElements->value();
double nbSegPerRadius = ui->spinCurvatureElements->value();
bool secondOrder = ui->checkSecondOrder->isChecked();
bool optimize = ui->checkOptimizeSurface->isChecked();
bool allowquad = ui->checkQuadDominated->isChecked();
if (fineness < 5) {
cmd = QString::fromAscii(
"__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,"
"Fineness=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6)\n"
"__mesh__.Label=\"%7 (Meshed)\"\n"
"__mesh__.ViewObject.CreaseAngle=25.0\n"
"del __doc__, __mesh__\n")
.arg(this->document)
.arg(shape)
.arg(fineness)
.arg(secondOrder ? 1 : 0)
.arg(optimize ? 1 : 0)
.arg(allowquad ? 1 : 0)
.arg(label);
}
else {
cmd = QString::fromAscii(
"__doc__=FreeCAD.getDocument(\"%1\")\n"
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__doc__.getObject(\"%2\").Shape,"
"GrowthRate=%3,SegPerEdge=%4,SegPerRadius=%5,SecondOrder=%6,Optimize=%7,AllowQuad=%8)\n"
"__mesh__.Label=\"%9 (Meshed)\"\n"
"__mesh__.ViewObject.CreaseAngle=25.0\n"
"del __doc__, __mesh__\n")
.arg(this->document)
.arg(shape)
.arg(growthRate)
.arg(nbSegPerEdge)
.arg(nbSegPerRadius)
.arg(secondOrder ? 1 : 0)
.arg(optimize ? 1 : 0)
.arg(allowquad ? 1 : 0)
.arg(label);
}
}
Gui::Command::doCommand(Gui::Command::Doc, (const char*)cmd.toUtf8());
}
activeDoc->commitTransaction();
}
catch (const Base::Exception& e) {
Base::Console().Error(e.what());
}
return true;
}
// ---------------------------------------
TaskTessellation::TaskTessellation()
{
widget = new Tessellation();
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
QPixmap()/*Gui::BitmapFactory().pixmap("MeshPart_Mesher")*/,
widget->windowTitle(), true, 0);
taskbox->groupLayout()->addWidget(widget);
Content.push_back(taskbox);
}
TaskTessellation::~TaskTessellation()
{
// automatically deleted in the sub-class
}
void TaskTessellation::open()
{
}
void TaskTessellation::clicked(int)
{
}
bool TaskTessellation::accept()
{
return widget->accept();
}
bool TaskTessellation::reject()
{
return true;
}
#include "moc_Tessellation.cpp"