parametric path expressions


3 parametric path expressions for After Effects TOC

circle path expression

//circle expression
var circle = content("Ellipse Path 1");
var radiusx = circle.size[0] * .5;
var radiusy = circle.size[1] * .5;
var myPosition = circle.position - radiusx;
var kappa =  0.5519;//4 * ((Math.sqrt(2) - 1) / 3)
var tanLengthx = (radiusy/2)  * kappa *2;
var tanLengthy = (radiusx/2)  * kappa *2;
var myPoints = [myPosition + [0,0], 
                myPosition + [radiusx, radiusy], 
                myPosition + [radiusx*2,0], 
                myPosition + [radiusx, -radiusy]    ];
var myinTangents = [    [0, -tanLengthx],
                        [-tanLengthy,0],
                        [0, tanLengthx],
                        [tanLengthy,0]  ];
var myoutTangents = [   [0, tanLengthx],
                        [tanLengthy,0],
                        [0,-tanLengthx],
                        [-tanLengthy,0] ];
myIs_closed = true;
createPath(myPoints, myinTangents, myoutTangents, myIs_closed);

square path expression

//rectangle path expression
var square = content("Rectangle Path 1");
var rectsize = square.size;
var rectpos = square.position;
var roundingBase = square.roundness;

var point1 = [-rectsize[0]/2 + rectpos[0], -rectsize[1]/2 + rectpos[1]];
var point2 = [rectsize[0]/2 + rectpos[0], -rectsize[1]/2 + rectpos[1]];
var point3 = [rectsize[0]/2 + rectpos[0], rectsize[1]/2 + rectpos[1]];
var point4 = [-rectsize[0]/2 + rectpos[0], rectsize[1]/2 + rectpos[1]];

var mypt = [point1, point2, point3, point4];
var myit = [[0,0], [0,0], [0,0], [0,0]];
var myot = [[0,0], [0,0], [0,0], [0,0]];
var mylength = mypt.length;
var myopenclose = true;
var kappa = 0.5519;//4 * ((Math.sqrt(2) - 1) / 3); 

var newpt = [];
var newit = [];
var newot = [];
for(var i=0;i<mylength;i++){
    rounding = Math.min(Math.min(roundingBase, rectsize[0]/2),rectsize[1]/2);
    currentV = mypt[i];
    currentO = myot[i] + mypt[i];
    currentI = myit[i] + mypt[i];
    if (currentV[0] === currentO[0] && currentV[1] === currentO[1] && currentV[0] === currentI[0] && currentV[1] === currentI[1]) {
        if ((i === 0 || i === mylength - 1) && !myopenclose) {
            newpt.push(currentV);
            newit.push(currentI - currentV);
            newot.push(currentO - currentV);
        } else {
            if (i === 0) {
                closerV = mypt[mylength - 1];
                closerO = myot[mylength - 1] + closerV;
                closerI = myit[mylength - 1] + closerV;
            } else {
                closerV = mypt[i - 1];
                closerO = myot[i - 1] + closerV;
                closerI = myit[i - 1] + closerV;
            }
            if (closerV[0] === closerO[0] && closerV[1] === closerO[1]) {
                distance = Math.sqrt(Math.pow(currentV[0] - closerV[0], 2) 
                         + Math.pow(currentV[1] - closerV[1], 2));
                newPosPerc = distance ? Math.min(distance / 2, rounding) / distance : 0;
                iX = currentV[0] + (closerV[0] - currentV[0]) * newPosPerc;
                vX = iX;
                iY = currentV[1] - (currentV[1] - closerV[1]) * newPosPerc;
                vY = iY;
            } else {
                distance = Math.sqrt(Math.pow(currentV[0] - (closerO[0]), 2) 
                         + Math.pow(currentV[1] - (closerO[1]), 2));
                newPosPerc = distance ? Math.min(distance, rounding) / distance : 0;
                iX = currentV[0] + ((closerO[0]) - currentV[0]) * newPosPerc;
                vX = iX;
                iY = currentV[1] - (currentV[1] - (closerO[1])) * newPosPerc;
                vY = iY;
            }
            oX = vX - (vX - currentV[0]) * kappa;
            oY = vY - (vY - currentV[1]) * kappa;

            newpt.push([vX,vY]);
            newit.push([iX,iY] - [vX,vY]);
            newot.push([oX,oY] - [vX,vY]);

            if (i === mylength - 1) {
                closerV = mypt[0];
                closerO = myot[0] + closerV;
                closerI = myit[0] + closerV;
            } else {
                closerV = mypt[i + 1];
                closerO = myot[i + 1] + closerV;
                closerI = myit[i + 1] + closerV;
            }
            if (closerV[0] === closerI[0] && closerV[1] === closerI[1]){
                distance = Math.sqrt(Math.pow(currentV[0] - closerV[0], 2) 
                         + Math.pow(currentV[1] - closerV[1], 2));
                newPosPerc = distance ? Math.min(distance / 2, rounding) / distance : 0;
                oX = currentV[0] + (closerV[0] - currentV[0]) * newPosPerc;
                vX = oX;
                oY = currentV[1] - (currentV[1] - closerV[1]) * newPosPerc;
                vY = oY;
            } else {
                distance = Math.sqrt(Math.pow(currentV[0] - (closerI[0]), 2) 
                         + Math.pow(currentV[1] - (closerI[1]), 2));
                newPosPerc = distance ? Math.min(distance , rounding) / distance: 0;
                oX = currentV[0] + ((closerI[0]) - currentV[0]) * newPosPerc;
                vX = oX;
                oY = currentV[1] - (currentV[1] - (closerI[1])) * newPosPerc;
                vY = oY;
            }
            iX = vX - (vX - currentV[0]) * kappa;
            iY = vY - (vY - currentV[1]) * kappa;

            newpt.push([vX,vY]);
            newit.push([iX,iY] - [vX,vY]);
            newot.push([oX,oY] - [vX,vY]);
        }
    } else {
        newpt.push(currentV);
        newit.push(currentI - currentV);
        newot.push(currentO - currentV);
    } 
}

createPath(newpt, newit, newot, myopenclose);

polystar path expression

// polystar path expression
var polystar = content("Polystar Path 1");
var isStar = polystar.type; //star = 1, polygon = 2
var numberOfPoints = polystar.points;
var pos = polystar.position;
var offsetangle = degreesToRadians( polystar.rotation );
var or = polystar.outerRadius;

var tau = Math.PI*2;
var kappa = 0.5519;//4 * ((Math.sqrt(2) - 1) / 3); 
var factor =  linear(numberOfPoints,3,4,8.25,9);
var outerSeg = (tau * or) / (numberOfPoints * 2) * factor;
var outerRound = polystar.outerRoundness * .001 * outerSeg * kappa ;
var times = 1;
var angle = tau / Math.floor(numberOfPoints) ;

if(isStar == 1){
    var ir = polystar.innerRadius;
    var innerSeg = (tau * ir) / (numberOfPoints * 2) * factor;
    var innerRound = polystar.innerRoundness * .001 * innerSeg * kappa ;
    var times = 2;
    angle = tau / Math.floor(numberOfPoints*2) ;
}

//pointAndTangents grouped as: point, inTangent, outTangent
var pointsAndTangents = [];
for(var i = 0; i < numberOfPoints*times; i++){
    var currentAng = angle * i + offsetangle;
    var currentAngle = currentAng - Math.PI *.5;
    var x = or * Math.cos(currentAngle);
    var y = or * Math.sin(currentAngle);
    var ty = x === 0 && y === 0 ? 0 : -x / Math.sqrt(x * x + y * y);
    var tx = x === 0 && y === 0 ? 0 :  y / Math.sqrt(x * x + y * y);
    if(i%2 && isStar == 1){
        pointsAndTangents[i]=   [
        [   pos[0] + ir * Math.sin(currentAng), pos[1] - ir * Math.cos(currentAng)], 
        [ +tx * innerRound, +ty * innerRound],
        [ -tx * innerRound, -ty * innerRound]];
    }else{
        pointsAndTangents[i]=   [
        [   pos[0] + or * Math.sin(currentAng), pos[1] - or * Math.cos(currentAng)], 
        [ +tx * outerRound, +ty * outerRound],
        [ -tx * outerRound, -ty * outerRound]];
    }
}

var myPoints = [];
var myinTangents = [];
var myoutTangents = [];
for(var i = 0;i<numberOfPoints*times;i++){
    myPoints.push(pointsAndTangents[i][0]);
    myinTangents.push(pointsAndTangents[i][1]);
    myoutTangents.push(pointsAndTangents[i][2]);
}

myIs_closed = true;
createPath(myPoints, myinTangents, myoutTangents, myIs_closed);