I'm working on a flowchart system in JS, that allows the user to click on one element followed by another, and the program inserts an arrow connecting them. For this, I need a line-drawing algorithm which meets the following criteria:
Only straight lines/90deg turns
Guaranteed to take an efficient route, such that...
... it can take into consideration other lines (as it cannot intersect) - e.g, if I insert one line, and then another, it is able to draw the second without having to rearrange the first, or take a wildly inefficient route to get to its destination to avoid the first line.
If you know any algorithms which fit the bill (I've only found ones that match just one or at most two of the criteria), I'd be interested; also, if there's a JS implementation I can steal then please link that too.
Some notes:
Time complexity does not matter, as long as the result is aesthetically pleasant
There can be multiple lines originating from or entering one element. This is to allow for loopbacks/subroutines.
Lines can go on top of each other, just not perpendicularly across one another.
Examples:
image 1
I click on one element...
image 2
... and then on another, which then inserts the arrow between them.
image 3
If I continue this, I expect to get a linear sequence, with the arrows inserted automagically.
image 4
Alternatively, I can make use of multiple inputs/outputs to get a more closed chart, generating a more complex result.
image 5
I should be able to do this in any order to get the same result.
Related
I've been performing some research, in order to find the best approach to identify break points (trend direction change) in a dataset (with pairs of x/y coordinates), that allow me to identify the trend lines behind my data collections.
However I had no luck, finding anything that brings me some light.
The yellow dots in the following image, represent the breakpoints I need to detect.
Any suggestion about an article, algorithm, or implementation example (typescript prefered) would be very helpful and appreciated.
Usually, people tend to filter the data by looking only maximums (support) or only minimums (resistance). A trend line could be the average of those. The breakpoints are when the data crosses the trend, but this gives a lot of false breakpoints. Because images are better than words, you can look at page 2 of http://www.meacse.org/ijcar/archives/128.pdf.
There are a lot of scripts available look for "ZigZag" in
https://www.tradingview.com/
e.g. https://www.tradingview.com/script/lj8djt1n-ZigZag/ https://www.tradingview.com/script/prH14cfo-Trend-Direction-Helper-ZigZag-and-S-R-and-HH-LL-labels/
Also you can find an interesting blog post here (but code in in python):
https://towardsdatascience.com/programmatic-identification-of-support-resistance-trend-lines-with-python-d797a4a90530
with code available: https://pypi.org/project/trendln/
If you can identify trend lines then can't you just identify a breakpoint as when the slope changes? If you can't identify trend lines, then can you for example, take a 5-day moving average and see when that changes slope?
This might sound strange, or even controversial, but -- there are no "breakpoints". Even looking at your image, the fourth breakpoint might as well be on the local maximum immediately before its current position. So, different people might call "breakpoints" different points on the same graph (and, indeed, they do).
What you have in the numbers are several possible moving averages (calculated on a varying interval, so you might consider MA5 for five-day average, or MA7 for a week average) and their first and maybe second derivatives (if you feel fancy you can experiment with third derivatives). If you plot all these lines, suitably smoothed, over your data, you will notice that the salient points of some of them will roughly intersect near the "breakpoints". Those are the parameters that your brain considers when you "see" the breakpoints; it is why you see there the breakpoints, and not somewhere else.
Another method that the human vision employs to recognize features is trimming outliers: you discard in the above calculations either any value outside a given tolerance, or a fixed percentage of all values starting from those farther from the average. You can also experiment not trimming those values that are outliers for longer-period moving averages but are not for shorter periods (this gives better responsivity but will find more "breakpoints"). Then you run the same calculations on the remaining data.
Finally you can attribute a "breakpoint score" based on weighing the distance from nearby salient points. Then, choose a desired breakpoint distance and call "breakpoint" the highest scoring point in that interval; repeat for all subsequent breakpoints. Again, you may want to experiment with different intervals. This allows for a conveniently paced breakpoint set.
And, finally, you will probably notice that different kinds of signal sources have different "best" breakpoint parameters, so there is no one "One-Size-Fits-All" parameter set.
If you're building an interface to display data, leaving the control of these parameters to the user might be a good idea.
I am creating an application and I have a question about the way in which I go about making it.
You will be able to choose a number which determines the passage of time in minutes for two identical circles. (Separate buttons are created for incrementing and decrementing time for each circle)
As the time passes, the first circle fills up until the countdown for the first circle reaches 0 minutes.
Now a second identical circle will start the countdown and to fill up also based on the initial time you had given to it.
I have linked all the appropriate DOM elements(the circle, the buttons for incrementing/decrementing time) to the functions and event handlers written for the first circle and it runs perfectly. The second circle is essentially the exact same thing, except that it has a different button element for it's events and of course it is a different circle.
If I copy and paste all my code and just change the variables and function names associated with circle 1 to new ones for circle 2 it would work perfectly. That seems very repetitive and I'm sure there is a better way to go about this.
What comes to my mind is OOP. So instead of saying circle1 OR circle2 should fill up when I press this button, I can just say THIS circle fills up, when I press THIS button associated with each circle. Am I right in my thinking ? Is OOP the answer to my question here?
If you can get it to work with code duplication, that's a great start. What you have to do then is called refactoring:
Look for parts of the code which are exactly repeated, and if possible extract them into one function.
Then look for the parts of the code where you are doing things like var1 and var2, and think about ways to abstract that repetition in either a loop over an array, a generator function, or OOP class & instance patterns.
As you go along you will notice that your code will be functionally the same, but much easier to reason about and read.
Also don't be afraid of re-starting from a blank file!
I have a 10x10 grid filled with objects in certain coordinates and I have a character that needs to get from the start to finish but I would like to avoid the certain coordinates on the route to the finish. Could someone please tell what would be the best way of approaching this in Javascript.
Also, if I was to initialise an array with the obstacles in an array how would I best code this to avoid those certain plots.
Thank you.
Sounds like you're looking for a pathfinding algorithm. The only one that comes to mind is A-Star, or "A*". The short version is that it recursively picks a random "next node" from the nodes it hasn't checked, being more likely to pick nodes that are physically closer to the goal. This is a commonly-used function that you may want to find a tutorial for (it doesn't have to be a JavaScript tutorial as long as you can reuse the concepts in JavaScript)
I have a number of elements that I need to add to a page using javascript with data pulled from the server with their position information. I want to arrange them so that there is no overlap. For example, element 5 would be moved to where the thin green box is, so that it doesn't overlap element 3.
I have successfully created a function which decides whether two boxes overlap. For example, if I ran overlaps($('#element5')[0],$('#element3')[0]) it would return true.
However, with this function I would have to loop through each element and compare it with every other element. So for 50 elements I would need to do run the overlays function 1275 times which would take a long time to load.
I decided I would best creating an rtree to organise the elements first so that I could easily work out which 2 elements I would need to run the overlay function with, significantly reducing the number of runs of the overlay function. However, I am extremely confused on how this would work. How would I organise them so that I would only have to run the function with a small number? Wouldn't 2 of the rtree's bounding boxes overlap and make this technique redundant? What would be the best way to do this?
In an R-tree, rectangular pages can indeed overlap.
When searching for overlaps, you would have to explore both groups then.
But the number of overlapping pages in the r-tree shouldn't be too big (unless the tree was built very badly), so this will still yield a good speedup. Assuming you have 50 elements in 5 pages of 10 elements each, you will first have to test the 5 top level pages, then maybe test the 10 elements in 0-2 of these pages, so maybe just 15 overlap tests instead of 50.
The exact numbers will of course vary a lot.
For a HTML solution, however, I would consider a grid based approximation instead.
Divide your surface in 10x10 cells. Each cell contains references of the rectangles that overlap with this grid cell.
When testing for overlap, you look at the grid cells the query rectangle touches, collect all referenced existing rectangles, and then overlap test only those. If you store two lists in each cell - "overlaps partially" and "overlaps completely", you can even skip many of the overlap tests: if any grid cell touched by one is overlapped completely by the other, they will overlap somewhere.
Yet another approach would be to sort the rectangles by X axis, to quickly narrow down the number of rectangles that can actually overlap with a binary search. This also should drastically reduce the number of intersection calls.
Oh, and last but not least: 1275 overlap tests should not take a lot of time anyway. This is by any means a tiny data set that you are talking about. R-trees and similar approaches are meant for data sets with millions of items.
Suppose I have a large list of objects (thousands or tens of thousands), each of which is tagged with a handful of tags.
There are dozens or hundreds of possible tags and their usage follows a typical power law:
some tags are used extremely often but most are rare.
All but the most frequent couple dozen tags could typically be ignored, in fact.
Now the problem is how to visualize the relationship between these tags.
A tag cloud is a nice visualization of just their frequencies but it ignores which tags occur with which other tags.
Suppose tag :bar only occurs on objects also tagged :foo.
That should be visually apparent.
Similarly for three tags that tend to occur together.
You could make each tag a bubble and let them partially overlap with each other.
Technically that's a Venn diagram but treating it that way might be unwieldy.
For example, Google charts can create Venn diagrams, but only for 3 or fewer sets (tags):
http://code.google.com/apis/chart/docs/gallery/venn_charts.html
The reason they limit it to 3 sets is that any more and it looks horrendous.
See "extentions to higher numbers of sets" on the Wikipedia page: http://en.wikipedia.org/wiki/Venn_diagrams
But that's only if every possible intersection is non-empty.
If no more than 3 tags ever co-occur (maybe after throwing out the rare tags) then a collection of Venn diagrams could work (with the sizes of the bubbles representing tag frequency).
Or perhaps a graph (as in vertices and edges) with visually thicker or thinner edges to represent frequency of co-occurrence.
Do you have any ideas, or pointers to tools or libraries?
Ideally I'd do this with javascript but I'm open to things like R and Mathematica or really anything else.
I'm happy to share some actual data (you'll laugh if I tell you what it represents) if anyone is curious.
Addendum: The application I originally had in mind was TagTime but it occurs to me that this also maps well to the problem of visualizing one's delicious bookmarks.
If i understand your question correctly, an image matrix should work nicely here. The implementation i have in mind would be an n x m matrix in which the tagged items are rows, and each tags type is a separate column. Every cell in the matrix would consist entirely of "1's" and "0's", i.e., a particular item either has a given tag or it doesn't.
In the matrix below (which i rotated 90 degrees so it would fit better in this window--so columns actually represent tagged items, and each row shows the presence or absence of a given tag across all items), i simulated the scenario in which there are 8 tags and 200 tagged items. , a "0" is blue and a "1" is light yellow.
All values in this matrix were randomly selected (each tagged item is eight draws from a box consisting of two tokens, one blue and one yellow (no tag and tag, respectively). So not surprisingly there's no visual evidence of a pattern here, but if there is one in your data, this technique, which is dead simple to implement, can help you find it.
I used R to generate and plot the simulated data, using only base graphics (no external packages or libraries):
# create the matrix
A = matrix(data=r1, nrow=1, ncol=8)
# populate it with random data
for (i in seq(0, 200, 1)){r1 = sample(0:1, 8, replace=TRUE); A = rbind(A, r1)}
# now plot it
image(z=A, ann=F, axes=F, col=topo.colors(12))
I would create something like this if you are targeting the web. Edges connecting the nodes could be thicker or darker in color, or perhaps a stronger force connecting them so they are close in distance. I would also add the tag name inside the circle.
Some libraries that would be very good for this include:
Protovis (Javascript)
Flare (Adobe Flash)
Some other fun javascript libraries worth looking into are:
Processing for Javascript
Raphael
Although this is an old thread, I just came across it today.
You may also want to consider using a Self-Organizing Map.
Here is an example of a self-organizing map for world poverty. It used 39 of what you call your "tags" to arrange what you call your "objects".
http://www.cis.hut.fi/research/som-research/povertymap.gif
Note sure it would work as I did not test that, but here is how I would start:
You can create a matrix as doug suggests in his answer, but instead of having documents as rows and tags as columns, you take a square matrix where tags are rows and columns. Value of the cell T1;T2 will be the number of documents tagged with both T1 and T2 (note that by doing that you'll get a symetric matrix because [T1;T2] will have the same value as [T2;T1]).
Once you have done that, each row (or column) is a vector locating the tag in a space with T dimensions. Tags near each others in this space often occur together. To visualize co-occurrence you can then use a method to reduce your space dimensionality or any clustering method. For example you can use a kohonen self organizing map to project your T-dimensions space to a 2D space, you'll then get a 2D matrix where each cell represents an abstract vector in the tag space (meaning the vector won't necessary exists in your data set). This vector reflect a topological constraint of your source space, and can be seen as a "model" vector reflecting a significant co-occurence of some tags. Moreover, cells near each others on this map will represent vectors close to each other in the source space, thus allowing you to map the tag space on a 2D matrix.
Final visualization of the matrix can be done in many ways but I cannot give you advice on that without first seeing the results of the previous processing.