public bool ContainInArea(myVertex vertex) { if (ContainVertex(vertex,0) != -1) return true; double x_max = vertexes[0].X; for (int i = 1; i < vertexes.Count - 1; i++) if (vertexes[i].X > x_max) x_max = vertexes[i].X; x_max += 10; mySection luch = new mySection(vertex, new myVertex(x_max,vertex.Y)); int k = 0; for (int i = 0; i < vertexes.Count - 1; i++ ) { mySection section = new mySection(vertexes[i], vertexes[i + 1]); myVertex intersection = luch.Intersect(section); if (intersection != null) { k++; if (this.ContainVertex(intersection,0) != -1) i++; } } if (k>0 && k % 2 == 1) return true; else return false; }
public bool AddVertex(myVertex vertex, Graphics graphics, Pen pen) { bool result = this.AddVertex(vertex); if (result == true) { vertex.Paint(graphics, pen); new mySection(vertexes[vertexes.Count - 2], vertexes[vertexes.Count - 1]).Paint(graphics, pen); } else new mySection(vertexes[vertexes.Count - 2], vertexes[0]).Paint(graphics, pen); return result; }
public bool AddVertex(myVertex vertex) { bool result = true; if (vertexes[0].DistanceTo(vertex) < 4) { result = false; vertexes.Add(vertexes[0]); } else vertexes.Add(vertex); return result; }
public bool Contain(myVertex vertex) { if (right.X != left.X && right.Y != left.Y) { double t_x = (vertex.X - left.X) / (right.X - left.X); double t_y = (vertex.Y - left.Y) / (right.Y - left.Y); if (Math.Abs(t_x - t_y) < 0.001 && t_x >= 0 && t_x <= 1 && t_y>=0 && t_y <=1) return true; else return false; } else if (right.X == left.X && right.Y != left.Y) { if (vertex.X == right.X) { if ((vertex.Y >= left.Y && vertex.Y <= right.Y) || (vertex.Y <= left.Y && vertex.Y >= right.Y)) return true; else return false; } else return false; } else if (right.X != left.X && right.Y == left.Y) { if (vertex.Y == right.Y) { if ((vertex.X >= left.X && vertex.X <= right.X) || (vertex.X <= left.X && vertex.X >= right.X)) return true; else return false; } else return false; } return false; }
public myVertex Intersect(mySection section) { myVertex result = null; //если вектора не коллинеарны - просто найдем координаты точки пересечения double dx = right.X - left.X; double dy = right.Y - left.Y; double sdx = section.right.X - section.left.X; double sdy = section.right.Y - section.left.Y; //проверяем вектора на коллинеарность if (dx * sdy - dy * sdx != 0) { /* * если они не коллинеарны, тогда точки пересечения отрезков либо нет, либо она одна * * x_l + a * dx = s_x_l + b * sdx | * sdy * y_l + a * dy = s_y_l + b * sdy | * sdx * * sdy*x_l + sdy*a*dx = sdy*s_x_l + sdy*b*sdx (1) * sdx*y_l + sdx*a*dy = sdx*s_y_l + sdx*b*sdy (2) * * (1)-(2) = sdy*(x_l-y_l) + a*(sdy*dx - sdx*dy) = sdy*s_x_l - sdx*s_y_l; * a = ( sdy*s_x_l - sdx*s_y_l - sdy*(x_l-y_l) )/(sdy*dx - sdx*dy); * таким образом вычислим параметр а * */ double a = (sdy * section.left.X - sdx * section.left.Y - (sdy * left.X - sdx * left.Y)) / (sdy * dx - sdx * dy); /* * x_l + a * dx = s_x_l + b * sdx | * dy * y_l + a * dy = s_y_l + b * sdy | * dx * * dy*x_l + dy*a*dx = dy*s_x_l + dy*b*sdx (1) * dx*y_l + dx*a*dy = dx*s_y_l + dx*b*sdy (2) * * (1)-(2) = dy*x_l - dx*y_l = b * (dy*sdx - dx*sdy) + (dy*s_x_l - dx*s_y_l) * b = (dy*x_l - dx*y_l - (dy*s_x_l - dx*s_y_l))/(dy*sdx - dx*sdy) * таким образом вычислим параметр b */ double b = (dy * left.X - dx * left.Y - (dy * section.left.X - dx * section.left.Y)) / (dy * sdx - dx * sdy); //если оба параметра лежат на [0;1], тогда точка пересечения отрезков - лежит на отрезков (!) if (a >= 0 && a <= 1 && b >= 0 && b <= 1) result = new myVertex(left.X + a * dx, left.Y + a * dy); } else { /* * теперь рассмоотрим случай с коллинеарными векторами * 1) dx != 0 * 2) dy != 0 * 3) а если и то и то 0, тогда это не отрезок, а точка - таких в данном случае сработает алгоритм заполнения полигона * * суть метода: * найдем какая точка из концов отсекающего отрезка наиболее приближена к правой границе со стороны левой * она и будет результатом (если конечно она попадает на [0;1] */ if (dx != 0) { double t_left = (section.left.X - left.X) / (dx); double t_right = (section.right.X - left.X) / (dx); double result_t = -1; if (t_left <= 1 && t_left > result_t) result_t = t_left; if (t_right <= 1 && t_right > result_t) result_t = t_right; //теперь проверим, а точно ли точка лежит на отрезке if (result_t != -1 && (left.Y + result_t * dy == section.left.Y || left.Y + t_right * dy == section.right.Y)) result = new myVertex(left.X + result_t * dx, left.Y + result_t * dy); } else if (dy != 0) { //всё то же, что и в предыдущем пункте, но с dy double t_left = (section.left.Y - left.Y) / (dy); double t_right = (section.right.Y - left.Y) / (dy); double result_t = -1; if (t_left <= 1 && t_left > result_t) result_t = t_left; if (t_right <= 1 && t_right > result_t) result_t = t_right; //теперь проверим, а точно ли точка лежит на отрезке if (result_t != -1 && (left.X + result_t * dx == section.left.X || left.X + t_right * dx == section.right.X)) result = new myVertex(left.X + result_t * dx, left.Y + result_t * dy); } else throw new Exception("Ошибка при поиске пересечения отрезков:\ndx == dy == 0"); } return result; }
public mySection(myVertex Left, myVertex Right) { this.left = new myVertex(Left); this.right = new myVertex(Right); }
public myPolygon(myVertex head, Graphics graphics, Pen pen) { vertexes = new List<myVertex>(); vertexes.Add(head); head.Paint(graphics, pen); }
public int ContainVertex(myVertex vertex, int start_pos) { for (int i = start_pos; i < vertexes.Count; i++) if (vertex.Equals(vertexes[i])) return i; return -1; }
public myPolygon(myVertex head) { vertexes = new List<myVertex>(); vertexes.Add(head); }
public bool Equals(myVertex point) { return (Math.Abs(x - point.x) < 0.001 && Math.Abs(y - point.y) < 0.001); }
public double DistanceTo(myVertex vertex) { return Math.Sqrt((vertex.x - x) * (vertex.x - x) + (vertex.y - y) * (vertex.y - y)); }
public double CountAngleBetween(myVertex first, myVertex third) { return (new myVector(first, this).getAngleTo(new myVector(this, third))) *180/Math.PI; }
public myVertex(myVertex vertex) { this.x = vertex.x; this.y = vertex.y; }
public myVector(myVertex start, myVertex end) { this.x = end.X - start.X; this.y = end.Y - start.Y; }