ET_NormalCurves


Here is a script that will add a curve to each point or polygon aligned to its normal. Change the arguments according to what you need.

# Python
from win32com.client import constants as c
from win32com.client import Dispatch as d
 
xsi = Application
log = xsi.LogMessage
collSel = xsi.Selection
 
def axesFromNormal(vecNormal, vecUpV):
    """Creates vectors for each axis of a transform."""
 
    vecX = XSIMath.CreateVector3()
    vecY = XSIMath.CreateVector3()
    vecZ = XSIMath.CreateVector3()
    vecToTgt = XSIMath.CreateVector3()
    vecBaseToUpV = XSIMath.CreateVector3()
 
    vecX.Cross(vecUpV, vecNormal)
    vecX.NormalizeInPlace()
 
    vecY.Copy(vecNormal)
    vecY.NormalizeInPlace()
 
    vecZ.Cross(vecX, vecNormal)
    vecZ.NormalizeInPlace()
 
    return vecX,vecY,vecZ
 
def ET_NormalCurves(oTgtObj, bUsePolys=False, sNormalScale=1.0):
 
    try:
        xsi.BeginUndo("ET_NormalCurves")
 
        lNormalCurveData = [[0.0, 0.0], [0.0, sNormalScale], [0.0, 0.0], [1.0, 1.0]]
 
        oTgtGeo = oTgtObj.ActivePrimitive.Geometry
 
        if bUsePolys:
            aPolygonPositionICEData = oTgtGeo.ICEAttributes("PolygonPosition").GetDataArrayChunk(0,0)
            aPositions = [[i.X,i.Y,i.Z] for i in aPolygonPositionICEData]
 
            aPolygonNormalICEData = oTgtGeo.ICEAttributes("PolygonNormal").GetDataArrayChunk(0,0)
            aNormals = [[i.X,i.Y,i.Z] for i in aPolygonNormalICEData]
        else:
            aPointPositionICEData = oTgtGeo.ICEAttributes("PointPosition").GetDataArrayChunk(0,0)
            aPositions = [[i.X,i.Y,i.Z] for i in aPointPositionICEData]
 
            aPointNormalICEData = oTgtGeo.ICEAttributes("PointNormal").GetDataArrayChunk(0,0)
            aNormals = [[i.X,i.Y,i.Z] for i in aPointNormalICEData]        
 
        xformUtil = XSIMath.CreateTransform()
        vecNormal = XSIMath.CreateVector3()
        vecUpV = XSIMath.CreateVector3()
        for i in xrange(len(aPositions)):
            oNormalCrv = oTgtObj.AddNurbsCurve(lNormalCurveData, None, True, 1, c.siNonUniformParameterization, c.siSINurbs)
            oNormalCrv.Name = oTgtObj.Name + "_Normal" + str(i).zfill(len(str(len(aPositions)))) + "_Crv"
 
            xformUtil.SetTranslationFromValues(aPositions[i][0],aPositions[i][1],aPositions[i][2])
            vecNormal.Set(aNormals[i][0],aNormals[i][1],aNormals[i][2])
 
            if aNormals[i][1] >= 0.999:
                vecUpV.Set(aPositions[i][0],aPositions[i][1],aPositions[i][2])
                vecUpV.NormalizeInPlace()
            elif aNormals[i][1] = 0.000 and aNormals[i][1] < 0.999:
                vecUpV.Set(0,1,0)
                vecUpV.NormalizeInPlace()
            elif aNormals[i][1] < 0.000 and aNormals[i][1] > -0.999:
                vecUpV.Set(0,-1,0)
                vecUpV.NormalizeInPlace()
 
            vecX, vecY, vecZ = axesFromNormal(vecNormal, vecUpV)
            xformUtil.SetRotationFromXYZAxes(vecX,vecY,vecZ)
            xformUtil.MulInPlace(oTgtObj.Kinematics.Global.GetTransform2(None))
 
            oNormalCrv.Kinematics.Global.PutTransform2(None,xformUtil)
    finally:
        xsi.EndUndo()
 
ET_NormalCurves(collSel(0))