MeshPart: support link in Tessellation
This commit is contained in:
@@ -94,7 +94,7 @@ Tessellation::Tessellation(QWidget* parent)
|
|||||||
ui->radioButtonNetgen->setChecked(true);
|
ui->radioButtonNetgen->setChecked(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Gui::Command::doCommand(Gui::Command::Doc, "import Mesh");
|
Gui::Command::doCommand(Gui::Command::Doc, "import Mesh, Part, PartGui");
|
||||||
try {
|
try {
|
||||||
Gui::Command::doCommand(Gui::Command::Doc, "import MeshPart");
|
Gui::Command::doCommand(Gui::Command::Doc, "import MeshPart");
|
||||||
}
|
}
|
||||||
@@ -182,63 +182,56 @@ void Tessellation::changeEvent(QEvent *e)
|
|||||||
QWidget::changeEvent(e);
|
QWidget::changeEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<App::DocumentObjectT> Tessellation::findShapes()
|
namespace MeshPartGui {
|
||||||
{
|
struct ShapeInfo {
|
||||||
std::list<App::DocumentObjectT> shapeObjects;
|
App::DocumentObjectT obj;
|
||||||
App::Document* activeDoc = App::GetApplication().getActiveDocument();
|
std::string subname;
|
||||||
if (!activeDoc) return shapeObjects;
|
|
||||||
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
|
|
||||||
if (!activeGui) return shapeObjects;
|
|
||||||
|
|
||||||
this->document = QString::fromLatin1(activeDoc->getName());
|
ShapeInfo(const App::DocumentObject *o, const char *s)
|
||||||
std::vector<Part::Feature*> objs = activeDoc->getObjectsOfType<Part::Feature>();
|
: obj(o), subname(s)
|
||||||
|
{}
|
||||||
double edgeLen = 0;
|
};
|
||||||
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());
|
|
||||||
|
|
||||||
if (Gui::Selection().isSelected(*it)) {
|
|
||||||
App::DocumentObjectT objT(*it);
|
|
||||||
shapeObjects.push_back(objT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->spinMaximumEdgeLength->setValue(edgeLen/10);
|
|
||||||
return shapeObjects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tessellation::accept()
|
bool Tessellation::accept()
|
||||||
{
|
{
|
||||||
std::list<App::DocumentObjectT> shapeObjects = findShapes();
|
std::list<ShapeInfo> shapeObjects;
|
||||||
|
App::Document* activeDoc = App::GetApplication().getActiveDocument();
|
||||||
|
if (!activeDoc) {
|
||||||
|
QMessageBox::critical(this, windowTitle(), tr("No active document"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
|
||||||
|
if (!activeGui) {
|
||||||
|
QMessageBox::critical(this, windowTitle(), tr("No active document"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->document = QString::fromLatin1(activeDoc->getName());
|
||||||
|
|
||||||
|
double edgeLen = 0;
|
||||||
|
for (auto &sel : Gui::Selection().getSelection("*",0)) {
|
||||||
|
auto shape = Part::Feature::getTopoShape(sel.pObject,sel.SubName);
|
||||||
|
if (shape.hasSubShape(TopAbs_FACE)) {
|
||||||
|
Base::BoundBox3d bbox = shape.getBoundBox();
|
||||||
|
edgeLen = std::max<double>(edgeLen, bbox.LengthX());
|
||||||
|
edgeLen = std::max<double>(edgeLen, bbox.LengthY());
|
||||||
|
edgeLen = std::max<double>(edgeLen, bbox.LengthZ());
|
||||||
|
shapeObjects.emplace_back(sel.pObject,sel.SubName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->spinMaximumEdgeLength->setValue(edgeLen/10);
|
||||||
|
|
||||||
if (shapeObjects.empty()) {
|
if (shapeObjects.empty()) {
|
||||||
QMessageBox::critical(this, windowTitle(),
|
QMessageBox::critical(this, windowTitle(),
|
||||||
tr("Select a shape for meshing, first."));
|
tr("Select a shape for meshing, first."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
App::Document* activeDoc = App::GetApplication().getDocument((const char*)this->document.toLatin1());
|
|
||||||
if (!activeDoc) {
|
|
||||||
QMessageBox::critical(this, windowTitle(),
|
|
||||||
tr("No such document '%1'.").arg(this->document));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
QString shape, label;
|
QString objname, label, subname;
|
||||||
Gui::WaitCursor wc;
|
Gui::WaitCursor wc;
|
||||||
|
|
||||||
int method = buttonGroup->checkedId();
|
int method = buttonGroup->checkedId();
|
||||||
@@ -256,59 +249,60 @@ bool Tessellation::accept()
|
|||||||
}
|
}
|
||||||
|
|
||||||
activeDoc->openTransaction("Meshing");
|
activeDoc->openTransaction("Meshing");
|
||||||
for (std::list<App::DocumentObjectT>::iterator it = shapeObjects.begin(); it != shapeObjects.end(); ++it) {
|
for (auto &info : shapeObjects) {
|
||||||
shape = QString::fromLatin1(it->getObjectName().c_str());
|
subname = QString::fromLatin1(info.subname.c_str());
|
||||||
label = QString::fromUtf8(it->getObjectLabel().c_str());
|
objname = QString::fromLatin1(info.obj.getObjectName().c_str());
|
||||||
|
|
||||||
QString cmd;
|
auto obj = info.obj.getObject();
|
||||||
|
if (!obj)
|
||||||
|
continue;
|
||||||
|
auto sobj = obj->getSubObject(info.subname.c_str());
|
||||||
|
if (!sobj)
|
||||||
|
continue;
|
||||||
|
sobj = sobj->getLinkedObject(true);
|
||||||
|
if (!sobj)
|
||||||
|
continue;
|
||||||
|
label = QString::fromUtf8(sobj->Label.getValue());
|
||||||
|
auto svp = Base::freecad_dynamic_cast<PartGui::ViewProviderPartExt>(
|
||||||
|
Gui::Application::Instance->getViewProvider(sobj));
|
||||||
|
|
||||||
|
QString param;
|
||||||
if (method == 0) { // Standard
|
if (method == 0) { // Standard
|
||||||
double devFace = ui->spinSurfaceDeviation->value().getValue();
|
double devFace = ui->spinSurfaceDeviation->value().getValue();
|
||||||
double devAngle = ui->spinAngularDeviation->value().getValue();
|
double devAngle = ui->spinAngularDeviation->value().getValue();
|
||||||
devAngle = Base::toRadians<double>(devAngle);
|
devAngle = Base::toRadians<double>(devAngle);
|
||||||
bool relative = ui->relativeDeviation->isChecked();
|
bool relative = ui->relativeDeviation->isChecked();
|
||||||
QString param = QString::fromLatin1("Shape=__shape__, "
|
param = QString::fromLatin1("Shape=__shape__, "
|
||||||
"LinearDeflection=%1, "
|
"LinearDeflection=%1, "
|
||||||
"AngularDeflection=%2, "
|
"AngularDeflection=%2, "
|
||||||
"Relative=%3")
|
"Relative=%3")
|
||||||
.arg(devFace)
|
.arg(devFace)
|
||||||
.arg(devAngle)
|
.arg(devAngle)
|
||||||
.arg(relative ? QString::fromLatin1("True") : QString::fromLatin1("False"));
|
.arg(relative ? QString::fromLatin1("True") : QString::fromLatin1("False"));
|
||||||
if (ui->meshShapeColors->isChecked())
|
if (ui->meshShapeColors->isChecked())
|
||||||
param += QString::fromLatin1(",Segments=True");
|
param += QString::fromLatin1(",Segments=True");
|
||||||
if (ui->groupsFaceColors->isChecked())
|
if (ui->groupsFaceColors->isChecked() && svp) {
|
||||||
param += QString::fromLatin1(",GroupColors=__doc__.getObject(\"%1\").ViewObject.DiffuseColor")
|
// TODO: currently, we can only retrieve part feature
|
||||||
.arg(shape);
|
// color. The problem is that if the feature is linked,
|
||||||
cmd = QString::fromLatin1(
|
// there are potentially many places where the color can
|
||||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
// get overriden.
|
||||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
//
|
||||||
"__part__=__doc__.getObject(\"%2\")\n"
|
// With topo naming feature merged, it will be possible to
|
||||||
"__shape__=__part__.Shape.copy(False)\n"
|
// infer more accurate colors from just the shape names,
|
||||||
"__shape__.Placement=__part__.getGlobalPlacement()\n"
|
// with static function,
|
||||||
"__mesh__.Mesh=MeshPart.meshFromShape(%3)\n"
|
//
|
||||||
"__mesh__.Label=\"%4 (Meshed)\"\n"
|
// PartGui::ViewProviderPartExt::getShapeColors().
|
||||||
"del __doc__, __mesh__, __part__, __shape__\n")
|
//
|
||||||
.arg(this->document)
|
param += QString::fromLatin1(",GroupColors=Gui.getDocument('%1').getObject('%2').DiffuseColor")
|
||||||
.arg(shape)
|
.arg(QString::fromLatin1(sobj->getDocument()->getName()),
|
||||||
.arg(param)
|
QString::fromLatin1(sobj->getNameInDocument()));
|
||||||
.arg(label);
|
}
|
||||||
}
|
}
|
||||||
else if (method == 1) { // Mefisto
|
else if (method == 1) { // Mefisto
|
||||||
double maxEdge = ui->spinMaximumEdgeLength->value().getValue();
|
double maxEdge = ui->spinMaximumEdgeLength->value().getValue();
|
||||||
if (!ui->spinMaximumEdgeLength->isEnabled())
|
if (!ui->spinMaximumEdgeLength->isEnabled())
|
||||||
maxEdge = 0;
|
maxEdge = 0;
|
||||||
cmd = QString::fromLatin1(
|
param = QString::fromLatin1("Shape=__shape__,MaxLength=%1").arg(maxEdge);
|
||||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
|
||||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
|
||||||
"__part__=__doc__.getObject(\"%2\")\n"
|
|
||||||
"__shape__=__part__.Shape.copy(False)\n"
|
|
||||||
"__shape__.Placement=__part__.getGlobalPlacement()\n"
|
|
||||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__shape__,MaxLength=%3)\n"
|
|
||||||
"__mesh__.Label=\"%4 (Meshed)\"\n"
|
|
||||||
"del __doc__, __mesh__, __part__, __shape__\n")
|
|
||||||
.arg(this->document)
|
|
||||||
.arg(shape)
|
|
||||||
.arg(maxEdge)
|
|
||||||
.arg(label);
|
|
||||||
}
|
}
|
||||||
else if (method == 2) { // Netgen
|
else if (method == 2) { // Netgen
|
||||||
int fineness = ui->comboFineness->currentIndex();
|
int fineness = ui->comboFineness->currentIndex();
|
||||||
@@ -319,46 +313,39 @@ bool Tessellation::accept()
|
|||||||
bool optimize = ui->checkOptimizeSurface->isChecked();
|
bool optimize = ui->checkOptimizeSurface->isChecked();
|
||||||
bool allowquad = ui->checkQuadDominated->isChecked();
|
bool allowquad = ui->checkQuadDominated->isChecked();
|
||||||
if (fineness < 5) {
|
if (fineness < 5) {
|
||||||
cmd = QString::fromLatin1(
|
param = QString::fromLatin1("Shape=__shape__,"
|
||||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
"Fineness=%1,SecondOrder=%2,Optimize=%3,AllowQuad=%4")
|
||||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
|
||||||
"__part__=__doc__.getObject(\"%2\")\n"
|
|
||||||
"__shape__=__part__.Shape.copy(False)\n"
|
|
||||||
"__shape__.Placement=__part__.getGlobalPlacement()\n"
|
|
||||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__shape__,"
|
|
||||||
"Fineness=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6)\n"
|
|
||||||
"__mesh__.Label=\"%7 (Meshed)\"\n"
|
|
||||||
"del __doc__, __mesh__, __part__, __shape__\n")
|
|
||||||
.arg(this->document)
|
|
||||||
.arg(shape)
|
|
||||||
.arg(fineness)
|
.arg(fineness)
|
||||||
.arg(secondOrder ? 1 : 0)
|
.arg(secondOrder ? 1 : 0)
|
||||||
.arg(optimize ? 1 : 0)
|
.arg(optimize ? 1 : 0)
|
||||||
.arg(allowquad ? 1 : 0)
|
.arg(allowquad ? 1 : 0);
|
||||||
.arg(label);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cmd = QString::fromLatin1(
|
param = QString::fromLatin1("Shape=__shape__,"
|
||||||
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
"GrowthRate=%1,SegPerEdge=%2,SegPerRadius=%3,SecondOrder=%4,Optimize=%5,AllowQuad=%6")
|
||||||
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
|
||||||
"__part__=__doc__.getObject(\"%2\")\n"
|
|
||||||
"__shape__=__part__.Shape.copy(False)\n"
|
|
||||||
"__shape__.Placement=__part__.getGlobalPlacement()\n"
|
|
||||||
"__mesh__.Mesh=MeshPart.meshFromShape(Shape=__shape__,"
|
|
||||||
"GrowthRate=%3,SegPerEdge=%4,SegPerRadius=%5,SecondOrder=%6,Optimize=%7,AllowQuad=%8)\n"
|
|
||||||
"__mesh__.Label=\"%9 (Meshed)\"\n"
|
|
||||||
"del __doc__, __mesh__, __part__, __shape__\n")
|
|
||||||
.arg(this->document)
|
|
||||||
.arg(shape)
|
|
||||||
.arg(growthRate)
|
.arg(growthRate)
|
||||||
.arg(nbSegPerEdge)
|
.arg(nbSegPerEdge)
|
||||||
.arg(nbSegPerRadius)
|
.arg(nbSegPerRadius)
|
||||||
.arg(secondOrder ? 1 : 0)
|
.arg(secondOrder ? 1 : 0)
|
||||||
.arg(optimize ? 1 : 0)
|
.arg(optimize ? 1 : 0)
|
||||||
.arg(allowquad ? 1 : 0)
|
.arg(allowquad ? 1 : 0);
|
||||||
.arg(label);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString cmd = QString::fromLatin1(
|
||||||
|
"__doc__=FreeCAD.getDocument(\"%1\")\n"
|
||||||
|
"__mesh__=__doc__.addObject(\"Mesh::Feature\",\"Mesh\")\n"
|
||||||
|
"__part__=__doc__.getObject(\"%2\")\n"
|
||||||
|
"__shape__=Part.getShape(__part__,\"%3\")\n"
|
||||||
|
"__mesh__.Mesh=MeshPart.meshFromShape(%4)\n"
|
||||||
|
"__mesh__.Label=\"%5 (Meshed)\"\n"
|
||||||
|
"del __doc__, __mesh__, __part__, __shape__\n")
|
||||||
|
.arg(this->document)
|
||||||
|
.arg(objname)
|
||||||
|
.arg(subname)
|
||||||
|
.arg(param)
|
||||||
|
.arg(label);
|
||||||
|
|
||||||
Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8());
|
Gui::Command::runCommand(Gui::Command::Doc, cmd.toUtf8());
|
||||||
|
|
||||||
// if Standard mesher is used and face colors should be applied
|
// if Standard mesher is used and face colors should be applied
|
||||||
@@ -366,12 +353,9 @@ bool Tessellation::accept()
|
|||||||
if (ui->meshShapeColors->isChecked()) {
|
if (ui->meshShapeColors->isChecked()) {
|
||||||
Gui::ViewProvider* vpm = Gui::Application::Instance->getViewProvider
|
Gui::ViewProvider* vpm = Gui::Application::Instance->getViewProvider
|
||||||
(activeDoc->getActiveObject());
|
(activeDoc->getActiveObject());
|
||||||
Gui::ViewProvider* vpp = Gui::Application::Instance->getViewProvider
|
|
||||||
(activeDoc->getObject(shape.toLatin1()));
|
|
||||||
MeshGui::ViewProviderMesh* vpmesh = dynamic_cast<MeshGui::ViewProviderMesh*>(vpm);
|
MeshGui::ViewProviderMesh* vpmesh = dynamic_cast<MeshGui::ViewProviderMesh*>(vpm);
|
||||||
PartGui::ViewProviderPart* vppart = dynamic_cast<PartGui::ViewProviderPart*>(vpp);
|
if (vpmesh && svp) {
|
||||||
if (vpmesh && vppart) {
|
std::vector<App::Color> diff_col = svp->DiffuseColor.getValues();
|
||||||
std::vector<App::Color> diff_col = vppart->DiffuseColor.getValues();
|
|
||||||
if (ui->groupsFaceColors->isChecked()) {
|
if (ui->groupsFaceColors->isChecked()) {
|
||||||
// unique colors
|
// unique colors
|
||||||
std::set<uint32_t> col_set;
|
std::set<uint32_t> col_set;
|
||||||
|
|||||||
@@ -47,9 +47,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void changeEvent(QEvent *e);
|
void changeEvent(QEvent *e);
|
||||||
|
|
||||||
private:
|
|
||||||
std::list<App::DocumentObjectT> findShapes();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void meshingMethod(int id);
|
void meshingMethod(int id);
|
||||||
void on_comboFineness_currentIndexChanged(int);
|
void on_comboFineness_currentIndexChanged(int);
|
||||||
|
|||||||
Reference in New Issue
Block a user