Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Tracing along Shape Path with Rounded Corners

  • Tracing along Shape Path with Rounded Corners

    Posted by Rob Mcdougall on October 29, 2020 at 5:49 pm

    Hi there.

    I’m prototyping some design stuff and have hit a bit of a wall. It’s necessary for me to have control of line width vs corner radius and a few other options. I’ve got a template working well, apart from one thing.

    I have a line with an arrowhead, it’s being traced with the built-in Trace Path script. However, after adding Round Corners to my line, the script is still referencing the original path, not the path with rounded corners.

    I took the expression in the null generated by the script apart a bit and re-wrote the pathToTrace variable to reference

    var pathLayer = thisComp.layer("Line_01"); 
    var progress = thisLayer.effect("Pseudo/ADBE Trace Path")("Pseudo/ADBE Trace Path-0001")/100;
    var pathToTrace = thisComp.layer("Line_01").content("Shape 1").content("Round Corners 1").path;
    pathLayer.toComp(pathToTrace.pointOnPath(progress));

    but get

    Cannot read property 'pointOnPath' of undefined

    I presume this means Round Corners doesn’t contain a path? I’ve also tried similar with a Path Merge, both inside the shape group and outside.

    Any thoughts on how I can “see” my path after it’s been rounded? I need to keep it editable so other designers can adjust it in the future.

    Filip Vandueren replied 3 weeks, 2 days ago 2 Members · 2 Replies
  • 2 Replies
  • Rob Mcdougall

    October 30, 2020 at 12:30 pm

    Working on this a little more, I figure out how to draw a path using expressions only, but I can’t figure out a way of rounding the corners. I can add a tangent but that’s not right… Does anyone know how to add rounded corners as an expression?

  • Filip Vandueren

    May 16, 2023 at 8:43 am

    Folllowing a question on reddit, I reverse engineered the rounding function, so I might as well add it here for future reference:

    function roundCorners(aPath, rounding) {
    	// Mimic After Effects' native round corner shape modifier but return an actual new Path
            // 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++) {
    			
    		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);
    }
    
    roundCorners(thisProperty, 50);

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