MeshPart: support link in Tessellation

This commit is contained in:
Zheng, Lei
2019-10-15 10:49:36 +08:00
committed by wmayer
parent 9ee436f27f
commit 95f20b9d85
2 changed files with 100 additions and 119 deletions

View File

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

View File

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