} // Default constructor public CQue(int len) // Constructor { Len = len; input = 0; output = 0; full = false; Array = new iVect2[Len]; for (int i = 0; i < Len; i++) { Array[i] = new iVect2(); } }
} // 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 *********************
public int Put(iVect2 V) { if (full) { return(-1); } Array[input] = V; if (input == Len - 1) { input = 0; } else { input++; } return(1); }
} //***************************************** end TraceApp *********************************************** public int ComponPoly(CImage Comb, int X, int Y, double eps) /* Encodes in "CListLines" the polygones of the edge component with the point (X, Y) being * a branch or an end point. Puts the starting point 'Pinp' into the queue and starts * the 'while' loop. It tests each labeled crack incident to the point 'P' fetched from the queue. * If the next point of the crack is a branch or an end point, then crack is being ignorred. * Otherwise the funktion "TraceApp" is called. "TraceApp" traces the edge until the next end or * branch point and calulates the verices of the approximating polygon. The tracing ends at the * point 'Pterm' with the direction 'DirT'. If the point 'Pterm' is a branch point then it is put * to the queue. "ComponPoly" returns when the queue is empty. ---------------*/ { int dir, dirT; int LabNext, rv; iVect2 Crack, P, Pinp, Pnext, Pterm; Crack = new iVect2(); P = new iVect2(); Pinp = new iVect2(); Pnext = new iVect2(); Pinp.X = X; Pinp.Y = Y; // comb. coord. int CNX = Comb.width; int CNY = Comb.height; pQ.Put(Pinp); while (!pQ.Empty()) //=========================================================================== { P = pQ.Get(); if ((Comb.Grid[P.X + CNX * P.Y] & 128) != 0) { continue; } for (dir = 0; dir < 4; dir++) //================================================================ { Crack.X = P.X + Step[dir].X; Crack.Y = P.Y + Step[dir].Y; if (Crack.X < 0 || Crack.X > CNX - 1 || Crack.Y < 0 || Crack.Y > CNY - 1) { continue; } if (Comb.Grid[Crack.X + CNX * Crack.Y] == 1) //-------------------------------------- { Pnext.X = Crack.X + Step[dir].X; Pnext.Y = Crack.Y + Step[dir].Y; LabNext = Comb.Grid[Pnext.X + CNX * Pnext.Y] & 7; if (LabNext == 3) { pQ.Put(Pnext); } if (LabNext == 2) //-------------------------------------------------------------- { Polygon[nPolygon].firstVert = nVert; dirT = dir; Pterm = new iVect2(); rv = TraceApp(Comb, P.X, P.Y, eps, ref Pterm, ref dirT); if (rv < 0) { MessageBox.Show("ComponPoly, Alarm! TraceApp returned " + rv + ". return -1."); return(-1); } if (nPolygon > MaxPoly - 1) { MessageBox.Show("ComponPoly: Overflow in Polygon; nPolygon=" + nPolygon + " MaxPoly=" + MaxPoly); return(-1); } else { nPolygon++; } if ((Comb.Grid[Pterm.X + CNX * Pterm.Y] & 128) == 0 && rv >= 3) { pQ.Put(Pterm); } } // ------------- end if (LabNest==2) ----------------------------------------------------- if ((Comb.Grid[P.X + CNX * P.Y] & 7) == 1) { break; } } //--------------- end if (Comb.Grid[Crack.X ...==1) ------------------------------------------ } //================================== end for (dir ... ========================================== Comb.Grid[P.X + CNX * P.Y] |= 128; } //==================================== end while ========================================== return(1); } //************************************** end ComponPoly ************************************************
} //*************************** end CheckComb ************************************ public int TraceApp(CImage Comb, int X, int Y, double eps, ref iVect2 Pterm, ref int dir) /* This method traces a line in the image "Comb" with combinatorial coordinates, where the cracks * and points of the edges are labeled: bits 0 and 1 of a point contain the label 1 to 3 of the point. * The label indicates the number of incident edge cracks. Bits 2 to 5 indicate the presence of * incident cracks of directions 0, 1, 2 and 3 correspondingly. Labeled bit 6 indicates that the point * already has been put into the queue; labeled bit 7 indicates that the point shoud not been used any more. * The crack has only one label 1 in bit 0. * This function traces the edge from one end or branch point to another while changing the parameter "dir". * It makes polygonal approximation with precision "eps" and saves STANDARD coordinats in "Vert". * ----------*/ { int br, Lab, rv = 0; bool BP = false, END = false; bool atSt_P = false, CHECK = true; iVect2 Crack, P, P1, Pold, Pstand, StartEdge, StartLine, Vect; Crack = new iVect2(); P = new iVect2(); P1 = new iVect2(); Pold = new iVect2(); Pstand = new iVect2(); StartEdge = new iVect2(); StartLine = new iVect2(); Vect = new iVect2(); int iCrack = 0; P.X = X; P.Y = Y; Pstand.X = X / 2; Pstand.Y = Y / 2; P1.X = Pold.X = P.X; P1.Y = Pold.Y = P.Y; StartEdge.X = X / 2; StartEdge.Y = Y / 2; StartLine.X = X / 2; StartLine.Y = Y / 2; int[] Shift = new int[4]; Shift[0] = 0; Shift[1] = 2; Shift[2] = 4; Shift[3] = 6; Vert[nVert].X = Pstand.X; Vert[nVert].Y = Pstand.Y; nVert++; Vect = new iVect2(); int CNX = Comb.width; int CNY = Comb.height; CheckComb(StartEdge, Pstand, eps, ref Vect); while (true) //==================================================================== { Crack.X = P.X + Step[dir].X; Crack.Y = P.Y + Step[dir].Y; if (Comb.Grid[Crack.X + CNX * Crack.Y] == 0) { MessageBox.Show("TraceApp, error: dir=" + dir + " the Crack=(" + Crack.X + "," + Crack.Y + ") has label 0; X=" + X + ", Y=" + Y + "; iCrack=" + iCrack + " return -1"); MessageBox.Show("Point before Crack Lab=" + (Comb.Grid[P.X + CNX * P.Y] & 7) + " P+0=" + (Comb.Grid[P.X + 1 + CNX * P.Y] & 7) + " P+1=" + (Comb.Grid[P.X + CNX * (P.Y + 1)] & 7) + " P+2=" + (Comb.Grid[P.X - 1 + CNX * P.Y] & 7) + " P+3=" + (Comb.Grid[P.X + CNX * (P.Y - 1)] & 7)); } P.X = P1.X = Crack.X + Step[dir].X; P.Y = P1.Y = Crack.Y + Step[dir].Y; Pstand.X = P.X / 2; Pstand.Y = P.Y / 2; br = CheckComb(StartEdge, Pstand, eps, ref Vect); Lab = Comb.Grid[P.X + CNX * P.Y] & 7; switch (Lab) { case 1: END = true; BP = false; rv = 1; break; case 2: BP = END = false; break; case 3: BP = true; END = false; rv = 3; break; case 4: BP = true; END = false; rv = 4; break; } if (Lab == 2) { Comb.Grid[P.X + CNX * P.Y] = 0; // deleting all labels of P } iCrack++; if (br > 0) //-------------------------------------------------------------- { if (nVert >= MaxVert - 1) { MessageBox.Show("TraceApp: Overflow in 'Vert'; X=" + X + " Y=" + Y + " nVert=" + nVert); return(-1); } if (CHECK) //------------------------------------------- { if (br == 1) { Vert[nVert].X = Pold.X / 2; Vert[nVert].Y = Pold.Y / 2; } else { Vert[nVert] = Vect; } StartEdge = Vert[nVert]; } else // CHECK == false { if (br == 10) { Vert[nVert].X = Pold.X / 2; Vert[nVert].Y = Pold.Y / 2; } else { Vert[nVert] = P1; } } //----------------------------- end if (CHECK) ------------------------------ br = 0; nVert++; } //------------------ end if (br) -------------------------------------- atSt_P = (Pstand == StartLine); if (atSt_P) { Pterm.X = P.X; // Pterm is a parameter of TraceApp Pterm.Y = P.Y; Polygon[nPolygon].lastVert = nVert - 1; Polygon[nPolygon].closed = true; rv = 2; break; } if (!atSt_P && (BP || END)) { Pterm.X = P.X; // Pterm is a parameter of TraceApp Pterm.Y = P.Y; Vert[nVert].X = Pstand.X; Vert[nVert].Y = Pstand.Y; Polygon[nPolygon].lastVert = nVert; Polygon[nPolygon].closed = false; nVert++; if (BP) { rv = 3; } else { rv = 1; } break; } if (!BP && !END) //--------------------------- { Crack.X = P.X + Step[(dir + 1) % 4].X; Crack.Y = P.Y + Step[(dir + 1) % 4].Y; if (Comb.Grid[Crack.X + CNX * Crack.Y] == 1) { dir = (dir + 1) % 4; } else { Crack.X = P.X + Step[(dir + 3) % 4].X; Crack.Y = P.Y + Step[(dir + 3) % 4].Y; if (Comb.Grid[Crack.X + CNX * Crack.Y] == 1) { dir = (dir + 3) % 4; } } } else { break; } Pold.X = P.X; Pold.Y = P.Y; } //======================================= end while ============================================ Polygon[nPolygon].nCrack = iCrack; return(rv); } //***************************************** end TraceApp ***********************************************
} //****************************** end SearchPoly ******************************** int CheckComb(iVect2 StartP, iVect2 P, double eps, ref iVect2 Vect) // This is the new function for polygonal approximation with the sector method. // It replaces the old function "secomb"; 'P' is in standard coord. { double Length, Sin, Cos, Proj, PosTangX, PosTangY, NegTangX, NegTangY; iVect2 Line = new iVect2(); if (StartP == P) { PosSectX = -1000.0; return(0); } Line.X = P.X - StartP.X; Line.Y = P.Y - StartP.Y; Length = Math.Sqrt(Math.Pow((double)Line.X, 2.0) + Math.Pow((double)Line.Y, 2.0)); if (Length < eps) { return(0); } if (PosSectX == -1000.0) { Sin = eps / Length; Cos = Math.Sqrt(1.0 - Sin * Sin); PosSectX = Line.X * Cos - Line.Y * Sin; PosSectY = Line.X * Sin + Line.Y * Cos; NegSectX = Line.X * Cos + Line.Y * Sin; NegSectY = -Line.X * Sin + Line.Y * Cos; Far = P; return(0); } Proj = (double)((Far.X - StartP.X) * (P.X - Far.X) + (Far.Y - StartP.Y) * (P.Y - Far.Y)); if (Proj < -eps * Math.Sqrt(Math.Pow((double)(Far.X - StartP.X), 2.0) + Math.Pow((double)(Far.Y - StartP.Y), 2.0))) { Vect = Far; PosSectX = -1000.0; return(2); } if (Proj >= 0.0) { Far = P; } if (PosSectX * Line.Y - PosSectY * Line.X > 0.0 || NegSectX * Line.Y - NegSectY * Line.X < 0.0) { PosSectX = -1000.0; return(1); } if (PosSectX != -1000.0 && Length > eps) { Sin = eps / Length; Cos = Math.Sqrt(1 - Sin * Sin); PosTangX = Line.X * Cos - Line.Y * Sin; PosTangY = Line.X * Sin + Line.Y * Cos; NegTangX = Line.X * Cos + Line.Y * Sin; NegTangY = -Line.X * Sin + Line.Y * Cos; if (NegSectX * NegTangY - NegSectY * NegTangX > 0.0) { NegSectX = NegTangX; NegSectY = NegTangY; } if (PosSectX * PosTangY - PosSectY * PosTangX < 0.0) { PosSectX = PosTangX; PosSectY = PosTangY; } } return(0); } //*************************** end CheckComb ************************************