Linearize an exponential function

  • Hi,
    I have created an user data slider (with percent unit) to controlling subdivisions number of a spline (spline with an Adaptive interpolation). So I have used a MapRange function to convert a percentage to a degree but this dosen't returnning a natural result. because the number of an intermediate subdivision points is increasing exponentially.
    I want to know how to fit an exponential number of intermediate points to a linear.

            SplineObject *sp = SplineObject::Alloc(4, SPLINETYPE_BEZIER); // create a spline with 3 verts
            Vector *gp = sp->GetPointW();
            gp[0] = Vector(0, 0, 0);
            gp[1] = Vector(0, 0, 900);
            gp[2] = Vector(0, 250, 1200);
            gp[3] = Vector(0, 900, 1200);
            sp->GetDataInstance()->SetBool(SPLINEOBJECT_CLOSED, false);
            Float value = data->GetFloat(BSK_OBJECT_CURVE_SUB);
    	Float min_input = 0;
    	Float max_input = 1;
    	Float min_output = 90;
    	Float max_output = 1;
    	Float inrange = max_input - min_input;
    	if (CompareFloatTolerant(inrange, 0.0)) value = 0.0;
    	else value = (value - min_input) / inrange;
    	curve_sub = DegToRad(min_output + (max_output - min_output) * value);
    	sp->SetParameter(SPLINEOBJECT_ANGLE, curve_sub, DESCFLAGS_SET_0);

  • Hi mfersaoui, thanks for reaching out us.

    With regard to your issue I've a few notes:

    • the Adaptive interpolation is by definition strictly dependent on the shape of the spline with regard to the tessellation of the curve: the curve will be tessellated more where the curvature is larger and this generates evidently non-uniform segments distribution - check here for further notes -;
    • standing on the code presented the in_range variable is always 1.0 which makes this
    if (CompareFloatTolerant(inrange, 0.0)) value = 0.0;
    	else value = (value - min_input) / inrange;

    pretty useless.

    I would recommend, assuming that the adaptive strategy is the one you want to keep to consider ( sorry for the python code, but porting should be trivial)

            # swap the max/min values of the slider
            val = op[c4d.ID_USERDATA, 1]
            # set the interpolation method
            interp = 3
            # allocate the spline
            spline = c4d.SplineObject(4, c4d.SPLINETYPE_BSPLINE)
            # set interpolation method
            spline[c4d.SPLINEOBJECT_INTERPOLATION] = interp
            # switch according to interpolation method
            if interp == 2: # uniform
                # set the max number of segs
                maxSegs = 100
                spline[c4d.SPLINEOBJECT_SUB] = int(maxSegs * val)
            if interp == 3: # adaptive
                # get the rad representation of the slider's value
                radVal = c4d.utils.DegToRad(90 * (1.0 - val))
                # set the adaptive angle value
                spline[c4d.SPLINEOBJECT_ANGLE] = radVal
            # set the points
            point = spline.SetAllPoints((c4d.Vector(0,0,0),c4d.Vector(0,0,900),c4d.Vector(0,900,900), c4d.Vector(0,900,0)))
            # return the spline
            return spline

    If instead you'd like to linearly increase the subdivision, I warmly recommend to switch to the uniform method and you'll see that a linear behavior is established

    Best, R

  • @r_gigante Thank you for the detailed reply,

    Sorry, I didn't put the last part of my code in my question above. I will mention that I want to set a tangent on the points 2 and 3, here is the last part of my code in python:

    curve_offset = op[c4d.BSK_OBJ_CURVE_OFFSET] # correspond to the value "250" in my above code
    spline.SetTangent(1, Vector(0, 0, 0), Vector(0, 0, curve_offset * 0.5))
    spline.SetTangent(2, Vector(0, -curve_offset * 0.5, 0), Vector(0, 0, 0))

    So, I try to add the lines above on your code but this returning this error message:

    IndexError: tangent index out of range

    Thanks Again.

  • @r_gigante
    Finally I found the solution to linearize the subdivision expansion on Adaptive spline interpolation on the angle deviation.

    I just replaced the line :

    radVal = c4d.utils.DegToRad(90 * (1.0 - val)

    By :

    radVal = math.pow(val, -0.85)

    I changed also the slider user data unit to REAL
    if I want to keep it with a PERCENT unit I just multiply the value by 100

    radVal = math.pow(val*100, -0.85)

    Here is demo:

Log in to reply