Algorithm 如何比较两种形状?

Algorithm 如何比较两种形状?,algorithm,vba,comparison,geometry,shapes,Algorithm,Vba,Comparison,Geometry,Shapes,当涉及公差时,有没有一种方法可以在不使用暴力的情况下比较两个几何形状(或任何两个更通用的数据结构) 蛮力(即将每个对象的每个值与另一个对象的每个值进行比较)可以工作,但速度很慢,我无法使用它 我尝试对数据进行排序并比较两个排序的集合。它很快,但只能在零容忍的情况下工作。我一加上容忍度就迷路了。问题是,在比较时,两个值可能相同,而在排序时,两个值可能不同 以下是我的问题的一些细节 在我的Excel VBA加载项中,我有一组由两个点对象组成的形状对象。外接程序通过COM扫描CAD图形,并创建形状对象

当涉及公差时,有没有一种方法可以在不使用暴力的情况下比较两个几何形状(或任何两个更通用的数据结构)

蛮力(即将每个对象的每个值与另一个对象的每个值进行比较)可以工作,但速度很慢,我无法使用它

我尝试对数据进行排序并比较两个排序的集合。它很快,但只能在零容忍的情况下工作。我一加上容忍度就迷路了。问题是,在比较时,两个值可能相同,而在排序时,两个值可能不同

以下是我的问题的一些细节

在我的Excel VBA加载项中,我有一组由两个
对象组成的
形状
对象。外接程序通过COM扫描CAD图形,并创建
形状
对象的集合

简化版本可能会产生以下结果:

            Shape 1     Shape 2
Point 1    0.0  5.0    0.0  4.9
Point 2    4.9  0.0    5.1  0.0
Point 3    5.0  5.0    5.0  5.0
我需要找出哪些形状与哪些形状相同,其中相同的意思是具有相同的形状、大小和方向,但不具有相同的位置(到目前为止,它是微不足道的)加上或减去公差(现在不是那么微不足道!)

点IsIdenticalTo(其他点)
定义为:

Function IsIdenticalTo(OtherPoint As Point) As Boolean
  IsIdenticalTo = Abs(X - OtherPoint.X) < Tolerance And Abs(Y - OtherPoint.Y) < Tolerance
End Function
  • SortedLines
    集合包含从最接近原点的点开始逆时针排序的所有行。这种方法不会丢失任何信息,但在上面的示例中失败了,因为排序算法与等式比较不一致。如果公差为0.5,则它们应该相同,但排序算法生成的集合如下所示。事情变得更加困难,因为我的形状包含子形状,所以每个形状都有许多起点

            Shape 1     Shape 2
    Point 1    4.9  0.0    0.0  4.9
    Point 2    5.0  5.0    5.1  0.0
    Point 3    0.0  5.0    5.0  5.0
    
  • 编辑:

    形状通过COM从外部图形应用程序导入。一个形状可以像矩形一样简单,也可以像任何有10个圆圈、20个内部形状和30条线的奇特轮廓一样复杂。它们代表有孔和简单装饰的面板,有时它们有锯齿形,形成十几条边

  • 将形状处理为多边形

    将点(每条线)转换为一组线
    (长度、角度)
    ,如下图所示:

    这确保了旋转/平移时的不变性。如果您看到更多的线具有
    angle=PI
    将它们连接在一起,以避免遗漏具有不同采样的相同形状的比较,还应尝试为两个形状匹配相同的CW/CCW多边形缠绕规则

  • 找到起点

    可以是最大或最小的角度、长度。。。或角度+长度的特定顺序。因此,对一个多边形的线重新排序
    (循环移位)
    ,以便可以从“同一点”比较形状

  • 比较-精确匹配

    • 行数必须相同
    • 周长必须相同+/-一定精度
    例如:

    fabs (sum of all lengths of poly1 - sum of all lengths of poly2) <= 1e-3
    
    然后,您必须比较所有5种组合(除非您更快找到匹配项):

    [Notes]

  • 也有更快的方法进行比较,但在某些情况下可能会遗漏

    • 您可以比较直线、角度的直方图
    • 你可以使用神经网络(我不喜欢它们,但它们非常适合这样的分类)
  • 如果形状必须以相同的方式定向(无旋转不变性)

    然后使用线方向角度代替顶点角度

  • 如果无法确保两个比较多边形的缠绕规则相同

    然后你必须检查他们,布斯:

    cmp (l11,l12,l13,l14,l15),(l21,l22,l23,l24,l25)
    cmp (l11,l12,l13,l14,l15),(l25,l24,l23,l22,l21)
    

  • 我知道这是一个模糊的答案,但还是希望它至少有一点帮助…

    我也有同样的问题。我计算顶点的邻接矩阵,用距离加权。这将计算所有边的长度和对角线。如果矩阵的每一行或每一列的模与另一个矩阵相同,则这两个形状相同。对于公差,只需在开始之前使用函数round()。复杂度是O(n2/2),因为你只需要计算相邻对称矩阵的一半。问题是我无法检测形状是否翻转。

    我不确定您希望如何解决此问题。你想要深入,或者你只是想要一个解决方案。我可以建议您使用名为“matchShapes”的OpenCV函数。该函数基于Hu矩,对于刚性形状具有良好的性能。提取目标和主轮廓后,使用下面的代码进行比较

    dif = cv.matchShapes(Contour1, Contour2, 1, 0, 0)
    

    “dif”值越小,表示轮廓之间的相似性越大

    我不清楚您正在比较的“形状”是工作表上的实际形状,还是从VBA项目中的某个类实例化的“形状对象”。你比较的对象到底是什么?如果
    x
    值具有可比性,则只需比较
    y
    值,就可以稍微加快比较速度。@TimWilliams形状是从CAD图形导入的几何对象,并从我自己的VBA类实例化。形状可以是一个简单的矩形,也可以是一个有30个孔和40条线穿过的20点星。如果您了解AutoCad,请考虑块内的任何线(我不使用AutoCad,但它类似)。它们是我的类,非常灵活,但我不能使用外部库。。。除非我可以?您是否尝试过基于最近邻的算法?嗯,我不知道autoCAD,但似乎有一些方法可以提高性能,例如排序:即使对单个属性进行排序,也应允许您快速排除大量可能的比较候选项。同时嵌套属性比较检查,以便“尽早失败”,而不是在单个“and”语句中检查每对值。@NiklasB。我不知道如何在多维问题中使用最近邻。我试着给你打电话
        cmp (l11,l12,l13,l14,l15),(l21,l22,l23,l24,l25)
        cmp (l11,l12,l13,l14,l15),(l22,l23,l24,l25,l21)
        cmp (l11,l12,l13,l14,l15),(l22,l23,l24,l25,l21)
        cmp (l11,l12,l13,l14,l15),(l23,l24,l25,l21,l22)
        cmp (l11,l12,l13,l14,l15),(l24,l25,l21,l22,l23)
        cmp (l11,l12,l13,l14,l15),(l25,l21,l22,l23,l24)
    
    cmp (l11,l12,l13,l14,l15),(l21,l22,l23,l24,l25)
    cmp (l11,l12,l13,l14,l15),(l25,l24,l23,l22,l21)
    
    dif = cv.matchShapes(Contour1, Contour2, 1, 0, 0)