diff --git a/spatial/include/spatial/core/geometry/geometry.hpp b/spatial/include/spatial/core/geometry/geometry.hpp index fb6d1d37..b2e9994d 100644 --- a/spatial/include/spatial/core/geometry/geometry.hpp +++ b/spatial/include/spatial/core/geometry/geometry.hpp @@ -104,8 +104,7 @@ class Point { } string ToString() const; bool IsEmpty() const; - Vertex &GetVertex(); - const Vertex &GetVertex() const; + Vertex GetVertex() const; const VertexVector &Vertices() const { return vertices; diff --git a/spatial/include/spatial/core/geometry/vertex_vector.hpp b/spatial/include/spatial/core/geometry/vertex_vector.hpp index 9e839fa9..af06f911 100644 --- a/spatial/include/spatial/core/geometry/vertex_vector.hpp +++ b/spatial/include/spatial/core/geometry/vertex_vector.hpp @@ -66,39 +66,18 @@ class VertexVector { public: uint32_t count; uint32_t capacity; - Vertex *data; + data_ptr_t data; - explicit VertexVector(Vertex *data, uint32_t count, uint32_t capacity) + explicit VertexVector(data_ptr_t data, uint32_t count, uint32_t capacity) : count(count), capacity(capacity), data(data) { } // Create a VertexVector from an already existing buffer - static VertexVector FromBuffer(Vertex *buffer, uint32_t count) { + static VertexVector FromBuffer(data_ptr_t buffer, uint32_t count) { VertexVector array(buffer, count, count); return array; } - inline Vertex &operator[](uint32_t index) const { - D_ASSERT(index < count); - return data[index]; - } - - inline Vertex *begin() { - return data; - } - - inline Vertex *end() { - return data + count; - } - - const Vertex *begin() const { - return data; - } - - const Vertex *end() const { - return data + count; - } - inline uint32_t Count() const { return count; } @@ -109,7 +88,18 @@ class VertexVector { inline void Add(const Vertex &v) { D_ASSERT(count < capacity); - data[count++] = v; + Store(v, data + count * sizeof(Vertex)); + count++; + } + + inline void Set(uint32_t index, const Vertex &v) const { + D_ASSERT(index < count); + Store(v, data + index * sizeof(Vertex)); + } + + inline Vertex Get(uint32_t index) const { + D_ASSERT(index < count); + return Load(data + index * sizeof(Vertex)); } // Returns the number of bytes that this VertexVector requires to be serialized @@ -120,10 +110,6 @@ class VertexVector { void Serialize(Cursor &cursor) const; void SerializeAndUpdateBounds(Cursor &cursor, BoundingBox &bbox) const; - inline Vertex *Data() { - return data; - } - double Length() const; double SignedArea() const; double Area() const; diff --git a/spatial/src/spatial/core/functions/cast/geometry_cast.cpp b/spatial/src/spatial/core/functions/cast/geometry_cast.cpp index 28cfd26e..d88b6408 100644 --- a/spatial/src/spatial/core/functions/cast/geometry_cast.cpp +++ b/spatial/src/spatial/core/functions/cast/geometry_cast.cpp @@ -46,7 +46,7 @@ static bool GeometryToPoint2DCast(Vector &source, Vector &result, idx_t count, C if (point.IsEmpty()) { throw CastException("Cannot cast empty point GEOMETRY to POINT_2D"); } - auto &vertex = point.GetVertex(); + auto vertex = point.GetVertex(); return POINT_TYPE {vertex.x, vertex.y}; }); return true; @@ -103,8 +103,8 @@ static bool GeometryToLineString2DCast(Vector &source, Vector &result, idx_t cou ListVector::Reserve(result, total_coords); for (idx_t i = 0; i < line_size; i++) { - x_data[entry.offset + i] = line.Vertices()[i].x; - y_data[entry.offset + i] = line.Vertices()[i].y; + x_data[entry.offset + i] = line.Vertices().Get(i).x; + y_data[entry.offset + i] = line.Vertices().Get(i).y; } return entry; }); @@ -182,8 +182,8 @@ static bool GeometryToPolygon2DCast(Vector &source, Vector &result, idx_t count, ring_entries[total_rings + ring_idx] = ring_entry; for (idx_t j = 0; j < ring_size; j++) { - x_data[ring_entry.offset + j] = ring.data[j].x; - y_data[ring_entry.offset + j] = ring.data[j].y; + x_data[ring_entry.offset + j] = ring.Get(j).x; + y_data[ring_entry.offset + j] = ring.Get(j).y; } total_coords += ring_size; } @@ -217,16 +217,13 @@ static bool Box2DToGeometryCast(Vector &source, Vector &result, idx_t count, Cas auto geom = lstate.factory.CreatePolygon(1, &capacity); auto &shell = geom.Ring(0); - shell.data[0].x = minx; - shell.data[0].y = miny; - shell.data[1].x = maxx; - shell.data[1].y = miny; - shell.data[2].x = maxx; - shell.data[2].y = maxy; - shell.data[3].x = minx; - shell.data[3].y = maxy; - shell.data[4].x = minx; - shell.data[4].y = miny; + + shell.Set(0, Vertex(minx, miny)); + shell.Set(1, Vertex(maxx, miny)); + shell.Set(2, Vertex(maxx, maxy)); + shell.Set(3, Vertex(minx, maxy)); + shell.Set(4, Vertex(minx, miny)); + shell.count = 5; return lstate.factory.Serialize(result, Geometry(geom)); }); diff --git a/spatial/src/spatial/core/functions/scalar/st_asgeojson.cpp b/spatial/src/spatial/core/functions/scalar/st_asgeojson.cpp index 87f02d2d..cabe2ceb 100644 --- a/spatial/src/spatial/core/functions/scalar/st_asgeojson.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_asgeojson.cpp @@ -60,7 +60,7 @@ class JSONAllocator { static void VerticesToGeoJSON(const VertexVector &vertices, yyjson_mut_doc *doc, yyjson_mut_val *arr) { // TODO: If the vertexvector is empty, do we null, add an empty array or a pair of NaN? for (uint32_t i = 0; i < vertices.count; i++) { - auto &vertex = vertices[i]; + auto vertex = vertices.Get(i); auto coord = yyjson_mut_arr(doc); yyjson_mut_arr_add_real(doc, coord, vertex.x); yyjson_mut_arr_add_real(doc, coord, vertex.y); @@ -75,7 +75,7 @@ static void ToGeoJSON(const Point &point, yyjson_mut_doc *doc, yyjson_mut_val *o yyjson_mut_obj_add_val(doc, obj, "coordinates", coords); if (!point.IsEmpty()) { - auto &vertex = point.GetVertex(); + auto vertex = point.GetVertex(); yyjson_mut_arr_add_real(doc, coords, vertex.x); yyjson_mut_arr_add_real(doc, coords, vertex.y); } diff --git a/spatial/src/spatial/core/functions/scalar/st_endpoint.cpp b/spatial/src/spatial/core/functions/scalar/st_endpoint.cpp index d65cfcc3..b17aa5af 100644 --- a/spatial/src/spatial/core/functions/scalar/st_endpoint.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_endpoint.cpp @@ -80,7 +80,7 @@ static void GeometryEndPointFunction(DataChunk &args, ExpressionState &state, Ve return string_t(); } - auto &point = line.Vertices()[point_count - 1]; + auto point = line.Vertices().Get(point_count - 1); return lstate.factory.Serialize(result, Geometry(lstate.factory.CreatePoint(point.x, point.y))); }); } diff --git a/spatial/src/spatial/core/functions/scalar/st_exteriorring.cpp b/spatial/src/spatial/core/functions/scalar/st_exteriorring.cpp index 6127b2fb..f450d751 100644 --- a/spatial/src/spatial/core/functions/scalar/st_exteriorring.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_exteriorring.cpp @@ -114,7 +114,7 @@ static void GeometryExteriorRingFunction(DataChunk &args, ExpressionState &state auto line = lstate.factory.CreateLineString(num_points); for (uint32_t i = 0; i < num_points; i++) { - line.Vertices().Add(shell[i]); + line.Vertices().Add(shell.Get(i)); } return lstate.factory.Serialize(result, Geometry(line)); }); diff --git a/spatial/src/spatial/core/functions/scalar/st_flipcoordinates.cpp b/spatial/src/spatial/core/functions/scalar/st_flipcoordinates.cpp index 7c69852f..5ba87e92 100644 --- a/spatial/src/spatial/core/functions/scalar/st_flipcoordinates.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_flipcoordinates.cpp @@ -155,7 +155,9 @@ static void BoxFlipCoordinatesFunction(DataChunk &args, ExpressionState &state, //------------------------------------------------------------------------------ static void FlipVertexVector(VertexVector &vertices) { for (idx_t i = 0; i < vertices.count; i++) { - std::swap(vertices[i].x, vertices[i].y); + auto vertex = vertices.Get(i); + std::swap(vertex.x, vertex.y); + vertices.Set(i, vertex); } } static void FlipGeometry(Point &point) { diff --git a/spatial/src/spatial/core/functions/scalar/st_makepolygon.cpp b/spatial/src/spatial/core/functions/scalar/st_makepolygon.cpp index 181fb921..27523adc 100644 --- a/spatial/src/spatial/core/functions/scalar/st_makepolygon.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_makepolygon.cpp @@ -35,7 +35,7 @@ static void MakePolygonFromRingsFunction(DataChunk &args, ExpressionState &state } auto &shell_verts = shell.Vertices(); - if (shell_verts[0] != shell_verts[shell_vert_count - 1]) { + if (!shell_verts.IsClosed()) { throw InvalidInputException( "ST_MakePolygon shell must be closed (first and last vertex must be equal)"); } @@ -70,7 +70,7 @@ static void MakePolygonFromRingsFunction(DataChunk &args, ExpressionState &state } auto &ring_verts = hole.Vertices(); - if (ring_verts[0] != ring_verts[hole_count - 1]) { + if (!ring_verts.IsClosed()) { throw InvalidInputException(StringUtil::Format( "ST_MakePolygon hole #%lu must be closed (first and last vertex must be equal)", hole_idx + 1)); } @@ -84,8 +84,9 @@ static void MakePolygonFromRingsFunction(DataChunk &args, ExpressionState &state for (idx_t ring_idx = 0; ring_idx < rings.size(); ring_idx++) { auto &new_ring = rings[ring_idx]; auto &poly_ring = polygon.Ring(ring_idx); - for (auto &v : new_ring.Vertices()) { - poly_ring.Add(v); + + for(auto i = 0; i < new_ring.Vertices().Count(); i++) { + poly_ring.Add(new_ring.Vertices().Get(i)); } } @@ -111,13 +112,13 @@ static void MakePolygonFromShellFunction(DataChunk &args, ExpressionState &state } auto &line_verts = line.Vertices(); - if (line_verts[0] != line_verts[line_count - 1]) { + if (!line_verts.IsClosed()) { throw InvalidInputException("ST_MakePolygon shell must be closed (first and last vertex must be equal)"); } auto polygon = lstate.factory.CreatePolygon(1, &line_count); - for (auto &v : line_verts) { - polygon.Shell().Add(v); + for (uint32_t i = 0; i < line_count; i++) { + polygon.Shell().Add(line_verts.Get(i)); } return lstate.factory.Serialize(result, Geometry(polygon)); diff --git a/spatial/src/spatial/core/functions/scalar/st_perimeter.cpp b/spatial/src/spatial/core/functions/scalar/st_perimeter.cpp index 752e27f8..88efd4ef 100644 --- a/spatial/src/spatial/core/functions/scalar/st_perimeter.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_perimeter.cpp @@ -76,8 +76,8 @@ static double PolygonPerimeter(const Polygon &poly) { double perimeter = 0; for (auto &ring : poly.Rings()) { for (uint32_t i = 0; i < ring.Count() - 1; i++) { - auto &v1 = ring[i]; - auto &v2 = ring[i + 1]; + auto v1 = ring.Get(i); + auto v2 = ring.Get(i + 1); perimeter += std::sqrt(std::pow(v1.x - v2.x, 2) + std::pow(v1.y - v2.y, 2)); } } diff --git a/spatial/src/spatial/core/functions/scalar/st_pointn.cpp b/spatial/src/spatial/core/functions/scalar/st_pointn.cpp index 0d35a2de..4bb8511f 100644 --- a/spatial/src/spatial/core/functions/scalar/st_pointn.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_pointn.cpp @@ -90,7 +90,7 @@ static void GeometryPointNFunction(DataChunk &args, ExpressionState &state, Vect } auto actual_index = index < 0 ? point_count + index : index - 1; - auto &point = line.Vertices()[actual_index]; + auto point = line.Vertices().Get(actual_index); return lstate.factory.Serialize(result, Geometry(lstate.factory.CreatePoint(point.x, point.y))); }); } diff --git a/spatial/src/spatial/core/functions/scalar/st_startpoint.cpp b/spatial/src/spatial/core/functions/scalar/st_startpoint.cpp index 722c21c6..2e960cad 100644 --- a/spatial/src/spatial/core/functions/scalar/st_startpoint.cpp +++ b/spatial/src/spatial/core/functions/scalar/st_startpoint.cpp @@ -80,7 +80,7 @@ static void GeometryStartPointFunction(DataChunk &args, ExpressionState &state, return string_t(); } - auto &point = line.Vertices()[0]; + auto point = line.Vertices().Get(0); return lstate.factory.Serialize(result, Geometry(lstate.factory.CreatePoint(point.x, point.y))); }); } diff --git a/spatial/src/spatial/core/geometry/geometry.cpp b/spatial/src/spatial/core/geometry/geometry.cpp index 9d400ace..138f0449 100644 --- a/spatial/src/spatial/core/geometry/geometry.cpp +++ b/spatial/src/spatial/core/geometry/geometry.cpp @@ -33,28 +33,22 @@ string Point::ToString() const { if (IsEmpty()) { return "POINT EMPTY"; } - auto &vert = vertices[0]; + auto vert = vertices.Get(0); if (std::isnan(vert.x) && std::isnan(vert.y)) { // This is a special case for WKB. WKB does not support empty points, // and instead writes a point with NaN coordinates. We therefore need to // check for this case and return POINT EMPTY instead to round-trip safely return "POINT EMPTY"; } - auto x = vertices[0].x; - auto y = vertices[0].y; - return StringUtil::Format("POINT (%s)", Utils::format_coord(x, y)); + return StringUtil::Format("POINT (%s)", Utils::format_coord(vert.x, vert.y)); } bool Point::IsEmpty() const { return vertices.Count() == 0; } -Vertex &Point::GetVertex() { - return vertices[0]; -} - -const Vertex &Point::GetVertex() const { - return vertices[0]; +Vertex Point::GetVertex() const { + return vertices.Get(0); } Point::operator Geometry() const { @@ -85,8 +79,8 @@ string LineString::ToString() const { string result = "LINESTRING ("; for (uint32_t i = 0; i < vertices.Count(); i++) { - auto x = vertices[i].x; - auto y = vertices[i].y; + auto x = vertices.Get(i).x; + auto y = vertices.Get(i).y; result += Utils::format_coord(x, y); if (i < vertices.Count() - 1) { result += ", "; @@ -150,8 +144,8 @@ string Polygon::ToString() const { for (uint32_t i = 0; i < num_rings; i++) { result += "("; for (uint32_t j = 0; j < rings[i].Count(); j++) { - auto x = rings[i][j].x; - auto y = rings[i][j].y; + auto x = rings[i].Get(j).x; + auto y = rings[i].Get(j).y; result += Utils::format_coord(x, y); if (j < rings[i].Count() - 1) { result += ", "; @@ -187,7 +181,7 @@ string MultiPoint::ToString() const { if (points[i].IsEmpty()) { str += "EMPTY"; } else { - auto &vert = points[i].GetVertex(); + auto vert = points[i].GetVertex(); str += Utils::format_coord(vert.x, vert.y); } if (i < num_points - 1) { @@ -249,7 +243,8 @@ string MultiLineString::ToString() const { } str += "("; bool first_vert = true; - for (auto &vert : line.Vertices()) { + for (uint32_t i = 0; i < line.Vertices().Count(); i++) { + auto vert = line.Vertices().Get(i); if (first_vert) { first_vert = false; } else { @@ -330,7 +325,8 @@ string MultiPolygon::ToString() const { } str += "("; bool first_vert = true; - for (auto &vert : ring) { + for (uint32_t v = 0; v < ring.Count(); v++) { + auto vert = ring.Get(v); if (first_vert) { first_vert = false; } else { diff --git a/spatial/src/spatial/core/geometry/geometry_factory.cpp b/spatial/src/spatial/core/geometry/geometry_factory.cpp index 68372017..01c2dab7 100644 --- a/spatial/src/spatial/core/geometry/geometry_factory.cpp +++ b/spatial/src/spatial/core/geometry/geometry_factory.cpp @@ -33,7 +33,7 @@ data_ptr_t GeometryFactory::ToWKB(const Geometry &geometry, uint32_t *size) { } VertexVector GeometryFactory::AllocateVertexVector(uint32_t capacity) { - auto data = reinterpret_cast(allocator.AllocateAligned(sizeof(Vertex) * capacity)); + auto data = allocator.AllocateAligned(sizeof(Vertex) * capacity); return VertexVector(data, 0, capacity); } @@ -563,11 +563,11 @@ Point GeometryFactory::DeserializePoint(Cursor &reader) { // Points can be empty too, in which case the count is 0 auto count = reader.Read(); if (count == 0) { - VertexVector vertex_data((Vertex *)reader.GetPtr(), 0, 0); + VertexVector vertex_data(reader.GetPtr(), 0, 0); return Point(vertex_data); } else { D_ASSERT(count == 1); - VertexVector vertex_data((Vertex *)reader.GetPtr(), 1, 1); + VertexVector vertex_data(reader.GetPtr(), 1, 1); // Move the pointer forward (in case we are reading from a collection type) reader.Skip(sizeof(Vertex)); return Point(vertex_data); @@ -581,7 +581,7 @@ LineString GeometryFactory::DeserializeLineString(Cursor &reader) { // 0 if the linestring is empty auto count = reader.Read(); // read data - VertexVector vertex_data((Vertex *)reader.GetPtr(), count, count); + VertexVector vertex_data(reader.GetPtr(), count, count); reader.Skip(count * sizeof(Vertex)); @@ -601,7 +601,7 @@ Polygon GeometryFactory::DeserializePolygon(Cursor &reader) { auto data_ptr = reader.GetPtr() + sizeof(uint32_t) * num_rings + ((num_rings % 2) * sizeof(uint32_t)); for (uint32_t i = 0; i < num_rings; i++) { auto count = reader.Read(); - rings[i] = VertexVector((Vertex *)data_ptr, count, count); + rings[i] = VertexVector(data_ptr, count, count); data_ptr += count * sizeof(Vertex); } reader.SetPtr(data_ptr); @@ -696,7 +696,7 @@ GeometryCollection GeometryFactory::DeserializeGeometryCollection(Cursor &reader VertexVector GeometryFactory::CopyVertexVector(const VertexVector &vector) { auto result = VertexVector(vector); - result.data = (Vertex *)allocator.AllocateAligned(vector.capacity * sizeof(Vertex)); + result.data = allocator.AllocateAligned(vector.capacity * sizeof(Vertex)); memcpy(result.data, vector.data, vector.capacity * sizeof(Vertex)); return result; } diff --git a/spatial/src/spatial/core/geometry/vertex_vector.cpp b/spatial/src/spatial/core/geometry/vertex_vector.cpp index dd5e29a7..a8ab838f 100644 --- a/spatial/src/spatial/core/geometry/vertex_vector.cpp +++ b/spatial/src/spatial/core/geometry/vertex_vector.cpp @@ -34,7 +34,7 @@ void VertexVector::Serialize(Cursor &cursor) const { void VertexVector::SerializeAndUpdateBounds(Cursor &cursor, BoundingBox &bbox) const { for (idx_t i = 0; i < count; i++) { - auto &p = data[i]; + auto p = Get(i); bbox.minx = std::min(bbox.minx, p.x); bbox.miny = std::min(bbox.miny, p.y); bbox.maxx = std::max(bbox.maxx, p.x); @@ -50,8 +50,8 @@ double VertexVector::Length() const { return 0.0; } for (uint32_t i = 0; i < count - 1; i++) { - auto &p1 = data[i]; - auto &p2 = data[i + 1]; + auto p1 = Get(i); + auto p2 = Get(i + 1); length += std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } return length; @@ -67,11 +67,11 @@ double VertexVector::SignedArea() const { // We don't need to do this for the y coordinate because we already // subtract them between consecutive vertices double area = 0; - auto x0 = data[0].x; + auto x0 = Get(0).x; for (uint32_t i = 1; i < count - 1; ++i) { - auto x1 = data[i].x; - auto y1 = data[i + 1].y; - auto y2 = data[i - 1].y; + auto x1 = Get(i).x; + auto y1 = Get(i + 1).y; + auto y2 = Get(i - 1).y; area += (x1 - x0) * (y2 - y1); } @@ -152,7 +152,7 @@ bool VertexVector::IsClosed() const { if (count == 1) { return true; } - return data[0] == data[count - 1]; + return Get(0) == Get(count - 1); } bool VertexVector::IsEmpty() const { @@ -177,8 +177,8 @@ bool VertexVector::IsSimple() const { Contains VertexVector::ContainsVertex(const Vertex &p, bool ensure_closed) const { - auto &p1 = data[0]; - auto &p2 = data[count - 1]; + auto p1 = Get(0); + auto p2 = Get(count - 1); if (ensure_closed && p1 != p2) { throw InternalException("VertexVector::Contains: VertexVector is not closed"); @@ -187,7 +187,7 @@ Contains VertexVector::ContainsVertex(const Vertex &p, bool ensure_closed) const int winding_number = 0; for (uint32_t i = 0; i < count; i++) { - p2 = data[i]; + p2 = Get(i); if (p1 == p2) { p1 = p2; continue; @@ -218,9 +218,9 @@ std::tuple VertexVector::ClosestSegment(const Vertex &p) const double min_distance = std::numeric_limits::max(); uint32_t min_index = 0; // Loop over all segments and find the closest one - auto &p1 = data[0]; + auto p1 = Get(0); for (uint32_t i = 1; i < count; i++) { - auto &p2 = data[i]; + auto p2 = Get(i); auto distance = p.DistanceSquared(p1, p2); if (distance < min_distance) { min_distance = distance; @@ -243,7 +243,7 @@ std::tuple VertexVector::ClosetVertex(const Vertex &p) const { // Loop over all segments and find the closest one for (uint32_t i = 0; i < count; i++) { - auto &p1 = data[i]; + auto p1 = Get(i); auto distance = p.DistanceSquared(p1); if (distance < min_distance) { @@ -264,18 +264,18 @@ std::tuple VertexVector::LocateVertex(const Vertex &p) c return std::make_tuple(Vertex(), 0, 0); } if (count == 1) { - auto single = data[0]; + auto single = Get(0); return std::make_tuple(single, 0, p.Distance(single)); } auto min_distance = std::numeric_limits::max(); uint32_t min_index = 0; - auto &p1 = data[0]; - auto &p2 = data[1]; + auto p1 = Get(0); + auto p2 = Get(1); // Search for the closest segment for (uint32_t i = 1; i < count; i++) { - p2 = data[i]; + p2 = Get(i); auto seg_distance = p.DistanceSquared(p1, p2); if (seg_distance < min_distance) { min_distance = seg_distance; @@ -300,8 +300,8 @@ std::tuple VertexVector::LocateVertex(const Vertex &p) c } auto Vertex_length = 0.0; for (uint32_t i = 0; i < min_index; i++) { - p1 = data[i]; - p2 = data[i + 1]; + p1 = Get(i); + p2 = Get(i + 1); Vertex_length += p1.Distance(p2); } diff --git a/spatial/src/spatial/core/geometry/wkb_writer.cpp b/spatial/src/spatial/core/geometry/wkb_writer.cpp index 3ccdd430..c0c651fa 100644 --- a/spatial/src/spatial/core/geometry/wkb_writer.cpp +++ b/spatial/src/spatial/core/geometry/wkb_writer.cpp @@ -145,7 +145,7 @@ void WKBWriter::Write(const Point &point, data_ptr_t &ptr) { WriteDouble(x, ptr); WriteDouble(y, ptr); } else { - auto &vertex = point.GetVertex(); + auto vertex = point.GetVertex(); WriteDouble(vertex.x, ptr); WriteDouble(vertex.y, ptr); } @@ -157,7 +157,8 @@ void WKBWriter::Write(const LineString &line, data_ptr_t &ptr) { auto num_points = line.Count(); WriteInt(num_points, ptr); - for (auto &vertex : line.Vertices()) { + for(uint32_t i = 0; i < line.Vertices().Count(); i++) { + auto vertex = line.Vertices().Get(i); WriteDouble(vertex.x, ptr); WriteDouble(vertex.y, ptr); } @@ -170,7 +171,9 @@ void WKBWriter::Write(const Polygon &polygon, data_ptr_t &ptr) { WriteInt(polygon.Count(), ptr); for (auto &ring : polygon.Rings()) { WriteInt(ring.Count(), ptr); - for (auto &vertex : ring) { + + for (uint32_t i = 0; i < ring.Count(); i++) { + auto vertex = ring.Get(i); WriteDouble(vertex.x, ptr); WriteDouble(vertex.y, ptr); } diff --git a/spatial/src/spatial/geographiclib/functions/st_area_spheroid.cpp b/spatial/src/spatial/geographiclib/functions/st_area_spheroid.cpp index 71bd2556..01f02edc 100644 --- a/spatial/src/spatial/geographiclib/functions/st_area_spheroid.cpp +++ b/spatial/src/spatial/geographiclib/functions/st_area_spheroid.cpp @@ -85,7 +85,7 @@ static double PolygonArea(const core::Polygon &poly, GeographicLib::PolygonArea auto &ring = poly.Ring(ring_idx); // Note: the last point is the same as the first point, but geographiclib doesn't know that, for (uint32_t coord_idx = 0; coord_idx < ring.Count() - 1; coord_idx++) { - auto &coord = ring[coord_idx]; + auto coord = ring.Get(coord_idx); comp.AddPoint(coord.x, coord.y); } double ring_area; diff --git a/spatial/src/spatial/geographiclib/functions/st_length_spheroid.cpp b/spatial/src/spatial/geographiclib/functions/st_length_spheroid.cpp index 9b71ca18..9d09a32f 100644 --- a/spatial/src/spatial/geographiclib/functions/st_length_spheroid.cpp +++ b/spatial/src/spatial/geographiclib/functions/st_length_spheroid.cpp @@ -59,7 +59,8 @@ static void GeodesicLineString2DFunction(DataChunk &args, ExpressionState &state //------------------------------------------------------------------------------ static double LineLength(const core::LineString &line, GeographicLib::PolygonArea &comp) { comp.Clear(); - for (auto &vert : line.Vertices()) { + for (uint32_t i = 0; i < line.Vertices().Count(); i++) { + auto vert = line.Vertices().Get(i); comp.AddPoint(vert.x, vert.y); } double _area; diff --git a/spatial/src/spatial/geographiclib/functions/st_perimeter_spheroid.cpp b/spatial/src/spatial/geographiclib/functions/st_perimeter_spheroid.cpp index 613a9f35..71c62b18 100644 --- a/spatial/src/spatial/geographiclib/functions/st_perimeter_spheroid.cpp +++ b/spatial/src/spatial/geographiclib/functions/st_perimeter_spheroid.cpp @@ -77,7 +77,7 @@ static double PolygonPerimeter(const core::Polygon &poly, GeographicLib::Polygon // Note: the last point is the same as the first point, but geographiclib doesn't know that, // so skip it. for (uint32_t coord_idx = 0; coord_idx < ring.Count() - 1; coord_idx++) { - auto &coord = ring[coord_idx]; + auto coord = ring.Get(coord_idx); comp.AddPoint(coord.x, coord.y); } double _ring_area; diff --git a/spatial/src/spatial/proj/functions.cpp b/spatial/src/spatial/proj/functions.cpp index 5900cdcd..db4c2206 100644 --- a/spatial/src/spatial/proj/functions.cpp +++ b/spatial/src/spatial/proj/functions.cpp @@ -234,26 +234,29 @@ static void TransformGeometry(PJ *crs, core::Point &point) { if (point.IsEmpty()) { return; } - auto &vertex = point.GetVertex(); + auto vertex = point.GetVertex(); auto transformed = proj_trans(crs, PJ_FWD, proj_coord(vertex.x, vertex.y, 0, 0)).xy; - vertex.x = transformed.x; - vertex.y = transformed.y; + point.Vertices().Set(0, core::Vertex(transformed.x, transformed.y)); } static void TransformGeometry(PJ *crs, core::LineString &line) { - for (auto &vert : line.Vertices()) { + + for (uint32_t i = 0; i < line.Vertices().Count(); i++) { + auto vert = line.Vertices().Get(i); auto transformed = proj_trans(crs, PJ_FWD, proj_coord(vert.x, vert.y, 0, 0)).xy; - vert.x = transformed.x; - vert.y = transformed.y; + + core::Vertex new_vert(transformed.x, transformed.y); + line.Vertices().Set(i, new_vert); } } static void TransformGeometry(PJ *crs, core::Polygon &poly) { for (auto &ring : poly.Rings()) { - for (auto &vert : ring) { + for (uint32_t i = 0; i < ring.Count(); i++) { + auto vert = ring.Get(i); auto transformed = proj_trans(crs, PJ_FWD, proj_coord(vert.x, vert.y, 0, 0)).xy; - vert.x = transformed.x; - vert.y = transformed.y; + core::Vertex new_vert(transformed.x, transformed.y); + ring.Set(i, new_vert); } } }