Skip to content

Commit 3bb37f8

Browse files
authored
Merge pull request #532 from Maxxen/v1.2.0-dev
New functions and misc bug fixes
2 parents 2905968 + 007102d commit 3bb37f8

24 files changed

+2119
-15
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.2)
1+
cmake_minimum_required(VERSION 3.5)
22
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
33

44
# Set extension name here

deps/patches/proj.patch

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- a/cmake/Ccache.cmake
2+
+++ b/cmake/Ccache.cmake
3+
@@ -7,7 +7,7 @@
4+
# Add "include(Ccache)" to CMakeLists.txt and enable
5+
# using the option -D USE_CCACHE=ON
6+
7+
-cmake_minimum_required(VERSION 3.4)
8+
+cmake_minimum_required(VERSION 3.5)
9+
10+
11+
option(USE_CCACHE

deps/patches/proj_wasm.patch

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,14 @@
4747

4848
# If unsuitable, append the reason to the package version so that it's
4949
# visible to the user.
50+
--- a/cmake/Ccache.cmake
51+
+++ b/cmake/Ccache.cmake
52+
@@ -7,7 +7,7 @@
53+
# Add "include(Ccache)" to CMakeLists.txt and enable
54+
# using the option -D USE_CCACHE=ON
55+
56+
-cmake_minimum_required(VERSION 3.4)
57+
+cmake_minimum_required(VERSION 3.5)
58+
59+
60+
option(USE_CCACHE

src/sgl/sgl.hpp

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,109 @@ struct box_xyzm {
109109
}
110110
};
111111

112+
struct affine_matrix {
113+
114+
// *------------*
115+
// | a b c xoff |
116+
// | d e f yoff |
117+
// | g h i zoff |
118+
// | 0 0 0 1 |
119+
// *------------*
120+
double v[16] = {};
121+
122+
static affine_matrix identity() {
123+
affine_matrix result;
124+
result.v[0] = 1;
125+
result.v[5] = 1;
126+
result.v[10] = 1;
127+
return result;
128+
}
129+
130+
static affine_matrix translate(double x, double y, double z = 0) {
131+
affine_matrix result = identity();
132+
result.v[3] = x;
133+
result.v[7] = y;
134+
result.v[11] = z;
135+
return result;
136+
}
137+
138+
static affine_matrix scale(double x, double y, double z = 1) {
139+
affine_matrix result = identity();
140+
result.v[0] = x;
141+
result.v[5] = y;
142+
result.v[10] = z;
143+
return result;
144+
}
145+
146+
static affine_matrix rotate_x(double angle) {
147+
affine_matrix result = identity();
148+
const auto c = std::cos(angle);
149+
const auto s = std::sin(angle);
150+
result.v[5] = c;
151+
result.v[6] = -s;
152+
result.v[9] = s;
153+
result.v[10] = c;
154+
return result;
155+
}
156+
157+
static affine_matrix rotate_y(double angle) {
158+
affine_matrix result = identity();
159+
const auto c = std::cos(angle);
160+
const auto s = std::sin(angle);
161+
result.v[0] = c;
162+
result.v[2] = s;
163+
result.v[8] = -s;
164+
result.v[10] = c;
165+
return result;
166+
}
167+
168+
static affine_matrix rotate_z(double angle) {
169+
affine_matrix result = identity();
170+
const auto c = std::cos(angle);
171+
const auto s = std::sin(angle);
172+
result.v[0] = c;
173+
result.v[1] = -s;
174+
result.v[4] = s;
175+
result.v[5] = c;
176+
return result;
177+
}
178+
179+
static affine_matrix translate_scale(double x, double y, double z, double sx, double sy, double sz) {
180+
affine_matrix result = identity();
181+
result.v[0] = sx;
182+
result.v[5] = sy;
183+
result.v[10] = sz;
184+
result.v[3] = x;
185+
result.v[7] = y;
186+
result.v[11] = z;
187+
return result;
188+
}
189+
190+
vertex_xy apply_xy(const vertex_xy &vertex) const {
191+
192+
// x = a * x + b * y + xoff;
193+
// y = d * x + e * y + yoff;
194+
195+
vertex_xy result = {0, 0};
196+
result.x = v[0] * vertex.x + v[1] * vertex.y + v[3];
197+
result.y = v[4] * vertex.x + v[5] * vertex.y + v[7];
198+
return result;
199+
}
200+
201+
vertex_xyzm apply_xyz(const vertex_xyzm &vertex) const {
202+
203+
// x = a * x + b * y + c * z + xoff;
204+
// y = d * x + e * y + f * z + yoff;
205+
// z = g * x + h * y + i * z + zoff;
206+
207+
vertex_xyzm result = {0, 0, 0, 0};
208+
result.x = v[0] * vertex.x + v[1] * vertex.y + v[2] * vertex.zm + v[3];
209+
result.y = v[4] * vertex.x + v[5] * vertex.y + v[6] * vertex.zm + v[7];
210+
result.zm = v[8] * vertex.x + v[9] * vertex.y + v[10] * vertex.zm + v[11];
211+
return result;
212+
}
213+
};
214+
112215
enum class geometry_type : uint8_t {
113216
INVALID = 0,
114217
POINT,
@@ -812,6 +915,9 @@ inline double perimeter(const geometry *geom);
812915

813916
namespace ops {
814917

918+
// If the allocator is null, transform in-place. Otherwise allocate new vertex data
919+
void affine_transform(sgl::allocator *alloc, sgl::geometry *geom, const sgl::affine_matrix *matrix);
920+
815921
double area(const geometry *geom);
816922
double perimeter(const geometry *geom);
817923
double length(const geometry *geom);
@@ -820,6 +926,7 @@ int32_t max_surface_dimension(const geometry *geom, bool ignore_empty);
820926

821927
double distance(const geometry* lhs, const geometry* rhs);
822928

929+
// This will NOT visit polygon rings if the requested dimension is 1
823930
typedef void (*visit_func)(void *state, const geometry *part);
824931
void visit_by_dimension(const geometry *geom, int surface_dimension, void *state, visit_func func);
825932

@@ -903,6 +1010,75 @@ bool is_valid(const sgl::geometry *geom);
9031010

9041011
namespace sgl {
9051012
namespace ops {
1013+
1014+
inline void affine_transform(sgl::allocator *alloc, sgl::geometry *geom, const sgl::affine_matrix *matrix) {
1015+
if (!geom) {
1016+
return;
1017+
}
1018+
1019+
geometry *part = geom;
1020+
geometry *root = part->get_parent();
1021+
1022+
while (true) {
1023+
switch (part->get_type()) {
1024+
case geometry_type::POINT:
1025+
case geometry_type::LINESTRING: {
1026+
const auto vertex_width = part->get_vertex_size();
1027+
const auto vertex_count = part->get_count();
1028+
1029+
if(vertex_count == 0) {
1030+
break;
1031+
}
1032+
1033+
const auto old_vertex_data = part->get_vertex_data();
1034+
auto new_vertex_data = old_vertex_data;
1035+
if(alloc) {
1036+
new_vertex_data = static_cast<uint8_t*>(alloc->alloc(vertex_width * vertex_count));
1037+
}
1038+
1039+
// Now, apply the transformation
1040+
vertex_xyzm old_vertex = {0, 0, 0, 0};
1041+
for (uint32_t i = 0; i < vertex_count; i++) {
1042+
memcpy(&old_vertex, old_vertex_data + i * vertex_width, vertex_width);
1043+
auto new_vertex = matrix->apply_xyz(old_vertex);
1044+
memcpy(new_vertex_data + i * vertex_width, &new_vertex, vertex_width);
1045+
}
1046+
1047+
part->set_vertex_data(new_vertex_data, vertex_count);
1048+
}
1049+
break;
1050+
case geometry_type::POLYGON:
1051+
case geometry_type::MULTI_POINT:
1052+
case geometry_type::MULTI_LINESTRING:
1053+
case geometry_type::MULTI_POLYGON:
1054+
case geometry_type::MULTI_GEOMETRY:
1055+
if (!part->is_empty()) {
1056+
part = part->get_first_part();
1057+
continue;
1058+
}
1059+
break;
1060+
default:
1061+
SGL_ASSERT(false);
1062+
return;
1063+
}
1064+
1065+
while (true) {
1066+
const auto parent = part->get_parent();
1067+
if (parent == root) {
1068+
return;
1069+
}
1070+
1071+
if (part != parent->get_last_part()) {
1072+
part = part->get_next();
1073+
break;
1074+
}
1075+
1076+
part = parent;
1077+
}
1078+
}
1079+
}
1080+
1081+
9061082
inline double area(const geometry *geom) {
9071083
switch (geom->get_type()) {
9081084
case geometry_type::POLYGON: {
@@ -1061,21 +1237,45 @@ inline void visit_by_dimension(const geometry *geom, int surface_dimension, void
10611237
while (true) {
10621238
switch (part->get_type()) {
10631239
case geometry_type::POINT:
1240+
if(surface_dimension == 0) {
1241+
func(state, part);
1242+
}
1243+
break;
10641244
case geometry_type::MULTI_POINT:
10651245
if(surface_dimension == 0) {
10661246
func(state, part);
1247+
if (!part->is_empty()) {
1248+
part = part->get_first_part();
1249+
continue;
1250+
}
10671251
}
10681252
break;
10691253
case geometry_type::LINESTRING:
1254+
if(surface_dimension == 1) {
1255+
func(state, part);
1256+
}
1257+
break;
10701258
case geometry_type::MULTI_LINESTRING:
10711259
if(surface_dimension == 1) {
10721260
func(state, part);
1261+
if (!part->is_empty()) {
1262+
part = part->get_first_part();
1263+
continue;
1264+
}
10731265
}
10741266
break;
10751267
case geometry_type::POLYGON:
1268+
if(surface_dimension == 2) {
1269+
func(state, part);
1270+
}
1271+
break;
10761272
case geometry_type::MULTI_POLYGON:
10771273
if(surface_dimension == 2) {
10781274
func(state, part);
1275+
if (!part->is_empty()) {
1276+
part = part->get_first_part();
1277+
continue;
1278+
}
10791279
}
10801280
break;
10811281
case geometry_type::MULTI_GEOMETRY:

src/spatial/modules/gdal/gdal_module.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "spatial/geometry/sgl.hpp"
66
#include "spatial/geometry/wkb_writer.hpp"
77
#include "spatial/geometry/geometry_serialization.hpp"
8+
#include "spatial/util/function_builder.hpp"
89

910
// DuckDB
1011
#include "duckdb/main/database.hpp"
@@ -26,8 +27,6 @@
2627
#include "cpl_vsi_virtual.h"
2728
#include "ogrsf_frmts.h"
2829

29-
#include <spatial/util/function_builder.hpp>
30-
3130
namespace duckdb {
3231

3332
namespace {

0 commit comments

Comments
 (0)