PyObject* TopoShapeWirePy::fixWire(PyObject *args) { PyObject* face=0; double tol = Precision::Confusion(); if (!PyArg_ParseTuple(args, "|O!d",&(TopoShapeFacePy::Type), &face, &tol)) return 0; try { ShapeFix_Wire aFix; const TopoDS_Wire& w = TopoDS::Wire(getTopoShapePtr()->_Shape); if (face) { const TopoDS_Face& f = TopoDS::Face(static_cast<TopoShapePy*>(face)->getTopoShapePtr()->_Shape); aFix.Init(w, f, tol); } else { aFix.SetPrecision(tol); aFix.Load(w); } aFix.FixReorder(); aFix.FixConnected(); aFix.FixClosed(); getTopoShapePtr()->_Shape = aFix.Wire(); Py_Return; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PyExc_Exception, e->GetMessageString()); return 0; } }
PyObject* TopoShapeFacePy::validate(PyObject *args) { if (!PyArg_ParseTuple(args, "")) return 0; try { const TopoDS_Face& face = TopoDS::Face(getTopoShapePtr()->getShape()); BRepCheck_Analyzer aChecker(face); if (!aChecker.IsValid()) { TopoDS_Wire outerwire = ShapeAnalysis::OuterWire(face); TopTools_IndexedMapOfShape myMap; myMap.Add(outerwire); TopExp_Explorer xp(face,TopAbs_WIRE); ShapeFix_Wire fix; fix.SetFace(face); fix.Load(outerwire); fix.Perform(); BRepBuilderAPI_MakeFace mkFace(fix.WireAPIMake()); while (xp.More()) { if (!myMap.Contains(xp.Current())) { fix.Load(TopoDS::Wire(xp.Current())); fix.Perform(); mkFace.Add(fix.WireAPIMake()); } xp.Next(); } aChecker.Init(mkFace.Face()); if (!aChecker.IsValid()) { ShapeFix_Shape fix(mkFace.Face()); fix.SetPrecision(Precision::Confusion()); fix.SetMaxTolerance(Precision::Confusion()); fix.SetMaxTolerance(Precision::Confusion()); fix.Perform(); fix.FixWireTool()->Perform(); fix.FixFaceTool()->Perform(); getTopoShapePtr()->setShape(fix.Shape()); } else { getTopoShapePtr()->setShape(mkFace.Face()); } } Py_Return; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
void Extrusion::makeDraft(ExtrusionParameters params, const TopoDS_Shape& shape, std::list<TopoDS_Shape>& drafts) { double distanceFwd = tan(params.taperAngleFwd)*params.lengthFwd; double distanceRev = tan(params.taperAngleRev)*params.lengthRev; gp_Vec vecFwd = gp_Vec(params.dir)*params.lengthFwd; gp_Vec vecRev = gp_Vec(params.dir.Reversed())*params.lengthRev; bool bFwd = fabs(params.lengthFwd) > Precision::Confusion(); bool bRev = fabs(params.lengthRev) > Precision::Confusion(); bool bMid = !bFwd || !bRev || params.lengthFwd*params.lengthRev > 0.0; //include the source shape as loft section? TopoDS_Wire sourceWire; if (shape.IsNull()) Standard_Failure::Raise("Not a valid shape"); if (shape.ShapeType() == TopAbs_WIRE) { ShapeFix_Wire aFix; aFix.Load(TopoDS::Wire(shape)); aFix.FixReorder(); aFix.FixConnected(); aFix.FixClosed(); sourceWire = aFix.Wire(); } else if (shape.ShapeType() == TopAbs_FACE) { TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape)); sourceWire = outerWire; } else if (shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape); for (; it.More(); it.Next()) { makeDraft(params, it.Value(), drafts); } } else { Standard_Failure::Raise("Only a wire or a face is supported"); } if (!sourceWire.IsNull()) { std::list<TopoDS_Wire> list_of_sections; //first. add wire for reversed part of extrusion if (bRev){ gp_Vec translation = vecRev; double offset = distanceRev; BRepOffsetAPI_MakeOffset mkOffset; #if OCC_VERSION_HEX >= 0x060800 mkOffset.Init(GeomAbs_Arc); #endif #if OCC_VERSION_HEX >= 0x070000 mkOffset.Init(GeomAbs_Intersection); #endif gp_Trsf mat; mat.SetTranslation(translation); TopLoc_Location loc(mat); TopoDS_Wire movedSourceWire = TopoDS::Wire(sourceWire.Moved(loc)); TopoDS_Shape offsetShape; if (fabs(offset)>Precision::Confusion()){ mkOffset.AddWire(movedSourceWire); mkOffset.Perform(offset); offsetShape = mkOffset.Shape(); } else { //stupid OCC doesn't understand, what to do when offset value is zero =/ offsetShape = movedSourceWire; } if (offsetShape.IsNull()) Standard_Failure::Raise("Tapered shape is empty"); TopAbs_ShapeEnum type = offsetShape.ShapeType(); if (type == TopAbs_WIRE) { list_of_sections.push_back(TopoDS::Wire(offsetShape)); } else if (type == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(offsetShape)); list_of_sections.push_back(mkWire.Wire()); } else { Standard_Failure::Raise("Tapered shape type is not supported"); } } //next. Add source wire as middle section. Order is important. if (bMid){ list_of_sections.push_back(sourceWire); } //finally. Forward extrusion offset wire. if (bFwd){ gp_Vec translation = vecFwd; double offset = distanceFwd; BRepOffsetAPI_MakeOffset mkOffset; #if OCC_VERSION_HEX >= 0x060800 mkOffset.Init(GeomAbs_Arc); #endif #if OCC_VERSION_HEX >= 0x070000 mkOffset.Init(GeomAbs_Intersection); #endif gp_Trsf mat; mat.SetTranslation(translation); TopLoc_Location loc(mat); TopoDS_Wire movedSourceWire = TopoDS::Wire(sourceWire.Moved(loc)); TopoDS_Shape offsetShape; if (fabs(offset)>Precision::Confusion()){ mkOffset.AddWire(movedSourceWire); mkOffset.Perform(offset); offsetShape = mkOffset.Shape(); } else { //stupid OCC doesn't understand, what to do when offset value is zero =/ offsetShape = movedSourceWire; } if (offsetShape.IsNull()) Standard_Failure::Raise("Tapered shape is empty"); TopAbs_ShapeEnum type = offsetShape.ShapeType(); if (type == TopAbs_WIRE) { list_of_sections.push_back(TopoDS::Wire(offsetShape)); } else if (type == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(offsetShape)); list_of_sections.push_back(mkWire.Wire()); } else { Standard_Failure::Raise("Tapered shape type is not supported"); } } //make loft BRepOffsetAPI_ThruSections mkGenerator(params.solid ? Standard_True : Standard_False, /*ruled=*/Standard_True); for (std::list<TopoDS_Wire>::const_iterator it = list_of_sections.begin(); it != list_of_sections.end(); ++it) { const TopoDS_Wire &wire = *it; mkGenerator.AddWire(wire); } try { #if defined(__GNUC__) && defined (FC_OS_LINUX) Base::SignalException se; #endif mkGenerator.Build(); drafts.push_back(mkGenerator.Shape()); } catch (Standard_Failure &){ throw; } catch (...) { throw Base::Exception("Unknown exception from BRepOffsetAPI_ThruSections"); } } }
TopoDS_Face FaceMakerCheese::validateFace(const TopoDS_Face& face) { BRepCheck_Analyzer aChecker(face); if (!aChecker.IsValid()) { TopoDS_Wire outerwire = ShapeAnalysis::OuterWire(face); TopTools_IndexedMapOfShape myMap; myMap.Add(outerwire); TopExp_Explorer xp(face,TopAbs_WIRE); ShapeFix_Wire fix; fix.SetFace(face); fix.Load(outerwire); fix.Perform(); BRepBuilderAPI_MakeFace mkFace(fix.WireAPIMake()); while (xp.More()) { if (!myMap.Contains(xp.Current())) { fix.Load(TopoDS::Wire(xp.Current())); fix.Perform(); mkFace.Add(fix.WireAPIMake()); } xp.Next(); } aChecker.Init(mkFace.Face()); if (!aChecker.IsValid()) { ShapeFix_Shape fix(mkFace.Face()); fix.SetPrecision(Precision::Confusion()); fix.SetMaxTolerance(Precision::Confusion()); fix.SetMaxTolerance(Precision::Confusion()); fix.Perform(); fix.FixWireTool()->Perform(); fix.FixFaceTool()->Perform(); TopoDS_Face fixedFace = TopoDS::Face(fix.Shape()); aChecker.Init(fixedFace); if (!aChecker.IsValid()) Standard_Failure::Raise("Failed to validate broken face"); return fixedFace; } return mkFace.Face(); } return face; }
void Run() { std::list<HeeksObj*>::const_iterator It; for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++) { HeeksObj* obj = (HeeksObj*)*It; if(obj->GetType() == SketchType) { CSketch* sketch = (CSketch*)obj; std::list<TopoDS_Shape> wires; if (! ConvertSketchToFaceOrWire( sketch, wires, false)) { wxMessageBox(_("Failed to convert sketch to wire")); } // End if - then else { try { // For all wires in this sketch... for(std::list<TopoDS_Shape>::iterator It2 = wires.begin(); It2 != wires.end(); It2++) { TopoDS_Shape& wire_to_fix = *It2; ShapeFix_Wire fix; fix.Load( TopoDS::Wire(wire_to_fix) ); // fix.ClearModes(); fix.ModifyTopologyMode() = sketch_tool_options.m_modify_topology; fix.ModifyGeometryMode() = sketch_tool_options.m_modify_geometry; fix.ClosedWireMode() = sketch_tool_options.m_closed_wire; fix.PreferencePCurveMode() = sketch_tool_options.m_preference_pcurve; fix.FixGapsByRangesMode() = sketch_tool_options.m_fix_gaps_by_ranges; fix.FixSelfIntersectionMode() = sketch_tool_options.m_fix_self_intersection; fix.FixReorderMode() = sketch_tool_options.m_reorder; fix.FixDegeneratedMode() = sketch_tool_options.m_fix_degenerated; if (sketch_tool_options.m_fix_small) { fix.FixSmallMode() = true; fix.FixSmall( false, sketch_tool_options.m_fix_small_precision ); } if (sketch_tool_options.m_fix_lacking) { fix.FixLackingMode() = sketch_tool_options.m_fix_lacking; fix.FixLacking(false); } if (! fix.Perform()) { wxMessageBox(_("Wire fix failed")); } else { TopoDS_Shape wire = fix.Wire(); HeeksObj *new_sketch = heekscad_interface.NewSketch(); double deviation = 0.001; if (! ConvertWireToSketch(TopoDS::Wire(wire), new_sketch, deviation)) { wxMessageBox(_("Failed to convert wire to sketch")); } else { if (sketch != NULL) { heekscad_interface.Remove( sketch ); sketch = NULL; } heekscad_interface.Add(new_sketch, NULL); } } } } // End try catch (Standard_Failure & error) { (void) error; // Avoid the compiler warning. Handle_Standard_Failure e = Standard_Failure::Caught(); wxMessageBox(_("Failed to fix wire")); } // End catch } } } }
/** We can see what diameter tool was used to create the pocket or contour child operation. We assume that this has already occured. We want to fit down into the slot cut by these operations as far as possible but only touching the appropriate side of the material (inside or outside). We also need to make sure we don't go too deep. If the chamfering bit is small while the endmill used to cut the profile or contour was large then we may need to limit the depth of cut. */ Python CChamfer::AppendTextForProfileChildren( CMachineState *pMachineState, const double theta, HeeksObj *child, CTool *pChamferingBit ) { Python python; unsigned int number_of_bad_sketches = 0; double tolerance = heeksCAD->GetTolerance(); double start_depth = 0.0; double final_depth = 0.0; double clearance_height = 0.0; double rapid_safety_space = 0.0; std::list<HeeksObj *> sketches; CDepthOp *pDepthOp = dynamic_cast<CDepthOp *>(child); if (pDepthOp == NULL) { start_depth = m_depth_op_params.m_start_depth; final_depth = m_depth_op_params.m_final_depth; clearance_height = m_depth_op_params.ClearanceHeight(); rapid_safety_space = m_depth_op_params.m_rapid_safety_space; if (child->GetType() == SketchType) { sketches.push_back(child); } } else { start_depth = pDepthOp->m_depth_op_params.m_start_depth; final_depth = pDepthOp->m_depth_op_params.m_final_depth; clearance_height = pDepthOp->m_depth_op_params.ClearanceHeight(); rapid_safety_space = pDepthOp->m_depth_op_params.m_rapid_safety_space; for (HeeksObj *object = child->GetFirstChild(); object != NULL; object = child->GetNextChild()) { if (object->GetType() == SketchType) { sketches.push_back(object); } } } for (std::list<HeeksObj *>::iterator itChild = sketches.begin(); itChild != sketches.end(); itChild++) { HeeksObj *object = *itChild; std::list<TopoDS_Shape> wires; if (! heeksCAD->ConvertSketchToFaceOrWire( object, wires, false)) { number_of_bad_sketches++; } // End if - then else { // The wire(s) represent the sketch objects for a tool path. if (object->GetShortString() != NULL) { wxString comment; comment << _T("Chamfering of ") << object->GetShortString(); python << _T("comment(") << PythonString(comment).c_str() << _T(")\n"); } try { for(std::list<TopoDS_Shape>::iterator It2 = wires.begin(); It2 != wires.end(); It2++) { TopoDS_Shape& wire_to_fix = *It2; ShapeFix_Wire fix; fix.Load( TopoDS::Wire(wire_to_fix) ); fix.FixReorder(); TopoDS_Shape wire = fix.Wire(); wire = pMachineState->Fixture().Adjustment(wire); BRepOffsetAPI_MakeOffset offset_wire(TopoDS::Wire(wire)); // Now generate a toolpath along this wire. std::list<double> depths = GetProfileChamferingDepths(child); for (std::list<double>::iterator itDepth = depths.begin(); itDepth != depths.end(); itDepth++) { double radius = pChamferingBit->CuttingRadius(false,fabs(*itDepth - start_depth)); // We know what offset we'd really like. See how far we can offset the shape before we start // getting cross-over of graphics. double max_offset = CInlay::FindMaxOffset( radius, TopoDS::Wire(wire), radius / 10.0 ); if (radius > max_offset) radius = max_offset; // Now move the tool slightly less than this offset so that the chamfering width is // produced. double theta = pChamferingBit->m_params.m_cutting_edge_angle / 360.0 * 2.0 * PI; radius -= this->m_params.m_chamfer_width * sin(theta); switch (child->GetType()) { case ProfileType: if (((CProfile *) child)->m_profile_params.m_tool_on_side == CProfileParams::eLeftOrOutside) radius *= +1.0; if (((CProfile *) child)->m_profile_params.m_tool_on_side == CProfileParams::eRightOrInside) radius *= -1.0; if (((CProfile *) child)->m_profile_params.m_tool_on_side == CProfileParams::eOn) radius *= +1.0; break; case ContourType: if (((CContour *) child)->m_params.m_tool_on_side == CContourParams::eLeftOrOutside) radius *= +1.0; if (((CContour *) child)->m_params.m_tool_on_side == CContourParams::eRightOrInside) radius *= -1.0; if (((CContour *) child)->m_params.m_tool_on_side == CContourParams::eOn) radius *= +1.0; break; case PocketType: radius *= -1.0; break; default: if (m_params.m_tool_on_side == CContourParams::eLeftOrOutside) radius *= +1.0; if (m_params.m_tool_on_side == CContourParams::eRightOrInside) radius *= -1.0; if (m_params.m_tool_on_side == CContourParams::eOn) radius *= +1.0; break; } // End switch TopoDS_Wire tool_path_wire(TopoDS::Wire(wire)); double offset = radius; if (offset < 0) offset *= -1.0; if (offset > tolerance) { offset_wire.Perform(radius); if (! offset_wire.IsDone()) { break; } tool_path_wire = TopoDS::Wire(offset_wire.Shape()); } if (offset > tolerance) { gp_Trsf matrix; matrix.SetTranslation( gp_Vec( gp_Pnt(0,0,0), gp_Pnt( 0,0,*itDepth))); BRepBuilderAPI_Transform transform(matrix); transform.Perform(tool_path_wire, false); // notice false as second parameter tool_path_wire = TopoDS::Wire(transform.Shape()); python << CContour::GCode( tool_path_wire, pMachineState, clearance_height, rapid_safety_space, start_depth, CContourParams::ePlunge ); } // End if - then } // End for } // End for } // End try catch (Standard_Failure & error) { (void) error; // Avoid the compiler warning. Handle_Standard_Failure e = Standard_Failure::Caught(); number_of_bad_sketches++; } // End catch } // End if - else } // End for if (pMachineState->Location().Z() < (m_depth_op_params.ClearanceHeight() / theApp.m_program->m_units)) { // Move up above workpiece to relocate to the start of the next operation. python << _T("rapid(z=") << m_depth_op_params.ClearanceHeight() / theApp.m_program->m_units << _T(")\n"); CNCPoint where(pMachineState->Location()); where.SetZ(m_depth_op_params.ClearanceHeight() / theApp.m_program->m_units); pMachineState->Location(where); } if (number_of_bad_sketches > 0) { wxString message; message << _("Failed to create contours around ") << number_of_bad_sketches << _(" sketches"); wxMessageBox(message); } return(python); }