Discovering the Nearest Point to the Mouse Cursor using Three JS Ray Casting

Three.js version r85

While using raycasting in Three JS, a list of points is generated, and I am interested in identifying the point closest to the cursor. It appears that the first point returned is typically the one nearest to the camera.

Is there a method available to determine the distance between the cursor position and a specific point?

The following code snippet is what I currently have for debugging purposes:

var raygun = new THREE.Raycaster();
raygun.setFromCamera(mouse, camera);
var hits = raygun.intersectObjects([plotpoints]);

if (hits.length > 0) {
    scope.remove(dotPlot);
    scope.remove(dotPlot2);

    // All points except the first one - rendered in grey
    dotGeo = new THREE.Geometry();
    for (var i=1; i < hits.length; i++) {
        dotGeo.vertices.push(plotpoints.geometry.vertices[hits[i].index]);
    }
    dotPlot = new THREE.Points(dotGeo, dotMat);
    scope.add(dotPlot);

    // First point highlighted in orange
    var geo2 = new THREE.Geometry();
    geo2.vertices.push(plotpoints.geometry.vertices[hits[0].index]);
    dotPlot2 = new THREE.Points(geo2, dotMat2);
    scope.add(dotPlot2);

    scope.render();
}

This is the current output I'm observing:

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

Answer №1

Success! I solved it using mathematical computations!

One important thing to note is that hits[].points gives the point directly under the cursor, but it doesn't snap to points.

To obtain the precise position of the point, we must first use hits[].index to retrieve the index number of the point/vertex we hit. Then, we can access that specific vertex by utilizing GEOMETRY.vertices[], providing a THREE.Vector3 representation of the vertex point where our raycast landed.

By inputting the index, we can acquire the exact position of each vertex struck by our raycast:
GEOMETRY.vertices[hits[i].index]

This method offers basic snapping functionality to vertices.

Note: When employing THREE.LineSegments, the outcome will always be the starting point, not the end point. To get the ending point, simply add 1 to the index value:

GEOMETRY.vertices[hits[i+1].index]

In order to snap directly to the vertex nearest to the cursor, we need to determine the vertex with the shortest perpendicular distance from the ray of the raycaster. This involves using a cross product of two vectors—a math concept rather than a programming one. For further understanding on this topic, look up something like: perpendicular distance from a point to a line

I borrowed and adapted the code from this query:

And here's the resulting code snippet:

// Variables for comparison
var smallestDist = 99;
var smallestPointIndex = 0;

// Declaring variables outside the loop for efficiency
var m_ray = raycaster.ray;
var raydir = m_ray.direction; 
var origin = m_ray.origin;
var hitray = new THREE.Vector3(0,0,0);
var dist = 1;

// Traverse all points to find the closest one
for (var i=0; i<hits.length; i++){
    // Mathematical calculations at work
    hitray.subVectors(plotpoints.geometry.vertices[hits[i].index], origin);
    dist = new THREE.Vector3().crossVectors(raydir, hitray).lengthSq();

    // Keeping track of the nearest point
    if (dist < smallestDist) {
        smallestDist = dist;
        smallestPointIndex = i;
    }
}

// Now we have the single closest point

That's the solution :)

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

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

Change the text of a button by using an input field

How can I dynamically update button text based on input field value? <input class="paymentinput w-input" type="tel" placeholder="0" id="amount-field"> <button id="rzp-button1" class="paynowbutton w-button">Pay Now</button> I want the bu ...

Issues arise when attempting to utilize jQuery to print a string once a button is pressed

I am trying to display a string on the webpage when the user clicks a button. Below is the HTML code: <p> <h1 class="text-center" id="notif"> </h1> </p> Here is the relevant part of the script: $("#btn_My").click(functio ...

What is the best way to retrieve the duration of an object tag using JavaScript or jQuery?

My goal is to determine the duration and length of only mp4 type videos. Although I used the video tag to retrieve these values, it does not support mp4 files. Despite several attempts, I was unable to get the video tag to play only mp4 files, as it stric ...

Can CSS Variables be changed globally using jQuery?

How can I dynamically change CSS Variables globally using jQuery? Check out this code snippet: $("div").click(function() { // Update the global variable "--text_color: rgb(0, 0, 255);" to a new value like "--text_color: rgb(0, 255, 255);" }); :roo ...

Gradually vanishing words while they glide across the screen

I want to achieve a similar effect seen in the game A Dark Room. The text in the game serves two purposes which I am trying to replicate: The new text is added above the old text instead of below it, pushing the older text down the page as the game progr ...

Encountering a MiniCssExtractPlugin error while trying to build with npm

I have encountered an issue while trying to execute "Npm Run Build" on my reactjs website. The error message I keep receiving is as follows: /usr/local/lib/node_modules/react-scripts/config/webpack.config.js:664 new MiniCssExtractPlugin({ ^ TypeErr ...

Can Vue.js automatically refresh the display when there are changes in a third-party JSON file?

I'm attempting to achieve a specific goal using Vue, but I'm uncertain if it's feasible given my current struggles in obtaining the desired outcome: An API endpoint returns an array containing multiple objects. While I am able to successfu ...

Refreshing the Table to Update Data

I am working on a jquery application that includes a table with time and number fields. My goal is to increment the values every 3 seconds by creating a function to update the numbers automatically. Initially, the data in the table looks like this: Kobe ...

Unable to create the complete PDF file using html-pdf in a NodeJS environment

When trying to create a PDF from an HTML template, I am encountering some difficulties. While it works with static entries, I want to generate the PDF for multiple items that can vary each time. I feel like I might be overlooking something, so any suggesti ...

Is there a way to simulate a click event (on a file type input) within a promise?

I've been struggling with this issue for a long time and have not been able to find a solution. The problem arises when attempting to trigger a click event on a file input type from within a promise. When I directly trigger the event inside the promis ...

Creating a personalized pivot-table using the WebDataRock Javascript library with a unique configuration based on a

I'm having trouble getting this demo to work with the "hierarchy" parameter. Even when I specify the parameter value, it seems to apply the condition to the entire hierarchy chain. "conditions": [{ "formula": "#val ...

How would you go about creating a VueJS component that displays a table with a set number of columns and automatically distributes the cells within them?

Hey there! I'm currently working with a VueJS component that looks like this: <template> <div> <table> <tbody> <tr v-for="(item, index) in items" :key="index"> <t ...

Creating a three-row CSS layout where the middle row aligns to the right side

I am working on developing a mobile device layout with 3 blocks. The first and third blocks contain text fields, while the second block is filled with a map. However, all of my blocks don't look good when they are too wide. The browser window can have ...

Save the output of a knex query to a variable

I'm struggling to assign the result of a select query using Knexjs to a variable. Here is my code: function getAllCategories() { let categories; categories = database.from("categories").select("category").then(function (rows) { for (let row of ro ...

Display the json encoded result of a MySQL SUM() query

I am attempting to use JSON to print the total sum of a price. Here is my current approach: $query="SELECT SUM(cost) FROM `Service`"; $result = mysql_query($query); $json = array(); while($row = mysql_fetch_array($result)) { $json[&a ...

Accepting multiple file inputs in a form without using a selector, but instead utilizing the 'this' keyword or finding an alternative approach

When dealing with single file uploads, you can access the file input using this.image <form id="form"> <input type="file" name="image"> <input type="submit" name="submit"> </form> $ ...

Adjusting the height of an element as you scroll will activate the scroll event

One issue I'm facing is with adding a class to my header. The goal is to reduce the height of the top part of the header when the user scrolls down and then remove the class when they scroll back up. While this functionality is working, there is an un ...

Do you know if there is a setting in prettier that allows line breaks to be preserved?

Encountering an issue with the prettier extension in VS Code, Whenever I enter the following code: const result = await pool .request() .query('select NumberPlate, ID, TimeStamp from RESULTS order by ID'); and save the file, it con ...

Is the npm mqtt module continuously running but not performing any tasks?

I'm relatively new to the world of JS, node.js, and npm. I am attempting to incorporate a mqtt broker into a project for one of my classes. To gain a better understanding of how it functions, I installed the mqtt module from npm. However, when I tried ...

Issue with Electron-vue: 'compute:' not functioning as expected

My attempt to create a simple example using the element-ui library was not successful. There are two 'switches' with different active state values: 2 and 1. The values of the switches are supposed to be displayed in <p>{{sw1}}</p> and ...