oceanbase/unittest/share/test_geo_func_difference.cpp

2050 lines
74 KiB
C++

/**
* 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 <gtest/gtest.h>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/foreach.hpp>
#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 <sys/time.h>
#include <stdexcept>
#include <exception>
#include <typeinfo>
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<uint8_t>(bo);
return data.append(reinterpret_cast<char*>(&sbo), sizeof(uint8_t));
}
int append_type(ObJsonBuffer& data, ObGeoType type, ObGeoWkbByteOrder bo = ObGeoWkbByteOrder::LittleEndian)
{
INIT_SUCC(ret);
uint32_t stype = static_cast<uint32_t>(type);
if (OB_FAIL(data.reserve(sizeof(uint32_t)))) {
} else {
char *ptr = data.ptr() + data.length();
ObGeoWkbByteOrderUtil::write<uint32_t>(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<uint32_t>(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<double>(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<double, double> > &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<double, double> > &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<double, double> > &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<double, double> > &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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianLineString *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultilinestring *>(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<boost::geometry::model::d2::point_xy<double> > 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<line_bg> 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<double, double> > 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<ObWkbGeomPolygon *>(const_cast<char *>(poly.val()));
ObWkbGeomLineString *line_condidate = reinterpret_cast<ObWkbGeomLineString *>(const_cast<char *>(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<ObGeoFuncType::Difference>::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<ObCartesianMultilinestring *>(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<boost::geometry::model::d2::point_xy<double> > line_bg;
typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > 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<line_bg> 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<ObCartesianMultilinestring *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultilinestring *>(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<boost::geometry::model::d2::point_xy<double> > linestring_t;
typedef boost::geometry::model::multi_linestring<linestring_t> 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<linestring_t> 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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultilinestring *>(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<boost::geometry::model::d2::point_xy<double>, 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<polygon> output;
boost::geometry::difference(green, blue, output);
int i = 0;
std::vector< std::pair<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipolygon *>(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<double> point_t;
typedef bg::model::polygon<point_t> polygon_t;
typedef bg::model::multi_polygon<polygon_t> 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<polygon_t> output;
boost::geometry::difference(pol, mpoly1, output);
int i = 0;
std::vector< std::pair<double, double> > 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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipolygon *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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 <typename GeometryType1, typename GeometryType2, typename GeometryRes>
void apply_bg_diff_line_test(GeometryType1 &geo1, GeometryType2 &geo2, const ObSrsItem *srs,
GeometryRes &res)
{
boost::geometry::srs::spheroid<double> geog_sphere(srs->semi_major_axis(), srs->semi_minor_axis());
ObLlLaAaStrategy line_strategy(geog_sphere);
boost::geometry::difference(geo1, geo2, res, line_strategy);
}
template <typename GeometryType1, typename GeometryType2, typename GeometryRes>
void apply_bg_diff_point_test(GeometryType1 &geo1, GeometryType2 &geo2, const ObSrsItem *srs,
GeometryRes &res)
{
boost::geometry::srs::spheroid<double> 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<ObGeoFuncType::Difference>::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<ObCartesianMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipoint *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographLineString *>(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<boost::geometry::model::d2::point_xy<double, boost::geometry::cs::geographic<boost::geometry::radian>> > 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<line_bg> output;
boost::geometry::difference(green, blue, output);
int i = 0;
std::vector< std::pair<double, double> > 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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultilinestring *>(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<double, bg::cs::geographic<bg::radian> > point_geog_t;
typedef bg::model::multi_point<point_geog_t> mpoint_geog_t;
typedef bg::model::linestring<point_geog_t> line_geog_t;
typedef bg::model::multi_linestring<line_geog_t> mline_geog_t;
typedef bg::model::polygon<point_geog_t, false> polygon_geog_t;
typedef bg::model::multi_polygon<polygon_geog_t> mpolygon_geog_t;
template<typename GEO1, typename GEO2>
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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultilinestring *>(result);
ASSERT_EQ(res->size(), 1);
ASSERT_EQ(true, is_geo_equal(output, *res));
}
TEST_F(TestGeoFuncDifference, line_multiline_geog)
{
typedef bg::model::linestring<bg::model::d2::point_xy<double, bg::cs::geographic<bg::radian>> > linestring_t;
typedef bg::model::multi_linestring<linestring_t> 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<linestring_t> output;
boost::geometry::difference(ls, mls, output);
ASSERT_EQ(output.size(), 1);
int i = 0;
std::vector< std::pair<double, double> > 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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultilinestring *>(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<double, double> > 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<double, double> > 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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultilinestring *>(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<double, double> > 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<ObGeoFuncType::Difference>::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<ObGeographMultipolygon *>(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<double, double> > 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<double, double> > 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<double, double> > 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<double, double> > 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<const ObWkbGeogMultiPolygon*>(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<ObGeoFuncType::Difference>::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<ObGeographMultipolygon *>(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();
}