By Xiaodong Liang
Autodesk provides solutions of CAM: Inventor CAM, CAM 360 etc. Some custom applications of Inventor would need to produce their own CAM process with the custom algorism. The most important step is to analogous to a machining operation.
I explored a bit with Inventor API. Basically, we need to get the update to date status of the base body that the tool has affected, by TransientBrep.DoBoolean, and display them by client graphics.
TransientBRep.DoBoolean( BlankBody As SurfaceBody,
ToolBody As SurfaceBody,
BooleanType As BooleanTypeEnum )
BlankBody: Input/Output SurfaceBody that will be modified as a result.
ToolBody: Input SurfaceBody that is used to operate on the blank body.
BooleanType: Input BooleanTypeEnum that specifies the type of Boolean operation to perform. Valid values are kBooleanTypeDifference, kBooleanTypeUnion, and kBooleanTypeIntersect.
In CAM simulation, the BooleanType is kBooleanTypeDifference which means the tool will remove the materials of the base body.
If you are not familiar with client graphics, I’d recommend with the tutorials we posted on Brian’s blog.
The following demo tests with the attached part in a standalone EXE, in which there are one plate which is base body and a small stick as a tool. The tool will move on X-Y plane and inside the base body along Z (depth = 1cm). It removes the material from the diameter = 4 cm and shrink to diameter = 0.
Download CamPart
Inventor.Application oInvApp;
Asset toolAppearance;
Asset baseAppearance;
void CamTest()
{
//get active Inventor process
oInvApp =
System.Runtime.InteropServices.Marshal.
GetActiveObject("Inventor.Application")
as Inventor.Application;
//get active document
PartDocument oPartDoc =
oInvApp.ActiveDocument asPartDocument;
PartComponentDefinition oPartDef =
oPartDoc.ComponentDefinition;
//Transient Brep object
TransientBRep oTBrep =
oInvApp.TransientBRep;
//Transient Geometry
TransientGeometry oTG=
oInvApp.TransientGeometry;
//base body
SurfaceBody oBaseBody =
oPartDef.SurfaceBodies[1];
//tool body
SurfaceBody oToolBody =
oPartDef.SurfaceBodies[2];
//make base body and tool body invisible
//we just show client graphics
oBaseBody.Visible = false;
oToolBody.Visible = false;
//make a copy of base body and tool body
//we will use them as client graphics
SurfaceBody oBaseBody_Copy =
oTBrep.Copy(oBaseBody);
SurfaceBody oToolBody_Copy =
oTBrep.Copy(oToolBody);
//Client Graphics
ClientGraphics oClientGraphics;
try
{
//delete if the Client Graphics exists
oClientGraphics =
oPartDef.ClientGraphicsCollection["CAMDemo"];
// An existing client graphics object
// was successfully obtained so clean up.
oClientGraphics.Delete();
// update the display to see the results.
oApp.ActiveView.Update();
}
catch
{
//get the appearance for tool
toolAppearance =
oPartDoc.Assets["Gold - Metal"];
baseAppearance =
oPartDoc.Assets["Plate"];
// Create the ClientGraphics
oClientGraphics =
oPartDef.ClientGraphicsCollection.Add("CAMDemo");
//add graphics node for base body
GraphicsNode _oNode_BaseBody =
oClientGraphics.AddNode(1);
//add graphics of base body
SurfaceGraphics _Gra_BaseBody =
_oNode_BaseBody.AddSurfaceGraphics(oBaseBody_Copy);
_oNode_BaseBody.Appearance = baseAppearance;
//add graphics node for tool body
GraphicsNode _oNode_ToolBody =
oClientGraphics.AddNode(2);
//add graphics of tool body
SurfaceGraphics _Gra_ToolBody =
_oNode_ToolBody.AddSurfaceGraphics(oToolBody_Copy);
_oNode_ToolBody.Appearance = toolAppearance;
//CAM Simulation starts:
//move tool inside the base along Z
Matrix oMovingM =
oTG.CreateMatrix();
oMovingM.SetTranslation(oTG.CreateVector(0, 0, -1));
//move tool inside base body: depth = 1
eachCAM(oMovingM,
ref oBaseBody_Copy,
ref oToolBody_Copy,
ref _oNode_BaseBody,
ref _oNode_ToolBody,
ref _Gra_BaseBody,
ref _Gra_ToolBody);
// diameter of the tool body
double toolDia = 0.5;
// how many circle loops the tool will move
int loopCount = 10;
//from which diamater the tool starts to move
double max_CAM_Dia = 4.0;
//last matrix of the tool body
Matrix oLastMovingM = oTG.CreateMatrix();
oLastMovingM.SetToIdentity();
//tool moves from max diameter to 0
for (int circleLoop = loopCount;
circleLoop > 0 ;
circleLoop--)
{
//diameter of this loop
double thisDia = max_CAM_Dia * circleLoop / loopCount;
//the perimeter of this circle
double perimeterofLoop = Math.PI * thisDia;
//how many steps the tool needs to move for this loop
int circleStepCount =
(int)(perimeterofLoop / toolDia) *2;
//moving of each circle
for (int angleIndex = 1;
angleIndex < circleStepCount;
angleIndex++)
{
//get the location the tool will move to
double x = thisDia / 2.0 *
Math.Cos(angleIndex * Math.PI * 2 / circleStepCount);
double y = thisDia/ 2.0 *
Math.Sin(angleIndex * Math.PI * 2 / circleStepCount );
//transform matrix
Matrix oEachMovingM = oTG.CreateMatrix();
oEachMovingM.SetTranslation(oTG.CreateVector(x, y, 0));
//the last location of the tool affects
//so invert and update with the new matrix
oLastMovingM.Invert();
oLastMovingM.TransformBy(oEachMovingM);
oMovingM = oLastMovingM;
//move
eachCAM(oMovingM,
ref oBaseBody_Copy,
ref oToolBody_Copy,
ref _oNode_BaseBody,
ref _oNode_ToolBody,
ref _Gra_BaseBody,
ref _Gra_ToolBody);
//record the current matrix for next use
oLastMovingM = oEachMovingM;
}
}
}
}
// each step of moving
void eachCAM(Matrix _oMovingM,
refSurfaceBody _BaseBody,
refSurfaceBody _ToolBody,
refGraphicsNode _BaseBodyNode,
refGraphicsNode _ToolBodyNode,
refSurfaceGraphics _BaseGrap,
refSurfaceGraphics _ToolGrap
)
{
TransientBRep oTBrep = oInvApp.TransientBRep;
// we need to recreate the graphics.
_BaseGrap.Delete();
_ToolGrap.Delete();
//transform the tool body
oTBrep.Transform(_ToolBody, _oMovingM);
//remove material of the base body
oTBrep.DoBoolean(_BaseBody, _ToolBody,
BooleanTypeEnum.kBooleanTypeDifference);
//add the update bodies again
_BaseGrap = _BaseBodyNode.AddSurfaceGraphics(_BaseBody);
_ToolGrap = _ToolBodyNode.AddSurfaceGraphics(_ToolBody);
//assign the appearance to the tool graphics
_BaseBodyNode.Appearance = baseAppearance;
_ToolBodyNode.Appearance =toolAppearance;
//update the view
oInvApp.ActiveView.Update();
}
Note: the residual images in this gif is caused by the video production.Tthere is no residual when working with Inventor.