Common.cs 10.6 KB
using CodeLibrary;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace DeviceLibrary
{
    public class Common
    {

        /// <summary>
        /// 获取角度
        /// 求3点形成的夹角
        /// </summary>
        /// <param name="pt1"></param>
        /// <param name="pt2"></param>
        /// <param name="pt0">顶角</param>
        /// <returns></returns>
        public static float getAngle2(Point pt1, Point pt2, Point pt0)
        {
            double ma_x = pt1.X - pt0.X;
            double ma_y = pt1.Y - pt0.Y;
            double mb_x = pt2.X - pt0.X;
            double mb_y = pt2.Y - pt0.Y;
            double k = (ma_x * mb_y - mb_x * ma_y);

            if (k != 0)
            {
                k = (k / Math.Sqrt(k * k));
            }
            else
            {
                k = 1;
            }

            double v1 = (ma_x * mb_x) + (ma_y * mb_y);
            double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y);
            double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y);
            double cosM = v1 / (ma_val * mb_val);

            return (float)(Math.Acos(cosM) * 180 / Math.PI * k);
        }
        /// <summary>
        /// 计算2点之间的角度
        /// </summary>
        /// <param name="pt1"></param>
        /// <param name="pt2"></param>
        /// <returns></returns>
        public static double getAngle(Point pt1, Point pt2)
        {
            double mb_x = pt2.X - pt1.X;
            double mb_y = pt2.Y - pt1.Y;
            double rotation = Math.Atan2(mb_y, mb_x);
           

            rotation = rotation / Math.PI * 180;
            return rotation;
            //double angle = 360 - rotation + 90;

            //angle = angle < 0 ? 360 + angle : angle;
            //angle = angle % 360;
            //return Math.Floor(angle / 360 * 24);
        }
        /// <summary>
        /// 计算2点之间的距离
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static double distance(Point p1, Point p2)
        {
            double result;
            result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;
        }
        /// <summary>
        /// 计算2个坐标的中心点
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        public static Point pointCenter(Point p1, Point p2)
        {
            var x1 = Math.Abs((p1.X - p2.X) / 2);
            var y1 = Math.Abs((p1.Y - p2.Y) / 2);

            var x = Math.Min(p1.X, p2.X) + x1;
            var y = Math.Min(p1.Y, p2.Y) + y1;
            return new Point(x, y);
        }

        /// <summary>
        /// 以中心点旋转Angle角度
        /// </summary>
        /// <param name="origin">中心点</param>
        /// <param name="reRotate">待旋转的点</param>
        /// <param name="angle">旋转角度, 逆时针</param>
        public static Point PointRotate(Point origin, Point rePoint, double angle)
        {

            double x = (rePoint.X - origin.X) * Math.Cos(angle) - (rePoint.Y - origin.Y) * Math.Sin(angle) + origin.X;
            double y = (rePoint.X - origin.X) * Math.Sin(angle) + (rePoint.Y - origin.Y) * Math.Cos(angle) + origin.Y;

            //rePoint.X = x;
            //rePoint.Y = y;
            return new Point((int)x, (int)y);
        }
        /// <summary>
        /// 以指定点为中心,测算指定角度,指定长度位置的点
        /// </summary>
        /// <param name="p1">原点</param>
        /// <param name="angle">角度</param>
        /// <param name="distance">距离</param>
        /// <returns></returns>
        public static Point PointWithAngle(Point p1, double angle, double distance) {
            var x2 = p1.X + distance * Math.Cos(angle / 180 * Math.PI);
            var y2 = p1.Y + distance * Math.Sin(angle / 180 * Math.PI);
            return new Point((int)x2, (int)y2);
        }
        /// <summary>
        /// 盒体到点的距离, 返回距离,最远点索引
        /// </summary>
        /// <param name="lp"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        public static (double,int) DistanceWithBoxAndPoint(List<Point> lp, Point point)
        {
            Point lc;
            if (Common.distance(lp[0], lp[1]) > Common.distance(lp[0], lp[3]))
            {
                //横着的
                lc = Common.pointCenter(lp[0], lp[1]);
                
            }
            else {
                //竖着的
                lc = Common.pointCenter(lp[0], lp[3]);
            }
            double maxlen=0;
            int maxindex = 0; ;
            for (int i = 0; i < lp.Count; i++) {
                var cc = Common.distance(point, lp[i]);
                if (cc > maxlen) {
                    maxlen = cc;
                    maxindex = i;
                }
            }
            

            return (Common.distance(point, lc), maxindex);
        }

        public static Rectangle EllipseCenter(Point p, int size) {
            return new Rectangle(p.X - size / 2, p.Y - size / 2, size, size);
        }

        /// <summary>
        /// 找到无标签角度
        /// </summary>
        /// <param name="codeInfos"></param>
        /// <param name="org"></param>
        /// <param name="widthOffset"></param>
        /// <param name="labelAngle"></param>
        /// <returns></returns>
        public static Point CalcLabelPoint(List<CodeInfo> codeInfos, Point org,int widthOffset,out int labelAngle) {
            //Point Right_Batch_Point = new Point(RobotManage.Config.Right_Batch_X, RobotManage.Config.Right_Batch_Y);
            Point Right_Batch_Point = org;
            List<int> angles = new List<int>();
            codeInfos.ForEach((c) => {
                //Point op = Common.PointRotate(Right_Batch_Point, new Point(c.X, c.Y), 83d / 180 * Math.PI);
                //c.X = op.X;
                //c.Y = op.Y;
                Point op = new Point(c.X, c.Y);
                var a = (int)getAngle(Right_Batch_Point, op);
                a += ConfigHelper.Config.Get<int>("AngleChange");
                a = a < 0 ? 360 + a : a;
                angles.Add(a);
            });
            angles.Sort();
            //if (angles.Count > 1) {
                angles.Add(360 + angles[0]);
            //}
            int biglen = 0;
            int bigangles = 0;
            for (int i = 0; i < angles.Count; i++) {
                if (angles.Count() - i < 2)
                    break;

                var x = angles[i+1] - angles[i];
                if (x > biglen)
                {
                    biglen = x;
                    bigangles = angles[i];
                }
            }
            labelAngle = bigangles + biglen / 2;
            labelAngle = labelAngle > 360 ? 360 - labelAngle : labelAngle;

            var p2 = PointWithAngle(org, labelAngle, widthOffset);
            return p2;
        }
        /// <summary>
        /// 剪裁图像
        /// </summary>
        /// <param name="src"></param>
        /// <param name="cropRect"></param>
        /// <returns></returns>
        public static Bitmap ImageCrop(Bitmap src, Rectangle cropRect)
        {
            //Rectangle cropRect = new Rectangle(0, 0, 400, 400);
            Bitmap target = new Bitmap(cropRect.Width, cropRect.Height,System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            using (Graphics g = Graphics.FromImage(target))
            {
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;

                g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height),
                      cropRect,
                      GraphicsUnit.Pixel);
            }
            return target;
        }
        /// <summary>
        /// 计算2个文本的相似度
        /// </summary>
        /// <param name="txt1"></param>
        /// <param name="txt2"></param>
        /// <returns></returns>
        public static double Sim(string txt1, string txt2)
        {
            List<char> sl1 = txt1.ToCharArray().ToList();
            List<char> sl2 = txt2.ToCharArray().ToList();
            //去重
            List<char> sl = sl1.Union(sl2).ToList<char>();

            //获取重复次数
            List<int> arrA = new List<int>();
            List<int> arrB = new List<int>();
            foreach (var str in sl)
            {
                arrA.Add(sl1.Where(x => x == str).Count());
                arrB.Add(sl2.Where(x => x == str).Count());
            }
            //计算商
            double num = 0;
            //被除数
            double numA = 0;
            double numB = 0;
            for (int i = 0; i < sl.Count; i++)
            {
                num += arrA[i] * arrB[i];
                numA += Math.Pow(arrA[i], 2);
                numB += Math.Pow(arrB[i], 2);
            }
            double cos = num / (Math.Sqrt(numA) * Math.Sqrt(numB));
            return cos;
        }

        public static T DeepClone<T>(T _object)
        {
            T dstobject;
            using (MemoryStream mStream = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(mStream, _object);
                mStream.Seek(0, SeekOrigin.Begin);//指定当前流的位置为流的开头。
                dstobject = (T)bf.Deserialize(mStream);
                mStream.Close();
            }
            return dstobject;
        }
    }
    public class Msg
    {
        public string msgtxt;
        public MsgLevel msgLevel;
        public DateTime datetime;
    }
    /*
        public class Msg
    {
        public static List<Msg> msg = new List<Msg>(); 
        public string msgtxt;
        public MsgLevel msgLevel;
        public DateTime datetime;

        public static List<Msg> get() {
            if (_setlogones) {
                _setlogones = false;
                foreach (var m in msg)
                    LogUtil.info(m.msgtxt);
            }
            List<Msg> mm = new List<Msg>(msg);
            return mm;
        }
        public static void add(string m, MsgLevel ml)
        {
            msg.Add(new Msg { msgtxt = m, msgLevel = ml, datetime=DateTime.Now });
        }
        static bool _setlogones = false;
        internal static void setlogones()
        {
            _setlogones = true;
        }

        public static void clear()
        {
            msg.Clear();
        }
    }*/
    public enum MsgLevel {

        warning,
        info
    }
}