Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Multiple corner radii for rounded corners

  • Multiple corner radii for rounded corners

    Posted by Filip Vandueren on May 16, 2023 at 9:18 am

    Hi guys,

    don’t know if there was already a solution for doing this in After Effects like in Illustrator, but here is a method for adding multiple different values for corner radius within 1 shape.

    I reverse engineered the round corners algorithm, so this was a logical next step.

    https://imgur.com/a/QA5oblT

    This only works on Custom Paths, not on built-in rectangles/polygons/…

    It uses an expression, so the “round corners” modifier shouldn’t be added.

    I hope someone will find this useful in the future. And perhaps someone can add/remix the code

    function multiRound(aPath, roundings) {
    // multiple corner-radii
    // Filip Vandueren 2023
    const pts = aPath.points();
    const it = aPath.inTangents(); const ot = aPath.outTangents(); const cl = aPath.isClosed();
    let newPts = []; let newIt = []; let newOt = [];
    for (let i=0; i<pts.length; i++) {
    rounding = roundings[i%roundings.length];
    if ((!cl && (i==0 || i==pts.length-1)) || length(it[i])!=0 || length(ot[i])!=0) {
    // re-use the first and last vertex unaltered if the path is not closed
    // OR if this vertex originally had tangents, it's also not discarded and chamfered, but kept:
    newPts.push(pts[i]);
    newIt.push(it[i]);
    newOt.push(ot[i]);
    } else {
    // add chamfer vertices, discarding the original vertex
    // giving these new vertices tangents creates the rounded corners
    // look at previous vertex
    let j = i-1;
    if (j<0) j+=pts.length; // loop around in closed paths
    let segment = (pts[j]+ot[j]-pts[i]); // consider a linesegment from this vertex to the prev outTangent
    // where should we place the chamferpoint:
    // on that segment, at a point that's 'roundingvalue' away from the current vertex
    // but on a straight linesegment it should never be further than 1/2 the distance
    // (the rounding is limited by the edges length)
    let n = normalize(segment)*Math.min(rounding, length(segment)/(length(ot[j])==0 ? 2 : 1));
    let chamferPoint = pts[i] + n;
    // add the point and it's tangent, using the magic number 0.55
    // it's on the same linesegment
    newPts.push(chamferPoint);
    newIt.push([0,0]);
    newOt.push(-n*0.55);
    // look at next vertex
    j = (i+1)%pts.length; // loop around in closed paths
    segment = (pts[j]+it[j]-pts[i]);
    // same logic as above
    n = normalize(segment)*Math.min(rounding, length(segment)/(length(it[j])==0 ? 2 : 1));
    chamferPoint = pts[i] + n;
    newPts.push(chamferPoint);
    newIt.push(-n*0.55);
    newOt.push([0,0]);
    }
    }
    return createPath(newPts, newIt, newOt, cl);
    }
    multiRound(thisProperty, [20,100,250]);

    Multiple corner radii in after effects

    Andre Vieira replied 2 years ago 2 Members · 1 Reply
  • 1 Reply
  • Filip Vandueren

    May 16, 2023 at 9:26 am

    Already had an idea for a remix: negative values give a chamfer instead of rounding:

    https://imgur.com/a/nO51Q10

    function multiRound(aPath, roundings) {
    // multiple corner-radii
    // a negative value will add a chamfer
    // Filip Vandueren 2023
    const pts = aPath.points();
    const it = aPath.inTangents(); const ot = aPath.outTangents(); const cl = aPath.isClosed();
    let newPts = []; let newIt = []; let newOt = [];
    for (let i=0; i<pts.length; i++) {
    rounding = roundings[i%roundings.length];
    if ((!cl && (i==0 || i==pts.length-1)) || length(it[i])!=0 || length(ot[i])!=0) {
    // re-use the first and last vertex unaltered if the path is not closed
    // OR if this vertex originally had tangents, it's also not discarded and chamfered, but kept:
    newPts.push(pts[i]);
    newIt.push(it[i]);
    newOt.push(ot[i]);
    } else {
    // add chamfer vertices, discarding the original vertex
    // giving these new vertices tangents creates the rounded corners
    // look at previous vertex
    let j = i-1;
    if (j<0) j+=pts.length; // loop around in closed paths
    let segment = (pts[j]+ot[j]-pts[i]); // consider a linesegment from this vertex to the prev outTangent
    // where should we place the chamferpoint:
    // on that segment, at a point that's 'roundingvalue' away from the current vertex
    // but on a straight linesegment it should never be further than 1/2 the distance
    // (the rounding is limited by the edges length)
    let n = normalize(segment)*Math.min(Math.abs(rounding), length(segment)/(length(ot[j])==0 ? 2 : 1));
    let chamferPoint = pts[i] + n;
    // add the point and it's tangent, using the magic number 0.55
    // it's on the same linesegment
    newPts.push(chamferPoint);
    newIt.push([0,0]);
    newOt.push(-n*(rounding>0 ? 0.55 : 0));
    // look at next vertex
    j = (i+1)%pts.length; // loop around in closed paths
    segment = (pts[j]+it[j]-pts[i]);
    // same logic as above
    n = normalize(segment)*Math.min(Math.abs(rounding), length(segment)/(length(it[j])==0 ? 2 : 1));
    chamferPoint = pts[i] + n;
    newPts.push(chamferPoint);
    newIt.push(-n*(rounding>0 ? 0.55 : 0));
    newOt.push([0,0]);
    }
    }
    return createPath(newPts, newIt, newOt, cl);
    }
    multiRound(thisProperty, [10,200,-50]);

    View post on imgur.com

  • Andre Vieira

    April 16, 2024 at 4:12 pm

    Hi guys,
    this is super super useful. And I didn’t find any good solution before this (after a good amount of searching).
    I added some sliders and I can animate each vertice independently, and in an non-destructible workflow.
    You should totally create a simple UI for this! Something where you could just use it as an layer effect – that detects how many vertices the shape have and adds the equivalent number of sliders (if that’s possible…).
    It would probably sell easily on something like Aescripts.

    Cheers,
    André

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy