可以采用生成刀轨的方式,按照样条曲线的轨迹生成刀路,将其输出为后处理文件后,再进行解析。
using System;
using NXOpen;
using NXOpenUI;
using NXOpen.Utilities;
using NXOpen.UF;
using FxpApi;
using NXOpen.BlockStyler;
using NXOpen.CAM;
using System.IO;
using System.Collections.Generic;
using System.Threading;
//------------------------------------------------------------------------------
//Represents Block Styler application class
//------------------------------------------------------------------------------
public class FitCurves
{
//class members
public static Session theSession = null;
public static UI theUI = null;
public static UFSession theUFSession = null;
public static Part workPart = null;
private string theDlxFileName;
private NXOpen.BlockStyler.BlockDialog theDialog;
private NXOpen.BlockStyler.SelectObject selection0;// Block type: Selection
//------------------------------------------------------------------------------
//Bit Option for Property: SnapPointTypesEnabled
//------------------------------------------------------------------------------
public static readonly int SnapPointTypesEnabled_UserDefined = (1 << 0);
public static readonly int SnapPointTypesEnabled_Inferred = (1 << 1);
public static readonly int SnapPointTypesEnabled_ScreenPosition = (1 << 2);
public static readonly int SnapPointTypesEnabled_EndPoint = (1 << 3);
public static readonly int SnapPointTypesEnabled_MidPoint = (1 << 4);
public static readonly int SnapPointTypesEnabled_ControlPoint = (1 << 5);
public static readonly int SnapPointTypesEnabled_Intersection = (1 << 6);
public static readonly int SnapPointTypesEnabled_ArcCenter = (1 << 7);
public static readonly int SnapPointTypesEnabled_QuadrantPoint = (1 << 8);
public static readonly int SnapPointTypesEnabled_ExistingPoint = (1 << 9);
public static readonly int SnapPointTypesEnabled_PointonCurve = (1 << 10);
public static readonly int SnapPointTypesEnabled_PointonSurface = (1 << 11);
public static readonly int SnapPointTypesEnabled_PointConstructor = (1 << 12);
public static readonly int SnapPointTypesEnabled_TwocurveIntersection = (1 << 13);
public static readonly int SnapPointTypesEnabled_TangentPoint = (1 << 14);
public static readonly int SnapPointTypesEnabled_Poles = (1 << 15);
public static readonly int SnapPointTypesEnabled_BoundedGridPoint = (1 << 16);
public static readonly int SnapPointTypesEnabled_FacetVertexPoint = (1 << 17);
//------------------------------------------------------------------------------
//Bit Option for Property: SnapPointTypesOnByDefault
//------------------------------------------------------------------------------
public static readonly int SnapPointTypesOnByDefault_EndPoint = (1 << 3);
public static readonly int SnapPointTypesOnByDefault_MidPoint = (1 << 4);
public static readonly int SnapPointTypesOnByDefault_ControlPoint = (1 << 5);
public static readonly int SnapPointTypesOnByDefault_Intersection = (1 << 6);
public static readonly int SnapPointTypesOnByDefault_ArcCenter = (1 << 7);
public static readonly int SnapPointTypesOnByDefault_QuadrantPoint = (1 << 8);
public static readonly int SnapPointTypesOnByDefault_ExistingPoint = (1 << 9);
public static readonly int SnapPointTypesOnByDefault_PointonCurve = (1 << 10);
public static readonly int SnapPointTypesOnByDefault_PointonSurface = (1 << 11);
public static readonly int SnapPointTypesOnByDefault_PointConstructor = (1 << 12);
public static readonly int SnapPointTypesOnByDefault_BoundedGridPoint = (1 << 16);
//------------------------------------------------------------------------------
//Constructor for NX Styler class
//------------------------------------------------------------------------------
public FitCurves()
{
try
{
theSession = Session.GetSession();
theUI = UI.GetUI();
theUFSession = UFSession.GetUFSession();
workPart = theSession.Parts.Work;
theDlxFileName = "FitCurves.dlx";
theDialog = theUI.CreateDialog(theDlxFileName);
theDialog.AddApplyHandler(new NXOpen.BlockStyler.BlockDialog.Apply(apply_cb));
theDialog.AddOkHandler(new NXOpen.BlockStyler.BlockDialog.Ok(ok_cb));
theDialog.AddUpdateHandler(new NXOpen.BlockStyler.BlockDialog.Update(update_cb));
theDialog.AddCancelHandler(new NXOpen.BlockStyler.BlockDialog.Cancel(cancel_cb));
theDialog.AddFilterHandler(new NXOpen.BlockStyler.BlockDialog.Filter(filter_cb));
theDialog.AddInitializeHandler(new NXOpen.BlockStyler.BlockDialog.Initialize(initialize_cb));
theDialog.AddDialogShownHandler(new NXOpen.BlockStyler.BlockDialog.DialogShown(dialogShown_cb));
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
throw ex;
}
}
public static void Main()
{
FitCurves theFitCurves = null;
try
{
theFitCurves = new FitCurves();
// The following method shows the dialog immediately
theFitCurves.Show();
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
finally
{
if (theFitCurves != null)
theFitCurves.Dispose();
theFitCurves = null;
}
}
public static int GetUnloadOption(string arg)
{
//return System.Convert.ToInt32(Session.LibraryUnloadOption.Explicitly);
return System.Convert.ToInt32(Session.LibraryUnloadOption.Immediately);
// return System.Convert.ToInt32(Session.LibraryUnloadOption.AtTermination);
}
public static void UnloadLibrary(string arg)
{
try
{
//---- Enter your code here -----
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
}
public NXOpen.UIStyler.DialogResponse Show()
{
try
{
theDialog.Show();
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return 0;
}
public void Dispose()
{
if (theDialog != null)
{
theDialog.Dispose();
theDialog = null;
}
}
public void initialize_cb()
{
try
{
selection0 = (NXOpen.BlockStyler.SelectObject)theDialog.TopBlock.FindBlock("selection0");
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
}
public void dialogShown_cb()
{
try
{
//---- Enter your callback code here -----
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
}
public int apply_cb()
{
int errorCode = 0;
try
{
Run_Main();
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
errorCode = 1;
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return errorCode;
}
public int update_cb(NXOpen.BlockStyler.UIBlock block)
{
try
{
if (block == selection0)
{
//---------Enter your code here-----------
}
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return 0;
}
public int ok_cb()
{
int errorCode = 0;
try
{
errorCode = apply_cb();
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
errorCode = 1;
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return errorCode;
}
public int cancel_cb()
{
try
{
//---- Enter your callback code here -----
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return 0;
}
public int filter_cb(NXOpen.BlockStyler.UIBlock block, NXOpen.TaggedObject selectedObject)
{
return (NXOpen.UF.UFConstants.UF_UI_SEL_ACCEPT);
}
public PropertyList GetBlockProperties(string blockID)
{
PropertyList plist = null;
try
{
plist = theDialog.GetBlockProperties(blockID);
}
catch (Exception ex)
{
//---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString());
}
return plist;
}
public void Run_Main()
{
var selObjs = selection0.GetSelectedObjects();
if (selObjs.Length != 1)
{
NxOpen.MsgNx("请先择正确的对象!");
return;
}
//将控件对象转化为Spline对象
Spline spline = selObjs[0] as Spline;
//创建操作
Operation op = workPart.CAMSetup.CAMOperationCollection.Create(
NxOpen.CreateNcGroup("NC_PROGRAM"),
NxOpen.CreateMethod("DefaultMethod_Fxp"),
NxOpen.CreateTool("TEST10", 10, 0),
NxOpen.CreateMCS("MCS"),
"mill_planar",
"PLANAR_MILL",
NXOpen.CAM.OperationCollection.UseDefaultName.True, "123");
//设置操作的底面
var pmb = NxOpen.SetPlanarMillFloorPlane(op, 0);
Plane plane_zero = NxOpen.CreatePlanar(0);
//设置操作的边界几何体
NxOpen.SetCurvesToPlaneMill(op.Tag, plane_zero.Tag, new Tag[] { spline.Tag },
CamGeomType.CamPart,//部件边界
CamBoundaryType.CamBoundaryTypeOpen,//开放区域
CamMaterialSide.CamMaterialSideInLeft,//左侧
CamToolPosition.CamToolPositionOn); //对中
//刀轨参数:轮廓加工模式
pmb.CutPattern.CutPattern = CutPatternBuilder.Types.Profile;
//刀轨参数:移除刀轨的进退刀类型。
pmb.NonCuttingBuilder.EngageClosedAreaBuilder.EngRetType = NcmPlanarEngRetBuilder.EngRetTypes.None;
pmb.NonCuttingBuilder.EngageOpenAreaBuilder.EngRetType = NcmPlanarEngRetBuilder.EngRetTypes.None;
pmb.NonCuttingBuilder.RetractAreaBuilder.EngRetType = NcmPlanarEngRetBuilder.EngRetTypes.None;
pmb.Commit();
//生成刀轨
op.GenToolPath();
workPart.Views.UpdateDisplay();
//输出后处理文件
workPart.CAMSetup.Postprocess(new CAMObject[] { op }, "Fxp_Post_FitCurves",
Base.GetFileLocal() + "test.txt", CAMSetup.OutputUnits.Metric);
List<PostLinePropry> allPls = new List<PostLinePropry>();
//读取后处理文件的所有行
string[] allLines = File.ReadAllLines(Base.GetFileLocal() + "test.txt");
bool IsStart = false;
//遍历文件、解析数据
foreach (string line in allLines)
{
if (line.Contains("X") && line.Contains("Y"))
IsStart = true;
if (!IsStart)
continue;
if (!line.Contains("X") && !line.Contains("Y") && !line.Contains("Z") && !line.Contains("I") && !line.Contains("J"))
break;
PostLinePropry pl = new PostLinePropry();
foreach (string subRange in line.Split(' '))
{
if (subRange.Contains("X"))
pl.X = Convert.ToDouble(subRange.Split('X')[1]);
if (subRange.Contains("Y"))
pl.Y = Convert.ToDouble(subRange.Split('Y')[1]);
if (subRange.Contains("Z"))
pl.Z = Convert.ToDouble(subRange.Split('Z')[1]);
if (subRange.Contains("I"))
pl.I = Convert.ToDouble(subRange.Split('I')[1]);
if (subRange.Contains("J"))
pl.J = Convert.ToDouble(subRange.Split('J')[1]);
if (subRange.Contains("K"))
pl.K = Convert.ToDouble(subRange.Split('K')[1]);
if (subRange.Contains("G"))
{
int type = Convert.ToInt32(subRange.Split('G')[1]);
if (type == 1)
pl.MoveMode = PostLinePropry.MoveModeEnum.Move_Line;
if (type == 2)
pl.MoveMode = PostLinePropry.MoveModeEnum.Move_Arc_G2;
if (type == 3)
pl.MoveMode = PostLinePropry.MoveModeEnum.Move_Arc_G3;
}
}
if (allPls.Count == 0)
pl.MoveMode = PostLinePropry.MoveModeEnum.Move_Start;
if (pl.X == 0 && pl.Y == 0 && pl.I == 0 && pl.J == 0)
continue;
allPls.Add(pl);
}
//遍历数据,并创建圆和直线对样条拟合
FxpApiOther o = new FxpApiOther();
for (int i = 0; i < allPls.Count; i++)
{
Thread.Sleep(200);
workPart.Views.UpdateDisplay();
PostLinePropry pl = allPls[i];
PostLinePropry _pl = null;
if (i != 0)
_pl = allPls[i - 1];
if (pl.MoveMode == PostLinePropry.MoveModeEnum.Move_Start)
{
o.CreatePoint(new double[] { pl.X, pl.Y, pl.Z });
continue;
}
if (pl.MoveMode == PostLinePropry.MoveModeEnum.SameAsBack)
{
pl.MoveMode = _pl.MoveMode;
}
if (pl.MoveMode == PostLinePropry.MoveModeEnum.Move_Line)
{
o.CreateLine(new double[] { _pl.X, _pl.Y, _pl.Z }, new double[] { pl.X, pl.Y, pl.Z });
}
if (pl.MoveMode == PostLinePropry.MoveModeEnum.Move_Arc_G2)
{
Tag oTag = o.CreatePoint(new double[] { pl.X, pl.Y, pl.Z });
theUFSession.Obj.SetColor(oTag, 186);
Tag cTag = o.CreateArc(new double[] { _pl.X + pl.I, _pl.Y + pl.J, _pl.Z + pl.K }, GetRaduis(_pl.X, _pl.Y, _pl.Z, _pl.X + pl.I, _pl.Y + pl.J, _pl.Z + pl.K));
theUFSession.Obj.SetColor(cTag, 186);
}
if (pl.MoveMode == PostLinePropry.MoveModeEnum.Move_Arc_G3)
{
Tag oTag = o.CreatePoint(new double[] { pl.X, pl.Y, pl.Z });
theUFSession.Obj.SetColor(oTag, 36);
Tag cTag = o.CreateArc(new double[] { _pl.X + pl.I, _pl.Y + pl.J, _pl.Z + pl.K }, GetRaduis(_pl.X, _pl.Y, _pl.Z, _pl.X + pl.I, _pl.Y + pl.J, _pl.Z + pl.K));
theUFSession.Obj.SetColor(cTag, 36);
}
}
}
/// <summary>
/// 获取半径值:即圆心位置到圆弧起始位置的距离
/// </summary>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <param name="Z"></param>
/// <param name="I"></param>
/// <param name="J"></param>
/// <param name="K"></param>
/// <returns></returns>
public double GetRaduis(double X, double Y, double Z, double I, double J, double K)
{
return Math.Sqrt(Math.Pow(X - I, 2) + Math.Pow(Y - J, 2) + Math.Pow(Z - K, 2));
}
/// <summary>
/// 数据类
/// </summary>
public class PostLinePropry
{
public PostLinePropry()
{
//默认的构造函数给枚举设置为与上一个相同
MoveMode = MoveModeEnum.SameAsBack;
}
/// <summary>
/// 刀轨运动模式枚举
/// </summary>
public enum MoveModeEnum
{
/// <summary>
/// 刀轨开始
/// </summary>
Move_Start = 0,
/// <summary>
/// 刀轨运动模式与上一个相同
/// </summary>
SameAsBack = 1,
/// <summary>
/// 直线运动模式(G01)
/// </summary>
Move_Line = 2,
/// <summary>
/// 圆弧运动模式(G02)
/// </summary>
Move_Arc_G2 = 3,
/// <summary>
/// 圆弧运动模式(G03)
/// </summary>
Move_Arc_G3 = 4
}
/// <summary>
/// X坐标(圆弧起始位置)
/// </summary>
public double X { get; set; }
/// <summary>
/// Y坐标(圆弧起始位置)
/// </summary>
public double Y { get; set; }
/// <summary>
/// Y坐标(圆弧起始位置)
/// </summary>
public double Z { get; set; }
/// <summary>
/// I值(圆弧起始位置距离圆弧中心的X方向投影距离)
/// </summary>
public double I { get; set; }
/// <summary>
/// J值(圆弧起始位置距离圆弧中心的Y方向投影距离)
/// </summary>
public double J { get; set; }
/// <summary>
/// K值(圆弧起始位置距离圆弧中心的Z方向投影距离)
/// </summary>
public double K { get; set; }
/// <summary>
/// 刀轨运动模式
/// </summary>
public MoveModeEnum MoveMode { get; set; }
}
}