Sometimes when using a layout algorithm such as layout.fruchterman.reingold you can get some nodes that are outliers in the sense that they extend out disproportionately from the rest of the structure. Does anyone know how to impose a maximum length on edges (such as =1) so that the edge cannot exceed a max length and therefore remove these outliers?
l <- layout.fruchterman.reingold(subgraph)
BTW, I'm aware of an employ a scale factor already to regin things in:
l <- layout.fruchterman.reingold(subgraph) * scaleFactor
There is no built-in functionality for that in the Fruchterman-Reingold algorithm (and I suspect that using xmin, ymin, xmax and ymax would not work because it might simply "compress" the non-outlier part of the network to make more space for the outliers), but you can probably experiment with edge weights. When the FR layout algorithm is used with weights, the algorithm will strive to make edges with a larger weight to be shorter. You could probably try setting the weights incident on "outlier" vertices (i.e. vertices with degree=1 or 2) to a smaller value. Another possibility is to make the edge weights depend on the degrees of both endpoints such that smaller degrees are mapped to smaller values but larger degrees are not mapped to disproportionately larger values - maybe the geometric mean of the degrees of the two endpoints could be useful here. But there is no "universal" solution as far as I know so you'll have to experiment a bit.
When asking a question with an example that is dependent on non-base functions, please remember to note which package they live in.
(for those wondering, it's in igraph).
igraph's documentation for the fruchterman-reingold layout method contains, in "arguments":
xmin,xmax
The limits for the first coordinate, if one of them or both are NULL then no normalization is performed along this direction.
ymin,ymax
The limits for the second coordinate, if one of them or both are NULL then no normalization is performed along this direction.
zmin,zmax
The limits for the third coordinate, if one of them or both are NULL then no normalization is performed along this direction.
...so, set limits on x and y? Z isn't necessary unless it's a three-dimensional graph.
Related
Okay first I wasn't sure if this was better suited to the MathSO so apologies if it needs migrating.
I have a 3D grid of points (representing the centers of voxels) with pitch varying in each dimension, but regular. For example resolution may be 100 by 50 by 40 for a cube shaped object.
Giving me nVox = 200,000.
For each voxel - I would like to cast (nVox - 1) rays, ending at the center, and originating from each of the other voxels.
Now there is obviously a lot of overlap here but I am having trouble finding how to calculate the minimum set of rays required. This sounds like a problem that has an elegant solution, I am however struggling to find it.
As a start, it is obvious that you only need to compute
[nVox * (nVox - 1)] / 2
of the rays, as the other half will simply be in the opposite directions. It is also easy in the 2D case to combine all of those parallel to one of the grid axes (and the two diagonals).
So how do I find the minimum set of rays I need, to pass from all voxel centers, to all others?
If someone could point me in the right direction that'd be great. Any and all help will be much appreciated.
Your problem really isn't about three dimensions in any specific way. All the conceptual complexity is present in the two dimensional case.
Instead of connecting points individually, think about the set of lines that pass through at least two points on your grid. Thus instead of thinking about points initially, think about directions. For 2-D these directions are slopes of lines. These slopes have to be rational numbers, since they intersect points on an integer lattice. Since you have a finite lattice, the numerator and the denominator of the slope can be bounded by the size of the figure. So your underlying problem is enumerating possible slopes for rational numbers of bounded "height" (math jargon).
There's an algorithm for that. It's the one used to generate the Farey sequence of reduced fractions. If your figure is N pixels wide, there will (in general) be a slope with denominator N in the somewhere, but there can't be a slope in reduced form with denominator >N; it wouldn't fit.
It's easier to deal with slopes between 0 and 1 directly. You get the other directions by two operations: negating the slope and by interchanging axes. For three dimensions, you need two slopes to define a direction.
Given an arbitrary direction (no necessarily a rational one as above), there's a perpendicular linear space of dimension k-1; for 3-D that's a plane. Projecting a 3-D parallelpiped onto this plane yields a hexagon in general; two vertices project onto the interior, six project to the vertices of the hexagon.
For a given discrete direction, there's a minimal bounding box on the integer lattice such that two opposite vertices lie along that direction. As long as that bounding box fits within your original grid, each of the interior points of the projection each correspond to a line that intersects your grid in at least two points.
In summary, enumerate directions, then for each direction enumerate where that direction intersects your grid in at least two points.
I'm working in OpenCV but I don't think there is a function for this. I can find a function for finding affine transformations, but affine transformations include scaling, and I only want to consider rotation + translation.
Imagine I have two sets of points in 2d - let's say each set has exactly 50 points.
E.g. set A = {x1, y1, x2, y2, ... , x50, y50}
set B = {x1', y1', x2', y2', ... , x50', y50'}
I want to find the rotation and translation combination that gets closest to mapping set A onto set B. I guess I would define "closest" as minimises the average distance between points in A and corresponding points in B. I.e., minimises the average distance between (x1, y1) and (x1', y1'), etc.
I guess I could use brute force testing all possible translations and rotations but this would be extremely inefficient. Does anyone know a simpler way?
Thanks!
This problem has a very elegant solution in terms of singular value decomposition of the proximity matrix (distances between pairs of points). The name of this is the orthogonal Procrustes problem, after the Greek legend about a fellow who offered travellers a bed that would fit anyone.
The solution comes from finding the nearest orthogonal matrix to a given (not necessarily orthogonal) matrix.
The way I would do it in Excel is to make a couple columns representing the points.
Cells representing rotation/translation of a set (no need to rotate and translate both of them).
Then columns representing those same points rotated/translated.
Then another column for the distance between the points of the rotated/translated points.
Then a cell of the sum of the distances between points.
Finally, use Solver to optimize the rotation and translation cells.
If you fix some rotation you can get an answer using ternary search. Run search in x and for every tested x run it in y to get the best value. This will give you the correct answer since the function (sum of corresponding distances) is convex (this can be proved through observing that restriction of the function to any line is a one-dimensional convex function; and the last is a standard fact: the sum of several convex functions is convex).
Instead of brute force over the angle I can propose such a method based on the ternary search. Choose some not very large step S. Compute the target function for every angle in (0, S, 2S,...). Then, if S is small enough, we can exclude some of segments (iS, (i + 1)S) from consideration. Namely ones with relatively large values of function with angles iS and (i + 1)S. Being implemented carefully this can give an answer and can do it faster than brute force.
If I have a mesh of triangles, how does one go about calculating the normals at each given vertex?
I understand how to find the normal of a single triangle. If I have triangles sharing vertices, I can partially find the answer by finding each triangle's respective normal, normalizing it, adding it to the total, and then normalizing the end result. However, this obviously does not take into account proper weighting of each normal (many tiny triangles can throw off the answer when linked with a large triangle, for example).
I think a good method should be using a weighted average but using angles instead of area as weights. This is in my opinion a better answer because the normal you are computing is a "local" feature so you don't really care about how big is the triangle that is contributing... you need a sort of "local" measure of the contribution and the angle between the two sides of the triangle on the specified vertex is such a local measure.
Using this approach a lot of small (thin) triangles doesn't give you an unbalanced answer.
Using angles is the same as using an area-weighted average if you localize the computation by using the intersection of the triangles with a small sphere centered in the vertex.
The weighted average appears to be the best approach.
But be aware that, depending on your application, sharp corners could still give you problems. In that case, you can compute multiple vertex normals by averaging surface normals whose cross product is less than some threshold (i.e., closer to being parallel).
Search for Offset triangular mesh using the multiple normal vectors of a vertex by SJ Kim, et. al., for more details about this method.
This blog post outlines three different methods and gives a visual example of why the standard and simple method (area weighted average of the normals of all the faces joining at the vertex) might sometimes give poor results.
You can give more weight to big triangles by multiplying the normal by the area of the triangle.
Check out this paper: Discrete Differential-Geometry Operators for Triangulated 2-Manifolds.
In particular, the "Discrete Mean Curvature Normal Operator" (Section 3.5, Equation 7) gives a robust normal that is independent of tessellation, unlike the methods in the blog post cited by another answer here.
Obviously you need to use a weighted average to get a correct normal, but using the triangles area won't give you what you need since the area of each triangle has no relationship with the % weight that triangles normal represents for a given vertex.
If you base it on the angle between the two sides coming into the vertex, you should get the correct weight for every triangle coming into it. It might be convenient if you could convert it to 2d somehow so you could go off of a 360 degree base for your weights, but most likely just using the angle itself as your weight multiplier for calculating it in 3d space and then adding up all the normals produced that way and normalizing the final result should produce the correct answer.
I'm looking for a way to determine the optimal X/Y/Z rotation of a set of vertices for rendering (using the X/Y coordinates, ignoring Z) on a 2D canvas.
I've had a couple of ideas, one being pure brute-force involving performing a 3-dimensional loop ranging from 0..359 (either in steps of 1 or more, depending on results/speed requirements) on the set of vertices, measuring the difference between the min/max on both X/Y axis, storing the highest results/rotation pairs and using the most effective pair.
The second idea would be to determine the two points with the greatest distance between them in Euclidean distance, calculate the angle required to rotate the 'path' between these two points to lay along the X axis (again, we're ignoring the Z axis, so the depth within the result would not matter) and then repeating several times. The problem I can see with this is first by repeating it we may be overriding our previous rotation with a new rotation, and that the original/subsequent rotation may not neccesarily result in the greatest 2D area used. The second issue being if we use a single iteration, then the same problem occurs - the two points furthest apart may not have other poitns aligned along the same 'path', and as such we will probably not get an optimal rotation for a 2D project.
Using the second idea, perhaps using the first say 3 iterations, storing the required rotation angle, and averaging across the 3 would return a more accurate result, as it is taking into account not just a single rotation but the top 3 'pairs'.
Please, rip these ideas apart, give insight of your own. I'm intreaged to see what solutions you all may have, or algorithms unknown to me you may quote.
I would compute the principal axes of inertia, and take the axis vector v with highest corresponding moment. I would then rotate the vertices to align v with the z-axis. Let me know if you want more details about how to go about this.
Intuitively, this finds the axis about which it's hardest to rotate the points, ie, around which the vertices are the most "spread out".
Without a concrete definition of what you consider optimal, it's impossible to say how well this method performs. However, it has a few desirable properties:
If the vertices are coplanar, this method is optimal in that it will always align that plane with the x-y plane.
If the vertices are arranged into a rectangular box, the box's shortest dimension gets aligned to the z-axis.
EDIT: Here's more detailed information about how to implement this approach.
First, assign a mass to each vertex. I'll discuss options for how to do this below.
Next, compute the center of mass of your set of vertices. Then translate all of your vertices by -1 times the center of mass, so that the new center of mass is now (0,0,0).
Compute the moment of inertia tensor. This is a 3x3 matrix whose entries are given by formulas you can find on Wikipedia. The formulas depend only on the vertex positions and the masses you assigned them.
Now you need to diagonalize the inertia tensor. Since it is symmetric positive-definite, it is possible to do this by finding its eigenvectors and eigenvalues. Unfortunately, numerical algorithms for finding these tend to be complicated; the most direct approach requires finding the roots of a cubic polynomial. However finding the eigenvalues and eigenvectors of a matrix is an extremely common problem and any linear algebra package worth its salt will come with code that can do this for you (for example, the open-source linear algebra package Eigen has SelfAdjointEigenSolver.) You might also be able to find lighter-weight code specialized to the 3x3 case on the Internet.
You now have three eigenvectors and their corresponding eigenvalues. These eigenvalues will be positive. Take the eigenvector corresponding to the largest eigenvalue; this vector points in the direction of your new z-axis.
Now, about the choice of mass. The simplest thing to do is to give all vertices a mass of 1. If all you have is a cloud of points, this is probably a good solution.
You could also set each star's mass to be its real-world mass, if you have access to that data. If you do this, the z-axis you compute will also be the axis about which the star system is (most likely) rotating.
This answer is intended to be valid only for convex polyhedra.
In http://203.208.166.84/masudhasan/cgta_silhouette.pdf you can find
"In this paper, we study how to select view points of convex polyhedra such that the silhouette satisfies certain properties. Specifically, we give algorithms to find all projections of a convex polyhedron such that a given set of edges, faces and/or vertices appear on the silhouette."
The paper is an in-depth analysis of the properties and algorithms of polyhedra projections. But it is not easy to follow, I should admit.
With that algorithm at hand, your problem is combinatorics: select all sets of possible vertexes, check whether or not exist a projection for each set, and if it does exists, calculate the area of the convex hull of the silhouette.
You did not provide the approx number of vertex. But as always, a combinatorial solution is not recommended for unbounded (aka big) quantities.
I'm looking to build an algorithm (or reuse one) that organizes nodes and edges on a 2 dimensional canvas where edges can have corresponding weights.
Any starting material and info would be helpful.
What would the weights do to affect their placement on your canvas?
That being said, you might want to look into graphviz and, more specifically, the DOT language, which organizes nodes on a canvas.
Many graph visualization frameworks use a force-based simulation, in which all nodes exert a repulsive force against each other (with their mass being their size), and edges exert tension on the nodes they connect. This creates aesthetically-arranged graph visualizations.
Although again, I'm not sure where you want node "weights" to come into play. Do you want weighted nodes to be more in the center? To be larger? More further apart?
Many graph/network layout algorithms are implicitly capable of handling weighted networks, but you may need to do some pre-processing and tweaks to the implementation to get it to work. Usually the first step is to determine if your weights represent "similarities" (usually interpreted to mean that stronger weights should place nodes closer togeter) or "dissimilarities" (stronger weights = father apart). The most common case is the former, so you will need to translate them to dissimilarities, often done by subtracting each edge value from the maximum observed edge value in the network. The matrix of dissimilarity values for each edge can then be fed to the algorithm and interpreted as desired distances in the layout space for each edge (i.e. "spring lengths")--usually after multiplying by some constant to transform to display units (pixels).
If you tell me what language you are using, I may be able to point you to some code examples.