void DlgExtrusion::setAxisLink(const App::PropertyLinkSub& lnk) { if (!lnk.getValue()){ ui->txtLink->clear(); return; } if (lnk.getSubValues().size() == 1){ this->setAxisLink(lnk.getValue()->getNameInDocument(), lnk.getSubValues()[0].c_str()); } else { this->setAxisLink(lnk.getValue()->getNameInDocument(), ""); } }
void ProfileBased::getUpToFaceFromLinkSub(TopoDS_Face& upToFace, const App::PropertyLinkSub& refFace) { App::DocumentObject* ref = refFace.getValue(); std::vector<std::string> subStrings = refFace.getSubValues(); if (ref == NULL) throw Base::ValueError("SketchBased: Up to face: No face selected"); if (ref->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { upToFace = TopoDS::Face(makeShapeFromPlane(ref)); return; } else if (ref->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { Part::Datum* datum = static_cast<Part::Datum*>(ref); upToFace = TopoDS::Face(datum->getShape()); return; } if (!ref->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::TypeError("SketchBased: Up to face: Must be face of a feature"); Part::TopoShape baseShape = static_cast<Part::Feature*>(ref)->Shape.getShape(); if (subStrings.empty() || subStrings[0].empty()) throw Base::ValueError("SketchBased: Up to face: No face selected"); // TODO: Check for multiple UpToFaces? upToFace = TopoDS::Face(baseShape.getSubShape(subStrings[0].c_str())); if (upToFace.IsNull()) throw Base::ValueError("SketchBased: Up to face: Failed to extract face"); }
const Base::Vector3d Constraint::getDirection(const App::PropertyLinkSub &direction) { App::DocumentObject* obj = direction.getValue(); std::vector<std::string> names = direction.getSubValues(); if (names.size() == 0) return Base::Vector3d(0,0,0); std::string subName = names.front(); Part::Feature* feat = static_cast<Part::Feature*>(obj); TopoDS_Shape sh = feat->Shape.getShape().getSubShape(subName.c_str()); gp_Dir dir; if (sh.ShapeType() == TopAbs_FACE) { BRepAdaptor_Surface surface(TopoDS::Face(sh)); if (surface.GetType() == GeomAbs_Plane) { dir = surface.Plane().Axis().Direction(); } else { return Base::Vector3d(0,0,0); // "Direction must be a planar face or linear edge" } } else if (sh.ShapeType() == TopAbs_EDGE) { BRepAdaptor_Curve line(TopoDS::Edge(sh)); if (line.GetType() == GeomAbs_Line) { dir = line.Line().Direction(); } else { return Base::Vector3d(0,0,0); // "Direction must be a planar face or linear edge" } } Base::Vector3d the_direction(dir.X(), dir.Y(), dir.Z()); the_direction.Normalize(); return the_direction; }
bool Extrusion::fetchAxisLink(const App::PropertyLinkSub& axisLink, Base::Vector3d& basepoint, Base::Vector3d& dir) { if (!axisLink.getValue()) return false; if (!axisLink.getValue()->isDerivedFrom(Part::Feature::getClassTypeId())) throw Base::TypeError("AxisLink has no OCC shape"); Part::Feature* linked = static_cast<Part::Feature*>(axisLink.getValue()); TopoDS_Shape axEdge; if (axisLink.getSubValues().size() > 0 && axisLink.getSubValues()[0].length() > 0){ axEdge = linked->Shape.getShape().getSubShape(axisLink.getSubValues()[0].c_str()); } else { axEdge = linked->Shape.getValue(); } if (axEdge.IsNull()) throw Base::ValueError("DirLink shape is null"); if (axEdge.ShapeType() != TopAbs_EDGE) throw Base::TypeError("DirLink shape is not an edge"); BRepAdaptor_Curve crv(TopoDS::Edge(axEdge)); gp_Pnt startpoint; gp_Pnt endpoint; if (crv.GetType() == GeomAbs_Line){ startpoint = crv.Value(crv.FirstParameter()); endpoint = crv.Value(crv.LastParameter()); if (axEdge.Orientation() == TopAbs_REVERSED) std::swap(startpoint, endpoint); } else { throw Base::TypeError("DirLink edge is not a line."); } basepoint.Set(startpoint.X(), startpoint.Y(), startpoint.Z()); gp_Vec vec = gp_Vec(startpoint, endpoint); dir.Set(vec.X(), vec.Y(), vec.Z()); return true; }
int ComboLinks::setCurrentLink(const App::PropertyLinkSub &lnk) { for(size_t i = 0 ; i < linksInList.size() ; i++) { App::PropertyLinkSub &it = *(linksInList[i]); if(lnk.getValue() == it.getValue() && lnk.getSubValues() == it.getSubValues()){ bool wasBlocked = _combo->signalsBlocked(); _combo->blockSignals(true); _combo->setCurrentIndex(i); _combo->blockSignals(wasBlocked); return i; } } return -1; }
Base::Vector3d Constraint::getBasePoint(const Base::Vector3d& base, const Base::Vector3d& axis, const App::PropertyLinkSub& location, const double& dist) { // Get the point specified by Location and Distance App::DocumentObject* objLoc = location.getValue(); std::vector<std::string> names = location.getSubValues(); if (names.size() == 0) return Base::Vector3d(0,0,0); std::string subName = names.front(); Part::Feature* featLoc = static_cast<Part::Feature*>(objLoc); TopoDS_Shape shloc = featLoc->Shape.getShape().getSubShape(subName.c_str()); // Get a plane from the Location reference gp_Pln plane; gp_Dir cylaxis(axis.x, axis.y, axis.z); if (shloc.ShapeType() == TopAbs_FACE) { BRepAdaptor_Surface surface(TopoDS::Face(shloc)); plane = surface.Plane(); } else { BRepAdaptor_Curve curve(TopoDS::Edge(shloc)); gp_Lin line = curve.Line(); gp_Dir tang = line.Direction().Crossed(cylaxis); gp_Dir norm = line.Direction().Crossed(tang); plane = gp_Pln(line.Location(), norm); } // Translate the plane in direction of the cylinder (for positive values of Distance) Handle(Geom_Plane) pln = new Geom_Plane(plane); gp_Pnt cylbase(base.x, base.y, base.z); GeomAPI_ProjectPointOnSurf proj(cylbase, pln); if (!proj.IsDone()) return Base::Vector3d(0,0,0); gp_Pnt projPnt = proj.NearestPoint(); if ((fabs(dist) > Precision::Confusion()) && (projPnt.IsEqual(cylbase, Precision::Confusion()) == Standard_False)) plane.Translate(gp_Vec(projPnt, cylbase).Normalized().Multiplied(dist)); Handle(Geom_Plane) plnt = new Geom_Plane(plane); // Intersect translated plane with cylinder axis Handle(Geom_Curve) crv = new Geom_Line(cylbase, cylaxis); GeomAPI_IntCS intersector(crv, plnt); if (!intersector.IsDone()) return Base::Vector3d(0,0,0); gp_Pnt inter = intersector.Point(1); return Base::Vector3d(inter.X(), inter.Y(), inter.Z()); }
void DlgExtrusion::writeParametersToFeature(App::DocumentObject &feature, App::DocumentObject* base) const { Gui::Command::doCommand(Gui::Command::Doc,"f = App.getDocument('%s').getObject('%s')", feature.getDocument()->getName(), feature.getNameInDocument()); if (base) Gui::Command::doCommand(Gui::Command::Doc,"f.Base = App.getDocument('%s').getObject('%s')", base->getDocument()->getName(), base->getNameInDocument()); Part::Extrusion::eDirMode dirMode = this->getDirMode(); const char* modestr = Part::Extrusion::eDirModeStrings[dirMode]; Gui::Command::doCommand(Gui::Command::Doc,"f.DirMode = \"%s\"", modestr); if (dirMode == Part::Extrusion::dmCustom){ Base::Vector3d dir = this->getDir(); Gui::Command::doCommand(Gui::Command::Doc, "f.Dir = App.Vector(%.15f, %.15f, %.15f)", dir.x, dir.y, dir.z); } App::PropertyLinkSub lnk; this->getAxisLink(lnk); std::stringstream linkstr; if(lnk.getValue() == nullptr){ linkstr << "None"; } else { linkstr << "(App.getDocument(\"" << lnk.getValue()->getDocument()->getName() <<"\")." << lnk.getValue()->getNameInDocument(); linkstr << ", ["; for (const std::string &str: lnk.getSubValues()){ linkstr << "\"" << str << "\""; } linkstr << "])"; } Gui::Command::doCommand(Gui::Command::Doc,"f.DirLink = %s", linkstr.str().c_str()); Gui::Command::doCommand(Gui::Command::Doc,"f.LengthFwd = %.15f", ui->spinLenFwd->value().getValue()); Gui::Command::doCommand(Gui::Command::Doc,"f.LengthRev = %.15f", ui->spinLenRev->value().getValue()); Gui::Command::doCommand(Gui::Command::Doc,"f.Solid = %s", ui->chkSolid->isChecked() ? "True" : "False"); Gui::Command::doCommand(Gui::Command::Doc,"f.Reversed = %s", ui->chkReversed->isChecked() ? "True" : "False"); Gui::Command::doCommand(Gui::Command::Doc,"f.Symmetric = %s", ui->chkSymmetric->isChecked() ? "True" : "False"); Gui::Command::doCommand(Gui::Command::Doc,"f.TaperAngle = %.15f", ui->spinTaperAngle->value().getValue()); Gui::Command::doCommand(Gui::Command::Doc,"f.TaperAngleRev = %.15f", ui->spinTaperAngleRev->value().getValue()); }
const Base::Vector3d Constraint::getDirection(const App::PropertyLinkSub &direction) { App::DocumentObject* obj = direction.getValue(); std::vector<std::string> names = direction.getSubValues(); if (names.size() == 0) return Base::Vector3d(0,0,0); std::string subName = names.front(); Part::Feature* feat = static_cast<Part::Feature*>(obj); const Part::TopoShape& shape = feat->Shape.getShape(); if (shape.isNull()) return Base::Vector3d(0,0,0); TopoDS_Shape sh; try { sh = shape.getSubShape(subName.c_str()); } catch (Standard_Failure&) { std::stringstream str; str << "No such sub-element '" << subName << "'"; throw Base::AttributeError(str.str()); } return Fem::Tools::getDirectionFromShape(sh); }
bool ProfileBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Face &face) { #if 1 BRepBuilderAPI_MakeEdge mkEdge(line); TopoDS_Wire wire = ShapeAnalysis::OuterWire(face); BRepExtrema_DistShapeShape distss(wire, mkEdge.Shape(), Precision::Confusion()); if (distss.IsDone()) { if (distss.Value() > Precision::Confusion()) return false; // build up map vertex->edge TopTools_IndexedDataMapOfShapeListOfShape vertex2Edge; TopExp::MapShapesAndAncestors(wire, TopAbs_VERTEX, TopAbs_EDGE, vertex2Edge); for (Standard_Integer i=1; i<= distss.NbSolution(); i++) { if (distss.PointOnShape1(i).Distance(distss.PointOnShape2(i)) > Precision::Confusion()) continue; BRepExtrema_SupportType type = distss.SupportTypeShape1(i); if (type == BRepExtrema_IsOnEdge) { TopoDS_Edge edge = TopoDS::Edge(distss.SupportOnShape1(i)); BRepAdaptor_Curve adapt(edge); // create a plane (pnt,dir) that goes through the intersection point and is built of // the vectors of the sketch normal and the rotation axis const gp_Dir& normal = BRepAdaptor_Surface(face).Plane().Axis().Direction(); gp_Dir dir = line.Direction().Crossed(normal); gp_Pnt pnt = distss.PointOnShape1(i); Standard_Real t; distss.ParOnEdgeS1(i, t); gp_Pnt p_eps1 = adapt.Value(std::max<double>(adapt.FirstParameter(), t-10*Precision::Confusion())); gp_Pnt p_eps2 = adapt.Value(std::min<double>(adapt.LastParameter(), t+10*Precision::Confusion())); // now check if we get a change in the sign of the distances Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir)); Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir)); // distance to the plane must be noticeable if (fabs(dist_p_eps1_pnt) > 5*Precision::Confusion() && fabs(dist_p_eps2_pnt) > 5*Precision::Confusion()) { if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) return true; } } else if (type == BRepExtrema_IsVertex) { // for a vertex check the two adjacent edges if there is a change of sign TopoDS_Vertex vertex = TopoDS::Vertex(distss.SupportOnShape1(i)); const TopTools_ListOfShape& edges = vertex2Edge.FindFromKey(vertex); if (edges.Extent() == 2) { // create a plane (pnt,dir) that goes through the intersection point and is built of // the vectors of the sketch normal and the rotation axis BRepAdaptor_Surface adapt(face); const gp_Dir& normal = adapt.Plane().Axis().Direction(); gp_Dir dir = line.Direction().Crossed(normal); gp_Pnt pnt = distss.PointOnShape1(i); // from the first edge get a point next to the intersection point const TopoDS_Edge& edge1 = TopoDS::Edge(edges.First()); BRepAdaptor_Curve adapt1(edge1); Standard_Real dist1 = adapt1.Value(adapt1.FirstParameter()).SquareDistance(pnt); Standard_Real dist2 = adapt1.Value(adapt1.LastParameter()).SquareDistance(pnt); gp_Pnt p_eps1; if (dist1 < dist2) p_eps1 = adapt1.Value(adapt1.FirstParameter() + 2*Precision::Confusion()); else p_eps1 = adapt1.Value(adapt1.LastParameter() - 2*Precision::Confusion()); // from the second edge get a point next to the intersection point const TopoDS_Edge& edge2 = TopoDS::Edge(edges.Last()); BRepAdaptor_Curve adapt2(edge2); Standard_Real dist3 = adapt2.Value(adapt2.FirstParameter()).SquareDistance(pnt); Standard_Real dist4 = adapt2.Value(adapt2.LastParameter()).SquareDistance(pnt); gp_Pnt p_eps2; if (dist3 < dist4) p_eps2 = adapt2.Value(adapt2.FirstParameter() + 2*Precision::Confusion()); else p_eps2 = adapt2.Value(adapt2.LastParameter() - 2*Precision::Confusion()); // now check if we get a change in the sign of the distances Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir)); Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir)); // distance to the plane must be noticeable if (fabs(dist_p_eps1_pnt) > Precision::Confusion() && fabs(dist_p_eps2_pnt) > Precision::Confusion()) { if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) return true; } } } } } return false; #else // This is not as easy as it looks, because a distance of zero might be OK if // the axis touches the sketchshape in in a linear edge or a vertex // Note: This algorithm does not catch cases where the sketchshape touches the // axis in two or more points // Note: And it only works on closed outer wires TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(face); BRepBuilderAPI_MakeEdge mkEdge(line); if (!mkEdge.IsDone()) throw Base::RuntimeError("Revolve: Unexpected OCE failure"); BRepAdaptor_Curve axis(TopoDS::Edge(mkEdge.Shape())); TopExp_Explorer ex; int intersections = 0; std::vector<gp_Pnt> intersectionpoints; // Note: We need to look at every edge separately to catch coincident lines for (ex.Init(outerWire, TopAbs_EDGE); ex.More(); ex.Next()) { BRepAdaptor_Curve edge(TopoDS::Edge(ex.Current())); Extrema_ExtCC intersector(axis, edge); if (intersector.IsDone()) { for (int i = 1; i <= intersector.NbExt(); i++) { #if OCC_VERSION_HEX >= 0x060500 if (intersector.SquareDistance(i) < Precision::Confusion()) { #else if (intersector.Value(i) < Precision::Confusion()) { #endif if (intersector.IsParallel()) { // A line that is coincident with the axis produces three intersections // 1 with the line itself and 2 with the adjacent edges intersections -= 2; } else { Extrema_POnCurv p1, p2; intersector.Points(i, p1, p2); intersectionpoints.push_back(p1.Value()); intersections++; } } } } } // Note: We might check this inside the loop but then we have to rely on TopExp_Explorer // returning the wire's edges in adjacent order (because of the coincident line checking) if (intersections > 1) { // Check that we don't touch the sketchface just in two identical vertices if ((intersectionpoints.size() == 2) && (intersectionpoints[0].IsEqual(intersectionpoints[1], Precision::Confusion()))) return false; else return true; } return false; #endif } void ProfileBased::remapSupportShape(const TopoDS_Shape& newShape) { TopTools_IndexedMapOfShape faceMap; TopExp::MapShapes(newShape, TopAbs_FACE, faceMap); // here we must reset the placement otherwise the geometric matching doesn't work Part::TopoShape shape = this->Shape.getValue(); TopoDS_Shape sh = shape.getShape(); sh.Location(TopLoc_Location()); shape.setShape(sh); std::vector<App::DocumentObject*> refs = this->getInList(); for (std::vector<App::DocumentObject*>::iterator it = refs.begin(); it != refs.end(); ++it) { std::vector<App::Property*> props; (*it)->getPropertyList(props); for (std::vector<App::Property*>::iterator jt = props.begin(); jt != props.end(); ++jt) { if (!(*jt)->isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) continue; App::PropertyLinkSub* link = static_cast<App::PropertyLinkSub*>(*jt); if (link->getValue() != this) continue; std::vector<std::string> subValues = link->getSubValues(); std::vector<std::string> newSubValues; for (std::vector<std::string>::iterator it = subValues.begin(); it != subValues.end(); ++it) { std::string shapetype; if (it->size() > 4 && it->substr(0,4) == "Face") { shapetype = "Face"; } else if (it->size() > 4 && it->substr(0,4) == "Edge") { shapetype = "Edge"; } else if (it->size() > 6 && it->substr(0,6) == "Vertex") { shapetype = "Vertex"; } else { newSubValues.push_back(*it); continue; } bool success = false; TopoDS_Shape element; try { element = shape.getSubShape(it->c_str()); } catch (Standard_Failure&) { // This shape doesn't even exist, so no chance to do some tests newSubValues.push_back(*it); continue; } try { // as very first test check if old face and new face are parallel planes TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(it->c_str()); if (isParallelPlane(element, newElement)) { newSubValues.push_back(*it); success = true; } } catch (Standard_Failure&) { } // try an exact matching if (!success) { for (int i=1; i<faceMap.Extent(); i++) { if (isQuasiEqual(element, faceMap.FindKey(i))) { std::stringstream str; str << shapetype << i; newSubValues.push_back(str.str()); success = true; break; } } } // if an exact matching fails then try to compare only the geometries if (!success) { for (int i=1; i<faceMap.Extent(); i++) { if (isEqualGeometry(element, faceMap.FindKey(i))) { std::stringstream str; str << shapetype << i; newSubValues.push_back(str.str()); success = true; break; } } } // the new shape couldn't be found so keep the old sub-name if (!success) newSubValues.push_back(*it); } link->setValue(this, newSubValues); } } }
void Part2DObject::Restore(Base::XMLReader &reader) { //override generic restoration to convert Support property from PropertyLinkSub to PropertyLinkSubList reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // NOTE: We must also check the type of the current property because a // subclass of PropertyContainer might change the type of a property but // not its name. In this case we would force to read-in a wrong property // type and the behaviour would be undefined. try { if(prop){ if (strcmp(prop->getTypeId().getName(), TypeName) == 0){ prop->Restore(reader); } else if (prop->isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())){ //reading legacy Support - when the Support could only be a single flat face. App::PropertyLinkSub tmp; if (0 == strcmp(tmp.getTypeId().getName(),TypeName)) { tmp.setContainer(this); tmp.Restore(reader); static_cast<App::PropertyLinkSubList*>(prop)->setValue(tmp.getValue(), tmp.getSubValues()); } this->MapMode.setValue(Attacher::mmFlatFace); } } } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::Exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const std::exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const char* e) { Base::Console().Error("%s\n", e); } #ifndef FC_DEBUG catch (...) { Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void DlgRevolution::accept() { if (!this->validate()) return; Gui::WaitCursor wc; App::Document* activeDoc = App::GetApplication().getActiveDocument(); activeDoc->openTransaction("Revolve"); try{ QString shape, type, name, solid; QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems(); if (ui->checkSolid->isChecked()) { solid = QString::fromLatin1("True");} else { solid = QString::fromLatin1("False");} App::PropertyLinkSub axisLink; this->getAxisLink(axisLink); QString strAxisLink; if (axisLink.getValue()){ strAxisLink = QString::fromLatin1("(App.ActiveDocument.%1, %2)") .arg(QString::fromLatin1(axisLink.getValue()->getNameInDocument())) .arg(axisLink.getSubValues().size() == 1 ? QString::fromLatin1("\"%1\"").arg(QString::fromLatin1(axisLink.getSubValues()[0].c_str())) : QString() ); } else { strAxisLink = QString::fromLatin1("None"); } QString symmetric; if (ui->checkSymmetric->isChecked()) { symmetric = QString::fromLatin1("True");} else { symmetric = QString::fromLatin1("False");} for (QList<QTreeWidgetItem *>::iterator it = items.begin(); it != items.end(); ++it) { shape = (*it)->data(0, Qt::UserRole).toString(); type = QString::fromLatin1("Part::Revolution"); name = QString::fromLatin1(activeDoc->getUniqueObjectName("Revolve").c_str()); Base::Vector3d axis = this->getDirection(); Base::Vector3d pos = this->getPosition(); QString code = QString::fromLatin1( "FreeCAD.ActiveDocument.addObject(\"%1\",\"%2\")\n" "FreeCAD.ActiveDocument.%2.Source = FreeCAD.ActiveDocument.%3\n" "FreeCAD.ActiveDocument.%2.Axis = (%4,%5,%6)\n" "FreeCAD.ActiveDocument.%2.Base = (%7,%8,%9)\n" "FreeCAD.ActiveDocument.%2.Angle = %10\n" "FreeCAD.ActiveDocument.%2.Solid = %11\n" "FreeCAD.ActiveDocument.%2.AxisLink = %12\n" "FreeCAD.ActiveDocument.%2.Symmetric = %13\n" "FreeCADGui.ActiveDocument.%3.Visibility = False\n") .arg(type).arg(name).arg(shape) //%1, 2, 3 .arg(axis.x,0,'f',15) //%4 .arg(axis.y,0,'f',15) //%5 .arg(axis.z,0,'f',15) //%6 .arg(pos.x, 0,'f',15) //%7 .arg(pos.y, 0,'f',15) //%8 .arg(pos.z, 0,'f',15) //%9 .arg(getAngle(),0,'f',15) //%10 .arg(solid) //%11 .arg(strAxisLink) //%12 .arg(symmetric) //13 ; Gui::Command::runCommand(Gui::Command::App, code.toLatin1()); QByteArray to = name.toLatin1(); QByteArray from = shape.toLatin1(); Gui::Command::copyVisual(to, "ShapeColor", from); Gui::Command::copyVisual(to, "LineColor", from); Gui::Command::copyVisual(to, "PointColor", from); } activeDoc->commitTransaction(); activeDoc->recompute(); } catch (Base::Exception &err) { QMessageBox::critical(this, windowTitle(), tr("Creating Revolve failed.\n\n%1").arg(QString::fromUtf8(err.what()))); return; } catch (...){ QMessageBox::critical(this, windowTitle(), tr("Creating Revolve failed.\n\n%1").arg(QString::fromUtf8("Unknown error"))); return; } QDialog::accept(); }