//获取点集中,与指定点距离最大的点下标 private int GetMaxDistancePointIndex(ShootPoint P, ref List <ShootPoint> Points) { //构造间距(平方)序列 double[] Mat = new double[Points.Count]; //中间变量 ShootPoint TempPoint; double DeltaX = 0; double DeltaY = 0; //填充序列 for (int i = 0; i < Points.Count; i++) { //获取对应的点 TempPoint = Points.ElementAt(i); //计算坐标增量 DeltaX = TempPoint.X_Pos - P.X_Pos; DeltaY = TempPoint.Y_Pos - P.Y_Pos; //获取两点间距的平方(因为最终只是比大小,所以省去了开方这一步骤用以节省运算量) Mat[i] = DeltaX * DeltaX + DeltaY * DeltaY; } //遍历间距序列,找到值最大的元素 return(Array.IndexOf(Mat, Mat.Max())); }
//判断某点是否在圆范围内(在圆上和在圆内都算在圆范围内) public bool isInThisCircle(ShootPoint Point) { double DeltaX = Point.X_Pos - Center.X_Pos; double DeltaY = Point.Y_Pos - Center.Y_Pos; //忽略0.01mm以内的偏差,防止出现边界情况导致错误 return((this.radius * this.radius + 1e-04) >= (DeltaX * DeltaX + DeltaY * DeltaY)); }
//以两点连线作为直径构造圆 public Circle(ShootPoint Point1, ShootPoint Point2) { //获取圆心坐标 double Center_X = (Point1.X_Pos + Point2.X_Pos) / 2; double Center_Y = (Point1.Y_Pos + Point2.Y_Pos) / 2; center = new ShootPoint(Center_X, Center_Y); //计算半径 double DeltaX = center.X_Pos - Point2.X_Pos; double DeltaY = center.Y_Pos - Point2.Y_Pos; radius = Math.Sqrt(DeltaX * DeltaX + DeltaY * DeltaY); }
//画一个点(此单位为mm,将在内部进行转换) private void DrawPoint(ShootPoint P, Color color) { //申请一个蓝画刷 Pen pen = new Pen(color); Graphics Grphc = this.GrphcBuf.Graphics; //反向映射 int Point_X = (int)(P.X_Pos / mm_PixelRate_X); int Point_Y = (int)(P.Y_Pos / mm_PixelRate_Y); //获得外框矩形参数 Rectangle RecCenter = new Rectangle(Point_X - 4, Point_Y - 4, 8, 8); //画圆心 Grphc.FillEllipse(pen.Brush, RecCenter); //从缓冲区输出至图框 this.GrphcBuf.Render(); }
//以三个不共线的点确定的三角形构造圆,此时圆为三角形的外接圆 //若共线,则按照无参数方式构造空圆 public Circle(ShootPoint Point1, ShootPoint Point2, ShootPoint Point3) { //求从点1出发指向点2、3的向量 Vector2 Vec_1 = new Vector2(Point1, Point2); Vector2 Vec_2 = new Vector2(Point1, Point3); //如果斜率差小于一定阈值,则认为是一条直线 if (Vec_1.isCollinear(Vec_2)) { center = new ShootPoint(0, 0); radius = 0; } else { //求从点1出发指向点2、3向量的正交向量,作为其连线中垂线的方向向量 Vector2 Vector_1 = Vec_1.GetOrthogonalVector(); Vector2 Vector_2 = Vec_2.GetOrthogonalVector(); //获取两直线中点 ShootPoint CenterPoint1 = new ShootPoint((Point1.X_Pos + Point2.X_Pos) / 2, (Point1.Y_Pos + Point2.Y_Pos) / 2); ShootPoint CenterPoint2 = new ShootPoint((Point1.X_Pos + Point3.X_Pos) / 2, (Point1.Y_Pos + Point3.Y_Pos) / 2); ///则直线参数方程可以是:直线上某点P = CenterPoint + k * Vector_1.其中,k为任意实数。 //据参数方程求中垂线交点参数 double k1 = (Vector_2.X * (CenterPoint1.Y_Pos - CenterPoint2.Y_Pos) + Vector_2.Y * (CenterPoint2.X_Pos - CenterPoint1.X_Pos)) / (Vector_1.X * Vector_2.Y - Vector_2.X * Vector_1.Y); //求得交点坐标,即为圆心坐标 center = new ShootPoint(new Vector2(CenterPoint1) + k1 * Vector_1); ///验证正确性用 //double k2 = (k1 * Vector_1.Y + CenterPoint1.Y_Pos - CenterPoint2.Y_Pos) / Vector_2.Y; //ShootPoint CheckCenter = new ShootPoint(new Vector2(CenterPoint2) + k2 * Vector_2); //计算半径 double DeltaX = Point1.X_Pos - Center.X_Pos; double DeltaY = Point1.Y_Pos - Center.Y_Pos; radius = Math.Sqrt(DeltaX * DeltaX + DeltaY * DeltaY); } }
public Vector2(ShootPoint Src, ShootPoint Aim) { x = Aim.X_Pos - Src.X_Pos; y = Aim.Y_Pos - Src.Y_Pos; }
public Vector2(ShootPoint Point) { x = Point.X_Pos; y = Point.Y_Pos; }
//构造空圆 public Circle() { center = new ShootPoint(0, 0); radius = 0; }
//以圆心和半径构造圆 public Circle(ShootPoint Center, double R) { center = Center; radius = R; }
//从已经确定在圆上的一点和其他三点中确定最小包络圆 private Circle GetNewCircle(ShootPoint P_Certain, ref List <ShootPoint> CirclePoints) { List <ShootPoint> Points = new List <ShootPoint>(); List <ShootPoint> AllPoints = CirclePoints.GetRange(0, CirclePoints.Count); //添加必在圆上的点到点集中 Points.Add(P_Certain); AllPoints.Add(P_Certain); //第一轮尝试 Points.Add(CirclePoints.ElementAt(0)); Points.Add(CirclePoints.ElementAt(1)); //求出此三点的最小包络圆 Circle MinCircle = GetMinCircleOf3Points(ref Points); //判断是否包含所有点 if (isAllPointsInCircle(ref AllPoints, MinCircle)) { //仅保留在圆上的点,用于优化算法运行速度 CirclePoints = Points; return(MinCircle); } else if (CirclePoints.Count < 3) { //如果在圆上的点比3小,就说明用于输入函数的点一定全拿来生成新圆了 //如此还没通过上面的条件,那么一定是前面的运算中哪里算错了。 return(new Circle()); } //第二轮尝试 if (Points.Count == 3) { //如果在生成上一个圆时,三个点都在圆上,拿掉最后面的点。 Points.RemoveAt(2); } Points.Add(CirclePoints.ElementAt(2)); //求出此三点的最小包络圆 MinCircle = GetMinCircleOf3Points(ref Points); //判断是否包含所有点 if (isAllPointsInCircle(ref AllPoints, MinCircle)) { //仅保留在圆上的点,用于优化算法运行速度 CirclePoints = Points; return(MinCircle); } //最后一轮尝试 if (Points.Count == 3) { //如果在生成上一个圆时,三个点都在圆上,拿掉1点。 Points.RemoveAt(1); } Points.Add(CirclePoints.ElementAt(1)); //求出此三点的最小包络圆 MinCircle = GetMinCircleOf3Points(ref Points); //判断是否包含所有点 if (isAllPointsInCircle(ref AllPoints, MinCircle)) { //仅保留在圆上的点,用于优化算法运行速度 CirclePoints = Points; return(MinCircle); } //按道理讲不会到这里,若到了这里,说明出现了输入上的问题。 return(new Circle()); }