Sematic-Cartographer/cartographer-master/cartographer/mapping/internal/2d/ray_to_pixel_mask.cc

708 lines
26 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright 2016 The Cartographer Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cartographer/mapping/internal/2d/ray_to_pixel_mask.h"
#include "Eigen/Dense"
int cnew[4000000]={0};
namespace cartographer {
namespace mapping {
namespace {
bool isEqual(const Eigen::Array2i& lhs, const Eigen::Array2i& rhs) {
return ((lhs - rhs).matrix().lpNorm<1>() == 0);
}
} // namespace
// Compute all pixels that contain some part of the line segment connecting
// 'scaled_begin' and 'scaled_end'. 'scaled_begin' and 'scaled_end' are scaled
// by 'subpixel_scale'. 'scaled_begin' and 'scaled_end' are expected to be
// greater than zero. Return values are in pixels and not scaled.
std::vector<Eigen::Array2i> RayToPixelMask(const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale) {
// For simplicity, we order 'scaled_begin' and 'scaled_end' by their x
// coordinate.
if (scaled_begin.x() > scaled_end.x()) {
return RayToPixelMask(scaled_end, scaled_begin, subpixel_scale);
}
CHECK_GE(scaled_begin.x(), 0);
CHECK_GE(scaled_begin.y(), 0);
CHECK_GE(scaled_end.y(), 0);
std::vector<Eigen::Array2i> pixel_mask;
// Special case: We have to draw a vertical line in full pixels, as
// 'scaled_begin' and 'scaled_end' have the same full pixel x coordinate.
if (scaled_begin.x() / subpixel_scale == scaled_end.x() / subpixel_scale) {
Eigen::Array2i current(
scaled_begin.x() / subpixel_scale,
std::min(scaled_begin.y(), scaled_end.y()) / subpixel_scale);
pixel_mask.push_back(current);
const int end_y =
std::max(scaled_begin.y(), scaled_end.y()) / subpixel_scale;
for (; current.y() <= end_y; ++current.y()) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
return pixel_mask;
}
const int64 dx = scaled_end.x() - scaled_begin.x();
const int64 dy = scaled_end.y() - scaled_begin.y();
const int64 denominator = 2 * subpixel_scale * dx;
// The current full pixel coordinates. We scaled_begin at 'scaled_begin'.
Eigen::Array2i current = scaled_begin / subpixel_scale;
pixel_mask.push_back(current);
// To represent subpixel centers, we use a factor of 2 * 'subpixel_scale' in
// the denominator.
// +-+-+-+ -- 1 = (2 * subpixel_scale) / (2 * subpixel_scale)
// | | | |
// +-+-+-+
// | | | |
// +-+-+-+ -- top edge of first subpixel = 2 / (2 * subpixel_scale)
// | | | | -- center of first subpixel = 1 / (2 * subpixel_scale)
// +-+-+-+ -- 0 = 0 / (2 * subpixel_scale)
// The center of the subpixel part of 'scaled_begin.y()' assuming the
// 'denominator', i.e., sub_y / denominator is in (0, 1).
int64 sub_y = (2 * (scaled_begin.y() % subpixel_scale) + 1) * dx;
// The distance from the from 'scaled_begin' to the right pixel border, to be
// divided by 2 * 'subpixel_scale'.
const int first_pixel =
2 * subpixel_scale - 2 * (scaled_begin.x() % subpixel_scale) - 1;
// The same from the left pixel border to 'scaled_end'.
const int last_pixel = 2 * (scaled_end.x() % subpixel_scale) + 1;
// The full pixel x coordinate of 'scaled_end'.
const int end_x = std::max(scaled_begin.x(), scaled_end.x()) / subpixel_scale;
// Move from 'scaled_begin' to the next pixel border to the right.
sub_y += dy * first_pixel;
if (dy > 0) {
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == denominator) {
sub_y -= denominator;
++current.y();
}
if (current.x() == end_x) {
break;
}
// Move from one pixel border to the next.
sub_y += dy * 2 * subpixel_scale;
}
// Move from the pixel border on the right to 'scaled_end'.
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, denominator);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
return pixel_mask;
}
// Same for lines non-ascending in y coordinates.
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == 0) {
sub_y += denominator;
--current.y();
}
if (current.x() == end_x) {
break;
}
sub_y += dy * 2 * subpixel_scale;
}
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, 0);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
return pixel_mask;
}
Eigen::Affine3d ToEigen(const ::cartographer::transform::Rigid3d& rigid3) {
return Eigen::Translation3d(rigid3.translation()) * rigid3.rotation();
}
/**
* @brief 根据local_pose将miss点转换成全局坐标
*
* @param[in]
* @param[in]
* @param[in]
* @param[in]
* @param[in]
*/
std::vector<Eigen::Array2i> LocalToMap(const Eigen::Array2i& pixel,
const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale,
int flag,
const transform::Rigid3d local_pose_){
int o_x=1000;
int o_y=1000;
int xm;
int ym;
int xm_begin;
int ym_begin;
int xm_end;
int ym_end;
const Eigen::Matrix4d homo =ToEigen(local_pose_).matrix();
if (flag==0){
if (scaled_begin.y()/1000>150){
xm=-(pixel).y()+20*homo(0,3)+(o_x+200);
ym=(pixel).x()-20*homo(1,3)+(o_y-200);
xm_begin=-scaled_begin.y()/1000+20*homo(0,3)+(o_x+200);
ym_begin=scaled_begin.x()/1000-20*homo(1,3)+(o_y-200);
xm_end=-scaled_begin.y()/1000+20*homo(0,3)+(o_x+200);
ym_end=scaled_begin.x()/1000-20*homo(1,3)+(o_y-200);
}else{
xm=-(pixel).y()+20*homo(0,3)+(o_x+100);
ym=(pixel).x()-20*homo(1,3)+(o_y-100);
xm_begin=-scaled_begin.y()/1000+20*homo(0,3)+(o_x+100);
ym_begin=scaled_begin.x()/1000-20*homo(1,3)+(o_y-100);
xm_end=-scaled_end.y()/1000+20*homo(0,3)+(o_x+100);
ym_end=scaled_end.x()/1000-20*homo(1,3)+(o_y-100);
}
}else{
if (scaled_end.y()/1000>150){
xm=-(pixel).y()+20*homo(0,3)+(o_x+200);
ym=(pixel).x()-20*homo(1,3)+(o_y-200);
xm_begin=-scaled_end.y()/1000+20*homo(0,3)+(o_x+200);
ym_begin=scaled_end.x()/1000-20*homo(1,3)+(o_y-200);
xm_end=-scaled_begin.y()/1000+20*homo(0,3)+(o_x+200);
ym_end=scaled_begin.x()/1000-20*homo(1,3)+(o_y-200);
}else{
xm=-(pixel).y()+20*homo(0,3)+(o_x+100);
ym=(pixel).x()-20*homo(1,3)+(o_y-100);
xm_begin=-scaled_end.y()/1000+20*homo(0,3)+(o_x+100);
ym_begin=scaled_end.x()/1000-20*homo(1,3)+(o_y-100);
xm_end=-scaled_begin.y()/1000+20*homo(0,3)+(o_x+100);
ym_end=scaled_begin.x()/1000-20*homo(1,3)+(o_y-100);
// LOG(INFO)<<"wyk--begin is:"<<xm_begin<<" ni "<<ym_begin;
// LOG(INFO)<<"wyk--end is:"<<xm_end<<" end "<<ym_end;
// LOG(INFO)<<"wyk--xiaowuti is:"<<xm<<" "<<ym;
}
}
std::vector<Eigen::Array2i> map_position;
map_position.push_back(Eigen::Array2i(xm_begin, ym_begin));
map_position.push_back(Eigen::Array2i(xm,ym));
map_position.push_back(Eigen::Array2i(xm_end,ym_end));
return map_position;
}
/**
* @brief 非摄像头视域或摄像头视域超过两米范围的小物体不更新即该范围内的删去miss点
*
*/
std::vector<Eigen::Array2i> ProcessPixelMask(std::vector<Eigen::Array2i> pixel_mask,
const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale,
int flag,
const uint8 intensities,
const transform::Rigid3d local_pose_){
int xm;
int ym;
int xm_begin=LocalToMap(scaled_begin,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[0].x();
int ym_begin=LocalToMap(scaled_begin,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[0].y();
int xm_end;
int ym_end;
for(std::vector<Eigen::Array2i>::iterator pixel=pixel_mask.begin();pixel!=pixel_mask.end(); ){
xm=LocalToMap(*pixel,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[1].x();
ym=LocalToMap(*pixel,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[1].y();
if(0<ym*2000+xm && ym*2000+xm<4000000){
//标志是否删去miss 0代表没有删去
int flag_miss=0;
//以小物体为中心2*2搜索
for (int i=-3;i<=3;i++){
for (int j=-3;j<=3;j++){
if (cnew[(ym+j)*2000+xm+i]==115 || cnew[(ym+j)*2000+xm+i]==117 || cnew[(ym+j)*2000+xm+i]==121 || cnew[(ym+j)*2000+xm+i]==200 ||
cnew[(ym+j)*2000+xm+i]==201 || cnew[(ym+j)*2000+xm+i]==205 || cnew[(ym+j)*2000+xm+i]==153 ){
//如果在非摄像头视域
if (intensities == 0) {
pixel=pixel_mask.erase(pixel);
//probability_grid->ApplyLookupTable(*pixel, hit_table);
flag_miss=1;
break;
//在摄像头视域
}else{
//超过两米 小物体不更新
if ((xm-xm_begin)*(xm-xm_begin)+(ym-ym_begin)*(ym-ym_begin)>1600){
pixel=pixel_mask.erase(pixel);
flag_miss=1;
break;
}
}
}
}
if (flag_miss==1)
break;
}
if (flag_miss == 0)
++pixel;
}
else{
LOG(INFO)<<"frame erro:"<<xm<<" "<<ym;
}
}
return pixel_mask;
}
std::vector<Eigen::Array2i> ProcessPixelMaskHit(std::vector<Eigen::Array2i> pixel_mask,
const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale,
int flag,
const uint8 intensities,
const transform::Rigid3d local_pose_,
const std::vector<uint16>& hit_table,
cartographer::mapping::ProbabilityGrid* probability_grid){
int xm;
int ym;
int xm_begin=LocalToMap(scaled_begin,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[0].x();
int ym_begin=LocalToMap(scaled_begin,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[0].y();
int xm_end;
int ym_end;
for(std::vector<Eigen::Array2i>::iterator pixel=pixel_mask.begin();pixel!=pixel_mask.end(); ){
xm=LocalToMap(*pixel,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[1].x();
ym=LocalToMap(*pixel,scaled_begin,scaled_end,subpixel_scale,flag,local_pose_)[1].y();
if(0<ym*2000+xm && ym*2000+xm<4000000){
//标志是否删去miss 0代表没有删去
int flag_miss=0;
//以小物体为中心2*2搜索
for (int i=-1;i<=1;i++){
for (int j=-1;j<=1;j++){
if (cnew[(ym+j)*2000+xm+i]>100 ){
//如果在非摄像头视域
if (intensities == 0) {
//pixel=pixel_mask.erase(pixel);
probability_grid->ApplyLookupTable(*pixel, hit_table);
// for(std::vector<Eigen::Array2i>::iterator pixel_hit=pixel_mask.begin();pixel!=pixel_mask.end(); ){
// probability_grid->ApplyLookupTable(*pixel_hit, hit_table);
// }
++pixel;
flag_miss=1;
break;
}
}
}
if (flag_miss==1)
break;
}
if (flag_miss == 0)
++pixel;
}
else{
LOG(INFO)<<"frame erro:"<<xm<<" "<<ym;
}
}
return pixel_mask;
}
std::vector<Eigen::Array2i> RayToPixelMaskVisualNew(const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale,
const uint8 intensities,
const transform::Rigid3d local_pose_,
int flag,
const std::vector<uint16>& hit_table,
cartographer::mapping::ProbabilityGrid* probability_grid) {
if (scaled_begin.x() > scaled_end.x()) {
//flag=1代表end和begin交换
flag=1;
return RayToPixelMaskVisualNew(scaled_end, scaled_begin, subpixel_scale,intensities,local_pose_,flag,hit_table,
probability_grid);
}
CHECK_GE(scaled_begin.x(), 0);
CHECK_GE(scaled_begin.y(), 0);
CHECK_GE(scaled_end.y(), 0);
std::vector<Eigen::Array2i> pixel_mask;
// Special case: We have to draw a vertical line in full pixels, as
// 'scaled_begin' and 'scaled_end' have the same full pixel x coordinate.
if (scaled_begin.x() / subpixel_scale == scaled_end.x() / subpixel_scale) {
Eigen::Array2i current(
scaled_begin.x() / subpixel_scale,
std::min(scaled_begin.y(), scaled_end.y()) / subpixel_scale);
pixel_mask.push_back(current);
const int end_y =
std::max(scaled_begin.y(), scaled_end.y()) / subpixel_scale;
for (; current.y() <= end_y; ++current.y()) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
const Eigen::Matrix4d homo =ToEigen(local_pose_).matrix();
// jzq新加 标记摄像头范围
if(intensities != 0) {
if ((scaled_end.x()/1000-scaled_begin.x()/1000)*(scaled_end.x()/1000-scaled_begin.x()/1000)
+(scaled_end.y()/1000-scaled_begin.y()/1000)*(scaled_end.y()/1000-scaled_begin.y()/1000)<576){
for(Eigen::Array2i pixel : pixel_mask) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
else{
Eigen::Array2i ori_begin;
if(flag == 1)
ori_begin = scaled_end;
else
ori_begin = scaled_begin;
for(Eigen::Array2i pixel : pixel_mask){
if ((pixel.x()-ori_begin.x()/1000)*(pixel.x()-ori_begin.x()/1000)
+(pixel.y()-ori_begin.y()/1000)*(pixel.y()-ori_begin.y()/1000)<576) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
}
}
return pixel_mask;
//return ProcessPixelMask(pixel_mask,scaled_begin,scaled_end,subpixel_scale,flag,intensities,local_pose_);
}
const int64 dx = scaled_end.x() - scaled_begin.x();
const int64 dy = scaled_end.y() - scaled_begin.y();
const int64 denominator = 2 * subpixel_scale * dx;
// The current full pixel coordinates. We scaled_begin at 'scaled_begin'.
Eigen::Array2i current = scaled_begin / subpixel_scale;
pixel_mask.push_back(current);
// To represent subpixel centers, we use a factor of 2 * 'subpixel_scale' in
// the denominator.
// +-+-+-+ -- 1 = (2 * subpixel_scale) / (2 * subpixel_scale)
// | | | |
// +-+-+-+
// | | | |
// +-+-+-+ -- top edge of first subpixel = 2 / (2 * subpixel_scale)
// | | | | -- center of first subpixel = 1 / (2 * subpixel_scale)
// +-+-+-+ -- 0 = 0 / (2 * subpixel_scale)
// The center of the subpixel part of 'scaled_begin.y()' assuming the
// 'denominator', i.e., sub_y / denominator is in (0, 1).
int64 sub_y = (2 * (scaled_begin.y() % subpixel_scale) + 1) * dx;
// The distance from the from 'scaled_begin' to the right pixel border, to be
// divided by 2 * 'subpixel_scale'.
const int first_pixel =
2 * subpixel_scale - 2 * (scaled_begin.x() % subpixel_scale) - 1;
// The same from the left pixel border to 'scaled_end'.
const int last_pixel = 2 * (scaled_end.x() % subpixel_scale) + 1;
// The full pixel x coordinate of 'scaled_end'.
const int end_x = std::max(scaled_begin.x(), scaled_end.x()) / subpixel_scale;
// Move from 'scaled_begin' to the next pixel border to the right.
sub_y += dy * first_pixel;
if (dy > 0) {
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == denominator) {
sub_y -= denominator;
++current.y();
}
if (current.x() == end_x) {
break;
}
// Move from one pixel border to the next.
sub_y += dy * 2 * subpixel_scale;
}
// Move from the pixel border on the right to 'scaled_end'.
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, denominator);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
// jzq新加 标记摄像头范围
if(intensities != 0) {
if ((scaled_end.x()/1000-scaled_begin.x()/1000)*(scaled_end.x()/1000-scaled_begin.x()/1000)
+(scaled_end.y()/1000-scaled_begin.y()/1000)*(scaled_end.y()/1000-scaled_begin.y()/1000)<576){
for(Eigen::Array2i pixel : pixel_mask) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
else{
Eigen::Array2i ori_begin;
if(flag == 1)
ori_begin = scaled_end;
else
ori_begin = scaled_begin;
for(Eigen::Array2i pixel : pixel_mask){
if ((pixel.x()-ori_begin.x()/1000)*(pixel.x()-ori_begin.x()/1000)
+(pixel.y()-ori_begin.y()/1000)*(pixel.y()-ori_begin.y()/1000)<576) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
}
}
return pixel_mask;
//可以不针对pixel_mask进行遍历当pushback一个miss点就对其判断 --王煜坤
// return ProcessPixelMask(pixel_mask,scaled_begin,scaled_end,subpixel_scale,flag,intensities,local_pose_);
}
// Same for lines non-ascending in y coordinates.
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == 0) {
sub_y += denominator;
--current.y();
}
if (current.x() == end_x) {
break;
}
sub_y += dy * 2 * subpixel_scale;
}
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, 0);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
// jzq新加 标记摄像头范围
if(intensities != 0) {
if ((scaled_end.x()/1000-scaled_begin.x()/1000)*(scaled_end.x()/1000-scaled_begin.x()/1000)
+(scaled_end.y()/1000-scaled_begin.y()/1000)*(scaled_end.y()/1000-scaled_begin.y()/1000)<576){
for(Eigen::Array2i pixel : pixel_mask) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
else{
Eigen::Array2i ori_begin;
if(flag == 1)
ori_begin = scaled_end;
else
ori_begin = scaled_begin;
for(Eigen::Array2i pixel : pixel_mask){
if ((pixel.x()-ori_begin.x()/1000)*(pixel.x()-ori_begin.x()/1000)
+(pixel.y()-ori_begin.y()/1000)*(pixel.y()-ori_begin.y()/1000)<576) {
probability_grid->mutable_semantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
probability_grid->mutable_scanSemantics_observer()->at(probability_grid->ToFlatIndex(pixel)) = 1;
}
}
}
}
return pixel_mask;
// return ProcessPixelMask(pixel_mask,scaled_begin,scaled_end,subpixel_scale,flag,intensities,local_pose_);
}
std::vector<Eigen::Array2i> RayToPixelMaskVisual(const Eigen::Array2i& scaled_begin,
const Eigen::Array2i& scaled_end,
int subpixel_scale,
const uint8 intensities) {
// For simplicity, we order 'scaled_begin' and 'scaled_end' by their x
// coordinate.
if (intensities != 0){
if (scaled_begin.x() > scaled_end.x()) {
return RayToPixelMask(scaled_end, scaled_begin, subpixel_scale);
}
CHECK_GE(scaled_begin.x(), 0);
CHECK_GE(scaled_begin.y(), 0);
CHECK_GE(scaled_end.y(), 0);
std::vector<Eigen::Array2i> pixel_mask;
// Special case: We have to draw a vertical line in full pixels, as
// 'scaled_begin' and 'scaled_end' have the same full pixel x coordinate.
if (scaled_begin.x() / subpixel_scale == scaled_end.x() / subpixel_scale) {
Eigen::Array2i current(
scaled_begin.x() / subpixel_scale,
std::min(scaled_begin.y(), scaled_end.y()) / subpixel_scale);
pixel_mask.push_back(current);
const int end_y =
std::max(scaled_begin.y(), scaled_end.y()) / subpixel_scale;
for (; current.y() <= end_y; ++current.y()) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
return pixel_mask;
}
const int64 dx = scaled_end.x() - scaled_begin.x();
const int64 dy = scaled_end.y() - scaled_begin.y();
const int64 denominator = 2 * subpixel_scale * dx;
// The current full pixel coordinates. We scaled_begin at 'scaled_begin'.
Eigen::Array2i current = scaled_begin / subpixel_scale;
pixel_mask.push_back(current);
// To represent subpixel centers, we use a factor of 2 * 'subpixel_scale' in
// the denominator.
// +-+-+-+ -- 1 = (2 * subpixel_scale) / (2 * subpixel_scale)
// | | | |
// +-+-+-+
// | | | |
// +-+-+-+ -- top edge of first subpixel = 2 / (2 * subpixel_scale)
// | | | | -- center of first subpixel = 1 / (2 * subpixel_scale)
// +-+-+-+ -- 0 = 0 / (2 * subpixel_scale)
// The center of the subpixel part of 'scaled_begin.y()' assuming the
// 'denominator', i.e., sub_y / denominator is in (0, 1).
int64 sub_y = (2 * (scaled_begin.y() % subpixel_scale) + 1) * dx;
// The distance from the from 'scaled_begin' to the right pixel border, to be
// divided by 2 * 'subpixel_scale'.
const int first_pixel =
2 * subpixel_scale - 2 * (scaled_begin.x() % subpixel_scale) - 1;
// The same from the left pixel border to 'scaled_end'.
const int last_pixel = 2 * (scaled_end.x() % subpixel_scale) + 1;
// The full pixel x coordinate of 'scaled_end'.
const int end_x = std::max(scaled_begin.x(), scaled_end.x()) / subpixel_scale;
// Move from 'scaled_begin' to the next pixel border to the right.
sub_y += dy * first_pixel;
if (dy > 0) {
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == denominator) {
sub_y -= denominator;
++current.y();
}
if (current.x() == end_x) {
break;
}
// Move from one pixel border to the next.
sub_y += dy * 2 * subpixel_scale;
}
// Move from the pixel border on the right to 'scaled_end'.
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y > denominator) {
sub_y -= denominator;
++current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, denominator);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
return pixel_mask;
}
// Same for lines non-ascending in y coordinates.
while (true) {
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
++current.x();
if (sub_y == 0) {
sub_y += denominator;
--current.y();
}
if (current.x() == end_x) {
break;
}
sub_y += dy * 2 * subpixel_scale;
}
sub_y += dy * last_pixel;
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
while (sub_y < 0) {
sub_y += denominator;
--current.y();
if (!isEqual(pixel_mask.back(), current)) pixel_mask.push_back(current);
}
CHECK_NE(sub_y, 0);
CHECK_EQ(current.y(), scaled_end.y() / subpixel_scale);
return pixel_mask;
}else {
return std::vector<Eigen::Array2i> ();
}
}
} // namespace mapping
} // namespace cartographer