Giter Club home page Giter Club logo

Comments (4)

rikkertkoppes avatar rikkertkoppes commented on May 29, 2024 1

FWIW, I just implemented this using an iterative approximation:

public getPointAtDistance(offset: number, ϵ: number = 1) {
    let l = this.length();
    if (offset < 0) return this.get(0);
    if (offset > l) return this.get(1);
    let i = 0, maxIterations = 10;
    let error = l;
    let guess = offset / l;
    //interpolate
    while (error > ϵ && i < maxIterations) {
        let segmentLength = this.split(guess).left.length();
        error = segmentLength - offset;
        guess = guess - (error / l);
        i += 1;
    }
    return this.get(guess);
}

It converges pretty fast, generally, within 3 or 4 iterations it achieves subpixel accuracy.
I should also note that my version works on the interval [0, length]

from bezierjs.

Pomax avatar Pomax commented on May 29, 2024

it would be useful to make maxIterations an overridable value as well.

A few notes:

  • You don't need to spend time on calculating .length() for <0 and >1 cases, putting it after will make <0 and >1 perform in O(1)
  • While guess = offset/length works, I suspect guess = offset works a little better on average. Generally the initial guess is going to be way too low, as it starts off dividing a number in [0,1] by a value orders of magnitude higher, so in this implementation we start at "barely above zero" in the vast majority of cases.
  • you can cache the this.split(guess).left during iteration in a variable declared outside the while loop, which removes the need to recompute this.get(guess) at return, as that yields the point corresponding to the last iterations's left.get(1).

from bezierjs.

rikkertkoppes avatar rikkertkoppes commented on May 29, 2024

This version works with offset on the range [0, length], rather than [0,1], which seemed more natural to me. Hence the first guess (for t) is offset / length

The rest of the notes are very useful, thanks

from bezierjs.

Pomax avatar Pomax commented on May 29, 2024

let's consider this a naming issue: getPointAtLength(...) should absolutely take a value in [0,curve.length], whereas getPointAtDistance(...) feels more like a 0%-100% call, but I can see how someone else might still consider [0,length] more appropriate.

So let's say this:

  • getPointAtDistance: based on actual curve length
  • getPointAtPercentage: based on 0%-100% (rather than [0,1])

from bezierjs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.