Best way to draw 'paths' to an array? - c#

I have a question about drawing lines/paths on my own.
I use a combination of C#/WPF/Cudafy for UI and some calculations (e.g. the paths). Now I have a Byte[] array that should be filled with 'colors'/values (array-length = 4 * width * height of the result image).
I got some startpoints for the lines and one endpoint (somewhere between the startpoints). First I calculated some paths from those startpoints to the endpoints and then want to 'draw' them to the array (that will be used to construct a WriteableBitmap). The point coordinates are present in a 'reduced environment' though (since calculation of the paths needed to run a Dijkstra algorithm).
My paths are now defined by Tuples holding the point-coordinates (reduced size) and a 'linewidth'.
Since some paths may 'overlap' I thought I will do the following steps to ensure a nice looking of the result:
Merge the paths:
For that I will take one path and just keep it. Then I take the second and check if the path-points are somewhere near a path already added (like a near-neighbor search). I want to do this because in the end, I want to widen the line-width where paths overlap (3rd Tuple value).
When finished, I want to 'interpolate' the paths:
I don't really know how I should do that, since every path has a point at every (reduced-size) pixel.
One possibility would be to clear out all those path-coortinates of the paths that 'lie on a line' (and are not really necessary) and then do something like a Bezier - Interpolation. But all these steps seem to be overkill to me.
Don't you think there might be a better way to do this? If so, please share your thoughts :)
Thank's for any help!
Here's a link to an image of how it looks right now: CPVL Application

Related

how to create a path that when blocked it follows another path that is predefined

I'm using unity2d to create a map for a fnaf prototype and I want a enemy to follow a predetermined path
but when I close a door on the map I want it to use another predetermined path and repeat that for all other paths until the last path then go back to the start but I have no idea what the best way to go about this is I was thinking if and else statements but i would think there is like a tool or something to help do that? So to sum it all up:** I want to make a path following enemy that when blocked uses another path and want to know the best way to do it or if there is tools to do this in unity2d **
I tried to use if and else statements but that got pretty messy and my code got all jumbled
You could create a graph of all your possible predefined paths, and set the cost of the preferred path lower than the alternative paths. If you close the door you would then change the cost of that node to infinite, forcing the enemy to take the alternative route. You could then use something like A* or Djikstra to find the correct path to follow, this should be fairly cheep unless the number of nodes is very large.
If you use a cost function that uses the maximum of any visited note you can simply assign a cost of zero to the preferred path, one to the first alternative, 2 to the second etc. That way the number of nodes visited is irrelevant, only the preferred order to take.

How to randomly place objects as player move around in an infinity map without overlap?

I trying to make a game where player only move forward in an infinity map, and the path (just thing of them like points, the path is only the visual) is procedurally generated. I want those path to have different length (something like the tree of life, but only branches of the selected path are generated).
This is how I generate branches without overlap:
List<Vector3> everyPos; //predetermined position
public void Spawn(int amount)
{
List<Vector3> possiblePos = new List<Vector3>(everyPos);
for (int i = 0; i < amount; i++)
{
int index = Random(0, possiblePos.Count); //Find a random position
SpawnObjectAt(currentPosition+possiblePos[index]));//Create a point there
possiblePos.RemoveAt(index); //Remove that position from the list
}
}
The problem is , look at this image(I can't embed image yet):
Red is where player start, green is possible spawn position in the first move.
If there are 2 point spawned at 1 and 2, player choose point1, then the possible position in the second time will be a point in the black zone, which include point2, so if I keep continue there will eventually overlap.
How can I avoid this? I'm making a mobile game so I don't want to cache every single point. Any help would be really appreciated! Thanks!
This is a small web game that have somewhat similar mechanic to what I trying to achieve: newgrounds.com/portal/view/592325/
This is an attempt here to answer, but honestly, you need to provide more information.
Depending on the language you are writing in, you can handle this differently. You may need dynamic allocation, but for now lets assume, since your idea is quite small, that you can just do one large array predefined before compile time.
I assume you know how to make an array, so create one with say, 500 length to start. If you want to 'generate' a link like they did in that game, you simply need a random function, (there is a built in library in pretty much every language I think) and you need to do a little math.
Whatever language you use will surely have a built in graphics library, or you can use a popular easy to use one. I'll just draw a picture to make this clear.
There are a number of ways you can do this mathematically as shown in the image, using angles for example, the simplest way, however, is just to follow the boxes.
If you have worked with graphics before, you know what a vector is, if not, you will need to learn. The 9 vectors presented in this image (0,1) (1,0) (1,1) etc. can be created as vector objects, or even stored as individual ints.
To make your nodes 'move' into another path, you can simply do a rand 1-9 and then correlated the result to one of 9 possible vectors, and then add them to your position vector. It is easiest to do this in array and just use the rand int as the index. In most c derived languages you do that like this:
positionVector += changeVectorArray[rand(1,9)];
You then increment your position vector by one of the 9 vectors as shown above.
The simplest way of making the 'path' is to copy the position before you add the change vector, and then store all of the changes sequentially in another 'path' array.
To show the path on screen, simply draw a line between the first and second, second and third, third and forth elements of your path array. This formula (of joining lines) is discrete mathematics if I'm not mistaken, and you can do much more complicated path shapes if you want, but you get the gist.
That should at least start you off. Without more info I can't really help you.
I could go off on a tangent describe a bunch of different ways you can make this happen differently but its probably easier if you just ask for specifics.
EDIT>>>
Continuing with this answer, yes, looking at it now, the nodes can definitely overlap. To solve this problem you could use collision detection, every time you generate a new 'position', before adding it and drawing the line you have to loop through your array like this:
boolean copy = true;
for(int i = 0; i < getLength(pathArray); i++){
if( newVector == pathArray[i]){
copy=false;
}
}
Then of course, if copy still is true, copy the new position int the pathArray. NOTE: this whole solution is sloppy as hell, and as your array gets larger, your program is going to take longer and longer to search through that loop. This may not also guarantee that the path goes in one direction, but it is likely. And note that the lines will still be able to overlap each other, even though the position vectors can't be on top of one another.
All this considered, I think it will work, the optimization is up to you. I would suggest that there is probably a much more efficient solution using a discrete formula. You can also use such a formula to make the path go in particular directions and do other more complicated things.
You could also quite easily apply constraints on your random rolls if you want to make the path go in a particular direction. But there are so many ways of doing this I can't begin to explain. You could google path-finding algorithms for that.
Good luck.

Dijkstra algorithm expanded with extra limit variable

I am having trouble implementing this into my current path finding algorithm.
Currently I have Dijkstra written and works like it should, but I need to step further away and add a limit (range). I can better explain with an image:
Let's say I have range of 80. I want to go from A to E. My current algorithm, works as it should, so it results in A->B-E.
However, I need to go only on paths with weight not more than the range - 80, which would mean that A->B->E is not the option any more, but A->C->D->B->E (considering that range/limit resets on every stop)
So far, I have implemented a bool named Possible which would return for the single part of path (e.g. A->B) is it possible comparing to my limit / range.
My main problem is that I do not know where/how to start. My only idea was to see where Possible is false (A->B on the total route A->B->E) and run the algorithm from A to A->E again without / excluding B stop/vertex.
Is this a good approach? Because of that my big O notation would increment twice (as far as I understand it).
I see two ways of doing this
Create a new graph G' that contains only edges < 80, and look for shortest path there... reduction time is O(V+E), and additional O(V+E) memory usage
You can change Dijkstra's algorithm, to ignore edges > 80, just skip edges >80, when giving values to neighbor vertices, the complexity and memory usage will stay the same in this case
Create a temporary version of your graph, and set all weights above the threshold to infinity. Then run the ordinary Dijkstra algorithm on it.
Complexity will increase or not, depending on your version of the algorithm:
if you have O(V^2) then it will increase to O(E + V^2)
if you have the O(ElogV) version then it will increase to O(E + ElogV)
if you have the O(E + VlogV) version it will remain the same
As noted by ArsenMkrt you can as well remove these edges, which makes even more sense but will make the complexity a bit worse. Modifying the algorithm to just skip those edges seems to be the best option though, as he suggested in his answer.

Dealing with imprecision in CAD drawing

I have a CAD application, that allows user to draw lines and polygons and all that.
One thorny problem that I face is user drawing can be highly imprecise, for example, a user might want to draw two rectangles that are connected to each other. Hence there should be one line shared by two rectangles. However, it's easy for user to, instead of draw a line, draw two lines that are very close to each other, so close to each other that when look from the screen, you would be mistaken that they are the same line, except that they aren't when you zoom in a little bit.
My application would require user to properly draw the lines ( or my preprocessing must be able to do auto correction), or else my internal algorithm (let's call it The Algorithm) would not be able to process the inputs correctly.
What is the best strategy to combat this kind of problem? I am thinking about rounding the point coordinates to a certain degree of precision, but although I can't exactly pinpoint the problem of this approach, but I feel that this is not the correct way of doing things, that this will introduce a new set of problem.
Edit: For the sake of argument the snapping isn't an available option. For the matter, all sorts of "input-side" guidance are not available. The correction must be done via preprocessing on my code, when the drawing is finished, but just before I submit it to my algorithm.
Crazy restriction, you say. But a user can construct their input either in my application, or they can construct their input in other CAD software and then submit to my engine to do the calculation. I can't control how they input in other CAD software.
Edit 2:I can let user to specify the "cluster radius" to occur, but the important point is, I would need to make sure that my preprocessing algorithm is consistent and won't really introduce a new set of problem.
Any idea?
One problem I see is that your clustering/snapping algorithm would have to decide on its own which point to move onto which other point.
During live input snapping is simple: the first point stays put, the second point is snapped onto the first. If in offline mode you get a bunch of points that you know should be snapped together, you have no idea where the resulting point should lie. Calculate the average, possibly resulting in a completely new point? Choose the most central point out of all the candidates? Pick one at random? Try to align your point with some other points on the x/y/z-axis?
If your program allows any user interaction at all, you could detect point clusters that might be candidates for merging, and present the user with different merge target points to choose from.
Otherwise, you could make this kind of behaviour configurable: take a merge radius ("if two or more poins are within n units of one another...") and a merging algorithm ("... merge them into the most central of the points given") as parameters and read them from a config file.
Snapping points. User should be able to snap to end points (and many more) then, when you detect a snap, just change the point user clicked to snap point point. Check AutoCAD, functions line End, Middle and so on.
EDIT: If you want offline snapping then you just need to check every pair of points if they are near each other. The problem is that this in NP-problem so it will take a lot of time as you can't really get under O(n^2) time complexity. This algorithm you need should be under "clustering".
EDIT2: I think you shouldn't consider that input data is bad. But if you reallllllly want to do this, simples way is to take each point, check if there are other points in users defined radius, if yes find whole group that should merge into one point, find avg of coordinates of points and point all of them to that specific point. But remember - most designers KNOW what are snap points for and if they don't use them they have valid idea for that.
Your basic problem seems to me (I hope I understood correctly) to determine if two lines are the "same" line.
Out of my own experience your feeling is correct, rounding the coordinates in the input might prove not to be a good idea.
Maybe you should leave the coordinates in the input as they are but implement your function let's name it IsSameLine That you use in "The Algorithm" (who among others determines if two rectangles are connected if i understood your description correctly).
IsSameLine could transform the endpoints of the input lines from source coordinates to screen coordinates considering a certain (possibly configurable) screen resolution and check if they are the same in screen coordinates.
I.e. let's say you have an input file with the following extent (lowerleft) (upperRight) ((10,10), (24,53)). The question would be how far apart would be points (11,15) and (11.1, 15.1) if drawn at "zoom to extents" level on a 1600x1200 pixels screen. So you can determine a transform from source coordinates to "screen coordinates". You use then this transformation in IsSameLine as described above.
I'm not sure however this would be actually a good solution for you.
Another (maybe better?) possibility is to implement IsSameLine to return true if the points of the two lines are at maximum epsilon distance apart. The epsilon could have a default value computed based on the extent of the input vector data and probably it would be a good idea to give the user the possibility to give another value for it.

Longest Path between two vertices

I have a directed graph with weighted edges (weights are all positive).
Now, I'm looking for an efficient algorithm or code (specifically, C#) to find the longest path between two given vertices.
This is exactly equivalent to a shortest-path algorithm with all negative weights. To do that, you need to verify that there are no negative-weight cycles (which in your original case is probably equivalent to verifying no positive-weight cycles). Best bet is to take the additive inverse of the weights and run Bellman-Ford, then take the additive inverse of the result.
David Berger's answer is correct, unless you mean a simple path, where each vertex can occur at most once, in which case Bellman-Ford will not give the longest path. Since you say the weights are positive, it's not possible for a longest path to exist when the graph has a cycle (reachable from the source), unless you mean simple path. The longest simple path problem is NP-complete. See Wikipedia.
So, let's assume you mean a directed acyclic graph (DAG). In linear time, you can compute the longest path to each vertex v from the start vertex s, given that you know the longest path from s->*u for each u where u->v directly. This is easy - you can do a depth first search on your directed graph and compute the longest path for the vertices in reverse order of visiting them. You can also detect back edges whole you DFS using a 3-color marking (opened but not finished vertices are gray). See Wikipedia again for more information. Longest/shortest path finding on a DAG is sometimes called the Viterbi algorithm (even though it was given assuming a specific type of DAG).
I'd attempt the linear time dynamic programming solution first. If you do have cycles, then Bellman-Ford won't solve your problem anyway.
Please refer to the QuickGraph project as it provides .NET data structures implementing graphs, and also provides algorithms to operate on such data structures. I'm certain the algorithm you are looking for is implemented in the library.
Just in case it helps anyone, as I was looking for this for a while but couldn't find it, I used QuickGraph to solve a problem where I had to find the longest path that also complies with a certain rule. It is not very elegant as I did it a bit on brute force once I get the first result, but here it is.
https://github.com/ndsrf/random/blob/master/LongestSkiPath/LongestSkiPath/SkiingResolver.cs#L129-L161
To get the longest path you use an algorithm to find the shortest with lenghts = -1. And then to find subsequent longest paths I start removing edges from that longest path to see if I manage to get a "better" (based on the conditions of the problem) longest path.

Categories

Resources