コード例 #1
0
ファイル: Op.cpp プロジェクト: DesignerMK/heekscnc
/**
    Change tools (if necessary) and assign any private fixtures.
 */
Python COp::AppendTextToProgram(CMachineState *pMachineState )
{
    Python python;

	if(m_comment.Len() > 0)
	{
		python << _T("comment(") << PythonString(m_comment) << _T(")\n");
	}

	if(UsesTool())python << MACHINE_STATE_TOOL(m_tool_number);  // Select the correct  tool.

	return(python);
}
コード例 #2
0
ファイル: AttachOp.cpp プロジェクト: DesignerMK/heekscnc
Python CAttachOp::AppendTextToProgram(CMachineState *pMachineState)
{
	Python python;

 #ifdef OP_SKETCHES_AS_CHILDREN
   ReloadPointers();   // Make sure all the solids in m_solids are included as child objects.
#endif

	python << COp::AppendTextToProgram(pMachineState);

	//write stl file
	std::list<HeeksObj*> solids;
	std::list<HeeksObj*> copies_to_delete;
#ifdef OP_SKETCHES_AS_CHILDREN
    for (HeeksObj *object = GetFirstChild(); object != NULL; object = GetNextChild())
    {
	    if (object->GetType() != SolidType && object->GetType() != StlSolidType)
	    {
	        continue;
	    }

#else
	for (std::list<int>::iterator It = m_solids.begin(); It != m_solids.end(); It++)
    {
		HeeksObj* object = heeksCAD->GetIDObject(SolidType, *It);
#endif
		if (object != NULL)
		{
			if(1/* to do pMachineState->Fixture().GetMatrix() == gp_Trsf()*/)
			{
				solids.push_back(object);
			}
		} // End if - then
	} // End for


    wxStandardPaths standard_paths;
    wxFileName filepath( standard_paths.GetTempDir().c_str(), wxString::Format(_T("surface%d.stl"), number_for_stl_file).c_str() );
	number_for_stl_file++;

	heeksCAD->SaveSTLFile(solids, filepath.GetFullPath(), 0.01);

	// We don't need the duplicate solids any more.  Delete them.
	for (std::list<HeeksObj*>::iterator l_itSolid = copies_to_delete.begin(); l_itSolid != copies_to_delete.end(); l_itSolid++)
	{
		delete *l_itSolid;
	} // End for

	python << _T("nc.attach.units = ") << theApp.m_program->m_units << _T("\n");
	python << _T("nc.attach.attach_begin()\n");
	python << _T("nc.nc.creator.stl = ocl_funcs.STLSurfFromFile(") << PythonString(filepath.GetFullPath()) << _T(")\n");
	python << _T("nc.nc.creator.minz = ") << m_min_z << _T("\n");
	python << _T("nc.nc.creator.material_allowance = ") << m_material_allowance << _T("\n");

	pMachineState->m_attached_to_surface = this;

	return(python);
} // End AppendTextToProgram() method

static void on_set_tolerance(double value, HeeksObj* object){((CAttachOp*)object)->m_tolerance = value;}
static void on_set_min_z(double value, HeeksObj* object){((CAttachOp*)object)->m_min_z = value;}
static void on_set_material_allowance(double value, HeeksObj* object){((CAttachOp*)object)->m_material_allowance = value;}

void CAttachOp::GetProperties(std::list<Property *> *list)
{
#ifdef OP_SKETCHES_AS_CHILDREN
	AddSolidsProperties(list, this);
#else
	AddSolidsProperties(list, m_solids);
#endif
	list->push_back(new PropertyLength(_("tolerance"), m_tolerance, this, on_set_tolerance));
	list->push_back(new PropertyLength(_("minimum z"), m_min_z, this, on_set_min_z));
	list->push_back(new PropertyLength(_("material allowance"), m_material_allowance, this, on_set_material_allowance));
	COp::GetProperties(list);
}
コード例 #3
0
ファイル: Waterline.cpp プロジェクト: DavidNicholls/heekscnc
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);
}
コード例 #4
0
ファイル: Adaptive.cpp プロジェクト: JonasThomas/heekscnc
Python CAdaptive::AppendTextToProgram(CMachineState *pMachineState )
{
	Python python;

	python << COp::AppendTextToProgram(pMachineState);

	heeksCAD->CreateUndoPoint();

	//write stl file
	std::list<HeeksObj*> solids;
	for(std::list<int>::iterator It = m_solids.begin(); It != m_solids.end(); It++)
	{
		HeeksObj* object = heeksCAD->GetIDObject(SolidType, *It);
		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

	// Reconfirm that our retractzheight value is sufficient.
	const double small_buffer = 5.0;	// Don't scrape the mountain tops.
	double max_z = CAdaptive::GetMaxHeight( SolidType, m_solids );
	if (m_params.m_retractzheight < (max_z + small_buffer))
	{
		m_params.m_retractzheight = max_z + small_buffer;
	} // End if - then

	max_z = CAdaptive::GetMaxHeight( SketchType, m_sketches );
	if (m_params.m_boundaryclear < max_z) m_params.m_boundaryclear = max_z;

    wxStandardPaths standard_paths;
    wxFileName filepath;

    filepath.Assign( standard_paths.GetTempDir().c_str(), wxString::Format(_T("adaptive%d.stl"), number_for_stl_file).c_str() );

	number_for_stl_file++;
	heeksCAD->SaveSTLFile(solids, filepath.GetFullPath());

	// 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

	python << _T("rapid(z=") << m_params.m_retractzheight << _T(")\n");

	gp_Pnt start = pMachineState->Fixture().Adjustment( gp_Pnt( m_params.m_startpoint_x, m_params.m_startpoint_y, m_params.m_retractzheight ) );
	python << _T("rapid(x=") << start.X() << _T(", y=") << start.Y() << _T(")\n");

	python << _T("actp.setleadoffdz(") << m_params.m_leadoffdz << _T(")\n");

	python << _T("actp.setleadofflen(") << m_params.m_leadofflen << _T(")\n");

	python << _T("actp.setleadoffrad(") << m_params.m_leadoffrad << _T(")\n");

	python << _T("actp.setretractzheight(") << m_params.m_retractzheight << _T(")\n");

	python << _T("actp.setleadoffsamplestep(") << m_params.m_leadoffsamplestep << _T(")\n");

	if ((((COp *)this)->m_tool_number > 0) &&
	    (CTool::FindTool( ((COp *)this)->m_tool_number ) > 0) )
	{
		// We have a  tool to refer to.  Get these values from there instead.

		CTool *pTool = (CTool *) CTool::Find( ((COp *)this)->m_tool_number );
		if (pTool != NULL)
		{
			python << _T("actp.settoolcornerrad(") << pTool->m_params.m_corner_radius << _T(")\n");
			python << _T("actp.settoolflatrad(") << pTool->m_params.m_flat_radius << _T(")\n");
		} // End if - then
	} // End if - then
	else
	{
		// This object has values and/or we don't have a  tool number to refer to.
		// Use these values instead.

		python << _T("actp.settoolcornerrad(") << m_params.m_toolcornerrad << _T(")\n");
		python << _T("actp.settoolflatrad(") << m_params.m_toolflatrad << _T(")\n");
	} // End if - else

	python << _T("actp.setsamplestep(") << m_params.m_samplestep << _T(")\n");

	python << _T("actp.setstepdown(") << m_params.m_stepdown << _T(")\n");

	python << _T("actp.setclearcuspheight(") << m_params.m_clearcuspheight << _T(")\n");

	python << _T("actp.settriangleweaveres(") << m_params.m_triangleweaveres << _T(")\n");

	python << _T("actp.setflatradweaveres(") << m_params.m_flatradweaveres << _T(")\n");

	python << _T("actp.setdchangright(") << m_params.m_dchangright << _T(")\n");

	python << _T("actp.setdchangrightoncontour(") << m_params.m_dchangrightoncontour << _T(")\n");

	python << _T("actp.setdchangleft(") << m_params.m_dchangleft << _T(")\n");

	python << _T("actp.setdchangefreespace(") << m_params.m_dchangefreespace << _T(")\n");

	python << _T("actp.setsidecutdisplch(") << m_params.m_sidecutdisplch << _T(")\n");

	python << _T("actp.setfcut(") << m_params.m_fcut << _T(")\n");

	python << _T("actp.setfretract(") << m_params.m_fretract << _T(")\n");

	python << _T("actp.setthintol(") << m_params.m_thintol << _T(")\n");

	python << _T("actp.setstartpoint(") << start.X() << _T(", ") << start.Y() << _T(", ") << m_params.m_startvel_x << _T(", ") << m_params.m_startvel_y << _T(")\n");

	python << _T("actp.setminz(") << m_params.m_minz << _T(")\n");

	python << _T("actp.boundaryclear(") << m_params.m_boundaryclear << _T(")\n");

	if(!m_sketches.empty())
	{
		std::list<HeeksObj*> sketches;
		for(std::list<int>::iterator It = m_sketches.begin(); It != m_sketches.end(); It++)
		{
			HeeksObj* sketch = heeksCAD->GetIDObject(SketchType, *It);
			if(sketch){
				for(HeeksObj* span_object = sketch->GetFirstChild(); span_object; span_object = sketch->GetNextChild())
				{
					double s[3] = {0, 0, 0};
					double e[3] = {0, 0, 0};
					if(span_object){
						int type = span_object->GetType();
						//TODO: add support for arcs
						if(type == LineType)
						{
							span_object->GetStartPoint(s);
							pMachineState->Fixture().Adjustment(s);

							span_object->GetEndPoint(e);
							pMachineState->Fixture().Adjustment(e);

							python << _T("actp.boundaryadd(") << s[0] << _T(", ") << s[1] << _T(")\n");
							python << _T("actp.boundaryadd(") << e[0] << _T(", ") << e[1] << _T(")\n");
						}
					}
				}
			}
			python << _T("actp.boundarybreak()\n");
		}
	}
	else
	{
		gp_Pnt boundary[2];
		boundary[0] = pMachineState->Fixture().Adjustment( gp_Pnt( m_params.m_boundary_x0, m_params.m_boundary_y0, 0.0 ) );
		boundary[1] = pMachineState->Fixture().Adjustment( gp_Pnt( m_params.m_boundary_x1, m_params.m_boundary_y1, 0.0 ) );

		python << _T("actp.boundaryadd(") << boundary[0].X() << _T(", ") << boundary[0].Y() << _T(")\n");

		python << _T("actp.boundaryadd(") << boundary[0].X() << _T(", ") << boundary[1].Y() << _T(")\n");

		python << _T("actp.boundaryadd(") << boundary[1].X() << _T(", ") << boundary[1].Y() << _T(")\n");

		python << _T("actp.boundaryadd(") << boundary[1].X() << _T(", ") << boundary[0].Y() << _T(")\n");

		python << _T("actp.boundarybreak()\n");

	}

	python << _T("actp_funcs.cut(") << PythonString(filepath.GetFullPath()) << _T(")\n");

	python << _T("rapid(z=") << m_params.m_retractzheight << _T(")\n");

	return(python);
}
コード例 #5
0
ファイル: PythonString.cpp プロジェクト: AlanZheng/heekscnc
Python & Python::operator<<( const double value )
{
	wxString::operator<<(PythonString(value));
	return(*this);
}
コード例 #6
0
ファイル: Profile.cpp プロジェクト: AlanZheng/heekscnc
Python CProfile::WriteSketchDefn(HeeksObj* sketch, bool reversed )
{
	// write the python code for the sketch
	Python python;

	if ((sketch->GetShortString() != NULL) && (wxString(sketch->GetShortString()).size() > 0))
	{
		python << (wxString::Format(_T("comment(%s)\n"), PythonString(sketch->GetShortString()).c_str()));
	}

	python << _T("curve = area.Curve()\n");

	bool started = false;
	std::list<HeeksObj*> spans;
	switch(sketch->GetType())
	{
	case SketchType:
		for(HeeksObj* span_object = sketch->GetFirstChild(); span_object; span_object = sketch->GetNextChild())
		{
			if(reversed)spans.push_front(span_object);
			else spans.push_back(span_object);
		}
		break;
	case CircleType:
		spans.push_back(sketch);
		break;
	case AreaType:
		break;
	}

	std::list<HeeksObj*> new_spans;
	for(std::list<HeeksObj*>::iterator It = spans.begin(); It != spans.end(); It++)
	{
		HeeksObj* span = *It;
		if(span->GetType() == SplineType)
		{
			std::list<HeeksObj*> new_spans2;
			heeksCAD->SplineToBiarcs(span, new_spans2, CProfile::max_deviation_for_spline_to_arc);
			if(reversed)
			{
				for(std::list<HeeksObj*>::reverse_iterator It2 = new_spans2.rbegin(); It2 != new_spans2.rend(); It2++)
				{
					HeeksObj* s = *It2;
					new_spans.push_back(s);
				}
			}
			else
			{
				for(std::list<HeeksObj*>::iterator It2 = new_spans2.begin(); It2 != new_spans2.end(); It2++)
				{
					HeeksObj* s = *It2;
					new_spans.push_back(s);
				}
			}
		}
		else
		{
			new_spans.push_back(span->MakeACopy());
		}
	}

	for(std::list<HeeksObj*>::iterator It = new_spans.begin(); It != new_spans.end(); It++)
	{
		HeeksObj* span_object = *It;
		double s[3] = {0, 0, 0};
		double e[3] = {0, 0, 0};
		double c[3] = {0, 0, 0};


		if(span_object){
			int type = span_object->GetType();
			if(type == LineType || type == ArcType || type == CircleType)
			{
				if(!started && type != CircleType)
				{
					if(reversed)span_object->GetEndPoint(s);
					else span_object->GetStartPoint(s);
					CNCPoint start(s);

					python << _T("curve.append(area.Point(");
					python << start.X(true);
					python << _T(", ");
					python << start.Y(true);
					python << _T("))\n");
					started = true;
				}
				if(reversed)span_object->GetStartPoint(e);
				else span_object->GetEndPoint(e);
				CNCPoint end(e);

				if(type == LineType)
				{
					python << _T("curve.append(area.Point(");
					python << end.X(true);
					python << _T(", ");
					python << end.Y(true);
					python << _T("))\n");
				}
				else if(type == ArcType)
				{
					span_object->GetCentrePoint(c);
					CNCPoint centre(c);

					double pos[3];
					heeksCAD->GetArcAxis(span_object, pos);
					int span_type = ((pos[2] >=0) != reversed) ? 1: -1;
					python << _T("curve.append(area.Vertex(");
					python << (span_type);
					python << (_T(", area.Point("));
					python << end.X(true);
					python << (_T(", "));
					python << end.Y(true);
					python << (_T("), area.Point("));
					python << centre.X(true);
					python << (_T(", "));
					python << centre.Y(true);
					python << (_T(")))\n"));
				}
				else if(type == CircleType)
				{
					std::list< std::pair<int, gp_Pnt > > points;
					span_object->GetCentrePoint(c);

					double radius = heeksCAD->CircleGetRadius(span_object);

					// Setup the four arcs to make up the full circle using UNadjusted
					// coordinates.  We do this so that the offsets are expressed along the
					// X and Y axes.  We will adjust the resultant points later.

					// The kurve code needs a start point first.
					points.push_back( std::make_pair(0, gp_Pnt( c[0], c[1] + radius, c[2] )) ); // north
					if(reversed)
					{
						points.push_back( std::make_pair(1, gp_Pnt( c[0] - radius, c[1], c[2] )) ); // west
						points.push_back( std::make_pair(1, gp_Pnt( c[0], c[1] - radius, c[2] )) ); // south
						points.push_back( std::make_pair(1, gp_Pnt( c[0] + radius, c[1], c[2] )) ); // east
						points.push_back( std::make_pair(1, gp_Pnt( c[0], c[1] + radius, c[2] )) ); // north
					}
					else
					{
						points.push_back( std::make_pair(-1, gp_Pnt( c[0] + radius, c[1], c[2] )) ); // east
						points.push_back( std::make_pair(-1, gp_Pnt( c[0], c[1] - radius, c[2] )) ); // south
						points.push_back( std::make_pair(-1, gp_Pnt( c[0] - radius, c[1], c[2] )) ); // west
						points.push_back( std::make_pair(-1, gp_Pnt( c[0], c[1] + radius, c[2] )) ); // north
					}

					CNCPoint centre(c);

					for (std::list< std::pair<int, gp_Pnt > >::iterator l_itPoint = points.begin(); l_itPoint != points.end(); l_itPoint++)
					{
						CNCPoint pnt( l_itPoint->second );

						python << (_T("curve.append(area.Vertex("));
						python << l_itPoint->first << _T(", area.Point(");
						python << pnt.X(true);
						python << (_T(", "));
						python << pnt.Y(true);
						python << (_T("), area.Point("));
						python << centre.X(true);
						python << (_T(", "));
						python << centre.Y(true);
						python << (_T(")))\n"));
					} // End for
				}
			}
		}
	}

	// delete the spans made
	for(std::list<HeeksObj*>::iterator It = new_spans.begin(); It != new_spans.end(); It++)
	{
		HeeksObj* span = *It;
		delete span;
	}

	python << _T("\n");

	if(m_profile_params.m_start_given || m_profile_params.m_end_given)
	{
		double startx, starty, finishx, finishy;

		wxString start_string;
		if(m_profile_params.m_start_given)
		{
#ifdef UNICODE
			std::wostringstream ss;
#else
			std::ostringstream ss;
#endif

			gp_Pnt starting(m_profile_params.m_start[0] / theApp.m_program->m_units,
					m_profile_params.m_start[1] / theApp.m_program->m_units,
					0.0 );

			startx = starting.X();
			starty = starting.Y();

			ss.imbue(std::locale("C"));
			ss<<std::setprecision(10);
			ss << ", start = area.Point(" << startx << ", " << starty << ")";
			start_string = ss.str().c_str();
		}


		wxString finish_string;
		wxString beyond_string;
		if(m_profile_params.m_end_given)
		{
#ifdef UNICODE
			std::wostringstream ss;
#else
			std::ostringstream ss;
#endif

			gp_Pnt finish(m_profile_params.m_end[0] / theApp.m_program->m_units,
					m_profile_params.m_end[1] / theApp.m_program->m_units,
					0.0 );

			finishx = finish.X();
			finishy = finish.Y();

			ss.imbue(std::locale("C"));
			ss<<std::setprecision(10);
			ss << ", finish = area.Point(" << finishx << ", " << finishy << ")";
			finish_string = ss.str().c_str();

			if(m_profile_params.m_end_beyond_full_profile)beyond_string = _T(", end_beyond = True");
		}

		python << (wxString::Format(_T("kurve_funcs.make_smaller( curve%s%s%s)\n"), start_string.c_str(), finish_string.c_str(), beyond_string.c_str())).c_str();
	}

	return(python);
}
コード例 #7
0
ファイル: Chamfer.cpp プロジェクト: DavidNicholls/heekscnc
/**
	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);
}