1 #include "dynamic_depth/plane.h"
2
3 #include "android-base/logging.h"
4 #include "dynamic_depth/const.h"
5 #include "strings/numbers.h"
6 #include "xmpmeta/base64.h"
7
8 using ::dynamic_depth::xmpmeta::EncodeFloatArrayBase64;
9 using ::dynamic_depth::xmpmeta::xml::Deserializer;
10 using ::dynamic_depth::xmpmeta::xml::Serializer;
11
12 namespace dynamic_depth {
13 namespace {
14
15 constexpr char kBoundary[] = "Boundary";
16 constexpr char kBoundaryVertexCount[] = "BoundaryVertexCount";
17 constexpr char kExtentX[] = "ExtentX";
18 constexpr char kExtentZ[] = "ExtentZ";
19
20 constexpr char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/plane/";
21
22 } // namespace
23
24 // Private constructor.
Plane()25 Plane::Plane() {}
26
27 // Public methods.
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)28 void Plane::GetNamespaces(
29 std::unordered_map<string, string>* ns_name_href_map) {
30 if (ns_name_href_map == nullptr) {
31 LOG(ERROR) << "Namespace list is null";
32 return;
33 }
34 ns_name_href_map->emplace(DynamicDepthConst::Plane(), kNamespaceHref);
35
36 if (pose_ != nullptr) {
37 pose_->GetNamespaces(ns_name_href_map);
38 }
39 }
40
FromData(std::unique_ptr<Pose> pose,const std::vector<float> & boundary,const double extent_x,const double extent_z)41 std::unique_ptr<Plane> Plane::FromData(std::unique_ptr<Pose> pose,
42 const std::vector<float>& boundary,
43 const double extent_x,
44 const double extent_z) {
45 if (pose == nullptr) {
46 LOG(ERROR) << "The Plane's pose must be provided";
47 return nullptr;
48 }
49
50 if (boundary.size() % 2 != 0) {
51 LOG(ERROR) << "Number of vertices in the boundary polygon must be 2-tuples";
52 return nullptr;
53 }
54
55 std::unique_ptr<Plane> plane(std::unique_ptr<Plane>(new Plane())); // NOLINT
56 plane->pose_ = std::move(pose);
57 plane->boundary_vertex_count_ = boundary.size() / 2;
58 if (!boundary.empty()) {
59 plane->boundary_ = boundary;
60 }
61
62 plane->extent_x_ = extent_x;
63 plane->extent_z_ = extent_z;
64 return plane;
65 }
66
FromDeserializer(const Deserializer & parent_deserializer)67 std::unique_ptr<Plane> Plane::FromDeserializer(
68 const Deserializer& parent_deserializer) {
69 std::unique_ptr<Deserializer> deserializer =
70 parent_deserializer.CreateDeserializer(
71 DynamicDepthConst::Namespace(DynamicDepthConst::Plane()),
72 DynamicDepthConst::Plane());
73 if (deserializer == nullptr) {
74 return nullptr;
75 }
76
77 std::unique_ptr<Plane> plane(std::unique_ptr<Plane>(new Plane())); // NOLINT
78 if (!plane->ParsePlaneFields(*deserializer)) {
79 return nullptr;
80 }
81
82 return plane;
83 }
84
GetPose() const85 const Pose* Plane::GetPose() const { return pose_.get(); }
86
GetBoundary() const87 const std::vector<float>& Plane::GetBoundary() const { return boundary_; }
88
GetBoundaryVertexCount() const89 int Plane::GetBoundaryVertexCount() const { return boundary_vertex_count_; }
90
GetExtentX() const91 const double Plane::GetExtentX() const { return extent_x_; }
92
GetExtentZ() const93 const double Plane::GetExtentZ() const { return extent_z_; }
94
Serialize(Serializer * serializer) const95 bool Plane::Serialize(Serializer* serializer) const {
96 if (serializer == nullptr) {
97 LOG(ERROR) << "Serializer is null";
98 return false;
99 }
100
101 if (pose_ == nullptr) {
102 LOG(ERROR) << "Plane's pose must be present, not serializing";
103 return false;
104 }
105
106 if (!serializer->WriteProperty(
107 DynamicDepthConst::Plane(), kBoundaryVertexCount,
108 ::dynamic_depth::strings::SimpleItoa(boundary_vertex_count_))) {
109 return false;
110 }
111 if (!boundary_.empty()) {
112 string base64_encoded_boundary;
113 if (!EncodeFloatArrayBase64(boundary_, &base64_encoded_boundary)) {
114 LOG(ERROR) << "Boundary polygon encoding failed.";
115 return false;
116 }
117
118 if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kBoundary,
119 base64_encoded_boundary)) {
120 return false;
121 }
122 }
123
124 if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kExtentX,
125 std::to_string(extent_x_))) {
126 return false;
127 }
128
129 if (!serializer->WriteProperty(DynamicDepthConst::Plane(), kExtentZ,
130 std::to_string(extent_z_))) {
131 return false;
132 }
133
134 std::unique_ptr<Serializer> pose_serializer = serializer->CreateSerializer(
135 DynamicDepthConst::Plane(), DynamicDepthConst::Pose());
136 return pose_->Serialize(pose_serializer.get());
137 }
138
139 // Private methods.
ParsePlaneFields(const Deserializer & deserializer)140 bool Plane::ParsePlaneFields(const Deserializer& deserializer) {
141 std::unique_ptr<Pose> pose =
142 Pose::FromDeserializer(deserializer, DynamicDepthConst::Plane());
143 if (pose == nullptr) {
144 LOG(ERROR) << "Plane's pose could not be parsed, stopping deserialization";
145 return false;
146 }
147
148 // The BoundaryVertexCount field is required only if the Boundary field is
149 // populated.
150 std::vector<float> boundary;
151 int boundary_vertex_count = 0;
152 if (deserializer.ParseFloatArrayBase64(DynamicDepthConst::Plane(), kBoundary,
153 &boundary)) {
154 if (!deserializer.ParseInt(DynamicDepthConst::Plane(), kBoundaryVertexCount,
155 &boundary_vertex_count)) {
156 return false;
157 }
158 }
159
160 double extent_x = -1;
161 deserializer.ParseDouble(DynamicDepthConst::Plane(), kExtentX, &extent_x);
162
163 double extent_z = -1;
164 deserializer.ParseDouble(DynamicDepthConst::Plane(), kExtentZ, &extent_z);
165
166 pose_ = std::move(pose);
167 boundary_ = boundary;
168 boundary_vertex_count_ = boundary_vertex_count;
169 extent_x_ = extent_x;
170 extent_z_ = extent_z;
171
172 return true;
173 }
174
175 } // namespace dynamic_depth
176