Построить линию между двумя точками географических координат графически - C#
Формулировка задачи:
Имея широту и долготу двух точек, можно ли каким-то образом изобразить графически как она будет направлена?
Решение задачи: «Построить линию между двумя точками географических координат графически»
textual
Листинг программы
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication339
{
public partial class Form1 : Form
{
public PointF P1 { get; set; }
public PointF P2 { get; set; }
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
P1 = new PointF(51.3f, -0.1f);
P2 = new PointF(28.6f, 77.2f);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.TranslateTransform(ClientSize.Width / 2, ClientSize.Height / 2);
var path = new GraphicsPath();
var points = new List<PointF>();
var gridStep = 15;
var step = 5;
//параллели
for (var lat = -90; lat < 90; lat += gridStep)
{
for (var lon = -180; lon <= 180; lon += step)
points.Add(new Point3(lat, rotate1 + lon).Projection(rotate2, R));
path.StartFigure();
path.AddLines(points.ToArray());
points.Clear();
}
//меридианы
for (var lon = -180; lon <= 180; lon += gridStep)
{
for (var lat = -90; lat <= 90; lat += step)
points.Add(new Point3(lat, rotate1 + lon).Projection(rotate2, R));
path.StartFigure();
path.AddLines(points.ToArray());
points.Clear();
}
//отрисовка
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.DrawPath(Pens.Silver, path);
//рисуем линию между точками
var p1 = new Point3(P1.X, P1.Y + rotate1);
var p2 = new Point3(P2.X, P2.Y + rotate1);
for (int i = 0; i <= 100; i++)
points.Add(p1.Lerp(p2, i / 100f).Projection(rotate2, R));
using(var pen = new Pen(Color.Red, 2))
e.Graphics.DrawLines(pen, points.ToArray());
}
private double rotate2 = 0;
private double rotate1 = 0;
private double R = 100;
private Point lastMousePos;
protected override void OnMouseMove(MouseEventArgs e)
{
if(MouseButtons == MouseButtons.Left)
{
var dx = e.X - lastMousePos.X;
var dy = e.Y - lastMousePos.Y;
rotate1 += dx / 2.0;
rotate2 -= dy / 2.0;
Invalidate();
}
lastMousePos = e.Location;
}
protected override void OnMouseWheel(MouseEventArgs e)
{
if (e.Delta < 0) R *= 0.98;
if (e.Delta > 0) R *= 1.02;
Invalidate();
}
}
class Point3
{
public double X;
public double Y;
public double Z;
public Point3(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public Point3(double latitude, double longitude)
{
latitude *= Math.PI / 180;
longitude *= Math.PI / 180;
X = Math.Cos(latitude) * Math.Cos(longitude);
Y = Math.Cos(latitude) * Math.Sin(longitude);
Z = Math.Sin(latitude);
}
public PointF Projection(double rotate, double R)
{
rotate *= Math.PI / 180;
var kz = Math.Cos(rotate) * R;
var kx = Math.Sin(rotate) * R;
return new PointF((float)(Y * R), -(float)(Z * kz + X * kx));
}
public Point3 Lerp(Point3 p, float k)
{
var x = X * (1 - k) + p.X * k;
var y = Y * (1 - k) + p.Y * k;
var z = Z * (1 - k) + p.Z * k;
var l = Math.Sqrt(x * x + y * y + z * z);
return new Point3(x / l, y / l, z / l);
}
}
}