Jump to content

Welcome to eMastercam

Register now to participate in the forums, access the download area, buy Mastercam training materials, post processors and more. This message will be removed once you have signed in.

Use your display name or email address to sign in:

Write NCI Data To Operations Comment Section


Recommended Posts

Hi here is my latest project scanning the nci file and operation/tool then writing some information to the comment section.

Here we are renaming the operation posting the nci data reading it  then deleting the file and restoring the operations name.

Optional error report at the end

#include "StdAfx.h"
// <copyright file="AiOperationCommentInfo.cpp">
// Copyright (c) 2020 Peter Evans, Inc. All rights reserved.
// </copyright>
// <summary>Write information from the operation to the comments section</summary>

//////////////////////////////////////////

////start of StringManipulation header/////

//////////////////////////////////////////

namespace StringManipulation
{
	System::Int32^ stringtoint(System::String ^ numberStr);
	System::Double^ stringtodouble(System::String ^ numberStr);
	System::String ^ ConvertStringArrayToStringJoin(array<System::String^>^ array);
	System::String ^ GetAfter(System::String ^ strSource, System::String ^ toBeSearched);
	System::String ^ GetBefore(System::String ^ strSource, System::String ^ toBeSearched);
	System::String ^ GetStringAfter(long count, System::String ^ input, System::String ^ text);
}
//////////////////////////////////////////

////end of StringManipulation header/////

//////////////////////////////////////////
//////////////////////////////////////////

////start of FileManagerUtilities header/////

//////////////////////////////////////////

namespace FileManagerUtilities

{

	public ref struct TargetFile

	{

		System::String ^ pathtofile;

		System::String ^ filename;

		System::Int32 ^ index;

	};

	public ref class FileInformation

	{

	public:



		FileInformation();



		~FileInformation();



		//System::String^ GetCurrentFileName();




		array<System::String^>^ GetAllLinesFromFileToArray(System::String^ filepath);

		array<System::String^>^ SplitLineWhiteSpace(System::String ^ line);

		array<System::String^>^ FilePathList(System::String ^ filepathtodirectory, System::String ^ fileextention);

		array<TargetFile^>^ GetTargetFileArray(array<System::String^>^ StringArray);

	private:



	};
}
//////////////////////////////////////////

////end of FileManagerUtilities header/////

//////////////////////////////////////////
//////////////////////////////////////////

////start of StringManipulation funtions/////

//////////////////////////////////////////

System::Int32^ StringManipulation::stringtoint(System::String ^ numberStr)
{
	auto number = gcnew System::Int32;

	bool isParsable = System::Int32::TryParse(numberStr, *number);

	return isParsable ? number : nullptr;
}

System::Double^ StringManipulation::stringtodouble(System::String ^ numberStr)
{

	auto number = gcnew System::Double;// ^ number;// = gcnew double;

	bool isParsable = System::Double::TryParse(numberStr, *number);

	return isParsable ? number : nullptr;
}
System::String^ StringManipulation::ConvertStringArrayToStringJoin(array<System::String^>^ array)
{
	// Use string Join to concatenate the string elements.
	auto result = System::String::Join(".", array);
	return result;
}

System::String^ GetBetween(System::String^ strSource, System::String^ strStart, System::String^ strEnd)
{
	if (strSource != nullptr && strStart != nullptr && strEnd != nullptr)
	{
		int Start, End;
		if (strSource->Contains(strStart) && strSource->Contains(strEnd))
		{
			Start = strSource->IndexOf(strStart, 0) + strStart->Length;
			End = strSource->IndexOf(strEnd, Start);
			return strSource->Substring(Start, End - Start);

		}
	}
	return nullptr;
}

//in string 1 > initial string to be searched
//in string 2 > the value to search for
//returns new string found after first instance of initial string
System::String^  StringManipulation::GetAfter(System::String^  strSource, System::String^  toBeSearched)
{
	int ix = strSource->IndexOf(toBeSearched, System::StringComparison::InvariantCultureIgnoreCase);

	if (ix != -1)
	{
		System::String^ code = strSource->Substring(ix + toBeSearched->Length);
		return code;
	}
	return nullptr;

}
System::String^  StringManipulation::GetBefore(System::String^  strSource, System::String^  toBeSearched)
{
	int ix = strSource->IndexOf(toBeSearched, System::StringComparison::InvariantCultureIgnoreCase);

	if (ix != -1)
	{
		System::String^ code = strSource->Substring(0, ix);
		return code;
	}
	return nullptr;

}
System::String ^ StringManipulation::GetStringAfter(long count, System::String ^ input, System::String ^ text)
{
	System::String ^ code = GetAfter(text, input);

	if (code != nullptr)
	{
		count = count + 1;
		code = code->Trim();
		code = code->IndexOf(" ") > -1
			? code->Substring(0, code->IndexOf(" "))
			: code;
		return code;
	}
	return nullptr;
}
//////////////////////////////////////////

////end of StringManipulation functions/////

//////////////////////////////////////////


//////////////////////////////////////////

////start of WinformsUI header/////

//////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////the funtions headers used in our user interface
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//gets a listview from the supplied windows form control
//in : int x, int y, System::Windows::Forms::Control ^ control
//returns : System::Windows::Forms::ListView^
System::Windows::Forms::ListView^ GetListViewFromPoint(int x, int y, System::Windows::Forms::Control ^ control);

//gets a textbox from the supplied windows form control
//System::Windows::Forms::Control ^ control in : int x int y 
//returns : System::Windows::Forms::Control ^ 
System::Windows::Forms::Control ^ GetTextboxControlFromPoint(System::Windows::Forms::Control ^ control, int x, int y);


void SetMinMaxValueToList(System::Collections::Generic::List<double> ^ zdepthvaluelist, double &MinZValue, double &MaxZValue);

array<array<System::String^>^>^ GetArrayofArrayOfLinesFromFile(System::Windows::Forms::ListView::ListViewItemCollection ^ itemlist, System::String ^ pathtofiles, System::String ^ extention);

//The signature of Button click event handler is listed in the following code snippet.
//click event to write the quantity of parts to be nested to the user interface data label
//in : System::Object ^ sender, System::EventArgs ^ e

void GetMinMaxValueToList(System::String ^ negativezval, System::Collections::Generic::List<double> ^ zdepthvaluelist, System::String ^ positivezval);

//creates a listview on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form int mainlistitem
System::Windows::Forms::ListView ^ CreateListViewOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form, int mainlistitem);

//creates a textbos on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::TextBox ^ CreateTextboxOnWinform(int Left4, int Top4, int Width4, int Height4, System::Windows::Forms::Form ^ Form);

//creates a button on the supplied windows form
//in : int Left, int Top, int Width, int Height, 
//in : System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, 
//in : void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e)
System::Windows::Forms::Button ^ CreateButtonOnForm(int buttonleft, int buttontop, int buttonwidth, int buttonheight, System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e));

//creates a label on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::Label ^ CreateLabelOnForm(int labelleft, int labeltop, int labelwidth, int labelheight, System::String ^ labelmessage, System::Windows::Forms::Form ^ Form);


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////end of funtions region
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////

////end of WinformsUI header/////

//////////////////////////////////////////

//////////////////////////////////////////

////start of WinformsUI functions/////

//////////////////////////////////////////

void WriteLinesToTextFileDeleteIfExisting(array<System::String^>^ StringArray, System::String^ Path)
{
	//if (System::IO::File::Exists(Path))
	//{
	//	System::IO::File::Delete(Path);
	//}
	System::IO::StreamWriter ^ sw = gcnew System::IO::StreamWriter(Path);
	sw->WriteLine("Nc File Report");
	for (auto i = 0; i < StringArray->Length; i++)
	{
		sw->WriteLine(StringArray[i]);
	}
	sw->Close();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////the funtions used in our user interface
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public ref struct NcDataReaderParams
{
	System::String ^ NcFilenamePrefix;
	System::String ^ StockThicknessPrefix;
	System::String ^ DateAndTimePrefix;
	System::String ^ PathToNcFileFolder;
	System::String ^ PathToOutputFolder;
};

NcDataReaderParams ^ GetNcDataReaderParams(System::String ^ pathtofiles, System::String ^ filename, System::String ^ extention)
{

	auto params = gcnew NcDataReaderParams;

	if (System::IO::Directory::Exists(pathtofiles))
	{
		auto parameterlist = gcnew System::Collections::Generic::List<System::String ^>;

		FileManagerUtilities::FileInformation fileinformation;

		auto listoffiles = fileinformation.FilePathList(pathtofiles, extention);

		for (auto i = 0; i < listoffiles->Length; i++)

		{

			if (System::IO::Path::GetFileName(listoffiles[i]) == filename) {

				auto lines = System::IO::File::ReadAllLines(listoffiles[i]);

				for (auto j = 0; j < lines->Length; j++)
				{
					parameterlist->Add(lines[j]);
				}



				auto parameterarray = parameterlist->ToArray();

				if (parameterarray->Length == 5)

				{

					for (auto j = 0; j < parameterarray->Length; j++)

					{

						switch (j)

						{

						case 0:

						{

							params->NcFilenamePrefix = parameterarray[j];

						}



						case 1:

						{

							params->StockThicknessPrefix = parameterarray[j];

						}

						case 2:

						{

							params->DateAndTimePrefix = parameterarray[j];

						}

						case 3:

						{

							params->PathToNcFileFolder = parameterarray[j];

						}
						case 4:

						{

							params->PathToOutputFolder = parameterarray[j];

						}

						}

					}

				}

			}
		}
	}
	return params;
}

///
//creates a textbos on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::TextBox ^ CreateTextboxOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form)
{

	System::Windows::Forms::TextBox ^ txtbox = gcnew System::Windows::Forms::TextBox;
	txtbox->Left = Left;
	txtbox->Top = Top;
	txtbox->Width = Width;
	txtbox->Height = Height;
	txtbox->Text = "";
	txtbox->BackColor = System::Drawing::Color::Black;
	txtbox->ForeColor = System::Drawing::Color::White;
	return txtbox;
}
//creates a button on the supplied windows form
//in : int Left, int Top, int Width, int Height, 
//in : System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, 
//in : void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e)
System::Windows::Forms::Button ^ CreateButtonOnForm(int buttonleft, int buttontop, int buttonwidth, int buttonheight, System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e))
{
	System::Windows::Forms::Button ^ button = gcnew System::Windows::Forms::Button;
	button->Left = buttonleft;
	button->Top = buttontop;
	button->Width = buttonwidth;
	button->Height = buttonheight;
	button->Name = buttonname;
	button->Text = buttonname2;
	button->BackColor = System::Drawing::Color::Black;
	button->ForeColor = System::Drawing::Color::White;
	//button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
	//add event handler to the button //function below
	button->Click += gcnew System::EventHandler(funtioninput);


	return button;
}
//creates a label on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::Label ^ CreateLabelOnForm(int labelleft, int labeltop, int labelwidth, int labelheight, System::String ^ labelmessage, System::Windows::Forms::Form ^ Form)
{
	System::Windows::Forms::Label ^ label = gcnew System::Windows::Forms::Label;
	label->Left = labelleft;
	label->Top = labeltop;
	label->Width = labelwidth;
	label->Height = labelheight;
	label->Text = labelmessage;
	label->BackColor = System::Drawing::Color::Black;
	label->ForeColor = System::Drawing::Color::White;
	//label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
	return label;
}
//creates a listview on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form int mainlistitem
System::Windows::Forms::ListView ^ CreateListViewOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form, int mainlistitem)
{
	System::Windows::Forms::ListView ^ ListView1 = gcnew System::Windows::Forms::ListView;
	ListView1->Left = Left;
	ListView1->Top = Top;
	ListView1->Width = Width;
	ListView1->Height = Height;
	ListView1->BackColor = System::Drawing::Color::Black;
	ListView1->ForeColor = System::Drawing::Color::White;
	auto header = gcnew System::Windows::Forms::ColumnHeader();
	header->Text = "                            ";
	header->Name = "col1";
	header->Width = Width;
	ListView1->Columns->Add(header);
	ListView1->Scrollable = true;
	ListView1->View = System::Windows::Forms::View::Details;
	//ShowScrollBar(static_cast<HWND>(ListView1->Handle.ToPointer()), (int)SB_VERT, true)
	//Form->Controls->Add(ListView1);
	return ListView1;
}

void SetMinMaxValueToList(System::Collections::Generic::List<double> ^ zdepthvaluelist, double &MinZValue, double &MaxZValue)
{
	auto zdepthvaluearray = zdepthvaluelist->ToArray();
	if (zdepthvaluearray->Length > 0)
	{
		MinZValue = zdepthvaluearray[0];
		MaxZValue = zdepthvaluearray[0];
	}
	for (auto m = 0; m < zdepthvaluearray->Length; m++)
	{
		if (zdepthvaluearray[m] <= MinZValue)
		{
			MinZValue = zdepthvaluearray[m];

		}
		if (zdepthvaluearray[m] >= MaxZValue)
		{
			MaxZValue = zdepthvaluearray[m];
		}
	}
}

array<array<System::String^>^>^ GetArrayofArrayOfLinesFromFile(System::Windows::Forms::ListView::ListViewItemCollection ^ itemlist, System::String ^ pathtofiles, System::String ^ extention)
{

	auto listofarraysoflinesfromfile = gcnew System::Collections::Generic::List<array<System::String^>^>;
	//loop through the current listview located at the specified coordinates
	for (auto i = 0; i < itemlist->Count; i++)
	{
		//check the items select bit if it is selected -> continue
		if (itemlist[i]->Selected == true)

		{



			FileManagerUtilities::FileInformation fileinformation;
			if (System::IO::Directory::Exists(pathtofiles))
			{

				auto listoffiles = fileinformation.FilePathList(pathtofiles, extention);

				for (auto j = 0; j < listoffiles->Length; j++)
				{
					if (System::IO::File::Exists(listoffiles[j]))
					{
						if (System::IO::Path::GetFileName(listoffiles[j]) == itemlist[i]->Text)
						{
							auto lines = fileinformation.GetAllLinesFromFileToArray(listoffiles[j]);

							listofarraysoflinesfromfile->Add(lines);

						}
					}
				}
				
			}
		}
	}
	return listofarraysoflinesfromfile->ToArray();
}


void GetMinMaxValueToList(System::String ^ negativezval, System::Collections::Generic::List<double> ^ zdepthvaluelist, System::String ^ positivezval)
{
	if (negativezval != nullptr)
	{
		auto curzval = StringManipulation::stringtodouble(negativezval);
		if (curzval != nullptr)
		{
			zdepthvaluelist->Add(-*curzval);
		}
	}
	else
	{
		if (positivezval != nullptr)
		{
			auto curzval = StringManipulation::stringtodouble(positivezval);
			if (curzval != nullptr)
			{
				zdepthvaluelist->Add(*curzval);
			}
			
		}
	}
}

//gets a listview from the supplied windows form control
//in : int x, int y, System::Windows::Forms::Control ^ control
//returns : System::Windows::Forms::ListView^
System::Windows::Forms::ListView^ GetListViewFromPoint(int x, int y, System::Windows::Forms::Control ^ control)
{
	System::Drawing::Point listviewpoint;
	//define x position
	listviewpoint.X = x;
	//define y position
	listviewpoint.Y = y;
	//get the parent System::Windows::Forms::Form
	auto listviewformcontrol = control->GetChildAtPoint(listviewpoint);
	//typecast the System::Windows::Forms::Control as a textbox so we can access it
	return dynamic_cast<System::Windows::Forms::ListView^>(listviewformcontrol);
}
//gets a textbox from the supplied windows form control
//System::Windows::Forms::Control ^ control in : int x int y 
//returns : System::Windows::Forms::Control ^ 
System::Windows::Forms::Control ^ GetTextboxControlFromPoint(System::Windows::Forms::Control ^ control, int x, int y)
{
	System::Drawing::Point textpoint;
	//define x position
	textpoint.X = x;
	//define y position
	textpoint.Y = y;
	//get the parent System::Windows::Forms::Form
	return control->GetChildAtPoint(textpoint);
}

//////////////////////////////////////////

////end of WinformsUI functions/////

//////////////////////////////////////////





//////////////////////////////////////////

////start of FileManagerUtilities function definitions/////

//////////////////////////////////////////

FileManagerUtilities::FileInformation::FileInformation()
{

}

FileManagerUtilities::FileInformation::~FileInformation()
{

}

array<System::String^>^ FileManagerUtilities::FileInformation::GetAllLinesFromFileToArray(System::String ^ filepath)
{
	return System::IO::File::Exists(filepath) ?
		System::IO::File::ReadAllLines(filepath) :
		nullptr;

}

array<System::String^>^ FileManagerUtilities::FileInformation::SplitLineWhiteSpace(System::String ^ line)

{
	return line != nullptr ? line->Split(nullptr) : nullptr;
}

array<System::String^>^ FileManagerUtilities::FileInformation::FilePathList(System::String ^ filepathtodirectory, System::String ^ fileextention)
{


	auto count = 0;
	auto filelist = gcnew System::Collections::Generic::List <System::String^>(0);
	auto files = System::IO::Directory::GetFiles(filepathtodirectory, fileextention);
	for (auto i = 0; i < files->Length; i++)
	{
		auto fileinfo = gcnew System::IO::FileInfo(files[i]);

		if (fileinfo != nullptr &&
			files[i] != nullptr &&
			files[i] != System::String::Empty)
		{
			filelist->Add(files[i]);
			count++;
		}
	}
	return count > 0 ? filelist->ToArray() : nullptr;
}

array<FileManagerUtilities::TargetFile^>^ FileManagerUtilities::FileInformation::GetTargetFileArray(array<System::String^>^ StringArray)
{
	auto targetfilelist = gcnew System::Collections::Generic::List<TargetFile ^>(0);

	auto count = 0;


	for (auto i = 0; i < StringArray->Length; i++)
	{
		auto targetfile = gcnew TargetFile();
		targetfile->filename =
			System::IO::Path::GetFileName(StringArray[i]);
		targetfile->pathtofile = StringArray[i];
		targetfile->index = count;
		targetfilelist->Add(targetfile);
		count++;
	}
	return count > 0 ? targetfilelist->ToArray() : nullptr;
}


namespace AiTools
{
	//get a list of all the operations in the database
	std::vector<operation *> GetListOfOperations()
	{
		//vector to hold operations
		std::vector<operation *> ops;
		//check if we have something
		if (!TpMainOpMgr.GetMainOpList().IsEmpty())
		{
			//loop through the list of operation
			for (auto index = 0; index < TpMainOpMgr.GetMainOpList().GetSize(); ++index)
			{
				//get the current operation
				auto op = TpMainOpMgr.GetMainOpList()[index];
				//check if the pointer is valid
				if (op != nullptr)
				{
					//add the operation
					ops.push_back(op);
				}
			}
		}
		return ops;
	}
	//get a list of tool assemblies from the database
	std::vector<Cnc::Tool::TlAssemblyCPtr> GetListOfTools()
	{
		//vector to hold assemblies
		std::vector<Cnc::Tool::TlAssemblyCPtr> toolassemblies;
		//check if we have something
		if (!Cnc::Tool::GetToolSystem()->GetAssemblies().empty())
		{
			//loop through the list of assemblies
			for (auto index = 0; index < Cnc::Tool::GetToolSystem()->GetAssemblies().size(); ++index)
			{
				//loop through the list of assemblies
				auto tool = Cnc::Tool::GetToolSystem()->GetAssemblies()[index];
				//check if the pointer is valid
				if (tool != nullptr)
				{
					//add the current assembbly
					toolassemblies.push_back(tool);
				}
			}
		}
		return toolassemblies;
	}
	void PostOperationNci(const operation *op)
	{
		nci_bin n;
		long long fpos = 0;
		bool succf = false;
		//post 1 operationss NCI data
		nci_manager(op->op_idn, NCIMGR_POST_ONE, &n, &fpos, &succf);
	}

	System::String^ GetPathToNciFolder()
	{
		//get the path to the nci data output folder
	return System::IO::Path::Combine(Mastercam::IO::SettingsManager::SharedDirectory, "Mill\\NCI\\");
	}
#include "atlstr.h"
	public ref class Functions
	{
	    public : void AiOperationCommentInfo()
		{
			//create a list strings to output to our report
			auto listviewlist = gcnew System::Collections::Generic::List<System::String^>;
			//get the list of operations
			auto ops = GetListOfOperations();
			//get the list of tool assemblies
			auto toolassemblies = GetListOfTools();
			//check if we have something
			if (!ops.empty() && !toolassemblies.empty())
			{
				//loop through the list of operations
				for (const auto op : ops)
				{
					//loop through the list of tool assemblies
					for (const auto tool : toolassemblies)
					{
						//find the tool that matches the operation
						if (tool->GetSlot() == op->tl.slot)
						{
							//store the name of the operation
							CString ncioriginalname = op->cmn.nci_name;
							//create a new variable to hold the temporary operation nci name
							CString nci_name;
							//store the operation index in the variable
							nci_name.Format(_T("%sOperation %d.nci"), NCIPrefixStr(), op->op_idn);

#if C_H_VERSION >= 2100 // Mastercam 2019 or later
							//assign the new name to the operation
							_tcscpy(op->cmn.nci_name, nci_name);
#else
							//assign the new name to the operation
							sprintf(op->cmn.nci_name, _T(nci_name));
#endif

							DB_LIST_ENT_PTR ptr = nullptr; bool bsuccf;
							//rewite the operation
							operation_manager(op, OPMGR_REWRITE, &ptr, &bsuccf);

							nci_bin n;
							long long fpos = 0;
							bool succf = false;
							//post the operation
							nci_manager(op->op_idn, NCIMGR_POST_ONE, &n, &fpos, &succf);
							//get the current nci filename//no need to convert from CString we know the opid
							System::String^ filename = "Operation " + op->op_idn.ToString() + ".nci";
							//get the path to mastercams NCI output directory
							auto path = System::IO::Path::Combine(System::IO::Path::Combine(Mastercam::IO::SettingsManager::UserDirectory, "Mill//NCI//"));
							//check if the path exists
							if (System::IO::Directory::Exists(path))
							{
								FileManagerUtilities::FileInformation fileinformation;
								//Get the list of NCI files in the output folder
								auto filearray = fileinformation.FilePathList(path, "*.nci*");
								//loop through the list of NCI files in the output folder
								for (auto i = 0; i < filearray->Length; i++)
								{
									//check if we have something
									if (System::IO::File::Exists(filearray[i]))
									{
										
										auto checkzdepthmode = false;

										if (System::IO::Path::GetFileName(filearray[i]) == filename)
										{
											//create a new list to hold z values
											auto  zdepthvaluelist = gcnew System::Collections::Generic::List<System::Double>;
											//get an array of lines from the NCI file
											auto lines = fileinformation.GetAllLinesFromFileToArray(filearray[i]);
											//loop through the lines
											for (auto j = 0; j < lines->Length; j++)
											{
												//get an array of substrings from each line
												auto substrings = fileinformation.SplitLineWhiteSpace(lines[j]);
												//copy some information from the nci file
												for (auto k = 0; k < substrings->Length; k++)
												{
													if (substrings->Length == 1)
													{
														System::Int32^ number1002 = 1002;
														auto number = StringManipulation::stringtoint(substrings[k]);

														if (number != nullptr)
														{
															
															if (*number != 0 && *number != 1 && *number != 2 && *number != 3 && *number != 80 && *number != 81 && *number != 82 && *number != 83)
															{
																if (*number == *number1002)
																{
																	
																	checkzdepthmode = true;
																}
																else
																{
																	checkzdepthmode = false;
																}
															}
														}
													}

													if (substrings->Length == 18 && checkzdepthmode == true)
													{
														if (k == 12)
														{
															auto zval = StringManipulation::stringtodouble(substrings[k]);

															zdepthvaluelist->Add(*zval);
														}
													}
													if (substrings->Length == 10 && checkzdepthmode == true)
													{
														if (k == 6)
														{
															auto zval = StringManipulation::stringtodouble(substrings[k]);

															zdepthvaluelist->Add(*zval);
														}
													}

													if (substrings->Length == 6 && checkzdepthmode == true)
													{

															if (k == 3)
															{
																auto zval = StringManipulation::stringtodouble(substrings[k]);

																zdepthvaluelist->Add(*zval);

															}
													}

													if (op->opcode == TP_DRILL)
													{
														if (substrings->Length == 20 && checkzdepthmode == true)
														{

															if (k == 3)
															{
																auto zval = StringManipulation::stringtodouble(substrings[k]);

																zdepthvaluelist->Add(*zval);

															}
														}
													}
													
												}

											}

											auto maxzval = 0.0;

											auto minzval = 0.0;
											//find the min max z value
											SetMinMaxValueToList(zdepthvaluelist, minzval, maxzval);
											CString OperationInfo;
										    //copy some other information
											OperationInfo.Format(_T("ZMin :Z%lf ZMax :Z%lf TlLength :%lf Tldia :%lf Tlnum :%d RPM :%d Feed :%lf"), minzval,maxzval, tool->GetStickout(), op->tl.dia,op->tl.tlno, op->tl.rpm, op->tl.feed);
#if C_H_VERSION >= 2100 // Mastercam 2019 or later

											//write the information to the operation comment
											_tcscpy(op->comment, OperationInfo);
											//restore the original filename
											_tcscpy(op->cmn.nci_name, ncioriginalname);
#else
											//write the information to the operation comment
											sprintf(op->comment, OperationInfo);
											//restore the original filename
											sprintf(op->cmn.nci_name, ncioriginalname);
#endif
											//rewrite the operation
											operation_manager(op, OPMGR_REWRITE, &ptr, &bsuccf);
											//optional create a list of errors and send them to a report
											auto minzstrval = StringManipulation::GetAfter(minzval.ToString(),"-");

											if (minzstrval != nullptr)
											{
												auto minzdblval = StringManipulation::stringtodouble(minzstrval);
												if (minzdblval != nullptr)
												{

													if (tool->GetStickout() <= *minzdblval + .05)
													{
														listviewlist->Add("Error operation -> " + op->op_idn + " -> tool stickout is too short by ->" + (*minzdblval + .05 - tool->GetStickout()).ToString() + " -> please extend your tool stickout." + "   Max Depth = -" + minzdblval->ToString() + "   Min Depth = " + maxzval.ToString() + "   Tool Stickout = " + tool->GetStickout().ToString());
														
														op->db.select_flag = TRUE;
													}
													else
													{
														op->db.select_flag = FALSE;
													}
													if (tool->GetStickout() > *minzdblval + .5)
													{
														listviewlist->Add("Error operation -> " + op->op_idn + " -> tool stickout is too long by ->" + (tool->GetStickout() - (*minzdblval + .5)).ToString() + " -> please shorten your tool stickout." + "   Max Depth = -" + minzdblval->ToString() +"   Min Depth = " + maxzval.ToString() + "   Tool Stickout = " + tool->GetStickout().ToString());
														
														op->db.select_flag = TRUE;
													}
													else
													{
														op->db.select_flag = FALSE;
													}
												}
											}
											
										}
									System::IO::File::Delete(filearray[i]);
									}
								}
							
							}
						
						}
					}
				}
			}
				
			//optional create a list of errors and send them to a report
			auto array = listviewlist->ToArray();
			//check if we have something
			if (array->Length > 0)
			{
				System::Windows::Forms::Form ^ Form = gcnew System::Windows::Forms::Form;
				Form->BackColor = System::Drawing::Color::DarkGray;
				Form->Width = 1000;
				Form->Height = 650;
				Form->AutoScroll = true;
				Form->HorizontalScroll->Maximum = 0;
				Form->VerticalScroll->Visible = true;
				Form->VerticalScroll->Enabled = true;
				Form->HorizontalScroll->Enabled = false;
				Form->HorizontalScroll->Enabled = false;
				Form->HorizontalScroll->Visible = false;
				System::Windows::Forms::Application::EnableVisualStyles();
				//add the list view to the windows form
				int Left = 10; int Top = 75; int Width = 1000; int Height = Form->Height - 150;
				//add a listview control to the windows form
				auto listview = CreateListViewOnWinform(Left, Top, Width, Height, Form, 1);
				Form->Controls->Add(listview);
				for (auto i = 0; i < array->Length; i++)
				{
					auto listViewItem1 = gcnew System::Windows::Forms::ListViewItem(array[i]);
					//add the listview items to the listview
					listview->Items->Add(listViewItem1);
				}
				Form->Show();
			}
		}
	};
	public ref class AiOperationCommentInfoNethook : public Mastercam::App::NetHook3App
	{

	public: Mastercam::App::Types::MCamReturn AiOperationCommentInfo(int param)
	{
	
		AiTools::Functions functions;
		functions.AiOperationCommentInfo();

		return Mastercam::App::Types::MCamReturn::NoErrors;
	}

	};
}

https://github.com/PeterRussellEvans/WriteOperationDataToCommentSection

Link to comment
Share on other sites

This seems like a lot of code to accomplish this.  Writing the text NCI to disk then scanning it seems rather inefficient, especially on larger NCI files.

I think you could achieve the same result doing something like this...

extern "C" __declspec(dllexport) int eMCExample452020Entry (int param)
{
	// Must call this prior to accessing any Resources in the C-Hook DLL !
	ChangeResCl res (GetChookResourceHandle ());

	CInterrogateMastercamFile fileInterrogator;

	fileInterrogator.Load();

	auto operationIDs = fileInterrogator.GetOpIDsInOpMgrOrder();

	if (operationIDs != nullptr)
	{
		p_3d min;
		p_3d max;

		Cnc::Tool::TlAssemblyCPtr toolAssembly;

		std::wstring newComment = L"";

		DB_LIST_ENT_PTR outPointer = nullptr;

		bool result;

		for (auto opID : *operationIDs)
		{
			auto operation = TpMainOpMgr.GetMainOpList().OpByID(opID);

			fileInterrogator.LoadForSingleOperation(operation->op_idn, true);

			fileInterrogator.CalcBnciExtents(false, false, true, true);

			min = fileInterrogator.GetBnciLowerLeft();
			max = fileInterrogator.GetBnciUpperRight();

			newComment = L"Z Min: " + std::to_wstring(min[2]) + L"\r\n";
			newComment += L"Z Max: " + std::to_wstring(max[2]) + L"\r\n";

			Cnc::Tool::GetToolSystem()->Find(operation->tl.slot, toolAssembly);

			if (toolAssembly != nullptr)
			{
				newComment += L"Tool Projection: " + std::to_wstring(toolAssembly->GetToolProjection()) + L"\r\n";
			}

			_tcscpy_s(operation->comment, newComment.c_str());
			
			operation_manager(operation, OPMGR_REWRITE, &outPointer, &result);
		}
	}
	

	return MC_NOERROR | MC_UNLOADAPP;
}

  

I know you might feel like this...

...but don't; developing in a vacuum is hard. 

 

 

  • Like 1
Link to comment
Share on other sites
15 minutes ago, Zaffin_D said:

.but don't; developing in a vacuum is hard

That is why I share what I do, so others won't have to search the galaxy for answers.

Link to comment
Share on other sites
1 hour ago, Zaffin_D said:

extern "C" __declspec(dllexport) int eMCExample452020Entry (int param) { // Must call this prior to accessing any Resources in the C-Hook DLL ! ChangeResCl res (GetChookResourceHandle ()); CInterrogateMastercamFile fileInterrogator; fileInterrogator.Load(); auto operationIDs = fileInterrogator.GetOpIDsInOpMgrOrder(); if (operationIDs != nullptr) { p_3d min; p_3d max; Cnc::Tool::TlAssemblyCPtr toolAssembly; std::wstring newComment = L""; DB_LIST_ENT_PTR outPointer = nullptr; bool result; for (auto opID : *operationIDs) { auto operation = TpMainOpMgr.GetMainOpList().OpByID(opID); fileInterrogator.LoadForSingleOperation(operation->op_idn, true); fileInterrogator.CalcBnciExtents(false, false, true, true); min = fileInterrogator.GetBnciLowerLeft(); max = fileInterrogator.GetBnciUpperRight(); newComment = L"Z Min: " + std::to_wstring(min[2]) + L"\r\n"; newComment += L"Z Max: " + std::to_wstring(max[2]) + L"\r\n"; Cnc::Tool::GetToolSystem()->Find(operation->tl.slot, toolAssembly); if (toolAssembly != nullptr) { newComment += L"Tool Projection: " + std::to_wstring(toolAssembly->GetToolProjection()) + L"\r\n"; } _tcscpy_s(operation->comment, newComment.c_str()); operation_manager(operation, OPMGR_REWRITE, &outPointer, &result); } } return MC_NOERROR | MC_UNLOADAPP; }

This is also a good solution, thanks Zaffin.

+1000

:thumbsup:

Link to comment
Share on other sites
  • 3 weeks later...
On 4/5/2020 at 9:04 AM, Zaffin_D said:

min = fileInterrogator.GetBnciLowerLeft(); max = fileInterrogator.GetBnciUpperRight();

When I used your method on operations on the bottom plane the value gets inverted

For example Method 1 outputs ZMin -.500 ZMax-.035

Method 2 outputs ZMin .035 ZMax .500 

is there a reliable way to use your method for bottom operations?

#include "stdafx.h"
using Mastercam::App::NetHook3App;
#ifdef UNICODE
#define std_tostring std::to_wstring
#define std_string std::wstring
#else
#define std_tostring std::to_string
#define std_string std::string
#endif //UNICODE 
// <copyright file="AiOperationCommentInfo.cpp">
// Copyright (c) 2020 Peter Evans, Inc. All rights reserved.
// </copyright>
// <summary>Write information from the operation to the comments section</summary>

//////////////////////////////////////////

////start of StringManipulation header/////

//////////////////////////////////////////

namespace StringManipulation
{
	System::Int32^ stringtoint(System::String ^ numberStr);
	System::Double^ stringtodouble(System::String ^ numberStr);
	System::String ^ ConvertStringArrayToStringJoin(array<System::String^>^ array);
	System::String ^ GetAfter(System::String ^ strSource, System::String ^ toBeSearched);
	System::String ^ GetBefore(System::String ^ strSource, System::String ^ toBeSearched);
	System::String ^ GetStringAfter(long count, System::String ^ input, System::String ^ text);
}
//////////////////////////////////////////

////end of StringManipulation header/////

//////////////////////////////////////////
//////////////////////////////////////////

////start of FileManagerUtilities header/////

//////////////////////////////////////////

namespace FileManagerUtilities

{

	public ref struct TargetFile

	{

		System::String ^ pathtofile;

		System::String ^ filename;

		System::Int32 ^ index;

	};

	public ref class FileInformation

	{

	public:



		FileInformation();



		~FileInformation();



		//System::String^ GetCurrentFileName();




		array<System::String^>^ GetAllLinesFromFileToArray(System::String^ filepath);

		array<System::String^>^ SplitLineWhiteSpace(System::String ^ line);

		array<System::String^>^ FilePathList(System::String ^ filepathtodirectory, System::String ^ fileextention);

		array<TargetFile^>^ GetTargetFileArray(array<System::String^>^ StringArray);

	private:



	};
}
//////////////////////////////////////////

////end of FileManagerUtilities header/////

//////////////////////////////////////////
//////////////////////////////////////////

////start of StringManipulation funtions/////

//////////////////////////////////////////

System::Int32^ StringManipulation::stringtoint(System::String ^ numberStr)
{
	auto number = gcnew System::Int32;

	bool isParsable = System::Int32::TryParse(numberStr, *number);

	return isParsable ? number : nullptr;
}

System::Double^ StringManipulation::stringtodouble(System::String ^ numberStr)
{

	auto number = gcnew System::Double;// ^ number;// = gcnew double;

	bool isParsable = System::Double::TryParse(numberStr, *number);

	return isParsable ? number : nullptr;
}
System::String^ StringManipulation::ConvertStringArrayToStringJoin(array<System::String^>^ array)
{
	// Use string Join to concatenate the string elements.
	auto result = System::String::Join(".", array);
	return result;
}

System::String^ GetBetween(System::String^ strSource, System::String^ strStart, System::String^ strEnd)
{
	if (strSource != nullptr && strStart != nullptr && strEnd != nullptr)
	{
		int Start, End;
		if (strSource->Contains(strStart) && strSource->Contains(strEnd))
		{
			Start = strSource->IndexOf(strStart, 0) + strStart->Length;
			End = strSource->IndexOf(strEnd, Start);
			return strSource->Substring(Start, End - Start);

		}
	}
	return nullptr;
}

//in string 1 > initial string to be searched
//in string 2 > the value to search for
//returns new string found after first instance of initial string
System::String^  StringManipulation::GetAfter(System::String^  strSource, System::String^  toBeSearched)
{
	int ix = strSource->IndexOf(toBeSearched, System::StringComparison::InvariantCultureIgnoreCase);

	if (ix != -1)
	{
		System::String^ code = strSource->Substring(ix + toBeSearched->Length);
		return code;
	}
	return nullptr;

}
System::String^  StringManipulation::GetBefore(System::String^  strSource, System::String^  toBeSearched)
{
	int ix = strSource->IndexOf(toBeSearched, System::StringComparison::InvariantCultureIgnoreCase);

	if (ix != -1)
	{
		System::String^ code = strSource->Substring(0, ix);
		return code;
	}
	return nullptr;

}
System::String ^ StringManipulation::GetStringAfter(long count, System::String ^ input, System::String ^ text)
{
	System::String ^ code = GetAfter(text, input);

	if (code != nullptr)
	{
		count = count + 1;
		code = code->Trim();
		code = code->IndexOf(" ") > -1
			? code->Substring(0, code->IndexOf(" "))
			: code;
		return code;
	}
	return nullptr;
}
//////////////////////////////////////////

////end of StringManipulation functions/////

//////////////////////////////////////////


//////////////////////////////////////////

////start of WinformsUI header/////

//////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////the funtions headers used in our user interface
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//gets a listview from the supplied windows form control
//in : int x, int y, System::Windows::Forms::Control ^ control
//returns : System::Windows::Forms::ListView^
System::Windows::Forms::ListView^ GetListViewFromPoint(int x, int y, System::Windows::Forms::Control ^ control);

//gets a textbox from the supplied windows form control
//System::Windows::Forms::Control ^ control in : int x int y 
//returns : System::Windows::Forms::Control ^ 
System::Windows::Forms::Control ^ GetTextboxControlFromPoint(System::Windows::Forms::Control ^ control, int x, int y);


void SetMinMaxValueToList(System::Collections::Generic::List<double> ^ zdepthvaluelist, double &MinZValue, double &MaxZValue);

array<array<System::String^>^>^ GetArrayofArrayOfLinesFromFile(System::Windows::Forms::ListView::ListViewItemCollection ^ itemlist, System::String ^ pathtofiles, System::String ^ extention);

//The signature of Button click event handler is listed in the following code snippet.
//click event to write the quantity of parts to be nested to the user interface data label
//in : System::Object ^ sender, System::EventArgs ^ e

void GetMinMaxValueToList(System::String ^ negativezval, System::Collections::Generic::List<double> ^ zdepthvaluelist, System::String ^ positivezval);

//creates a listview on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form int mainlistitem
System::Windows::Forms::ListView ^ CreateListViewOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form, int mainlistitem);

//creates a textbos on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::TextBox ^ CreateTextboxOnWinform(int Left4, int Top4, int Width4, int Height4, System::Windows::Forms::Form ^ Form);

//creates a button on the supplied windows form
//in : int Left, int Top, int Width, int Height, 
//in : System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, 
//in : void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e)
System::Windows::Forms::Button ^ CreateButtonOnForm(int buttonleft, int buttontop, int buttonwidth, int buttonheight, System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e));

//creates a label on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::Label ^ CreateLabelOnForm(int labelleft, int labeltop, int labelwidth, int labelheight, System::String ^ labelmessage, System::Windows::Forms::Form ^ Form);


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////end of funtions region
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////

////end of WinformsUI header/////

//////////////////////////////////////////

//////////////////////////////////////////

////start of WinformsUI functions/////

//////////////////////////////////////////

void WriteLinesToTextFileDeleteIfExisting(array<System::String^>^ StringArray, System::String^ Path)
{
	//if (System::IO::File::Exists(Path))
	//{
	//	System::IO::File::Delete(Path);
	//}
	System::IO::StreamWriter ^ sw = gcnew System::IO::StreamWriter(Path);
	sw->WriteLine("Nc File Report");
	for (auto i = 0; i < StringArray->Length; i++)
	{
		sw->WriteLine(StringArray[i]);
	}
	sw->Close();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////
//////////the funtions used in our user interface
//////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public ref struct NcDataReaderParams
{
	System::String ^ NcFilenamePrefix;
	System::String ^ StockThicknessPrefix;
	System::String ^ DateAndTimePrefix;
	System::String ^ PathToNcFileFolder;
	System::String ^ PathToOutputFolder;
};

NcDataReaderParams ^ GetNcDataReaderParams(System::String ^ pathtofiles, System::String ^ filename, System::String ^ extention)
{

	auto params = gcnew NcDataReaderParams;

	if (System::IO::Directory::Exists(pathtofiles))
	{
		auto parameterlist = gcnew System::Collections::Generic::List<System::String ^>;

		FileManagerUtilities::FileInformation fileinformation;

		auto listoffiles = fileinformation.FilePathList(pathtofiles, extention);

		for (auto i = 0; i < listoffiles->Length; i++)

		{

			if (System::IO::Path::GetFileName(listoffiles[i]) == filename) {

				auto lines = System::IO::File::ReadAllLines(listoffiles[i]);

				for (auto j = 0; j < lines->Length; j++)
				{
					parameterlist->Add(lines[j]);
				}



				auto parameterarray = parameterlist->ToArray();

				if (parameterarray->Length == 5)

				{

					for (auto j = 0; j < parameterarray->Length; j++)

					{

						switch (j)

						{

						case 0:

						{

							params->NcFilenamePrefix = parameterarray[j];

						}



						case 1:

						{

							params->StockThicknessPrefix = parameterarray[j];

						}

						case 2:

						{

							params->DateAndTimePrefix = parameterarray[j];

						}

						case 3:

						{

							params->PathToNcFileFolder = parameterarray[j];

						}
						case 4:

						{

							params->PathToOutputFolder = parameterarray[j];

						}

						}

					}

				}

			}
		}
	}
	return params;
}

///
//creates a textbos on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::TextBox ^ CreateTextboxOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form)
{

	System::Windows::Forms::TextBox ^ txtbox = gcnew System::Windows::Forms::TextBox;
	txtbox->Left = Left;
	txtbox->Top = Top;
	txtbox->Width = Width;
	txtbox->Height = Height;
	txtbox->Text = "";
	txtbox->BackColor = System::Drawing::Color::Black;
	txtbox->ForeColor = System::Drawing::Color::White;
	return txtbox;
}
//creates a button on the supplied windows form
//in : int Left, int Top, int Width, int Height, 
//in : System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, 
//in : void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e)
System::Windows::Forms::Button ^ CreateButtonOnForm(int buttonleft, int buttontop, int buttonwidth, int buttonheight, System::String ^ buttonname, System::String ^ buttonname2, System::Windows::Forms::Form ^ Form, void(*funtioninput)(System::Object ^ sender, System::EventArgs ^ e))
{
	System::Windows::Forms::Button ^ button = gcnew System::Windows::Forms::Button;
	button->Left = buttonleft;
	button->Top = buttontop;
	button->Width = buttonwidth;
	button->Height = buttonheight;
	button->Name = buttonname;
	button->Text = buttonname2;
	button->BackColor = System::Drawing::Color::Black;
	button->ForeColor = System::Drawing::Color::White;
	//button->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
	//add event handler to the button //function below
	button->Click += gcnew System::EventHandler(funtioninput);


	return button;
}
//creates a label on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form
System::Windows::Forms::Label ^ CreateLabelOnForm(int labelleft, int labeltop, int labelwidth, int labelheight, System::String ^ labelmessage, System::Windows::Forms::Form ^ Form)
{
	System::Windows::Forms::Label ^ label = gcnew System::Windows::Forms::Label;
	label->Left = labelleft;
	label->Top = labeltop;
	label->Width = labelwidth;
	label->Height = labelheight;
	label->Text = labelmessage;
	label->BackColor = System::Drawing::Color::Black;
	label->ForeColor = System::Drawing::Color::White;
	//label->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
	return label;
}
//creates a listview on the supplied windows form
//in : int Left  int Top int Width int Height System::Windows::Forms::Form ^ Form int mainlistitem
System::Windows::Forms::ListView ^ CreateListViewOnWinform(int Left, int Top, int Width, int Height, System::Windows::Forms::Form ^ Form, int mainlistitem)
{
	System::Windows::Forms::ListView ^ ListView1 = gcnew System::Windows::Forms::ListView;
	ListView1->Left = Left;
	ListView1->Top = Top;
	ListView1->Width = Width;
	ListView1->Height = Height;
	ListView1->BackColor = System::Drawing::Color::Black;
	ListView1->ForeColor = System::Drawing::Color::White;
	auto header = gcnew System::Windows::Forms::ColumnHeader();
	header->Text = "                            ";
	header->Name = "col1";
	header->Width = Width;
	ListView1->Columns->Add(header);
	ListView1->Scrollable = true;
	ListView1->View = System::Windows::Forms::View::Details;
	//ShowScrollBar(static_cast<HWND>(ListView1->Handle.ToPointer()), (int)SB_VERT, true)
	//Form->Controls->Add(ListView1);
	return ListView1;
}

void SetMinMaxValueToList(System::Collections::Generic::List<double> ^ zdepthvaluelist, double &MinZValue, double &MaxZValue)
{
	auto zdepthvaluearray = zdepthvaluelist->ToArray();
	if (zdepthvaluearray->Length > 0)
	{
		MinZValue = zdepthvaluearray[0];
		MaxZValue = zdepthvaluearray[0];
	}
	for (auto m = 0; m < zdepthvaluearray->Length; m++)
	{
		if (zdepthvaluearray[m] <= MinZValue)
		{
			MinZValue = zdepthvaluearray[m];

		}
		if (zdepthvaluearray[m] >= MaxZValue)
		{
			MaxZValue = zdepthvaluearray[m];
		}
	}
}

array<array<System::String^>^>^ GetArrayofArrayOfLinesFromFile(System::Windows::Forms::ListView::ListViewItemCollection ^ itemlist, System::String ^ pathtofiles, System::String ^ extention)
{

	auto listofarraysoflinesfromfile = gcnew System::Collections::Generic::List<array<System::String^>^>;
	//loop through the current listview located at the specified coordinates
	for (auto i = 0; i < itemlist->Count; i++)
	{
		//check the items select bit if it is selected -> continue
		if (itemlist[i]->Selected == true)

		{



			FileManagerUtilities::FileInformation fileinformation;
			if (System::IO::Directory::Exists(pathtofiles))
			{

				auto listoffiles = fileinformation.FilePathList(pathtofiles, extention);

				for (auto j = 0; j < listoffiles->Length; j++)
				{
					if (System::IO::File::Exists(listoffiles[j]))
					{
						if (System::IO::Path::GetFileName(listoffiles[j]) == itemlist[i]->Text)
						{
							auto lines = fileinformation.GetAllLinesFromFileToArray(listoffiles[j]);

							listofarraysoflinesfromfile->Add(lines);

						}
					}
				}

			}
		}
	}
	return listofarraysoflinesfromfile->ToArray();
}


void GetMinMaxValueToList(System::String ^ negativezval, System::Collections::Generic::List<double> ^ zdepthvaluelist, System::String ^ positivezval)
{
	if (negativezval != nullptr)
	{
		auto curzval = StringManipulation::stringtodouble(negativezval);
		if (curzval != nullptr)
		{
			zdepthvaluelist->Add(-*curzval);
		}
	}
	else
	{
		if (positivezval != nullptr)
		{
			auto curzval = StringManipulation::stringtodouble(positivezval);
			if (curzval != nullptr)
			{
				zdepthvaluelist->Add(*curzval);
			}

		}
	}
}

//gets a listview from the supplied windows form control
//in : int x, int y, System::Windows::Forms::Control ^ control
//returns : System::Windows::Forms::ListView^
System::Windows::Forms::ListView^ GetListViewFromPoint(int x, int y, System::Windows::Forms::Control ^ control)
{
	System::Drawing::Point listviewpoint;
	//define x position
	listviewpoint.X = x;
	//define y position
	listviewpoint.Y = y;
	//get the parent System::Windows::Forms::Form
	auto listviewformcontrol = control->GetChildAtPoint(listviewpoint);
	//typecast the System::Windows::Forms::Control as a textbox so we can access it
	return dynamic_cast<System::Windows::Forms::ListView^>(listviewformcontrol);
}
//gets a textbox from the supplied windows form control
//System::Windows::Forms::Control ^ control in : int x int y 
//returns : System::Windows::Forms::Control ^ 
System::Windows::Forms::Control ^ GetTextboxControlFromPoint(System::Windows::Forms::Control ^ control, int x, int y)
{
	System::Drawing::Point textpoint;
	//define x position
	textpoint.X = x;
	//define y position
	textpoint.Y = y;
	//get the parent System::Windows::Forms::Form
	return control->GetChildAtPoint(textpoint);
}

//////////////////////////////////////////

////end of WinformsUI functions/////

//////////////////////////////////////////





//////////////////////////////////////////

////start of FileManagerUtilities function definitions/////

//////////////////////////////////////////

FileManagerUtilities::FileInformation::FileInformation()
{

}

FileManagerUtilities::FileInformation::~FileInformation()
{

}

array<System::String^>^ FileManagerUtilities::FileInformation::GetAllLinesFromFileToArray(System::String ^ filepath)
{
	return System::IO::File::Exists(filepath) ?
		System::IO::File::ReadAllLines(filepath) :
		nullptr;

}

array<System::String^>^ FileManagerUtilities::FileInformation::SplitLineWhiteSpace(System::String ^ line)

{
	return line != nullptr ? line->Split(nullptr) : nullptr;
}

array<System::String^>^ FileManagerUtilities::FileInformation::FilePathList(System::String ^ filepathtodirectory, System::String ^ fileextention)
{


	auto count = 0;
	auto filelist = gcnew System::Collections::Generic::List <System::String^>(0);
	auto files = System::IO::Directory::GetFiles(filepathtodirectory, fileextention);
	for (auto i = 0; i < files->Length; i++)
	{
		auto fileinfo = gcnew System::IO::FileInfo(files[i]);

		if (fileinfo != nullptr &&
			files[i] != nullptr &&
			files[i] != System::String::Empty)
		{
			filelist->Add(files[i]);
			count++;
		}
	}
	return count > 0 ? filelist->ToArray() : nullptr;
}

array<FileManagerUtilities::TargetFile^>^ FileManagerUtilities::FileInformation::GetTargetFileArray(array<System::String^>^ StringArray)
{
	auto targetfilelist = gcnew System::Collections::Generic::List<TargetFile ^>(0);

	auto count = 0;


	for (auto i = 0; i < StringArray->Length; i++)
	{
		auto targetfile = gcnew TargetFile();
		targetfile->filename =
			System::IO::Path::GetFileName(StringArray[i]);
		targetfile->pathtofile = StringArray[i];
		targetfile->index = count;
		targetfilelist->Add(targetfile);
		count++;
	}
	return count > 0 ? targetfilelist->ToArray() : nullptr;
}


namespace AiTools
{
	//get a list of all the operations in the database
	std::vector<operation *> GetListOfOperations()
	{
		//vector to hold operations
		std::vector<operation *> ops;
		//check if we have something
		if (!TpMainOpMgr.GetMainOpList().IsEmpty())
		{
			//loop through the list of operation
			for (auto index = 0; index < TpMainOpMgr.GetMainOpList().GetSize(); ++index)
			{
				//get the current operation
				auto op = TpMainOpMgr.GetMainOpList()[index];
				//check if the pointer is valid
				if (op != nullptr)
				{
					//add the operation
					ops.push_back(op);
				}
			}
		}
		return ops;
	}
	//get a list of tool assemblies from the database
	std::vector<Cnc::Tool::TlAssemblyCPtr> GetListOfTools()
	{
		//vector to hold assemblies
		std::vector<Cnc::Tool::TlAssemblyCPtr> toolassemblies;
		//check if we have something
		if (!Cnc::Tool::GetToolSystem()->GetAssemblies().empty())
		{
			//loop through the list of assemblies
			for (auto index = 0; index < Cnc::Tool::GetToolSystem()->GetAssemblies().size(); ++index)
			{
				//loop through the list of assemblies
				auto tool = Cnc::Tool::GetToolSystem()->GetAssemblies()[index];
				//check if the pointer is valid
				if (tool != nullptr)
				{
					//add the current assembbly
					toolassemblies.push_back(tool);
				}
			}
		}
		return toolassemblies;
	}
	void PostOperationNci(const operation *op)
	{
		nci_bin n;
		long long fpos = 0;
		bool succf = false;
		//post 1 operationss NCI data
		nci_manager(op->op_idn, NCIMGR_POST_ONE, &n, &fpos, &succf);
	}

	System::String^ GetPathToNciFolder()
	{
		//get the path to the nci data output folder
		return System::IO::Path::Combine(Mastercam::IO::SettingsManager::SharedDirectory, "Mill\\NCI\\");
	}
#include "atlstr.h"
	public ref class Functions
	{
	public: void AiOperationCommentInfo()
	{
		//create a list strings to output to our report
		auto listviewlist = gcnew System::Collections::Generic::List<System::String^>;
		//get the list of operations
		auto ops = GetListOfOperations();
		//get the list of tool assemblies
		auto toolassemblies = GetListOfTools();
		//check if we have something
		if (!ops.empty() && !toolassemblies.empty())
		{
			//loop through the list of operations
			for (const auto op : ops)
			{
				//loop through the list of tool assemblies
				for (const auto tool : toolassemblies)
				{
					//find the tool that matches the operation
					if (tool->GetSlot() == op->tl.slot)
					{
						//store the name of the operation
						CString ncioriginalname = op->cmn.nci_name;
						//create a new variable to hold the temporary operation nci name
						CString nci_name;
						//store the operation index in the variable
						nci_name.Format(_T("%sOperation %d.nci"), NCIPrefixStr(), op->op_idn);

#if C_H_VERSION >= 2100 // Mastercam 2019 or later
						//assign the new name to the operation
						_tcscpy_s(op->cmn.nci_name, nci_name);
#else
						//assign the new name to the operation
						sprintf_s(op->cmn.nci_name, _T(nci_name));
#endif

						DB_LIST_ENT_PTR ptr = nullptr; bool bsuccf;
						//rewite the operation
						operation_manager(op, OPMGR_REWRITE, &ptr, &bsuccf);

						nci_bin n;
						long long fpos = 0;
						bool succf = false;
						//post the operation
						nci_manager(op->op_idn, NCIMGR_POST_ONE, &n, &fpos, &succf);
						//get the current nci filename//no need to convert from CString we know the opid
						System::String^ filename = "Operation " + op->op_idn.ToString() + ".nci";
						//get the path to mastercams NCI output directory
						auto path = System::IO::Path::Combine(System::IO::Path::Combine(Mastercam::IO::SettingsManager::UserDirectory, "Mill//NCI//"));
						//check if the path exists
						if (System::IO::Directory::Exists(path))
						{
							FileManagerUtilities::FileInformation fileinformation;
							//Get the list of NCI files in the output folder
							auto filearray = fileinformation.FilePathList(path, "*.nci*");
							//loop through the list of NCI files in the output folder
							for (auto i = 0; i < filearray->Length; i++)
							{
								//check if we have something
								if (System::IO::File::Exists(filearray[i]))
								{

									auto checkzdepthmode = false;

									if (System::IO::Path::GetFileName(filearray[i]) == filename)
									{
										//create a new list to hold z values
										auto  zdepthvaluelist = gcnew System::Collections::Generic::List<System::Double>;
										//get an array of lines from the NCI file
										auto lines = fileinformation.GetAllLinesFromFileToArray(filearray[i]);
										//loop through the lines
										for (auto j = 0; j < lines->Length; j++)
										{
											//get an array of substrings from each line
											auto substrings = fileinformation.SplitLineWhiteSpace(lines[j]);
											//copy some information from the nci file
											for (auto k = 0; k < substrings->Length; k++)
											{
												if (substrings->Length == 1)
												{
													System::Int32^ number1002 = 1002;
													auto number = StringManipulation::stringtoint(substrings[k]);

													if (number != nullptr)
													{

														if (*number != 0 && *number != 1 && *number != 2 && *number != 3 && *number != 80 && *number != 81 && *number != 82 && *number != 83)
														{
															if (*number == *number1002)
															{

																checkzdepthmode = true;
															}
															else
															{
																checkzdepthmode = false;
															}
														}
													}
												}

												if (substrings->Length == 18 && checkzdepthmode == true)
												{
													if (k == 12)
													{
														auto zval = StringManipulation::stringtodouble(substrings[k]);

														zdepthvaluelist->Add(*zval);
													}
												}
												if (substrings->Length == 10 && checkzdepthmode == true)
												{
													if (k == 6)
													{
														auto zval = StringManipulation::stringtodouble(substrings[k]);

														zdepthvaluelist->Add(*zval);
													}
												}

												if (substrings->Length == 6 && checkzdepthmode == true)
												{

													if (k == 3)
													{
														auto zval = StringManipulation::stringtodouble(substrings[k]);

														zdepthvaluelist->Add(*zval);

													}
												}

												if (op->opcode == TP_DRILL)
												{
													if (substrings->Length == 20 && checkzdepthmode == true)
													{

														if (k == 3)
														{
															auto zval = StringManipulation::stringtodouble(substrings[k]);

															zdepthvaluelist->Add(*zval);

														}
													}
												}

											}

										}

										auto maxzval = 0.0;

										auto minzval = 0.0;
										//find the min max z value
										SetMinMaxValueToList(zdepthvaluelist, minzval, maxzval);
										CString OperationInfo;
										//copy some other information
										OperationInfo.Format(_T("ZMin :Z%lf ZMax :Z%lf TlLength :%lf Tldia :%lf Tlnum :%d RPM :%d Feed :%lf"), minzval, maxzval, tool->GetStickout(), op->tl.dia, op->tl.tlno, op->tl.rpm, op->tl.feed);
#if C_H_VERSION >= 2100 // Mastercam 2019 or later

										//write the information to the operation comment
										_tcscpy_s(op->comment, OperationInfo);
										//restore the original filename
										_tcscpy_s(op->cmn.nci_name, ncioriginalname);
#else
										//write the information to the operation comment
										sprintf_s(op->comment, OperationInfo);
										//restore the original filename
										sprintf_s(op->cmn.nci_name, ncioriginalname);
#endif
											//rewrite the operation
											operation_manager(op, OPMGR_REWRITE, &ptr, &bsuccf);
										//optional create a list of errors and send them to a report
										auto minzstrval = StringManipulation::GetAfter(minzval.ToString(), "-");

										if (minzstrval != nullptr)
										{
											auto minzdblval = StringManipulation::stringtodouble(minzstrval);
											if (minzdblval != nullptr)
											{

												if (tool->GetStickout() <= *minzdblval + .05)
												{
													listviewlist->Add("Error operation -> " + op->op_idn + " -> tool stickout is too short by ->" + (*minzdblval + .05 - tool->GetStickout()).ToString() + " -> please extend your tool stickout." + "   Max Depth = -" + minzdblval->ToString() + "   Min Depth = " + maxzval.ToString() + "   Tool Stickout = " + tool->GetStickout().ToString());

													op->db.select_flag = TRUE;
												}
												else
												{
													op->db.select_flag = FALSE;
												}
												if (tool->GetStickout() > *minzdblval + .5)
												{
													listviewlist->Add("Error operation -> " + op->op_idn + " -> tool stickout is too long by ->" + (tool->GetStickout() - (*minzdblval + .5)).ToString() + " -> please shorten your tool stickout." + "   Max Depth = -" + minzdblval->ToString() + "   Min Depth = " + maxzval.ToString() + "   Tool Stickout = " + tool->GetStickout().ToString());

													op->db.select_flag = TRUE;
												}
												else
												{
													op->db.select_flag = FALSE;
												}
											}
										}

									}
									System::IO::File::Delete(filearray[i]);
								}
							}

						}

					}
				}
			}
		}

		//optional create a list of errors and send them to a report
		auto array = listviewlist->ToArray();
		//check if we have something
		if (array->Length > 0)
		{
			System::Windows::Forms::Form ^ Form = gcnew System::Windows::Forms::Form;
			Form->BackColor = System::Drawing::Color::DarkGray;
			Form->Width = 1000;
			Form->Height = 650;
			Form->AutoScroll = true;
			Form->HorizontalScroll->Maximum = 0;
			Form->VerticalScroll->Visible = true;
			Form->VerticalScroll->Enabled = true;
			Form->HorizontalScroll->Enabled = false;
			Form->HorizontalScroll->Enabled = false;
			Form->HorizontalScroll->Visible = false;
			System::Windows::Forms::Application::EnableVisualStyles();
			//add the list view to the windows form
			int Left = 10; int Top = 75; int Width = 1000; int Height = Form->Height - 150;
			//add a listview control to the windows form
			auto listview = CreateListViewOnWinform(Left, Top, Width, Height, Form, 1);
			Form->Controls->Add(listview);
			for (auto i = 0; i < array->Length; i++)
			{
				auto listViewItem1 = gcnew System::Windows::Forms::ListViewItem(array[i]);
				//add the listview items to the listview
				listview->Items->Add(listViewItem1);
			}
			//Form->Show();
		}
	}
	};

}
public ref class MyEntryPoint : public NetHook3App
{
public: virtual Mastercam::App::Types::MCamReturn Run(int param) override {
	//start program//
	Method2();

	//end program//
	return Mastercam::App::Types::MCamReturn::NoErrors;
}
		void Method1()
		{
			// Must call this prior to accessing any Resources in the C-Hook DLL !

			CInterrogateMastercamFile fileInterrogator;

			fileInterrogator.Load();

			auto operationIDs = fileInterrogator.GetOpIDsInOpMgrOrder();

			if (operationIDs != nullptr)
			{
				p_3d min;
				p_3d max;

				Cnc::Tool::TlAssemblyCPtr toolAssembly;

				std_string newComment = _T("");

				DB_LIST_ENT_PTR outPointer = nullptr;

				bool result;

				for (auto opID : *operationIDs)
				{
					auto operation = TpMainOpMgr.GetMainOpList().OpByID(opID);

					fileInterrogator.LoadForSingleOperation(operation->op_idn, true);

					fileInterrogator.CalcBnciExtents(false, false, true, true);

					min = fileInterrogator.GetBnciLowerLeft();
					max = fileInterrogator.GetBnciUpperRight();

					newComment = _T("Z Min: ") + std_tostring(min[2]) + _T("\r\n");
					newComment += _T("Z Max: ") + std_tostring(max[2]) + _T("\r\n");

					Cnc::Tool::GetToolSystem()->Find(operation->tl.slot, toolAssembly);

					if (toolAssembly != nullptr)
					{
						newComment += _T("Tool Projection: ") + std_tostring(toolAssembly->GetToolProjection()) + _T("\r\n");
					}
#if C_H_VERSION >= 2100 // Mastercam 2019 or later

					_tcscpy_s(operation->comment, newComment.c_str());
#else
					//write the information to the operation comment
					sprintf_s(operation->comment, newComment.c_str());
#endif


					operation_manager(operation, OPMGR_REWRITE, &outPointer, &result);
				}

			}
		}
		void Method2()
		{
			AiTools::Functions functions;
			functions.AiOperationCommentInfo();
		}

};

 

Link to comment
Share on other sites
21 hours ago, Megabyte said:

When I used your method on operations on the bottom plane the value gets inverted

For example Method 1 outputs ZMin -.500 ZMax-.035

Method 2 outputs ZMin .035 ZMax .500 

is there a reliable way to use your method for bottom operations?

Hmm that is odd.  Rather than rely on the GetBnciLowerLeft()/GetBnciUpperRight() function, try reading the BNCI as shown below.  You'll want to cover more NCI lines (NCI_ARC_CW, NCI_5AX_LINEAR, NCI_ARC_CCW, etc.),  but it should get you started.

			double minZ = 99999.999;
			double maxZ = -99999.999;

			CBnciReadWrite bnciReader;

			bnciReader.ReadSection(currentOperation->op_idn, false);

			auto binaryNCILines = bnciReader.GetData();

			for (auto nciLine : binaryNCILines)
			{
				switch (nciLine->gcode)
				{
				case NCI_RAPID:
					if (minZ > nciLine->u.m0.ep1[Z])
					{
						minZ = nciLine->u.m0.ep1[Z];
					}
					if (maxZ < nciLine->u.m0.ep1[Z])
					{
						maxZ = nciLine->u.m0.ep1[Z];
					}
					break;
				case NCI_LINEAR:
					if (minZ > nciLine->u.m1.ep1[Z])
					{
						minZ = nciLine->u.m1.ep1[Z];
					}
					if (maxZ < nciLine->u.m1.ep1[Z])
					{
						maxZ = nciLine->u.m1.ep1[Z];
					}
					break;
				default:
					break;
				}
			}

 

Link to comment
Share on other sites
58 minutes ago, Zaffin_D said:

Hmm that is odd.  Rather than rely on the GetBnciLowerLeft()/GetBnciUpperRight() function, try reading the BNCI as shown below.  You'll want to cover more NCI lines (NCI_ARC_CW, NCI_5AX_LINEAR, NCI_ARC_CCW, etc.),  but it should get you started.


			double minZ = 99999.999;
			double maxZ = -99999.999;

			CBnciReadWrite bnciReader;

			bnciReader.ReadSection(currentOperation->op_idn, false);

			auto binaryNCILines = bnciReader.GetData();

			for (auto nciLine : binaryNCILines)
			{
				switch (nciLine->gcode)
				{
				case NCI_RAPID:
					if (minZ > nciLine->u.m0.ep1[Z])
					{
						minZ = nciLine->u.m0.ep1[Z];
					}
					if (maxZ < nciLine->u.m0.ep1[Z])
					{
						maxZ = nciLine->u.m0.ep1[Z];
					}
					break;
				case NCI_LINEAR:
					if (minZ > nciLine->u.m1.ep1[Z])
					{
						minZ = nciLine->u.m1.ep1[Z];
					}
					if (maxZ < nciLine->u.m1.ep1[Z])
					{
						maxZ = nciLine->u.m1.ep1[Z];
					}
					break;
				default:
					break;
				}
			}

 

Okay, I see, that is very helpful, I will post what I come up with here when it is done. Hopefully something shorter than my first iteration..

Thanks Zaffin.

Link to comment
Share on other sites
  • 4 weeks later...

@Zaffin_D

I used colored points to display the results in a fun way..

I had to add some extra numbers to capture the first drill position and retract point, here is the code GitHub or source :

void StorePoint( p_3d &pt, short view, MC_BYTE color,int levelnumber)
{

	DB_LIST_ENT_PTR ptr = nullptr;
	ent point;
	point.id = P_ID;
	if (view != 1)
	{
		p_3d NewPointInOperationView;
		view_to_view(pt, 1, view, NewPointInOperationView);
		point.u.pt = NewPointInOperationView;
	}
	else
	{
		point.u.pt = pt;
	}
	bool succf;
	store_ent(&point, &ptr, 0, color, levelnumber, main_attrib, &succf);
}

#pragma region Exported Entry Points (Optional)

/// <summary> This is an optional additional exported entry point function. </summary>
///
/// <remarks> It is usually used via a "FUNCTION CPP" command in a Function Table (FT) file.
///
/// <param name="param"> An optional value passed in using a PARAM value in the "FUNCTION CPP" command block. </param>
///
/// <returns> The MC_RETURN state flag(s) back to Mastercam. </returns>
extern "C" __declspec(dllexport) int BnciReaderEntry (int param)
	{
	// Must call this prior to accessing any Resources in the C-Hook DLL !
	ChangeResCl res (GetChookResourceHandle ());


	auto mToolMinZ = 99999.999;

	auto mToolMaxZ = -99999.999;

	auto mToolRapidMinZ = 99999.999;

	auto mToolRapidMaxZ = -99999.999;

	CInterrogateMastercamFile fileInterrogator;

	fileInterrogator.Load();

	auto operationIDs = fileInterrogator.GetOpIDsInOpMgrOrder();

	auto errcount = 0;
	if (operationIDs != nullptr)
	{
		for (auto op : *operationIDs)
		{
			auto currentOperation = TpMainOpMgr.GetMainOpList().OpByID(op);

			CBnciReadWrite bnciReader;

			bnciReader.ReadSection(currentOperation->op_idn, false);

			auto binaryNCILines = bnciReader.GetData();

			auto view = currentOperation->tpln.v_idn;
			for (auto nciLine : binaryNCILines)
			{
				if (nciLine->type == NCI_MILL_TYPE)
				{
					if (nciLine->gcode == 1000)
					{
						StorePoint(nciLine->u.m0.ep1, view, MC_YELLOW, 5005);
						if (mToolRapidMinZ > nciLine->u.m0.ep1[Z])
						{
							mToolRapidMinZ = nciLine->u.m0.ep1[Z];
						}
						if (mToolRapidMaxZ < nciLine->u.m0.ep1[Z])
						{
							mToolRapidMaxZ = nciLine->u.m0.ep1[Z];
						}
					}
					if (nciLine->gcode == 1001)
					{
						if (mToolRapidMinZ > nciLine->u.m0.ep1[Z])
						{
							mToolRapidMinZ = nciLine->u.m0.ep1[Z];
						}
						if (mToolRapidMaxZ < nciLine->u.m0.ep1[Z])
						{
							mToolRapidMaxZ = nciLine->u.m0.ep1[Z];
						}
						StorePoint(nciLine->u.m0.ep1, view,  MC_YELLOW, 5005);
					}
					if (nciLine->gcode == NCI_RAPID)
					{
						if (mToolRapidMinZ > nciLine->u.m0.ep1[Z])
						{
							mToolRapidMinZ = nciLine->u.m0.ep1[Z];
						}
						if (mToolRapidMaxZ < nciLine->u.m0.ep1[Z])
						{
							mToolRapidMaxZ = nciLine->u.m0.ep1[Z];
						}
						StorePoint(nciLine->u.m0.ep1, view, MC_YELLOW, 5005);
					}
					if (nciLine->gcode == NCI_LINEAR)
					{
						if (mToolMinZ > nciLine->u.m1.ep1[Z])
						{
							mToolMinZ = nciLine->u.m1.ep1[Z];
						}
						if (mToolMaxZ < nciLine->u.m1.ep1[Z])
						{
							mToolMaxZ = nciLine->u.m1.ep1[Z];
						}
						StorePoint(nciLine->u.m1.ep1, view,MC_GREEN, 6005);
					}
					if (nciLine->gcode == NCI_ARC_CW)
					{
						StorePoint(nciLine->u.m1.ep1, view, MC_LT_BLUE, 6005);
						if (mToolMinZ > nciLine->u.m1.ep1[Z])
						{
							mToolMinZ = nciLine->u.m1.ep1[Z];
						}
						if (mToolMaxZ < nciLine->u.m1.ep1[Z])
						{
							mToolMaxZ = nciLine->u.m1.ep1[Z];
						}
					}
					if (nciLine->gcode == NCI_ARC_CCW)
					{
						StorePoint(nciLine->u.m1.ep1, view,MC_BLUE, 6005);
						if (mToolMinZ > nciLine->u.m1.ep1[Z])
						{
							mToolMinZ = nciLine->u.m1.ep1[Z];
						}
						if (mToolMaxZ < nciLine->u.m1.ep1[Z])
						{
							mToolMaxZ = nciLine->u.m1.ep1[Z];
						}
					}
					if (nciLine->gcode == NCI_DRILL_HOLE)
					{
						if (mToolRapidMinZ > nciLine->u.m100.ep2[Z])
						{
							mToolRapidMinZ = nciLine->u.m100.ep2[Z];
						}
						if (mToolRapidMaxZ < nciLine->u.m100.ep2[Z])
						{
							mToolRapidMaxZ = nciLine->u.m100.ep2[Z];
						}
						StorePoint(nciLine->u.m100.ep2, view, MC_YELLOW, 5005);
						p_3d pt = {};
						pt.SetXY(nciLine->u.m100.x, nciLine->u.m100.y);
						pt[2] = nciLine->u.m100.depth;
						StorePoint( pt, view, MC_RED, 6005);
						if (mToolMinZ > nciLine->u.m100.depth)
						{
							mToolMinZ = nciLine->u.m100.depth;
						}
						if (mToolMaxZ < nciLine->u.m100.depth)
						{
							mToolMaxZ = nciLine->u.m100.depth;
						}
					}

					if (nciLine->gcode == NCI_DRILL_START)
					{
						p_3d pt = {};
						pt.SetXY(nciLine->u.m100.x, nciLine->u.m100.y);
						pt[2] = nciLine->u.m100.depth;
						StorePoint( pt, view, MC_RED, 6005);
						if (mToolMinZ > nciLine->u.m100.depth)
						{
							mToolMinZ = nciLine->u.m100.depth;
						}
						if (mToolMaxZ < nciLine->u.m100.depth)
						{
							mToolMaxZ = nciLine->u.m100.depth;
						}
					}
				}
			}
			Cnc::Tool::TlAssemblyCPtr tool;

		
				
		}
	}
	return MC_NOERROR | MC_UNLOADAPP;
	}

 

Link to comment
Share on other sites

You don't need to check for 1000 or 1001 in the BNCI.  1000 and 1001 are text NCI lines, the don't exist in the binary; the binary NCI only contains 1002(NCI_TOOLCHG) lines.

It also seems like you're storing a point for each move and not just the extents?  

  

Link to comment
Share on other sites
25 minutes ago, Zaffin_D said:

You don't need to check for 1000 or 1001 in the BNCI.  1000 and 1001 are text NCI lines, the don't exist in the binary; the binary NCI onlcontains 1002(NCI_TOOLCHG) lines.

Yes, you are right, thanks.

25 minutes ago, Zaffin_D said:

It also seems like you're storing a point for each move and not just the extents?  

Yeah, it was an easy way to check if it is working okay, I find it is actually a useful way to look at a large quantity of toolpaths, I think I will use it in a standalone add-in.

The performance is a lot better with your method. Nice work!! 

Did you learn all that from just reading the docs?

 

Link to comment
Share on other sites
20 hours ago, megabyte said:

Did you learn all that from just reading the docs?

Are there c-hook docs?  I know about the .chm file, but I never spent any time with it; it was very hard for me to find anything in there.

I search the headers in Visual Studio.  If my search comes up empty I ask a coworker.  If my coworkers don’t know I ask the SDK team.

It comes down to time and experience;  I stated with C++ and c-hooks about 8 months ago, and at first I couldn’t find my butt with both hands.

 

 

 

  • Like 1
Link to comment
Share on other sites
Just now, Zaffin_D said:

Are there c-hook docs?  I know about the .chm file, but I never spent any time with it; it was very hard for me to find anything in there.

I search the headers in Visual Studio.  If my search comes up empty I ask a coworker.  If my coworkers don’t know I ask the SDK team.

It comes down to time and experience;  I stated with C++ and c-hooks about 8 months ago, and at first I couldn’t find my butt with both hands.

 

 

 

The chm file has a few extra notes that don't appear in the header files.

I have only been programming about a year or so, I learned programming with mastercam vbscript and went from there.

Didn't know what a chook was before that..

I saw they started to make c++ example projects now so I think that will be interesting!

Link to comment
Share on other sites

@Zaffin_D I would say the area I struggle the most with is like matrix/vector stuff, I am trying to get my libraries down.

I started learing some "modern" opengl it's pretty fun, I made like a simple object loader in one tutorial, I was reading how you could build a .stp file parser as well.The hard part was just getting all the libraries and header files built and working lol.

Hopefully that is going to improve my programming knowledge. 

Link to comment
Share on other sites

I am also hoping to get a good menu system on the open gl platform, most people seem to say use qt.Then I will have a nice cross platform application, I think wpf also has that though anyway and there is c# graphic too, but I try to learn the low level api stuff first so when I do my high level program I will have a better trouble shooting skill, but it takes long to figure stuff out with .net.

Lots of people do graphics with python too, but I don't want that.

Link to comment
Share on other sites
  • 2 weeks later...

Checking Against the Stock Setup ->

#include "stdafx.h"
using Mastercam::App::NetHook3App;
void SetMinMaxValueToList(System::Collections::Generic::List<double> ^ zdepthvaluelist, double &MinZValue, double &MaxZValue)
{
	auto zdepthvaluearray = zdepthvaluelist->ToArray();
	if (zdepthvaluearray->Length > 0)
	{
		MinZValue = zdepthvaluearray[0];
		MaxZValue = zdepthvaluearray[0];
	}
	for (auto m = 0; m < zdepthvaluearray->Length; m++)
	{
		if (zdepthvaluearray[m] <= MinZValue)
		{
			MinZValue = zdepthvaluearray[m];

		}
		if (zdepthvaluearray[m] >= MaxZValue)
		{
			MaxZValue = zdepthvaluearray[m];
		}
	}
}
void StorePoint(p_3d &pt, short view, MC_BYTE color, int levelnumber)
{

	DB_LIST_ENT_PTR ptr = nullptr;
	ent point;
	point.id = P_ID;
	if (view != 1)
	{
		p_3d NewPointInOperationView;
		view_to_view(pt, 1, view, NewPointInOperationView);
		point.u.pt = NewPointInOperationView;
	}
	else
	{
		point.u.pt = pt;
	}
	bool succf;
	store_ent(&point, &ptr, 0, color, levelnumber, main_attrib, &succf);
}

namespace McConvertToType
{
	int DatabasePointerToInt(ent &surf)
	{
		return static_cast<int>(PtrToInt(surf.eptr));
	}
	const DB_LIST_ENT_PTR &IntToDatabasePointer(int DatabasePointer)
	{
		return static_cast<DB_LIST_ENT_PTR>(IntToPtr(DatabasePointer));
	}
	void ConvertPointToP_3d(p_3d &pt, Mastercam::Math::Point3D &Point)
	{
		pt[0] = Point.x; pt[1] = Point.y; pt[2] = Point.z;
	}
	Mastercam::Math::Point3D ConvertP_3dToPoint(p_3d &pt0)
	{
		Mastercam::Math::Point3D Point;
		Point.x = pt0[0]; Point.y = pt0[1]; Point.z = pt0[2];
		return Point;
	}
}

public ref class MyEntryPoint : public NetHook3App
{
public: virtual Mastercam::App::Types::MCamReturn Run(int param) override {
	//start program//
	CInterrogateMastercamFile fileInterrogator;

	fileInterrogator.Load();
	auto opnumber = 1;
	auto operationIDs = fileInterrogator.GetOpIDsInOpMgrOrder();
	auto errcount = 0;
	if (operationIDs != nullptr)
	{
		for (auto op : *operationIDs)
		{
			
			auto  zdepthvaluelist = gcnew System::Collections::Generic::List<System::Double>;

			auto currentOperation = TpMainOpMgr.GetMainOpList().OpByID(op);
			//Avoid nesting
			if (currentOperation->opcode != TP_NEST)
			{
				CBnciReadWrite bnciReader;

				bnciReader.ReadSection(currentOperation->op_idn, false);

				auto binaryNCILines = bnciReader.GetData();

				auto view = currentOperation->tpln.v_idn;
				auto PointOrigin = Mastercam::Operations::OperationsManager::JobSetupStockOrigin;
				auto PointSize = Mastercam::Operations::OperationsManager::JobSetupStockSize;
				p_3d ptstockmaxfrom;
				McConvertToType::ConvertPointToP_3d(ptstockmaxfrom, PointSize);
				p_3d ptstockmax; view_to_view(ptstockmaxfrom, 1, 4, ptstockmax);//edited 
				for (auto nciLine : binaryNCILines)
				{
					if (nciLine->type == NCI_MILL_TYPE)
					{
						if (nciLine->gcode == NCI_RAPID)
						{
							zdepthvaluelist->Add(nciLine->u.m0.ep1[Z]);
							//StorePoint(nciLine->u.m0.ep1, view, MC_YELLOW, 5005);
						}
						if (nciLine->gcode == NCI_LINEAR)
						{
							zdepthvaluelist->Add(nciLine->u.m1.ep1[Z]);
						}
						if (nciLine->gcode == NCI_ARC_CW)
						{
							zdepthvaluelist->Add(nciLine->u.m1.ep1[Z]);
						}
						if (nciLine->gcode == NCI_ARC_CCW)
						{
							zdepthvaluelist->Add(nciLine->u.m1.ep1[Z]);
						}
						if (nciLine->gcode == NCI_DRILL_HOLE)
						{
							zdepthvaluelist->Add(nciLine->u.m100.depth);
							zdepthvaluelist->Add(nciLine->u.m100.ep2[Z]);
						}

						if (nciLine->gcode == NCI_DRILL_START)
						{
							zdepthvaluelist->Add(nciLine->u.m100.depth);
						}
					}
				}
				auto maxzval = 0.0;

				auto minzval = 0.0;
				//find the min max z value
				SetMinMaxValueToList(zdepthvaluelist, minzval, maxzval);
				
				if (view == 4)
				{
					if (ptstockmaxfrom[2] + .05 >= maxzval)
					{
						System::Windows::Forms::MessageBox::Show("Error Retract is too low in operation #" + opnumber + " StockThickness = " + ptstockmaxfrom[2] + " Rapidheight = " + maxzval);
					}
					if (-.1 >= minzval)
					{
						System::Windows::Forms::MessageBox::Show("Warning depth in operation #" + opnumber + " is greater then -.100 into the spoilboard : Stock = " + ptstockmaxfrom[2] + " Depth = " + minzval);
					}
				}
				if (view == 1)
				{
					if (.05 >= maxzval)
					{
						System::Windows::Forms::MessageBox::Show("Error Retract is too low in operation #" + opnumber + " StockThickness = " + ptstockmaxfrom[2] + " Rapidheight = " + maxzval);
					}
					if (ptstockmax[2] - .1 >= minzval)
					{
						System::Windows::Forms::MessageBox::Show("Warning depth in operation #" + opnumber + " is greater then -.100 into the spoilboard : Stock = " + ptstockmaxfrom[2] + " Depth = " + minzval);
					}
				}
				opnumber++;
				Cnc::Tool::TlAssemblyCPtr toolAssembly;
				Cnc::Tool::GetToolSystem()->Find(currentOperation->tl.slot, toolAssembly);
				CString OperationInfo;
				//copy some other information
				OperationInfo.Format(_T("ZMin :Z%lf ZMax :Z%lf TlLength :%lf Tldia :%lf Tlnum :%d RPM :%d Feed :%lf"), minzval, maxzval, toolAssembly->GetStickout(), currentOperation->tl.dia, currentOperation->tl.tlno, currentOperation->tl.rpm, currentOperation->tl.feed);
#if C_H_VERSION >= 2100 // Mastercam 2019 or later

				//write the information to the operation comment
				_tcscpy_s(currentOperation->comment, OperationInfo);
#else
				//write the information to the operation comment
				sprintf_s(op->comment, OperationInfo);
#endif
				//rewrite the operation
				auto bsuccf = static_cast<bool>(false);
				auto ptr = static_cast<DB_LIST_ENT_PTR>(nullptr);
				operation_manager(currentOperation, OPMGR_REWRITE, &ptr, &bsuccf);
				//optional create a list of errors and send them to a report

			}
		}
	}
	//end program//
	return Mastercam::App::Types::MCamReturn::NoErrors;
}

};

 

Link to comment
Share on other sites
  • 2 weeks later...

Here is the output in my post :

%
;PROGRAM NAME     : Fizzy.NC
;MC File Name.Ext : Fizzy.MCAM
;Date             : JUN-12-2020 TIME - 1:17 PM
;Machine Type     : DMS 3 AXIS D3 GANTRY
;POST             : IN-HOUSE SOLUTIONS DMS FAGOR 8065
;Licensed to      : Fizzy
;TOOL - 168 |DRILL 1/4 (.250)         | DIA. - .25|DRILL/MISC.|BOTTOM
;TOOL - 103 |1/4 (.250) EM            | DIA. - .25|POCKET.....|BOTTOM
;TOOL - 104 |1/2 (.500) EM            | DIA. - .5|CONTOUR....|BOTTOM
;TOOL - 184 |T84 0.563 INSERT CLEANER | DIA. - .559|POCKET.....|BOTTOM
;TOOL - 185 |0.5625 INSERT 0380 FLUTE | DIA. - .5625|CONTOUR....|BOTTOM
#MCS OFF
#CS OFF
#HSC OFF
;MATL' THK
V.A.ORGT[1].Z=.5
G73
G00 G17 G70 G80 G90 G94
G40
M61
M63

;ZMIN :Z-0.080000 ZMAX :Z0.750000 TLLENGTH :3.100000 TLDIA :0.250000 TLNUM :168 RPM :5000 FEED :100.000000
T168 M06 ;DRILL 1/4 (.250) 
G501 A75 E.001
S5000 M03
G04 K3
G54
D1
G00 G17 G90 X.306 Y.306
M08
Z.25
G99 G81 Z.25 I-.58 F100.
Y47.694
X83.5
Y.306
G80
M05
G00
#MCS Z0.

 

Link to comment
Share on other sites
  • 2 years later...
On 5/25/2023 at 7:47 AM, Tariq Aslam said:

is there some way to automatically call this NC file based on the toolpath generated in mastercam, in the form of some method or function in NET HOOKS API? when the toolpath is generated ,the toolpath data needs to be converted into an NC file or GCode file

 

Thanks 

 

Yes,

when you post the g-code is generated, you can then read it back into mastercam,

this is fairly trivial to do

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.

Join us!

eMastercam - your online source for all things Mastercam.

Together, we are the strongest Mastercam community on the web with over 56,000 members, and our online store offers a wide selection of training materials for all applications and skill levels.

Follow us

×
×
  • Create New...