340 lines
14 KiB
C++
340 lines
14 KiB
C++
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License, version 2.0,
|
|
// as published by the Free Software Foundation.
|
|
//
|
|
// This program is also distributed with certain software (including
|
|
// but not limited to OpenSSL) that is licensed under separate terms,
|
|
// as designated in a particular file or component or in included license
|
|
// documentation. The authors of MySQL hereby grant you an additional
|
|
// permission to link the program and your derivative works with the
|
|
// separately licensed software that they have included with MySQL.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License, version 2.0, for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
/// @file
|
|
///
|
|
/// This file test gis::write_geometry and the gis::Wkb_visitor class.
|
|
|
|
#include "my_config.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <memory> // unique_ptr
|
|
#include <string>
|
|
|
|
#include "sql/dd/dd.h"
|
|
#include "sql/dd/impl/types/spatial_reference_system_impl.h"
|
|
#include "sql/dd/properties.h"
|
|
#include "sql/dd/types/spatial_reference_system.h"
|
|
#include "sql/gis/geometries.h"
|
|
#include "sql/gis/geometries_cs.h"
|
|
#include "sql/gis/wkb.h"
|
|
|
|
namespace wkb_writer_unittest {
|
|
|
|
class WkbWriterTest : public ::testing::Test {
|
|
protected:
|
|
dd::Spatial_reference_system_impl *m_cartesian_srs;
|
|
dd::Spatial_reference_system_impl *m_radian_srs;
|
|
dd::Spatial_reference_system_impl *m_grad_srs;
|
|
|
|
void SetUp() {
|
|
m_cartesian_srs = dynamic_cast<dd::Spatial_reference_system_impl *>(
|
|
dd::create_object<dd::Spatial_reference_system>());
|
|
m_cartesian_srs->set_id(3857);
|
|
m_cartesian_srs->set_name("WGS 84 / Pseudo-Mercator");
|
|
m_cartesian_srs->set_created(0UL);
|
|
m_cartesian_srs->set_last_altered(0UL);
|
|
m_cartesian_srs->set_organization("EPSG");
|
|
m_cartesian_srs->set_organization_coordsys_id(3857);
|
|
m_cartesian_srs->set_definition(
|
|
"PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"World "
|
|
"Geodetic System 1984\",SPHEROID[\"WGS "
|
|
"84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY["
|
|
"\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\","
|
|
"\"8901\"]],UNIT[\"degree\",0.017453292519943278,AUTHORITY[\"EPSG\","
|
|
"\"9122\"]],AXIS[\"Lat\",NORTH],AXIS[\"Lon\",EAST],AUTHORITY[\"EPSG\","
|
|
"\"4326\"]],PROJECTION[\"Popular Visualisation Pseudo "
|
|
"Mercator\",AUTHORITY[\"EPSG\",\"1024\"]],PARAMETER[\"Latitude of "
|
|
"natural "
|
|
"origin\",0,AUTHORITY[\"EPSG\",\"8801\"]],PARAMETER[\"Longitude of "
|
|
"natural origin\",0,AUTHORITY[\"EPSG\",\"8802\"]],PARAMETER[\"False "
|
|
"easting\",0,AUTHORITY[\"EPSG\",\"8806\"]],PARAMETER[\"False "
|
|
"northing\",0,AUTHORITY[\"EPSG\",\"8807\"]],UNIT[\"metre\",1,AUTHORITY["
|
|
"\"EPSG\",\"9001\"]],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH],AUTHORITY["
|
|
"\"EPSG\",\"3857\"]]");
|
|
m_cartesian_srs->set_description("");
|
|
m_cartesian_srs->parse_definition();
|
|
|
|
// EPSG 4326, lat-long (N-E), Greenwich Meridian, but in radians
|
|
m_radian_srs = dynamic_cast<dd::Spatial_reference_system_impl *>(
|
|
dd::create_object<dd::Spatial_reference_system>());
|
|
m_radian_srs->set_id(1000000);
|
|
m_radian_srs->set_name("WGS 84");
|
|
m_radian_srs->set_created(0UL);
|
|
m_radian_srs->set_last_altered(0UL);
|
|
m_radian_srs->set_organization("EPSG");
|
|
m_radian_srs->set_organization_coordsys_id(4326);
|
|
m_radian_srs->set_definition(
|
|
"GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System 1984\",SPHEROID[\"WGS "
|
|
"84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY["
|
|
"\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\","
|
|
"\"8901\"]],UNIT[\"radian\",1.0],AXIS[\"Lat\",NORTH],AXIS[\"Lon\",EAST]"
|
|
",AUTHORITY[\"EPSG\",\"4326\"]]");
|
|
m_radian_srs->set_description("");
|
|
m_radian_srs->parse_definition();
|
|
|
|
// Lat-long (S-W) in grad, Meridian 10 grad East of Greenwich
|
|
m_grad_srs = dynamic_cast<dd::Spatial_reference_system_impl *>(
|
|
dd::create_object<dd::Spatial_reference_system>());
|
|
m_grad_srs->set_id(1000001);
|
|
m_grad_srs->set_name("Tweaked");
|
|
m_grad_srs->set_created(0UL);
|
|
m_grad_srs->set_last_altered(0UL);
|
|
m_grad_srs->set_organization("EPSG");
|
|
m_grad_srs->set_organization_coordsys_id(1000000);
|
|
m_grad_srs->set_definition(
|
|
"GEOGCS[\"Tweaked\",DATUM[\"World Geodetic System "
|
|
"1984\",SPHEROID[\"WGS "
|
|
"84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY["
|
|
"\"EPSG\",\"6326\"]],PRIMEM[\"10 "
|
|
"E\",10,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"grad\",0."
|
|
"01570796326794895,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Lat\",SOUTH],"
|
|
"AXIS[\"Lon\",WEST],AUTHORITY[\"EPSG\",\"4326\"]]");
|
|
m_grad_srs->set_description("");
|
|
m_grad_srs->parse_definition();
|
|
}
|
|
|
|
void TearDown() {
|
|
delete m_cartesian_srs;
|
|
delete m_radian_srs;
|
|
delete m_grad_srs;
|
|
}
|
|
|
|
WkbWriterTest() {}
|
|
|
|
private:
|
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(WkbWriterTest);
|
|
};
|
|
|
|
TEST_F(WkbWriterTest, Point) {
|
|
gis::Cartesian_point cpt(1, 2);
|
|
gis::Geographic_point gpt(1, 2);
|
|
|
|
// Little-endian POINT(1 2)
|
|
std::string point(
|
|
"\x00\x00\x00\x00" // SRID
|
|
"\x01" // Byte order
|
|
"\x01\x00\x00\x00" // WKB type
|
|
"\x00\x00\x00\x00\x00\x00\xf0\x3f" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x40", // Y
|
|
25);
|
|
|
|
// Cartesian
|
|
String srid0_point;
|
|
gis::write_geometry(nullptr, cpt, &srid0_point);
|
|
EXPECT_EQ(point.size(), srid0_point.length());
|
|
EXPECT_FALSE(memcmp(point.c_str(), srid0_point.c_ptr(), point.size()));
|
|
|
|
String cartesian_point;
|
|
gis::write_geometry(m_cartesian_srs, cpt, &cartesian_point);
|
|
EXPECT_EQ(point.size(), cartesian_point.length());
|
|
EXPECT_FALSE(memcmp("\x11\x0f\x00\x00", cartesian_point.c_ptr(), 4));
|
|
EXPECT_FALSE(
|
|
memcmp(point.c_str() + 4, cartesian_point.c_ptr() + 4, point.size() - 4));
|
|
|
|
// Radians
|
|
String radian_point;
|
|
gis::write_geometry(m_radian_srs, gpt, &radian_point);
|
|
EXPECT_EQ(point.size(), radian_point.length());
|
|
EXPECT_FALSE(memcmp("\x40\x42\x0f\x00", radian_point.c_ptr(), 4));
|
|
EXPECT_FALSE(
|
|
memcmp(point.c_str() + 4, radian_point.c_ptr() + 4, point.size() - 4));
|
|
|
|
// Lat-long (S-W), grad, meridian 10 grad East of Greenwich. Point is 1 grad
|
|
// West (=9 grad East of Greenwich), 2 grad South.
|
|
gis::Geographic_point grad_pt(0.14137166941154056, -0.031415926535897899);
|
|
String grad_point;
|
|
gis::write_geometry(m_grad_srs, grad_pt, &grad_point);
|
|
EXPECT_EQ(point.size(), grad_point.length());
|
|
EXPECT_FALSE(memcmp("\x41\x42\x0f\x00", grad_point.c_ptr(), 4));
|
|
EXPECT_FALSE(
|
|
memcmp(point.c_str() + 4, grad_point.c_ptr() + 4, point.size() - 4));
|
|
}
|
|
|
|
TEST_F(WkbWriterTest, Linestring) {
|
|
gis::Cartesian_linestring cls;
|
|
cls.push_back(gis::Cartesian_point(0, 0));
|
|
cls.push_back(gis::Cartesian_point(0, 0));
|
|
gis::Geographic_linestring gls;
|
|
gls.push_back(gis::Geographic_point(0, 0));
|
|
gls.push_back(gis::Geographic_point(0, 0));
|
|
|
|
// Linestring with two points
|
|
std::string linestring(
|
|
"\x00\x00\x00\x00" // SRID
|
|
"\x01" // Byte order
|
|
"\x02\x00\x00\x00" // WKB type
|
|
"\x02\x00\x00\x00" // numPoints
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00", // Y
|
|
45);
|
|
|
|
// Cartesian
|
|
String srid0_linestring;
|
|
gis::write_geometry(nullptr, cls, &srid0_linestring);
|
|
EXPECT_EQ(linestring.size(), srid0_linestring.length());
|
|
EXPECT_FALSE(
|
|
memcmp(linestring.c_str(), srid0_linestring.c_ptr(), linestring.size()));
|
|
|
|
String cartesian_linestring;
|
|
gis::write_geometry(m_cartesian_srs, cls, &cartesian_linestring);
|
|
EXPECT_EQ(linestring.size(), cartesian_linestring.length());
|
|
EXPECT_FALSE(memcmp("\x11\x0f\x00\x00", cartesian_linestring.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(linestring.c_str() + 4, cartesian_linestring.c_ptr() + 4,
|
|
linestring.size() - 4));
|
|
|
|
// Radians
|
|
String radian_linestring;
|
|
gis::write_geometry(m_radian_srs, gls, &radian_linestring);
|
|
EXPECT_EQ(linestring.size(), radian_linestring.length());
|
|
EXPECT_FALSE(memcmp("\x40\x42\x0f\x00", radian_linestring.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(linestring.c_str() + 4, radian_linestring.c_ptr() + 4,
|
|
linestring.size() - 4));
|
|
}
|
|
|
|
TEST_F(WkbWriterTest, Polygon) {
|
|
gis::Cartesian_polygon cpy;
|
|
gis::Cartesian_linearring cexterior;
|
|
cexterior.push_back(gis::Cartesian_point(0, 0));
|
|
cexterior.push_back(gis::Cartesian_point(0, 0));
|
|
cexterior.push_back(gis::Cartesian_point(0, 0));
|
|
cexterior.push_back(gis::Cartesian_point(0, 0));
|
|
cpy.push_back(cexterior);
|
|
gis::Cartesian_linearring cinterior;
|
|
cinterior.push_back(gis::Cartesian_point(0, 0));
|
|
cinterior.push_back(gis::Cartesian_point(0, 0));
|
|
cinterior.push_back(gis::Cartesian_point(0, 0));
|
|
cinterior.push_back(gis::Cartesian_point(0, 0));
|
|
cpy.push_back(cinterior);
|
|
|
|
gis::Geographic_polygon gpy;
|
|
gis::Geographic_linearring gexterior;
|
|
gexterior.push_back(gis::Geographic_point(0, 0));
|
|
gexterior.push_back(gis::Geographic_point(0, 0));
|
|
gexterior.push_back(gis::Geographic_point(0, 0));
|
|
gexterior.push_back(gis::Geographic_point(0, 0));
|
|
gpy.push_back(gexterior);
|
|
gis::Geographic_linearring ginterior;
|
|
ginterior.push_back(gis::Geographic_point(0, 0));
|
|
ginterior.push_back(gis::Geographic_point(0, 0));
|
|
ginterior.push_back(gis::Geographic_point(0, 0));
|
|
ginterior.push_back(gis::Geographic_point(0, 0));
|
|
gpy.push_back(ginterior);
|
|
|
|
// Polygon with two rings, each with four points
|
|
std::string polygon(
|
|
"\x00\x00\x00\x00" // SRID
|
|
"\x01" // Byte order
|
|
"\x03\x00\x00\x00" // WKB type
|
|
"\x02\x00\x00\x00" // numRings
|
|
"\x04\x00\x00\x00" // numPoints
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x04\x00\x00\x00" // numPoints
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // Y
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x00", // Y
|
|
149);
|
|
|
|
// Cartesian
|
|
String srid0_polygon;
|
|
gis::write_geometry(nullptr, cpy, &srid0_polygon);
|
|
EXPECT_EQ(polygon.size(), srid0_polygon.length());
|
|
EXPECT_FALSE(memcmp(polygon.c_str(), srid0_polygon.c_ptr(), polygon.size()));
|
|
|
|
String cartesian_polygon;
|
|
gis::write_geometry(m_cartesian_srs, cpy, &cartesian_polygon);
|
|
EXPECT_EQ(polygon.size(), cartesian_polygon.length());
|
|
EXPECT_FALSE(memcmp("\x11\x0f\x00\x00", cartesian_polygon.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(polygon.c_str() + 4, cartesian_polygon.c_ptr() + 4,
|
|
polygon.size() - 4));
|
|
|
|
// Radians
|
|
String radian_polygon;
|
|
gis::write_geometry(m_radian_srs, gpy, &radian_polygon);
|
|
EXPECT_EQ(polygon.size(), radian_polygon.length());
|
|
EXPECT_FALSE(memcmp("\x40\x42\x0f\x00", radian_polygon.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(polygon.c_str() + 4, radian_polygon.c_ptr() + 4,
|
|
polygon.size() - 4));
|
|
}
|
|
|
|
TEST_F(WkbWriterTest, Geometrycollection) {
|
|
gis::Cartesian_geometrycollection cgc;
|
|
cgc.push_back(gis::Cartesian_point(1, 2));
|
|
gis::Geographic_geometrycollection ggc;
|
|
ggc.push_back(gis::Geographic_point(1, 2));
|
|
|
|
// Little-endian GEOMETRYCOLLECTION(POINT(1 2));
|
|
std::string geometrycollection(
|
|
"\x00\x00\x00\x00" // SRID
|
|
"\x01" // Byte order
|
|
"\x07\x00\x00\x00" // WKB type
|
|
"\x01\x00\x00\x00" // numGeometries
|
|
"\x01" // Byte order
|
|
"\x01\x00\x00\x00" // WKB type
|
|
"\x00\x00\x00\x00\x00\x00\xf0\x3f" // X
|
|
"\x00\x00\x00\x00\x00\x00\x00\x40", // Y
|
|
34);
|
|
|
|
// Cartesian
|
|
String srid0_geometrycollection;
|
|
gis::write_geometry(nullptr, cgc, &srid0_geometrycollection);
|
|
EXPECT_EQ(geometrycollection.size(), srid0_geometrycollection.length());
|
|
EXPECT_FALSE(memcmp(geometrycollection.c_str(),
|
|
srid0_geometrycollection.c_ptr(),
|
|
geometrycollection.size()));
|
|
|
|
String cartesian_geometrycollection;
|
|
gis::write_geometry(m_cartesian_srs, cgc, &cartesian_geometrycollection);
|
|
EXPECT_EQ(geometrycollection.size(), cartesian_geometrycollection.length());
|
|
EXPECT_FALSE(
|
|
memcmp("\x11\x0f\x00\x00", cartesian_geometrycollection.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(geometrycollection.c_str() + 4,
|
|
cartesian_geometrycollection.c_ptr() + 4,
|
|
geometrycollection.size() - 4));
|
|
|
|
// Radians
|
|
String radian_geometrycollection;
|
|
gis::write_geometry(m_radian_srs, ggc, &radian_geometrycollection);
|
|
EXPECT_EQ(geometrycollection.size(), radian_geometrycollection.length());
|
|
EXPECT_FALSE(
|
|
memcmp("\x40\x42\x0f\x00", radian_geometrycollection.c_ptr(), 4));
|
|
EXPECT_FALSE(memcmp(geometrycollection.c_str() + 4,
|
|
radian_geometrycollection.c_ptr() + 4,
|
|
geometrycollection.size() - 4));
|
|
}
|
|
|
|
} // namespace wkb_writer_unittest
|