对于任意给定的离散点搜索其边界,主要通过判断边界类型然后指定相应的搜索方式。一般边界主要分为凸边界和既有凸边界又有凹边界两种类型。如下图所示:
对于不同类型的边界有不同的计算算法搜索点,在搜索边界时,现约定统一采用逆时针方向搜索。如现已经存在边界AC,需要搜索下一条边界AB,如下图所示:
添加一个按钮,设置其Name和Text属性都为“凸边界搜索”。由于在搜索到边界时需要添加新的对象,所以采用ArrayList类型,需要添加引用“using System.Collections;”
同时定义类Edge用于保存该边界的起点与终点,如下:
public class Edge
{
public int Start;//边的起点
public int End;//边的终点
}
在全局变量中添加定义“private ArrayList arrayEdges = new ArrayList();”用于定义边界数组。
为“凸边界搜索”按钮的Click事件添加代码如下:
private void 凸边界搜索_Click(object sender, EventArgs e)
{
arrayEdges.Clear();
Microsoft.VisualBasic.Interaction.AppActivate(AcadApp.Caption);
AcadSelectionSet mySelectionSet;
mySelectionSet = AcadDoc.SelectionSets.Add("NewSelectionSet001");
Int16[] FilterType = new Int16[1];
object[] FilterData = new object[1];
FilterType[0] = 0;
FilterData[0] = "POINT";
mySelectionSet.SelectOnScreen(FilterType, FilterData);
double[] arrPoints = new double[3 * mySelectionSet.Count];
int count = 0;
foreach (AcadObject acadObj in mySelectionSet)
{
if (acadObj.ObjectName == "AcDbPoint")
{
count++;
double[] PointCoord;
PointCoord = (Double[])(((AcadPoint)acadObj).Coordinates);
arrPoints[3 * count - 3] = PointCoord[0];
arrPoints[3 * count - 2] = PointCoord[1];
arrPoints[3 * count - 1] = PointCoord[2];
}
}
AcadDoc.SelectionSets.Item("NewSelectionSet001").Delete();
//获取点集外围边界
int i, StartIndex=0, AIndex, BIndex, pointCount = arrPoints.Length / 3;
for (i = 1; i < pointCount; i++) //寻找X值最小的点号
{
if (arrPoints[3 * i] < arrPoints[3 * StartIndex])
{
StartIndex = i;
}
}
Edge edge = new Edge();
edge.Start = StartIndex;
BIndex = StartIndex - 1;
AIndex = StartIndex;
double[] vector1 = new double[2], vector2 = new double[2];
vector1[0] = 0; vector1[1] = 100;
double vector1Length, vector2Length, angleTemp, angleMax, lengthMin, vectorDirect;
angleMax = 0;
while (BIndex != StartIndex)
{
vector1Length = Math.Sqrt(vector1[0] * vector1[0] + vector1[1] * vector1[1]);
lengthMin = 300;
for (i = 0; i < pointCount; i++)//找边界
{
if (i != edge.Start)
{
vector2[0] = arrPoints[3 * i] - arrPoints[3 * AIndex];
vector2[1] = arrPoints[3 * i + 1] - arrPoints[3 * AIndex + 1];
vector2Length = Math.Sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1]);
angleTemp = Math.Acos((vector1[0] * vector2[0] + vector1[1] * vector2[1]) / (vector1Length * vector2Length));
vectorDirect = vector1[0] * vector2[1] - vector1[1] * vector2[0];
if (angleTemp > angleMax && vectorDirect<0)
{
angleMax = angleTemp;
edge.End = i;
lengthMin = vector2Length;
}
else if (angleTemp == angleMax && vector2Length < lengthMin)
{
edge.End = i;
lengthMin = vector2Length;
}
}
}
arrayEdges.Add(edge);
BIndex = edge.End;
edge = new Edge();
edge.Start = BIndex;
vector1[0] = arrPoints[3 * AIndex] - arrPoints[3 * BIndex];
vector1[1] = arrPoints[3 * AIndex + 1] - arrPoints[3 * BIndex + 1];
angleMax = 0;
AIndex = BIndex;
}
//绘制边界
double[] lineCoords = new double[3*(arrayEdges.Count+1)];
Edge[] edges = new Edge[arrayEdges.Count];
arrayEdges.CopyTo(edges);
for(i=0;i<arrayEdges.Count;i++)
{
double[] p1=new double[3];
p1[0] = arrPoints[3 * edges[i].Start];
p1[1] = arrPoints[3 * edges[i].Start+1];
p1[2] = arrPoints[3 * edges[i].Start+2];
lineCoords[3 * i] = arrPoints[3 * edges[i].Start];
lineCoords[3 * i + 1] = arrPoints[3 * edges[i].Start + 1];
lineCoords[3 * i + 2] = arrPoints[3 * edges[i].Start + 2];
}
lineCoords[3 * arrayEdges.Count - 3] = arrPoints[3 * edges[arrayEdges.Count - 1].Start];
lineCoords[3 * arrayEdges.Count - 2] = arrPoints[3 * edges[arrayEdges.Count - 1].Start + 1];
lineCoords[3 * arrayEdges.Count - 1] = arrPoints[3 * edges[arrayEdges.Count - 1].Start + 2];
lineCoords[3 * arrayEdges.Count] = arrPoints[3 * edges[arrayEdges.Count-1].End];
lineCoords[3 * arrayEdges.Count+1] = arrPoints[3 * edges[arrayEdges.Count-1].End + 1];
lineCoords[3 * arrayEdges.Count+2] = arrPoints[3 * edges[arrayEdges.Count - 1].End + 2];
AcadDoc.ModelSpace.Add3DPoly(lineCoords);
}
运行程序,其结果如下图所示: