cad_pixel_to_surface — CADMAP raycast op

• Data kinds: mesh × keypoints → table

• Call: import fullseye as fs; fs.ledger.cad_pixel_to_surface(mesh, pixels, K=None, R=None, t=None, cull_backfaces=True, image_size=None, strict=False) (to call the implementation directly, import cadmap; cadmap.cad_pixel_to_surface(mesh, pixels, K=None, R=None, t=None, cull_backfaces=True, image_size=None, strict=False); from the registry, opscadmap.get("cad_pixel_to_surface"))

Usage

Pixels (N,2) → (face_id, barycentric coordinates, 3-D point) on the CAD surface (closed form).

Builds a viewing ray per pixel (camera.py convention: centres at integer coordinates, u = column, v = row), intersects it with all triangles by Möller-Trumbore, and takes the nearest hit. For pixels that hit nothing it returns face_id = -1 and never rounds to the nearest face (so that in inspection "the defect was on the background" does not turn into "a defect on face 17"). With cull_backfaces=True (default), faces whose normal does not point at the camera do not count as hits.

The return is a dict:

• face_id (N,) int64 -- row index of the hit triangle. -1 on a miss.

• bary (N,3) -- barycentric coordinates (w0, w1, w2), in the order of the 3 vertices of F[face_id]. point = w0*V[i0] + w1*V[i1] + w2*V[i2] holds exactly. NaN on a miss. On an edge or vertex, 1 component is 0 (tolerance 1e-9).

• point (N,3) -- intersection point in world coordinates. NaN on a miss.

• depth (N,) -- Z in camera coordinates (not the distance along the ray). NaN on a miss.

• normal (N,3) -- unit normal of the hit face (world coordinates, as wound). NaN on a miss (same convention as bary/point/depth).

• hit (N,) bool.

• camera the K/R/t/width/height actually used. If it fell back to the defaults, you can see it here.

• winding_fixed bool -- whether an inward-wound closed mesh was detected and the winding was fixed inside this call. Always present (present even when False).

With cull_backfaces=True (default), if the mesh is closed and its signed volume is negative, by default the winding is fixed and winding_fixed=True is returned. With strict=True it is not fixed but rejected with ValueError. With cull_backfaces=False no backface test is done, so the winding direction does not affect the result; it is not checked and winding_fixed is always False (normal comes back with the sign of the input winding). For details see _orient_for_culling.

If K/R/t are omitted, a default camera that fits the mesh in the image is built (R = I, camera on the -Z side of the centroid). If image_size is omitted, the image size is determined from the bounding box of the given pixels -- so that the default camera looks where the pixels are; when K is given explicitly, it only affects the in_image test.

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

• The canonical algorithm (author, year) and its uses are named in the family usage guide above.

Runnable examples (verified samples that actually call this op)

• defect_to_cad — py -3.11 examples/defect_to_cad.py

Ops the type connects to (they accept table as input)

—

Same category (raycast)

—


*Provenance: cadmap.py — CADMAP operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.