double ProfileBased::getReversedAngle(const Base::Vector3d &b, const Base::Vector3d &v) { try { Part::Feature* obj = getVerifiedObject(); TopoDS_Shape sketchshape = getVerifiedFace(); // get centre of gravity of the sketch face GProp_GProps props; BRepGProp::SurfaceProperties(sketchshape, props); gp_Pnt cog = props.CentreOfMass(); Base::Vector3d p_cog(cog.X(), cog.Y(), cog.Z()); // get direction to cog from its projection on the revolve axis Base::Vector3d perp_dir = p_cog - p_cog.Perpendicular(b, v); // get cross product of projection direction with revolve axis direction Base::Vector3d cross = v % perp_dir; // get sketch vector pointing away from support material Base::Placement SketchPos = obj->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchNormal(0,0,1); SketchOrientation.multVec(SketchNormal,SketchNormal); return SketchNormal * cross; } catch (...) { return Reversed.getValue() ? 1 : 0; } }
Base::Vector3d ProfileBased::getProfileNormal() const { Base::Vector3d SketchVector(0,0,1); auto obj = getVerifiedObject(true); if(!obj) return SketchVector; // get the Sketch plane if(obj->isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Base::Placement SketchPos = obj->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); SketchOrientation.multVec(SketchVector,SketchVector); } else { TopoDS_Shape shape = getVerifiedFace(true); if (shape == TopoDS_Shape()) return SketchVector; if (shape.ShapeType() == TopAbs_FACE) { BRepAdaptor_Surface adapt(TopoDS::Face(shape)); double u = adapt.FirstUParameter() + (adapt.LastUParameter() - adapt.FirstUParameter())/2.; double v = adapt.FirstVParameter() + (adapt.LastVParameter() - adapt.FirstVParameter())/2.; BRepLProp_SLProps prop(adapt,u,v,2,Precision::Confusion()); if(prop.IsNormalDefined()) { gp_Pnt pnt; gp_Vec vec; // handles the orientation state of the shape BRepGProp_Face(TopoDS::Face(shape)).Normal(u,v,pnt,vec); SketchVector = Base::Vector3d(vec.X(), vec.Y(), vec.Z()); } } } return SketchVector; }
PyObject* RotationPy::isNull(PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; Base::Rotation rot = * getRotationPtr(); Base::Rotation nullrot(0,0,0,1); bool null = rot.isSame(nullrot); return Py_BuildValue("O", (null ? Py_True : Py_False)); }
gp_Pln Feature::makePlnFromPlane(const App::DocumentObject* obj) { const App::GeoFeature* plane = static_cast<const App::GeoFeature*>(obj); if (plane == NULL) throw Base::Exception("Feature: Null object"); Base::Vector3d pos = plane->Placement.getValue().getPosition(); Base::Rotation rot = plane->Placement.getValue().getRotation(); Base::Vector3d normal(0,0,1); rot.multVec(normal, normal); return gp_Pln(gp_Pnt(pos.x,pos.y,pos.z), gp_Dir(normal.x,normal.y,normal.z)); }
void TaskDatumParameters::updateSuperplacementUI() { Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject()); Base::Placement pl = pcDatum->superPlacement.getValue(); Base::Vector3d pos = pl.getPosition(); Base::Rotation rot = pl.getRotation(); double yaw, pitch, roll; rot.getYawPitchRoll(yaw, pitch, roll); bool bBlock = true; ui->superplacementX->blockSignals(bBlock); ui->superplacementY->blockSignals(bBlock); ui->superplacementZ->blockSignals(bBlock); ui->superplacementYaw->blockSignals(bBlock); ui->superplacementPitch->blockSignals(bBlock); ui->superplacementRoll->blockSignals(bBlock); ui->superplacementX->setValue(Base::Quantity(pos.x,Base::Unit::Length)); ui->superplacementY->setValue(Base::Quantity(pos.y,Base::Unit::Length)); ui->superplacementZ->setValue(Base::Quantity(pos.z,Base::Unit::Length)); ui->superplacementYaw->setValue(yaw); ui->superplacementPitch->setValue(pitch); ui->superplacementRoll->setValue(roll); auto expressions = pcDatum->ExpressionEngine.getExpressions(); bool bRotationBound = false; bRotationBound = bRotationBound || expressions.find(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Rotation.Angle"))) != expressions.end(); bRotationBound = bRotationBound || expressions.find(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Rotation.Axis.x"))) != expressions.end(); bRotationBound = bRotationBound || expressions.find(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Rotation.Axis.y"))) != expressions.end(); bRotationBound = bRotationBound || expressions.find(App::ObjectIdentifier::parse(pcDatum,std::string("superPlacement.Rotation.Axis.z"))) != expressions.end(); ui->superplacementYaw->setEnabled(!bRotationBound); ui->superplacementPitch->setEnabled(!bRotationBound); ui->superplacementRoll->setEnabled(!bRotationBound); QString tooltip = bRotationBound ? tr("Not editable because rotation part of superplacement is bound by expressions.") : QString(); ui->superplacementYaw->setToolTip(tooltip); ui->superplacementPitch->setToolTip(tooltip); ui->superplacementRoll->setToolTip(tooltip); bBlock = false; ui->superplacementX->blockSignals(bBlock); ui->superplacementY->blockSignals(bBlock); ui->superplacementZ->blockSignals(bBlock); ui->superplacementYaw->blockSignals(bBlock); ui->superplacementPitch->blockSignals(bBlock); ui->superplacementRoll->blockSignals(bBlock); }
// constructor method int RotationPy::PyInit(PyObject* args, PyObject* /*kwd*/) { PyObject* o; if (PyArg_ParseTuple(args, "")) { return 0; } PyErr_Clear(); if (PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type), &o)) { Base::Rotation *rot = static_cast<Base::RotationPy*>(o)->getRotationPtr(); getRotationPtr()->setValue(rot->getValue()); return 0; } PyErr_Clear(); double angle; if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &o, &angle)) { // NOTE: The last parameter defines the rotation angle in degree. getRotationPtr()->setValue(static_cast<Base::VectorPy*>(o)->value(), Base::toRadians<double>(angle)); return 0; } PyErr_Clear(); double q0, q1, q2, q3; if (PyArg_ParseTuple(args, "dddd", &q0, &q1, &q2, &q3)) { getRotationPtr()->setValue(q0, q1, q2, q3); return 0; } PyErr_Clear(); double y, p, r; if (PyArg_ParseTuple(args, "ddd", &y, &p, &r)) { getRotationPtr()->setYawPitchRoll(y, p, r); return 0; } PyErr_Clear(); PyObject *v1, *v2; if (PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type), &v1, &(Base::VectorPy::Type), &v2)) { Py::Vector from(v1, false); Py::Vector to(v2, false); getRotationPtr()->setValue(from.toVector(), to.toVector()); return 0; } PyErr_SetString(PyExc_Exception, "empty parameter list, four floats or Vector and float"); return -1; }
void TaskDatumParameters::onSuperplacementChanged(double /*val*/, int idx) { Part::Datum* pcDatum = static_cast<Part::Datum*>(DatumView->getObject()); Base::Placement pl = pcDatum->superPlacement.getValue(); Base::Vector3d pos = pl.getPosition(); if (idx == 0) { pos.x = ui->superplacementX->value().getValueAs(Base::Quantity::MilliMetre); } if (idx == 1) { pos.y = ui->superplacementY->value().getValueAs(Base::Quantity::MilliMetre); } if (idx == 2) { pos.z = ui->superplacementZ->value().getValueAs(Base::Quantity::MilliMetre); } if (idx >= 0 && idx <= 2){ pl.setPosition(pos); } Base::Rotation rot = pl.getRotation(); double yaw, pitch, roll; rot.getYawPitchRoll(yaw, pitch, roll); if (idx == 3) { yaw = ui->superplacementYaw->value().getValueAs(Base::Quantity::Degree); } if (idx == 4) { pitch = ui->superplacementPitch->value().getValueAs(Base::Quantity::Degree); } if (idx == 5) { roll = ui->superplacementRoll->value().getValueAs(Base::Quantity::Degree); } if (idx >= 3 && idx <= 5){ rot.setYawPitchRoll(yaw,pitch,roll); pl.setRotation(rot); } pcDatum->superPlacement.setValue(pl); updatePreview(); }
Base::Placement Transform::getPlacementData() const { int index = ui->rotationInput->currentIndex(); Base::Rotation rot; Base::Vector3d pos; Base::Vector3d cnt; pos = Base::Vector3d(ui->xPos->value().getValue(),ui->yPos->value().getValue(),ui->zPos->value().getValue()); cnt = Base::Vector3d(ui->xCnt->value().getValue(),ui->yCnt->value().getValue(),ui->zCnt->value().getValue()); if (index == 0) { Base::Vector3d dir = getDirection(); rot.setValue(Base::Vector3d(dir.x,dir.y,dir.z),ui->angle->value().getValue()*D_PI/180.0); } else if (index == 1) { rot.setYawPitchRoll( ui->yawAngle->value().getValue(), ui->pitchAngle->value().getValue(), ui->rollAngle->value().getValue()); } Base::Placement p(pos, rot, cnt); return p; }
bool Revolution::suggestReversed(void) { try { updateAxis(); Part::Part2DObject* sketch = getVerifiedSketch(); std::vector<TopoDS_Wire> wires = getSketchWires(); TopoDS_Shape sketchshape = makeFace(wires); Base::Vector3d b = Base.getValue(); Base::Vector3d v = Axis.getValue(); // get centre of gravity of the sketch face GProp_GProps props; BRepGProp::SurfaceProperties(sketchshape, props); gp_Pnt cog = props.CentreOfMass(); Base::Vector3d p_cog(cog.X(), cog.Y(), cog.Z()); // get direction to cog from its projection on the revolve axis Base::Vector3d perp_dir = p_cog - p_cog.Perpendicular(b, v); // get cross product of projection direction with revolve axis direction Base::Vector3d cross = v % perp_dir; // get sketch vector pointing away from support material Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchNormal(0,0,1); SketchOrientation.multVec(SketchNormal,SketchNormal); // simply convert double to float Base::Vector3d norm(SketchNormal.x, SketchNormal.y, SketchNormal.z); // return true if the angle between norm and cross is obtuse return norm * cross < 0.f; } catch (...) { return Reversed.getValue(); } }
void ComplexGeoData::applyRotation(const Base::Rotation& rot) { Base::Matrix4D mat; rot.getValue(mat); setTransform(mat * getTransform()); }
void ProfileBased::getAxis(const App::DocumentObject *pcReferenceAxis, const std::vector<std::string> &subReferenceAxis, Base::Vector3d& base, Base::Vector3d& dir) { dir = Base::Vector3d(0,0,0); // If unchanged signals that no valid axis was found if (pcReferenceAxis == NULL) return; App::DocumentObject* profile = Profile.getValue(); gp_Pln sketchplane; if (profile->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* sketch = getVerifiedSketch(); Base::Placement SketchPlm = sketch->Placement.getValue(); Base::Vector3d SketchVector = Base::Vector3d(0, 0, 1); Base::Rotation SketchOrientation = SketchPlm.getRotation(); SketchOrientation.multVec(SketchVector, SketchVector); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); if (pcReferenceAxis == profile) { bool hasValidAxis = false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = sketch->getAxis(Part::Part2DObject::H_Axis); } else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0, 4) == "Axis") { int AxId = std::atoi(subReferenceAxis[0].substr(4, 4000).c_str()); if (AxId >= 0 && AxId < sketch->getAxisCount()) { hasValidAxis = true; axis = sketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; base = axis.getBase(); dir = axis.getDirection(); return; } //else - an edge of the sketch was selected as an axis } } else if (profile->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Base::Placement SketchPlm = getVerifiedObject()->Placement.getValue(); Base::Vector3d SketchVector = getProfileNormal(); Base::Vector3d SketchPos = SketchPlm.getPosition(); sketchplane = gp_Pln(gp_Pnt(SketchPos.x, SketchPos.y, SketchPos.z), gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); } // get reference axis if (pcReferenceAxis->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { const PartDesign::Line* line = static_cast<const PartDesign::Line*>(pcReferenceAxis); base = line->getBasePoint(); dir = line->getDirection(); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { const App::Line* line = static_cast<const App::Line*>(pcReferenceAxis); base = Base::Vector3d(0,0,0); line->Placement.getValue().multVec(Base::Vector3d (1,0,0), dir); // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(gp_Dir(dir.x, dir.y, dir.z), Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } if (pcReferenceAxis->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subReferenceAxis.empty()) throw Base::ValueError("No rotation axis reference specified"); const Part::Feature* refFeature = static_cast<const Part::Feature*>(pcReferenceAxis); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subReferenceAxis[0].c_str()); if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::ValueError("Failed to extract rotation edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::TypeError("Rotation edge must be a straight line"); gp_Pnt b = adapt.Line().Location(); base = Base::Vector3d(b.X(), b.Y(), b.Z()); gp_Dir d = adapt.Line().Direction(); dir = Base::Vector3d(d.X(), d.Y(), d.Z()); // Check that axis is co-planar with sketch plane! // Check that axis is perpendicular with sketch plane! if (sketchplane.Axis().Direction().IsParallel(d, Precision::Angular())) throw Base::ValueError("Rotation axis must not be perpendicular with the sketch plane"); return; } else { throw Base::TypeError("Rotation reference must be an edge"); } } throw Base::TypeError("Rotation axis reference is invalid"); }
App::DocumentObjectExecReturn *Pad::execute(void) { // Validate parameters double L = Length.getValue(); if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Length of pad too small"); double L2 = Length2.getValue(); if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Second length of pad too small"); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; try { sketch = getVerifiedSketch(); wires = getSketchWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } TopoDS_Shape support; try { support = getSupportShape(); } catch (const Base::Exception&) { // ignore, because support isn't mandatory support = TopoDS_Shape(); } // get the Sketch plane Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchVector(0,0,1); SketchOrientation.multVec(SketchVector,SketchVector); this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); try { support.Move(invObjLoc); gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pad: Creating a face from sketch failed"); sketchshape.Move(invObjLoc); TopoDS_Shape prism; std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") { TopoDS_Face supportface = getSupportFace(); supportface.Move(invObjLoc); if (Reversed.getValue()) dir.Reverse(); // Find a valid face to extrude up to TopoDS_Face upToFace; if (method == "UpToFace") { getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } getUpToFace(upToFace, support, supportface, sketchshape, method, dir); // A support object is always required and we need to use BRepFeat_MakePrism // Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid // because the feature does not add any material. This only happens with the "2" option, though // Note: It might be possible to pass a shell or a compound containing multiple faces // as the Until parameter of Perform() BRepFeat_MakePrism PrismMaker; PrismMaker.Init(support, sketchshape, supportface, dir, 2, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!"); prism = PrismMaker.Shape(); } else { generatePrism(prism, sketchshape, method, dir, L, L2, Midplane.getValue(), Reversed.getValue()); } if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is empty"); // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(prism); // if the sketch has a support fuse them to get one result object if (!support.IsNull()) { // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support, prism); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) return new App::DocumentObjectExecReturn("Pad: Fusion with support failed"); TopoDS_Shape result = mkFuse.Shape(); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(result); // lets check if the result is a solid if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pad: Resulting shape is not a solid"); this->Shape.setValue(solRes); } else { this->Shape.setValue(prism); } return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face") return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
// constructor method int RotationPy::PyInit(PyObject* args, PyObject* /*kwd*/) { PyObject* o; if (PyArg_ParseTuple(args, "")) { return 0; } PyErr_Clear(); if (PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type), &o)) { Base::Rotation *rot = static_cast<Base::RotationPy*>(o)->getRotationPtr(); getRotationPtr()->setValue(rot->getValue()); return 0; } PyErr_Clear(); double angle; if (PyArg_ParseTuple(args, "O!d", &(Base::VectorPy::Type), &o, &angle)) { // NOTE: The last parameter defines the rotation angle in degree. getRotationPtr()->setValue(static_cast<Base::VectorPy*>(o)->value(), Base::toRadians<double>(angle)); return 0; } PyErr_Clear(); if (PyArg_ParseTuple(args, "O!d", &(Base::MatrixPy::Type), &o, &angle)) { // NOTE: The last parameter defines the rotation angle in degree. getRotationPtr()->setValue(static_cast<Base::MatrixPy*>(o)->value()); return 0; } PyErr_Clear(); double q0, q1, q2, q3; if (PyArg_ParseTuple(args, "dddd", &q0, &q1, &q2, &q3)) { getRotationPtr()->setValue(q0, q1, q2, q3); return 0; } PyErr_Clear(); double y, p, r; if (PyArg_ParseTuple(args, "ddd", &y, &p, &r)) { getRotationPtr()->setYawPitchRoll(y, p, r); return 0; } double a11 = 1.0, a12 = 0.0, a13 = 0.0, a14 = 0.0; double a21 = 0.0, a22 = 1.0, a23 = 0.0, a24 = 0.0; double a31 = 0.0, a32 = 0.0, a33 = 1.0, a34 = 0.0; double a41 = 0.0, a42 = 0.0, a43 = 0.0, a44 = 1.0; // try read a 4x4 matrix PyErr_Clear(); if (PyArg_ParseTuple(args, "dddddddddddddddd", &a11, &a12, &a13, &a14, &a21, &a22, &a23, &a24, &a31, &a32, &a33, &a34, &a41, &a42, &a43, &a44)) { Matrix4D mtx(a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44); getRotationPtr()->setValue(mtx); return 0; } // try read a 3x3 matrix PyErr_Clear(); if (PyArg_ParseTuple(args, "ddddddddd", &a11, &a12, &a13, &a21, &a22, &a23, &a31, &a32, &a33)) { Matrix4D mtx(a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44); getRotationPtr()->setValue(mtx); return 0; } PyErr_Clear(); PyObject *v1, *v2; if (PyArg_ParseTuple(args, "O!O!", &(Base::VectorPy::Type), &v1, &(Base::VectorPy::Type), &v2)) { Py::Vector from(v1, false); Py::Vector to(v2, false); getRotationPtr()->setValue(from.toVector(), to.toVector()); return 0; } PyErr_Clear(); PyObject *v3; char *priority = nullptr; if (PyArg_ParseTuple(args, "O!O!O!|s", &(Base::VectorPy::Type), &v1, &(Base::VectorPy::Type), &v2, &(Base::VectorPy::Type), &v3, &priority )) { Py::Vector xdir(v1, false); Py::Vector ydir(v2, false); Py::Vector zdir(v3, false); if (!priority) priority = "ZXY"; try { *getRotationPtr() = (Rotation::makeRotationByAxes(xdir.toVector(), ydir.toVector(), zdir.toVector(), priority)); } catch(Base::Exception &e) { std::string str; str += "FreeCAD exception thrown ("; str += e.what(); str += ")"; PyErr_SetString(Base::BaseExceptionFreeCADError,str.c_str()); return -1; } return 0; } PyErr_SetString(PyExc_TypeError, "Rotation constructor accepts:\n" "-- empty parameter list\n" "-- Rotation object" "-- four floats (a quaternion)\n" "-- three floats (yaw, pitch, roll)" "-- Vector (rotation axis) and float (rotation angle)\n" "-- two Vectors (two axes)\n" "-- Matrix object\n" "-- 16 floats (4x4 matrix)\n" "-- 9 floats (3x3 matrix)\n" "-- 3 vectors + optional string" ); return -1; }
App::DocumentObjectExecReturn *Pocket::execute(void) { // Handle legacy features, these typically have Type set to 3 (previously NULL, now UpToFace), // empty FaceName (because it didn't exist) and a value for Length if (std::string(Type.getValueAsString()) == "UpToFace" && (UpToFace.getValue() == NULL && Length.getValue() > Precision::Confusion())) Type.setValue("Length"); // Validate parameters double L = Length.getValue(); if ((std::string(Type.getValueAsString()) == "Length") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Pocket: Length of pocket too small"); Part::Part2DObject* sketch = 0; std::vector<TopoDS_Wire> wires; TopoDS_Shape support; try { sketch = getVerifiedSketch(); wires = getSketchWires(); support = getSupportShape(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } // get the Sketch plane Base::Placement SketchPos = sketch->Placement.getValue(); Base::Rotation SketchOrientation = SketchPos.getRotation(); Base::Vector3d SketchVector(0,0,1); SketchOrientation.multVec(SketchVector,SketchVector); // turn around for pockets SketchVector *= -1; this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); try { support.Move(invObjLoc); gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); dir.Transform(invObjLoc.Transformation()); TopoDS_Shape sketchshape = makeFace(wires); if (sketchshape.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Creating a face from sketch failed"); sketchshape.Move(invObjLoc); std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToFace") { TopoDS_Face supportface = getSupportFace(); supportface.Move(invObjLoc); // Find a valid face to extrude up to TopoDS_Face upToFace; if (method == "UpToFace") { getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } getUpToFace(upToFace, support, supportface, sketchshape, method, dir); // Special treatment because often the created stand-alone prism is invalid (empty) because // BRepFeat_MakePrism(..., 2, 1) is buggy BRepFeat_MakePrism PrismMaker; PrismMaker.Init(support, sketchshape, supportface, dir, 0, 1); PrismMaker.Perform(upToFace); if (!PrismMaker.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not extrude the sketch!"); TopoDS_Shape prism = PrismMaker.Shape(); prism = refineShapeIfActive(prism); // And the really expensive way to get the SubShape... BRepAlgoAPI_Cut mkCut(support, prism); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Up to face: Could not get SubShape!"); // FIXME: In some cases this affects the Shape property: It is set to the same shape as the SubShape!!!! TopoDS_Shape result = refineShapeIfActive(mkCut.Shape()); this->SubShape.setValue(result); this->Shape.setValue(prism); } else { TopoDS_Shape prism; generatePrism(prism, sketchshape, method, dir, L, 0.0, Midplane.getValue(), Reversed.getValue()); if (prism.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is empty"); // set the subtractive shape property for later usage in e.g. pattern prism = refineShapeIfActive(prism); this->SubShape.setValue(prism); // Cut the SubShape out of the support BRepAlgoAPI_Cut mkCut(support, prism); if (!mkCut.IsDone()) return new App::DocumentObjectExecReturn("Pocket: Cut out of support failed"); TopoDS_Shape result = mkCut.Shape(); // we have to get the solids (fuse sometimes creates compounds) TopoDS_Shape solRes = this->getSolid(result); if (solRes.IsNull()) return new App::DocumentObjectExecReturn("Pocket: Resulting shape is not a solid"); solRes = refineShapeIfActive(solRes); remapSupportShape(solRes); this->Shape.setValue(solRes); } return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); if (std::string(e->GetMessageString()) == "TopoDS::Face" && (std::string(Type.getValueAsString()) == "UpToFirst" || std::string(Type.getValueAsString()) == "UpToFace")) return new App::DocumentObjectExecReturn("Could not create face from sketch.\n" "Intersecting sketch entities or multiple faces in a sketch are not allowed " "for making a pocket up to a face."); else return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } }
const std::list<gp_Trsf> LinearPattern::getTransformations(const std::vector<App::DocumentObject*>) { double distance = Length.getValue(); if (distance < Precision::Confusion()) throw Base::Exception("Pattern length too small"); int occurrences = Occurrences.getValue(); if (occurrences < 2) throw Base::Exception("At least two occurrences required"); bool reversed = Reversed.getValue(); double offset = distance / (occurrences - 1); App::DocumentObject* refObject = Direction.getValue(); if (refObject == NULL) throw Base::Exception("No direction reference specified"); std::vector<std::string> subStrings = Direction.getSubValues(); if (subStrings.empty()) throw Base::Exception("No direction reference specified"); gp_Dir dir; if (refObject->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { Part::Part2DObject* refSketch = static_cast<Part::Part2DObject*>(refObject); Base::Axis axis; if (subStrings[0] == "H_Axis") axis = refSketch->getAxis(Part::Part2DObject::H_Axis); else if (subStrings[0] == "V_Axis") axis = refSketch->getAxis(Part::Part2DObject::V_Axis); else if (subStrings[0] == "N_Axis") axis = refSketch->getAxis(Part::Part2DObject::N_Axis); else if (subStrings[0].size() > 4 && subStrings[0].substr(0,4) == "Axis") { int AxId = std::atoi(subStrings[0].substr(4,4000).c_str()); if (AxId >= 0 && AxId < refSketch->getAxisCount()) axis = refSketch->getAxis(AxId); } axis *= refSketch->Placement.getValue(); dir = gp_Dir(axis.getDirection().x, axis.getDirection().y, axis.getDirection().z); } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Plane::getClassTypeId())) { PartDesign::Plane* plane = static_cast<PartDesign::Plane*>(refObject); Base::Vector3d d = plane->getNormal(); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(PartDesign::Line::getClassTypeId())) { PartDesign::Line* line = static_cast<PartDesign::Line*>(refObject); Base::Vector3d d = line->getDirection(); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { App::Line* line = static_cast<App::Line*>(refObject); Base::Rotation rot = line->Placement.getValue().getRotation(); Base::Vector3d d(1,0,0); rot.multVec(d, d); dir = gp_Dir(d.x, d.y, d.z); } else if (refObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { if (subStrings[0].empty()) throw Base::Exception("No direction reference specified"); Part::Feature* refFeature = static_cast<Part::Feature*>(refObject); Part::TopoShape refShape = refFeature->Shape.getShape(); TopoDS_Shape ref = refShape.getSubShape(subStrings[0].c_str()); if (ref.ShapeType() == TopAbs_FACE) { TopoDS_Face refFace = TopoDS::Face(ref); if (refFace.IsNull()) throw Base::Exception("Failed to extract direction plane"); BRepAdaptor_Surface adapt(refFace); if (adapt.GetType() != GeomAbs_Plane) throw Base::Exception("Direction face must be planar"); dir = adapt.Plane().Axis().Direction(); } else if (ref.ShapeType() == TopAbs_EDGE) { TopoDS_Edge refEdge = TopoDS::Edge(ref); if (refEdge.IsNull()) throw Base::Exception("Failed to extract direction edge"); BRepAdaptor_Curve adapt(refEdge); if (adapt.GetType() != GeomAbs_Line) throw Base::Exception("Direction edge must be a straight line"); dir = adapt.Line().Direction(); } else { throw Base::Exception("Direction reference must be edge or face"); } } else { throw Base::Exception("Direction reference must be edge/face of a feature or a datum line/plane"); } TopLoc_Location invObjLoc = this->getLocation().Inverted(); dir.Transform(invObjLoc.Transformation()); gp_Vec direction(dir.X(), dir.Y(), dir.Z()); if (reversed) direction.Reverse(); // Note: The original feature is NOT included in the list of transformations! Therefore // we start with occurrence number 1, not number 0 std::list<gp_Trsf> transformations; gp_Trsf trans; transformations.push_back(trans); // identity transformation for (int i = 1; i < occurrences; i++) { trans.SetTranslation(direction * i * offset); transformations.push_back(trans); } return transformations; }