A guide on assigning specific (x, y) coordinates to individual IDs within the tree structure

When attempting to calculate the positions of each ID in order to arrange them hierarchically on the canvas, I encounter some challenges. Whether it's organizing them into a tree structure or multiple trees resembling a forest, one restriction is that cycles are not allowed and each box should measure 240 x 100.

I kickstart this process with the connections I receive: connectionsArr.

The function graphWithTopLeft plays a pivotal role in the position calculation for each ID. However, in my test case, certain IDs end up stacked atop one another and the spacing between them doesn't meet my desired layout.

In any scenario, my objective is to achieve an outcome similar to this:

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

Although I'm aware that these algorithms can be quite complex, I aim to refrain from relying on external libraries for assistance.

A massive thank you in advance to those who have helped or plan to assist!

Check out the code example here: codesandbox & also here.

const connectionsArr = [
  { sourceId: 1, targetId: 2 },
  { sourceId: 1, targetId: 3 },
  { sourceId: 1, targetId: 4 },

  { sourceId: 2, targetId: 5 },
  { sourceId: 2, targetId: 6 },
  ...
   (The rest of the JavaScript code remains unchanged) ... 
<html>
  <head>
    <title>Sandbox</title>
    <meta charset="UTF-8" />
    <style>
      body {
        background: black;
        margin: 0;
      }
    </style>
  </head>
  
  <body>
    <canvas id="paper" width="10000" height="10000"></canvas>
    <script src="src/index.ts"></script>
  </body>
</html>

Answer №1

Apologies for using an answer instead of a comment due to length constraints.

This answer fulfills the specified requirements:

const unique = (xs) => [... new Set (xs)]

const vertices = (edges) => 
  unique (edges .flatMap (({sourceId, targetId}) => [sourceId, targetId])) .sort ((a, b) => a - b)

const coordinates = (edges) =>
  vertices (edges) .map (v => ({id: v, location: {x: 0, y: 0}}))

const connectionsArr = [{sourceId: 1, targetId: 2}, {sourceId: 1, targetId: 9}, {sourceId: 9, targetId: 3}, {sourceId: 3, targetId: 5}, {sourceId: 3, targetId: 7}, {sourceId: 5, targetId: 6}, {sourceId: 6, targetId: 10}, {sourceId: 11, targetId: 12}]

console .log (coordinates (connectionsArr))
.as-console-wrapper {max-height: 100% !important; top: 0}

Each vertex in the graph is returned with properties id and location, containing numeric x and y values as shown below:

[
  {id: 1,  location: {x: 0, y: 0}},
  {id: 2,  location: {x: 0, y: 0}},
  {id: 3,  location: {x: 0, y: 0}},
  {id: 5,  location: {x: 0, y: 0}},
  {id: 6,  location: {x: 0, y: 0}},
  {id: 7,  location: {x: 0, y: 0}},
  {id: 9,  location: {x: 0, y: 0}},
  {id: 10, location: {x: 0, y: 0}},
  {id: 11, location: {x: 0, y: 0}},
  {id: 12, location: {x: 0, y: 0}},
]

If objections arise regarding box placements, adjustments can be made easily by modifying the coordinates function.

const coordinates = (edges) =>
  vertices (edges) .map ((v, i) => ({id: v, location: {x: i, y: i}}))

To avoid overlapping boxes, further changes can be implemented:

const coordinates = (edges) => {
  const vs = vertices (edges)
  const angle = 2 * Math.PI / vs .length
  return vs .map ((v, i) => ({id: v, location: {
    x: Math .round (150 * Math .cos (i * angle)) + 300, 
    y: Math .round (150 * Math .sin (i * angle)) + 300, 
  }}))
}

The updated approach ensures non-overlapping positions of boxes within the graph.

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

If this does not align with expectations, consider providing clearer specifications before seeking assistance on graph layout optimizations.

  • Determine if the edges form a tree or a forest.

  • Consider the presence of cycles in the graph.

  • Evaluate if the graph is planar without edge intersections.

  • Define preferred node layouts for accurate visualization.

Prioritize refining requirements and exploring initial attempts for effective solutions to graph representation challenges.

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

Encountering difficulties while attempting to deploy NodeJS application on Heroku

When attempting to deploy my nodejs app, I encountered the following error: 2019-11-25T18:16:16.927748+00:00 app[web.1]: > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c9a8a7a6a7b0a4a6bcbae4afa6bbbca4e4ada0baaabcbabaa0a6a ...

Activate the text area message by clicking on the href link

I am currently working on customizing the intercom plugin for a WordPress site. My goal is to have a message triggered when a user clicks on a hyperlink, essentially simulating the enter key press in a textarea. Here is the code snippet that I am using: ...

Merging two arrays of objects from the same response in JavaScript

How can I efficiently merge two arrays of objects from the same response? let data = [{ "testLevel":"mid", "testId":"m-001", "majorCourse": [ { "courseName":"C++" ...

In Typescript, develop a tuple type that repeats itself

My API, specifically the Elasticsearch bulk API, requires an array of operations where each operation is a pair. The first element in the pair specifies the operation (index, update, create, delete) and the second element contains the data (excluding delet ...

Issues with react-bootstrap component Switches functionality not operating as expected

It looks like the bootstrap switches are not functioning properly. Even the documentation version is not working as expected <Form> <Form.Check type="switch" id="custom-switch" label="Check this switch" /> <Form.Check ...

Verify Ionic storage for an item

Is there a way to display an introductory slider only once for new users when they install the app? Solution If the user installs the app, set an item in the storage called intro with a value of false When the user opens the app, check the intro item. I ...

The selector-triggered JQuery event being invoked by my script

Facing an issue while trying to invoke my jQuery event. I am working with 2 jQuery events: $element.on('click', function (e) { ... }); $element.on('click', '.toggle', function (e) { ... }); My question is how can I trigge ...

Tips for modifying the background color of all elements ahead of the element I have selected within a grid

https://i.stack.imgur.com/cW4Lp.png I'm trying to achieve a functionality where clicking on the 20th numbered block changes everything before it to light orange. I have a sandbox code snippet attached and would appreciate any guidance on what needs t ...

The click-handler method in VueJS Paginate Component fails to activate

I'm currently working on a Vue Component code that involves pagination for a list. The pagination seems to be working fine, except for the issue I encounter when trying to navigate to the next page, which in this case is page 2. I've added a cons ...

Issue: [Issue: ENOENT: the file or directory './1695556319341.mp3' does not exist]

I am currently facing an issue while trying to convert an mp4 file to an mp3 file and then uploading it directly to Firebase storage without saving it locally on my machine. The error I encounter is "Error: [Error: ENOENT: no such file or directory, open ...

AngularJS allows for dynamic routing within applications

I'm a beginner with AngularJs and I've run into an issue where the URL changes but the page remains the same. Any help would be greatly appreciated. Here is my configuration: var app = angular.module('MyApp', ['ngResource',& ...

Tap on the HTML5 video to exit the fullscreen mode

Objective I have successfully implemented a fullscreen video setup that triggers when a link is tapped on a mobile device. To maintain a clean aesthetic, I have hidden the HTML5 video controls using CSS. The desired functionality includes closing the full ...

We are unable to create a 'Worker' as Module scripts are not yet supported on DedicatedWorkers in Angular 8

Error An error has occurred in the following files: node_modules/typescript/lib/lib.dom.d.ts and node_modules/typescript/lib/lib.webworker.d.ts. Definitions of various identifiers conflict with those in other files, leading to modifier conflicts and dup ...

"Using JavaScript to extract a portion of the URL and perform a redirect

I am attempting to extract a specific part of the URL and then redirect to that particular section. Essentially, what I want is for a script to generate a link that will be opened. This link would appear as . My goal now is to extract the portion of the ...

The confirm alert from Material UI is being obscured by the dialog

How can I ensure that a material ui dialog does not hide the alert behind it when confirming an action? Is there a way to adjust the z index of the alert so that it appears in front of the dialog? import Dialog from "@material-ui/core/Dialog"; i ...

When my script is located in the head of the HTML page, I am unable to

My goal is to make my JavaScript code function properly when I insert it into either the head or body elements of an HTML document. Let's look at some examples: First, I insert the script into the body as shown in this example (works correctly): ...

What is the reason for using a string as the index of an array in the following code?

var arrayOfNumbers = [1, 2, 3, 4, 5, 6, 78]; for(var index in arrayOfNumbers){ console.log(index+1); } The result produced by the given code snippet is as follows: 01 11 21 31 41 51 61 What is the reason behind JavaScript treating these ...

"Enhance the functionality of material-table by incorporating a multi-select feature

My data management has been made easier with Material-Table, but I have encountered a small issue. The code below shows how I currently get a select menu for my data. However, I am looking to have a multiselect menu instead, allowing me to save more than o ...

The Google Books API has reached its limit for requests

Encountering a rate limit exceeded error from the Google Books API while using this demo: To reproduce, open the developer console in Chrome and perform some searches. The rate limit errors will be displayed in the console. [],"lazyUpdate":null},"status" ...

There are a total of 152 issues found in the index.tsx file within the react

Despite everything working correctly, I am continuously encountering these errors. Is this a common occurrence? What steps can I take to resolve them? I have developed my react application using Javascript instead of Typescript; however, I don't belie ...