public void update(VectorPixel v) { if (!fromPnt.defined) { fromPnt = v.fromPnt; } toPnt = v.toPnt; int d1; int d2; if (dx > dy) { d1 = dx; d2 = dy; } else { d1 = dy; d2 = dx; } maxleft = Math.Max(maxleft, 1.0 * (d1 - 1) / d2); minright = Math.Min(minright, 1.0 * (d1 + 1) / d2); var dmin = maxleft * (d2 + 1) + 0.5 - d1; var dmax = minright * (d2 + 1) - 0.5 - d1; if (Math.Ceiling(dmin) - dmin == 0.5) { dmin += 0.5; } if (Math.Ceiling(dmax) - dmax == 0.5) { dmax -= 0.5; } if (dx > dy) { nextmindx = (int)Math.Round(dmin); nextmaxdx = (int)Math.Round(dmax); nextmindy = 0; nextmaxdy = 1; } else if (dx < dy) { nextmindx = 0; nextmaxdx = 1; nextmindy = (int)Math.Round(dmin); nextmaxdy = (int)Math.Round(dmax); } else { nextmindx = 0; nextmaxdx = 2; nextmindy = 0; nextmaxdy = 2; } //Console.WriteLine("({0}, {1}) - ({2}, {3})", outerFromPnt.x, outerFromPnt.y, toPnt.x, toPnt.y); }
public Line(VectorPixel v) { maxleft = double.MinValue; minright = double.MaxValue; outerFromPnt = v.fromPnt; toPnt = v.toPnt; nextmindx = 0; nextmaxdx = int.MaxValue; nextmindy = 0; nextmaxdy = int.MaxValue; }
public bool satisfiesInner(VectorPixel v) { if (!fromPnt.defined) { return(Math.Abs(toPnt.x - outerFromPnt.x) == Math.Abs(toPnt.y - outerFromPnt.y) ? true : // anything goes Math.Abs(v.toPnt.x - toPnt.x) >= Math.Abs(v.fromPnt.x - outerFromPnt.x) && Math.Abs(v.toPnt.y - toPnt.y) >= Math.Abs(v.fromPnt.y - outerFromPnt.y)); } // inner segment must be >= the outer segment return (nextmindx <= Math.Abs(v.toPnt.x - toPnt.x) && Math.Abs(v.toPnt.x - toPnt.x) <= nextmaxdx && nextmindy <= Math.Abs(v.toPnt.y - toPnt.y) && Math.Abs(v.toPnt.y - toPnt.y) <= nextmaxdy); }
public bool sameDir(VectorPixel v) { if (v.linkVector()) { return (Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - (v.toPnt.x - toPnt.x)) <= 1 && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - (v.toPnt.y - toPnt.y)) <= 1); } if (Math.Abs(toPnt.x - outerFromPnt.x) > Math.Abs(toPnt.y - outerFromPnt.y)) { return (Math.Sign(toPnt.x - outerFromPnt.x) == Math.Sign(v.toPnt.x - toPnt.x) && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - (v.toPnt.y - toPnt.y)) <= 1); } if (Math.Abs(toPnt.x - outerFromPnt.x) < Math.Abs(toPnt.y - outerFromPnt.y)) { return (Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - (v.toPnt.x - toPnt.x)) <= 1 && Math.Sign(toPnt.y - outerFromPnt.y) == Math.Sign(v.toPnt.y - toPnt.y)); } return (Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - Math.Sign(v.toPnt.x - toPnt.x)) <= 1 && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - Math.Sign(v.toPnt.y - toPnt.y)) <= 1); }
public void update(VectorPixel v) { if (!fromPnt.defined) fromPnt = v.fromPnt; toPnt = v.toPnt; int d1; int d2; if (dx > dy) { d1 = dx; d2 = dy; } else { d1 = dy; d2 = dx; } maxleft = Math.Max(maxleft, 1.0 * (d1 - 1) / d2); minright = Math.Min(minright, 1.0 * (d1 + 1) / d2); double dmin = maxleft * (d2 + 1) + 0.5 - d1; double dmax = minright * (d2 + 1) - 0.5 - d1; if (Math.Ceiling(dmin) - dmin == 0.5) dmin += 0.5; if (Math.Ceiling(dmax) - dmax == 0.5) dmax -= 0.5; if (dx > dy) { nextmindx = (int)Math.Round(dmin); nextmaxdx = (int)Math.Round(dmax); nextmindy = 0; nextmaxdy = 1; } else if (dx < dy) { nextmindx = 0; nextmaxdx = 1; nextmindy = (int)Math.Round(dmin); nextmaxdy = (int)Math.Round(dmax); } else { nextmindx = 0; nextmaxdx = 2; nextmindy = 0; nextmaxdy = 2; } //Console.WriteLine("({0}, {1}) - ({2}, {3})", outerFromPnt.x, outerFromPnt.y, toPnt.x, toPnt.y); }
public bool satisfiesOuter(VectorPixel v) { return Math.Abs(v.toPnt.x - toPnt.x) <= nextmaxdx && Math.Abs(v.toPnt.y - toPnt.y) <= nextmaxdy; // outer segment must be shorter than inner segment }
public bool satisfiesInner(VectorPixel v) { if (!fromPnt.defined) return Math.Abs(toPnt.x - outerFromPnt.x) == Math.Abs(toPnt.y - outerFromPnt.y) ? true : // anything goes Math.Abs(v.toPnt.x - toPnt.x) >= Math.Abs(v.fromPnt.x - outerFromPnt.x) && Math.Abs(v.toPnt.y - toPnt.y) >= Math.Abs(v.fromPnt.y - outerFromPnt.y); // inner segment must be >= the outer segment return nextmindx <= Math.Abs(v.toPnt.x - toPnt.x) && Math.Abs(v.toPnt.x - toPnt.x) <= nextmaxdx && nextmindy <= Math.Abs(v.toPnt.y - toPnt.y) && Math.Abs(v.toPnt.y - toPnt.y) <= nextmaxdy; }
public bool sameDir(VectorPixel v) { if (v.linkVector()) return Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - (v.toPnt.x - toPnt.x)) <= 1 && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - (v.toPnt.y - toPnt.y)) <= 1; if (Math.Abs(toPnt.x - outerFromPnt.x) > Math.Abs(toPnt.y - outerFromPnt.y)) return Math.Sign(toPnt.x - outerFromPnt.x) == Math.Sign(v.toPnt.x - toPnt.x) && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - (v.toPnt.y - toPnt.y)) <= 1; if (Math.Abs(toPnt.x - outerFromPnt.x) < Math.Abs(toPnt.y - outerFromPnt.y)) return Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - (v.toPnt.x - toPnt.x)) <= 1 && Math.Sign(toPnt.y - outerFromPnt.y) == Math.Sign(v.toPnt.y - toPnt.y); return Math.Abs(Math.Sign(toPnt.x - outerFromPnt.x) - Math.Sign(v.toPnt.x - toPnt.x)) <= 1 && Math.Abs(Math.Sign(toPnt.y - outerFromPnt.y) - Math.Sign(v.toPnt.y - toPnt.y)) <= 1; }
public Line(VectorPixel v) { maxleft = Double.MinValue; minright = Double.MaxValue; outerFromPnt = v.fromPnt; toPnt = v.toPnt; nextmindx = 0; nextmaxdx = Int32.MaxValue; nextmindy = 0; nextmaxdy = Int32.MaxValue; }
protected void saveAsBmp(String fileName) { if (polygons.Count == 0) throw new Exception("there must be at least one polygon!"); ArrayList[] inPnt = new ArrayList[ymax - ymin + 1]; for (int i = 0; i < inPnt.Length; i++) inPnt[i] = new ArrayList(20); for (int j = 0; j < polygons.Count; j++) { ArrayList vertices = (ArrayList)polygons[j]; for (int i = 0; i < vertices.Count; i++) { DoubleVector2 vertex = (DoubleVector2)vertices[i]; DoubleVector2 vertexNext = i + 1 < vertices.Count ? (DoubleVector2)vertices[i + 1] : (DoubleVector2)vertices[0]; IntVector2 pointFrom = new IntVector2((int)vertex.x - xmin, (int)vertex.y - ymin); IntVector2 pointTo = new IntVector2((int)vertexNext.x - xmin, (int)vertexNext.y - ymin); VectorPixel vect = new VectorPixel(pointFrom, pointTo); if (vect.dy != 1) { IntVector2 pointNow; for (int k = 0; k < vect.dy; k++) { if (vect.dx > vect.dy) { if (vect.sx * vect.sy == 1) pointNow = new IntVector2(pointFrom.x + vect.sx * (2 * vect.dx * k + vect.dy - 1) / (2 * vect.dy), pointFrom.y + vect.sy * k); else pointNow = new IntVector2(pointFrom.x + vect.sx * ((2 * vect.dx * (k + 1) + vect.dy - 1) / (2 * vect.dy) - 1), pointFrom.y + vect.sy * k); } else pointNow = new IntVector2(pointFrom.x + vect.sx * (2 * (vect.dx - 1) * k + vect.dy - 1) / (2 * (vect.dy - 1)), pointFrom.y + vect.sy * k); inPnt[pointNow.y].Add(new FromToInt(pointNow.x, vect.sx, vect.sy, pointFrom.x + pointTo.x)); } } } } Bitmap bmp = new Bitmap(xmax - xmin + 3, ymax - ymin + 3, PixelFormat.Format32bppRgb); BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat); int stride = bmpData.Stride; Int64 startPtr = bmpData.Scan0.ToInt64(); if (stride < 0) { startPtr += stride * (bmpData.Height - 1); stride = Math.Abs(stride); } byte[] rowBytes = new byte[bmpData.Stride]; for (int i = 0; i < bmpData.Height; i++) // make everything black first System.Runtime.InteropServices.Marshal.Copy(new IntPtr(startPtr + stride * i), rowBytes, 0, bmpData.Stride); for (int i = 0; i < bmpData.Stride; i++) rowBytes[i] = 255; for (int i = 0; i < inPnt.Length; i++) { inPnt[i].Sort(); for (int j = 1; j < inPnt[i].Count; j++) { FromToInt f = (FromToInt)inPnt[i][j]; FromToInt fprev = (FromToInt)inPnt[i][j - 1]; if (f.sy > 0 && fprev.sy <= 0 && f.x - (fprev.x + 1) > 0) // insert empty space where appropriate System.Runtime.InteropServices.Marshal.Copy(rowBytes, 0, new IntPtr(startPtr + stride * i + 4 * (fprev.x + 1)), 4 * (f.x - (fprev.x + 1))); f = (FromToInt)inPnt[i][j]; fprev = (FromToInt)inPnt[i][j - 1]; } } bmp.UnlockBits(bmpData); bmp.Save(fileName); }
protected SortedList createVectors(byte[,] pixelOn, Bitmap bmp) { SortedList vectors = new SortedList(bmp.Width * bmp.Height / 32); Hashtable vectorsReverse = new Hashtable(bmp.Width * bmp.Height / 32); int steps = 0; for (int j = 0; j < bmp.Height + 1; j++) for (int i = 0; i < bmp.Width + 1; i++) { printProgress(ref steps, 400000); int type = (pixelOn[i, j] & 1) + ((pixelOn[i + 1, j] & 1) << 1) + ((pixelOn[i, j + 1] & 1) << 2) + ((pixelOn[i + 1, j + 1] & 1) << 3); if (type == 1 + 8 || type == 2 + 4) { // get rid of illegal situations pixelOn[i, j] |= 1; pixelOn[i + 1, j] |= 1; pixelOn[i, j + 1] |= 1; pixelOn[i + 1, j + 1] |= 1; printWarning("\nillegal pixel configuration at [" + i + ", " + j + "]"); } } for (int j = 0; j < bmp.Height; j++) for (int i = 0; i < bmp.Width; i++) { printProgress(ref steps, 800000); if ((pixelOn[i + 1, j + 1] & 1) == 1) { int type1 = (pixelOn[i + 1, j] & 1) + (pixelOn[i + 1, j + 2] & 1); int type2 = (pixelOn[i, j + 1] & 1) + (pixelOn[i + 2, j + 1] & 1); if (type1 == 2 && type2 == 0 || type1 == 0 && type2 == 2 ) { // get rid of illegal situations pixelOn[i + 2, j + 1] |= 1; pixelOn[i + 1, j + 2] |= 1; printWarning("\nillegal pixel configuration at [" + i + ", " + j + "]"); } } } for (int j = -1; j < bmp.Height; j++) for (int i = -1; i < bmp.Width; i++) { printProgress(ref steps, 400000); int type = (pixelOn[i + 1, j + 1] & 1) + ((pixelOn[i + 2, j + 1] & 1) << 1) + ((pixelOn[i + 1, j + 2] & 1) << 2) + ((pixelOn[i + 2, j + 2] & 1) << 3); IntVector2 fromPnt = new IntVector2(); IntVector2 toPnt = new IntVector2(); switch (type) { // create horizontal and vertical vectors between adjacent pixels case 3: // xx // -- fromPnt = new IntVector2(i, j); toPnt = new IntVector2(i + 1, j); break; case 12: // -- // xx fromPnt = new IntVector2(i + 1, j + 1); toPnt = new IntVector2(i, j + 1); break; case 5: // x- // x- fromPnt = new IntVector2(i, j + 1); toPnt = new IntVector2(i, j); break; case 10: // -x // -x fromPnt = new IntVector2(i + 1, j); toPnt = new IntVector2(i + 1, j + 1); break; case 14: // -x // xx fromPnt = new IntVector2(i + 1, j); toPnt = new IntVector2(i, j + 1); break; case 13: // x- // xx fromPnt = new IntVector2(i + 1, j + 1); toPnt = new IntVector2(i, j); break; case 11: // xx // -x fromPnt = new IntVector2(i, j); toPnt = new IntVector2(i + 1, j + 1); break; case 7: // xx // x- fromPnt = new IntVector2(i, j + 1); toPnt = new IntVector2(i + 1, j); break; } if (fromPnt.defined) { if (vectorsReverse.Contains(fromPnt)) { VectorPixel oldVP = (VectorPixel)vectorsReverse[fromPnt]; if ((toPnt - fromPnt).extension(oldVP.toPnt - oldVP.fromPnt)) { vectors.Remove(oldVP.fromPnt); vectorsReverse.Remove(oldVP.toPnt); fromPnt = oldVP.fromPnt; } } if (vectors.Contains(toPnt)) { VectorPixel oldVP = (VectorPixel)vectors[toPnt]; if ((toPnt - fromPnt).extension(oldVP.toPnt - oldVP.fromPnt)) { vectors.Remove(oldVP.fromPnt); vectorsReverse.Remove(oldVP.toPnt); toPnt = oldVP.toPnt; } } if (!fromPnt.Equals(toPnt)) { // do not add null vectors, they ugly :/ VectorPixel newVP = new VectorPixel(fromPnt, toPnt); if (vectors.Contains(newVP.fromPnt)) throw new Exception("illegal edge configuration at pixel [" + newVP.fromPnt.x + ", " + newVP.fromPnt.y + "]"); else vectors.Add(newVP.fromPnt, newVP); if (vectorsReverse.Contains(newVP.toPnt)) throw new Exception("illegal edge configuration at pixel [" + newVP.toPnt.x + ", " + newVP.toPnt.y + "]"); else vectorsReverse.Add(newVP.toPnt, newVP); } } } return vectors; }
protected void saveAsBmp(string fileName) { if (polygons.Count == 0) { throw new Exception("there must be at least one polygon!"); } var inPnt = new ArrayList[ymax - ymin + 1]; for (var i = 0; i < inPnt.Length; i++) { inPnt[i] = new ArrayList(20); } for (var j = 0; j < polygons.Count; j++) { var vertices = (ArrayList)polygons[j]; for (var i = 0; i < vertices.Count; i++) { var vertex = (DoubleVector2)vertices[i]; var vertexNext = i + 1 < vertices.Count ? (DoubleVector2)vertices[i + 1] : (DoubleVector2)vertices[0]; var pointFrom = new IntVector2((int)vertex.x - xmin, (int)vertex.y - ymin); var pointTo = new IntVector2((int)vertexNext.x - xmin, (int)vertexNext.y - ymin); var vect = new VectorPixel(pointFrom, pointTo); if (vect.dy != 1) { IntVector2 pointNow; for (var k = 0; k < vect.dy; k++) { if (vect.dx > vect.dy) { if (vect.sx * vect.sy == 1) { pointNow = new IntVector2(pointFrom.x + vect.sx * (2 * vect.dx * k + vect.dy - 1) / (2 * vect.dy), pointFrom.y + vect.sy * k); } else { pointNow = new IntVector2( pointFrom.x + vect.sx * ((2 * vect.dx * (k + 1) + vect.dy - 1) / (2 * vect.dy) - 1), pointFrom.y + vect.sy * k); } } else { pointNow = new IntVector2( pointFrom.x + vect.sx * (2 * (vect.dx - 1) * k + vect.dy - 1) / (2 * (vect.dy - 1)), pointFrom.y + vect.sy * k); } inPnt[pointNow.y].Add(new FromToInt(pointNow.x, vect.sx, vect.sy, pointFrom.x + pointTo.x)); } } } } var bmp = new Bitmap(xmax - xmin + 3, ymax - ymin + 3, PixelFormat.Format32bppRgb); var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat); var stride = bmpData.Stride; var startPtr = bmpData.Scan0.ToInt64(); if (stride < 0) { startPtr += stride * (bmpData.Height - 1); stride = Math.Abs(stride); } var rowBytes = new byte[bmpData.Stride]; for (var i = 0; i < bmpData.Height; i++) // make everything black first { Marshal.Copy(new IntPtr(startPtr + stride * i), rowBytes, 0, bmpData.Stride); } for (var i = 0; i < bmpData.Stride; i++) { rowBytes[i] = 255; } for (var i = 0; i < inPnt.Length; i++) { inPnt[i].Sort(); for (var j = 1; j < inPnt[i].Count; j++) { var f = (FromToInt)inPnt[i][j]; var fprev = (FromToInt)inPnt[i][j - 1]; if (f.sy > 0 && fprev.sy <= 0 && f.x - (fprev.x + 1) > 0) // insert empty space where appropriate { Marshal.Copy(rowBytes, 0, new IntPtr(startPtr + stride * i + 4 * (fprev.x + 1)), 4 * (f.x - (fprev.x + 1))); } f = (FromToInt)inPnt[i][j]; fprev = (FromToInt)inPnt[i][j - 1]; } } bmp.UnlockBits(bmpData); bmp.Save(fileName); }
public SortedList createVectors(byte[,] pixelOn, Bitmap bmp) { var vectors = new SortedList(bmp.Width * bmp.Height / 32); var vectorsReverse = new Hashtable(bmp.Width * bmp.Height / 32); var steps = 0; for (var j = 0; j < bmp.Height + 1; j++) { for (var i = 0; i < bmp.Width + 1; i++) { printProgress(ref steps, 400000); var type = (pixelOn[i, j] & 1) + ((pixelOn[i + 1, j] & 1) << 1) + ((pixelOn[i, j + 1] & 1) << 2) + ((pixelOn[i + 1, j + 1] & 1) << 3); if (type == 1 + 8 || type == 2 + 4) { // get rid of illegal situations pixelOn[i, j] |= 1; pixelOn[i + 1, j] |= 1; pixelOn[i, j + 1] |= 1; pixelOn[i + 1, j + 1] |= 1; printWarning("\nillegal pixel configuration at [" + i + ", " + j + "]"); } } } for (var j = 0; j < bmp.Height; j++) { for (var i = 0; i < bmp.Width; i++) { printProgress(ref steps, 800000); if ((pixelOn[i + 1, j + 1] & 1) == 1) { var type1 = (pixelOn[i + 1, j] & 1) + (pixelOn[i + 1, j + 2] & 1); var type2 = (pixelOn[i, j + 1] & 1) + (pixelOn[i + 2, j + 1] & 1); if (type1 == 2 && type2 == 0 || type1 == 0 && type2 == 2) { // get rid of illegal situations pixelOn[i + 2, j + 1] |= 1; pixelOn[i + 1, j + 2] |= 1; printWarning("\nillegal pixel configuration at [" + i + ", " + j + "]"); } } } } for (var j = -1; j < bmp.Height; j++) { for (var i = -1; i < bmp.Width; i++) { printProgress(ref steps, 400000); var type = (pixelOn[i + 1, j + 1] & 1) + ((pixelOn[i + 2, j + 1] & 1) << 1) + ((pixelOn[i + 1, j + 2] & 1) << 2) + ((pixelOn[i + 2, j + 2] & 1) << 3); var fromPnt = new IntVector2(); var toPnt = new IntVector2(); switch (type) { // create horizontal and vertical vectors between adjacent pixels case 3: // xx // -- fromPnt = new IntVector2(i, j); toPnt = new IntVector2(i + 1, j); break; case 12: // -- // xx fromPnt = new IntVector2(i + 1, j + 1); toPnt = new IntVector2(i, j + 1); break; case 5: // x- // x- fromPnt = new IntVector2(i, j + 1); toPnt = new IntVector2(i, j); break; case 10: // -x // -x fromPnt = new IntVector2(i + 1, j); toPnt = new IntVector2(i + 1, j + 1); break; case 14: // -x // xx fromPnt = new IntVector2(i + 1, j); toPnt = new IntVector2(i, j + 1); break; case 13: // x- // xx fromPnt = new IntVector2(i + 1, j + 1); toPnt = new IntVector2(i, j); break; case 11: // xx // -x fromPnt = new IntVector2(i, j); toPnt = new IntVector2(i + 1, j + 1); break; case 7: // xx // x- fromPnt = new IntVector2(i, j + 1); toPnt = new IntVector2(i + 1, j); break; } if (fromPnt.defined) { if (vectorsReverse.Contains(fromPnt)) { var oldVP = (VectorPixel)vectorsReverse[fromPnt]; if ((toPnt - fromPnt).extension(oldVP.toPnt - oldVP.fromPnt)) { vectors.Remove(oldVP.fromPnt); vectorsReverse.Remove(oldVP.toPnt); fromPnt = oldVP.fromPnt; } } if (vectors.Contains(toPnt)) { var oldVP = (VectorPixel)vectors[toPnt]; if ((toPnt - fromPnt).extension(oldVP.toPnt - oldVP.fromPnt)) { vectors.Remove(oldVP.fromPnt); vectorsReverse.Remove(oldVP.toPnt); toPnt = oldVP.toPnt; } } if (!fromPnt.Equals(toPnt)) { // do not add null vectors, they ugly :/ var newVP = new VectorPixel(fromPnt, toPnt); if (vectors.Contains(newVP.fromPnt)) { throw new Exception("illegal edge configuration at pixel [" + newVP.fromPnt.x + ", " + newVP.fromPnt.y + "]"); } vectors.Add(newVP.fromPnt, newVP); if (vectorsReverse.Contains(newVP.toPnt)) { throw new Exception("illegal edge configuration at pixel [" + newVP.toPnt.x + ", " + newVP.toPnt.y + "]"); } vectorsReverse.Add(newVP.toPnt, newVP); } } } } return(vectors); }
public void collapseVectors(SortedList vectors) { ArrayList vertices; var steps = 0; while (vectors.Count > 0) { var vectorOld = (VectorPixel)vectors.GetByIndex(0); // ensures we begin at start/end of some line (as opposed to an inner segment) var startPnt = vectorOld.fromPnt; VectorPixel vectorNow; VectorPixel vectorNew; VectorPixel vectorPrev = null; var line = new Line(vectorOld); vertices = new ArrayList(1000); do { printProgress(ref steps, 2000); vectorNow = (VectorPixel)vectors[vectorOld.toPnt]; vectorNew = (VectorPixel)vectors[vectorNow.toPnt]; if (!vectorNow.fromPnt.Equals(startPnt) && !vectorNow.toPnt.Equals(startPnt) && vectorNow.linkVector() && line.sameDir(vectorNow) && !vectorNew.linkVector() && line.sameDir(vectorNew)) { if (line.satisfiesInner(vectorNew)) { // new segment ok, let's try the next one line.update(vectorNew); vectors.Remove(vectorNow.fromPnt); vectorOld = vectorNew; } else if (line.satisfiesOuter(vectorNew)) { // vectorNow can be an outer segment line.update(vectorNew); vertices.Add(new DoubleVector2(line.toPnt)); vectors.Remove(vectorNew.fromPnt); vectors.Remove(vectorNow.fromPnt); vectorOld = (VectorPixel)vectors[vectorNew.toPnt]; line = new Line(vectorOld); } else { // new segment off, but link is ok as an outer segment line.update(vectorNow); vertices.Add(new DoubleVector2(line.toPnt)); vectors.Remove(vectorNow.fromPnt); vectorOld = vectorNew; line = new Line(vectorOld); } } else if (!vectorNow.fromPnt.Equals(startPnt) && line.sameDir(vectorNow)) { // vectorNow is not a simple link between two segments if (line.satisfiesInner(vectorNow)) { // new segment ok, let's try the next one line.update(vectorNow); vectorOld = vectorNow; } else if (line.satisfiesOuter(vectorNow)) { // vectorNow can be an outer segment line.update(vectorNow); vertices.Add(new DoubleVector2(line.toPnt)); vectors.Remove(vectorNow.fromPnt); vectorOld = vectorNew; line = new Line(vectorOld); } else { // vectorNow just won't fit - process it separately vertices.Add(new DoubleVector2(line.toPnt)); vectorOld = vectorNow; line = new Line(vectorOld); } } else { // vectorNow just won't fit - process it separately vertices.Add(new DoubleVector2(line.toPnt)); vectorOld = vectorNow; line = new Line(vectorOld); } if (vectorPrev != null) { vectors.Remove(vectorPrev.fromPnt); } vectorPrev = vectorOld; } while (!vectorOld.fromPnt.Equals(startPnt)); vectors.Remove(startPnt); vertices.TrimToSize(); polygons.Add(vertices); } }
public bool satisfiesOuter(VectorPixel v) { return (Math.Abs(v.toPnt.x - toPnt.x) <= nextmaxdx && Math.Abs(v.toPnt.y - toPnt.y) <= nextmaxdy); // outer segment must be shorter than inner segment }