} // Default constructor public CListLines(int maxL2, int maxV, int maxArc) // constructor { MaxPoly = maxL2; MaxVert = maxV; MaxArc = maxArc; pQ = new CQue(1000); // necessary to find connected components nArc = 0; nPolygon = 0; Polygon = new CPolygon[MaxPoly]; int i = 0; for (i = 0; i < MaxPoly; i++) { Polygon[i] = new CPolygon(); } Vert = new iVect2[MaxVert]; for (i = 0; i < MaxVert; i++) { Vert[i] = new iVect2(); } Arc = new CArc[MaxArc]; for (i = 0; i < MaxArc; i++) { Arc[i] = new CArc(); } Arc2 = new CArc2[MaxArc]; for (i = 0; i < MaxArc; i++) { Arc2[i] = new CArc2(); } Step = new iVect2[4]; for (i = 0; i < 4; i++) { Step[i] = new iVect2(); } Norm = new iVect2[4]; for (i = 0; i < 4; i++) { Norm[i] = new iVect2(); } Step[0].X = 1; Step[0].Y = 0; Step[1].X = 0; Step[1].Y = 1; Step[2].X = -1; Step[2].Y = 0; Step[3].X = 0; Step[3].Y = -1; Norm[0].X = 0; Norm[0].Y = 1; Norm[1].X = -1; Norm[1].Y = 0; Norm[2].X = 0; Norm[2].Y = -1; Norm[3].X = 1; Norm[3].Y = 0; } //*************** end constructor *********************
} // ********************** end DrawArc ********************************* public int Curvature(int x1, int y1, int x2, int y2, int x3, int y3, double eps, ref CArc arc) /* Calculates the curvature 'k' of an arc lying in the tolerance tube * around the given two polygon edges [(x1,y1), (x2,y2)] and * [(x2,y2), (x3,y3)] and having the outer boundary of the tube as its * tangent. The tangency point should be not farther as the half length * of the shorter edge from (x2,y2). The radius of the arc should be as * large as possible. */ { //bool deb = false; double a1, a2, lp, // Variables for calculating the projections dx1, dy1, dx2, dy2, len1, len2, // Inkrements, lengths of edges cosgam, // cosine of the outer angle between the edges sinbet, cosbet, // cosine and sine of the half angle strip = 0.6, // correcture of the deviation k, cru1, cru2; // curvature for long and short edges dx1 = (double)(x2 - x1); dy1 = (double)(y2 - y1); // first edge len1 = Math.Sqrt(dx1 * dx1 + dy1 * dy1); dx2 = (double)(x3 - x2); dy2 = (double)(y3 - y2); // second edge len2 = Math.Sqrt(dx2 * dx2 + dy2 * dy2); if ((len1 == 0.0) || (len2 == 0.0)) { return(-1); } cosgam = (dx1 * dx2 + dy1 * dy2) / len1 / len2; // angle between the edges if (Math.Abs(cosgam) <= 1.0) { sinbet = Math.Sqrt((1.0 - cosgam) * 0.5); // half angle } else { sinbet = 0.0; } cosbet = Math.Sqrt((1.0 + cosgam) * 0.5); cru1 = (1.0 - cosbet) / (eps - strip); // long edge, it is important // that the arc goes throught the vertex double min_len = len1; if (len2 < min_len) { min_len = len2; } if (min_len != 0.0 && cosbet != 0.0) { cru2 = 2.0 * sinbet / cosbet / min_len; // short edge, it is important } else { cru2 = 0.0; // that the tangency is in the midle of the shortest edge } if ((Math.Abs(cru1) > Math.Abs(cru2)) && cru1 != 0.0) { if (cosbet != 0.0 && cru1 != 0.0) { lp = sinbet / cosbet / cru1; // distance of the point of tangency from (x2, y2) } else { lp = 100.0; } k = cru1; // first curvature } else { lp = min_len / 2.0; k = cru2 * 0.95; // second curvature } if (dx1 * dy2 - dy1 * dx2 > 0.0) { k = -k; // the sign } // the first edge is devided in relation a1 : a2 a1 = lp / len1; a2 = 1.0 - a1; if (k != 0.0) { arc.rad = 1.0F / (float)k; } else { arc.rad = 0.0F; } arc.xb = (float)(x1 * a1 + x2 * a2); // first tangency (begin of the arc) arc.yb = (float)(y1 * a1 + y2 * a2); a1 = lp / len2; a2 = 1.0 - a1; arc.xe = (float)(x3 * a1 + x2 * a2); // second tangency (end of the arc) arc.ye = (float)(y3 * a1 + y2 * a2); double AbsR, R, chord_X, chord_Y, Length, Lot_x, Lot_y; R = arc.rad; AbsR = R; if (R < 0.0) { AbsR = -R; } chord_X = arc.xe - arc.xb; chord_Y = arc.ye - arc.yb; // the chord Length = Math.Sqrt(chord_X * chord_X + chord_Y * chord_Y); // Length of the chord if (R < 0.0) // 'Lot' is orthogonal to chord { Lot_x = chord_Y; Lot_y = -chord_X; } else { Lot_x = -chord_Y; Lot_y = chord_X; } if (2 * AbsR < Length) { return(-1); } if (Length < 0.1) { return(-2); } double Lot = Math.Sqrt(4 * R * R - Length * Length); arc.xm = (float)((arc.xb + arc.xe) / 2 - Lot_x * Lot / 2 / Length); arc.ym = (float)((arc.yb + arc.ye) / 2 - Lot_y * Lot / 2 / Length); if ((arc.xe == arc.xb) && (arc.ye == arc.yb)) { // can a closed line of three points exist?? return(-2); } return(0); } // *********************** end Curvature ******************************************************
} //************************* end DrawPolygons ************************* public int DrawArc(CArc arc, bool DispRad, Form1 fm1, int ip) /* Draws an arc with radius arc.rad going through (arc.xb, arc.yb) and (arc.xe, arc.ye) * with the scale "fm1.Scale1". Draws also the radii at the ends of the arc if arc.rad < maxRad. * Starts at the point (arc.xb, arc.yb) undependently of the tracing direction of the polygon. */ { bool bar_on; double AbsR, al, del = 0.1, angle = 0.0, R = 0.0, chord_X, chord_Y, Length, fmag = fm1.Scale1, sin_d, cos_d, x = 0, y = 0, xn = 0, yn = 0, fmx = arc.xm, fmy = arc.ym, Scale1 = fm1.Scale1; int maxRad = 200, marginX = fm1.marginX, marginY = fm1.marginY, ixb, iyb, ixe, iye, ixm, iym; int penWidth = fm1.WidthG / 800; if (penWidth == 0) { penWidth = 1; } Pen arcPen = new Pen(Color.Red, penWidth); Pen posLinePen = new Pen(Color.Yellow, penWidth); Pen negLinePen = new Pen(Color.Violet, penWidth); bar_on = fmag >= 2.0; // switches on the filling of the 3x3 rectangles for points R = arc.rad; AbsR = R; if (R < 0.0) { AbsR = -R; } chord_X = arc.xe - arc.xb; chord_Y = arc.ye - arc.yb; // the chord Length = Math.Sqrt(chord_X * chord_X + chord_Y * chord_Y); // Length of the chord ixb = (int)arc.xb; // marginX + (int)(Scale1 * arc.xb); iyb = (int)arc.yb; // marginY + (int)(Scale1 * arc.yb); ixe = (int)arc.xe; // marginX + (int)(Scale1 * arc.xe); iye = (int)arc.ye; // marginY + (int)(Scale1 * arc.ye); ixm = (int)arc.xm; // marginX + (int)(Scale1 * arc.xm); iym = (int)arc.ym; // marginY + (int)(Scale1 * arc.ym); Pen linePen; // = new System.Drawing.Pen(Color.Blue); if (AbsR < maxRad && AbsR > 30.0 && DispRad) // Radius vectors at the end ppoints of the arc { if (R > 0) { linePen = posLinePen; } else { linePen = negLinePen; } fm1.g2Bmp.DrawLine(linePen, ixm, iym, ixb, iyb); fm1.g2Bmp.DrawLine(linePen, ixm, iym, ixe, iye); } angle = 2.0 * Math.Asin(Length / 2.0 / AbsR); // angle of the arc if (R > 0) { linePen = new Pen(Color.Red); } del = 0.1; cos_d = Math.Cos(del); // "del" is the step of the circular moving of the point (x, y) if (R < 0.0) { sin_d = -Math.Sin(del); } else { sin_d = Math.Sin(del); } if (angle < 2.0 * del) // The for-loop with 'al' is not used in this case { fm1.g2Bmp.DrawLine(arcPen, ixb, iyb, ixe, iye); xn = yn = 0; } else { x = arc.xb - arc.xm; y = arc.yb - arc.ym; for (al = 0.0; al < angle; al += del) // Drawing an arc step by step { xn = x * cos_d + y * sin_d; yn = -x * sin_d + y * cos_d; fm1.g2Bmp.DrawLine(arcPen, (int)(arc.xm + x + 0.5), (int)(arc.ym + y + 0.5), (int)(arc.xm + xn + 0.5), (int)(arc.ym + yn + 0.5)); x = xn; y = yn; } } if (bar_on) { Brush myBrush = new System.Drawing.SolidBrush(Color.Violet); int size = 4; Rectangle rect = new Rectangle((int)arc.xb, (int)arc.yb, size, size); fm1.g2Bmp.FillRectangle(myBrush, rect); rect = new Rectangle((int)arc.xe, (int)arc.ye, size, size); fm1.g2Bmp.FillRectangle(myBrush, rect); } fm1.pictureBox2.Image = fm1.BmpPictBox2; return(0); } // ********************** end DrawArc *********************************
} // ***************************** end FindArcs ************************************************************** public void CurvatureNew(int x1, int y1, int x2, int y2, int x3, int y3, double eps, ref CArc arc) { double chordX, chordY, ortX, ortY, Length, dist, VectProd; chordX = x2 - x1; chordY = y2 - y1; Length = Math.Sqrt(chordX * chordX + chordY * chordY); arc.rad = (float)(Length * Length / eps / 8.0); arc.xb = (float)x1; arc.yb = (float)y1; arc.xe = (float)x2; arc.ye = (float)y2; dist = Math.Sqrt(arc.rad * arc.rad - Length * Length / 4.0); VectProd = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1); if (VectProd < 0) { ortX = chordY; ortY = -chordX; } else { ortX = -chordY; ortY = chordX; } arc.xm = (float)((x1 + x2) / 2 + ortX * dist / Length); arc.ym = (float)((y1 + y2) / 2 + ortY * dist / Length); }
} // *********************** end Curvature ****************************************************** public int FindArcs(PictureBox pictureBox, CImage EdgeIm, double eps, Form1 fm1) /* The method calculates the parametrs of the arcs contained in * the polygons. Fills the array 'Arc[]' of structures "CArc". Shows the contents * of this array graphically. */ { bool disp = true; int j, ip, first, last, Len, rv, x1, y1, x2, y2, x3, y3; nArc = 0; Pen linePen = new System.Drawing.Pen(Color.LightBlue); int marginX = fm1.marginX; int marginY = fm1.marginY; double Scale1 = fm1.Scale1; fm1.progressBar1.Value = 0; fm1.progressBar1.Visible = true; fm1.progressBar1.Step = 1; int jump, Len1 = nPolygon, nStep = 100; if (Len1 > 2 * nStep) { jump = Len1 / nStep; } else { jump = 2; } for (ip = 0; ip < nPolygon; ip++) // =========================== { if (ip % jump == jump - 1) { fm1.progressBar1.PerformStep(); } int cntArc = 0; Polygon[ip].firstArc = -1; Polygon[ip].lastArc = -2; first = Polygon[ip].firstVert; last = Polygon[ip].lastVert; if (last > first + 1) // ------- are there sufficient many vertices?----------- { if (disp) // here are three points of a polygon calculated but not drawn { x1 = (int)(Scale1 * Vert[first].X + 0.5); // starting point y1 = (int)(Scale1 * Vert[first].Y + 0.5); } x2 = Vert[first].X; // will become the first point of the arc y2 = Vert[first].Y; x3 = Vert[first + 1].X; // second point y3 = Vert[first + 1].Y; Polygon[ip].firstArc = nArc; // Points from the second one until the one before the last Len = last - first + 1; for (j = 2; j <= Len; j++) // ============================= { x1 = x2; y1 = y2; x2 = x3; y2 = y3; x3 = Vert[first + j % Len].X; y3 = Vert[first + j % Len].Y; CArc arc = new CArc(); // 'Curvature' calculates and saves parameters of an arc in 'arc'. rv = Curvature(x1, y1, x2, y2, x3, y3, eps, ref arc); if (rv < 0) { continue; } if (Math.Abs(arc.xb - arc.xe) < 1.0 && Math.Abs(arc.yb - arc.ye) < 1.0 || Math.Abs(arc.rad) < 2.0) { continue; } // The arc is saved in the array "Arc" of arcs: Arc[nArc] = arc; if (cntArc == 0) { Polygon[ip].firstArc = nArc; } cntArc++; nArc++; if (disp) //------------------------------------------------------------- { rv = DrawArc(arc, true, fm1, ip); if (rv < 0) { return(-1); } } //---------------------- end if (disp) --------------------------------------------------------- if (j == Len - 1) { Polygon[ip].lastArc = nArc - 1; } } // ======================= end for (j... ========================================================= } // ------------------------- end if (last > first+1 ) ----------------------------------------------- } // =========================== end for (ip... ========================================================== fm1.pictureBox2.Image = fm1.BmpPictBox2; fm1.progressBar1.Visible = false; return(0); } // ***************************** end FindArcs **************************************************************