Base::Vector3d Extrusion::calculateShapeNormal(const App::PropertyLink& shapeLink)
{
    if (!shapeLink.getValue())
        throw Base::Exception("calculateShapeNormal: link is empty");
    const App::DocumentObject* docobj = shapeLink.getValue();

    //special case for sketches and the like: no matter what shape they have, use their local Z axis.
    if (docobj->isDerivedFrom(Part::Part2DObject::getClassTypeId())){
        const Part::Part2DObject* p2do = static_cast<const Part::Part2DObject*>(docobj);
        Base::Vector3d OZ (0.0, 0.0, 1.0);
        Base::Vector3d result;
        p2do->Placement.getValue().getRotation().multVec(OZ, result);
        return result;
    }

    //extract the shape
    if (! docobj->isDerivedFrom(Part::Feature::getClassTypeId()))
        throw Base::TypeError("Linked object doesn't have shape.");

    const TopoShape &tsh = static_cast<const Part::Feature*>(docobj)->Shape.getShape();
    TopoDS_Shape sh = tsh.getShape();
    if (sh.IsNull())
        throw Base::Exception("calculateShapeNormal: link points to a valid object, but its shape is null.");

    //find plane
    BRepLib_FindSurface planeFinder(sh, -1, /*OnlyPlane=*/true);
    if (! planeFinder.Found())
        throw Base::ValueError("Can't find normal direction, because the shape is not on a plane.");

    //find plane normal and return result.
    GeomAdaptor_Surface surf(planeFinder.Surface());
    gp_Dir normal = surf.Plane().Axis().Direction();

    //now se know the plane. But if there are faces, the
    //plane normal direction is not dependent on face orientation (because findPlane only uses edges).
    //let's fix that.
    TopExp_Explorer ex(sh, TopAbs_FACE);
    if(ex.More()) {
        BRepAdaptor_Surface surf(TopoDS::Face(ex.Current()));
        normal = surf.Plane().Axis().Direction();
        if (ex.Current().Orientation() == TopAbs_REVERSED){
            normal.Reverse();
        }
    }

    return Base::Vector3d(normal.X(), normal.Y(), normal.Z());
}
Example #2
0
void DlgExtrusion::fetchDir()
{
    bool lengths_are_at_defaults =
        (fabs(ui->spinLenFwd->value().getValue() - 10.0) < 1e-7)
        && (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);
    bool lengths_are_zero =
        (fabs(ui->spinLenFwd->value().getValue() - 0.0) < 1e-7)
        && (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);

    try {
        Base::Vector3d pos, dir;
        bool fetched = false;
        bool dir_has_valid_magnitude = false;
        if(this->getDirMode() == Part::Extrusion::dmEdge) {
            App::PropertyLinkSub lnk;
            this->getAxisLink(lnk);
            fetched = Part::Extrusion::fetchAxisLink(lnk, pos, dir);
            dir_has_valid_magnitude = fetched;
        } else if (this->getDirMode() == Part::Extrusion::dmNormal) {
            App::PropertyLink lnk;
            lnk.setValue(&this->getShapeToExtrude());
            dir = Part::Extrusion::calculateShapeNormal(lnk);
            fetched = true;
        }
        if (dir_has_valid_magnitude && lengths_are_at_defaults) {
            ui->spinLenFwd->setValue(0);
        } else if (!dir_has_valid_magnitude && lengths_are_zero) {
            ui->spinLenFwd->setValue(1.0);
        }
        if (fetched) {
            this->setDir(dir);
        }
    } catch (Base::Exception &) {

    } catch (...) {

    }
}
//DVA is still Source PropertyLink so needs different logic vs DV::Restore
void DrawViewArch::Restore(Base::XMLReader &reader)
{
// this is temporary code for backwards compat (within v0.17).  can probably be deleted once there are no development
// fcstd files with old property types in use. 
    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* schemaProp = getPropertyByName(PropName);
        try {
            if(schemaProp){
                if (strcmp(schemaProp->getTypeId().getName(), TypeName) == 0){        //if the property type in obj == type in schema
                    schemaProp->Restore(reader);                                      //nothing special to do
                } else if (strcmp(PropName, "Source") == 0) {
                    App::PropertyLinkGlobal glink;
                    App::PropertyLink link;
                    if (strcmp(glink.getTypeId().getName(),TypeName) == 0) {            //property in file is plg
                        glink.setContainer(this);
                        glink.Restore(reader);
                        if (glink.getValue() != nullptr) {
                            static_cast<App::PropertyLink*>(schemaProp)->setScope(App::LinkScope::Global);
                            static_cast<App::PropertyLink*>(schemaProp)->setValue(glink.getValue());
                        }
                    } else if (strcmp(link.getTypeId().getName(),TypeName) == 0) {            //property in file is pl
                        link.setContainer(this);
                        link.Restore(reader);
                        if (link.getValue() != nullptr) {
                            static_cast<App::PropertyLink*>(schemaProp)->setScope(App::LinkScope::Global);
                            static_cast<App::PropertyLink*>(schemaProp)->setValue(link.getValue());
                        }
                    
                    } else {
                        // has Source prop isn't PropertyLink or PropertyLinkGlobal! 
                        Base::Console().Log("DrawViewArch::Restore - old Document Source is weird: %s\n", TypeName);
                        // no idea
                    }
                } else {
                    Base::Console().Log("DrawViewArch::Restore - old Document has unknown Property\n");
                }
            }
        }
        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\n");
        }
#endif

        reader.readEndElement("Property");
    }
    reader.readEndElement("Properties");

}
Example #4
0
bool DlgExtrusion::validate()
{
    //check source shapes
    if (ui->treeWidget->selectedItems().isEmpty()) {
        QMessageBox::critical(this, windowTitle(),
            tr("No shapes selected for extrusion. Select some, first."));
        return false;
    }

    //check axis link
    QString errmsg;
    bool hasValidAxisLink = false;
    try{
        App::PropertyLinkSub lnk;
        this->getAxisLink(lnk);
        Base::Vector3d dir, base;
        hasValidAxisLink = Part::Extrusion::fetchAxisLink(lnk, base, dir);
    } catch(Base::Exception &err) {
        errmsg = QString::fromUtf8(err.what());
    } catch(Standard_Failure &err) {
        errmsg = QString::fromLocal8Bit(err.GetMessageString());
    } catch(...) {
        errmsg = QString::fromUtf8("Unknown error");
    }
    if (this->getDirMode() == Part::Extrusion::dmEdge && !hasValidAxisLink){
        if (errmsg.length() > 0)
            QMessageBox::critical(this, windowTitle(), tr("Extrusion direction link is invalid.\n\n%1").arg(errmsg));
        else
            QMessageBox::critical(this, windowTitle(), tr("Direction mode is to use an edge, but no edge is linked."));
        ui->txtLink->setFocus();
        return false;
    } else if (this->getDirMode() != Part::Extrusion::dmEdge && !hasValidAxisLink){
        //axis link is invalid, but it is not required by the mode. We shouldn't complain it's invalid then...
        ui->txtLink->clear();
    }

    //check normal
    if (this->getDirMode() == Part::Extrusion::dmNormal){
        errmsg.clear();
        try {
            App::PropertyLink lnk;
            lnk.setValue(&this->getShapeToExtrude()); //simplified - check only for the first shape.
            Part::Extrusion::calculateShapeNormal(lnk);
        } catch(Base::Exception &err) {
            errmsg = QString::fromUtf8(err.what());
        } catch(Standard_Failure &err) {
            errmsg = QString::fromLocal8Bit(err.GetMessageString());
        } catch(...) {
            errmsg = QString::fromUtf8("Unknown error");
        }
        if (errmsg.length() > 0){
            QMessageBox::critical(this, windowTitle(), tr("Can't determine normal vector of shape to be extruded. Please use other mode. \n\n(%1)").arg(errmsg));
            ui->rbDirModeNormal->setFocus();
            return false;
        }
    }

    //check axis dir
    if (this->getDirMode() == Part::Extrusion::dmCustom){
        if(this->getDir().Length() < Precision::Confusion()){
            QMessageBox::critical(this, windowTitle(),
                tr("Extrusion direction is zero-length. It must be non-zero."));
            ui->dirX->setFocus();
            return false;
        }
    }

    //check lengths
    if (!ui->chkSymmetric->isChecked()
            && fabs(ui->spinLenFwd->value().getValue() + ui->spinLenRev->value().getValue()) < Precision::Confusion()
            && ! (fabs(ui->spinLenFwd->value().getValue() - ui->spinLenRev->value().getValue()) < Precision::Confusion())){
        QMessageBox::critical(this, windowTitle(),
            tr("Total extrusion length is zero (length1 == -length2). It must be nonzero."));
        ui->spinLenFwd->setFocus();
        return false;
    }

    return true;
}