Create smooth links in JointJS that route around obstacles - svg

I'm attempting to create links in JointJS that are smooth curves but also route around obstacles. The default implementation allows us to choose routers and connectors. Routers let you define the logic to avoid obstacles and basically return a set of points to hit on the connector. The connector takes that set of points and converts it into an svg path.
Using no router or the "orthogonal" router with the "smooth" connector produces a result like this
The manhattan and metro routers have logic to avoid obstacles. You can use them with the default connector or a rounded one (default but with rounded corners) to get something like this:
For comparison, the metro router without the smooth connector looks like
Combining the smooth connector with one of those routers works great, except that you tend to get strange artifacts at the ends (and unnecessarily complex curves):
I believe this issue is that the smooth connector is just calculating bezier curves that go through the points from the router.
I thought that perhaps I could solve the problem by calculating the curves (using g.Curve.throughPoint() which created this last picture and then adjusting the very first and very last control points to be inline with the start and end points horizontally and vertically, respectively (in this case). That made far less difference than I hoped (in particular at the start):
This is the svg path of that last one:
M 150 110 C 155.78724378793083 110 161.57448757586167 98.34306652925683 170 110 C 178.42551242413833 121.65693347074317 189.48929348448416 150.79926714760109 220 160 C 250.51070651551584 169.20073285239891 300.46833848620173 158.45986488033893 320 160 C 339.53166151379827 161.54013511966107 328.6373525707088 175.36127333104315 340 180 C 351.3626474292912 184.63872666895685 384.982251230963 180.09504179548838 400 180 C 415.017748769037 179.90495820451162 411.43364250543914 184.2585594870033 410 190 C 408.56635749456086 195.7414405129967 410 202.87072025649834 410 210
I think the issue is the control points are so close together that it while it is technically perpendicular, it comes in very steep so you can only see it if you zoom way in.
Fundamentally, I think the problem to all the issues is that we don't really want to go through the same points as the metro router. By definition, that's going to make the curve more 'wiggly' than needed.
So my question is - is there a way to programmatically "round" the curves to look more like the one at the top, while ensuring they avoid obstacles? I suspect this will require both new router and connector logic to ensure the curve works for any arbitrary layout, though perhaps that's not true.
Something more like this:

Related

2D Godot raycastin is unituitive to use & 2D Global coordinates and rotation

Hey so i am working on a interactive mini game in my work. New to godot!
Item.rotate(rand_range(-1.22173,1.22173)) just shooting missiles apromaxily 70 degrees at random. Its doing more like 140 degrees and i don't know why when i rotate.
Item = ammo.instance()
Item.position = Vector2(960,0)
Item.rotate(rand_range(-1.22173,1.22173))
add_child(Item)
bulletArray.append(Item)
var rot = Item.rotation
angle = rot + PI/2
angleArray.append(angle)
then when i shoot it with bullet array loop:
x.position += Vector2(1, 0).rotated(angleArray[index]) * speed * delta
its like 1-3 degreees off sometimes you can slightly notice it so its weird.
I wanted raycasting to just use some visual elements there maybe add collider later dont know. I tried
var randomvec = Vector2(rand_range(-400, 1120),1080)
with local coordinates when y is = 0 window size is 1080 y. It jus shoots so much wider than it should. And theres no documentation i can find. when i used something more like ((-30,30),1080)*MAX (max was = 1050) i was getting better results.
Is there any reliable way to use global coordinates on 2D games. Mostly for everything.
Thanks ! Just trying something new to this engine.
Its good enough but its not perfect angle how to fix that ?
I tried those codes shooting works and angle is 98% perfect. Raycasting was really hard to get on right area on random. Tried looking some documentation but cant figure it out.
Easy way to just use global coordsinates for almost everything ?
Okay im an idiot im working 12 hours a daý..... i just need to Item.rotate(rand_range(-1.22173,1.22173)) / 2 Sorry about that im really overworking..... of course its 140 degrees.... but raycasting question and angle couple degrees off still stands. It was still better gameplay when it was little wider so i try 90 pii/2. lol haha. Need to have a break.
As you must have figured out 1.22173 radians is 70º. Which means the range from -1.22173 to 1.22173 is a range from -70º to 70º which is a total of 140º.
I will also remind you that you can use the to_local and to_global methods to convert from and to global coordinates.
Furthermore in 2D you can use global_rotation.
And if you want to transform a direction, you can use node2d.global_transform.basis_xform(direction) (or use basis_xform_inv for the inverse).
its like 1-3 degreees off sometimes you can slightly notice it so its weird.
I'm guessing this is floating point error. Work with the rotated direction (a unit vector), instead of storing an angle and rotating again. Or use the transform of the Node2D as mentioned above.

3d Graphing Application Questions

For one of my classes, I made a 3D graphing application (using Visual Basic). It takes in a string (z=f(x,y)) as input, parses it into RPN notation, then evaluates and graphs the equation. While it did work, it took about 20 seconds to graph. I would have liked to add slide bars to rotate the graph vertically and horizontally, but it was definitely too slow to allow that.
Does anyone know what programming languages would be best for this type of thing? Ideally, I will be able to smoothly rotate the function once it is graphed.
Also, I’m trying to find a better way to rotate the function. Right now, I evaluate it at a bunch of points, and then plot the points to the screen. Every time it is rotated, it must be re-evaluated and plot all the new points. This takes just as long as the original graph process, as it basically treats it as a completely new function.
Lastly, I need a better way to display the graph. Currently (using VB with visual studio) I plot 200,000 points to a chart, but this does not look great by any means. Eventually, I would like to be able to change color based on height, and other graphics manipulation to make it look better.
To be clear, I am not asking for someone to do any of this for me, but rather the means to go about coding this in an efficient way. I will greatly appreciate any advice anyone can give to help with any of these three concerns.
So I will explain how I would go about it using C++ and OpenGL. This doesn't mean those are the tools that you must use, it's just those are standard graphics tools.
Your function's surface is essentially a 2D manifold, which has the nice property of having an intuitive mapping to a 2D space. What is commonly referred to as UV mapping.
What you should do is pick the ranges for the rectangle domain you want to display (minimum x, maximum x, minimum y, maximum y) And make 2 nested for loops of the form:
// Pseudocode
for (x=minimum; x<maximum; x++)
for (y=minimum; y=maximum; y++)
3D point = (x,y, f(x,y))
Store all of these points into a container (std vector for c++ works fine) and this will be your "mesh".
This is done once, prior to rendering. You then render those points using, for example GL_POINTS, and rotate your graph mesh using rotations on the GPU.
This will only show scattered points, not a surface.
If you also wish to show the surface of your function, and not just the points, you can triangulate that set of points fairly easily.
Group each 4 contiguous vertices (i.e the vertices at indices <x,y>, <x+1,y>, <x+1,y>, <x+1,y+1>) and create the 2 triangles:
(<x,y>, <x+1,y>, <x,y+1>), (<x+1,y>, <x+1,y+1>, <x,y+1>)
This will fill triangulate the surface of your mesh.
Essentially you only need to build your mesh once, and this way rendering should be 60 fps for something with 20 000 vertices, regardless of whether you only render points or triangles too.
Programming language is mostly not relevant, so VB itself is probably not the issue. You can have the same issues in Python, C#, C++, etc. Of course you must master the programming language you choose.
One key aspect is using the right algorithms and data-structures. Proper use of memory allocations and memory layout for maximizing CPU (and GPU) cache are also key. Then you must take advantage of the platform and hardware capabilities (GPU and Multithreading). For the last point you definetely need to use a graphics library such as OpenGL or Vulkan.

Three.js ParticleSystem flickering with large data

Back story: I'm creating a Three.js based 3D graphing library. Similar to sigma.js, but 3D. It's called graphosaurus and the source can be found here. I'm using Three.js and using a single particle representing a single node in the graph.
This was the first task I had to deal with: given an arbitrary set of points (that each contain X,Y,Z coordinates), determine the optimal camera position (X,Y,Z) that can view all the points in the graph.
My initial solution (which we'll call Solution 1) involved calculating the bounding sphere of all the points and then scale the sphere to be a sphere of radius 5 around the point 0,0,0. Since the points will be guaranteed to always fall in that area, I can set a static position for the camera (assuming the FOV is static) and the data will always be visible. This works well, but it either requires changing the point coordinates the user specified, or duplicating all the points, neither of which are great.
My new solution (which we'll call Solution 2) involves not touching the coordinates of the inputted data, but instead just positioning the camera to match the data. I encountered a problem with this solution. For some reason, when dealing with really large data, the particles seem to flicker when positioned in front/behind of other particles.
Here are examples of both solutions. Make sure to move the graph around to see the effects:
Solution 1
Solution 2
You can see the diff for the code here
Let me know if you have any insight on how to get rid of the flickering. Thanks!
It turns out that my near value for the camera was too low and the far value was too high, resulting in "z-fighting". By narrowing these values on my dataset, the problem went away. Since my dataset is user dependent, I need to determine an algorithm to generate these values dynamically.
I noticed that in the sol#2 the flickering only occurs when the camera is moving. One possible reason can be that, when the camera position is changing rapidly, different transforms get applied to different particles. So if a camera moves from X to X + DELTAX during a time step, one set of particles get the camera transform for X while the others get the transform for X + DELTAX.
If you separate your rendering from the user interaction, that should fix the issue, assuming this is the issue. That means that you should apply the same transform to all the particles and the edges connecting them, by locking (not updating ) the transform matrix until the rendering loop is done.

Contact area size in MultitouchSupport private framework

I've been playing around with the carbon multitouch support private framework and I've been able to retrieve various type of data.
Among these, each contact seems to have a size and is as well described by an ellipsoid (angle, minor axis, major axis). However, I haven't been able to identify the frame of reference used for the size and the minor and major axis.
If anybody has been able to find it out, I'm interested in your information.
Thanks in advance
I've been using the framework for two years now and I've found that the ellipse is not in standard units (e.g. inches, milimeters). You could approximate millimeters by doubling the values you get for the ellipse.
Here's how I derived the ellipse information.
First, my best guess for how it works is that it's close to Synaptics "units per mm": http://ccdw.org/~cjj/l/docs/ACF126.pdf But since Apple has not released any of that information for developers, I'm relying on information that I print to the console.
You may get slightly different values based on the dimensions of the device (e.g. native trackpad vs magic mouse) you're using with the MultiTouchSupport.framework. This might also be caused by the differences in the surface (magic mouse is curved).
The code on http://www.steike.com/code/multitouch/ has a parameter called mm. This gives you the raw (non-normalized) position and velocity for the device.
Based on the width's observed min & max values from mm (-47.5,52.5), the trackpad is ~100 units wide (~75 units the other way). The trackpad is about 100mm wide x 80mm. But no, it's not a direct unit to millimeter translation. I think the parameter being named 'mm' may have just been a coincidence.
My forearm can cover about 90% of the surface of the trackpad. After laying it across the trackpad, the output will read to about 58 units wide by 36 units long, with a size of 55. If you double the units you get 116 by 72 which is really close to 100mm by 80mm. So that's why I say just double the units to approximate the millimeters. I've done this with my forearm the other way and with my palm and the approximations still seem to work.
The size of 55 doesn't seem to coincide with the values of ellipse. I'm inclined to believe that ellipse is an approximation of the surface dimensions and size is the actual surface area (probably in decimeters).
Sorry there's no straight answer (this is after all a reverse engineering project) but maybe this information can help you find the answer yourself.
(Note: I'd like to know what you're working on?)

Graphviz DOT arrange Nodes in circles, layout too "compact"

I'm halfway there please see the edit
OK here's my problem, I'm generating a graph of a python module, including all the files with their functions/methods/classes.
I want to arrange it so, that nodes gather in circles around their parent nodes, currently everything is on one gargantuan horizontal row, which makes the thing >50k pixels wide and also let's the svg converter fail(only renders about the half of the graph).
I went through the docs but couldn't find anything that seems to do the trick.
So the question is:
Is there a simple way to do this or do I have to layout the whole thing by myself? :/
EDIT:
Thanks to Andrews comment I've got the right layout, the only problem now is that it's a bit to "compact"... so the question now is, how to fix this?
i've mentioned all of the most significant parameters that influence your current layout and then suggested values for those parameters. Still, i suspect you can get the layout that you want just from applying a couple of these suggestions.
reduce the edge weight, eg, [weight=0.5]; this will make the
edges longer, causing the tight
clusters you currently see in your
graph to 'fan out'.
get rid of the node borders, node_A
[color=none; shape=plaintext];
especially for oval-shaped nodes, a
substantial fraction of the total
node space is 'unused' (ie, not used
to display the node label).
explicitly set the font size for
the nodes (the node borders are
enlarged so that they surround the
node text, which means that the font
size and amount of text for a given
node has a significant effect on its
size); [fontsize=11] should be large
enough to be legible yet also reduce
the 'cluttered' appearance (the
default size is 14).
increase minimum separation between
nodes, via 'nodesep'; eg, nodesep=2.0; this will
directly address your objection
regarding your graph being "too
compact." ('nodesep' and 'ranksep'
probably affect how dot draws a graph
more than any other parameters for
node, edge, or graph. In your case,
it looks like you have only two ranks
of nodes; 'ranksep' sets the minimum
distance between nodes of different
ranks--it looks like all of the nodes
that comprise your graph are of the
same rank (except for few top level
nodes in the centers).
explicitly set total graph size, eg,
size="7.75,10.25" (ensures that your
graph fits on an 8.5 x 11 page and
that it occupies the entire space)
And one purely aesthetic suggestion
that at most will only help your
graph appear less cluttered: the
default fontcolor for both edges and
nodes is black. The majority of the
ink on your graph is from those two
structures (particularly if you
remove the node borders), so i would
for instance set either the node
(text) fontcolor or the edge
fontcolor to "blue" to help the eye
distinguish the two sets of graph
structures.
If it is too compact, you will want to mess with the edge length. You have a couple options depending on the graph layout:
If your layout is sfdp or fdp, tweak the graph property K. Default is 0.3.
For neato (or fdp), tweak the edge property len. Default is 1.0 for neato and 0.3 for fdp.
For dot you can use the edge property minlen which is the minimum edge length. Default is 1.
You might also want to mess with the graph property model which determines clustering behavior. Specifically, try subset. I believe this handles len for you:
http://www.graphviz.org/doc/info/attrs.html#d:model
Also, you can remove overlaps all together with scaling techniques: http://www.graphviz.org/doc/info/attrs.html#d:overlap
I have around 500 nodes and used doug's recommendation.
This is my sample code that works (in python):
f = Digraph('companies',filename='companies.gv',
edge_attr={'weight':'1',
'fontsize':'11',
'fontcolor':'blue',
'len':'4'},
graph_attr={'fixedsize':'false',
'bgcolor':'transparent'},
node_attr={'fontsize':'11',
'shape':'plaintext',
'color':'none',
'fontcolor':'black'})
f.attr(layout="neato")
f.attr(nodesep='3')
f.attr(ranksep='3')
f.attr(size='5000,5000')

Resources