Intersection of a curve and a mesh

Concerning the code resulted by you for closestIntersection.
This code cannot work correctly.

  1. wrong quotes. Possibly due to incorrect formatting.

  2. In this context, useless code:

tarMeshList=[]
tarMeshList.append("pPlane1")
tarMesh = tarMeshList[0]

  1. dir = (V1 - V2).normal()
    You specify direction in the opposite direction.
    And even with such an error, it could work,
    if you set the testBothDirections parameter to True :
intersection = fnMesh.closestIntersection(
                                            om.MFloatPoint(mPoint),
                                            om.MFloatVector(dir),
                                            None,
                                            None,
                                            False,
                                            om.MSpace.kWorld,
                                            99999,
                                            True,    # testBothDirections
                                            None,
                                            hitpoint,
                                            None,
                                            None,
                                            None,
                                            None,
                                            None
                                          )

In this case, the intersection would be searched in both directions.
And the position of the first found intersection would be returned:
Let’s see the result:
hitpoint
# Result: <maya.OpenMaya.MFloatPoint; proxy of <Swig Object of type 'MFloatPoint *' at 0x000001D06EE32660> >
Oops, to “get” the values you have to use the monstrous monster - MScriptUtil…

Okay, let’s use “as is”:
But first you have to convert MFloatPoint to MPoint

m_point = om.MPoint(hitpoint)
# Result: <maya.OpenMaya.MPoint; proxy of <Swig Object of type 'MPoint *' at 0x000001D0896F2540> >
selectionList.clear()
selectionList.add("pCylinder1")
dagPath = om.MDagPath()
selectionList.getDagPath(0, dagPath)
fnMesh = om.MFnMesh(dagPath)
fnMesh.setPoint(17, m_point, 4)
fnMesh.updateSurface()

Regarding a simple method for finding the intersection of a ray with a plane.
I will illustrate the mathematical method for finding the intersection of a ray with a plane for your example:

import maya.cmds as cmds
import maya.api.OpenMaya as om
maya_useNewAPI = True

## Let's create a polygonal plane and a polygonal cylinder without caps.
## Let's transform them to look like your sample.

poly_cyl = (cmds.polyCylinder(name="sourse_poly_000", r=10, h=20, sa=10, sh=1, sc=0, ax=(0, 1, 0), rcp=0, cuv=3, ch=0))[0]
# Result: 'sourse_poly_000'
cmds.delete( "{}.f[{}:{}]".format(poly_cyl,10, 11) )
cmds.move(0.0, 10.0, 0.0, poly_cyl, r=1)
cmds.scale(1.25, 1.0 ,1.25, "{}.e[{}:{}]".format(poly_cyl, 10, 19))
poly_plane = (cmds.polyPlane(name="target_poly_000", h=50, w=50, sh=10, sw=10, ax=(0, 1, 0), cuv=1, ch=0))[0]
# Result: 'target_poly_000'
cmds.move(0.0, 40.0, 0.0, poly_plane, r=1)
cmds.rotate(0.0, 0.0, 30.0, poly_plane, r=1)


## We need the normal (as a vector: "N") of our intersection plane (poly_plane "target_poly_000").
## And any point ("plane_point") on this plane (as its position: "plane_point_position")
## Let's create a Selection List and add our plane to it:

sel_list = om.MSelectionList()
sel_list.add(poly_plane)
# Result: <OpenMaya.MSelectionList object at 0x000001F5D58CB250>

## Get the DagPath for the contents of the Selection List
dag_path_plane = sel_list.getDagPath(0)
# Result: <OpenMaya.MDagPath object at 0x000001F5D58B0FB0>

## Let's create an `OpenMaya MFnMesh` object for our  plane (passing our plane's DagPath as a parameter).

fn_mesh_plane = om.MFnMesh(dag_path_plane)
# Result: <OpenMaya.MFnMesh object at 0x000001F5D58CB6F0>

## We obtain for our plane the normal vector in world space,
## since our plane could be transformed.
## (Yes, our plane has been rotated and shifted)
## To get the normal of a plane, we can request a normal for any face of that plane.
## For example for "target_poly_000.f[0]".

N = fn_mesh_plane.getPolygonNormal(0, om.MSpace.kWorld)
# Result: maya.api.OpenMaya.MVector(-0.49999999999999994449, 0.86602540378443870761, 0)
## "0" - face ID from "target_poly_000.f[0]".World Space: "om.MSpace.kWorld" or "4" (om.MSpace.kWorld == 4)

## In addition, we need the normalized value of this normal vector.
N.normalize()
# Result: maya.api.OpenMaya.MVector(-0.49999999999999994449, 0.86602540378443870761, 0)
## we get the same value, since Maya uses normalized vector values for normals.

## We need the position of any point on the plane.
## In "world space"
## since our plane could be transformed.
## (Yes, our plane has been rotated and shifted)
## For example, take the position for the first vertex of this plane: "target_poly_000.vtx[0]"

plane_point = "target_poly_000.vtx[0]"

plane_point_position = fn_mesh_plane.getPoint(0, 4)
# Result: maya.api.OpenMaya.MPoint(-21.650635094610969134, 27.5, 25, 1)
## "0" - verttex ID from "target_poly_000.vtx[0]".World Space: "om.MSpace.kWorld" or "4" (om.MSpace.kWorld == 4)

## "N" and "plane_point_position" only need to be calculated once.
## These values will be used to calculate the intersections for all rays.

## We want to get the coordinates of the intersection point of the plane and the ray.
## A ray coming out of "in_point_01" (vertex "0" of our cylinder "sourse_poly_000")
## and passing through "in_point_02" (vertex "10" of our cylinder).

in_point_01 ="sourse_poly_000.vtx[0]"
in_point_02 ="sourse_poly_000.vtx[10]"

## Instead of creating a new Selection List,
## clear the already existing Selection List "sel_list".
## And add our cylinder to it (poly_cyl "sourse_poly_000").
sel_list.clear()
sel_list.add(poly_cyl)

## Set Dag Path for Select List Content
dag_path_cyl = sel_list.getDagPath(0)


## Let's create an MFnMesh object for our OpenMaya plane (passing our cylinder's DagPath as a parameter).

fn_mesh_cyl = om.MFnMesh(dag_path_cyl)


## Get the positions ("ray_position" and "dir_position") of the vertices ("sourse_poly_000.vtx[0]",
## "sourse_poly_000.vtx[10]") in world space:

ray_position = fn_mesh_cyl.getPoint(0, 4)
# Result: maya.api.OpenMaya.MPoint(8.0901708602905273438, 0, -5.8778543472290039062, 1)
dir_position = fn_mesh_cyl.getPoint(10, 4)
# Result: maya.api.OpenMaya.MPoint(13.961696624755859375, 48.060791015625, -10.143764495849609375, 1)

## Let's get a normalized direction vector ("ray_direct") for our ray coming out of the point "ray_position".
## To calculate the direction, we subtract from the direction point "dir_position" the starting point
## of the ray "ray_position", (as if they were vectors) and interpret the result as the value of a vector.

ray_direct = om.MVector( dir - ray ).normalize()
# Result: maya.api.OpenMaya.MVector(0.1207991613430363792, 0.98878953802889624214, -0.087765665857559654883)

## Now we turn to the calculation of intersections.
## These calculations actively use "Dot Produkt" or "Scalar Product", the so-called "Scalar Multiplication".
## This is an algebraic operation that takes two sequences of numbers of the same length,
## such as coordinate vectors, and returns the value as a single number.
## Python didn't support "Dot Produkt" until version 3.5!
## This is a very simple sequence of operations.
## And for it, you can write your own function in Python.
## But you should not do this, since the Maya API already implements scalar vector multiplication directly.
## For example: "Dot(V1, V2)". In the Maya API it's just: "(V1 * V2)"

ratio = N * ray_direct
# Result: 0.7959172782577852

denominator = N * om.MVector( plane_point_position - ray_position )
# Result: 38.68610158152281

## Verify that the vector and the plane are not parallel:
if denominator > .00001: intersection = ray_position + ray_direct * denominator / ratio
else: print("Ray direction and plane - parallel !")
# Result: maya.api.OpenMaya.MPoint(13.961696399865353158, 48.060789174806089363, -10.143764332457209321, 1)

## Let's check the result.
## move our vertex responsible for "dir_position" (in_point_02 "sourse_poly_000.vtx[10]")
## to the position of the intersection point:

fn_mesh_cyl.setPoint(10, intersection, 4)

## setPoint(10, intersection, 4).
## "10" - verttex ID from "target_poly_000.vtx[10]"
## "intersection" - target position (OpenMaya.MPoint):
## (13.961696399865353158, 48.060789174806089363, -10.143764332457209321, 1)
## "4" - World Space in MSpace: "om.MSpace.kWorld" or "4" (om.MSpace.kWorld == 4)

## Or, for clarity, let's create a locator at the position of the intersection point:

sp_locator = cmds.spaceLocator(p=(intersection.x, intersection.y, intersection.z), n="Intersection_000", a=1)
om.MGlobal.clearSelectionList()
cmds.setAttr("{}.localScale".format(sp_locator[0]), 2.0,2.0,2.0, type="double3")
cmds.setAttr("{}Shape.overrideEnabled".format(sp_locator[0]), True)
cmds.setAttr("{}Shape.overrideColor".format(sp_locator[0]), 9)

We have verified that this method works.
Yes, but how much more efficient and reliable is this method than the universal “closestIntersection” (without activation of acceleration methods)?
First, we modernize the code to automate the process (for a cylinder with an arbitrary number of edges-rays)
Let’s include two functions for finding intersections in the code.
Let’s provide an opportunity to switch between methods.
The first one will use the “closestIntersection” method (without activating the acceleration methods).
The second will use the classical mathematical method.

import maya.cmds as cmds
import maya.api.OpenMaya as om
try: from time import perf_counter as t_clock
except ImportError: from time import clock as t_clock
from timeit import timeit
maya_useNewAPI = True

def create_cilynder(ray_count):
    poly_cyl = (cmds.polyCylinder(name="sourse_poly_000", r=10, h=20, sa=ray_count, sh=1, sc=0, ax=(0, 1, 0), rcp=0, cuv=3, ch=0))[0]
    om.MGlobal.clearSelectionList()
    cmds.delete( "{}.f[{}:{}]".format(poly_cyl,ray_count, ray_count + 1) )
    cmds.move(0.0, 10.0, 0.0, poly_cyl, r=1)
    cmds.scale(1.25, 1.0 ,1.25, "{}.e[{}:{}]".format(poly_cyl,ray_count,ray_count*2-1))
    return poly_cyl


def create_poly_plane(height, weight, division, translation, rotatation):
    poly_plane = (cmds.polyPlane(name="target_poly_000", h=height, w=weight, sh=division, sw=division, ax=(0, 1, 0), cuv=1, ch=0))[0]
    om.MGlobal.clearSelectionList()
    cmds.move(translation[0], translation[1], translation[2], poly_plane, r=1)
    cmds.rotate(rotatation[0], rotatation[1], rotatation[2], poly_plane, r=1)
    return poly_plane


def fn_mesh(name):
    sel_list = om.MSelectionList()
    sel_list.add(name)
    dag_path = sel_list.getDagPath(0)
    fn_mesh = om.MFnMesh(dag_path)
    return fn_mesh


def create_ray_dir_array(poly_cyl, ray_count):
    sel_list = om.MSelectionList()
    sel_list.add("{}.e[{}:{}]".format(poly_cyl, ray_count*2, ray_count*3-1))
    node, component = sel_list.getComponent(0)
    it = om.MItMeshEdge(node, component)
    edges_count_in = it.count()
    ray_float_point_array = om.MFloatPointArray()
    dir_float_vector_array = om.MFloatVectorArray()
    while not it.isDone():
        point_0 = om.MFloatPoint(it.point(0))
        point_1 = om.MFloatPoint(it.point(1))
        ray_float_point_array.append(point_0)
        vector_d = om.MFloatVector(point_1 - point_0).normalize()
        dir_float_vector_array.append(vector_d)
        it.next()
    return ray_float_point_array, dir_float_vector_array


def intersections(poly_cyl, ray_count):
    time_00 = t_clock()
    fn_mesh_target = fn_mesh(poly_plane)
    arrays = create_ray_dir_array(poly_cyl, ray_count)
    ray_float_point_array = arrays[0]
    dir_float_vector_array = arrays[1]
    k_space = om.MSpace.kWorld
    testBothDirections = False
    k_tolerance = 0.001
    maxParam = 100.0    # As the maximum possible value of this parameter,
                        # it would be correct to pre-calculate the diagonal of the overall boundingbox.
                        # But we will set just a reasonable value with a little "margin"
    gen_list_inter = om.MPointArray()
    for i in range (ray_count):
        raySource = ray_float_point_array[i] # start point for ray search intersects. current edge(0)
        rayDir = dir_float_vector_array[i] # calculate direction for search intersects. Vector from current edge(0) to current edge(1)
        hit = fn_mesh_target.closestIntersection( raySource,
                                                  rayDir,
                                                  k_space,
                                                  maxParam,
                                                  testBothDirections,
                                                  #faceIds, triIds, idsSorted, accelParams,
                                                  # If you do not use these parameters,
                                                  # then simply do not specify them.
                                                  # You do not need to specify the value "None" !!!
                                                  # Otherwise it will cause errors or Maya crash.
                                                  tolerance = k_tolerance
                                                 )
        if hit and hit[0]: # if no hits, in Maya <=2020: return [], Maya>2020: return None
            hit_point, hit_ray_param, hit_face, hit_triangle, hit_bary_1, hit_bary_2 = hit
            gen_list_inter.append(hit_point)
    time_00 = t_clock() - time_00
    print("\n\t\t Total search intersects time for {} rays: {} s. (\"closestIntersection\" metod)\n".format(ray_count,time_00))
    return gen_list_inter


def target_const(poly_plane):
    fn_mesh_plane = fn_mesh(poly_plane)
    N = om.MFloatVector(fn_mesh_plane.getPolygonNormal(0, om.MSpace.kWorld).normalize())
    plane_point = "{}.vtx[0]".format(poly_plane)
    plane_point_position = om.MFloatPoint(fn_mesh_plane.getPoint(0, 4))
    return N, plane_point_position


def intersections_simply(poly_cyl, poly_plane, ray_count):
    time_00 = t_clock()
    arrays = create_ray_dir_array(poly_cyl, ray_count)
    ray_float_point_array = arrays[0]
    dir_float_vector_array = arrays[1]
    N, plane_point_position = target_const(poly_plane)
    gen_list_inter = om.MPointArray()
    for i in range (ray_count):
        ray_direct = dir_float_vector_array[i]
        ray_position = ray_float_point_array[i]
        ratio = N * ray_direct
        denominator = N * om.MFloatVector( plane_point_position - ray_position )
        if denominator > .00001:
            intersection = ray_position + ray_direct * denominator / ratio
        else: cmds.error("Ray direction and plane - parallel !")
        gen_list_inter.append(intersection)
    time_00 = t_clock() - time_00
    print("\n\t\t Total search intersects time for {} rays: {} s. (\"Math Intersection\" metod)\n".format(ray_count,time_00))
    return gen_list_inter


def move_vertices(gen_list_inter, ray_count, poly_cyl):
    if len(gen_list_inter) == ray_count:
        fn_mesh_cyl=fn_mesh(poly_cyl)
        for i in range(ray_count):
            fn_mesh_cyl.setPoint(ray_count + i, gen_list_inter[i], 4)


def locators_for_intersects(gen_list_inter, ray_count):
    if len(gen_list_inter) == ray_count:
        for item in gen_list_inter:
            sp_locator = cmds.spaceLocator(p=(item.x, item.y, item.z), n="Intersection_000", a=1)
            om.MGlobal.clearSelectionList()
            cmds.setAttr("{}.localScale".format(sp_locator[0]), 2.0,2.0,2.0, type="double3")
            cmds.setAttr("{}Shape.overrideEnabled".format(sp_locator[0]), True)
            cmds.setAttr("{}Shape.overrideColor".format(sp_locator[0]), 9)


def general(ray_count, method=1):
    poly_cyl = create_cilynder(ray_count)
    poly_plane = create_poly_plane(50.0, 50.0, 10, (0.0,40.0,0.0), (0.0,0.0,30.0))
    if method !=0:
        gen_list_inter = intersections_simply(poly_cyl, poly_plane, ray_count)
    else:
        gen_list_inter = intersections(poly_cyl, ray_count)

    move_vertices(gen_list_inter, ray_count, poly_cyl)
    locators_for_intersects(gen_list_inter, ray_count)


general(50) ## "Math Intersection" metod. Or "general(50, 0)" - "closestIntersection" metod
            ## !!! Maya does not allow you to create a cylinder with more than 1000 divisions !!!

For 1000 intersections, without data preparation
(Time spent only on calculation of intersection. Without data preparation ):

general(1000, 0)
# Total search intersects time for 1000 rays: 0.0131282000002102 s. ("closestIntersection" metod)

general(1000)
# Total search intersects time for 1000 rays: 0.0029899000001024 s. ("Math Intersection" metod)

“Math Intersection” metod ~ 4.5 times faster

####################################################

For 5,000,000 intersections, including data preparation overhead:

ray_count = 1000
timeit(lambda: intersections(poly_cyl, ray_count), number = 5000)
# Result: 88.27569920000133 s. ("closestIntersection" metod)
timeit(lambda: intersections_simply(poly_cyl, ray_count), number = 5000)
# Result: 37.94165220000105 s. ("Math Intersection" metod)

“Math Intersection” metod ~ 2.5 times faster

#####################################################

Obviously, the mathematical method does not look for intersections within the boundaries of our plane.
Intersections are searched for an arbitrary infinite plane drawn through the specified point and oriented according to the specified normal.
This quality may be indispensable in some cases, but may be a hindrance in others.