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"))
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.
• 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.
• defect_to_cad — py -3.11 examples/defect_to_cad.py
table as input)—
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.