Добрый день, люди!
Пишу сейчас программу для оптимизации движения техники по полю.
Собственно не могу справится с такой задачей:
В программу задается полигон (он же является полем), в нем задается направление трека движения техники (пусть в данном случае будет комбайн), и нужно отрисовать трек движения весь в поле, чтобы он заполнил его, т.е. выглядит примерно так (рис. 1):
здесь на первом этапе задается полигон, а потом отрисовывается трек. Проблема в том, что когда трек прямолинейный - все хорошо прорисовывается, а если он будет направлен диагонально, возникает ошибка.
Уже неделю бьюсь головой о стол, не могу решить =(
Логика у меня такая:
1)сначала я получаю максимальные координаты поля по Х и Y
2)отрисовываю трек
3)чтобы трек не заходил за пределы поля, я написал функцию определения пересечения двух отрезков, и нахожу точки пересечения отрезка трека с отрезком полигона, собственно вот код функции:
Код функции пересеченияprivate float [] CrossLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
{
float Ua, Ub, numerator_a, numerator_b, denominator, x, y;
float [] pointCross = new float[2];
denominator = (y4 - y3) * (x1 - x2) - (x4 - x3) * (y1 - y2);
numerator_a = (x4 - x2) * (y4 - y3) - (x4 - x3) * (y4 - y2);
numerator_b = (x1 - x2) * (y4 - y2) - (x4 - x2) * (y1 - y2);
Ua = numerator_a / denominator;
Ub = numerator_b / denominator;
//cout << (Ua >=0 && Ua <=1 && Ub >=0 && Ub <=1 ? "peresek" : "ne peresek") << endl;
if (Ua >= 0 && Ua <= 1 && Ub >= 0 && Ub <= 1)
{
float dx1 = x2 - x1;
float dy1 = y2 - y1;
float dx2 = x4 - x3;
float dy2 = y4 - y3;
x = dy1 * dx2 - dy2 * dx1;
y = x3 * y4 - y3 * x4;
x = ((x1 * y2 - y1 * x2) * dx2 - y * dx1) / x;
y = (dy2 * x - y) / dx2;
pointCross[0] = x;
pointCross[1] = y;
}
else
{
pointCross[0] = 0;
pointCross[1] = 0;
}
//cout << pointCross[0] << "\t" << pointCross[1] << endl;
return pointCross;
}
В ней, если нашлось пересечение - мы возвращаем координаты точки пересечения, если пересечения нету - возвращаем нуль.
4)Повторяем эти итерации пока не покроем все поле
Собственно вот весь код функции отрисовки трека:
Код функции отрисовкиprivate void buttonTrackView_Click_1(object sender, EventArgs e)
{
if (textBoxTrack.Text != "")
{
Graphics g = pictureBoxField.CreateGraphics();
g.TranslateTransform((float)pictureBoxField.Width, 0);
Pen myPen = new Pen(Color.Blue); //Кисть синего цвета для отрисовки трека
StreamReader fcoords = new StreamReader(textBoxTrack.Text);
string temp = ""; //хранит текущее число в файле до точки с запятой
while (true) //Считывание с файла
{
string text = fcoords.ReadLine();
if (text == null) break;
temp += text;
}
String[] temps = temp.Split(';'); //создаем массив для списка координат
float coordsBeginTrackX = 1;
float coordsBeginTrackY = 1;
/*for (int i = 0; i < temps.Length-1; i++) //записываем в массив координаты
{
if(i % 2 == 0)
{
//coordsBeginTrackX = Convert.ToSingle(temps[i]);
coordsBeginTrackX = 1;
}
else
{
//coordsBeginTrackY = Convert.ToSingle(temps[i]);
coordsBeginTrackY = 1;
}
}*/
//MessageBox.Show(coordsBeginTrackX.ToString() + ";" + coordsBeginTrackY.ToString());
float maxFieldX = Convert.ToSingle(coordsX.Max()); //Максимальная координата поля по Х
float maxFieldY = Convert.ToSingle(coordsY.Max()); //Максимальная координата поля по У
float coordsEndTrackX = coordsBeginTrackX;
float coordsEndTrackY = coordsBeginTrackY;
//MessageBox.Show(maxFieldY.ToString() + ";" + maxFieldX.ToString());
/*for (int i = 0; coordsEndTrackY < maxFieldY; i++) //увеличиваем отрезок трека до границы поля
{
coordsEndTrackX = i * 0.5f;
coordsEndTrackY = coordsEndTrackX;
}*/
while(coordsEndTrackY < maxFieldY) //отрисовка первого отрезка
{
//coordsEndTrackX++;
coordsEndTrackY++;
}
//g.DrawLine(myPen, coordsBeginTrackX*(-0.1f), coordsBeginTrackY * (0.1f), coordsEndTrackX * (-0.1f), coordsEndTrackY * (0.1f));
List<double> crossPointX = new List<double>(); //координаты поля по x
List<double> crossPointY = new List<double>(); //ккординаты поля по у
//MessageBox.Show(coordsEndTrackX.ToString() + ";" + coordsEndTrackY.ToString());
float[] crossPoints = new float[2];
float[] points = new float[4];
while (coordsBeginTrackX < maxFieldX)
{
for (int i = 0; i < coordsX.Count - 1; i++)
{
crossPoints = CrossLine(coordsBeginTrackX, coordsBeginTrackY, coordsEndTrackX, coordsEndTrackY,
Convert.ToSingle(coordsX[i]), Convert.ToSingle(coordsY[i]),
Convert.ToSingle(coordsX[i + 1]), Convert.ToSingle(coordsY[i + 1]));
if (crossPoints[0] != 0 && crossPoints[1] != 0)
{
crossPointX.Add(crossPoints[0]);
crossPointY.Add(crossPoints[1]);
//MessageBox.Show(crossPoints[0].ToString() + "; " + crossPoints[1].ToString());
}
}
coordsBeginTrackX += 100;
coordsEndTrackX += 100;
//g.DrawLine(myPen, coordsBeginTrackX * (-0.1f), coordsBeginTrackY * (0.1f), coordsEndTrackX * (-0.1f), coordsEndTrackY * (0.1f));
}
for (int i = 0; i < crossPointX.Count - 1; i++)
{
if (i % 2 == 0)
{
/*при небольшом сдвиге дает ошибку перевыполнения*/
g.DrawLine(myPen, Convert.ToSingle(crossPointX[i]) * (-0.1f), Convert.ToSingle(crossPointY[i]) * (0.1f),
Convert.ToSingle(crossPointX[i + 1]) * (-0.1f), Convert.ToSingle(crossPointY[i + 1]) * (0.1f));
//MessageBox.Show(crossPointX[i].ToString() + "; " + crossPointY[i].ToString() + "; итерация: " + i.ToString());
//g.DrawLine(myPen, coordsBeginTrackX * (-0.1f), coordsBeginTrackY * (0.1f), coordsEndTrackX * (-0.1f), coordsEndTrackY * (0.1f));
}
//MessageBox.Show(crossPointX[i].ToString() + "; " + crossPointY[i].ToString() + "; итерация: " + i.ToString());
//MessageBox.Show(i.ToString());
}
//MessageBox.Show(crossPointX[0].ToString() + "; " + crossPointY[0].ToString());
//g.DrawLine(myPen, Convert.ToSingle(crossPointX[0]) * (-0.1f), Convert.ToSingle(crossPointY[0]) * (0.1f),
//Convert.ToSingle(crossPointX[1]) * (-0.1f), Convert.ToSingle(crossPointY[1]) * (0.1f));
}
else
{
MessageBox.Show("Файл с координатами направления трека не выбран!");
}
}
В общем, изложил как мог детально, не судите строго мои костыли, буду благодарен любой помощи)