using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
namespace LineSegmentSplitter
{
class FreeEndDetector
{
#region Fields
private List<bool[,]> _kernelType1List; // one and only one neighbourhood * 8
private List<bool[,]> _kernelType2List; // L shape ends * 8
private List<bool[,]> _kernelType3List; // T shape ends * 8
private List<Point> _freeEndList; // free end points list
#endregion
#region Fields
public List<Point> FreeEndList { get { return _freeEndList; } }
#endregion
#region Constructor
public FreeEndDetector()
{
PrepareKernels();
}
#endregion
#region Apply
public bool[,] Apply(bool[,] srcBoolMatrix)
{
// AndTrue operations with 16 kernels
List<bool[,]> dstMatrixList = new List<bool[,]>(20);
for (int i = 0; i < 8; i++)
dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType1List[i]));
for (int i = 0; i < 8; i++)
dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType2List[i]));
for (int i = 0; i < 4; i++)
dstMatrixList.Add(HitAndMissTransformation.AndTrueFalse2D(srcBoolMatrix, (bool[,])_kernelType3List[i]));
// OR all dstMatrixs
bool[,] dstMatrix = (bool[,])dstMatrixList[0];
int height = dstMatrix.GetLength(1);
int width = dstMatrix.GetLength(0);
bool temp;
for (int i = 1; i < 20; i++)
// for each AndTrue output
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
temp = ((bool[,])dstMatrixList[i])[x, y];
dstMatrix[x, y] = dstMatrix[x, y] || temp;
}
}
}
_freeEndList = new List<Point>(0);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (dstMatrix[x, y])
_freeEndList.Add(new Point(x, y));
}
}
return dstMatrix;
} // Apply()
#endregion
#region prepare kernel
/// <summary>
/// prepare kernels
/// </summary>
private void PrepareKernels()
{
_kernelType1List = new List<bool[,]>(8);
// have one and only one neighbour * 8
bool[,] kernel1 = new bool[,]
{
{false, false, true},
{false, true, false},
{false, false, false}
};
_kernelType1List.Add(kernel1);
bool[,] kernel2 = new bool[,]
{
{false, false, false},
{false, true, true},
{false, false, false}
};
_kernelType1List.Add(kernel2);
bool[,] kernel3 = new bool[,]
{
{false, false, false},
{false, true, false},
{false, false, true}
};
_kernelType1List.Add(kernel3);
bool[,] kernel4 = new bool[,]
{
{false, false, false},
{false, true, false},
{false, true, false}
};
_kernelType1List.Add(kernel4);
bool[,] kernel5 = new bool[,]
{
{false, false, false},
{false, true, false},
{true, false, false}
};
_kernelType1List.Add(kernel5);
bool[,] kernel6 = new bool[,]
{
{false, false, false},
{true, true, false},
{false, false, false}
};
_kernelType1List.Add(kernel6);
bool[,] kernel7 = new bool[,]
{
{true, false, false},
{false, true, false},
{false, false, false}
};
_kernelType1List.Add(kernel7);
bool[,] kernel8 = new bool[,]
{
{false, true, false},
{false, true, false},
{false, false, false}
};
_kernelType1List.Add(kernel8);
_kernelType2List = new List<bool[,]>(8);
// L shape ends, * 8
bool[,] kernel9 = new bool[,]
{
{false, false, true},
{false, true, true},
{false, false, false}
};
_kernelType2List.Add(kernel9);
bool[,] kernel10 = new bool[,]
{
{false, false, false},
{false, true, true},
{false, false, true}
};
_kernelType2List.Add(kernel10);
bool[,] kernel11 = new bool[,]
{
{false, false, false},
{false, true, false},
{false, true, true}
};
_kernelType2List.Add(kernel11);
bool[,] kernel12 = new bool[,]
{
{false, false, false},
{false, true, false},
{true, true, false}
};
_kernelType2List.Add(kernel12);
bool[,] kernel13 = new bool[,]
{
{false, false, false},
{true, true, false},
{true, false, false}
};
_kernelType2List.Add(kernel13);
bool[,] kernel14 = new bool[,]
{
{true, false, false},
{true, true, false},
{false, false, false}
};
_kernelType2List.Add(kernel14);
bool[,] kernel15 = new bool[,]
{
{true, true, false},
{false, true, false},
{false, false, false}
};
_kernelType2List.Add(kernel15);
bool[,] kernel16 = new bool[,]
{
{false, true, true},
{false, true, false},
{false, false, false}
};
_kernelType2List.Add(kernel16);
_kernelType3List = new List<bool[,]>(4);
// T shape ends, * 8
bool[,] kernel17 = new bool[,]
{
{true, true, true},
{false, true, false},
{false, false, false}
};
_kernelType3List.Add(kernel17);
bool[,] kernel18 = new bool[,]
{
{false, false, true},
{false, true, true},
{false, false, true}
};
_kernelType3List.Add(kernel18);
bool[,] kernel19 = new bool[,]
{
{false, false, false},
{false, true, false},
{true, true, true}
};
_kernelType3List.Add(kernel19);
bool[,] kernel20 = new bool[,]
{
{true, false, false},
{true, true, false},
{true, false, false}
};
_kernelType3List.Add(kernel20);
} // PrepareKernels()
#endregion
#region I/O method
/// <summary>
/// return a free end image
/// free ends are rendered in red, overlapping the srcImage
/// </summary>
/// <param name="srcImage"></param>
/// <returns></returns>
public Bitmap FreeEndImage(Bitmap srcImage)
{
Bitmap dstImage = new Bitmap(srcImage);
int freeEndCount = _freeEndList.Count;
for (int i = 0; i < freeEndCount; i++)
{
Point p = (Point)_freeEndList[i];
dstImage.SetPixel((int)p.X, (int)p.Y, Color.Red);
}
return dstImage;
} // FreeEndImage()
#endregion
}
}