views:

76

answers:

1

I am dynamically generating a WKT LineString between points in a map layer being generated for display in OpenLayers. I'd like to make the lines between the points curved, and I'd like to be able to dynamically change the curvature based on various input variables.

This is for a network monitoring app, and we'd like the curvature to based on delay times between the points (not the raw delay itself, but the deviation from "normal" values during a given time period).

While some GIS app and databases support a CircularString extension to WKT, OpenLayers doesn't know anything 'bout that.

So I'll need to generate a curved line out of line segments:

Right now, the line strings are simply:

LINESTRING(hop1_long hop1_lat, hop2_long hop2_lat)

The only way I can determine to make the linesegment "curved" is to insert intermediary points:

LINESTRING(hop1_long hop1_lat, long1 lat1, long2 lat2, ..., hop2_long hop2_lat)

This should be perfectly adequate for our application, but I don't know how to generate the intermediary points!

I assume there are well-known methods/algorithms for generating a "curved" line out of line segments in a 2d plane. Does anyone have any ideas as to how to accomplish this, or books/articles/online resources that could be helpful?

UPDATE (2010-08-13):

Bezier curves were the ticket, and implementing the basic Bezier algorithm was pretty easy after reading up on it. But I had to write some code to generate the control points. Here's the PHP code I came up with. This assumes a "Vector2d" class with x and y members.

function get_control_points($to, $from, $mag_scale, $angle) {
  $dirX = $to->x - $from->x;
  $dirY = $to->y - $from->y;

  $mag = sqrt(($dirX * $dirX) + ($dirY * $dirY));
  if (!$mag) {
    return array($to, $from);
  }

  $length = $mag * $mag_scale;

  $dirX = $dirX / $mag;
  $dirY = $dirY / $mag;

  $sin = sin($angle);
  $cos = cos($angle);

  $rotX = $cos * $dirX - $sin * $dirY;
  $rotY = $sin * $dirX + $cos * $dirY;
  $rotNegX = $cos * -$dirX - $sin * $dirY;
  $rotNegY = $sin * $dirX - $cos * $dirY;

  // Flip control points for "backwards" curves
  if ($dirX x;
    $y1 = -$rotNegY * $length + $from->y;
    $x2 = -$rotX * $length + $to->x;
    $y2 = -$rotY * $length + $to->y;
  }
  // Or generate "normal" control points
  else {
    $x1 = $rotX * $length + $from->x;
    $y1 = $rotY * $length + $from->y;
    $x2 = $rotNegX * $length + $to->x;
    $y2 = $rotNegY * $length + $to->y;
  }

  return array(new Vector2d($x2, $y2), new Vector2d($x1, $y1));
}
+1  A: 
brainjam
Handy! My geometry is truly weak if I forgot parameterized equations. The other question for me is determining (cx, cy) based on the start/end points on the plane.
David Eads