Calculating the 2D transformation matrix between two triangles using JavaScript

Seeking to determine the 2D transformation matrix for converting one triangle into another.
The coordinates of both triangles' points are known.
Although I typically utilize Paper.js for manipulating matrices, this particular scenario is outside its scope.
Nevertheless, I have employed it to demonstrate my issue in this

I believe I've come across the theoretical solution here, but implementing it in JavaScript proves challenging due to my limited knowledge in matrix mathematics.
Is there a JavaScript library capable of resolving such problems?
Alternatively, does anyone know how to tackle this in JavaScript?

Below is the code used to illustrate the issue:

// Known input points
const p1A = new Point(0, 0);
const p2A = new Point(25, 0);
const p3A = new Point(0, 15);

// Matrix to be calculated
const matrix = new Matrix();
matrix.translate(40, 0);
matrix.rotate(30);
matrix.scale(1.2, -0.2);
matrix.rotate(-70);

// Transformed points
const p1B = p1A.transform(matrix);
const p2B = p2A.transform(matrix);
const p3B = p3A.transform(matrix);

// Display elements for visual aid
drawPoint(p1A, 'p1A', 'red');
drawPoint(p2A, 'p2A', 'cyan');
drawPoint(p3A, 'p3A', 'lime');
drawPoint(p1B, 'p1B', 'red');
drawPoint(p2B, 'p2B', 'cyan');
drawPoint(p3B, 'p3B', 'lime');

drawPolygon([p1A, p2A, p3A], 'A');
drawPolygon([p1B, p2B, p3B], 'B');

// Fit to view for better visibility
project.activeLayer.fitBounds(view.bounds.scale(0.8));

//
// METHODS
//

function drawPoint(point, name, color) {
    new Path.Circle({
        center: point,
        radius: 1,
        fillColor: color
    });
    new PointText({
        content: name,
        point: point - [0, 1.5],
        justification: 'center',
        fontSize: 1
    });
}

function drawPolygon(points, name) {
    const path = new Path({
        segments: points,
        strokeColor: 'grey',
        closed: true
    });
    new PointText({
        content: name,
        point: path.bounds.center,
        justification: 'center',
        fontSize: 2
    });
}

Answer №1

After reading through this informative article, I found a clear and simple solution to the problem at hand. By following the proposed method outlined in the article and implementing it myself, I was able to successfully tackle the task.
The key concept of the solution involves calculating a transformation matrix for each triangle that can map the coordinates of the given triangle to those of a "standard triangle" (with coordinates (1,0), (0,1), (0,0)). Using these matrices, we first transform the initial triangle to the standard triangle by applying the inverse of the calculated matrix, and then further transform it to the target triangle.

To visualize the solution, you can view the detailed

function calculateResetMatrix(p1, p2, p3) {
    return new Matrix(
        p1.x - p3.x, p1.y - p3.y,
        p2.x - p3.x, p2.y - p3.y,
        p3.x, p3.y
    );
}

function calculateMatrix(p1, p2, p3, p1Transformed, p2Transformed, p3Transformed) {
    return calculateResetMatrix(p1, p2, p3).inverted()
        .prepend(calculateResetMatrix(p1Transformed, p2Transformed, p3Transformed));
}

Additionally, here is the complete code implementation:

// Code implementation goes here

Answer №2

The solution to this problem can be found in the article on Wikipedia that covers the math behind it. Check out the section discussing the concept of an augmented matrix, especially when dealing with translations.

If you are working in JavaScript, you can handle all the necessary computations by using the library linalg.js.

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

After the upgrade from Angular 5.2 to Angular 6, Bootstrap 4 dropdown and Bootstrap-select dropdown seem to have lost their dropdown functionality. This issue arose after updating to Bootstrap 4 and jquery

Update: Upon further investigation, I experimented with a standard Bootstrap 4 dropdown and encountered the same issue – it would not open. This leads me to believe that the problem may not be specific to the selectpicker class or the bootstrap-select de ...

Unable to access a nested JSON object that has a repeated name

I'm relatively new to working with JSON, so the issue I'm facing may be simple, but I haven't been able to find a similar problem on stackoverflow. Here's my question: My goal is to access a nested JSON object like: pizza.topping.ratin ...

MariaDB won't generate JSON output for a column that has a JSON data type

Currently, I am utilizing MariaDB and phpMyAdmin to effectively manage my database. Within one of my tables, I have a specific field that is defined as type json, or alternatively longtext. However, whenever I execute a SELECT query using JSON_EXTRACT(fiel ...

What are the steps to accessing the scene, renderer, and camera objects in Forge Viewer v6 using TypeScript?

In the past, I could utilize code such as this: var container = viewer.canvas.parentElement; var renderer = viewer.impl.renderer(); var scene = viewer.impl.scene; To access Three.js objects in Forge Viewer. With version 6, how can I achieve the same usin ...

Refresh the jQuery Raty choice when clicked (jQuery)

Currently, I am incorporating the jQuery Raty plugin into a jQuery UI dialog to create a questionnaire-style format. Through custom jQuery scripting, I have devised an interactive interface where users are presented with a new question upon each selection ...

Merge two arrays based on date and sort them using Angular.js/JavaScript

I am facing a challenge where I have two JSON arrays, each containing a field named date. My goal is to compare the two arrays and merge them into a single array. Check out the code snippet below: var firstArr=[{'name':'Ram','date ...

The current error message states that the function is undefined, indicating that the Bookshelf.js model function is not being acknowledged

I have implemented a user registration API endpoint using NodeJS, ExpressJS, and Bookshelf.js. However, I encountered an error while POSTing to the register URL related to one of the functions in the User model. Here is the code snippet from routes/index. ...

Tips for designing scrollable overlay content:

I am currently in the process of building a page inspired by the design of Hello Monday. Right now, I have added static content before implementing the parallax effect and auto-scroll. Here is my progress so far: Check out the Sandbox Link One challenge ...

Can you explain the distinct variations between these two approaches for obtaining API data?

When working with third-party APIs in NextJS 14, I encountered two different methods to query the API that resulted in slightly different outcomes. Method 1: Located within the /api folder as a route handler: export async function GET() { const res = aw ...

Is async programming synonymous with multi-threading?

Discussing a JavaScript code that utilizes the setInterval function every 2 seconds. There is also an animation event for some control triggered by the onblur event. If the onblur event occurs (along with the animation), there is a possibility of encount ...

Having trouble getting the Javascript/jQuery listener to function properly with Underscore.js templates

I've been working on developing a webapp using underscore.js for creating templates. However, I've encountered an issue when trying to render a basic template like the one below: <div id="container"></div> <script type=& ...

We encountered a ReferenceError stating that 'dc' is not defined, despite having already imported d3, dc, and crossfilter in

In my current angular project, I have included the necessary imports in the component.ts file in the specific order of d3, crossfilter2, dc, and leaflet. Additionally, I have added the cdn for dc-leaflet.js in the index.html file. Despite these steps, wh ...

Is there a way to identify when an image extends beyond the boundaries of the browser window and subsequently reposition it?

Currently, I am implementing a method found at this link to display popup images of my thumbnails. However, there is an issue when the thumbnail is positioned close to the edge of the screen and the original image is too large, causing it to be cut off by ...

What limitations prevent me from using "await .getAttribute()" in Protractor, despite the fact that it does return a promise?

I have been working on transitioning my Protractor tests from using the selenium control flow to async/await. However, I am facing an issue where it is not allowing me to use await for the .getAttribute() function. Each time I try, I receive the error mess ...

Getting the parameter route value from Laravel and passing it to Ajax

Need help with returning the parameter of a Laravel route to an AJAX response. Here is the relevant code: public function getPermissions(Request $request) { //$v = request()->route()->parameters('profile'); $v = request()-& ...

JavaScript hovering drop-down feature

Hi there, I'm just starting out with javascript and could use some help with a simple script. I have a shopping cart drop down that currently activates when clicked. However, I want it to fade in when hovered over instead. I've tried using .hove ...

What is the most efficient way to use the $slice operator on a highly nested array in mongoose

I am currently working on slicing a deeply nested array. To illustrate, consider the following structure. I aim to slice this array for pagination purposes. {messages: [{ message: { members: [ {example: object, blah: blah}, {example2: object2, blah2: blah ...

Using preventDefault in the compositionend event does not make any difference

var inputNode = document.getElementById('view_1'); inputNode.addEventListener('compositionend', function(e) { console.log(e.cancelable); // true e.preventDefault(); }); <div id="view_1" class="view" contenteditable="true> &l ...

Using Angular's ng-repeat prefilter with JavaScript

Is it possible to achieve the functionality of this angular js filter ng-repeat on a tr element using pure javascript? Could it be done in just one custom filter? Please note that showRow is a function that returns a boolean value, and searchString is a s ...

Finding the amount of memory that can be used in a WebView

I'm currently developing an application that features a WebView running JavaScript code. This particular JavaScript code tends to be memory-intensive and can sometimes exceed the allotted memory, leading to crashes in the WebView's Chromium proce ...