Skip to content

Commit

Permalink
Geo spatial: Geography
Browse files Browse the repository at this point in the history
  • Loading branch information
jievince committed Sep 22, 2021
1 parent 32ff73f commit 5a66a88
Show file tree
Hide file tree
Showing 60 changed files with 1,621 additions and 28 deletions.
11 changes: 11 additions & 0 deletions src/codec/RowReaderV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,17 @@ Value RowReaderV2::getValueByIndex(const int64_t index) const noexcept {
dt.microsec = microsec;
return dt;
}
case meta::cpp2::PropertyType::GEOGRAPHY: {
int32_t strOffset;
int32_t strLen;
memcpy(reinterpret_cast<void*>(&strOffset), &data_[offset], sizeof(int32_t));
memcpy(reinterpret_cast<void*>(&strLen), &data_[offset + sizeof(int32_t)], sizeof(int32_t));
if (static_cast<size_t>(strOffset) == data_.size() && strLen == 0) {
return Geography();
}
CHECK_LT(strOffset, data_.size());
return Geography(std::string(&data_[strOffset], strLen));
}
case meta::cpp2::PropertyType::UNKNOWN:
break;
}
Expand Down
13 changes: 13 additions & 0 deletions src/codec/RowWriterV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ RowWriterV2::RowWriterV2(RowReader& reader) : RowWriterV2(reader.getSchema()) {
case Value::Type::DATETIME:
set(i, v.moveDateTime());
break;
case Value::Type::GEOGRAPHY:
set(i, v.moveGeography());
break;
default:
LOG(FATAL) << "Invalid data: " << v << ", type: " << v.typeName();
}
Expand Down Expand Up @@ -203,6 +206,8 @@ WriteResult RowWriterV2::setValue(ssize_t index, const Value& val) noexcept {
return write(index, val.getTime());
case Value::Type::DATETIME:
return write(index, val.getDateTime());
case Value::Type::GEOGRAPHY:
return write(index, val.getGeography());
default:
return WriteResult::TYPE_MISMATCH;
}
Expand Down Expand Up @@ -637,6 +642,7 @@ WriteResult RowWriterV2::write(ssize_t index, folly::StringPiece v) noexcept {
auto field = schema_->field(index);
auto offset = headerLen_ + numNullBytes_ + field->offset();
switch (field->type()) {
case meta::cpp2::PropertyType::GEOGRAPHY: // write wkb
case meta::cpp2::PropertyType::STRING: {
if (isSet_[index]) {
// The string value has already been set, we need to turn it
Expand Down Expand Up @@ -755,6 +761,10 @@ WriteResult RowWriterV2::write(ssize_t index, const DateTime& v) noexcept {
return WriteResult::SUCCEEDED;
}

WriteResult RowWriterV2::write(ssize_t index, const Geography& v) noexcept {
return write(index, folly::StringPiece(v.wkb));
}

WriteResult RowWriterV2::checkUnsetFields() noexcept {
DefaultValueContext expCtx;
for (size_t i = 0; i < schema_->getNumFields(); i++) {
Expand Down Expand Up @@ -794,6 +804,9 @@ WriteResult RowWriterV2::checkUnsetFields() noexcept {
case Value::Type::DATETIME:
r = write(i, defVal.getDateTime());
break;
case Value::Type::GEOGRAPHY:
r = write(i, defVal.getGeography());
break;
default:
LOG(FATAL) << "Unsupported default value type: " << defVal.typeName()
<< ", default value: " << defVal
Expand Down
3 changes: 3 additions & 0 deletions src/codec/RowWriterV2.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum class WriteResult {
TIMESTAMP (8 bytes)
DATE (4 bytes)
DATETIME (15 bytes)
GEOGRAPHY (8 bytes) *
All except STRING typed properties are stored in-place. The STRING property
stored the offset of the string content in the first 4 bytes and the length
Expand Down Expand Up @@ -188,6 +189,8 @@ class RowWriterV2 {
WriteResult write(ssize_t index, const Date& v) noexcept;
WriteResult write(ssize_t index, const Time& v) noexcept;
WriteResult write(ssize_t index, const DateTime& v) noexcept;

WriteResult write(ssize_t index, const Geography& v) noexcept;
};

} // namespace nebula
Expand Down
1 change: 1 addition & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ nebula_add_subdirectory(function)
nebula_add_subdirectory(graph)
nebula_add_subdirectory(plugin)
nebula_add_subdirectory(utils)
nebula_add_subdirectory(geo)
2 changes: 1 addition & 1 deletion src/common/base/Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@

#include "common/base/Logging.h"

#define MUST_USE_RESULT __attribute__((warn_unused_result))
#define NG_MUST_USE_RESULT __attribute__((warn_unused_result))
#define DONT_OPTIMIZE __attribute__((optimize("O0")))

#define ALWAYS_INLINE __attribute__((always_inline))
Expand Down
25 changes: 13 additions & 12 deletions src/common/conf/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ class Configuration final {
/**
* Parse from a file
*/
Status MUST_USE_RESULT parseFromFile(const std::string &filename);
Status NG_MUST_USE_RESULT parseFromFile(const std::string &filename);
/**
* Parse from a string buffer
*/
Status MUST_USE_RESULT parseFromString(const std::string &content);
Status NG_MUST_USE_RESULT parseFromString(const std::string &content);

std::string dumpToString() const;

Expand All @@ -42,19 +42,20 @@ class Configuration final {
* @key item key
* @val to hold the item value.
*/
Status MUST_USE_RESULT fetchAsInt(const char *key, int64_t &val) const;
Status MUST_USE_RESULT fetchAsDouble(const char *key, double &val) const;
Status MUST_USE_RESULT fetchAsBool(const char *key, bool &val) const;
Status MUST_USE_RESULT fetchAsString(const char *key, std::string &val) const;
Status NG_MUST_USE_RESULT fetchAsInt(const char *key, int64_t &val) const;
Status NG_MUST_USE_RESULT fetchAsDouble(const char *key, double &val) const;
Status NG_MUST_USE_RESULT fetchAsBool(const char *key, bool &val) const;
Status NG_MUST_USE_RESULT fetchAsString(const char *key, std::string &val) const;

Status MUST_USE_RESULT fetchAsIntArray(const char *key, std::vector<int64_t> &val) const;
Status MUST_USE_RESULT fetchAsDoubleArray(const char *key, std::vector<double> &val) const;
Status MUST_USE_RESULT fetchAsBoolArray(const char *key, std::vector<bool> &val) const;
Status MUST_USE_RESULT fetchAsStringArray(const char *key, std::vector<std::string> &val) const;
Status NG_MUST_USE_RESULT fetchAsIntArray(const char *key, std::vector<int64_t> &val) const;
Status NG_MUST_USE_RESULT fetchAsDoubleArray(const char *key, std::vector<double> &val) const;
Status NG_MUST_USE_RESULT fetchAsBoolArray(const char *key, std::vector<bool> &val) const;
Status NG_MUST_USE_RESULT fetchAsStringArray(const char *key,
std::vector<std::string> &val) const;

Status MUST_USE_RESULT fetchAsSubConf(const char *key, Configuration &val) const;
Status NG_MUST_USE_RESULT fetchAsSubConf(const char *key, Configuration &val) const;

Status MUST_USE_RESULT upsertStringField(const char *key, const std::string &val);
Status NG_MUST_USE_RESULT upsertStringField(const char *key, const std::string &val);

// Iterate through every key in the configuration
Status forEachKey(std::function<void(const std::string &)> processor) const;
Expand Down
1 change: 1 addition & 0 deletions src/common/datatypes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ nebula_add_library(
Map.cpp
List.cpp
Set.cpp
Geography.cpp
)

nebula_add_subdirectory(test)
2 changes: 2 additions & 0 deletions src/common/datatypes/CommonCpp2Ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct Map;
struct Set;
struct List;
struct DataSet;
struct Geography;
} // namespace nebula

namespace apache::thrift {
Expand All @@ -43,6 +44,7 @@ SPECIALIZE_CPP2OPS(nebula::Map);
SPECIALIZE_CPP2OPS(nebula::Set);
SPECIALIZE_CPP2OPS(nebula::List);
SPECIALIZE_CPP2OPS(nebula::DataSet);
SPECIALIZE_CPP2OPS(nebula::Geography);

} // namespace apache::thrift

Expand Down
76 changes: 76 additions & 0 deletions src/common/datatypes/Geography.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "common/datatypes/Geography.h"

#include <folly/String.h>
#include <folly/hash/Hash.h>

#include <cstdint>

namespace nebula {

S2Region* Geography::asS2() const {
// auto geom = WKBReader().read(wkb);
// return s2RegionFromGeom(&geom);
return nullptr;
}

// S2Region* Geography::s2RegionFromGeom(const geos::geom::Geometry* geom) {
// return new S2Region;
// switch (geom->getGeometryTypeId()) {
// case geos::geom::GEOS_POINT: {
// auto *point = static_cast<geos::geom::Point*>(geom);
// auto latlng = S2LatLng::FromDegrees(point->getX(), point->getY());
// return new S2PointRegion(latlng.toPoint());
// }
// case geos::geom::GEOS_LINESTRING: {
// auot *lineString = static_cast<geos::geom::LineString*>(geom);
// std::vector<S2Point> s2Points;
// latlngs.reserve(lineString->numPoints());
// for (size_t i = 0; i < lineString->numPoints(); ++i) {
// auto latlng = lineString->getCoordinateN(i);
// s2Points.emplace_back(S2LatLng::FromDegrees(latlng.x, latlng.y).ToPoint());
// }
// return new S2Polyline(s2Points);
// }
// case geos::geom::GEOS_POLYGON: {
// auto *polygon = static_cast<geos::geom::Polygon*>(geom);
// size_t ringNum = 1 + polygon->getNumInteriorRing();
// std::vector<std::unique_ptr<S2Loop>> s2Loops;
// s2Loops.reserve(ringNum);

// std::vector<const LinearRing*> rings;
// rings.reserve(ringNum);

// std::vector<S2Point> s2Points;
// for (size_t i = 0; i < rings.size(); ++i) {
// const auto *ring = rings[i];
// s2Points.clear();
// s2Points.reserve(ring->numPoints());
// for (size_t j = 0; j < ring->numPoints(); ++j) {
// auto latlng = ring->getCoordinateN(i);
// s2Points.empalce_back(S2LatLng::FromDegrees(latlng.x, latlng.y).ToPoint());
// }
// auto *s2Loop = new S2Loop(s2Points);
// s2Loop->Normalize();
// s2Loops.emplace_back(s2Loop); // make loop be CCW
// return new S2Polygon(s2Loops);
// }
// }
// }
// }

} // namespace nebula

namespace std {

// Inject a customized hash function
std::size_t hash<nebula::Geography>::operator()(const nebula::Geography& h) const noexcept {
return hash<std::string>{}(h.wkb);
}

} // namespace std
90 changes: 90 additions & 0 deletions src/common/datatypes/Geography.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#pragma once

#include <s2/s2point.h>
#include <s2/s2point_region.h>
#include <s2/s2polyline.h>
#include <s2/s2region.h>

#include <algorithm>
#include <typeinfo>
#include <vector>

#include "common/datatypes/Value.h"

class S2Polygon;

namespace nebula {

// clang-format off
/*
static const std::unordered_map<ShapeType, S2Region> kShapeTypeToS2Region = {
{ShapeType::Point, S2PointRegion}, // S2PointRegion is a wrapper of S2Point, and it inherits from the S2Region class
{ShapeType::LineString, S2Polyline},
{ShapeType::Polygon, S2Polygon},
};
*/
// clang-format on

enum class ShapeType : uint8_t {
Point = 1,
LineString = 2,
Polygon = 3,
};

// Do not construct a S2 data when constructing Geography. It's expensive.
// We just construct S2 when doing computation.
struct Geography {
std::string wkb;

Geography() = default;
explicit Geography(const std::string& validWKB) {
// DCHECK(WKB::isValid(wkb));
wkb = validWKB;
}

S2Region* asS2() const;

ShapeType shape() const {
// auto type = WKBReader.readUint32(wkb.substr(1));
// DCHECK(type >= 1 && type <= 3);
// return static_cast<ShapeType>(type);
return static_cast<ShapeType>(1);
}

void clear() { wkb.clear(); }

void __clear() { clear(); }

std::string toString() const { return wkb; }

folly::dynamic toJson() const { return toString(); }

bool operator==(const Geography& rhs) const { return wkb == rhs.wkb; }

bool operator!=(const Geography& rhs) const { return !(wkb == rhs.wkb); }

bool operator<(const Geography& rhs) const { return wkb < rhs.wkb; }

// private:
// S2Region* s2RegionFromGeom(const geos::geom::Geometry* geom);
};

inline std::ostream& operator<<(std::ostream& os, const Geography& g) { return os << g.wkb; }

} // namespace nebula

namespace std {

// Inject a customized hash function
template <>
struct hash<nebula::Geography> {
std::size_t operator()(const nebula::Geography& h) const noexcept;
};

} // namespace std
Loading

0 comments on commit 5a66a88

Please sign in to comment.