Zoom-to-fit functionality in Three.js with spacing adjustment

I am currently working on developing a zoom-to-fit function that can accurately adjust a list of points to fit within a specified drawing area, while also allowing for customizable offsets on all sides of the image. In essence, I aim to zoom-to-fit within a specific area of the frame rather than the entire viewer area:

https://i.sstatic.net/6y6Lr.png
(please note that the offsets depicted in this image may not be entirely accurate)

My current setup involves using a perspective camera. The objective is to update the camera's position without altering its parameters or view direction.

Although I have managed to implement a functional zoom-to-fit feature*, I am facing challenges when it comes to integrating the desired offsets.

Initially, my approach involved offsetting the point coordinates using the camera's coordinate system. However, this method did not yield the desired results - while more of the image was displayed, the selected points did not align with the edges of the designated area. This discrepancy can be attributed to the distortion caused by the perspective view, which deviates the points from their intended positions.

Is there anyone who could offer assistance on calculating the correct camera distance and position to address this issue?


* Although Three.js does not include a built-in zoom-to-fit function, various resources and discussions are available online on how to incorporate this functionality. One particularly useful resource for scenarios like these would be CameraViewBox. I have adapted their example to suit my requirements in this fiddle:

import * as THREE from 'https://cdn.skypack.dev/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="62160a10070722524c5351524c53">[email protected]</a>';
...

Answer №1

After figuring out a solution on my own, I realized that starting with symmetric offsets makes the process surprisingly easy: https://i.sstatic.net/vndgM.png

If we use a narrower FOV angle (green) to determine the camera position, the projected points will shift by a certain amount in the final image. By finding the correct angle, we can achieve the desired offset for the points.

To calculate this angle, basic trigonometry comes into play. We first find the distance to the Normalized Device Coordinate plane (height/width of -1 to 1; shown in blue in the image), then apply the offset (ranging from 0.0 to 1.0) to derive a new angle:

tan(FOV / 2) = 1 / dist  =>  dist = 1 / tan(FOV / 2)

tan(FOVg / 2) = (1 - offset) / dist  =>  FOVg = atan((1 - offset) / dist) * 2

Repeat this process for the horizontal FOV (adjusted by aspect ratio) with either the same or different offset value. Finally, implement the existing zoom-to-fit method based on these new angles.


This technique works effectively for symmetric offsets. It may also be applicable for asymmetric offsets by computing four separate new angles. The challenge lies in determining the appropriate camera position and zoom using these angles...

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

What is the format required for specifying the end date and start date when using

Implementing the bootstrap datepicker. The Documentation doesn't specify the expected format for setEndDate or setStartDate. It refers to endDate option, which also lacks details on the required format. I want to set endDate and newDate based on a s ...

Changing the color of a Highcharts series bar according to its value

Playing around with Highcharts in this plunker has led me to wonder if it's possible to dynamically set the color of a bar based on its value. In my current setup, I have 5 bars that change values between 0 and 100 at intervals. I'd like the colo ...

Steps for Setting Up and Organizing a Fresh Event

My goal is to generate new events (using document.createEvent() or Jquery.Event) by duplicating all essential attributes, and then sending the clone to prevent alterations to the original event. For reference, the source code can be found at http://jsfid ...

"Is there a way to instruct a Kafka client to process messages in the order in which they were

Currently, I am utilizing Kafka client version 2.4.4 for message consumption. const { Kafka, logLevel } = require("kafkajs") const kafka = new Kafka(config) const consumer = kafka.consumer({ groupId: "Default" }) await consumer.connect ...

Exploring ways to incorporate the context value into my component's functionality

Hi, I'm new to TypeScript and I'm facing an issue when trying to use a value I created in my context API. I keep getting the error message "Property 'sidebar' does not exist on type 'IStateContext | null'", even though it exis ...

No data found in Node.js after receiving AngularJS POST request

I've been working on sending a straightforward POST request to my server using AngularJS. The request successfully goes through and reaches the controller on the backend, but strangely, req.data is appearing as undefined. Front End Controller: funct ...

Is it possible for the app-routing.module.ts to have two paths with :/id?

When attempting to access the maindetail and childdetails pages using :/id, I encountered an issue on localhost where the desired card was not displaying on the maindetail page. The goal is to be able to click on the name "aniq" in the dashboard (image 1) ...

Extending a Typescript interface to include the functionality of two different component

When implementing this code snippet, a user will find an output of an <input> element, which works flawlessly: interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> { error?: FieldError; icon?: string; id: string; reg ...

Error message: Icons failing to display in conjunction with template output | 404 error code

I'm trying to display icons based on a search, but I keep getting a 404 error for http://localhost:3000/static when I input a value. My current folder structure looks like this: Root directory > Public > Icons and Root directory > index.js. ...

Encountered an error when attempting to access the property "addOption" on an undefined object

Every time I try to implement search functionality, I keep running into this error: "cannot read property 'addOption' of undefined in JavaScript selectize." I have confirmed that my result array does contain data. This is my JavaScript code: ...

Storing JSON strings in PHP differs from storing them in JavaScript

Using JavaScript, I can save a cookie using JSON.stringify(), which saves the cookie directly like this: '[{"n":"50fb0d0cc1277d182f000002","q":2},{"n":"50fb0d09c1277d182f000001","q":1},{"n":"50fb0d06c1277d182f000000","q":1}] Now, I am sending this t ...

How to associate an object with a component in Angular2/TypeScript using HTTP

I am currently working on displaying a list of item names retrieved from a REST API. By utilizing the map function on the response observable and subscribing to it, I was able to obtain the parsed items object. Now, my challenge is how to bind this object ...

The magic of jQuery when chaining AJAX callback functions

I have a centralized ajaxSuccess callback function that needs to initialize components from various AJAX calls across the project. Here is an example: $(document).ajaxSuccess(function (response, status, xhr) { initComponents(); }); For module-level a ...

What is the best way to transform a string into emojis using TypeScript or JavaScript?

Looking to convert emoji from string in typescript to display emoji in html. Here is a snippet of the Typescript file: export class Example { emoji:any; function(){ this.emoji = ":joy:" } } In an HTML file, I would like it to dis ...

Using Javascript to save basic high scores to a server

My JS game involves updating a score variable. When the game reaches a gameOver state, I want to compare the score to one saved on the server. If the player got a higher score, I'd like to overwrite the previous high score with the new one. If it&apos ...

Issue with Laravel - JavaScript not functioning properly following the passage of a parameter through the route

I am currently working on a website that will display search results from various e-marketplaces. Everything was going smoothly with the JavaScript implementation until I attempted to pass parameters through the route. Once I did that, the results stopped ...

Can HTML/CSS be used to specifically target handheld mobile devices?

I am looking to optimize my video display in HTML by only showing it on desktop browsers. The difference in bandwidth between desktop and mobile devices is affecting the performance of mobile browsers, so I want to target only desktop users. Is there a way ...

Creating an array in TypeScript that supports multiple possible types, recursively, and enforces that all elements must be of the same type

I've been having difficulty creating a type that fits this specific data model: Each node can be: - native type - string, number, boolean, null, undefined - a list containing all the *same type* of nodes - a dictionary of any type of nodes ...

Storing information in firebase using data structuring

While I initially passed an array to Firebase to store data, it proved to be inefficient when querying the data. As a result, I am now considering storing the data in mapping format. However, I am unsure of how to proceed with this. { "ClassDetails": ...

When comparing MongoDB to Javascript, the $regex matching pattern yields varied results

Currently, I am implementing the following $regex pattern in a mongo query: {domain: {$regex: '^(.+\.)?youtube.com$'}} I anticipate that it will match youtube.com as well as sub.youtube.com. However, the issue I have encountered is that i ...