/** * Copyright (c) 2023 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #include #include #include #include #include #define private public #include "lib/geo/ob_geo_bin.h" #include "lib/geo/ob_geo_tree.h" #include "lib/geo/ob_geo_tree_traits.h" #include "lib/geo/ob_geo_bin_traits.h" #include "lib/geo/ob_geo_func_register.h" #include "lib/geo/ob_geo_func_difference.h" #include "lib/json_type/ob_json_common.h" #include "lib/random/ob_random.h" #undef private #include #include #include #include namespace bg = boost::geometry; using namespace oceanbase::common; namespace oceanbase { namespace common { class TestGeoFuncDifference : public ::testing::Test { public: TestGeoFuncDifference() {} ~TestGeoFuncDifference() {} virtual void SetUp() {} virtual void TearDown() {} static void SetUpTestCase() {} static void TearDownTestCase() {} private: // disallow copy DISALLOW_COPY_AND_ASSIGN(TestGeoFuncDifference); }; int append_bo(ObJsonBuffer& data, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) { uint8_t sbo = static_cast(bo); return data.append(reinterpret_cast(&sbo), sizeof(uint8_t)); } int append_type(ObJsonBuffer& data, ObGeoType type, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) { INIT_SUCC(ret); uint32_t stype = static_cast(type); if (OB_FAIL(data.reserve(sizeof(uint32_t)))) { } else { char *ptr = data.ptr() + data.length(); ObGeoWkbByteOrderUtil::write(ptr, stype, bo); ret = data.set_length(data.length() + sizeof(uint32_t)); } return ret; } int append_uint32(ObJsonBuffer& data, uint32_t val, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) { INIT_SUCC(ret); if (OB_FAIL(data.reserve(sizeof(uint32_t)))) { } else { char *ptr = data.ptr() + data.length(); ObGeoWkbByteOrderUtil::write(ptr, val, bo); ret = data.set_length(data.length() + sizeof(uint32_t)); } return ret; } int append_double(ObJsonBuffer& data, double val, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian) { INIT_SUCC(ret); if (OB_FAIL(data.reserve(sizeof(double)))) { } else { char *ptr = data.ptr() + data.length(); ObGeoWkbByteOrderUtil::write(ptr, val, bo); ret = data.set_length(data.length() + sizeof(double)); } return ret; } void create_point(ObJsonBuffer &data, double x, double y) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::POINT)); ASSERT_EQ(OB_SUCCESS, append_double(data, x)); ASSERT_EQ(OB_SUCCESS, append_double(data, y)); } void create_line(ObJsonBuffer &data, std::vector< std::pair > &value) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::LINESTRING)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, value.size())); for (auto & p : value) { ASSERT_EQ(OB_SUCCESS, append_double(data, p.first)); ASSERT_EQ(OB_SUCCESS, append_double(data, p.second)); } } void create_polygon(ObJsonBuffer &data, int lnum, int pnum, std::vector< std::pair > &value) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::POLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, lnum)); int i = 0; for (int l = 0; l < lnum; l++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data, pnum)); for (int p = 0; p < pnum; p++) { ASSERT_EQ(OB_SUCCESS, append_double(data, value[i].first)); ASSERT_EQ(OB_SUCCESS, append_double(data, value[i].second)); i++; } } } void create_multipoint(ObJsonBuffer &data, std::vector< std::pair > &value) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::MULTIPOINT)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, value.size())); for (auto & p : value) { create_point(data, p.first, p.second); } } void create_multiline(ObJsonBuffer &data, int lnum, int pnum, std::vector< std::pair > &value) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::MULTILINESTRING)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, lnum)); int i = 0; for (int l = 0; l < lnum; l++) { ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::LINESTRING)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, pnum)); for (int p = 0; p < pnum; p++) { ASSERT_EQ(OB_SUCCESS, append_double(data, value[i].first)); ASSERT_EQ(OB_SUCCESS, append_double(data, value[i].second)); i++; } } } TEST_F(TestGeoFuncDifference, point_point) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); create_point(data1, 3.2, 5.5); ObIWkbGeomPoint q; q.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_line) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.4, 2.3)); val.push_back(std::make_pair(3.5, 5.5)); create_line(data1, val); ObIWkbGeomLineString line; line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_polygon) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_polygon(data1, 1, 5, val); ObIWkbGeomPolygon poly; poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_multipoint) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_point); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_multiline) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(0.0, 0.0)); create_multiline(data1, 2, 3, val); ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_multipolygon) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); int polynum = 2; ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polynum)); for (int i = 0; i < polynum; i++) { std::vector< std::pair > val; val.push_back(std::make_pair(5.0 + i, 0.0 + i)); val.push_back(std::make_pair(15.0 + i, 0.0 + i)); val.push_back(std::make_pair(15.0 + i, 10.0 + i)); val.push_back(std::make_pair(5.0 + i, 10.0 + i)); val.push_back(std::make_pair(5.0 + i, 0.0 + i)); create_polygon(data1, 1, 5, val); } ObIWkbGeomMultiPolygon multi_polygon; multi_polygon.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_polygon); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, line_point) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.4, 2.3)); val.push_back(std::make_pair(3.5, 5.5)); create_line(data, val); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); create_point(data1, 3.2, 5.5); ObIWkbGeomPoint q; q.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &q); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::LINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianLineString *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 2); uint i = 0; for (auto &point : *res) { ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, line_line) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0)); val.push_back(std::make_pair(1.0, 1.0)); create_line(data, val); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0, 0.0)); val1.push_back(std::make_pair(0.5, 0.5)); create_line(data1, val1); ObIWkbGeomLineString line1; line1.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultilinestring *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 0.5); ASSERT_EQ(line[0].get<1>(), 0.5); ASSERT_EQ(line[1].get<0>(), 1.0); ASSERT_EQ(line[1].get<1>(), 1.0); } /* typedef boost::geometry::model::linestring > line_bg; line_bg green, blue; boost::geometry::read_wkt( "LINESTRING(0 0, 1.0 1.0)", green); boost::geometry::read_wkt( "LINESTRING(0.0 0.0, 0.5 0.5)", blue); std::list output; boost::geometry::difference(green, blue, output); int i = 0; std::cout << "green - blue:" << std::endl; BOOST_FOREACH(line_bg const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; } }*/ } TEST_F(TestGeoFuncDifference, line_polygon) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0)); val.push_back(std::make_pair(1.0, 1.0)); create_line(data, val); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::POLYGON)); uint32_t ring_num = 1; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, ring_num)); for (uint32_t i = 0; i < ring_num; i++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data1, 5)); /*ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); */ ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); } ObIWkbGeomPolygon poly; poly.set_data(data1.string()); ObWkbGeomPolygon *geo_condidate = reinterpret_cast(const_cast(poly.val())); ObWkbGeomLineString *line_condidate = reinterpret_cast(const_cast(line.val())); //boost::geometry::correct(*geo_condidate); //boost::geometry::correct(*line_condidate); std::cout << boost::geometry::dsv(*geo_condidate) << std::endl; std::cout << boost::geometry::area(*geo_condidate) << std::endl; /* ASSERT_EQ(res_bg.size(), 1); for (auto & line : res_bg) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 0.5); ASSERT_EQ(line[0].get<1>(), 0.5); ASSERT_EQ(line[1].get<0>(), 1.0); ASSERT_EQ(line[1].get<1>(), 1.0); } */ ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultilinestring *res = reinterpret_cast(result); ASSERT_EQ(res->size(), 1); for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 0.5); ASSERT_EQ(line[0].get<1>(), 0.5); ASSERT_EQ(line[1].get<0>(), 1.0); ASSERT_EQ(line[1].get<1>(), 1.0); } /* typedef boost::geometry::model::linestring > line_bg; typedef boost::geometry::model::polygon > polygon_bg; line_bg green; polygon_bg blue; boost::geometry::read_wkt( "LINESTRING(0 0, 1.0 1.0)", green); boost::geometry::read_wkt( "POLYGON((0.0 0.0, 0.5 0.5, 15.0 10.0, 5.0 10.0, 0.0 0.0))", blue); //boost::geometry::correct(blue); std::list output; boost::geometry::difference(green, blue, output); std::cout << boost::geometry::dsv(blue) << std::endl; std::cout << boost::geometry::area(blue) << std::endl; int i = 0; std::cout << "green - blue:" << std::endl; BOOST_FOREACH(line_bg const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; } } ObCartesianMultilinestring *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 0.5); ASSERT_EQ(line[0].get<1>(), 0.5); ASSERT_EQ(line[1].get<0>(), 1.0); ASSERT_EQ(line[1].get<1>(), 1.0); } ObCartesianMultipoint multi_p(0, &allocator); ObCartesianMultilinestring multi_l(0, &allocator); ObCartesianMultipolygon output_ob(0, &allocator); boost::geometry::difference(multi_p, multi_l, output_ob);*/ } TEST_F(TestGeoFuncDifference, line_multiline) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0)); val.push_back(std::make_pair(2.0, 2.0)); create_line(data, val); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTILINESTRING)); uint32_t line_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, line_num)); for (uint32_t i = 0; i < line_num; i++) { std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0 + i, 0.0 + i)); val1.push_back(std::make_pair(0.5 + i, 0.5 + i)); create_line(data1, val1); } ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultilinestring *res = reinterpret_cast(result); EXPECT_EQ(res->size(), 2); int i = 0; for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 0.5 + i); ASSERT_EQ(line[0].get<1>(), 0.5 + i); ASSERT_EQ(line[1].get<0>(), 1.0 + i); ASSERT_EQ(line[1].get<1>(), 1.0 + i); i++; std::cout << "(" << line[0].get<0>() << ", " << line[0].get<1>() << ")"; std::cout << "(" << line[1].get<0>() << ", " << line[1].get<1>() << ")" << std::endl; } /* typedef boost::geometry::model::linestring > linestring_t; typedef boost::geometry::model::multi_linestring mlinestring_t; linestring_t ls; boost::geometry::read_wkt( "LINESTRING(0 0, 2.0 2.0)", ls); mlinestring_t mls{{{0.0, 0.0}, {0.5, 0.5}}, {{1.0, 1.0}, {1.5, 1.5}}}; std::list output; boost::geometry::difference(ls, mls, output); ASSERT_EQ(output.size(), 2); int i = 0; BOOST_FOREACH(linestring_t const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; } } */ } TEST_F(TestGeoFuncDifference, line_multipolygon) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.0, 0.0)); val.push_back(std::make_pair(1.0, 4.0)); create_line(data, val); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); uint32_t polygon_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polygon_num)); for (uint32_t i = 0; i < polygon_num; i++) { std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0 + 2 * i)); val.push_back(std::make_pair(2.0, 0.0 + 2 * i)); val.push_back(std::make_pair(2.0, 1.0 + 2 * i)); val.push_back(std::make_pair(0.0, 1.0 + 2 * i)); val.push_back(std::make_pair(0.0, 0.0 + 2 * i)); create_polygon(data1, 1, 5, val); } ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultilinestring *res = reinterpret_cast(result); EXPECT_EQ(res->size(), 2); int i = 0; for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), 1.0); ASSERT_EQ(line[0].get<1>(), 1.0 + 2 * i); ASSERT_EQ(line[1].get<0>(), 1.0); ASSERT_EQ(line[1].get<1>(), 2.0 + 2 * i); i++; std::cout << "(" << line[0].get<0>() << ", " << line[0].get<1>() << ")"; std::cout << "(" << line[1].get<0>() << ", " << line[1].get<1>() << ")" << std::endl; } } TEST_F(TestGeoFuncDifference, polygon_polygon) { typedef boost::geometry::model::polygon, false> polygon; polygon green, blue; boost::geometry::read_wkt( "POLYGON((0.0 0.0, 10.0 0.0, 10.0 10.0, 0.0 10.0, 0.0 0.0))", green); boost::geometry::read_wkt( "POLYGON((5.0 0.0, 15.0 0.0, 15.0 10.0, 5.0 10.0, 5.0 0.0))", blue); std::deque output; boost::geometry::difference(green, blue, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(polygon const& l, output) { auto & outer = l.outer(); std::cout << "outer : "; for (auto & p : outer) { std::cout << "(" << p.x() << ", "<< p.y() << ")"; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; for (auto & inner : l.inners()) { std::cout << "inner : " << i++; for (auto & p : inner) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; } } ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); uint32_t lnum = 1; uint32_t pnum = 5; ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::POLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, lnum)); for (int j = 0; j < lnum; j++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data, pnum)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); } ObIWkbGeomPolygon poly1; poly1.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::POLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data1, lnum)); for (int j = 0; j < lnum; j++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data1, pnum)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); } ObIWkbGeomPolygon poly2; poly2.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly1); gis_context.ut_set_geo_arg(1, &poly2); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOLYGON); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipolygon *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), output.size()); for (auto &polygon : *res) { auto & outer = polygon.exterior_ring(); for (auto & p : outer) { std::cout << "(" << p.get<0>() << ", " << p.get<1>() << ")" << std::endl; ASSERT_EQ(p.get<0>(), res_val[i].first); ASSERT_EQ(p.get<1>(), res_val[i].second); i++; } } for (auto &polygon : *res) { ASSERT_EQ(50, boost::geometry::area(polygon)); } } TEST_F(TestGeoFuncDifference, polygon_multipolygon) { typedef bg::model::d2::point_xy point_t; typedef bg::model::polygon polygon_t; typedef bg::model::multi_polygon mpolygon_t; polygon_t pol; boost::geometry::read_wkt( "POLYGON((0.0 0.0, 0.0 4.0, 1.0 4.0, 1.0 0.0, 0.0 0.0))", pol); /* boost::geometry::read_wkt( "POLYGON((1.21681 -1.07095, 5.0 10.0, 1.85841 -1.15838, 1.21681 -1.07095))", pol); */ mpolygon_t mpoly1; boost::geometry::read_wkt( "MULTIPOLYGON(((0.0 0.0, 0.0 1.0, 2.0 1.0, 2.0 0.0, 0.0 0.0)), ((0.0 2.0, 0.0 3.0, 2.0 3.0, 2.0 2.0, 0.0 2.0)))", mpoly1); ASSERT_EQ(mpoly1.size(), 2); std::cout << "bg::mpoly1" << boost::geometry::dsv(mpoly1) << std::endl; std::list output; boost::geometry::difference(pol, mpoly1, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(polygon_t const& l, output) { auto & outer = l.outer(); std::cout << "outer : "; for (auto & p : outer) { std::cout << "(" << p.x() << ", "<< p.y() << ")"; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; for (auto & inner : l.inners()) { std::cout << "inner : " << i++; for (auto & p : inner) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; } } ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > pol_val; pol_val.push_back(std::make_pair(0.0, 0.0)); pol_val.push_back(std::make_pair(1.0, 0.0)); pol_val.push_back(std::make_pair(1.0, 4.0)); pol_val.push_back(std::make_pair(0.0, 4.0)); pol_val.push_back(std::make_pair(0.0, 0.0)); create_polygon(data, 1, 5, pol_val); ObIWkbGeomPolygon poly; poly.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); uint32_t polygon_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polygon_num)); for (uint32_t i = 0; i < polygon_num; i++) { std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0 + 2 * i)); val.push_back(std::make_pair(2.0, 0.0 + 2 * i)); val.push_back(std::make_pair(2.0, 1.0 + 2 * i)); val.push_back(std::make_pair(0.0, 1.0 + 2 * i)); val.push_back(std::make_pair(0.0, 0.0 + 2 * i)); create_polygon(data1, 1, 5, val); } ObIWkbGeomMultiPolygon multi_poly; multi_poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOLYGON); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipolygon *res = reinterpret_cast(result); EXPECT_EQ(res->size(), 2); i = 0; for (auto & pol : *res) { auto & ring = pol.exterior_ring(); ASSERT_EQ(ring.size(), 5); ASSERT_EQ(ring[0].get<0>(), 0.0); ASSERT_EQ(ring[0].get<1>(), 1.0 + 2 * i); ASSERT_EQ(ring[1].get<0>(), 1.0); ASSERT_EQ(ring[1].get<1>(), 1.0 + 2 * i); ASSERT_EQ(ring[2].get<0>(), 1.0); ASSERT_EQ(ring[2].get<1>(), 2.0 + 2 * i); ASSERT_EQ(ring[3].get<0>(), 0.0); ASSERT_EQ(ring[3].get<1>(), 2.0 + 2 * i); ASSERT_EQ(ring[4].get<0>(), 0.0); ASSERT_EQ(ring[4].get<1>(), 1.0 + 2 * i); i++; } } TEST_F(TestGeoFuncDifference, multipoint_point) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); create_point(data, 15.0, 10.0); ObIWkbGeomPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &p); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 4); int i = 0; for (auto &point : *res) { if (i == 2) i++; ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, multipoint_linestring) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val1; val1.push_back(std::make_pair(6.0, 10.0)); val1.push_back(std::make_pair(20.0, 10.0)); create_line(data, val1); ObIWkbGeomLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 4); int i = 0; for (auto &point : *res) { if (i == 2) i++; ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, multipoint_polygon) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0, 0.0)); val1.push_back(std::make_pair(5.0, 0.0)); val1.push_back(std::make_pair(5.0, 10.0)); val1.push_back(std::make_pair(0.0, 10.0)); val1.push_back(std::make_pair(0.0, 0.0)); create_polygon(data, 1, 5, val1); ObIWkbGeomPolygon pol; pol.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &pol); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 2); int i = 0; for (auto &point : *res) { while (i == 0 || i == 3 || i == 4) i++; ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, multipoint_multipoint) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0, 0.0)); val1.push_back(std::make_pair(5.0, 0.0)); val1.push_back(std::make_pair(5.0, 10.0)); val1.push_back(std::make_pair(0.0, 10.0)); val1.push_back(std::make_pair(0.0, 0.0)); create_multipoint(data, val1); ObIWkbGeomMultiPoint multi_point1; multi_point1.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_point1); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 2); int i = 0; for (auto &point : *res) { while (i == 0 || i == 3 || i == 4) i++; ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, multipoint_multilinestring) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::MULTILINESTRING)); uint32_t line_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data, line_num)); for (uint32_t i = 0; i < line_num; i++) { std::vector< std::pair > val1; val1.push_back(std::make_pair(5.0 + i, 0.0 + i)); val1.push_back(std::make_pair(5.5 + i, 0.5 + i)); create_line(data, val1); } ObIWkbGeomMultiLineString multi_line; multi_line.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_multipoint(data1, val); ObIWkbGeomMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &multi_point); gis_context.ut_set_geo_arg(1, &multi_line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Cartesian); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 3); int i = 0; for (auto &point : *res) { while (i == 0 || i == 4) i++; ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } template void apply_bg_diff_line_test(GeometryType1 &geo1, GeometryType2 &geo2, const ObSrsItem *srs, GeometryRes &res) { boost::geometry::srs::spheroid geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis()); ObLlLaAaStrategy line_strategy(geog_sphere); boost::geometry::difference(geo1, geo2, res, line_strategy); } template void apply_bg_diff_point_test(GeometryType1 &geo1, GeometryType2 &geo2, const ObSrsItem *srs, GeometryRes &res) { boost::geometry::srs::spheroid geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis()); ObPlPaStrategy point_strategy(geog_sphere); boost::geometry::difference(geo1, geo2, res, point_strategy); } int mock_get_tenant_srs_item(ObIAllocator &allocator, uint64_t srs_id, const ObSrsItem *&srs_item) { int ret = OB_SUCCESS; ObGeographicRs rs; rs.rs_name.assign_ptr("ED50", strlen("ED50")); rs.datum_info.name.assign_ptr("European Datum 1950", strlen("European Datum 1950")); rs.datum_info.spheroid.name.assign_ptr("International 1924", strlen("International 1924")); rs.datum_info.spheroid.inverse_flattening = 297; rs.datum_info.spheroid.semi_major_axis = 6378388; rs.primem.longtitude = 0; rs.unit.conversion_factor = 0.017453292519943278; rs.axis.x.direction = ObAxisDirection::NORTH; rs.axis.y.direction = ObAxisDirection::EAST; rs.datum_info.towgs84.value[0] = -157.89; rs.datum_info.towgs84.value[1] = -17.16; rs.datum_info.towgs84.value[2] = -78.41; rs.datum_info.towgs84.value[3] = 2.118; rs.datum_info.towgs84.value[4] = 2.697; rs.datum_info.towgs84.value[5] = -1.434; rs.datum_info.towgs84.value[6] = -5.38; rs.authority.is_valid = false; ObSpatialReferenceSystemBase *srs_info; if (OB_FAIL(ObSpatialReferenceSystemBase::create_geographic_srs(&allocator, srs_id, &rs, srs_info))) { printf("faild to create geographical srs, ret=%d", ret); } ObSrsItem *tmp_srs_item = NULL; if (OB_ISNULL(tmp_srs_item = OB_NEWx(ObSrsItem, (&allocator), srs_info))) { ret = OB_ALLOCATE_MEMORY_FAILED; printf("fail to alloc memory for srs item, ret=%d", ret); } else { srs_item = tmp_srs_item; } return ret; } TEST_F(TestGeoFuncDifference, point_point_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); create_point(data1, 3.2, 5.5); ObIWkbGeogPoint q; q.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &q); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObCartesianMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_line_geog) { ObArenaAllocator allocator(ObModIds::TEST); ObJsonBuffer data(&allocator); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.2, 3.5)); val.push_back(std::make_pair(3.5, 5.5)); create_line(data1, val); ObIWkbGeogLineString line; line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), true); ASSERT_EQ(res->size(), 0); } TEST_F(TestGeoFuncDifference, point_polygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_polygon(data1, 1, 5, val); ObIWkbGeogPolygon poly; poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_multipoint_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(1.2, 3.5)); create_multipoint(data1, val); ObIWkbGeogMultiPoint multi_point; multi_point.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_point); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), true); ASSERT_EQ(res->size(), 0); } TEST_F(TestGeoFuncDifference, point_multiline_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(0.0, 0.0)); create_multiline(data1, 2, 3, val); ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, point_multipolygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); create_point(data, 1.2, 3.5); ObIWkbGeogPoint p; p.set_data(data.string()); ObJsonBuffer data1(&allocator); int polynum = 2; ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polynum)); for (int i = 0; i < polynum; i++) { std::vector< std::pair > val; val.push_back(std::make_pair(5.0 + i, 0.0 + i)); val.push_back(std::make_pair(15.0 + i, 0.0 + i)); val.push_back(std::make_pair(15.0 + i, 10.0 + i)); val.push_back(std::make_pair(5.0 + i, 10.0 + i)); val.push_back(std::make_pair(5.0 + i, 0.0 + i)); create_polygon(data1, 1, 5, val); } ObIWkbGeogMultiPolygon multi_polygon; multi_polygon.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &p); gis_context.ut_set_geo_arg(1, &multi_polygon); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOINT); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipoint *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); for (auto &point : *res) { ASSERT_EQ(1.2, point.get<0>()); ASSERT_EQ(3.5, point.get<1>()); } } TEST_F(TestGeoFuncDifference, line_point_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.4, 2.3)); val.push_back(std::make_pair(3.5, 5.5)); create_line(data, val); ObIWkbGeogLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); create_point(data1, 3.2, 5.5); ObIWkbGeogPoint q; q.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &q); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::LINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographLineString *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 2); uint i = 0; for (auto &point : *res) { ASSERT_EQ(val[i].first, point.get<0>()); ASSERT_EQ(val[i].second, point.get<1>()); i++; } } TEST_F(TestGeoFuncDifference, line_line_geog) { typedef boost::geometry::model::linestring> > line_bg; line_bg green, blue; boost::geometry::read_wkt( "LINESTRING(0 0, 1.0 1.0)", green); boost::geometry::read_wkt( "LINESTRING(0.0 0.0, 0.5 0.5)", blue); std::list output; boost::geometry::difference(green, blue, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(line_bg const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } } ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0)); val.push_back(std::make_pair(1.0, 1.0)); create_line(data, val); ObIWkbGeogLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0, 0.0)); val1.push_back(std::make_pair(0.5, 0.5)); create_line(data1, val1); ObIWkbGeogLineString line1; line1.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &line1); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultilinestring *res = reinterpret_cast(result); ASSERT_EQ(res->empty(), false); ASSERT_EQ(res->size(), 1); i = 0; for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), res_val[i].first); ASSERT_EQ(line[0].get<1>(), res_val[i].second); ASSERT_EQ(line[1].get<0>(), res_val[i + 1].first); ASSERT_EQ(line[1].get<1>(), res_val[i + 1].second); std::cout << "(" << line[0].get<0>() << ", " << line[0].get<1>() << ")"; std::cout << "(" << line[1].get<0>() << ", " << line[1].get<1>() << ")" << std::endl; i += 2; } } typedef bg::model::d2::point_xy > point_geog_t; typedef bg::model::multi_point mpoint_geog_t; typedef bg::model::linestring line_geog_t; typedef bg::model::multi_linestring mline_geog_t; typedef bg::model::polygon polygon_geog_t; typedef bg::model::multi_polygon mpolygon_geog_t; template bool is_geo_equal(GEO1 &geo1, GEO2 &geo2) { std::stringstream left; std::stringstream right; left << bg::dsv(geo1); right << bg::dsv(geo2); if (left.str() == right.str()) { return true; } std::cout << left.str() << std::endl; std::cout << right.str() << std::endl; return false; } TEST_F(TestGeoFuncDifference, line_polygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); line_geog_t green; polygon_geog_t blue; boost::geometry::read_wkt( "LINESTRING(1.0 1.0, 4.0 4.0)", green); boost::geometry::read_wkt( "POLYGON((0.5 0.5, 1.5 1.5, 2.0 2.5, 1.5 0.5, 0.5 0.5))", blue); mline_geog_t output; apply_bg_diff_line_test(green, blue, srs, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(line_geog_t const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } } ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.0, 1.0)); val.push_back(std::make_pair(4.0, 4.0)); create_line(data, val); ObIWkbGeogLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::POLYGON)); uint32_t ring_num = 1; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, ring_num)); for (uint32_t i = 0; i < ring_num; i++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data1, 5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 1.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 1.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 2.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 2.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 1.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.5)); } ObIWkbGeogPolygon poly; poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultilinestring *res = reinterpret_cast(result); ASSERT_EQ(res->size(), 1); ASSERT_EQ(true, is_geo_equal(output, *res)); } TEST_F(TestGeoFuncDifference, line_multiline_geog) { typedef bg::model::linestring> > linestring_t; typedef bg::model::multi_linestring mlinestring_t; linestring_t ls; boost::geometry::read_wkt( "LINESTRING(0 0, 2.0 2.0)", ls); mlinestring_t mls{{{0.0, 0.0}, {0.5, 0.5}}, {{1.0, 1.0}, {1.5, 1.5}}}; std::list output; boost::geometry::difference(ls, mls, output); ASSERT_EQ(output.size(), 1); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(linestring_t const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } } ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(0.0, 0.0)); val.push_back(std::make_pair(2.0, 2.0)); create_line(data, val); ObIWkbGeogLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTILINESTRING)); uint32_t line_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, line_num)); for (uint32_t i = 0; i < line_num; i++) { std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0 + i, 0.0 + i)); val1.push_back(std::make_pair(0.5 + i, 0.5 + i)); create_line(data1, val1); } ObIWkbGeogMultiLineString multi_line; multi_line.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_line); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultilinestring *res = reinterpret_cast(result); EXPECT_EQ(res->size(), output.size()); i = 0; for (auto & line : *res) { ASSERT_EQ(line.size(), 2); ASSERT_EQ(line[0].get<0>(), res_val[i].first); ASSERT_EQ(line[0].get<1>(), res_val[i].second); ASSERT_EQ(line[1].get<0>(), res_val[i + 1].first); ASSERT_EQ(line[1].get<1>(), res_val[i + 1].second); i += 2; std::cout << "(" << line[0].get<0>() << ", " << line[0].get<1>() << ")"; std::cout << "(" << line[1].get<0>() << ", " << line[1].get<1>() << ")" << std::endl; } } TEST_F(TestGeoFuncDifference, line_multipolygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); line_geog_t ls; boost::geometry::read_wkt( "LINESTRING(1.0 1.0, 4.0 4.0)", ls); mpolygon_geog_t mpols{{{{0.5, 0.5}, {1.5, 1.5}, {2.0, 2.5}, {1.5, 0.5}, {0.5, 0.5}}}, {{{0.5, 1.5}, {1.5, 2.5}, {2.0, 3.5}, {1.5, 1.5}, {0.5, 1.5}}}}; mline_geog_t output; apply_bg_diff_line_test(ls, mpols, srs, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(line_geog_t const& l, output) { std::cout << i++ << ": " << l.size() << std::endl; for (auto & p : l) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } } ObJsonBuffer data(&allocator); std::vector< std::pair > val; val.push_back(std::make_pair(1.0, 1.0)); val.push_back(std::make_pair(4.0, 4.0)); create_line(data, val); ObIWkbGeogLineString line; line.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); uint32_t polygon_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polygon_num)); for (uint32_t i = 0; i < polygon_num; i++) { std::vector< std::pair > val; val.push_back(std::make_pair(0.5, 0.5 + i)); val.push_back(std::make_pair(1.5, 1.5 + i)); val.push_back(std::make_pair(2.0, 2.5 + i)); val.push_back(std::make_pair(1.5, 0.5 + i)); val.push_back(std::make_pair(0.5, 0.5 + i)); create_polygon(data1, 1, 5, val); } ObIWkbGeogMultiPolygon multi_poly; multi_poly.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &line); gis_context.ut_set_geo_arg(1, &multi_poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTILINESTRING); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultilinestring *res = reinterpret_cast(result); EXPECT_EQ(res->size(), output.size()); ASSERT_EQ(true, is_geo_equal(*res, output)); } TEST_F(TestGeoFuncDifference, polygon_polygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); polygon_geog_t green, blue; boost::geometry::read_wkt( "POLYGON((0.0 0.0, 0.0 10.0, 10.0 10.0, 10.0 0.0, 0.0 0.0))", green); boost::geometry::read_wkt( "POLYGON((5.0 0.0, 5.0 10.0, 15.0 10.0, 15.0 0.0, 5.0 0.0))", blue); mpolygon_geog_t output; apply_bg_diff_line_test(green, blue, srs, output); int i = 0; std::cout << "green && blue:" << std::endl; std::vector< std::pair > res_val; BOOST_FOREACH(polygon_geog_t const& l, output) { auto & outer = l.outer(); std::cout << "outer : "; for (auto & p : outer) { std::cout << "(" << p.x() << ", "<< p.y() << ")"; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; for (auto & inner : l.inners()) { std::cout << "inner : " << i++; for (auto & p : inner) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; } } ObJsonBuffer data(&allocator); uint32_t lnum = 1; uint32_t pnum = 5; ASSERT_EQ(OB_SUCCESS, append_bo(data)); ASSERT_EQ(OB_SUCCESS, append_type(data, ObGeoType::POLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data, lnum)); for (int j = 0; j < lnum; j++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data, pnum)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data, 0.0)); } ObIWkbGeogPolygon poly1; poly1.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::POLYGON)); ASSERT_EQ(OB_SUCCESS, append_uint32(data1, lnum)); for (int j = 0; j < lnum; j++) { ASSERT_EQ(OB_SUCCESS, append_uint32(data1, pnum)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 10.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 15.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 5.0)); ASSERT_EQ(OB_SUCCESS, append_double(data1, 0.0)); } ObIWkbGeogPolygon poly2; poly2.set_data(data1.string()); ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly1); gis_context.ut_set_geo_arg(1, &poly2); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOLYGON); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipolygon *res = reinterpret_cast(result); ASSERT_EQ(true, is_geo_equal(*res, output)); } TEST_F(TestGeoFuncDifference, polygon_multipolygon_geog) { ObArenaAllocator allocator(ObModIds::TEST); const ObSrsItem *srs = NULL; ASSERT_EQ(OB_SUCCESS, mock_get_tenant_srs_item(allocator, 4326, srs)); polygon_geog_t pol; boost::geometry::read_wkt( "POLYGON((0.0 0.0, 10.0 0.0, 10.0 10.0, 0.0 10.0, 0.0 0.0))", pol); mpolygon_geog_t mpoly1; boost::geometry::read_wkt( "MULTIPOLYGON(((5.0 0.0, 15.0 0.0, 15.0 10.0, 5.0 10.0, 5.0 0.0)), ((0.0 5.0, 5.0 5.0, 5.0 8.0, 0.0 8.0, 0.0 5.0)))", mpoly1); mpolygon_geog_t output; apply_bg_diff_line_test(pol, mpoly1, srs, output); int i = 0; std::vector< std::pair > res_val; BOOST_FOREACH(polygon_geog_t const& l, output) { auto & outer = l.outer(); std::cout << "outer : "; for (auto & p : outer) { std::cout << "(" << p.x() << ", "<< p.y() << ")"; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; for (auto & inner : l.inners()) { std::cout << "inner : " << i++; for (auto & p : inner) { std::cout << "(" << p.x() << ", "<< p.y() << ")" << std::endl; res_val.push_back(std::make_pair(p.x(), p.y())); } std::cout << std::endl; } } ObJsonBuffer data(&allocator); std::vector< std::pair > pol_val; pol_val.push_back(std::make_pair(0.0, 0.0)); pol_val.push_back(std::make_pair(10.0, 0.0)); pol_val.push_back(std::make_pair(10.0, 10.0)); pol_val.push_back(std::make_pair(0.0, 10.0)); pol_val.push_back(std::make_pair(0.0, 0.0)); create_polygon(data, 1, 5, pol_val); ObIWkbGeogPolygon poly; poly.set_data(data.string()); ObJsonBuffer data1(&allocator); ASSERT_EQ(OB_SUCCESS, append_bo(data1)); ASSERT_EQ(OB_SUCCESS, append_type(data1, ObGeoType::MULTIPOLYGON)); uint32_t polygon_num = 2; ASSERT_EQ(OB_SUCCESS, append_uint32(data1, polygon_num)); std::vector< std::pair > val; val.push_back(std::make_pair(5.0, 0.0)); val.push_back(std::make_pair(15.0, 0.0)); val.push_back(std::make_pair(15.0, 10.0)); val.push_back(std::make_pair(5.0, 10.0)); val.push_back(std::make_pair(5.0, 0.0)); create_polygon(data1, 1, 5, val); std::vector< std::pair > val1; val1.push_back(std::make_pair(0.0, 5.0)); val1.push_back(std::make_pair(5.0, 5.0)); val1.push_back(std::make_pair(5.0, 8.0)); val1.push_back(std::make_pair(0.0, 8.0)); val1.push_back(std::make_pair(0.0, 5.0)); create_polygon(data1, 1, 5, val1); ObIWkbGeogMultiPolygon multi_poly; multi_poly.set_data(data1.string()); const ObWkbGeogMultiPolygon *multi_p = reinterpret_cast(multi_poly.val()); ASSERT_EQ(multi_p->size(), 2); std::cout << "ob::mpoly1" << boost::geometry::dsv(*multi_p) << std::endl; ObGeoEvalCtx gis_context(&allocator, srs); gis_context.ut_set_geo_count(2); gis_context.ut_set_geo_arg(0, &poly); gis_context.ut_set_geo_arg(1, &multi_poly); ObGeometry *result = NULL; int ret = ObGeoFunc::geo_func::eval(gis_context, result); ASSERT_EQ(OB_SUCCESS, ret); ASSERT_TRUE(result != NULL); ASSERT_EQ(result->type(), ObGeoType::MULTIPOLYGON); ASSERT_EQ(result->crs(), ObGeoCRS::Geographic); ObGeographMultipolygon *res = reinterpret_cast(result); EXPECT_EQ(res->size(), output.size()); ASSERT_EQ(true, is_geo_equal(*res, output)); } } // namespace common } // namespace oceanbase int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }