Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的Alpha形(凹壳)算法#_C#_.net_Aforge - Fatal编程技术网

C# C语言中的Alpha形(凹壳)算法#

C# C语言中的Alpha形(凹壳)算法#,c#,.net,aforge,C#,.net,Aforge,我需要凹形算法从一组点勾勒出形状,我是否可以使用AForge.NET中的实现,我在某个地方读到AForge.NET有该算法的实现,但我在文档中找不到 任何帮助都将不胜感激 致以最良好的祝愿 丹尼尔我知道一只巨蜥没有凹壳。 如果你想计算它,你需要使用EmguCV。我知道一只巨蜥没有凹壳。 如果你想计算它,你需要使用EmguCV。我也在寻找一个创建alpha形状的简单.NET实现,但找不到。所以我自己做了。苏黎世ETH的Kaspar Fischer在文件中提供了关键的见解 这个想法就是用一个半径为a

我需要凹形算法从一组点勾勒出形状,我是否可以使用AForge.NET中的实现,我在某个地方读到AForge.NET有该算法的实现,但我在文档中找不到

任何帮助都将不胜感激

致以最良好的祝愿


丹尼尔

我知道一只巨蜥没有凹壳。
如果你想计算它,你需要使用EmguCV。

我知道一只巨蜥没有凹壳。
如果你想计算它,你需要使用EmguCV。

我也在寻找一个创建alpha形状的简单.NET实现,但找不到。所以我自己做了。苏黎世ETH的Kaspar Fischer在文件中提供了关键的见解

这个想法就是用一个半径为alpha的圆形勺子吃掉一个有限点集的周围空间,而不实际击中这些点。这是卡斯帕报纸上的一张图片:

现在,每一个在其边界上正好包含两个点但内部没有点的圆都被称为alpha-exposed(AEC),正是这些AEC给出了最终的alpha形状——只需将定义AEC的两个点替换为一条边即可

注意:如果您的alpha形状看起来太像凸面外壳,请将alpha缩小。另一方面,如果您的alpha形状是碎片或有太多的洞,请将alpha变大

这是最低限度的代码(它以O(n³)为单位运行,其中n是点数):

公共类边缘
{
公共点f A{get;set;}
公共点f B{get;set;}
}
公共类字母形状
{
公共列表边界边{get;private set;}
公共字母形状(列表点、浮点字母)
{
//0.错误检查,初始化
如果(points==null | | points.Count<2){抛出新的ArgumentException(“AlphaShape至少需要2个点”);}
BorderEdges=新列表();
var alpha_2=α*α;
//1.穿过所有点对
对于(int i=0;i2*alpha){continue;}//点之间的圆拟合==>p_i,p_j不能被alpha曝光
浮点x1=点[i].X,x2=点[j].X,y1=点[i].Y,y2=点[j].Y;//为了清晰和简洁起见
var mid=新的点F((x1+x2)/2,(y1+y2)/2);
//找到包含p_i和p_j的两个圆;注意,如果dist==2*alpha,则center1==center2
var center1=新点f(
中间X+(浮点)数学Sqrt(alpha_2-(dist/2)*(dist/2))*(y1-y2)/dist,
中间Y+(浮点)数学Sqrt(alpha_2-(dist/2)*(dist/2))*(x2-x1)/dist
);
var center2=新点f(
中X-(浮点)数学Sqrt(alpha_2-(dist/2)*(dist/2))*(y1-y2)/dist,
中间Y-(浮点)数学Sqrt(alpha_2-(dist/2)*(dist/2))*(x2-x1)/dist
);
//检查其中一个圆是否为阿尔法曝光,即没有其他点位于其中
布尔c1_empty=真,c2_empty=真;
对于(int k=0;k
作为概念证明,以下是实际应用程序中使用的代码输出:


我也在寻找创建alpha形状的简单.NET实现,但找不到。所以我自己做了。苏黎世ETH的Kaspar Fischer在文件中提供了关键的见解

这个想法就是用一个半径为alpha的圆形勺子吃掉一个有限点集的周围空间,而不实际击中这些点。这是卡斯帕报纸上的一张图片:

现在,每一个在其边界上正好包含两个点但内部没有点的圆都被称为alpha-exposed(AEC),正是这些AEC给出了最终的alpha形状——只需将定义AEC的两个点替换为一条边即可

注意:如果您的alpha形状看起来太像凸面外壳,请将alpha缩小。另一方面,如果您的alpha形状是碎片或有太多的洞,请将alpha变大

这是最低限度的代码(它以O(n³)为单位运行,其中n是点数):

公共类边缘
{
公共点f A{get;set;}
公共点f B{get;set;}
}
公共类字母形状
{
公共列表边界边{get;private set;}
公共字母形状(列表点、浮点字母)
{
//0.错误检查,初始化
如果(points==null | | points.Count<2){thro
public class Edge
{
    public PointF A { get; set; }
    public PointF B { get; set; }
}

public class AlphaShape
{
    public List<Edge> BorderEdges { get; private set; }

    public AlphaShape(List<PointF> points, float alpha)
    {
        // 0. error checking, init
        if (points == null || points.Count < 2) { throw new ArgumentException("AlphaShape needs at least 2 points"); }
        BorderEdges = new List<Edge>();           
        var alpha_2 = alpha * alpha;

        // 1. run through all pairs of points
        for (int i = 0; i < points.Count - 1; i++)
        {
            for (int j = i + 1; j < points.Count; j++)
            {
                if (points[i] == points[j]) { throw new ArgumentException("AlphaShape needs pairwise distinct points"); } // alternatively, continue
                var dist = Dist(points[i], points[j]);                    
                if (dist > 2 * alpha) { continue; } // circle fits between points ==> p_i, p_j can't be alpha-exposed                    

                float x1 = points[i].X, x2 = points[j].X, y1 = points[i].Y, y2 = points[j].Y; // for clarity & brevity

                var mid = new PointF((x1 + x2) / 2, (y1 + y2) / 2);

                // find two circles that contain p_i and p_j; note that center1 == center2 if dist == 2*alpha
                var center1 = new PointF(
                    mid.X + (float)Math.Sqrt(alpha_2 - (dist / 2) * (dist / 2)) * (y1 - y2) / dist,
                    mid.Y + (float)Math.Sqrt(alpha_2 - (dist / 2) * (dist / 2)) * (x2 - x1) / dist
                    );

                var center2 = new PointF(
                    mid.X - (float)Math.Sqrt(alpha_2 - (dist / 2) * (dist / 2)) * (y1 - y2) / dist,
                    mid.Y - (float)Math.Sqrt(alpha_2 - (dist / 2) * (dist / 2)) * (x2 - x1) / dist
                    );

                // check if one of the circles is alpha-exposed, i.e. no other point lies in it
                bool c1_empty = true, c2_empty = true;
                for (int k = 0; k < points.Count && (c1_empty || c2_empty); k++)
                {
                    if (points[k] == points[i] || points[k] == points[j]) { continue; }

                    if ((center1.X - points[k].X) * (center1.X - points[k].X) + (center1.Y - points[k].Y) * (center1.Y - points[k].Y) < alpha_2)
                    {
                        c1_empty = false;
                    }

                    if ((center2.X - points[k].X) * (center2.X - points[k].X) + (center2.Y - points[k].Y) * (center2.Y - points[k].Y) < alpha_2)
                    {
                        c2_empty = false;
                    }                                                
                }

                if (c1_empty || c2_empty)
                {                       
                    // yup!
                    BorderEdges.Add(new Edge() { A = points[i], B = points[j] });
                }
            }
        }
    }

    // Euclidian distance between A and B
    public static float Dist(PointF A, PointF B)
    {
        return (float)Math.Sqrt((A.X - B.X) * (A.X - B.X) + (A.Y - B.Y) * (A.Y - B.Y));
    }      
}