Python CDepthOp::AppendTextToProgram() { Python python; python << CSpeedOp::AppendTextToProgram(); python << _T("depthparams = depth_params("); python << _T("float(") << m_depth_op_params.m_clearance_height / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_rapid_safety_space / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_start_depth / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_step_down / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_z_finish_depth / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_z_thru_depth / theApp.m_program->m_units << _T(")"); python << _T(", float(") << m_depth_op_params.m_final_depth / theApp.m_program->m_units << _T(")"); if(m_depth_op_params.m_user_depths.Len() == 0) python << _T(", None"); else python << _T(", [") << m_depth_op_params.m_user_depths << _T("]"); python << _T(")\n"); CTool *pTool = CTool::Find( m_tool_number ); if (pTool != NULL) { python << _T("tool_diameter = float(") << (pTool->CuttingRadius(true) * 2.0) << _T(")\n"); python << _T("cutting_edge_angle = float(") << pTool->m_params.m_cutting_edge_angle<< _T(")\n"); } // End if - then return(python); }
void CPocket::set_initial_values(int tool_number) { if (tool_number > 0) { CTool *pTool = CTool::Find(tool_number); if (pTool != NULL) { m_step_over = pTool->CuttingRadius() * 3.0 / 5.0; } } }
Python CWaterline::AppendTextToProgram(CMachineState *pMachineState) { Python python; ReloadPointers(); // Make sure all the solids in m_solids are included as child objects. CTool *pTool = CTool::Find(m_tool_number); if(pTool == NULL) { return(python); } python << CDepthOp::AppendTextToProgram(pMachineState); // write the corner radius python << _T("corner_radius = float("); double cr = pTool->m_params.m_corner_radius - pTool->m_params.m_flat_radius; if(cr<0)cr = 0.0; python << ( cr / theApp.m_program->m_units ) << _T(")\n"); heeksCAD->CreateUndoPoint(); //write stl file std::list<HeeksObj*> solids; for (HeeksObj *object = GetFirstChild(); object != NULL; object = GetNextChild()) { if (object->GetType() != SolidType && object->GetType() != StlSolidType) { continue; } if (object != NULL) { // Need to rotate a COPY of the solid by the fixture settings. HeeksObj* copy = object->MakeACopy(); if (copy != NULL) { double m[16]; // A different form of the transformation matrix. CFixture::extract( pMachineState->Fixture().GetMatrix(CFixture::YZ), m ); copy->ModifyByMatrix(m); CFixture::extract( pMachineState->Fixture().GetMatrix(CFixture::XZ), m ); copy->ModifyByMatrix(m); CFixture::extract( pMachineState->Fixture().GetMatrix(CFixture::XY), m ); copy->ModifyByMatrix(m); solids.push_back(copy); } // End if - then } // End if - then } // End for wxStandardPaths standard_paths; wxFileName filepath( standard_paths.GetTempDir().c_str(), wxString::Format(_T("waterline%d.stl"), number_for_stl_file).c_str() ); number_for_stl_file++; heeksCAD->SaveSTLFile(solids, filepath.GetFullPath(), m_params.m_tolerance); // We don't need the duplicate solids any more. Delete them. for (std::list<HeeksObj*>::iterator l_itSolid = solids.begin(); l_itSolid != solids.end(); l_itSolid++) { heeksCAD->Remove( *l_itSolid ); } // End for heeksCAD->Changed(); python << _T("ocl_funcs.waterline( filepath = ") << PythonString(filepath.GetFullPath()) << _T(", ") << _T("tool_diameter = ") << pTool->CuttingRadius() * 2.0 << _T(", ") << _T("corner_radius = ") << pTool->m_params.m_corner_radius / theApp.m_program->m_units << _T(", ") << _T("step_over = ") << m_params.m_step_over / theApp.m_program->m_units << _T(", ") << _T("mat_allowance = ") << m_params.m_material_allowance / theApp.m_program->m_units << _T(", ") << _T("clearance = clearance, ") << _T("rapid_safety_space = rapid_safety_space, ") << _T("start_depth = start_depth, ") << _T("step_down = step_down, ") << _T("final_depth = final_depth, ") << _T("units = ") << theApp.m_program->m_units << _T(", ") << _T("x0 = ") << m_params.m_box.m_x[0] / theApp.m_program->m_units << _T(", ") << _T("y0 = ") << m_params.m_box.m_x[1] / theApp.m_program->m_units << _T(", ") << _T("x1 = ") << m_params.m_box.m_x[3] / theApp.m_program->m_units << _T(", ") << _T("y1 = ") << m_params.m_box.m_x[4] / theApp.m_program->m_units << _T(", ") << _T("tolerance = ") << m_params.m_tolerance << _T(")\n"); return(python); }
/** This method adjusts any parameters that don't make sense. It should report a list of changes in the list of strings. */ std::list<wxString> CDrilling::DesignRulesAdjustment(const bool apply_changes) { std::list<wxString> changes; // Make some special checks if we're using a chamfering bit. if (m_tool_number > 0) { CTool *pChamfer = (CTool *) CTool::Find( m_tool_number ); if (pChamfer != NULL) { std::vector<CNCPoint> these_locations = CDrilling::FindAllLocations(this); if (pChamfer->m_params.m_type == CToolParams::eChamfer) { // We need to make sure that the diameter of the hole (that will // have been drilled in a previous drilling operation) is between // the chamfering bit's flat_radius (smallest) and diamter/2 (largest). // First find ALL drilling cycles that created this hole. Make sure // to get them all as we may have used a centre drill before the // main hole is drilled. for (HeeksObj *obj = theApp.m_program->Operations()->GetFirstChild(); obj != NULL; obj = theApp.m_program->Operations()->GetNextChild()) { if (obj->GetType() == DrillingType) { // Make sure we're looking at a hole drilled with something // more than a centre drill. CToolParams::eToolType type = CTool::CutterType( ((COp *)obj)->m_tool_number ); if ( (type == CToolParams::eDrill) || (type == CToolParams::eEndmill) || (type == CToolParams::eSlotCutter) || (type == CToolParams::eBallEndMill)) { // See if any of the other drilling locations line up // with our drilling locations. If so, we must be // chamfering a previously drilled hole. std::vector<CNCPoint> previous_locations = CDrilling::FindAllLocations((CDrilling *)obj); std::vector<CNCPoint> common_locations; std::set_intersection( previous_locations.begin(), previous_locations.end(), these_locations.begin(), these_locations.end(), std::inserter( common_locations, common_locations.begin() )); if (common_locations.size() > 0) { // We're here. We must be chamfering a hole we've // drilled previously. Check the diameters. CTool *pPreviousTool = CTool::Find( ((COp *)obj)->m_tool_number ); if (pPreviousTool->CuttingRadius() < pChamfer->m_params.m_flat_radius) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("Chamfering bit for drilling op") << " (id=" << m_id << ") " << _("is too big for previously drilled hole") << " (drilling id=" << obj->m_id << ")\n"; changes.push_back( l_ossChange.str().c_str() ); } // End if - then if (pPreviousTool->CuttingRadius() > (pChamfer->m_params.m_diameter/2.0)) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("Chamfering bit for drilling op") << " (id=" << m_id << ") " << _("is too small for previously drilled hole") << " (drilling id=" << obj->m_id << ")\n"; changes.push_back( l_ossChange.str().c_str() ); } // End if - then } // End if - then } // End if - then } // End if - then } // End for } // End if - then } // End if - then } // End if - then if (m_tool_number > 0) { // Make sure the hole depth isn't greater than the tool's cutting depth. CTool *pDrill = (CTool *) CTool::Find( m_tool_number ); if ((pDrill != NULL) && (pDrill->m_params.m_cutting_edge_height < m_params.m_depth)) { // The drill bit we've chosen can't cut as deep as we've setup to go. if (apply_changes) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("Adjusting depth of drill cycle") << " id='" << m_id << "' " << _("from") << " '" << m_params.m_depth / theApp.m_program->m_units << "' " << _("to") << " " << pDrill->m_params.m_cutting_edge_height / theApp.m_program->m_units << "\n"; changes.push_back(l_ossChange.str().c_str()); m_params.m_depth = pDrill->m_params.m_cutting_edge_height; } // End if - then else { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("WARNING") << ": " << _("Drilling") << " (id=" << m_id << "). " << _("Can't drill hole") << " " << m_params.m_depth / theApp.m_program->m_units << " when the drill bit's cutting length is only " << pDrill->m_params.m_cutting_edge_height << " long\n"; changes.push_back(l_ossChange.str().c_str()); } // End if - else } // End if - then } // End if - then // See if there is anything in the reference objects that may be in conflict with this object's current configuration. for (Symbols_t::const_iterator l_itSymbol = m_symbols.begin(); l_itSymbol != m_symbols.end(); l_itSymbol++) { switch (l_itSymbol->first) { case ProfileType: { CProfile *pProfile = (CProfile *) heeksCAD->GetIDObject( l_itSymbol->first, l_itSymbol->second ); if (pProfile != NULL) { double depthOp_depth = ((CDepthOp *) pProfile)->m_depth_op_params.m_start_depth - ((CDepthOp *) pProfile)->m_depth_op_params.m_final_depth; if (depthOp_depth != m_params.m_depth) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("Adjusting depth of drill cycle") << " (id='" << m_id << "') " << _("from") << " '" << m_params.m_depth / theApp.m_program->m_units << "' " << _("to") << " '" << depthOp_depth / theApp.m_program->m_units<< "'\n"; changes.push_back(l_ossChange.str().c_str()); if (apply_changes) { m_params.m_depth = depthOp_depth; } // End if - then } // End if - then } } break; default: break; } // End switch } // End for // see wether combination of retract_mode, spindle_mode and peck_depth is valid: // move to design rule check if ((m_params.m_retract_mode == 1) || (m_params.m_spindle_mode == 1)) { // if we feed retract, or stop the spindle at the bottom, this is a boring cycle. // cant have peck_depth > 0 then if (m_params.m_peck_depth > 0) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif l_ossChange << _("WARNING") << ": " << _("cant have boring cycle with pecking > 0") << " (id=" << m_id << ")\n"; changes.push_back(l_ossChange.str().c_str()); } } return(changes); } // End DesignRulesAdjustment() method
/** This method adjusts any parameters that don't make sense. It should report a list of changes in the list of strings. */ std::list<wxString> CChamfer::DesignRulesAdjustment(const bool apply_changes) { std::list<wxString> changes; // Make some special checks if we're using a chamfering bit. if (m_tool_number > 0) { CTool *pChamfer = (CTool *) CTool::Find( m_tool_number ); if (pChamfer != NULL) { std::vector<CNCPoint> these_locations = CDrilling::FindAllLocations(this); if (pChamfer->m_params.m_type == CToolParams::eChamfer) { // We need to make sure that the diameter of the hole (that will // have been drilled in a previous drilling operation) is between // the chamfering bit's flat_radius (smallest) and diamter/2 (largest). // First find ALL drilling cycles that created this hole. Make sure // to get them all as we may have used a centre drill before the // main hole is drilled. for (HeeksObj *obj = theApp.m_program->Operations()->GetFirstChild(); obj != NULL; obj = theApp.m_program->Operations()->GetNextChild()) { if (obj->GetType() == DrillingType) { // Make sure we're looking at a hole drilled with something // more than a centre drill. CToolParams::eToolType type = CTool::CutterType( ((COp *)obj)->m_tool_number ); if ( (type == CToolParams::eDrill) || (type == CToolParams::eEndmill) || (type == CToolParams::eSlotCutter) || (type == CToolParams::eBallEndMill)) { // See if any of the other drilling locations line up // with our drilling locations. If so, we must be // chamfering a previously drilled hole. std::vector<CNCPoint> previous_locations = CDrilling::FindAllLocations((CDrilling *)obj); std::vector<CNCPoint> common_locations; std::set_intersection( previous_locations.begin(), previous_locations.end(), these_locations.begin(), these_locations.end(), std::inserter( common_locations, common_locations.begin() )); if (common_locations.size() > 0) { // We're here. We must be chamfering a hole we've // drilled previously. Check the diameters. CTool *pPreviousTool = CTool::Find( ((COp *)obj)->m_tool_number ); if (pPreviousTool->CuttingRadius() < pChamfer->m_params.m_flat_radius) { wxString change; change << DesignRulesPreamble() << _("Chamfering bit for drilling op") << _(" (id=") << m_id << _T(") ") << _("is too big for previously drilled hole") ; changes.push_back( change ); } // End if - then if (pPreviousTool->CuttingRadius() > (pChamfer->m_params.m_diameter/2.0)) { wxString change; change << DesignRulesPreamble() << _("Chamfering bit for drilling op") << _(" (id=") << m_id << _T(") ") << _("is too small for previously drilled hole"); changes.push_back( change ); } // End if - then } // End if - then } // End if - then } // End if - then } // End for } // End if - then else { wxString change; change << DesignRulesPreamble() << _("found with ") << pChamfer->m_params.m_type; changes.push_back(change); } } // End if - then } // End if - then std::list<wxString> extra_changes = CDepthOp::DesignRulesAdjustment(apply_changes); std::copy( extra_changes.begin(), extra_changes.end(), std::inserter( changes, changes.end() )); return(changes); } // End DesignRulesAdjustment() method
Python CChamfer::AppendTextForCircularChildren( CMachineState *pMachineState, const double theta, HeeksObj *child, CTool *pChamferingBit ) { Python python; // See what the maximum possible depth is for this chamfering bit. We want to figure // out whether we can cut with the middle part of the chamfering bit rather than // cutting using the very tip (we don't want to break it off). In fact, we should // really cut with the top-most cutting edge so that it's as strong as it can be. This // depends on the area available for fitting the chamfering bit. double min_chamfer_diameter = pChamferingBit->m_params.m_flat_radius * 2.0; double stand_off = m_depth_op_params.m_rapid_safety_space; double clearance_height = m_depth_op_params.ClearanceHeight(); Circles_t circles; if (child->GetType() == DrillingType) { // Get the size of the drilled holes. We need to know whether we need to just plunge // the chamfering bit directly down into the hole or whether we need to run // around the edge. CDrilling *pDrilling = (CDrilling *) child; CTool *pDrillBit = CTool::Find( pDrilling->m_tool_number ); if (pDrillBit == NULL) { // It's difficult to drill a hole without a drill bit but apparently this file does. printf("Ignoring drilling operation (id=%d) with no tool defined\n", pDrilling->m_id ); return(python); // Empty. } stand_off = pDrilling->m_params.m_standoff; clearance_height = pDrilling->m_params.ClearanceHeight(); double hole_diameter = pDrillBit->CuttingRadius(false) * 2.0; if (hole_diameter < min_chamfer_diameter) { // The flat radius at the bottom of the chamfering bit is larger than the drilled hole. It won't fit in. printf("Ignoring chamfer for drilled hole due to geometry of selected chamfering bit\n"); return(python); // Empty. } // Get all the point locations relevant for this operation and then adjust their position to align with // the current fixture. std::vector<CNCPoint> locations = CDrilling::FindAllLocations(pDrilling, pMachineState->Location(), true, NULL); for (std::vector<CNCPoint>::const_iterator l_itLocation = locations.begin(); l_itLocation != locations.end(); l_itLocation++) { CNCPoint point = pMachineState->Fixture().Adjustment( *l_itLocation ); circles.push_back( Circle( point, hole_diameter, pDrilling->m_params.m_depth ) ); } // End for } // End if - then if (child->GetType() == CounterBoreType) { CCounterBore *pCounterBore = ((CCounterBore *) child); stand_off = pCounterBore->m_depth_op_params.m_rapid_safety_space; clearance_height = pCounterBore->m_depth_op_params.ClearanceHeight(); std::vector<CNCPoint> locations = CDrilling::FindAllLocations(pCounterBore, pMachineState->Location(), pCounterBore->m_params.m_sort_locations != 0, NULL); for (std::vector<CNCPoint>::const_iterator l_itLocation = locations.begin(); l_itLocation != locations.end(); l_itLocation++) { CNCPoint point = pMachineState->Fixture().Adjustment( *l_itLocation ); double max_depth = pCounterBore->m_depth_op_params.m_start_depth - pCounterBore->m_depth_op_params.m_final_depth; circles.push_back( Circle( point, pCounterBore->m_params.m_diameter, max_depth ) ); } // End for } // Now handle all the chamfering for both the drilled holes and/or the counterbores. // The circles indicate both the diameter and the depth of either hole. for (Circles_t::iterator l_itCircle = circles.begin(); l_itCircle != circles.end(); l_itCircle++) { // We want to select a depth such that we're cutting with the top-most part of the chamfering // bit as that is the strongest part. We don't want to break off the tip unless we really can't // get into the hole without doing so. double max_hole_depth = l_itCircle->MaxDepth(); double max_bit_plunge_depth = pChamferingBit->m_params.m_cutting_edge_height * cos(theta); double min_bit_radius = pChamferingBit->m_params.m_flat_radius; double hole_radius = l_itCircle->Diameter() / 2.0; double required_bit_plunge_depth = (m_params.m_chamfer_width * cos( theta )); if ((required_bit_plunge_depth >= max_hole_depth) || (required_bit_plunge_depth >= max_bit_plunge_depth) || (hole_radius < min_bit_radius)) { // It's too deep for one pass. return(python); // Empty. } double plunge_depth = (max_hole_depth<=max_bit_plunge_depth)?max_hole_depth:max_bit_plunge_depth; double bit_radius_at_plunge_depth = pChamferingBit->m_params.m_flat_radius + (plunge_depth / tan(theta)); // This is the gap between the bit and the hole when the bit's bottom is at the top surface. double gap_radius = hole_radius - min_bit_radius; // We need to figure out how far down to move before this gap is closed by the slope of the cutting edge. double gap_closure_depth = gap_radius / tan(theta); if ( hole_radius <= bit_radius_at_plunge_depth ) { // We can plunge straight down at the hole's location. // If the chamfering bit is at the top of the hole then the diameter of // cut is equal to the flat radius. How far should we plunge down before // the edge of the chamfering bit touches the top of the hole? CNCPoint point(l_itCircle->Location()); python << _T("drill(") << _T("x=") << point.X(true) << _T(", ") << _T("y=") << point.Y(true) << _T(", ") << _T("z=") << drawing_units(point.Z(false) - gap_closure_depth) << _T(", ") << _T("depth=") << drawing_units(required_bit_plunge_depth) << _T(", ") << _T("standoff=") << drawing_units(stand_off) << _T(", ") << _T("dwell=") << 0.0 << _T(", ") << _T("peck_depth=") << 0.0 << _T(", ") << _T("clearance_height=") << drawing_units(clearance_height) << _T(")\n"); } else { // We will have to run around the edge of the large hole. Figure out the offset // in from the edge and generate the corresponding tool path. CNCPoint centre(l_itCircle->Location()); CNCPoint point(l_itCircle->Location()); double radius_of_spiral = hole_radius - bit_radius_at_plunge_depth + (m_params.m_chamfer_width * sin(theta)); python << _T("rapid( x=") << centre.X(true) << _T(", ") << _T("y=") << centre.Y(true) << _T(", ") << _T("z=") << drawing_units(clearance_height) << _T(")\n"); python << _T("rapid(z=") << drawing_units(stand_off) << _T(")\n"); double cutting_depth = point.Z(false) - plunge_depth; // Move to 12 O'Clock. python << _T("feed( x=") << centre.X(true) << _T(", ") _T("y=") << drawing_units(centre.Y(false) + radius_of_spiral) << _T(", ") _T("z=") << drawing_units(cutting_depth) << _T(")\n"); point.SetX( centre.X(false) ); point.SetY( centre.Y(false) + radius_of_spiral ); // First quadrant (12 O'Clock to 9 O'Clock) python << _T("arc_ccw( x=") << drawing_units(centre.X(false) - radius_of_spiral) << _T(", ") << _T("y=") << centre.Y(true) << _T(", ") << _T("z=") << drawing_units(cutting_depth) << _T(", ") << // full depth _T("i=") << drawing_units(centre.X(false)) << _T(", ") << _T("j=") << drawing_units(centre.Y(false)) << _T(")\n"); point.SetX( centre.X(false) - radius_of_spiral ); point.SetY( centre.Y(false) ); // Second quadrant (9 O'Clock to 6 O'Clock) python << _T("arc_ccw( x=") << centre.X(true) << _T(", ") << _T("y=") << drawing_units(centre.Y(false) - radius_of_spiral) << _T(", ") << _T("z=") << drawing_units(cutting_depth) << _T(", ") << // full depth now _T("i=") << drawing_units(centre.X(false)) << _T(", ") << _T("j=") << drawing_units(centre.Y(false)) << _T(")\n"); point.SetX( centre.X(false) ); point.SetY( centre.Y(false) - radius_of_spiral ); // Third quadrant (6 O'Clock to 3 O'Clock) python << _T("arc_ccw( x=") << drawing_units(centre.X(false) + radius_of_spiral) << _T(", ") << _T("y=") << centre.Y(true) << _T(", ") << _T("z=") << drawing_units(cutting_depth) << _T(", ") << // full depth now _T("i=") << drawing_units(centre.X(false)) << _T(", ") << _T("j=") << drawing_units(centre.Y(false)) << _T(")\n"); point.SetX( centre.X(false) + radius_of_spiral ); point.SetY( centre.Y(false) ); // Fourth quadrant (3 O'Clock to 12 O'Clock) python << _T("arc_ccw( x=") << centre.X(true) << _T(", ") << _T("y=") << drawing_units(centre.Y(false) + radius_of_spiral) << _T(", ") << _T("z=") << drawing_units(cutting_depth) << _T(", ") << // full depth now _T("i=") << drawing_units(centre.X(false)) << _T(", ") << _T("j=") << drawing_units(centre.Y(false)) << _T(")\n"); point.SetX( centre.X(false) ); point.SetY( centre.Y(false) + radius_of_spiral ); python << _T("rapid( z=") << drawing_units(m_depth_op_params.ClearanceHeight()) << _T(")\n"); } } // End for return(python); }
unsigned int CProfile::GetNumSketches() { unsigned int num_sketches = 0; #ifdef OP_SKETCHES_AS_CHILDREN for (HeeksObj *object = GetFirstChild(); object != NULL; object = GetNextChild()) { #else for (std::list<int>::iterator It = m_sketches.begin(); It != m_sketches.end(); It++) { HeeksObj* object = heeksCAD->GetIDObject(SketchType, *It); #endif if(object && object->GetType() == SketchType)num_sketches++; } return num_sketches; } /** The old version of the CDrilling object stored references to graphics as type/id pairs that get read into the m_symbols list. The new version stores these graphics references as child elements (based on ObjList). If we read in an old-format file then the m_symbols list will have data in it for which we don't have children. This routine converts these type/id pairs into the HeeksObj pointers as children. */ #ifdef OP_SKETCHES_AS_CHILDREN void CProfile::ReloadPointers() { for (Sketches_t::iterator symbol = m_sketches.begin(); symbol != m_sketches.end(); symbol++) { HeeksObj *object = heeksCAD->GetIDObject( SketchType, *symbol ); if (object != NULL) { Add( object, NULL ); } } m_sketches.clear(); // We don't want to convert them twice. CDepthOp::ReloadPointers(); } #endif /** If it's an 'inside' profile then we need to make sure the auto_roll_radius is not so large that it's going to gouge the part outside the sketch's area. This routine only reduces the auto_roll_radius. Its value is not changed unless a gouge scenario is detected. */ std::list<wxString> CProfile::ConfirmAutoRollRadius(const bool apply_changes) { #ifdef UNICODE std::wostringstream l_ossChange; #else std::ostringstream l_ossChange; #endif std::list<wxString> changes; if (m_profile_params.m_tool_on_side == CProfileParams::eRightOrInside) { // Look at the dimensions of the sketches as well as the diameter of the bit to decide if // our existing m_auto_roll_radius is too big for this profile. If so, reduce it now. CTool *pTool = NULL; if ((m_tool_number > 0) && ((pTool = CTool::Find(m_tool_number)) != NULL)) { for (std::list<int>::iterator l_itSketchId = m_sketches.begin(); l_itSketchId != m_sketches.end(); l_itSketchId++) { HeeksObj *sketch = heeksCAD->GetIDObject( SketchType, *l_itSketchId ); if (sketch != NULL) { CBox bounding_box; sketch->GetBox( bounding_box ); double min_distance_across = (bounding_box.Height() < bounding_box.Width())?bounding_box.Height():bounding_box.Width(); double max_roll_radius = (min_distance_across - (pTool->CuttingRadius() * 2.0)) / 2.0; if (max_roll_radius < m_profile_params.m_auto_roll_radius) { l_ossChange << "Need to adjust auto_roll_radius for profile id=" << m_id << " from " << m_profile_params.m_auto_roll_radius << " to " << max_roll_radius << "\n"; changes.push_back(l_ossChange.str().c_str()); if (apply_changes) { m_profile_params.m_auto_roll_radius = max_roll_radius; } // End if - then } } // End if - then } // End for } // End if - then } // End if - then return(changes); } // End ConfirmAutoRollRadius() method