ID 字段在自定义点类中间歇性丢失

Posted

技术标签:

【中文标题】ID 字段在自定义点类中间歇性丢失【英文标题】:ID field intermittently lost in custom point class 【发布时间】:2015-03-15 01:53:13 【问题描述】:

我正在构建一个需要处理几何图形的 C++ 程序。我一直试图让boost::geometry 工作,但我遇到了以下问题。我的观点需要维护一个 ID 值或其他识别标签(我需要将它们链接到存储在其他对象中的属性)。我可以使用BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET 成功注册此点并执行boost::geometry 操作,但是当我对其执行任何操作时boost::geometry 似乎创建了我的点的新副本而没有id 值。

使用带有自定义点的boost::geometry 是否有什么我遗漏的东西可以做我想做的事情,还是我必须重新考虑我的方法并找到其他方法来做我想做什么?

以下代码显示了一个示例点类(int id 是标识符)以及一个编译和运行的代码示例(带有适当的#includenamespace 声明)但是它不断删除我的点 ID:

点类:

class My_Point

public:

    My_Point(const My_Point &p);
    My_Point(double x = 0.0, double y = 0.0, int new_id = 0);

    const double Get_X() const;
    const double Get_Y() const;

    void Set_X(double new_x);
    void Set_Y(double new_y);

    const int Get_ID() const;
    void Set_ID(int new_id);

private:
    int id;
    double x;
    double y;

复制构造函数:

My_Point::My_Point(const My_Point &p) 
    Set_X(p.Get_X());
    Set_Y(p.Get_Y());
    Set_ID(p.Get_ID());
 

测试代码:

void TestPolygon()

vector < My_Point > p;

p.push_back(My_Point(0.0, 0.0, 0));
p.push_back(My_Point(1.0, 0.0, 1));
p.push_back(My_Point(1.0, 1.0, 2));
p.push_back(My_Point(0.0, 1.0, 3));
p.push_back(My_Point(0.0, 0.0, 4));

cout << "Initial points are:\n";

for (int i = 0, n = p.size(); i < n; i++)

    cout << point_to_string(p.at(i)) << "\n";


detect_enter();

polygon<My_Point> poly;
append(poly, p);

//this code gives each point with an incorrect id of 0
cout << "Polygon points are:\n";

for (int i = 0, n = poly.outer().size(); i < n; i++)

    cout << point_to_string(poly.outer().at(i)) << "\n";


detect_enter();

strategy::transform::rotate_transformer<degree, double, 2, 2> rotate(45.0);

for (int i = 0, n = poly.outer().size(); i < n; i++)

    transform(poly.outer().at(i), poly.outer().at(i), rotate);


vector<My_Point> p2;
p2 = poly.outer();

//this code gives an incorrect id of 0.
cout << "Final points are:\n";

for (int i = 0, n = p2.size(); i < n; i++)

    cout << point_to_string(p2.at(i)) << "\n";


detect_enter();

//this code gives the correct id values as expected.
cout << "Original points were:\n";

for (int i = 0, n = p.size(); i < n; i++)

    cout << point_to_string(p.at(i)) << "\n";


【问题讨论】:

你的复制构造函数是做什么的? 感谢尼尔的提问。复制构造函数代码为: My_Point::My_Point(const My_Point &p) Set_X(p.Get_X()); Set_Y(p.Get_Y()); Set_ID(p.Get_ID()); 如果您所做的只是直接复制,则不应提供复制构造函数。它会自动生成一个。 谢谢尼尔 - 如果我注释掉复制构造函数,我仍然有同样的问题,所以这不是问题所在。另外,我显然没有使用 Stack Overflow 的评论格式的窍门,但我无法让我之前评论中的代码正确格式化...... “另外,我显然还没有掌握使用 Stack Overflow 的评论格式的窍门……” - 您应该将相关信息添加到您的问题中。您可以通过单击编辑链接来做到这一点。 【参考方案1】:

正如 sehe 指出的,该库只知道如何访问 My_Point 的 X 和 Y 坐标。此外, rotate_transformer 只知道如何旋转您的点的几何部分,它不知道您正在存储 ID 并且您想复制它们。您可以尝试为此编写自己的策略。类似的东西(未测试):

struct my_rotate_transformer
    : public strategy::transform::rotate_transformer<degree, double, 2, 2>

    typedef strategy::transform::rotate_transformer<degree, double, 2, 2> base_t;

    my_rotate_transformer(double angle)
        : base_t(angle)
      

    template <typename P1, typename P2>
    bool apply(P1 const& p1, P2& p2) const
    
        p2.Set_ID(p1.Get_ID());
        return base_t::apply(p1, p2);
    

这类似于std::transform() 的使用方式。您必须传递一个UnaryOperation,它可以按照您喜欢的方式转换 Range 的元素。在 Boost.Geometry 中,策略用于此目的。

顺便说一句,这是一个简单的案例,您可以手动复制/设置 ID。

另一件事是bg::transform() 适用于任意几何,因此您可以在那里传递多边形(但是您需要另一个多边形):

polygon<My_Point> poly_in;
polygon<My_Point> poly_out;
bg::transform(poly_in, poly_out, my_rotate_transformer(45))

使用append() 可以直接将点附加到多边形。我认为没有必要使用临时std::vector

另外,请记住,某些算法会创建全新的几何图形,包含新的点,例如intersection()convex_hull() 所以可能不应该复制 ID,或者不复制所有 ID。

最后但并非最不重要的一点是,我猜测某些算法可能会在您的场景中引起问题,这可能取决于算法。因此,请随时提出问题。还可以考虑订阅 Boost.Geometry 邮件列表。这是与开发人员联系、提出新功能、报告错误等的好地方。

【讨论】:

不错。我很想知道如何做到这一点。你认为点概念(和改编)是否应该扩展以允许“丰富”点?我知道许多应用程序拥有“重”点类型是愚蠢的,但对于只想在小几何图形上利用现有算法的应用程序......感觉有点像没有void* userdata 的 C 回调 API对我的争论 @sehe 这可能取决于我们究竟想如何处理这些重点。只是为了在可变算法中传播这个扩展部分?它可能仅对可变算法有用,但并非全部有用。集合操作会创建不同的几何形状,因此点可能不应该被传播。剩下的是transform()simplify() 问题是,目前没有没有方法将源几何的元数据与输出几何(例如,凸包、交叉点)相关联。按坐标走很脆弱,尤其是重复/共享点或浮点值。我真的不确定如何使这种事情可靠。 我试图在 mailing list thread 中找到我记得的处理多面体附加信息的代码,但遗憾的是 codepad.org 样本已经丢失。我认为它有一个非常通用的“二进制变换”算法(?) 啊,是的,convex_hull() 也可以从中受益。 intersection() 不是很多,因为通常会在线段中间的某个位置生成新点,对于相交的顶点,我们不知道应该传播哪个。【参考方案2】:

您执行BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET。问题是,这告诉库如何设置 x 和 y 值。它从不告诉库如何设置 ID 值(或者它甚至在那里)。

因此,该库将通过使用 x 和 y 的设置器从逻辑上简单地构造一个相同的点,当然,您将被困在没有 id 的情况下。

【讨论】:

以上是关于ID 字段在自定义点类中间歇性丢失的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 UlTableViewCell 中使用 UITextField 时 resignFirstResponder 崩溃

在自定义 UIView 类中从 UIView 快速创建 IBoutlet [重复]

如何让 .xib 出现在自定义类中

Datepicker 不会显示在自定义 UITableViewCell 类中

在自定义类中使用setMouseCallBack

在自定义 View 类中使用 UIImageView 的正确方法