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:

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.

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

Observables waiting inside one another

I've encountered an issue where I need to return an observable and at times, within that observable, I require a value from another observable. To simplify my problem, let's consider the following code snippet: public dummyStream(): Observabl ...

What is causing the data in the hierarchy table to be invisible?

I am attempting to build a hierarchical table using Vue.js as the foundation. However, I want the table to remain hidden with no data displayed. The issue seems to be within this section of code: <tr v-if="item.childrenVisible" v-for="chi ...

Issue: TypeError - 'process.env' can only accept a configurable while installing windows-build-tools

Unable to successfully download installers. Encountered an error: TypeError: 'process.env' can only accept a configurable, writable, and enumerable data descriptor. I attempted to resolve this issue by running the command npm install --global wi ...

How come the array's length is not appearing on the browser screen?

Code: initialize: function() { this.todos = [ {id: 100, text: 'Rich'}, {id: 200, text: 'Dave'} ]; }, activeTodos: function() { this.todos = this.todos.length(function() { return this.todos; }); ...

Is it possible for me to determine whether a javascript file has been executed?

I am currently working with an express framework on Node.js and I have a requirement to dynamically change the value (increase or decrease) of a variable in my testing module every time the module is executed. Is there a way to determine if the file has ...

An effective method to showcase the HTML content retrieved by getElementsByClassName using JSON.parse()

Can someone help me modify this code so that it displays the value of favFood? It currently works with getElementById but not getElementsByClassName, and I want to use a class: server file - ProcesssingFileOnServer.php: <?php $myObj = new stdClass(); ...

The Mongoose connection pool has been shut down

I am currently working on a web application that retrieves data from a Mongo database. I have set up 2 cron jobs using Heroku scheduler to run daily and perform tasks on a remote database. The issue arises when these jobs need to conclude and close the con ...

"Implementing a seamless transition effect on two slideshows using jQuery's fadeslideshow

I currently have a homepage featuring a fadeslideshow with 5 slides. The fadeslideshow plugin being used can be found at http://plugins.jquery.com/project/fadeslideshow. On the homepage, there is also a menu bar with various menu items. When a user clicks ...

Each time the button is clicked, the settings and values will rotate, creating a new

I'm looking to create a button system that transitions from "unmarked" to "form" and updates the database with each click. I want users to be able to cycle through the buttons, triggering a post request via ajax to update the associated ID in the data ...

Show a mpld3 graph in an HTML page using the Django framework

Incorporating mpld3 to showcase matplotlib charts within an HTML page through django has been my recent focus. I utilize the mpld3.fig_to_dict method to convert a matplotlib figure into a JSON string and store it in a variable. However, I am encountering ...

Organizing multiple <image> tags into an array with Javascript - a beginner's guide!

My HTML file contains multiple images. When a user clicks on them, their IDs should be captured without any issues. I am looking for help with the following tasks: 1) Storing all clicked image IDs in an array For example: array = img01 ; array = img ...

What is the best way to present a unique page overlay specifically for iPhone users?

When browsing WebMD on a computer, you'll see one page. However, if you access it from an iPhone, not only will you be directed to their mobile page (which is easy enough), but they also display a special overlay with a "click to close" button prompti ...

Switch up image origin when image reaches screen boundary

I am trying to create a DVD screensaver with changing images each time it hits the edge, but I can't seem to get it to work. I've attempted using the code snippet below: var img = document.getElementById("myImage"); img.src = 'img/new-image. ...

What is the maximum number of JSON responses that can be handled by AJAX?

Upon entering the site, I am attempting to receive a JSON as an AJAX response. However, I am curious if there is a limit to the size of the object I can retrieve - whether through a GET or POST request? $http({ method: 'POST', url: &apos ...

What is the best way to set up the login page and logged-in homepage using Node, Express, and Passport with the "/" route?

I am currently in the process of developing an application using Node.js, Express.js, and Passport.js. My goal is to create a seamless user experience on the homepage where if you are not logged in, you will see a login form (with potential for additional ...

Utilizing Ajax to dynamically load files within the Django framework

My current project involves working with Django, specifically a feature that requires loading a file and displaying its content in a textarea. Instead of storing the file on the server side or in a database, I am exploring the use of AJAX to send the file ...

One-of-a-kind npm module for typescript

As part of my project, I am enhancing an existing library to make it compatible with TypeScript. To showcase this modification, I have condensed it into a succinct Minimal working example The specified requirements To ensure backward compatibility, the li ...

Utilizing HTML's multiple input type color feature to save selected colors directly to the database

I am currently using the input type color to select colors for customizing my site. I save the selected color to a database and then retrieve it to apply it to different areas of the site. This works well for a single input type color, but now I have mul ...

An issue was encountered in the node_modules folder while attempting to access the 'Exclude' name in the lodash collection file. The error message reads: (1783,24): error TS2304: Cannot

When attempting to execute the ng serve command, I encountered an error. See below for more details. ERROR in node_modules/@types/lodash/common/collection.d.ts(1783,24): error TS2304: Cannot find name 'Exclude'. ... (error list continued) .. ...

Transform a section of text into JSON format to utilize in DataTables

Currently, I am utilizing DataTables and Leaflet in my project. The data displayed below needs to be represented on my screen using Datatables. Specifically, I would like to convert it into JSON format without including the {....} part. How should I proc ...