summaryrefslogtreecommitdiff
path: root/internal/dynamic_depth/plane.cc
blob: 7e3914eb37bf8037a0483981048c0db5d1054929 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "dynamic_depth/plane.h"

#include "android-base/logging.h"
#include "dynamic_depth/const.h"
#include "strings/numbers.h"
#include "xmpmeta/base64.h"

using photos_editing_formats::xml::Deserializer;
using photos_editing_formats::xml::Serializer;

namespace photos_editing_formats {
namespace dynamic_depth {
namespace {

constexpr char kBoundary[] = "Boundary";
constexpr char kBoundaryVertexCount[] = "BoundaryVertexCount";
constexpr char kExtentX[] = "ExtentX";
constexpr char kExtentZ[] = "ExtentZ";

constexpr char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/plane/";

}  // namespace

// Private constructor.
Plane::Plane() {}

// Public methods.
void Plane::GetNamespaces(
    std::unordered_map<string, string>* ns_name_href_map) {
  if (ns_name_href_map == nullptr) {
    LOG(ERROR) << "Namespace list is null";
    return;
  }
  ns_name_href_map->emplace(DynamicDepthConst::Plane(), kNamespaceHref);

  if (pose_ != nullptr) {
    pose_->GetNamespaces(ns_name_href_map);
  }
}

std::unique_ptr<Plane> Plane::FromData(std::unique_ptr<Pose> pose,
                                       const std::vector<float>& boundary,
                                       const double extent_x,
                                       const double extent_z) {
  if (pose == nullptr) {
    LOG(ERROR) << "The Plane's pose must be provided";
    return nullptr;
  }

  if (boundary.size() % 2 != 0) {
    LOG(ERROR) << "Number of vertices in the boundary polygon must be 2-tuples";
    return nullptr;
  }

  std::unique_ptr<Plane> plane(std::unique_ptr<Plane>(new Plane()));  // NOLINT
  plane->pose_ = std::move(pose);
  plane->boundary_vertex_count_ = boundary.size() / 2;
  if (!boundary.empty()) {
    plane->boundary_ = boundary;
  }

  plane->extent_x_ = extent_x;
  plane->extent_z_ = extent_z;
  return plane;
}

std::unique_ptr<Plane> Plane::FromDeserializer(
    const Deserializer& parent_deserializer) {
  std::unique_ptr<Deserializer> deserializer =
      parent_deserializer.CreateDeserializer(
          DynamicDepthConst::Namespace(DynamicDepthConst::Plane()),
          DynamicDepthConst::Plane());
  if (deserializer == nullptr) {
    LOG(ERROR) << "Deserializer must not be null";
    return nullptr;
  }

  std::unique_ptr<Plane> plane(std::unique_ptr<Plane>(new Plane()));  // NOLINT
  if (!plane->ParsePlaneFields(*deserializer)) {
    return nullptr;
  }

  return plane;
}

const Pose* Plane::GetPose() const { return pose_.get(); }

const std::vector<float>& Plane::GetBoundary() const { return boundary_; }

int Plane::GetBoundaryVertexCount() const { return boundary_vertex_count_; }

const double Plane::GetExtentX() const { return extent_x_; }

const double Plane::GetExtentZ() const { return extent_z_; }

bool Plane::Serialize(Serializer* serializer) const {
  if (serializer == nullptr) {
    LOG(ERROR) << "Serializer is null";
    return false;
  }

  if (pose_ == nullptr) {
    LOG(ERROR) << "Plane's pose must be present, not serializing";
    return false;
  }

  if (!serializer->WriteProperty(
          DynamicDepthConst::Plane(), kBoundaryVertexCount,
          ::dynamic_depth::strings::SimpleItoa(boundary_vertex_count_))) {
    return false;
  }
  if (!boundary_.empty()) {
    string base64_encoded_boundary;
    if (!EncodeFloatArrayBase64(boundary_, &base64_encoded_boundary)) {
      LOG(ERROR) << "Boundary polygon encoding failed.";
      return false;
    }

    if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kBoundary,
                                   base64_encoded_boundary)) {
      return false;
    }
  }

  if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kExtentX,
                                 std::to_string(extent_x_))) {
    return false;
  }

  if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kExtentZ,
                                 std::to_string(extent_z_))) {
    return false;
  }

  std::unique_ptr<Serializer> pose_serializer = serializer->CreateSerializer(
      DynamicDepthConst::Plane(), DynamicDepthConst::Pose());
  return pose_->Serialize(pose_serializer.get());
}

// Private methods.
bool Plane::ParsePlaneFields(const Deserializer& deserializer) {
  std::unique_ptr<Pose> pose =
      Pose::FromDeserializer(deserializer, DynamicDepthConst::Plane());
  if (pose == nullptr) {
    LOG(ERROR) << "Plane's pose could not be parsed, stopping deserialization";
    return false;
  }

  // The BoundaryVertexCount field is required only if the Boundary field is
  // populated.
  std::vector<float> boundary;
  int boundary_vertex_count = 0;
  if (deserializer.ParseFloatArrayBase64(DynamicDepthConst::Plane(), kBoundary,
                                         &boundary)) {
    if (!deserializer.ParseInt(DynamicDepthConst::Plane(), kBoundaryVertexCount,
                               &boundary_vertex_count)) {
      return false;
    }
  }

  double extent_x = -1;
  deserializer.ParseDouble(DynamicDepthConst::Plane(), kExtentX, &extent_x);

  double extent_z = -1;
  deserializer.ParseDouble(DynamicDepthConst::Plane(), kExtentZ, &extent_z);

  pose_ = std::move(pose);
  boundary_ = boundary;
  boundary_vertex_count_ = boundary_vertex_count;
  extent_x_ = extent_x;
  extent_z_ = extent_z;

  return true;
}

}  // namespace dynamic_depth
}  // namespace photos_editing_formats