Clay
Clay

Reputation: 2999

Cocoa: "Random" line between two points?

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]

  1. Use [p lineToPoint:ptx] where I create a meandering line that is jagged and
  2. Use [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?


Update

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


Another Update

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).

Example of pathfinding


Final Update

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.

Relaxation algorithm applied to cell sites

Upvotes: 3

Views: 1245

Answers (1)

Tommy
Tommy

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:

  • imagine you're going to break the line into two by dividing it at the centre point and moving that somewhere; so...
    • work out the line normal
    • figure out how far along the line normal you could move the imaginary centre cut point before your lines overlap pre-existing lines (the easiest way to do this would be a binary search, I think, rather than anything analytic)
    • if the two extremes are too close together then return
    • otherwise pick a random position between the two extremes, break the line and recurse

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

Related Questions