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;
}
示例#2
0
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");
}
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");
}
示例#4
0
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(), "");
    }
}
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;
}
示例#6
0
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());
}
示例#7
0
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());
}
示例#8
0
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);
}
示例#9
0
void DlgExtrusion::getAxisLink(App::PropertyLinkSub& lnk) const
{
    QString text = ui->txtLink->text();

    if (text.length() == 0) {
        lnk.setValue(nullptr);
    } else {
        QStringList parts = text.split(QChar::fromLatin1(':'));
        App::DocumentObject* obj = App::GetApplication().getActiveDocument()->getObject(parts[0].toLatin1());
        if(!obj){
            throw Base::ValueError(tr("Object not found: %1").arg(parts[0]).toUtf8().constData());
        }
        lnk.setValue(obj);
        if (parts.size() == 1) {
            return;
        } else if (parts.size() == 2) {
            std::vector<std::string> subs;
            subs.push_back(std::string(parts[1].toLatin1().constData()));
            lnk.setValue(obj,subs);
        }
    }

}
示例#10
0
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;
}
示例#11
0
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);
        }
    }
}
示例#12
0
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();
}