SplitItem.cs 6.0 KB
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AccImage
{
    public class SplitItem
    {
        public bool isEnd = false;
        public double avgRadius = 0;
        public int centerX = 0;
        public int centerY = 0;
        public double currentMaxRadius = 0;
        public List<Circle> circles = new List<Circle>();

        /// <summary>
        /// 一遍结束后调用
        /// </summary>
        public void calOneItem(double theFixRadius=-1)
        {
            //该半径是否有效
            bool isValid = false;
            if (avgRadius == 0)
            {
                isValid = true;
            }
            else
            {
                //与平均半径差值在10%以内,认为OK
                double diff = avgRadius - currentMaxRadius;
                if (diff/avgRadius <= 0.4)
                {
                    isValid = true;
                }
            }
            if (isValid)
            {
                Circle circle = new Circle();
                if(theFixRadius != -1 && currentMaxRadius > theFixRadius)
                {
                    currentMaxRadius = theFixRadius;
                }
                circle.radius = currentMaxRadius;
                circle.x = centerX;
                circle.y = centerY;
                circles.Add(circle);
                currentMaxRadius = 0;
                centerX = 0;
                centerY = 0;
                ////平均半径
                //double total = 0;
                //foreach (Circle c in circles)
                //{
                //    total = total + c.radius;
                //}
                //avgRadius = total / circles.Count;
                if(circle.radius > avgRadius)
                {
                    avgRadius = circle.radius;
                }
            }
            else
            {
                isEnd = true;
            }
            
        }
        

        public List<List<Circle>> groupCircles(double w, double h, Point2d center)
        {
            foreach(Circle c in circles)
            {
                c.calDistanceToCenter(center);
            }
            List<List<Circle>> allGroupCircle = new List<List<Circle>>();
            List<int> allreadyGroup = new List<int>();
            while (true)
            {
                List<Circle> groupCircle = new List<Circle>();
                Circle labelCircle = null;
                for (int i=0;i<circles.Count; i++)
                {
                    if (!allreadyGroup.Contains(i))
                    {
                        Circle c = circles[i];
                        if (labelCircle == null)
                        {
                            labelCircle = c;
                            allreadyGroup.Add(i);
                            groupCircle.Add(c);
                        }
                        else
                        {
                            //到圆心的距离差小于H
                            if (Math.Abs(c.distanceToCenter - labelCircle.distanceToCenter) < h)
                            {
                                //两圆心之间的距离+直径小于W认为是同一个元器件
                                if (c.distanceToCircle(labelCircle) < w)
                                {
                                    groupCircle.Add(c);
                                    allreadyGroup.Add(i);
                                }
                            }
                        }
                    }
                }
                allGroupCircle.Add(groupCircle);
                if (allreadyGroup.Count == circles.Count)
                {
                    break;
                }
            }
            return allGroupCircle;
        }

        /// <summary>
        /// 该点是否与其他圆内,或与圆的中心距离在半径内
        /// </summary>
        /// <param name="px"></param>
        /// <param name="py"></param>
        /// <returns></returns>
        public double minDistanceToCircles(int px, int py, Point2d reelCenter, double oneBlobWidth =-1, double oneBlobRadius = -1)
        {
            Point2d point = new Point2d(px, py);
            double minDistanceToCircle = -1;
            foreach (Circle c in circles)
            {
                Point2d circleCenter = new Point2d(c.x, c.y);
                double distanceToCircle = point.DistanceTo(circleCenter);
                if (distanceToCircle <= c.radius)
                {
                    return 0;
                }
                //当前点到料盘中心与圆心到料盘中心的距离在直径内,忽略
                //if(oneBlobRadius != -1 && oneBlobWidth != -1)
                //{
                //    double distanceToReelCenter = point.DistanceTo(reelCenter);
                //    double circleCenterToReelCenter = circleCenter.DistanceTo(reelCenter);
                //    if (Math.Abs(distanceToReelCenter - circleCenterToReelCenter) < oneBlobRadius)
                //    {
                //        if (distanceToCircle < oneBlobWidth)
                //        {
                //            return 0;
                //        }
                //    }
                //}

                if (minDistanceToCircle == -1 || distanceToCircle < minDistanceToCircle)
                {
                    minDistanceToCircle = distanceToCircle - c.radius;
                }
            }
            return minDistanceToCircle;
        }

    };

    public class Circle
    {
        public int x;
        public int y;
        public double radius;
        public double distanceToCenter = 0;

        public double distanceToCircle(Circle c)
        {
            double distance = new Point2d(x, y).DistanceTo(new Point2d(c.x, c.y));
            return distance + radius + c.radius;
        }
        public void calDistanceToCenter(Point2d center)
        {
            if(center.X > 0 && distanceToCenter <= 0)
            {
                distanceToCenter = center.DistanceTo(new Point2d(x, y));
            }
        }
    }
}