Reputation: 2999
In my Cocoa hobby project (on OSX), I have a view with some points identified. Something like this:
NSPoint pt1 = NSMakePoint(20,100);
NSPoint pt2 = NSMakePoint(100,30);
I would like to create a meandering line (that never crosses itself) between those two point. The points may vary, of course. I'm familiar with NSBezierPath
but I'm not graphics whiz.
There are two variations on this. Given NSBezierPath *p ...
and setup of [p moveToPoint:pt1]
[p lineToPoint:ptx]
where I create a meandering line that is jagged and[p curveToPoint:ptx controlPoint1:cpt1 controlPoint2:cpt2]
with a meandering line that is smooth.The 2nd case seems more difficult, since sensible control points also must be calculated.
Finally, I would like to be able to adjust the amount with which the line meanders. If I set a variable like int numOfIntermediatePoints
to 1, then there will be a smooth curve between pt1
and pt2
. If I set numberOfIntermediatePoints
to 10, there will be much more movement in the line. I don't want the last intermediate points to be very far from the final point (leaving a large change at the end of the line).
I've looked into using Perlin noise, but it seems like it would be hard to guide the line towards its end point. It seems like it would make sense to calculate an array of NSPoint
items (and possibly an array of control points, for case two) and then loop through them to create the line.
What's the best approach to this?
Following Tommy's advice led me to port Raymond Hill's Javascript-Voronoi library to Obj-C. You can find it here: https://github.com/ccheaton/objcvoronoi
One more update -- I played with Dijkstra's algorithm and found it to be overkill for what I was trying to achieve. I ended up implementing a simplified variation of it that allows me to specify guide nodes for the random line. In this image, the line start is on the mid left, the line end is on the mid right, and there are guide points at (xMax * 0.33, 0) and (xMax * 0.66, yMax).
To make it slightly less jagged, I added an optional relaxation algorithm. Performance isn't great now, but that doesn't matter for the use I have in mind.
Upvotes: 3
Views: 1245
Reputation: 100622
There are a bunch of approaches that spring to mind.
In terms of code you can pull directly off the internet, you could pull down a random maze generator and a maze solver, then generate a maze with entry and exit points as you require and take the solution.
Making things up as I go along, you could attempt a recursive approach — start with a straight line from start to end then for each straight line you have:
For other interesting ideas, you throw a load of random points between the start and end point, calculate the Voronoi diagram then walk (i) from the start point to anywhere on its boundary; (ii) along the cell boundaries according to the shortest path to the boundary of the end point (eg, using Dijkstra's algorithm); and then (iii) to the end point. You could then go through every vertex-to-vertex link added by (ii) and find the shortest route with all currently selected links eliminated from the potential set, and repeat that a few times to make the path more interesting.
From roughly the same school of thought, throwing a bunch of random obstacles between the points and running an A*-style pathfinder would probably yield something interesting.
Upvotes: 3