Pergunta

Estou gerando dinamicamente um LineString WKT entre pontos em uma camada de mapa que está sendo gerada para exibição em OpenLayers.Gostaria de tornar as linhas entre os pontos curvas e de poder alterar dinamicamente a curvatura com base em várias variáveis ​​de entrada.

Isto é para um aplicativo de monitoramento de rede, e gostaríamos que a curvatura fosse baseada nos tempos de atraso entre os pontos (não no atraso bruto em si, mas no desvio dos valores "normais" durante um determinado período de tempo).

Embora alguns aplicativos e bancos de dados GIS suportem um CircularString extensão para WKT, OpenLayers não sabe nada sobre isso.

Então, precisarei gerar uma linha curva a partir de segmentos de linha:

No momento, as strings de linha são simplesmente:

LINESTRING(hop1_long hop1_lat, hop2_long hop2_lat)

A única maneira que posso determinar para tornar o segmento de linha "curvo" é inserir pontos intermediários:

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

Isso deveria ser perfeitamente adequado para nossa aplicação, mas não sei como gerar os pontos intermediários!

Presumo que existam métodos/algoritmos bem conhecidos para gerar uma linha "curva" fora de segmentos de linha em um plano 2D.Alguém tem alguma idéia de como fazer isso ou livros/artigos/recursos on-line que possam ser úteis?

ATUALIZAÇÃO (13/08/2010):

As curvas de Bezier eram o bilhete, e implementar o algoritmo básico de Bezier foi muito fácil depois de ler sobre ele.Mas tive que escrever algum código para gerar os pontos de controle.Aqui está o código PHP que eu criei.Isso pressupõe uma classe "Vector2d" com x e y membros.

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));
}
Foi útil?

Solução

Se você quiser gerar uma série de segmentos de linha que formam uma curva, comece observando curvas que são facilmente parametrizadas por uma única variável.Por exemplo, um círculo centrado em (cx,cy) com raio r é parametrizado pela seguinte expressão:

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

onde t vai de 0 a 2π.

Então você poderia criar uma forma semicircular, digamos, avaliando o círculo em valores tk=π×k/30, onde k vai de 0 a 30.Isso lhe daria um arco semicircular feito de 30 segmentos de linha.

Se você quiser curvas mais gerais, confira Curvas de Bézier.Eles são parametrizados por um valor t que pode ser avaliado em intervalos uniformes entre 0 e 1.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top