• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

Point coordinates on curved spline

Advocate ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

Hi guys.

I am banging my head to the wall for some time now with this issue.

As a simplified version, I have a perfect circle and I need to find midpoint coordinates between two vertices. In this case:

A is a vertex with coordinates [0, 0]

B is a vertex with coordinates [500, 0]

A1 is OutTangent of point A with coordinates [138, -138]

B1 is InTangent of point B with coordinates [362, -138]

The goal is to find midpoint coordinates.

coordinates.jpg

Again, this is very simple scenario. Other times tangent will be different lengths and shapes will be random as well, so I'd like to wrap my head around finding coordinates based on 2 vertices and InTangents and OutTangents.

Thanks in advance.

UQg‌,

TOPICS
Scripting

Views

1.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jul 06, 2015 Jul 06, 2015

I think this works:

t = .5; // percentage along path (between 0 and 1)

p0 = [0,0]; // vertex 1

p1 = [138,-138]; // tangent 1

p2 = [362,-138]; // tangent 2

p3 = [500,0]; // vertex 2

c = 3*(p1 - p0);

b = 3*(p2 - p1) - c;

a = p3 - p0 - c - b;

((a*t +b )*t + c)*t + p0

Dan

Votes

Translate

Translate
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

What about

1) compute the line that is perpendicular to the tangents of A

2) compute the line that is perpendicular to the tangents of B

3) the two lines from 1) and 2) intersect in exactly one point which is probably the point you are looking for

Before you think about how to implement this as a script, I recommend to think about whether this is exactly what you need. Because when you say you need the middle of a circle but also have very different shapes, a big question is what you actually want to compute exactly.

Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

oops, sorry, just noticed that I didn't understand you correctly. I thought you want to find the middle point of the circle, not the middle on the curve.

This video shows how individual points on a bezier curve are calculated

Mathias Möhl - Developer of tools like BeatEdit and Automation Blocks for Premiere Pro and After Effects

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

I think this works:

t = .5; // percentage along path (between 0 and 1)

p0 = [0,0]; // vertex 1

p1 = [138,-138]; // tangent 1

p2 = [362,-138]; // tangent 2

p3 = [500,0]; // vertex 2

c = 3*(p1 - p0);

b = 3*(p2 - p1) - c;

a = p3 - p0 - c - b;

((a*t +b )*t + c)*t + p0

Dan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

Dan, in case vertices don't have tangents (tangent values are [0, 0] for each vertex), the results looks off? Here's the values:

t = .25; // quater of the length

p0 = [0, 0]; // vertex 1

p1 = [0, 0]; // tangent 1

p2 = [100, 0]; // tangent 2

p3 = [100, 0]; // vertex 2

c = 3*(p1 - p0);

b = 3*(p2 - p1) - c;

a = p3 - p0 - c - b;

((a*t +b )*t + c)*t + p0 = [15.625, 0]

Shouldn't the result be [25, 0] (quarter of the spline length?)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

As I recall, the way the math works, for a straight line, the tangents need to be 1/3 of the way towards the other vertex. So [33.33333,0] and [66.66667,0] in your example.

Dan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

yeap, with [33.33333,0] and [66.66667,0] math is correct.

However, in AE vertex hard interpolation has tangents [0, 0]

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

Maybe if both tangents are [0,0] you draw a line instead of a bezier?

Dan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

Mathias, that link you posted is exatly what I was trying to figure out. Thank for it.

And Dan, you are my hero. Your formula seems to work just perfect!!! Thank you.

How did you figure this out?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 06, 2015 Jul 06, 2015

Copy link to clipboard

Copied

I did the research a long time ago, back when I posted this:

Bezier Curve

I don't remember the original source docs.

Dan

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Jul 21, 2015 Jul 21, 2015

Copy link to clipboard

Copied

LATEST

Hi,

"old" thread but this might interest someone.

Normally calculating the point halfway on a bezier curve requires a numerical algorithm, a bunch of functions for it, and is subject to errors.

Here is a trick that let After Effects calculate things for you: it copies the path to a position property, makes sure that the speed is constant, and collect the mid points using valueAtTime("midTime").
Since it creates acomp and a layer, then removes it, it can be quite slow if used repetedly, but it's fine for one use:

function getMidPoints(shape){

  

    // collects the middle of each subcurve (bezier segment) in the shape;

    // returns these points (gathered into an array)

    // the number of mid points depends on the shape being closed or not.

    var ret = [];

    var v, i, o, N, NN, n, comp, p, t1, t2, x, t;

    // the parameter x can be set as an argument to allow other values

    x = 0.5;

    t1 = 0;

    t2 = 10;  

    t = x*(t2-t1);

    v = shape.vertices;

    i = shape.inTangents;

    o = shape.outTangents;

    N = v.length;

    NN = N-1;

  

    app.beginUndoGroup("Collect points");

    comp = app.project.items.addComp("temp", 10, 10, 1.0, 1.0, 1.0); // the comp spec don't matter

    p = comp.layers.addNull().transform.position;

  

    // shapes are 2D but a position property is 3D (optionnal for vertices, but mandatory for tangents, otherwise setSpatialTangentsAtKey will generate an error):

    for (n=0; n<N; n++){

        v[2] = 0;

        o[2] = 0;

        i[2] = 0;

        };

  

    // make sure that the temporal interpolation is LINEAR

    // in case that's not the default, do it now:

    p.addKey(t1); p.setInterpolationTypeAtKey(1, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.LINEAR);

    p.addKey(t2); p.setInterpolationTypeAtKey(2, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.LINEAR);

  

    for (n=0; n<NN; n++){

        p.setValuesAtTimes( [t1, t2], [v, v[n+1]]);

        // set spatial interpolation

        p.setSpatialTangentsAtKey(1, [0,0,0], o);

        p.setSpatialTangentsAtKey(2, i[n+1], [0,0,0]);

        // leave temporal interpolation to linear so that the null travels at constant speed

        ret.push(p.valueAtTime(t, true).slice(0,2));

        };

    if (shape.closed){

        p.setValuesAtTimes( [t1, t2], [v, v[0]]);

        p.setSpatialTangentsAtKey(1, [0,0,0], o);

        p.setSpatialTangentsAtKey(2, i[0], [0,0,0]);

        ret.push(p.valueAtTime(t, true).slice(0,2));

        };

    // delete everything;

    comp.layer(1).source.remove();

    comp.remove();

    app.endUndoGroup();

  

    return ret;

    };

function test(){

    // a mask must be selected

    // the test creates additionnal mask with just 1 vertex, one for each "midpoint"

  

    var comp = app.project.activeItem, props, p, points, n, N, L, shape;

  

    if (! (comp instanceof CompItem) || comp.selectedProperties.length===0) return;

    props = comp.selectedProperties;

    N = props.length;

    n=0; while (n<N && !props.isMask) ++n;

    if (n===N) {alert("Please select a mask"); return;};

    L = props.propertyGroup(2);

    points = getMidPoints(props.maskPath.value);

    N = points.length;

    for (n=0; n<N; n++){

        // Visualize points as shapes with just one vertex, on the same layer:

        shape = new Shape(); shape.vertices = [ points ];

        L.mask.addProperty("ADBE Mask Atom").maskPath.setValue(shape);

        };

    return;

    };

$.hiresTimer;

test();

alert($.hiresTimer);

Xavier.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines