Create an unconfigured, curved well-known text LineString for display in OpenLayers

I dynamically generate a WKT LineString between points in a map layer created for display in OpenLayers. I would like to make the lines between the points curved, and I would like to be able to dynamically change the curvature based on various input variables.

This is a network monitoring application, and we would like the curvature to be based on the delay time between points (and not on the initial delay itself, but on the deviation from the "normal" values ​​for a certain period of time).

Although some GIS applications and databases support the CircularString extension for WKT, OpenLayers knows nothing about this.

Therefore, I need to create a curved line from line segments:

Right now the line of the line is simple:

  LINESTRING (hop1_long hop1_lat, hop2_long hop2_lat)

The only way I can define to make the linesegment β€œbend” is to insert intermediate points:

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

This should be adequate for our application, but I don’t know how to create intermediate points!

I assume that there are known methods / algorithms for generating a β€œcurved” line from line segments in the 2d plane. Does anyone have any ideas on how to do this, or books / articles / online resources that might be helpful?

UPDATE (2010-08-13):

Bezier curves were a ticket, and implementing the basic Bezier algorithm was pretty easy after reading it. But I had to write code to create breakpoints. Here is the PHP code I came across. This assumes the class "Vector2d" with members x and y .

  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));
 }
+2
source share
1 answer

If you want to create a series of line segments that create a curve, start by looking at curves that are easily parameterized by a single variable. For example, a circle centered at (cx, cy) with radius r is parameterized by the following expression:

(x, y) = (cx, cy) + r * (cos (t), sin (t)),

where t runs from 0 to 2 ?.

So, you can create a semicircular shape by, say, evaluating a circle with t k = & pi; & times; k / 30, where k runs from 0 to 30. This would give you a semicircular arc of 30 line segments.

If you want more general curves, check out the Bezier curves . They are parameterized by a value of t, which can be estimated at even intervals between 0 and 1.

+3
source

All Articles