private void DrawPanel(Bitmap map)
        {
            using (Graphics g = Graphics.FromImage(map))
            {
                for (int i = 0; i < glsInfo.PNL_List.Count; ++i)
                {
                    PNL_INFO pnlinfo = glsInfo.PNL_List[i];

                    //pnl 외곽 선 그리기
                    Pen       pnlLinePen = new Pen(pnlLineColor);
                    Rectangle rect       = new Rectangle(pnlinfo.PnlOrigin, pnlinfo.PnlSize);
                    g.DrawRectangle(pnlLinePen, rect);

                    //글자가 짤리므로...
                    Rectangle sideRect = new Rectangle(rect.X + 2, rect.Y + 3, rect.Width - 2, rect.Height - 3);

                    //가운데 글자 넣기
                    string pointStr = pnlinfo.Point_ID;

                    SolidBrush   sideBrush   = new SolidBrush(SideColor);
                    SolidBrush   cenderBrush = new SolidBrush(SideColor);
                    Font         ft          = new Font(this.Font.FontFamily, 8F);
                    StringFormat format      = new StringFormat();
                    format.Alignment     = StringAlignment.Center;
                    format.LineAlignment = StringAlignment.Center;
                    g.DrawString(pointStr, ft, cenderBrush, sideRect, format);

                    //pnl 원점 표시
                    if (PanelOrigin == true)
                    {
                        int lineLength = (int)(7 * this.persent);
                        Pen p          = new Pen(Color.Lime, 2f);

                        if (glsInfo.MapType == MapType.DataX_GateY)
                        {
                            Point pLine01 = new Point(pnlinfo.Pnl_A_Origin.X - lineLength, pnlinfo.Pnl_A_Origin.Y + lineLength);
                            Point pLine02 = new Point(pnlinfo.Pnl_A_Origin.X + lineLength, pnlinfo.Pnl_A_Origin.Y - lineLength);
                            g.DrawLine(p, pLine01, pLine02);
                        }
                        else
                        {
                            Point pLine01 = new Point(pnlinfo.Pnl_A_Origin.X - lineLength, pnlinfo.Pnl_A_Origin.Y - lineLength);
                            Point pLine02 = new Point(pnlinfo.Pnl_A_Origin.X + lineLength, pnlinfo.Pnl_A_Origin.Y + lineLength);
                            g.DrawLine(p, pLine01, pLine02);
                        }
                    }
                }
            }
        }
        private void DrawBubbleMap(Bitmap map)
        {
            //Bubble Map 그리기
            using (Graphics g = Graphics.FromImage(map))
            {
                glsInfo.BBL_List = new List <BBL_INFO>();

                Image      bubbleImg  = null;
                SolidBrush valueBrush = null;

                StringFormat format = new StringFormat();
                format.Alignment     = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;

                for (int nPnl = 0; nPnl < glsInfo.PNL_List.Count; ++nPnl)
                {
                    PNL_INFO pnlInfo = glsInfo.PNL_List[nPnl];

                    if (this.Bubble_Type == BubbleType.Panel)
                    {
                        if (this.IsWhiteType == true)
                        {
                            valueBrush = new SolidBrush(Color.Red);
                            bubbleImg  = Properties.Resources.BG_Bubble02;
                        }
                        else
                        {
                            valueBrush = new SolidBrush(Color.Blue);
                            bubbleImg  = Properties.Resources.BG_Bubble;
                        }

                        //각 Point 별 Bubble Map
                        int width  = pnlInfo.MapSize.Width;
                        int height = pnlInfo.MapSize.Height;

                        int orgX = pnlInfo.MapOrigin.X;
                        int orgY = pnlInfo.MapOrigin.Y;

                        Pen linePen = new Pen(Color.FromArgb(100, 0, 0, 255), 1);

                        //기본 Rect 그리기
                        Rectangle rect = new Rectangle(orgX, orgY, width, height);
                        g.DrawRectangle(linePen, rect);
                        BBL_INFO bubble = new BBL_INFO();
                        bubble.Rect   = rect;
                        bubble.PNL_ID = pnlInfo.Point_ID;

                        glsInfo.BBL_List.Add(bubble);
                    }
                    else
                    {
                        if (this.IsWhiteType == true)
                        {
                            valueBrush = new SolidBrush(Color.Red);
                            bubbleImg  = Properties.Resources.BG_Bubble02_S;
                        }
                        else
                        {
                            valueBrush = new SolidBrush(Color.Blue);
                            bubbleImg  = Properties.Resources.BG_Bubble_S;
                        }

                        //각 Point 별 Bubble Map
                        int width  = pnlInfo.MapSize.Width / 3;
                        int height = pnlInfo.MapSize.Height / 3;

                        int orgX = pnlInfo.MapOrigin.X;
                        int orgY = pnlInfo.MapOrigin.Y;

                        Pen linePen = new Pen(Color.FromArgb(100, 0, 0, 255), 1);

                        //기본 Rect 그리기
                        for (int x = 0; x < 3; ++x)
                        {
                            int tmpX = orgX + (x * width);

                            for (int y = 0; y < 3; ++y)
                            {
                                int tmpY = orgY + (y * height);

                                if (x == 1 && y == 1)
                                {
                                    continue;
                                }

                                Rectangle rect = new Rectangle(tmpX, tmpY, width, height);
                                g.DrawRectangle(linePen, rect);

                                BBL_INFO bubble = new BBL_INFO();
                                bubble.Rect   = rect;
                                bubble.PNL_ID = pnlInfo.Point_ID;

                                glsInfo.BBL_List.Add(bubble);
                            }
                        }
                    }
                }

                //Defect 넣기
                for (int i = 0; i < glsInfo.DEF_List.Count; ++i)
                {
                    if (glsInfo.DEF_List[i].Visible == false)
                    {
                        continue;
                    }

                    string pointStr = glsInfo.DEF_List[i].Point_ID;

                    Rectangle defRect = glsInfo.DEF_List[i].Rect;

                    for (int k = 0; k < glsInfo.BBL_List.Count; ++k)
                    {
                        if (glsInfo.BBL_List[k].Rect.IntersectsWith(defRect))
                        {
                            if (pointStr == null)
                            {
                                glsInfo.BBL_List[k].DEF_Count++;
                                break;
                            }
                            else if (glsInfo.BBL_List[k].PNL_ID == pointStr)
                            {
                                glsInfo.BBL_List[k].DEF_Count++;
                                break;
                            }
                        }
                    }
                }

                //bubble Map 비율 가져오기
                double totalCount = 0;
                double maxCount   = 0;

                for (int i = 0; i < glsInfo.BBL_List.Count; ++i)
                {
                    if (glsInfo.BBL_List[i].DEF_Count > maxCount)
                    {
                        maxCount = glsInfo.BBL_List[i].DEF_Count;
                    }

                    totalCount += glsInfo.BBL_List[i].DEF_Count;
                }

                if (glsInfo.BBL_List.Count == 0)
                {
                    return;
                }

                double maxRate   = Math.Round(maxCount / totalCount, 4) * 100;
                int    sizePoint = (int)Math.Ceiling((double)glsInfo.BBL_List[0].Rect.Height / maxRate);

                //Bubble Map 그리기
                for (int i = 0; i < glsInfo.BBL_List.Count; ++i)
                {
                    BBL_INFO b = glsInfo.BBL_List[i];

                    if (b.DEF_Count == 0)
                    {
                        continue;
                    }

                    double m = Math.Round((double)b.DEF_Count / totalCount, 4) * 100;

                    Size bSize = new Size((int)(sizePoint * m), (int)(sizePoint * m));

                    if (bSize.Width > b.Rect.Width)
                    {
                        bSize.Width = b.Rect.Width;
                    }
                    if (bSize.Height > b.Rect.Height)
                    {
                        bSize.Height = b.Rect.Height;
                    }

                    Point center = new Point(b.Rect.X + b.Rect.Width / 2, b.Rect.Y + b.Rect.Height / 2);

                    Rectangle bubbleRect = new Rectangle(center.X - bSize.Width / 2, center.Y - bSize.Height / 2, bSize.Width, bSize.Height);
                    b.BBL_Rect = bubbleRect;
                    g.DrawImage(bubbleImg, bubbleRect);

                    //값 넣기
                    g.DrawString(b.DEF_Count.ToString(), this.Font, valueBrush, b.Rect, format);
                }

                bubbleImg.Dispose();
            }
        }
        private void InitData_Panel(double per)
        {
            //변환 된 pnl 크기 및 위치
            glsInfo.PNL_List.Clear();

            int cntX = 0;
            int cntY = 0;

            int pnlOrg_X = 0;
            int pnlOrg_Y = 0;

            int pnlDefect_Size_X = 0;
            int pnlDef_Size_Y    = 0;

            int distance_X = 0;
            int distance_Y = 0;
            int remindX    = 0;
            int remindY    = 0;

            //공정 별로 X, Y 뒤집기
            cntX = glsInfo.RawInfo.PnlCount.X;
            cntY = glsInfo.RawInfo.PnlCount.Y;

            //Data Gate 찾기
            if (cntX == 0 || cntY == 0)
            {
                //this.ErrorMsg = "Glass Recipe 정보가 올바르지 않습니다.";
                return;
            }

            int xSize = glsInfo.RawInfo.GlassSize.Width / cntX;
            int ySize = glsInfo.RawInfo.GlassSize.Height / cntY;

            pnlDefect_Size_X = (int)(glsInfo.RawInfo.PnlSize.Width * per);
            pnlDef_Size_Y    = (int)(glsInfo.RawInfo.PnlSize.Height * per);

            glsInfo.MapType = MapType.DataX_GateY;

            //if (xSize > ySize)
            //{
            //    pnlDefect_Size_X = (int)(glsInfo.RawInfo.PnlSize.Width * per);
            //    pnlDef_Size_Y = (int)(glsInfo.RawInfo.PnlSize.Height * per);

            //    glsInfo.MapType = MapType.DataX_GateY;
            //}
            //else
            //{
            //    pnlDefect_Size_X = (int)(glsInfo.RawInfo.PnlSize.Height * per);
            //    pnlDef_Size_Y = (int)(glsInfo.RawInfo.PnlSize.Width * per);

            //    glsInfo.MapType = MapType.GateX_DataY;
            //}

            //pnl 위치 및 간격 설정
            int nx = glsInfo.GlassSize.Width - (pnlDefect_Size_X * cntX);
            int ny = glsInfo.GlassSize.Height - (pnlDef_Size_Y * cntY);

            remindX = nx % (cntX + 1);
            remindY = ny % (cntY + 1);

            //pnl 간격
            distance_X = nx / (cntX + 1);
            distance_Y = ny / (cntY + 1);

            pnlOrg_X = glsInfo.GlassOrigin.X + distance_X + (remindX / 2);
            pnlOrg_Y = glsInfo.GlassOrigin.Y + distance_Y + (remindY / 2);

            int pnlMapDefect_Size_X = pnlDefect_Size_X + distance_X;
            int pnlMapDef_Size_Y    = pnlDef_Size_Y + distance_Y;

            string[,] points = GetPoints(cntX, cntY);

            string pnlNum = string.Empty;

            for (int x = 0; x < cntX; ++x)
            {
                pnlOrg_X = glsInfo.GlassOrigin.X + distance_X + (pnlMapDefect_Size_X * x) + (remindX / 2);

                for (int y = 0; y < cntY; ++y)
                {
                    pnlOrg_Y = glsInfo.GlassOrigin.Y + distance_Y + (pnlMapDef_Size_Y * y) + (remindY / 2);

                    PNL_INFO pnl = new PNL_INFO();

                    //pnl ID 넣기
                    pnl.Point_ID = points[x, y];

                    //원점 및 크기
                    pnl.MapSize   = new Size(pnlMapDefect_Size_X, pnlMapDef_Size_Y);
                    pnl.MapOrigin = new Point(pnlOrg_X - distance_X / 2, pnlOrg_Y - distance_Y / 2);

                    pnl.PnlSize   = new Size(pnlDefect_Size_X, pnlDef_Size_Y);
                    pnl.PnlOrigin = new Point(pnlOrg_X, pnlOrg_Y);

                    //변환 pnl 원점

                    int a_originX = 0;
                    int a_originY = 0;

                    if (glsInfo.MapType == MapType.DataX_GateY)
                    {
                        a_originX = pnl.PnlOrigin.X + pnl.PnlSize.Width;
                        a_originY = pnl.PnlOrigin.Y + pnl.PnlSize.Height;
                    }
                    else
                    {
                        a_originX = pnl.PnlOrigin.X + pnl.PnlSize.Width;
                        a_originY = pnl.PnlOrigin.Y;
                    }

                    pnl.Pnl_A_Origin = new Point(a_originX, a_originY);

                    glsInfo.PNL_List.Add(pnl);
                }
            }
        }