public static PadErrorDetail[] ComparePad(Models.Model model, PadSegmentInfo[] padSegment) { List <PadErrorDetail> padError = new List <PadErrorDetail>(); double umPPixel = 25.4 / model.DPI * 1000; for (int i = 0; i < model.Gerber.PadItems.Count; i++) { Models.PadItem padItem = model.Gerber.PadItems[i]; if (!padItem.Enable || model.Gerber.MarkPoint.PadMark.Contains(i)) { continue; } PadErrorDetail padEr = CheckPad(padItem, padSegment, umPPixel, false); if (padEr == null) { continue; } else { //padEr = CheckPad(padItem, padSegment, umPPixel, true); //if (padEr == null) // continue; //else padError.Add(padEr); } } return(padError.ToArray()); }
private static PadErrorDetail CheckPad(Models.PadItem padItem, PadSegmentInfo[] padSegment, double umPPixel, bool Inflate = false) { Rectangle boundPadRef = padItem.BoudingAdjust; if (Inflate) { boundPadRef.Inflate(3, 3); } double sPadRef = padItem.Area; List <int> idPadSegOverlap = new List <int>(); for (int j = 0; j < padSegment.Length; j++) { //if (boundPadRef.IntersectsWith(padSegment[j].Bouding)) //{ // idPadSegOverlap.Add(j); //} if (IntersectsContour(padItem.ContourAdjust, padSegment[j].Contours, boundPadRef)) { idPadSegOverlap.Add(j); } } boundPadRef = padItem.Bouding; PadErrorDetail padEr = new PadErrorDetail(); double scaleArea = 0; double scaleAreaAddperimeter = 0; double shiftx = 0; double shifty = 0; int inflate = 40; padEr.AreaStdHight = padItem.AreaThresh.UM_USL; padEr.AreaStdLow = padItem.AreaThresh.PERCENT_LSL; padEr.ShiftXStduM = padItem.ShiftXThresh.UM_USL; padEr.ShiftYStduM = padItem.ShiftYThresh.UM_USL; padEr.ShiftXStdArea = padItem.ShiftXThresh.PERCENT_LSL; padEr.ShiftYStdArea = padItem.ShiftYThresh.PERCENT_LSL; padEr.ROI = Rectangle.Inflate(boundPadRef, inflate, inflate); padEr.Pad = padItem; if (padItem.FOVs.Count > 0) { padEr.FOVNo = padItem.FOVs[0]; } if (idPadSegOverlap.Count > 0) { double areaAllPadSeg = 0; double perimeter = 0; Rectangle boundAllPadSeg = new Rectangle(); for (int j = 0; j < idPadSegOverlap.Count; j++) { PadSegmentInfo padSeg = padSegment[idPadSegOverlap[j]]; areaAllPadSeg += padSeg.Area; using (VectorOfPoint cnt = new VectorOfPoint(padSeg.Contours)) { perimeter += CvInvoke.ArcLength(cnt, true) / 2; } if (j == 0) { boundAllPadSeg = padSeg.Bouding; continue; } if (padSeg.Bouding.X < boundAllPadSeg.X) { boundAllPadSeg.X = padSeg.Bouding.X; } if (padSeg.Bouding.Y < boundAllPadSeg.Y) { boundAllPadSeg.Y = padSeg.Bouding.Y; } if (padSeg.Bouding.X + padSeg.Bouding.Width > boundAllPadSeg.X + boundAllPadSeg.Width) { boundAllPadSeg.Width = padSeg.Bouding.X + padSeg.Bouding.Width - boundAllPadSeg.X; } if (padSeg.Bouding.Y + padSeg.Bouding.Height > boundAllPadSeg.Y + boundAllPadSeg.Height) { boundAllPadSeg.Height = padSeg.Bouding.Y + padSeg.Bouding.Height - boundAllPadSeg.Y; } } padEr.Center = new Point(boundAllPadSeg.X + boundAllPadSeg.Width / 2, boundAllPadSeg.Y + boundAllPadSeg.Height / 2); scaleArea = areaAllPadSeg * 100 / sPadRef; scaleAreaAddperimeter = (areaAllPadSeg + perimeter) * 100 / sPadRef; shiftx = (Math.Max(Math.Abs(boundPadRef.X - boundAllPadSeg.X), Math.Abs((boundPadRef.X + boundPadRef.Width) - (boundAllPadSeg.X + boundAllPadSeg.Width))) * umPPixel); shifty = (Math.Max(Math.Abs(boundPadRef.Y - boundAllPadSeg.Y), Math.Abs((boundPadRef.Y + boundPadRef.Height) - (boundAllPadSeg.Y + boundAllPadSeg.Height))) * umPPixel); bool insert = false; double deviation = (100 - (sPadRef / umPPixel)) / 2; deviation = deviation < 0 ? 0 : deviation; if (scaleAreaAddperimeter < padItem.AreaThresh.PERCENT_LSL - deviation) { //if (sPadRef > 100 || (sPadRef < 100 && scaleArea < 5)) { insert = true; } } if (scaleArea > padItem.AreaThresh.UM_USL) { insert = true; } if (shiftx > padItem.ShiftXThresh.UM_USL) { insert = true; } if (shifty > padItem.ShiftXThresh.UM_USL) { insert = true; } if (insert) { padEr.Area = scaleArea; padEr.ShiftX = shiftx; padEr.ShiftY = shifty; return(padEr); } else { // pad pass return(null); } } else { // not found solder paste return(padEr); } }