0

我最近开始了解 python OpenMaya api v2.0,所以我一直在检查我的代码并尝试更新它以使用 2.0 版本。在大多数情况下,它对我来说比旧版本的 OpenMaya 更有意义......

我在尝试使用该OpenMaya.MFnNurbsSurface.closestPoint方法时遇到了障碍。我似乎无法弄清楚如何实际使用 kwargs 的方法。Maya 的文档是这样说的:

closestPoint(testPoint, uStart=None, vStart=None,
    ignoreTrimBoundaries=False, tolerance=kPointTolerance,
    space=kObject) -> (MPoint, float, float)

所以对我来说,这看起来像是我应该能够使用的 kwargs……但我几乎每次尝试使用它们时都会出错 - 当它没有出错时,我真的不明白为什么它没有t(以下示例)。如果我不放入 kwargs,它会“起作用”,但不会给我正确的结果,因为我确实需要更改其中的一些 kwargs。

这是执行此操作的旧方法和新方法的一些代码(新方法就是我到目前为止所拥有的……):

import maya.OpenMaya as oldOM
import maya.api.OpenMaya as om

def getClosestPointOnSurfaceOLD(surf, position):
    selList = oldOM.MSelectionList()
    selList.add(surf)
    mDagPath = oldOM.MDagPath()
    selList.getDagPath(0, mDagPath)
    surfFn = oldOM.MFnNurbsSurface(mDagPath)

    u_util = oldOM.MScriptUtil()
    u_util.createFromDouble(0)
    u_param = u_util.asDoublePtr()

    v_util = oldOM.MScriptUtil()
    v_util.createFromDouble(0)
    v_param = v_util.asDoublePtr()

    p = surfFn.closestPoint(oldOM.MPoint(*position), u_param, v_param, False, 1.0, oldOM.MSpace.kWorld)

    return [(p[0], p[1], p[2]), (oldOM.MScriptUtil.getDouble(u_param), oldOM.MScriptUtil.getDouble(v_param))]

def getClosestPointOnSurfaceNEW(surf, position):
    selList = om.MSelectionList()
    selList.add(surf)
    surfFn = om.MFnNurbsSurface(selList.getDagPath(0))

    p, u, v = surfFn.closestPoint(om.MPoint(*position), ignoreTrimBoundaries=False, tolerance=1.0, space=om.MSpace.kWorld)

    return [(p[0], p[1], p[2]), (u, v)]

我通过创建一个 nurbsPlane (使用默认值)然后将它在 y 中向上移动 0.5 个单位并将这两个函数的输出与这些行进行比较来测试它:

getClosestPointOnSurfaceOLD('nurbsPlane1', (0.0, 1.0, 0.0))
getClosestPointOnSurfaceNEW('nurbsPlane1', (0.0, 1.0, 0.0))

# Result: [(-2.7755575615628914e-17, 0.5, 2.7755575615628914e-17), (0.5, 0.5)] # <-- old function result
# Error: TypeError: file <maya console> line 28: integer argument expected, got float # <-- new function result

我尝试在函数中使用“closestPoint”行做的其他事情:

surfFn.closestPoint(om.MPoint(*position), ignoreTrimBoundaries=False)
# Result: [(-2.7755575615628914e-17, -1.5407439555097887e-33, 2.7755575615628914e-17), (0.5, 0.5)] #

surfFn.closestPoint(om.MPoint(*position), False)
# Result: [(-1.1102230246251565e-16, -6.162975822039155e-33, 1.1102230246251565e-16), (0.5, 0.5)] #

surfFn.closestPoint(om.MPoint(*position), tolerance=1.0)
# Error: TypeError: file <maya console> line 28: integer argument expected, got float #

surfFn.closestPoint(om.MPoint(*position), tolerance=1)
# Error: RuntimeError: file <maya console> line 28: More keyword list entries (6) than format specifiers (5) #

surfFn.closestPoint(om.MPoint(*position), 1.0)
# Result: [(-1.1102230246251565e-16, -6.162975822039155e-33, 1.1102230246251565e-16), (0.5, 0.5)] #

surfFn.closestPoint(om.MPoint(*position), space=om.MSpace.kWorld)
# Error: RuntimeError: file <maya console> line 28: More keyword list entries (6) than format specifiers (5) #

surfFn.closestPoint(om.MPoint(*position), om.MSpace.kWorld)
# Result: [(-1.1102230246251565e-16, -6.162975822039155e-33, 1.1102230246251565e-16), (0.5, 0.5)] #

surfFn.closestPoint(om.MPoint(*position))
# Result: [(-2.7755575615628914e-17, -1.5407439555097887e-33, 2.7755575615628914e-17), (0.5, 0.5)] #

surfFn.closestPoint(om.MPoint(*position), False, 1.0, om.MSpace.kWorld)
# Result: [(-2.7755575615628914e-17, 3.851859888774472e-33, -6.938893903907228e-17), (0.5, 0.5000000000000001)] #

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), uStart=0.0, vStart=0.0, ignoreTrimBoundaries=False, tolerance=1.0, space=om.MSpace.kWorld)
# Error: TypeError: file <maya console> line 28: integer argument expected, got float #

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, False, 1.0, om.MSpace.kWorld)
# Error: TypeError: file <maya console> line 28: integer argument expected, got float #

输出中的一些差异对我来说很奇怪,而且错误似乎没有意义(比如调整“公差”arg 值时的差异)......而且,事实证明 0.5 的 uv 值是正确只是巧合——如果我移动和/或旋转平面,旧函数会返回不同的 uv 值,而新函数总是返回 0.5,因为它是从平面的对象空间而不是使用世界空间来评估测试点。

我还查看了相应的旧 OpenMaya 命令的文档,其中有两个条目 - 如果您要提供一些启动 uv 值,则其中一个具有“paramAsStart”布尔参数。考虑到 2.0 文档可能错过了这一点,我也尝试将其添加到我的 api 2.0 尝试中......它也没有工作(给了我一个错误,我传递了太多的参数)。

至少,我需要弄清楚如何让它从世界空间评估测试点;但是,当我继续使用 OpenMaya api 2.0 时,我相信我会再次遇到这种类型的事情(kwargs 似乎不起作用......) - 任何有关如何实际使用这些 kwargs 的帮助表示赞赏!

编辑:

更多测试 - 在 theodox 的回答之后,我猜想文档的 arg 顺序可能不正确......所以,我决定测试排列。假设uStart并且vStart将始终彼此相邻给出“kwargs”的 24 种排列,但我决定也尝试 None、0.0 和 0 作为它们的值(72 个测试!)。 全部出错。

这是我的测试线:

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, False, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, False, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, 1.0, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, 1.0, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, om.MSpace.kWorld, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), None, None, om.MSpace.kWorld, 1.0, False)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, None, None, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, None, None, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, None, None, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, om.MSpace.kWorld, None, None)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, None, None, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, 1.0, None, None)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, None, None, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, None, None, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, None, None, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, om.MSpace.kWorld, None, None)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, None, None, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, False, None, None)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, None, None, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, None, None, 1.0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, None, None, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, 1.0, None, None)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, None, None, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, False, None, None)



surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, False, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, False, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, 1.0, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, 1.0, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, om.MSpace.kWorld, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0.0, 0.0, om.MSpace.kWorld, 1.0, False)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 0.0, 0.0, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 0.0, 0.0, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, 0.0, 0.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, om.MSpace.kWorld, 0.0, 0.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, 0.0, 0.0, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, 1.0, 0.0, 0.0)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, 0.0, 0.0, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, 0.0, 0.0, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, 0.0, 0.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, om.MSpace.kWorld, 0.0, 0.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, 0.0, 0.0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, False, 0.0, 0.0)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 0.0, 0.0, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 0.0, 0.0, 1.0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, 0.0, 0.0, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, 1.0, 0.0, 0.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, 0.0, 0.0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, False, 0.0, 0.0)



surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, False, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, False, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, 1.0, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, 1.0, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, om.MSpace.kWorld, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 0, 0, om.MSpace.kWorld, 1.0, False)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 0, 0, 1.0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 0, 0, om.MSpace.kWorld, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, 0, 0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, 1.0, om.MSpace.kWorld, 0, 0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, 0, 0, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), False, om.MSpace.kWorld, 1.0, 0, 0)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, 0, 0, False, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, 0, 0, om.MSpace.kWorld, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, 0, 0, om.MSpace.kWorld)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, False, om.MSpace.kWorld, 0, 0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, 0, 0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), 1.0, om.MSpace.kWorld, False, 0, 0)

surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 0, 0, False, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 0, 0, 1.0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, 0, 0, 1.0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, False, 1.0, 0, 0)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, 0, 0, False)
surfFn.closestPoint(om.MPoint(0.0, 1.0, 0.0), om.MSpace.kWorld, 1.0, False, 0, 0)

这些是会出现的常见错误:

# Error: RuntimeError: file <maya console> line 1: More keyword list entries (6) than format specifiers (5) #
# Error: TypeError: file <maya console> line 1: integer argument expected, got float #
# Error: TypeError: file <maya console> line 1: an integer is required #
# Error: TypeError: file <maya console> line 1: a float is required #

如果有人感兴趣,我可以发布线路/错误...

所以,我想这是一个玛雅错误 - bleh ...

4

2 回答 2

0

我认为这是文档生成方式的一个怪癖。C++ 版本以类似于 kwargs 之类的 Python 程序员的方式编写默认参数。但它不是真正的 kwargs,它是默认参数。您必须将它们视为只是命名为位置参数并按顺序提供它们。

这对我有用:

def getClosestPointOnSurfaceNEW(surf, position):
    selList = om.MSelectionList()
    selList.add(surf)
    surfFn = om.MFnNurbsSurface(selList.getDagPath(0))

    p, u, v = surfFn.closestPoint(om.MPoint(*position))

    return [(p[0], p[1], p[2]), (u, v)]

也是如此

    p, u, v = surfFn.closestPoint(om.MPoint(*position), 0, 0 )

通常,如果您想提供更多参数,通常只需按顺序执行即可:

p, u, v = surfFn.closestPoint(om.MPoint(*position), 0,0, False, 0.01, om.MSpace.kWorld)

但是我无法验证它是否有效,因为它会使我的(测试版)Maya 崩溃;不确定 2017 年或 2018 年的生产状态如何。

于 2017-08-16T06:31:52.973 回答
0

我也在 Autodesk Maya 论坛上发布了这个......原来有一个关于这个的已知错误。

如果有人好奇,这是Maya 论坛主题的链接

于 2017-08-16T15:50:25.037 回答