Calculating the tangent of a Bezier curve using the x and y coordinates of a specific point, instead of the parameter t where 0 < t < 1

Currently, I am faced with the challenge of dealing with a bezier curve intersecting with a line in the top left corner.

https://i.sstatic.net/QrgJP.png

After identifying the points at which the line and curve intersect, my goal is to determine the tangent of the bezier curve at those specific points. My existing function can find the tangent at a given point t on the curve but operates with values between 0 and 1 rather than coordinates. See below:

let bezierCurveTangent = function(start: Point, end: Point, controlPoint: Point, t: number): Point {

    let x = 2 * (1 - t) * (controlPoint.x - start.x) + 2 * t * (end.x - controlPoint.x);

    let y = 2 * (1 - t) * (controlPoint.y - start.y) + 2 * t * (end.y - controlPoint.y);

    return { x, y };
}

The question now remains, how can I calculate the tangent for a point using x and y coordinates instead of a value for t?

The equation for a point on a bezier curve follows this structure:

https://i.sstatic.net/Aol5x.png

Is it feasible to rearrange this equation to solve for t and then input that value into the function mentioned above?

It seems there should be a more efficient method to tackle this issue without the need for constant conversions between t values and various points.

Answer №1

To find the intersection point of a curve and a line, simply search for it in terms of parameter t.

Given the parametric equation of a line passing through points L0, L1:

L(u) = L0 + (L1-L0)*u = L0 + DL*u

We can set up an equation system as follows:

P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x = L0x+u*DLx
P0y*(1-t)^2+2*(1-t)*t*P1y+t^2*P2y = L0y+u*DLy

By expressing u from the first equation and substituting it into the second one:

u = (P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x - L0x)/Dlx

We then further substitute it in the second equation:

(P0y*(1-t)^2+2*(1-t)*t*P1y+t^2*P2y-L0y)*Dlx=
   (P0x*(1-t)^2+2*(1-t)*t*P1x+t^2*P2x-L0x)*DLy

Finally, solve the resulting quadratic equation to obtain the solutions t1 and t2, provided they exist within the range of 0 to 1.

Answer №2

To solve the equation, rather than expanding and solving the polynomials, I suggest a simpler computational solution. Let P0=(a1,a2), P1=(b1,b2), P2=(c1,c2). Consider (x,y) as the point at which you wish to determine the tangent.

  1. Begins by shifting coordinates so that P1 becomes the origin: let x=x'+b1, y=y'+b2. In the (x',y') coordinates, the curve is represented as:

    B(t) = (1-t)2P0 + t2 P2

    The coordinates of P0 and P2 will be recalculated accordingly using prime notation for them.

  2. Next step involves rotating and scaling the coordinate system so that P0 and P2 shift to points (0,1) and (1,0). Achieve this by inverting the matrix provided below:

    Note that an inverse exists if the points P0, P1, P2 do not lie on the same line, and the matrix looks like this:

    Therefore, the new coordinates (x'',y'') are expressed as (x',y')=A(x'',y''). The curve in this new system is given by:

    B(t) = (1-t)2e1 + t2e2

    Here, e1=(1,0) and e2=(0,1), simplifying to:

    x''(t) = (1-t)2
    y''(t) = t2

If y'' is known, it's easy to find t=sqrt(y''). Note that the square root always exists (if you began with a point lying on the bezier curve) because we transformed coordinates ensuring the curve lies where x>0 and y>0. Finding (x'',y'') from (x,y) is straightforward using the formula (x'',y'')=(x+c1, y+c2)B. This can be understood with this code snippet:

const getT = (start: Point, end: Point, controlPoint: Point, x: number, y: number) => {
  // xp stands for x'
  const xp = x - controlPoint.x
  const yp = y - controlPoint.y
  const a1p = start.x - controlPoint.x
  const a2p = start.y - controlPoint.y
  const c1p = end.x - controlPoint.x
  const c2p = end.y - controlPoint.y

  const det = a1p * c2p - a2p * c1p

  // Variable xpp included redundantly for clarity
  const xpp = (xp * c2p - yp * c1p) / det
  const ypp = (- xp * a2p + yp * a1p) / det

  return Math.sqrt(ypp)
}

Or more concise version:

const getT = (start: Point, end: Point, controlPoint: Point, x: number, y: number) => Math.sqrt(
  (- (x - controlPoint.x) * (start.y - controlPoint.y) 
    + (y - controlPoint.y) * (start.x - controlPoint.x)) / 
  ((start.x - controlPoint.x) * (end.y - controlPoint.y) -
    (start.y - controlPoint.y) * (end.x - controlPoint.x))
)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Extract the data that was returned from the AJAX post function

I am looking to create a condition that is dependent on the data received from an ajax post outside of the post function function post(){ $.post('page.php',$('#form').serialize(), function(data) { if(data !== 'good'){a ...

The logout feature might refresh the page, yet the user remains logged in

Currently, I am enrolled in a course on Udemy where the instructor is utilizing Angular 2. My task involves building the app using the latest version of Angular. The issue that I am facing pertains to the logout functionality. After successfully logging ou ...

Is there a way to remove unnecessary code from the end of a string using JavaScript?

Most of the users of my script are hosted on a server that inserts a text ad at the end of each page. Unfortunately, this code is appearing in my script's AJAX responses as well. The unwanted content is an HTML comment followed by a link to their sign ...

The setter of the computed property is failing to execute

Currently, I am working with a computed property that represents an object of a specific type defined within my Vuex Store. The goal is to utilize this property in my component using v-model. I have thoroughly set up getters and setters for this property a ...

What is the process for transferring ng-model values to a table in Angular?

My goal is to populate a table with JSON data using ng-repeat by clicking a button. I need to input either a first name or last name in order to display the results in the table. Is this the correct JavaScript function for achieving this? JavaScript Funct ...

Ways to conceal <td>s in angularjs on specific rows during ng-repeat

In the first <tr>, I have a table with many <td> elements that I am populating using ng-repeat. <tr ng-repeat="receipt in $data"> <td data-title="voucher number"> <span>{{receipt.voucher_no}}</span> </td ...

When utilizing a 'Token' in the provider() aliasing within Angular 2, the Typescript compiler may display an error message stating 'Unresolved variable or type'. This issue can arise when defining

When working with Typscript, I've encountered an issue where it can't handle a 'Token' in the context of an Angular2 provide() aliasing function. I'm unsure if there's a specific setting in the typescript compiler to address t ...

Tips for emptying the fields and restoring a form within a modal once it has been closed

I am facing an issue with a form inside a modal where the fields initially have red borders to indicate they are mandatory. However, when I fill out each field and then close the modal, the fields are cleared but the red borders indicating their mandatory ...

Obtain every selection from the multiselect box and add them to the database

How do I assign all selected measures to my "answers" object? The selected measures are: get selectedMeasures() { const items = this.measureItems.filter((item: any) => item.selected); return items.length ? JSON.stringify(items.map(item => ...

Ways to access states from a Vuex store within a Vuetify list in VueJs

Here is a snippet from my Vue file: import store from '@/store' export default{ name: 'myList', data: () => ({ show: true, listContent: [{ name: '1', icon: 'pers ...

What is the best method for retrieving data from a loop in a vuetify carousel?

I am using vuetify to create a carousel that displays recipes stored in the database. However, I would like the carousel to expand below with all the details of the recipe when clicked. After some research, I found a Vuetify component that fits my requirem ...

Adjusting the size of elements and the dimensions of the browser window

My challenge involves a container with multiple buttons that are absolutely positioned. I would like these buttons to dynamically resize based on the width of the browser window. Essentially, I want both the size and position of the buttons to adjust accor ...

How to Transfer Deleted List Items from one Unordered List to another in Angular 9 using Event Binding

Greetings to all =) I've recently delved into Angular 9 and I'm really enjoying the component-based approach. To sharpen my skills in property and event binding, I embarked on a project involving building a deck with two lists. English isn't ...

The requested :id route could not be found using the findById() method in

Having trouble retrieving data using Insomnia from a specific ID in my collection. Below is the sample request URL. http://localhost:5000/todos/5dd295a49d5d7a0b7a399bbe However, when I access http://localhost:5000/todos/ without the ID, I can see all the ...

Is there a way to expand a pie chart into a new pie chart with PHP and Javascript?

I need help finding a code that can expand a pie chart into another pie chart. The original pie chart appears too congested with numerous entries when it first loads. I have only come across tutorials for accomplishing this in Excel online. Can someone a ...

Managing Multiple Scheduled Tasks with Node.js and MongoDB

I've got a .js file as part of my node.js APP, with 2 questions to address. var User = require('../app/models/user'); var Agenda = require('agenda'); var mongoConnectionString = "mongodb://localhost/agenda"; var agenda = new A ...

The improved approach to implementing guards in Angular

I am currently looking for the most effective way to utilize Angular "guards" to determine if a user is logged in. Currently, I am checking if the token is stored. However, I am wondering if it would be better to create an endpoint in my API that can verif ...

Adding an object to an array of objects with the useState hook in React - A simple guide

Hello, I am currently working on a project that involves creating a dynamic test page with questions, answers, and points/grades. The goal is to generate input fields based on the number of questions selected by the admin, along with an "Add Question" butt ...

What is the best way to dynamically load a personalized JavaScript file for individual users depending on their PHP login credentials?

Currently, I am conducting a web-based experiment in which students log into a website to take practice tests for a class. Initially, the students land on a login page that includes the following code: include_once("core/config.php"); include_once("core/ ...

Retrieve information from an external website on the client's end

Is there a way to retrieve data such as titles and descriptions from a user-entered external URL using client-side methods, like how Facebook automatically populates information when a link is copied into a post? Are there any jQuery plugins or similar to ...