Skip to content

Commit a1dbb75

Browse files
committed
Use shared_ptr for CPolyline
This avoids a object lifetime bug in geo_polygon_collection
1 parent 4967a60 commit a1dbb75

21 files changed

Lines changed: 493 additions & 574 deletions

lib/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ add_resdata_pybind_module(_type resdata/rd_type_pybind.cpp resdata/types)
219219
add_resdata_pybind_module(_rd_util resdata/rd_util_pybind.cpp resdata)
220220
add_resdata_pybind_module(_ctime resdata/ctime_pybind.cpp resdata/util/util)
221221

222-
add_resdata_pybind_module(_cpolyline geometry/geo_polygon_pybind.cpp
222+
add_resdata_pybind_module(cpolyline geometry/geo_polygon_pybind.cpp
223223
resdata/geometry)
224224
add_resdata_pybind_module(
225225
_cpolyline_collection geometry/geo_polygon_collection_pybind.cpp

lib/geometry/geo_polygon.cpp

Lines changed: 47 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,14 @@
88
#include <ios>
99
#include <memory>
1010
#include <string>
11+
#include <tuple>
1112
#include <vector>
1213
#include <optional>
1314

1415
#include <ert/util/util.hpp>
1516

1617
#include <ert/geometry/geo_polygon.hpp>
1718

18-
void geo_polygon_add_point(rd::Polygon *polygon, double x, double y) {
19-
polygon->xcoord.push_back(x);
20-
polygon->ycoord.push_back(y);
21-
}
22-
23-
void geo_polygon_add_point_front(rd::Polygon *polygon, double x,
24-
double y) {
25-
polygon->xcoord.insert(polygon->xcoord.begin(), x);
26-
polygon->ycoord.insert(polygon->ycoord.begin(), y);
27-
}
28-
29-
void geo_polygon_close(rd::Polygon *polygon) {
30-
double x = polygon->xcoord.at(0);
31-
double y = polygon->ycoord.at(0);
32-
geo_polygon_add_point(polygon, x, y);
33-
}
34-
3519
static bool on_edge(double x1, double y1, double x2, double y2, double x0,
3620
double y0) {
3721
double xmin = std::min(x1, x2);
@@ -60,20 +44,18 @@ static bool on_edge(double x1, double y1, double x2, double y2, double x0,
6044
edge will be identified as inside. If the force_edge_inside variable
6145
is set to false the behaviour on the edges is undefined.
6246
*/
63-
bool geo_polygon_contains_point(const rd::Polygon *polygon, double x0,
64-
double y0, bool force_edge_inside) {
47+
bool rd::Polygon::contains_point(double x0, double y0,
48+
bool force_edge_inside) const {
6549
bool inside = false;
6650
double y = y0;
6751
double xc = 0;
6852

69-
const size_t num_points = polygon->xcoord.size();
53+
const size_t num_points = points.size();
7054

7155
for (size_t i = 0; i < num_points; i++) {
7256
const size_t next_point = ((i + 1) % num_points);
73-
double x1 = polygon->xcoord[i];
74-
double y1 = polygon->ycoord[i];
75-
double x2 = polygon->xcoord[next_point];
76-
double y2 = polygon->ycoord[next_point];
57+
auto [x1, y1] = points[i];
58+
auto [x2, y2] = points[next_point];
7759

7860
double ymin = std::min(y1, y2);
7961
double ymax = std::max(y1, y2);
@@ -117,48 +99,24 @@ bool geo_polygon_contains_point(const rd::Polygon *polygon, double x0,
11799
included.
118100
*/
119101

120-
rd::Polygon *geo_polygon_fload_alloc_irap(const char *filename) {
121-
std::string sfile{filename};
102+
std::shared_ptr<rd::Polygon> rd::Polygon::load_irap(const std::string &sfile) {
122103
std::ifstream stream{sfile};
123104
if (!stream)
124105
throw std::ios_base::failure("Failed to open: " + sfile);
125106

126-
auto polygon = std::make_unique<rd::Polygon>(filename);
107+
auto polygon = std::make_shared<rd::Polygon>(sfile);
127108
double x, y, z;
128109

129110
while (stream >> x >> y >> z) {
130111
if ((x == 999) && (y == 999) && (z == 999))
131112
break;
132-
133-
geo_polygon_add_point(polygon.get(), x, y);
113+
polygon->add_point(x, y);
134114
}
135115

136-
if ((polygon->xcoord.size() > 1)) {
137-
if ((polygon->xcoord.at(polygon->xcoord.size() - 1) ==
138-
polygon->xcoord.at(0)) &&
139-
(polygon->ycoord.at(polygon->ycoord.size() - 1) ==
140-
polygon->ycoord.at(0))) {
141-
142-
polygon->xcoord.pop_back();
143-
polygon->ycoord.pop_back();
144-
}
145-
}
146-
return polygon.release();
147-
}
148-
149-
void geo_polygon_reset(rd::Polygon *polygon) {
150-
polygon->xcoord.resize(0);
151-
polygon->ycoord.resize(0);
152-
}
153-
154-
size_t geo_polygon_get_size(const rd::Polygon *polygon) {
155-
return polygon->xcoord.size();
156-
}
157-
158-
void geo_polygon_iget_xy(const rd::Polygon *polygon, int index, double *x,
159-
double *y) {
160-
*x = polygon->xcoord.at(index);
161-
*y = polygon->ycoord.at(index);
116+
if ((polygon->size() > 1))
117+
if (polygon->points.back() == polygon->points[0])
118+
polygon->points.pop_back();
119+
return polygon;
162120
}
163121

164122
enum XLinesStatus {
@@ -184,7 +142,7 @@ static bool interval_overlap(double a1, double a2, double b1, double b2) {
184142
}
185143

186144
static XLinesStatus xsegments(const std::array<std::array<double, 2>, 4> points,
187-
double *x0, double *y0, double epsilon = 1e-6) {
145+
double epsilon = 1e-6) {
188146
double x1 = points[0][0];
189147
double x2 = points[1][0];
190148
double x3 = points[2][0];
@@ -210,7 +168,7 @@ static XLinesStatus xsegments(const std::array<std::array<double, 2>, 4> points,
210168
return NOT_CROSSING;
211169
}
212170

213-
// Parallell
171+
// Parallel
214172
if (fabs(denominator) < epsilon)
215173
return NOT_CROSSING;
216174

@@ -221,65 +179,46 @@ static XLinesStatus xsegments(const std::array<std::array<double, 2>, 4> points,
221179

222180
if ((mua < 0.0) || (mua > 1.0) || (mub < 0.0) || (mub > 1.0))
223181
return NOT_CROSSING;
224-
225-
*x0 = x1 + mua * (x2 - x1);
226-
*y0 = y1 + mua * (y2 - y1);
227-
228182
return CROSSING;
229183
}
230184
}
231185

232-
bool geo_polygon_segment_intersects(const rd::Polygon *polygon, double x1,
233-
double y1, double x2, double y2) {
234-
if (polygon->xcoord.empty())
186+
bool rd::Polygon::segment_intersects(double x1, double y1, double x2,
187+
double y2) const {
188+
if (empty())
235189
return false;
236-
std::array<std::array<double, 2>, 4> points{};
190+
std::array<std::array<double, 2>, 4> lpoints{};
237191

238-
points[0][0] = x1;
239-
points[1][0] = x2;
240-
points[0][1] = y1;
241-
points[1][1] = y2;
192+
lpoints[0][0] = x1;
193+
lpoints[1][0] = x2;
194+
lpoints[0][1] = y1;
195+
lpoints[1][1] = y2;
242196

243-
for (size_t index = 0; index < polygon->xcoord.size() - 1; index++) {
244-
double xc, yc;
197+
for (size_t index = 0; index < points.size() - 1; index++) {
245198

246-
points[2][0] = polygon->xcoord.at(index);
247-
points[3][0] = polygon->xcoord.at(index + 1);
248-
points[2][1] = polygon->ycoord.at(index);
249-
points[3][1] = polygon->ycoord.at(index + 1);
199+
auto [x, y] = points.at(index);
200+
auto [xn, yn] = points.at(index + 1);
201+
lpoints[2][0] = x;
202+
lpoints[3][0] = xn;
203+
lpoints[2][1] = y;
204+
lpoints[3][1] = yn;
250205

251-
{
252-
auto xline_status = xsegments(points, &xc, &yc);
253-
if ((xline_status == CROSSING) || (xline_status == OVERLAPPING))
254-
return true;
255-
}
206+
auto xline_status = xsegments(lpoints);
207+
if ((xline_status == CROSSING) || (xline_status == OVERLAPPING))
208+
return true;
256209
}
257210
return false;
258211
}
259212

260-
const char *geo_polygon_get_name(const rd::Polygon *polygon) {
261-
return polygon->name.has_value() ? (*polygon->name).c_str() : nullptr;
262-
}
263-
264-
void geo_polygon_set_name(rd::Polygon *polygon, const char *name) {
265-
if (name)
266-
polygon->name = name;
267-
else
268-
polygon->name = std::nullopt;
269-
}
270-
271-
double geo_polygon_get_length(rd::Polygon *polygon) {
272-
if (polygon->xcoord.size() == 1)
213+
double rd::Polygon::length() const {
214+
if (size() == 1)
273215
return 0;
274216
else {
275217
double length = 0;
276-
double x0 = polygon->xcoord.at(0);
277-
double y0 = polygon->ycoord.at(0);
278-
279-
for (size_t i = 1; i < polygon->xcoord.size(); i++) {
280-
double x1 = polygon->xcoord.at(i);
281-
double y1 = polygon->ycoord.at(i);
218+
auto [x0, y0] = points[0];
282219

220+
for (size_t i = 1; i < size(); i++) {
221+
auto [x1, y1] = points[i];
283222
length += sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
284223
x0 = x1;
285224
y0 = y1;
@@ -288,13 +227,17 @@ double geo_polygon_get_length(rd::Polygon *polygon) {
288227
}
289228
}
290229

291-
static bool approx_equal(const std::vector<double> &a,
292-
const std::vector<double> &b, double epsilon = 1e-8) {
230+
static bool approx_equal(const std::vector<std::tuple<double, double>> &a,
231+
const std::vector<std::tuple<double, double>> &b,
232+
double epsilon = 1e-8) {
293233
if (a.size() != b.size())
294234
return false;
295235

296236
for (size_t i = 0; i < a.size(); ++i) {
297-
if (std::abs(a[i] - b[i]) > epsilon) {
237+
if (std::abs(std::get<0>(a[i]) - std::get<0>(b[i])) > epsilon) {
238+
return false;
239+
}
240+
if (std::abs(std::get<1>(a[i]) - std::get<1>(b[i])) > epsilon) {
298241
return false;
299242
}
300243
}
@@ -303,15 +246,6 @@ static bool approx_equal(const std::vector<double> &a,
303246
/*
304247
Name is ignored in the comparison.
305248
*/
306-
bool geo_polygon_equal(const rd::Polygon *polygon1,
307-
const rd::Polygon *polygon2) {
308-
bool equal = polygon1->xcoord == polygon2->xcoord &&
309-
polygon1->ycoord == polygon2->ycoord;
310-
311-
if (!equal) {
312-
equal = approx_equal(polygon1->xcoord, polygon2->xcoord) &&
313-
approx_equal(polygon1->ycoord, polygon2->ycoord);
314-
}
315-
316-
return equal;
249+
bool rd::Polygon::operator==(const rd::Polygon &other) const {
250+
return approx_equal(this->points, other.points);
317251
}
Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include <cstdlib>
22

33
#include <map>
4+
#include <memory>
5+
#include <optional>
46
#include <string>
7+
#include <vector>
58

69
#include <ert/util/util.hpp>
710
#include <ert/util/type_macros.hpp>
8-
#include <ert/util/vector.hpp>
911

1012
#include <ert/geometry/geo_polygon.hpp>
1113
#include <ert/geometry/geo_polygon_collection.hpp>
@@ -14,8 +16,8 @@
1416

1517
struct geo_polygon_collection_struct {
1618
UTIL_TYPE_ID_DECLARATION;
17-
vector_ptr polygon_list = new_vector();
18-
std::map<std::string, rd::Polygon *> polygon_map;
19+
std::vector<std::shared_ptr<rd::Polygon>> polygon_list;
20+
std::map<std::string, std::shared_ptr<rd::Polygon>> polygon_map;
1921
};
2022

2123
UTIL_IS_INSTANCE_FUNCTION(geo_polygon_collection,
@@ -28,41 +30,35 @@ geo_polygon_collection_type *geo_polygon_collection_alloc() {
2830
}
2931

3032
int geo_polygon_collection_size(const geo_polygon_collection_type *polygons) {
31-
return vector_get_size(polygons->polygon_list.get());
33+
return polygons->polygon_list.size();
3234
}
3335

34-
rd::Polygon *
36+
std::shared_ptr<rd::Polygon>
3537
geo_polygon_collection_create_polygon(geo_polygon_collection_type *polygons,
3638
const char *name) {
37-
rd::Polygon *polygon{nullptr};
38-
bool create_polygon = true;
39+
std::shared_ptr<rd::Polygon> polygon;
3940

4041
if (name && geo_polygon_collection_has_polygon(polygons, name))
41-
create_polygon = false;
42+
return polygon;
4243

43-
if (create_polygon) {
44-
polygon = new rd::Polygon(name);
45-
geo_polygon_collection_add_polygon(polygons, polygon, true);
46-
}
44+
polygon = std::make_shared<rd::Polygon>(
45+
name ? std::optional<std::string>(name) : std::nullopt);
46+
geo_polygon_collection_add_polygon(polygons, polygon);
4747

4848
return polygon;
4949
}
5050

5151
bool geo_polygon_collection_add_polygon(geo_polygon_collection_type *polygons,
52-
rd::Polygon *polygon,
53-
bool polygon_owner) {
54-
const char *name = geo_polygon_get_name(polygon);
55-
if (geo_polygon_collection_has_polygon(polygons, name))
52+
std::shared_ptr<rd::Polygon> polygon) {
53+
auto name = polygon->get_name();
54+
if (geo_polygon_collection_has_polygon(
55+
polygons, name.has_value() ? name->c_str() : nullptr))
5656
return false;
5757
else {
58-
if (polygon_owner)
59-
vector_append_owned_ref(polygons->polygon_list.get(), polygon,
60-
[](void *arg) {delete static_cast<rd::Polygon *>(arg);});
61-
else
62-
vector_append_ref(polygons->polygon_list.get(), polygon);
58+
polygons->polygon_list.push_back(polygon);
6359

64-
if (name)
65-
polygons->polygon_map[name] = polygon;
60+
if (name.has_value())
61+
polygons->polygon_map[*name] = polygon;
6662

6763
return true;
6864
}
@@ -80,14 +76,14 @@ void geo_polygon_collection_free(geo_polygon_collection_type *polygons) {
8076
delete polygons;
8177
}
8278

83-
rd::Polygon *
79+
std::shared_ptr<rd::Polygon>
8480
geo_polygon_collection_iget_polygon(const geo_polygon_collection_type *polygons,
8581
int index) {
86-
return (rd::Polygon *)vector_iget(polygons->polygon_list.get(), index);
82+
return polygons->polygon_list.at(index);
8783
}
8884

89-
rd::Polygon *
85+
std::shared_ptr<rd::Polygon>
9086
geo_polygon_collection_get_polygon(const geo_polygon_collection_type *polygons,
91-
const char *polygon_name) {
87+
const std::string &polygon_name) {
9288
return polygons->polygon_map.at(polygon_name);
9389
}

0 commit comments

Comments
 (0)