我目前正在尝试编程一个拐角和边缘检测方案,该方案应该能够检测图形中的拐角和边缘。

图形数据结构是从2d char数组构建的,该数组看起来像此示例,其大小为10行9 col。 (空格填补了其余的空白,我无法在边框处添加空格...?)

      ...
 ..Y.....
 ..Y   .
  ZYZ.Z.Z
  .Y ....
  .M
  ..

将为节点中的每个字符创建一个节点,并将完整的图形存储为vector<Node> graph

每个节点都这样定义
struct Node
{
    char character;
    pair<int,int> position;
    bool lock;
    vector<Vertex> adjacent;
};

struct Vertex
{
   Node *current;
   Node *nextTo;

};

所以..我有很多节点,但其中一些在我的用例中是多余的,为此,每个节点都有一个bool lock =>告诉系统应忽略这些节点。

我要忽略的节点是那些在 map 中具有字符.的节点,并将其放置在一个角位置(该节点本身具有2个邻居(大小 vector 邻居== 2)),或者具有字符.的节点介于两个角落。如果在两个角之间出现其他字符,则只会将角设置为锁定状态。当遍历拐角的相邻节点(寻找第二个拐角),并且一个节点有4个相邻节点时,只会将看到的第一个拐角设置为锁定。

所以..我把它写成一些代码,最终看起来像这样。
 for(auto graph_it = begin(graph); graph_it != end(graph); graph_it++)
    {
        if(graph_it->adjacent.size() == 2 && graph_it->character == '.')
        {
            vector<Node*> trace;
            cout << "corner found " <<"("<< graph_it->position.first <<","<< graph_it->position.second << ")" << endl;
            graph_it->lock = true;

            for (Vertex edge : graph_it->adjacent)
            {
                cout << "Check neighbour direction" << endl;
                int changeX = 0;
                int changeY = 0;

                changeX = graph_it->position.first - edge.nextTo->position.first;
                changeY = graph_it->position.second - edge.nextTo->position.second;

                cout << "neighbour direction is first: " << changeX << changeY << endl;
                auto start_position = edge.nextTo;
                vector<Node*> trace;
                bool endIsCorner = false;
                bool conditionMet = false;
                cout << endl;
                while((start_position->adjacent.size() != 2|| start_position->adjacent.size() != 4) /*&& start_position->character =='.'*/)
                {
                    for(Vertex traversing_edge : start_position->adjacent)
                    {
                        cout <<"position before: " << graph_it->position.first << graph_it->position.second << " now position: "<< start_position->position.first << start_position->position.second <<  " change is: " << (start_position->position.first - traversing_edge.nextTo->position.first) <<  " " << start_position->position.second - traversing_edge.nextTo->position.second  << " character is: " << traversing_edge.nextTo->character << endl;
                        if (traversing_edge.nextTo->adjacent.size() == 2)
                        {
                            cout << "error found case 1" << endl;
                            cout << "position: " << traversing_edge.nextTo->character << traversing_edge.nextTo->position.first << traversing_edge.nextTo->position.second << endl;
                            start_position = traversing_edge.nextTo;
                            start_position->lock =true;
                            trace.push_back(start_position);
                            endIsCorner = true;
                            conditionMet = true;
                            break;
                        }
                        else if(traversing_edge.nextTo->adjacent.size() == 4)
                        {
                            cout << "error found case 2" << endl;
                            cout << "position: " << traversing_edge.nextTo->character << traversing_edge.nextTo->position.first << traversing_edge.nextTo->position.second << endl;
                            conditionMet = true;
                            break;
                        }

                        if (start_position->position.first - traversing_edge.nextTo->position.first  == changeX && start_position->position.second - traversing_edge.nextTo->position.second == changeY)
                        {
                            if (traversing_edge.nextTo->adjacent.size() == 3 )
                            {
                                start_position = traversing_edge.nextTo;
                                cout << "traversed to position: " << start_position->position.first << start_position->position.second <<" character: "<<start_position->character<< endl;
                                trace.push_back(start_position);
                            }

                            if (traversing_edge.nextTo->adjacent.size() == 2)
                            {
                                edge.nextTo->lock = true;
                                start_position = traversing_edge.nextTo;
                                cout << "traversed to position being corner: " << start_position->position.first << start_position->position.second <<" character: "<<start_position->character<< endl;
                                trace.push_back(start_position);
                                endIsCorner = true;
                            }

                            if (traversing_edge.nextTo->adjacent.size() == 4)
                            {
                                cout << "traversed something else: " << start_position->position.first << start_position->position.second <<" character: "<<start_position->character<< endl;
                                start_position = traversing_edge.nextTo;
                            }
                        }
                        cout << endl;
                    }
                    if (conditionMet)
                    {
                        break;/* code */
                    }

                }
                if (endIsCorner == true)
                {
                    for(auto traced: trace)
                    {
                        cout << "Traced for locking position: " <<traced->position.first << traced->position.second << traced->character<< endl;
                        if (traced->character == '.')
                        {
                            cout << "locking position: " <<traced->position.first << traced->position.second << traced->character<< endl;
                            traced->lock = true;
                        }
                    }
                }
                else
                {
                    trace.empty();
                    endIsCorner = false;
                }
                cout<<endl;
            }

        }
        cout << endl;
    }

  cout << "Locks detected" << endl;

当我意识到代码没有按照我想要的去做时,我开始调试它。

所以我看到的第一件事很奇怪。它检测到的第一个节点是一个角,位于第2行和col 1,是正确的。

然后,它尝试在第一个nextTo节点的方向(即第3行,第2列)(也是一个角)上移动,但是又以某种方式进入了while循环?我不明白。调试器也说,它的相邻 vector 大小为2,但是在while循环中它以某种方式检测到大小为2,并正确退出while循环并将其设置为锁定节点。

当我完成所有这些操作时,我检查了整个图表,看是否应该锁定的东西也被锁定了……事实并非如此。
for(auto node :  graph)
{
    cout << "node position: " <<"(" << node.position.first << "," << node.position.second << ")" << " " << node.character << endl;
    if (node.locked)
    {
      cout << node.position.first << node.position.second << endl;
    }
}

为此我得到这个输出
node position: (2,1) .
21
node position: (3,1) .
31
node position: (2,2) .
node position: (3,2) .
node position: (4,2) Z
node position: (5,2) .
52
node position: (6,2) .
node position: (7,2) .
72
node position: (2,3) Y
node position: (3,3) Y
node position: (4,3) Y
node position: (5,3) Y
node position: (6,3) M
node position: (7,3) .
73
node position: (2,4) .
24
node position: (4,4) Z
node position: (2,5) .
25
node position: (4,5) .
node position: (5,5) .
55
node position: (1,6) .
16
node position: (2,6) .
node position: (4,6) Z
node position: (5,6) .
node position: (1,7) .
node position: (2,7) .
node position: (3,7) .
37
node position: (4,7) .
node position: (5,7) .
57
node position: (1,8) .
18
node position: (2,8) .
28
node position: (4,8) Z
48
node position: (5,8) .
58

这意味着它不仅锁定那些我想要锁定的对象(即我放置在指定位置的.字符),而且还锁定那些我不想锁定的对象(.以外的其他字符)。
(5,2) should not be locked
(2,4) should not be locked
(2,5) should not be locked
(1,7) should be locked
(4,7) should be locked

这里出了什么问题..我很确定这一定与我在调试器中发现的问题有关,但是我不明白为什么什至会发生这种情况?

- -更新 -

我似乎在这里发现了另一个问题。
corner found (7,2)
Check neighbour direction
neighbour direction is first: 10

position before:  72 now position: 62 change is: 1 0 Element is: .
traversed in right direction .
traversed to position: 52 Element: .

position before:  72   now position: 52 change is: -2 0 Element is: .
error found case 1
position: .72

这是从while循环中输出的。
while((start_position->adjacent.size() != 2|| start_position->adjacent.size() != 4) /*&& start_position->character =='.'*/)
                    {
                        for(Vertex traversing_edge : start_position->adjacent)
                        { .. }

我在start_position循环中更改了for的值,该循环将如何对此使用react?..在我的头上,它应该从头开始,从头开始,而不是继续迭代第一个start_position vector 。

应该是while而不是for吗?
Start_position首先是位于(7,2)的节点,然后遍历到右侧(6,2)的节点,然后成为新的start_position。然后它再次向右移动(5,2),并且start_position成为该节点。但是变量traversing_edge成为位于(7,2)的节点,因此错误地结束。.traversing_edge变为不可能的值,因为与位于(5,2)的节点相邻的节点只有邻居(4,2), (6,2),(5,3)...所以这里肯定有问题。

- 更新 -
      DDD
 D.Y....D
 D.Y   .
  ZYZ.Z.Z
  .Y DDDD
  .M
  DD

没有节点具有大小为1的相邻 vector ,还会创建带有空格字符的节点。 D显示应锁定的节点。

--- Lamda更新---

它是一个推箱子 map ,M是人物,Y是钻石,Z是目标。这个想法是M沿某个方向插入Y,但是为了防止将钻石移动到无法再次获取的位置,该方案将对图形进行预处理,以使这些位置被忽略。

最佳答案

所以..我终于通过改写解决了我的问题。

新版本的工作方式有所不同,人眼看起来有些结构化,但是比上面发布的版本慢。

我确定我在上面的代码中也发现了错误。
由于过度使用基于范围的for循环,因此无法在对象的成员值上插入值,调试器向我展示了该值。

修复该问题和其他一些事情会使它正常工作。

我要感谢所有尝试帮助解决我的问题的人,非常感谢您的帮助。我认为人们不会对这么长的帖子使用react,但是我感到同时我必须提供所有给定的信息,因此,如果有人敢于研究它,他们将有合理的机会理解它。

谢谢 :)

09-06 06:43