0

In Maya 2015, I can get the arclen of a curve using this command:

cmds.arclen('bezier1')

But now I want to get the arclen of two points in my curve. Is there anyway to get this?

Noah Zuo
  • 98
  • 12

2 Answers2

1

Using the Maya API, you can use the MFnNurbsCurve::findLengthFromParam (Maya 2016+ only). If you need it between two points, then call this function with each parameters and subtract.

If you don't want to use the api, then the other option is create a duplicate of your original curve and use "detach" it at the needed points and then use the arclen command on that new curve to get your length. So that is another way.

Note that when detaching a curve, it appears to try to keep the curvature as close the original as possible, but this isn't exact so the length may not be the same compared to the original curve. Maybe rebuilding the curve to have more points may increase the accuracy if that is an important factor for you.

scottiedoo
  • 309
  • 2
  • 10
  • Thanks for answering, so there is no such this api in Maya2015? – Noah Zuo Nov 10 '16 at 02:12
  • Looking at the docs, it doesn't appear so. You could write one yourself but it's a bit more complex if you research into approximating lengths of b-splines – scottiedoo Nov 10 '16 at 02:48
  • But if there is scale transforms on the curve transform, how would I compute the length ? – Shuman Jul 19 '19 at 16:51
0

Using Maya's API is surely the best way to do it as @scottiedoo said, but here is a function I made when I didn't know API and which gives you the same results.

from maya import cmds

def computeCrvLength(crv, startParam = None, endParam = None):
    '''
    Compute the length of a curve between the two given UParameters. If the both
    UParameters arguments are set to None (default), will compute the length of
    the whole curve.

    Arguments:
    - crv = string; an existing nurbCurve
    - startParam = 0 <= float <= 1 or None; default = None; point parameter
      value, if not None, will compute the points only between the startPt and
      EndPt values.
    - endParam = 0 <= float <= 1 or None; default = None; point parameter
      value, if not None, will compute the points only between the startPt and
      EndPt values.

    Returns:
    - The length of the curve between the given UParameters
    - The length of the curve from its start to the startParam
    - The length of the curve from its start to the endParam
    '''

    ###### Exceptions
    if cmds.objExists(crv) == False:
        cmds.error ('The curve "%s" does\'nt exists.' % crv)

    if cmds.filterExpand (crv, sm = 9) == None:
        cmds.error ('The object "%s" is not a nurbCurve.' % crv)

    if startParam != None:
        if (0 <= startParam <= 1) == False:
            cmds.error ('The start point parameter value must be between 0 and 1.')

    if endParam != None:
        if (0 <= endParam <= 1) == False:
            cmds.error ('The end point parameter value must be between 0 and 1.')

    if (startParam == None and endParam != None) or (startParam != None and endParam == None):
        cmds.error ('The start and end points parameters must be both None or ' + 
                    'both have values.')

    if startParam != None and endParam != None:
        if endParam < startParam:
            cmds.error ('The end point parameter value cannot be less or ' + 
                        'equal to start point parameter value.')

    ###### Function
    if startParam == None and endParam == None:

        crvLength = cmds.arclen (crv, ch = False)
        distCrvToStartParam = 0
        distCrvToEndParam = crvLength

    else:

        tmpArclenDim = cmds.arcLengthDimension (cmds.listRelatives(crv, s = True)[0]
                                                + '.u[0]')
        cmds.setAttr (cmds.listRelatives(tmpArclenDim, p = True)[0] +
                      '.uParamValue', startParam)
        distCrvToStartParam = cmds.getAttr (tmpArclenDim + '.al')
        cmds.setAttr (cmds.listRelatives(tmpArclenDim, p = True)[0] +
                      '.uParamValue', endParam)
        distCrvToEndParam = cmds.getAttr (tmpArclenDim + '.al')
        cmds.delete (tmpArclenDim)
        crvLength = (distCrvToEndParam - distCrvToStartParam)

    return crvLength, distCrvToStartParam, distCrvToEndParam
UKDP
  • 226
  • 5
  • 21