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:

Zaffin_D

Verified Members
  • Posts

    374
  • Joined

  • Days Won

    1

Everything posted by Zaffin_D

  1. I think you are misunderstanding that thread. The example below works for me. OperationService.h #pragma once namespace OperationServiceNative { public ref struct OperationData { System::String^ Comment; int ID; int Type; int ToolNumber; }; public ref class OperationService { public: OperationService(); OperationData^ GetOperationData(int opID); ~OperationService(); }; } OperationService.cpp #include "pch.h" #include "OperationService.h" OperationServiceNative::OperationService::OperationService() { } OperationServiceNative::OperationData^ OperationServiceNative::OperationService::GetOperationData(int opID) { OperationData^ opData = nullptr; auto operation = TpMainOpMgr.GetMainOpList().OpByID(opID); if (operation != nullptr) { opData = gcnew OperationData(); System::String^ commentString = gcnew System::String(operation->comment); opData->Comment = commentString; opData->ID = operation->op_idn; opData->Type = operation->opcode; opData->ToolNumber = operation->tl.tlno; } return opData; } OperationServiceNative::OperationService::~OperationService() { } Main.cs namespace MyNetHook { using Mastercam.App; using Mastercam.App.Types; using OperationServiceNative; public class Main : NetHook3App { public override MCamReturn Run(int param) { var opService = new OperationServiceNative.OperationService(); var opData = opService.GetOperationData(1); return MCamReturn.NoErrors; } } }
  2. 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.
  3. 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?
  4. Are you looking at whatsnew.mastercam.com? If so, you’re looking at features that will be in the upcoming release, Mastercam2021.
  5. XML requires certain characters to be escaped, try putting an ampersand(&) in a text tag and watch the post text default to system text. If you add an ampersand thru the CD it will be escaped correctly. The post and post text also must be encoded in UTF-8, in the unlikely case the editor used to edit the post doesn't support UTF-8 (some people still use PFE) and you venture outside the ASCII range the post text will also blow up. Editing through the CD eliminates both problems. @Sushant Singh, ask your reseller for a copy of the Working with machine and control definitions MP application guide, it goes over everything in great detail.
  6. It’s cool to see this stuff used in the wild; Good work!
  7. MP has two data types, string and numeric. Strings always start with 's' and are initialized with quote characters (single or double). The data coming from the 20002 is a string, so try this.... s_group_com : "" pparameter$ if prmcode$ = 20002, s_group_com = sparameter$ If you'd like the "TC=" prefix you can build a string with a global formula as shown below s_group_com_out = "TC=" + s_group_com ptlchg$ s_group_com_out, e$
  8. I think it's worth noting that the K value in a ZXZ Euler can be anything provided the points are mapped to that XY orientation. I only bring this up because I think ZXZ is the default rotation order on a Fanuc. Also roll pitch yaw (Tait–Bryan angles) are very similar to Euler angles; the difference is that Euler's repeat an axis (ZXZ, XYX, ZYZ, you get the idea...), and roll pitch yaw angles don't(XYZ, YZX, YXZ, etc.)
  9. 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; } }
  10. Parameter 19 contains the minimum Z value for an operation. I think you could use this information to check if you're at the lowest Z; below is some pseudo code. op_min_z : 99999 fmt "Z" 2 z$ #Z position output fmt "" 2 op_min_z #Min Z position, formated for comparision ptlchg$ op_min_z = 99999 # Get the opertions min Z position op_min_z = opinfo(19, 0) plin$ # Test to see if we are at the min Z position if fmtrnd(op_min_z) = fmtrnd(z$), [ # The min Z has been reached, update the prefix/suffix result = nwadrs("Z[#502+", z$) result = nwsufx("]", z$) ] else, [ # We are not at the min Z, restore the orignal prefix/suffix result = nwadrs("Z", z$) result = nwsufx("", z$) ]
  11. Rather than use MP's comment mechanism, query parameter 15239. s_op_comment : "" p_any_postblock # Get the op comment of the current operation s_op_comment = opinfo(15239, 0, 0000) # If we are in a transform operation, we can query the soure operation... s_op_comment = opinfo(15239, 0, 0000) # ...or we can query the transform parameters. s_op_comment = opinfo(15239, 0, 0010)
  12. Using the previously attached part file that function returns the arc direction of the upper profile as CCW when chained clockwise with the C-plane set to TOP; so I think somethings up. I'm using 2020, but I don't think that would make a difference. The below function matches the analyze contour results in my tests. void GetChainDirection() { LPCTSTR prompt(_T("Select a Chain")); CHAIN* selectedChain = nullptr; auto result = chain_1(prompt, &selectedChain); if (result == CHAIN_OK && &selectedChain != nullptr) { auto selectedChainPointer = selectedChain->start; while (selectedChainPointer != nullptr) { auto entityPointer = selectedChainPointer->e_ptr->eptr; if (entityPointer->id == A_ID) { p_3d arcStartVector; p_3d arcEndVector; p_3d crossProduct; p_3d arcStart; p_3d arcCenter; p_3d arcEnd; double arcSweep; view_to_world(entityPointer->u.ar.c, entityPointer->u.ar.view, arcCenter); view_to_view(entityPointer->u.ar.ep1, 1, CONSTR_VIEW_N, arcStart); view_to_view(arcCenter, 1, CONSTR_VIEW_N, arcCenter); view_to_view(entityPointer->u.ar.ep2, 1, CONSTR_VIEW_N, arcEnd); if (selectedChainPointer->ep_n) { arcStartVector = arcEnd - arcCenter; arcEndVector = arcStart - arcCenter; } else { arcStartVector = arcStart - arcCenter; arcEndVector = arcEnd - arcCenter; } crossProduct = Cross(arcStartVector, arcEndVector).NormalizeThis(); arcSweep = std::abs(entityPointer->u.ar.sw) * (180.0 / PI); arcSweep = (int)(arcSweep * 1000.0) / 1000.0; if (crossProduct[Z] < 0.0) { if (arcSweep <= 180.0) { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CW ARC FOUND!"), _T("ArcDirection"), MB_OK); } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CCW ARC FOUND!"), _T("ArcDirection"), MB_OK); } } else if (crossProduct[Z] > 0.0) { if (arcSweep >= 180.0) { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CW ARC FOUND!"), _T("ArcDirection"), MB_OK); } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CCW ARC FOUND!"), _T("ArcDirection"), MB_OK); } } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("crossProduct = 0; arc direction could not be obtained."), _T("ArcDirection"), MB_OK); } } selectedChainPointer = selectedChainPointer->next; } free_chain(&selectedChain); } }
  13. Funny arcs... The center point isn't mapped to the same view as the endpoints, try mapping the center to world with view_to_world as shown below. if (entityPointer->id == A_ID) { p_3d worldCenter; view_to_world(entityPointer->u.ar.c, entityPointer->u.ar.view, worldCenter); if (selectedChainPointer->ep_n) { arcStartVector = entityPointer->u.ar.ep2 - worldCenter; arcEndVector = entityPointer->u.ar.ep1 - worldCenter; } else { arcStartVector = entityPointer->u.ar.ep1 - worldCenter; arcEndVector = entityPointer->u.ar.ep2 - worldCenter; } Also I think we should take the absolute sweep... arcSweep = fabs(entityPointer->u.ar.sw) * (180.0 / PI); ...but i'm not a math guru.
  14. I sometimes struggle to understand your code, but I appreciate that you're willing to share what you're working on!
  15. 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.
  16. I'm unfamiliar with how you are determining the arc's direction. Below is something that works in my testing as long as the sweep's not 180 degrees (it will fail if the sweep is 180). I'm not sure how helpful it will be. extern "C" __declspec(dllexport) int ArcDirectionEntry (int param) { // Must call this prior to accessing any Resources in the C-Hook DLL ! ChangeResCl res (GetChookResourceHandle ()); LPCTSTR prompt(_T("Select a Chain")); CHAIN* selectedChain = nullptr; auto result = chain_1(prompt, &selectedChain); if (result == CHAIN_OK && &selectedChain != nullptr) { auto selectedChainPointer = selectedChain->start; p_3d arcStartVector; p_3d arcEndVector; p_3d crossProduct; double arcSweep; while (selectedChainPointer != nullptr) { auto entityPointer = selectedChainPointer->e_ptr->eptr; if (entityPointer->id == A_ID) { if (selectedChainPointer->ep_n) { arcStartVector = entityPointer->u.ar.ep2 - entityPointer->u.ar.c; arcEndVector = entityPointer->u.ar.ep1 - entityPointer->u.ar.c; } else { arcStartVector = entityPointer->u.ar.ep1 - entityPointer->u.ar.c; arcEndVector = entityPointer->u.ar.ep2 - entityPointer->u.ar.c; } crossProduct = Cross(arcStartVector, arcEndVector).NormalizeThis(); arcSweep = entityPointer->u.ar.sw * (180.0 / PI); arcSweep = (int)(arcSweep * 1000.0) / 1000.0; if (crossProduct[2] < 0.0) { if (arcSweep <= 180.0) { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CW ARC FOUND!"), _T("ArcDirection"), MB_OK); } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CCW ARC FOUND!"), _T("ArcDirection"), MB_OK); } } else if (crossProduct[2] > 0.0) { if (arcSweep >= 180.0) { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CW ARC FOUND!"), _T("ArcDirection"), MB_OK); } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("CCW ARC FOUND!"), _T("ArcDirection"), MB_OK); } } else { ::MessageBox(get_MainFrame()->GetSafeHwnd(), _T("crossProduct = 0; arc direction could not be obtained."), _T("ArcDirection"), MB_OK); } } selectedChainPointer = selectedChainPointer->next; } free_chain(&selectedChain); } return MC_NOERROR | MC_UNLOADAPP; }
  17. double StringManipulation::StringToDouble(StringType input) { CString c_str = input.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); return atof(strStd.c_str()); /*c_str is needed to convert string to const char*/ } int StringManipulation::StringToInt(StringType input) { CString c_str = input.c_str(); // Convert a TCHAR string to a LPCSTR CT2CA pszConvertedAnsiString(c_str); // construct a std::string using the LPCSTR input std::string strStd(pszConvertedAnsiString); return atoi(strStd.c_str()); /*c_str is needed to convert string to const char*/ } These functions smell funny; atoi and atof both return 0 on failure and that's not great. Consider using std::stoi or std::stod. They accept a std::string or std::wstring so there is no need to do whatever your doing to convert the input. They also throw an exception on failure rather than an ambiguous value.
  18. Not much more to it. PLANE VECTOR requires two vectors defined by the values BX, BY, BZ (the base vector) and NX, NY, NZ (the normal vector). The normal vector is the Z vector of the tool plane. I can't remember, but I think the base vector is the X vector of the tool plane, but it could be the Y vector; it's been awhile.
  19. Can I ask why you are programming for COR? It seems that your issue would solve itself if you used the PLANE functions. WESC is not something the 530 offers out of the box. As you may or may not be aware you can not add a secondary axis (a or b) value in the preset table and have M128 or the PLANE function work. I thought Hermle had a cycle 300-something to work around this but I was a Mikron guy. Cycle 7 or TRANS DATUM if the machine is newer.
  20. What manuals are you looking at? I've always found Heidenhain manuals to be excellent. Anyway, you can define a plane in several ways. The old way was cycle 19, but you should be using the PLANE function if it's available. The PLANE function has several options for how to define a plane... Spatial angles Projection angles Euler angles ZXZ Two vectors Three points The plane function also allows you to specify other options... SEQ + or -; this chooses the rotation solution MOVE, TURN, STAY. MOVE will move the rotary axes and the tool when the command is executed. TURN will move only the rotary axes. STAY will do the math but will not cause motion. A retract can also be specified TABLE ROT or COORD ROT; move the rotaries or move the coordinate system The above lists are not exhaustive. When I was an AE for Mikron spatial angles were the most popular. If you have a BC machine, SPA would be 0, SPB would be the B-axis angle, and SPC would be the C-axis angle. On the machine this works great, but in the post this involves some mapping/rotating because the two angles don't fully define a plane. The code would look something like this... PLANE SPATIAL SPA+0 SPB-45 SPC+0 SEQ- TURN MBMAX FMAX TABLE ROT So that says I want to define the plane by spatial angles(PLANE SPATIAL); set the B-axis at 45 degrees(SPA+0 SPB-45 SPC+0); choose the negative solution(SEQ-); move only the rotaries(TURN); before you move, retract along the tool axis to the limit switch(MBMAX); do everything at max feed rate(FMAX); rotate the table(TABLE ROT). The above is from memory, it's best to build a few cycles at the control; it walks you through every step. Heidenhain also offers a free simulator. I personally like the two vectors method because Mastercam gives you the toolplane matrix. Hope that helps.
  21. Assuming you mean the MP post docs, this is likely specific to your reseller. The post docs for 2020 are available, but their format has changed. Gone is the bulky .PDF; for 2020 and beyond the post docs are in (a much improved) .HTML format.
  22. This appears to do a bit more than rename e$. It appers to allow the user to add a end of line string to every output line in one place. For example if you wanted to add '*' to the end of every string you could do the following. pe '*', e$ Even if the post isn't encrypted this seems to have value, no? I'm not a post expert so I'll differ to you; objectively whats wrong with the above? How would you handle this? What standards would you like to see set in regards to MP posts? Software development is an art as much as it is a science; a standard in something so abstract seems like telling a painter they can only paint black circles on a white background. How can innovation happen if everyone is required to do the same thing?
  23. The number of entities in an operation is stored in parameter 15083. Are you talking about the angle between holes in 3D space or the XY plane? For 3D space you'll need to determine the vector of a hole, then use the below formula to determine the angle. If you want the angle between holes in the XY plane atan2 should work.
  24. I think this is a great idea. However I couldn't get it to work in 2020. Are you interested in any constructive feedback regarding the execution?
  25. I think I see what's going on here; by non-reserved plane you mean a view that doesn't appear in the view manager? For example the view of a rotated arc? You should be able to get the arc's view matrix by using the get_view_matrix function.

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