How to Get a 3D Point on a Visible Face and Project it to 2D Screen Coordinates

Hello,

I’m working with a 3D model in Open CASCADE that includes a rim consisting of three layered parts. These parts are stacked such that the first part visually covers the second when viewed from the front.

In my use case:
- I have selected the second part, which is correctly highlighted in yellow.
- I want to pick a point on the face of this selected part that is actually visible to the camera (i.e., not occluded by the first part).
- This point must lie on the face geometry itself and be visible from the current camera/view direction.

My goal is to:
1) Identify a 3D point on the visible face of the selected part.
2) Project that 3D point into 2D screen space (in terms of screen X/Y or pixel coordinates).
3) Use this projected point as the starting point for drawing a leader line (annotation/notation line) in the viewer.

❓ Is this possible in Open CASCADE?
Can Open CASCADE determine which faces of a shape are visible from the current camera/view direction?
Is there a recommended way to find a representative 3D point (e.g., center of visible face or sampled point on surface) and project it into screen coordinates?
Are there existing utilities or example methods for 3D → 2D projection tied to the current viewer/view?

Additional Notes:
I'm happy to provide more details or a picture to clarify if needed. Let me know if sample shapes or view context are necessary to better explain the situation.

Thank you!

Attachments: 
gkv311 n's picture

Why do you want to calculate some point on selected Face and not let user to select the point lying on the Face? User selects the Face not in 3D Viewer? You want to update the attach point when user rotates the camera?

Selection routine in AIS will return you 3D point on selected Face for free - you'll just need to iterate over picking results in SelectMgr_ViewerSelector and find the one associated with your Face after ::MoveTo().

Is there a recommended way to find a representative 3D point (e.g., center of visible face or sampled point on surface) and project it into screen coordinates?

Cannot imagine existing algorithm that would give an answer to such a question. What OCCT provides is SelectMgr_ViewerSelector, but it doesn't answer the question which point on a Face is visible - it allows to find intersection between selectable objects and sort them by Depth from eye (hence, topmost sorted object will occlude others for a specific pixel).

But then, without a prior filtering - you would have to brute-force random pixels on the screen by SelectMgr_ViewerSelectorto find the visible ones and then to figure out which one among visible you like the most. The scope of pixels could be reduced by projecting Bnd_Box or Bnd_OBB of your Face onto the screen. Or by using triangulation nodes / centers of triangles of a Face for inquiring intersections from camera.

Are there existing utilities or example methods for 3D → 2D projection tied to the current viewer/view?

There are plenty of conversion utilities like V3d_View::Convert(), V3d_View::Project(), Graphic3d_Camera::Project(), Graphic3d_Camera::UnProject() and others, but you'll have to figure out which one to used based on specific scenario.

rahulmulik9's picture

// Update detection under cursor
AISContext->MoveTo(screenX, screenY, view, false);

// Get currently detected object
Handle(AIS_InteractiveObject) detectedObj = m_pAISContext->DetectedInteractive();
if (detectedObj.IsNull()) {
return false;
}

// Build current selection set
AIS_ListOfInteractive mySelectedObjects;
for (AISContext->InitSelected(); AISContext->MoreSelected(); AISContext->NextSelected()) {
mySelectedObjects.Append(AISContext->SelectedInteractive());
}

// Check if detected object is in selection
for (const auto& obj : mySelectedObjects) {
if (obj == detectedObj) {
return true;
}
}
return false;

Explanation of the Issue:
I've stored the point where the left mouse button was pressed, and I'm using that as the starting point for detection. However, when I pass this same point into the method above:
The first call returns true (i.e., the detected object is part of the selection),
But subsequent calls with the same point return false and then again true

Question:
Am I doing something wrong? Why would the same point give inconsistent detection results?

for (const auto& obj : mySelectedObjects) {
const Handle(AIS_Shape)& aisObj = Handle(AIS_Shape)::DownCast(obj);
const Handle(AIS_Shape)& aisdetectedObj = Handle(AIS_Shape)::DownCast(detectedObj);
//hashcode
int hashcodeObj = aisObj->Shape().HashCode(HASHCODE_UPPER_LIMIT);
int hashcodedetectedObj = aisdetectedObj->Shape().HashCode(HASHCODE_UPPER_LIMIT);
if (hashcodeObj == hashcodedetectedObj) {
return true;
}
}

For second time I am getting error at this line
int hashcodedetectedObj = aisdetectedObj->Shape().HashCode(HASHCODE_UPPER_LIMIT);
saying that Access violation reading location