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()); }
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"); }
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; }