27 return Eigen::Translation3d(rigid3.translation()) * rigid3.rotation();
30 void CairoPaintSubmapSlices(
32 const std::map<::cartographer::mapping::SubmapId, SubmapSlice>& submaps,
33 cairo_t* cr, std::function<
void(
const SubmapSlice&)> draw_callback) {
34 cairo_scale(cr, scale, scale);
36 for (
auto& pair : submaps) {
37 const auto& submap_slice = pair.second;
38 if (submap_slice.surface ==
nullptr) {
41 const Eigen::Matrix4d homo =
42 ToEigen(submap_slice.pose * submap_slice.slice_pose).matrix();
45 cairo_matrix_t matrix;
46 cairo_matrix_init(&matrix, homo(1, 0), homo(0, 0), -homo(1, 1), -homo(0, 1),
47 homo(0, 3), -homo(1, 3));
48 cairo_transform(cr, &matrix);
50 const double submap_resolution = submap_slice.resolution;
51 cairo_scale(cr, submap_resolution, submap_resolution);
55 draw_callback(submap_slice);
63 const std::map<::cartographer::mapping::SubmapId, SubmapSlice>& submaps,
64 const double resolution) {
65 Eigen::AlignedBox2f bounding_box;
70 const auto update_bounding_box = [&bounding_box, &cr](
double x,
double y) {
71 cairo_user_to_device(cr.get(), &x, &y);
72 bounding_box.extend(Eigen::Vector2f(x, y));
75 CairoPaintSubmapSlices(
76 1. / resolution, submaps, cr.get(),
77 [&update_bounding_box](
const SubmapSlice& submap_slice) {
78 update_bounding_box(0, 0);
79 update_bounding_box(submap_slice.width, 0);
80 update_bounding_box(0, submap_slice.height);
81 update_bounding_box(submap_slice.width, submap_slice.height);
85 const int kPaddingPixel = 5;
86 const Eigen::Array2i size(
87 std::ceil(bounding_box.sizes().x()) + 2 * kPaddingPixel,
88 std::ceil(bounding_box.sizes().y()) + 2 * kPaddingPixel);
89 const Eigen::Array2f origin(-bounding_box.min().x() + kPaddingPixel,
90 -bounding_box.min().y() + kPaddingPixel);
93 cairo_image_surface_create(
kCairoFormat, size.x(), size.y()));
96 cairo_set_source_rgba(cr.get(), 0.5, 0.0, 0.0, 1.);
97 cairo_paint(cr.get());
98 cairo_translate(cr.get(), origin.x(), origin.y());
99 CairoPaintSubmapSlices(1. / resolution, submaps, cr.get(),
101 cairo_set_source_surface(
102 cr.get(), submap_slice.surface.get(), 0., 0.);
103 cairo_paint(cr.get());
105 cairo_surface_flush(surface.get());
112 const ::cartographer::mapping::proto::Submap& proto,
114 ::cartographer::mapping::proto::SubmapQuery::Response response;
116 if (proto.has_submap_3d()) {
118 local_pose = submap.local_pose();
119 submap.ToResponseProto(global_submap_pose, &response);
122 local_pose = submap.local_pose();
123 submap.ToResponseProto(global_submap_pose, &response);
125 submap_slice->
pose = global_submap_pose;
127 auto& texture_proto = response.textures(0);
129 texture_proto.cells(), texture_proto.width(), texture_proto.height());
130 submap_slice->
width = texture_proto.width();
131 submap_slice->
height = texture_proto.height();
132 submap_slice->
resolution = texture_proto.resolution();
137 texture_proto.height(), &submap_slice->
cairo_data);
141 const int width,
const int height) {
145 const int num_pixels = width * height;
146 CHECK_EQ(cells.size(), 2 * num_pixels);
148 pixels.
alpha.reserve(num_pixels);
149 for (
int i = 0; i < height; ++i) {
150 for (
int j = 0; j < width; ++j) {
151 pixels.
intensity.push_back(cells[(i * width + j) * 2]);
152 pixels.
alpha.push_back(cells[(i * width + j) * 2 + 1]);
159 const std::vector<char>& alpha,
160 const int width,
const int height,
161 std::vector<uint32_t>*
const cairo_data) {
162 CHECK(cairo_data->empty());
166 const int expected_stride = 4 * width;
167 CHECK_EQ(expected_stride, cairo_format_stride_for_width(
kCairoFormat, width));
168 for (
size_t i = 0; i < intensity.size(); ++i) {
171 const uint8_t intensity_value = intensity.at(i);
172 const uint8_t alpha_value = alpha.at(i);
173 const uint8_t observed =
174 (intensity_value == 0 && alpha_value == 0) ? 0 : 255;
175 cairo_data->push_back((alpha_value << 24) | (intensity_value << 16) |
176 (observed << 8) | 0);
180 reinterpret_cast<unsigned char*>(cairo_data->data()),
kCairoFormat, width,
181 height, expected_stride));
182 CHECK_EQ(cairo_surface_status(surface.get()), CAIRO_STATUS_SUCCESS)
183 << cairo_status_to_string(cairo_surface_status(surface.get()));
std::vector< char > alpha
::cartographer::transform::Rigid3d pose
UniqueCairoSurfacePtr MakeUniqueCairoSurfacePtr(cairo_surface_t *surface)
PaintSubmapSlicesResult PaintSubmapSlices(const std::map<::cartographer::mapping::SubmapId, SubmapSlice > &submaps, const double resolution)
std::vector< uint32_t > cairo_data
constexpr cairo_format_t kCairoFormat
::cartographer::transform::Rigid3d slice_pose
void FillSubmapSlice(const ::cartographer::transform::Rigid3d &global_submap_pose, const ::cartographer::mapping::proto::Submap &proto, SubmapSlice *const submap_slice)
UniqueCairoSurfacePtr DrawTexture(const std::vector< char > &intensity, const std::vector< char > &alpha, const int width, const int height, std::vector< uint32_t > *const cairo_data)
void FastGunzipString(const std::string &compressed, std::string *decompressed)
::cartographer::io::UniqueCairoSurfacePtr surface
UniqueCairoPtr MakeUniqueCairoPtr(cairo_t *surface)
std::vector< char > intensity
SubmapTexture::Pixels UnpackTextureData(const std::string &compressed_cells, const int width, const int height)
std::unique_ptr< cairo_surface_t, void(*)(cairo_surface_t *)> UniqueCairoSurfacePtr