What are some effective methods for locating dual edges within a Half-Edge (DCEL) data structure?

I have implemented a HalfEdge data structure to represent the connectivity between faces in my mesh.

While importing an external model, I construct the HalfEdge structure. However, for meshes with numerous triangles, the construction process is time-consuming.

The most time-consuming part of the process seems to be linking the half-edges together. I am seeking advice on how to enhance my algorithm.

Below is the code used to initialize the data structure. The first loop creates a Face with vertex data and stores the corresponding HalfEdges in a separate array for later use.

The second loop aims to identify matching pairs of HalfEdges (twins).

I monitored the timestamps before and after each step and observed that the second loop significantly slows down the process.

Time stamps are as follows:

start constructing DCEL 14:55:22

start making faces 14:55:22

end making faces 14:55:22

/* This is where the process takes time... almost 6 seconds for a mesh with 13000 triangles */

start linking halfEdges 14:55:22

end linking halfEdges 14:55:28

end constructing DCEL 14:55:28

Here is the actual code snippet:

console.log('start constructing DCEL', new Date().toTimeString());

// Initialize Half-Edge data structure (DCEL)
const initialFaceColor = new THREE.Color(1, 1, 1);
const { position } = geometry.attributes;
const faces = [];
const edges = [];
let newFace;

console.log('start making faces', new Date().toTimeString());
for (let faceIndex = 0; faceIndex < (position.count / 3); faceIndex++) {
  newFace = new Face().create(
    new THREE.Vector3().fromBufferAttribute(position, faceIndex * 3 + 0),
    new THREE.Vector3().fromBufferAttribute(position, faceIndex * 3 + 1),
    new THREE.Vector3().fromBufferAttribute(position, faceIndex * 3 + 2),
    faceIndex);
  edges.push(newFace.edge);
  edges.push(newFace.edge.next);
  edges.push(newFace.edge.prev);
  newFace.color = initialFaceColor;
  faces.push(newFace);
}

console.log('end making faces', new Date().toTimeString());
console.log('start linking halfEdges', new Date().toTimeString());

/**
  * Find and connect twin Half-Edges
  * 
  * if two Half-Edges are twins:
  * Edge A   TAIL ----> HEAD
  *           =          =
  * Edge B   HEAD <---- TAIL
  */
let currentEdge;
let nextEdge;
for (let j = 0; j < edges.length; j++) {
  currentEdge = edges[j];

  // Skip this edge if it already has a twin
  if (currentEdge.twin !== null) continue;

  for (let k = j + 1; k < edges.length; k++) {
    nextEdge = edges[k];

    if (nextEdge.twin !== null) continue;

    if (currentEdge.head().equals(nextEdge.tail()) 
      && currentEdge.tail().equals(nextEdge.head())) {
          currentEdge.setTwin(nextEdge);
    }
  }
}

console.log('end linking halfEdges', new Date().toTimeString());
console.log('end constructing DCEL', new Date().toTimeString());

What optimizations can be made to speed up the search for twin edges?

Answer №1

To simplify the process, I would suggest hashing and searching for edges using the following code snippet:

function hash(p1, p2) {
  return JSON.stringify(p1)+JSON.stringify(p2);
}
const lookup = {}
for (let j = 0; j < edges.length; j++) {
  lookup[hash(edge.head(), edge.tail())] = edge;
}
for (let j = 0; j < edges.length; j++) {
  const twin = lookup[hash(edge.tail(), edge.head())];
  !edge.twin && twin && !twin.twin && edge.setTwin(twin);
}

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

The correct way to extract a jwt token from headers and integrate it into an express application

After successfully implementing both the frontend and backend in express.js with authentication and authorization using JWT, I have confirmed that the JWT token is being properly set upon login. You can see the auth-token key in the image below: https://i ...

Remove the content located beside an input element

Seeking assistance for a straightforward query: Snippet of code: <span> <input id="elemento_20_1" name="elemento_20_1" class="elemento text" size="2" maxlength="2" value="" type="text"> / <label for="elemento_20_1">DD</label> < ...

CSS styling doesn't take effect until the page is reloaded due to the failure of cssText

After generating a new list item, it appears that the CSS styling is not being inherited until the page is reloaded. Even though I have added styling using cssText dynamically, it doesn't seem to be working as expected. I've attempted using cssT ...

Obtain the selected dropdown value and transfer it to the controller seamlessly without the need to reload the page

Currently, I am facing an issue with two dropdown lists in a bootstrap modal - CATEGORY and SUBCATEGORY. The values in the SUBCATEGORY list depend on the selection made in the CATEGORY list. My goal is to retrieve the selected value ID and pass it to my co ...

Update the CSS styles using properties specified within an object

Is it possible to dynamically apply CSS styles stored in a JavaScript object to elements? For instance, can we change the width and background of a basic <div> element: <div id="box"></div> <button id="btn">click me</button> ...

What steps can I take to stop my browser from displaying the "waiting for MyHostName" message while performing an ajax Post/Get operation?

Whenever I access a website using Chrome, a message appears in the status bar saying "Waiting for MyHost name" along with an Ajax Loader circle in the browser tab. Here is a javascript function that I am working with: function listen_backend_client_reques ...

Printing from a Windows computer may sometimes result in a blank page

Looking to incorporate a print button into an HTML page, I'm facing an issue. The majority of the content on the page should not be included in the printed version, so my approach involves hiding everything in print and then showing only the designate ...

Setting up the current user's location when loading a map with Angular-google-maps

I am currently utilizing the library in conjunction with the IONIC framework. To manually set the center of the map, I have implemented the following code snippet: .controller('mainCtrl', function($scope) { $scope.map = { cen ...

What is the best way to store the outcome of a promise in a variable within a TypeScript constructor?

Is it possible to store the result of a promise in a variable within the constructor using Typescript? I'm working with AdonisJS to retrieve data from the database, but the process involves using promises. How do I assign the result to a variable? T ...

I am having issues with this knob not updating, and the reason for this problem is unknown to me

Within my PHP code, I am utilizing the following: <?php @include_once('fields.php'); $gg = fetchinfo("val","inf","n","current"); $mm = fetchinfo("val","info","n","max"); $cc = fetchinfo("num","games","id",$gg); $percent = $cc / $mm * 100; ...

Sharing environment variables between a React app and an Express.js server that hosts it as a static site can be achieved by setting

My static site react app is hosted under an express server project in a folder called client/build. The oauth redirect uris point to the express server for token retrieval. The react app redirects users to the oauth endpoint, which is also referenced by th ...

Disable the enter key from closing the alert box

Is there a way to ensure that a user must manually close a JavaScript alert, preventing them from simply closing it by pressing enter? (It may sound suspicious, but in the application users frequently press enter and I need to make sure they don't ov ...

How can I integrate custom PHP pages into Odoo Community 12?

I am looking for a way to integrate my custom PHP webpages with the login page of Odoo Community that is already set up and functioning on my server. I want specific users to be redirected to my custom pages after logging in. Any suggestions on how to ac ...

Determining the specific condition that failed in a series of condition checks within a TypeScript script

I am currently trying to determine which specific condition has failed in a set of multiple conditions. If one does fail, I want to identify it. What would be the best solution for achieving this? Here is the code snippet that I am using: const multiCondi ...

Ways to update the cart page automatically after quantity changes in Shopify

I have made some updates to the Approach and now I am using JavaScript. I've also updated the script and its logic, which is pasted below. Please take a look and see if you can assist me. I am trying to display information on the top of the cart page ...

The specific module 'franc' does not have the export named 'default' as requested

Every time I attempt to use the franc package, I encounter the following error message: "The requested module 'franc' does not provide an export named 'default'." Unfortunately, I am unsure of what this means, despite trying to resolve ...

Utilize AngularJS to bind keys to arrays

Hey there, I have an array that looks like this: $scope.Selectedgroups =[183,184,24] I want to convert it to the format shown below: [{groupId:183},{groupId:184},{groupId:24}]; I've been trying to convert it using a for loop: var groups=[] ...

Node.js: Capturing requests and responses for console logging

I'm currently working on a Hapi server using Good to log all requests and responses to the console. I've been able to successfully log responses but I'm facing issues with logging the body of the response, and for requests, I'm not gett ...

Leveraging D3.js in combination with Total.js and node.js

I have been attempting to utilize total.js in conjunction with D3 for creating a tree visualization. However, I am encountering issues when trying to download D3. This is what I do: npm install D3 Upon running the above command, I receive the following e ...

The deletion request using the form in Express is experiencing issues and not functioning properly

When attempting to delete data from a database using a form in node.js and express, I am encountering issues with the deletion process. It seems that there are only two methods available - get and post - and no specific delete method. router.js code rout ...