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
是标识符)以及一个编译和运行的代码示例(带有适当的#include
和namespace
声明)但是它不断删除我的点 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 [重复]