Connection of two objects in coordinate system

379 Views Asked by At

Please take a look at the following picture: illustration

I want to connect two objects by a line. This line has to start and end on an the red lines of the objects and are not allowed (at least it should be prevented) to strike through the objects body (what is inside the blue border).

At the moment I just connect $$(X_{12},\frac{Y_{11}+Y_{12}}{2})$$ with $$(X_{21},\frac{Y_{21}+Y_{22}}{2})$$ or the other way around, depended on the following condition $$X_{11} < X_{21}$$

The condition makes sense to prevent line going through the body of the object.

So the current implementation is just like the picture above.

Problem: You see the dot on the starting point of the line. The problem begins if you have several objects that are connected with several other objects. In worst case you can't differentiate if the dot is on object 1 or object 2 (both is possible).

So the idea is that the dot can move on the red line depending on the position of the objects to prevent overlapping dots (But they are allowed to overlap under specific circumstances e.g. if two objects with which another object is connected with have the same position). An illustration of what it should / could behave like is the following:

illustration

What's the best and simplest solution for this? I'm very open-minded for ideas.

Example Idea: One idea that I had is to map the angle between the objects on the length of the red line, but I really struggle with an mathematical intelligent and working implementation of this.

Hint: Since I want to to implement this in an application I would highly appreciate it, if the idea is relatively good in performance and I want to avoid high level operations like integrals / differentiation (just examples) and too complex data structures like matrices.

Another hint: I don't know if it's relevant but the objects do have the same width $w$. And the blue background colored header also has the same height $h$ for every object. What means that the red line for all objects are the same.

If you have further question or need additional information feel free to leave a comment.

1

There are 1 best solutions below

0
On BEST ANSWER

The problem at hand is at its core quite simple. First, let's draw a central object, and some other objects surrounding it. The red areas are the three active edges of each object, and the blue lines are all the possible connections to the central object. Only connections to the central object are shown. Bars and connections

Note that I assume a coordinate system where the $x$ axis increases right ($R \gt L$), and $y$ axis increases down ($B \gt T$).

Each object has three active sides: left, top, and right. These are marked red in the diagram. (Later on, I shall show how simple it is to distribute the connections on a side; for now, let's just assume they connect to the center.)

Because there is no bottom side, objects (almost) directly above or below must connect to a corner. There are four corners, and these are marked as yellow dots in the right side of the diagram.

The connection may be on the top side, if the other object is above the current one; on the left side, if the other object is to the left of the current one; and on the right side, if the other object is to the right of the current one.

Such generalities are not directly useful, except that we can now construct the rules that define where a connection is allowed. Let's use $L_0$, $T_0$, $R_0$, and $B_0$ for the current object, and $L_i$, $T_i$, $R_i$, and $B_i$ for the other object.

  • If $T_0 \gt B_i$, the connection may be on the top side.

  • If $L_0 \gt R_i$, the connection may be on the left side.

  • If $R_0 \lt L_i$, the connection may be on the right side.

Of the above, both top and either left or right side may be allowed at the same time.

You could work out a limit when to choose top based on the coordinate differences -- say, based on the angle between the two, $\operatorname{atan2}\left(T_0-T_i+B_0-B_i, L_0-L_i+R_0-R_i\right)$. However, if you look at the above illustration, you'll notice that the top side looks lesser used than the side, so in practice, it may be best to simply use the top side when allowed. (That will work especially well when distributing the connections along the entire side.)

If none of the above are allowed, then the connection is to one of the corners.

  • If $T_0 \ge B_i$, the connection is to an upper corner:

    • if ($L_0 \le L_i$) and ($R_0 \le R_i$), the connection is to upper left corner,

    • else if ($L_0 \gt L_i$) and ($R_0 \gt R_i$), the connection is to upper right corner,

    • else if ($L_0 + R_0 \le L_i + R_i$), the connection is to upper left corner,

    • otherwise the connection is to the upper right corner.

  • Otherwise, the connection is to a lower corner:

    • if ($L_0 \le L_i$) and ($R_0 \le R_i$), the connection is to lower right corner,

    • else if ($L_0 \gt L_i$) and ($R_0 \gt R_i$), the connection is to lower left corner,

    • else if ($L_0 + R_0 \le L_i + R_i$), the connection is to lower right corner,

    • otherwise the connection is to the lower left corner.

You can omit the two pairs of inner else cases if all objects have the same width ($R-L$).

Let's assume you have used the above to determine the side or corner for all the connections to all objects. (You'll probably need to use some form of temporary storage in a computer program for this.)

For each side, on each object that has at least one connection, we can distribute them in a visually appealing manner. Because we know which side or corner the connection is to and from, we can use the center of the sides ($(L,T/2+B/2)$ for left side, $(L/2+R/2,T)$ for top side, and $(R,T/2+B/2)$ for right side; corner coordinates are already known) as estimated endpoints for the connection line, and sort the connections according to the slope of the estimated connection line.

If there are $n$ connections to the side, and the other objects $i$ are sorted in counterclockwise order, $1 \le i \le n$, then the $y$ coordinate for connection $i$ on the left side is $$y_i = T_0 + \frac{i}{n + 1} \left(B_0 - T_0\right)$$ and on the right side, $$y_i = B_0 - \frac{i}{n + 1} \left(B_0 - T_0\right)$$ The $x$ coordinate on the top side is $$x_i = L_0 + \frac{i}{n + 1} \left(R_0 - L_0\right)$$

The exact implementation details are a programming problem, not a mathematical one, and some of the logic above might use some tuning based on human preferences.

I personally would next write a test bench, where there is one fixed object in the center, and the user can move another object with respect to the first one. The above logic would be used to determine how the connection should be drawn. If visual problems are found, the $(L,T,R,B)$ of the movable object (and the static object) should be noted, and the implementation fixed. (Assuming there is no logic errors in the above -- there may be.)

After the one-movable-object case is working as desired for all possible relative locations -- almost does NOT cut it! --, I'd add a configurable/addable amount of other objects, and test the interactions, and the connection distribution along the edges.

These tests can easily be written using e.g. Python and Qt5, or any other scripting language. It is not necessary to write such tests in the same programming language as the final application is written in, especially if you still explore the desired logic of how to locate the connection endpoints; simplicity is more important for such tests. (If you split the connection side selection logic into one function, and the object sorting for a side into another, they should be easy to port between programming languages anyway.)