Я динамически генерирую строку WKT LineString между точками в слое карты, создаваемом для отображения в OpenLayers. Я хотел бы, чтобы линии между точками были изогнутыми, и я хотел бы иметь возможность динамически изменять кривизну на основе различных входных переменных.
Это для приложения мониторинга сети, и мы хотели бы, чтобы кривизна основывалась на временах задержки между точками (не на самой необработанной задержке, а на отклонении от «нормальных» значений в течение заданного периода времени).
Хотя некоторые ГИС-приложения и базы данных поддерживают расширение CircularString
для WKT, OpenLayers ничего об этом не знает.
Поэтому мне нужно создать изогнутую линию из сегментов линии:
Прямо сейчас строки строки просто:
LINESTRING(hop1_long hop1_lat, hop2_long hop2_lat)
Единственный способ, которым я могу определить, чтобы сделать линейный сегмент «изогнутым», - это вставить промежуточные точки:
LINESTRING(hop1_long hop1_lat, long1 lat1, long2 lat2, ..., hop2_long hop2_lat)
Этого должно быть вполне достаточно для нашего приложения, но я не знаю, как генерировать промежуточные точки!
Я предполагаю, что существуют хорошо известные методы/алгоритмы для создания «изогнутой» линии из сегментов линии в 2d-плоскости. Есть ли у кого-нибудь идеи о том, как это сделать, или книги/статьи/интернет-ресурсы, которые могут быть полезны?
ОБНОВЛЕНИЕ (13 августа 2010 г.):
Кривые Безье были билетом, и реализовать базовый алгоритм Безье было довольно легко после прочтения о нем. Но мне пришлось написать код для генерации контрольных точек. Вот код PHP, который я придумал. Это предполагает класс "Vector2d" с элементами x
и 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)); }