void ProfileBased::generatePrism(TopoDS_Shape& prism, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir, const double L, const double L2, const bool midplane, const bool reversed) { if (method == "Length" || method == "TwoLengths" || method == "ThroughAll") { double Ltotal = L; double Loffset = 0.; if (method == "ThroughAll") // "ThroughAll" is modelled as a very long, but finite prism to avoid problems with pockets // Note: 1E6 created problems once... Ltotal = 1E4; if (method == "TwoLengths") { // midplane makes no sense here Loffset = -L2; Ltotal += L2; } else if (midplane) Loffset = -Ltotal/2; TopoDS_Shape from = sketchshape; if (method == "TwoLengths" || midplane) { gp_Trsf mov; mov.SetTranslation(Loffset * gp_Vec(dir)); TopLoc_Location loc(mov); from = sketchshape.Moved(loc); } else if (reversed) Ltotal *= -1.0; // Its better not to use BRepFeat_MakePrism here even if we have a support because the // resulting shape creates problems with Pocket BRepPrimAPI_MakePrism PrismMaker(from, Ltotal*gp_Vec(dir), 0,1); // finite prism if (!PrismMaker.IsDone()) throw Base::RuntimeError("SketchBased: Length: Could not extrude the sketch!"); prism = PrismMaker.Shape(); } else { throw Base::RuntimeError("SketchBased: Internal error: Unknown method for generatePrism()"); } }
App::DocumentObjectExecReturn *Revolution::execute(void) { App::DocumentObject* link = Sketch.getValue(); if (!link) return new App::DocumentObjectExecReturn("No sketch linked"); if (!link->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a Sketch or Part2DObject"); Part::Part2DObject* pcSketch=static_cast<Part::Part2DObject*>(link); TopoDS_Shape shape = pcSketch->Shape.getShape()._Shape; if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); // this is a workaround for an obscure OCC bug which leads to empty tessellations // for some faces. Making an explicit copy of the linked shape seems to fix it. // The error only happens when re-computing the shape. if (!this->Shape.getValue().IsNull()) { BRepBuilderAPI_Copy copy(shape); shape = copy.Shape(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape object is empty"); } TopExp_Explorer ex; std::vector<TopoDS_Wire> wires; for (ex.Init(shape, TopAbs_WIRE); ex.More(); ex.Next()) { wires.push_back(TopoDS::Wire(ex.Current())); } if (wires.empty()) // there can be several wires return new App::DocumentObjectExecReturn("Linked shape object is not a wire"); // get the Sketch plane Base::Placement SketchPlm = pcSketch->Placement.getValue(); // get reference axis App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); const std::vector<std::string> &subReferenceAxis = ReferenceAxis.getSubValues(); if (pcReferenceAxis && pcReferenceAxis == pcSketch) { bool hasValidAxis=false; Base::Axis axis; if (subReferenceAxis[0] == "V_Axis") { hasValidAxis = true; axis = pcSketch->getAxis(Part::Part2DObject::V_Axis); } else if (subReferenceAxis[0] == "H_Axis") { hasValidAxis = true; axis = pcSketch->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 < pcSketch->getAxisCount()) { hasValidAxis = true; axis = pcSketch->getAxis(AxId); } } if (hasValidAxis) { axis *= SketchPlm; Base::Vector3d base=axis.getBase(); Base::Vector3d dir=axis.getDirection(); Base.setValue(base.x,base.y,base.z); Axis.setValue(dir.x,dir.y,dir.z); } } // get revolve axis Base::Vector3f b = Base.getValue(); gp_Pnt pnt(b.x,b.y,b.z); Base::Vector3f v = Axis.getValue(); gp_Dir dir(v.x,v.y,v.z); // get the support of the Sketch if any App::DocumentObject* pcSupport = pcSketch->Support.getValue(); Part::Feature *SupportObject = 0; if (pcSupport && pcSupport->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) SupportObject = static_cast<Part::Feature*>(pcSupport); TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // Rotate the face by half the angle to get revolution symmetric to sketch plane if (Midplane.getValue()) { gp_Trsf mov; mov.SetRotation(gp_Ax1(pnt, dir), Base::toRadians<double>(Angle.getValue()) * (-1.0) / 2.0); TopLoc_Location loc(mov); aFace.Move(loc); } this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); // Reverse angle if selected double angle = Base::toRadians<double>(Angle.getValue()); if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); try { // revolve the face to a solid BRepPrimAPI_MakeRevol RevolMaker(aFace.Moved(invObjLoc), gp_Ax1(pnt, dir), angle); if (RevolMaker.IsDone()) { TopoDS_Shape result = RevolMaker.Shape(); // if the sketch has a support fuse them to get one result object (PAD!) if (SupportObject) { const TopoDS_Shape& support = SupportObject->Shape.getValue(); if (!support.IsNull() && support.ShapeType() == TopAbs_SOLID) { // set the additive shape property for later usage in e.g. pattern this->AddShape.setValue(result); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(support.Moved(invObjLoc), result); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion with support failed"); result = mkFuse.Shape(); } } this->Shape.setValue(result); } else return new App::DocumentObjectExecReturn("Could not revolve the sketch!"); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }