创建任意弯曲的众所周知的文本线串以在 OpenLayers 中显示

发布于 2024-09-13 04:57:09 字数 1772 浏览 2 评论 0原文

我正在生成用于在 OpenLayers 中显示的地图图层中的点之间动态生成 W​​KT LineString。我想让点之间的线弯曲,并且我希望能够根据各种输入变量动态改变曲率。

这是针对网络监控应用程序的,我们希望曲率基于点之间的延迟时间(不是原始延迟本身,而是给定时间段内与“正常”值的偏差)。

虽然某些 GIS 应用程序和数据库支持 WKT 的 CircularString 扩展,但 OpenLayers 对此一无所知。

所以我需要用线段生成一条曲线:

现在,线串很简单:

LINESTRING(hop1_long hop1_lat, hop2_long hop2_lat)

我可以确定使线段“弯曲”的唯一方法是插入中间点:

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

这对于我们的应用程序,但我不知道如何生成中介点!

我假设有众所周知的方法/算法用于从二维平面中的线段生成“弯曲”线。有谁对如何实现这一点有任何想法,或者可能有帮助的书籍/文章/在线资源?

更新 (2010-08-13):

贝塞尔曲线就是门票,在阅读完基本贝塞尔算法后,实现它非常容易。但我必须编写一些代码来生成控制点。这是我想出的 PHP 代码。这假定“Vector2d”类具有 xy 成员。

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));
}

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));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不在是我 2024-09-20 04:57:09

如果您想生成一系列构成曲线的线段,请首先查看易于由单个变量参数化的曲线。例如,以 (cx,cy) 为中心、半径为 r 的圆由以下表达式参数化:

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

其中 t范围从 0 到 2π。

因此,您可以通过计算圆的值 tk=π×k/30 来创建半圆形,其中 k 从 0 到 30。这将为您提供一个半圆形由 30 条线段组成的弧。

如果您想要更一般的曲线,请查看贝塞尔曲线。它们由值 t 参数化,该值可以按 0 到 1 之间的均匀间隔进行评估。

If you'd like to generate a series of line segments that make 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 could create a semi-circular shape by, say, evaluating the circle at values tk=π×k/30, where k runs from 0 to 30. This would give you a semi-circular arc made out of 30 line segments.

If you want more general curves, check out Bezier curves. They are parameterized by a value t that can be evaluated at uniform intervals between 0 and 1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文