Hi Toshi,
Thank you for referring to the A3DSurfEvaluateNormal API. I attempted to implement it, but unfortunately, it’s not working as expected.
I have included a sample of my code in the FeatureRecognitionDlg. I believe I might be getting confused about how to correctly pass arguments to the A3DSurfEvaluateNormal function (I am trying to get the normal vector of the selected, and all detected faces):
// Normal Vector Function
void FeatureRecognitionDlg::NormalVectors(A3DTopoFace* pSelTopoFace, std::vector<A3DEntity*>& pEntityArr)
{
A3DStatus status;
A3DTopoFaceData faceData;
A3D_INITIALIZE_DATA(A3DTopoFaceData, faceData);
// Retrieve face data for selected face
status = A3DTopoFaceGet(pSelTopoFace, &faceData);
if (status != A3D_SUCCESS)
{
CString errorMessage;
errorMessage.Format(L"Failed to get face data for selected face: Error code %d", status);
AfxMessageBox(errorMessage);
return;
}
// Retrieve UV parameters from face data
A3DVector2dData uvParameter;
uvParameter.m_dX = (faceData.m_sSurfaceDomain.m_sMin.m_dX + faceData.m_sSurfaceDomain.m_sMax.m_dX) / 2.0;
uvParameter.m_dY = (faceData.m_sSurfaceDomain.m_sMin.m_dY + faceData.m_sSurfaceDomain.m_sMax.m_dY) / 2.0;
A3DVector3dData normal;
A3D_INITIALIZE_DATA(A3DVector3dData, normal);
// Evaluate normal for the selected face
status = A3DSurfEvaluateNormal((const A3DSurfBase*)pSelTopoFace, &uvParameter, &normal);
if (status == A3D_SUCCESS)
{
CString message;
message.Format(L"Selected Face Normal: X: %f, Y: %f, Z: %f", normal.m_dX, normal.m_dY, normal.m_dZ);
AfxMessageBox(message);
}
else
{
CString errorMessage;
errorMessage.Format(L"Failed to evaluate normal for selected face: Error code %d", status);
AfxMessageBox(errorMessage);
}
// Evaluate normal for each detected face
for (size_t i = 0; i < pEntityArr.size(); ++i)
{
A3DTopoFace* pTopoFace = (A3DTopoFace*)pEntityArr[i];
// Retrieve face data for detected face
A3DTopoFaceData detectedFaceData;
A3D_INITIALIZE_DATA(A3DTopoFaceData, detectedFaceData);
status = A3DTopoFaceGet(pTopoFace, &detectedFaceData);
if (status != A3D_SUCCESS)
{
CString errorMessage;
errorMessage.Format(L"Failed to get face data for detected face %zu: Error code %d", i, status);
AfxMessageBox(errorMessage);
continue;
}
// Retrieve UV parameters from detected face data
uvParameter.m_dX = (detectedFaceData.m_sSurfaceDomain.m_sMin.m_dX + detectedFaceData.m_sSurfaceDomain.m_sMax.m_dX) / 2.0;
uvParameter.m_dY = (detectedFaceData.m_sSurfaceDomain.m_sMin.m_dY + detectedFaceData.m_sSurfaceDomain.m_sMax.m_dY) / 2.0;
status = A3DSurfEvaluateNormal((const A3DSurfBase*)pTopoFace, &uvParameter, &normal);
if (status == A3D_SUCCESS)
{
CString message;
message.Format(L"Detected Face %zu Normal: X: %f, Y: %f, Z: %f", i, normal.m_dX, normal.m_dY, normal.m_dZ);
AfxMessageBox(message);
}
else
{
CString errorMessage;
errorMessage.Format(L"Failed to evaluate normal for detected face %zu: Error code %d", i, status);
AfxMessageBox(errorMessage);
}
}
}
Then I tried to call NormalVectors(…) in the OnTimer(…) under Exchange part. It seems that the it is not being called here properly as I checked with debug text messages, or it may not be the right place to call it.
#ifdef USING_EXCHANGE_PARASOLID
selFace = ((HPS::Parasolid::Component)selCompArr[0]).GetParasolidEntity();
HPS::Component bodyComp = view->GetOwnerPSBodyCompo(selCompArr[0]);
PK_BODY_t body = ((HPS::Parasolid::Component)bodyComp).GetParasolidEntity();
std::vector<PK_ENTITY_t> pkEntityArr;
if (m_pProcess->FR((PsFRType)m_iFRType, selFace, pkEntityArr))
{
for (int i = 0; i < pkEntityArr.size(); i++)
{
PK_FACE_t face = pkEntityArr[i];
if (selFace != face)
{
// Highlight face
HPS::Component comp = view->GetPsComponent(body, face);
highlightCompArr.push_back(comp);
// Show list box
CString sEnt;
sEnt.Format(_T("%d"), pkEntityArr[i]);
m_detectedFaceListBox.AddString(sEnt);
}
}
}
#else
// Get owner BrepModel
HPS::Component ownerComp = view->GetOwnerBrepModel(selCompArr[0]);
A3DRiBrepModel* pRiBrepModel = HPS::Exchange::Component(ownerComp).GetExchangeEntity();
A3DTopoFace* pSelTopoFace = HPS::Exchange::Component(selCompArr[0]).GetExchangeEntity();
selFace = m_pProcess->GetEntityTag(pRiBrepModel, pSelTopoFace);
std::vector<A3DEntity*> pEntityArr;
if (m_pProcess->FR((PsFRType)m_iFRType, pRiBrepModel, pSelTopoFace, pEntityArr))
{
// Get component from selected A3DEntity
HPS::Exchange::CADModel cad_model = view->GetDocument()->GetCADModel();
for (int i = 0; i < pEntityArr.size(); i++)
{
A3DEntity* pEntity = pEntityArr[i];
if (pSelTopoFace != pEntity)
{
HPS::Component comp = cad_model.GetComponentFromEntity(pEntity);
highlightCompArr.push_back(comp);
// Show list box
int iEnt = m_pProcess->GetEntityTag(pRiBrepModel, pEntity);
CString sEnt;
sEnt.Format(_T("%d"), iEnt);
m_detectedFaceListBox.AddString(sEnt);
}
}
}
// Evaluate and display the normal vector
NormalVectors(pSelTopoFace, pEntityArr);
#endif
m_iSelFace = selFace;
m_selectedFaceID = selFace; // Store the selected face ID
Could you please take a look at the code? I would sincerely appreciate it if you could point out the mistakes and guide me with the corrected code if possible.
Thank you very much again, for all your time.
Kazi