outline2_rasterizer.cpp
Go to the documentation of this file.
00001 #include <wrap/qt/outline2_rasterizer.h>
00002 #include <wrap/qt/col_qt_convert.h>
00003 #include "stdio.h"
00004 #include "math.h"
00005 #include <vcg/space/color4.h>
00006 #include <wrap/qt/col_qt_convert.h>
00007 
00008 using namespace vcg;
00009 using namespace std;
00010 
00011 void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
00012                                  float scale,
00013                                  int rast_i,
00014                                  int rotationNum,
00015                                  int cellSize)
00016 {
00017 
00018     float rotRad = M_PI*2.0f*float(rast_i) / float(rotationNum);
00019 
00020     //get polygon's BB, rotated according to the input parameter
00021     Box2f bb;
00022     vector<Point2f> pointvec = poly.getPoints();
00023     for(size_t i=0;i<pointvec.size();++i) {
00024         Point2f pp=pointvec[i];
00025         pp.Rotate(rotRad);
00026         bb.Add(pp);
00027     }
00028 
00030     //we'll make so that sizeX and sizeY are multiples of CELLSIZE:
00031     //1) we round it to the next integer
00032     //2) add the number which makes it a multiple of CELLSIZE (only if it's not multiple already)
00033     int sizeX = (int)ceil(bb.DimX()*scale);
00034     int sizeY = (int)ceil(bb.DimY()*scale);
00035     if (sizeX % cellSize != 0) sizeX += (cellSize - ((int)ceil(bb.DimX()*scale) % cellSize));
00036     if (sizeY % cellSize != 0) sizeY += (cellSize - ((int)ceil(bb.DimY()*scale) % cellSize));
00037 
00038     //security measure: add a dummy column/row thus making the image bigger, and crop it afterwards
00039     //(if it hasn't been filled with anything)
00040     //this is due to the fact that if we have a rectangle which has bb 39.xxx wide, then it won't fit in a 40px wide QImage!! The right side will go outside of the image!! :/
00041     sizeX+=cellSize;
00042     sizeY+=cellSize;
00043 
00044     QImage img(sizeX,sizeY,QImage::Format_RGB32);
00045     QColor backgroundColor(Qt::transparent);
00046     img.fill(backgroundColor);
00047 
00049     QPainter painter;
00050     painter.begin(&img);
00051     QBrush br;
00052     br.setStyle(Qt::SolidPattern);
00053     QPen qp;
00054     qp.setWidthF(0);
00055     qp.setColor(Qt::yellow);
00056     painter.setBrush(br);
00057     painter.setPen(qp);
00058 
00059     painter.resetTransform();
00060     painter.translate(QPointF(-(bb.min.X()*scale) , -(bb.min.Y()*scale) ));
00061     painter.rotate(math::ToDeg(rotRad));
00062     painter.scale(scale,scale);
00063 
00064     //create the polygon to print it
00065     QVector<QPointF> points;
00066     vector<Point2f> newpoints = poly.getPoints();
00067     for (size_t i = 0; i < newpoints.size(); i++) {
00068         points.push_back(QPointF(newpoints[i].X(), newpoints[i].Y()));
00069     }
00070     painter.drawPolygon(QPolygonF(points));
00071 
00072 
00073     //CROPPING: it is enough to check for the (end - cellSize - 1)th row/col of pixels, if they're all black we can eliminate the last 8columns/rows of pixels
00074     bool cropX = true;
00075     bool cropY = true;
00076     for (int j=0; j<img.height(); j++) {
00077         const uchar* line = img.scanLine(j);
00078         if (j == img.height() - (cellSize - 1) - 1  ) {
00079             for (int x=0; x<img.width(); x++) {
00080                 if (((QRgb*)line)[x] != backgroundColor.rgb()) {
00081                     cropY = false;
00082                     break;
00083                 }
00084             }
00085         }
00086         else {
00087             if (((QRgb*)line)[img.width() - (cellSize - 1) - 1] != backgroundColor.rgb()) {
00088                 cropX = false;
00089                 break;
00090             }
00091         }
00092         if (!cropY) break;
00093     }
00094 
00095 
00096     if (cropX || cropY) {
00097         painter.end();
00098         img = img.copy(0, 0, img.width() - cellSize * cropX, img.height() - cellSize * cropY);
00099         painter.begin(&img);
00100         painter.setBrush(br);
00101         painter.setPen(qp);
00102     }
00103 
00104 
00105     //draw the poly for the second time, this time it is centered to the image
00106     img.fill(backgroundColor);
00107 
00108     painter.resetTransform();
00109     painter.translate(QPointF(-(bb.min.X()*scale) + (img.width() - ceil(bb.DimX()*scale))/2.0, -(bb.min.Y()*scale) + (img.height() - ceil(bb.DimY()*scale))/2.0));
00110     painter.rotate(math::ToDeg(rotRad));
00111     painter.scale(scale,scale);
00112     //create the polygon to print it
00113     QVector<QPointF> points2;
00114     vector<Point2f> newpoints2 = poly.getPoints();
00115     for (size_t i = 0; i < newpoints2.size(); i++) {
00116         points2.push_back(QPointF(newpoints2[i].X(), newpoints2[i].Y()));
00117     }
00118     painter.drawPolygon(QPolygonF(points2));
00119 
00120     //create the first grid, which will then be rotated 3 times.
00121     //we will reuse this grid to create the rasterizations corresponding to this one rotated by 90/180/270°
00122     vector<vector<int> > tetrisGrid;
00123     QRgb yellow = QColor(Qt::yellow).rgb();
00124     int gridWidth = img.width() / cellSize;
00125     int gridHeight = img.height() / cellSize;
00126     int x = 0;
00127     tetrisGrid.resize(gridHeight);
00128     for (int k = 0; k < gridHeight; k++) {
00129         tetrisGrid[k].resize(gridWidth, 0);
00130     }
00131     for (int y = 0; y < img.height(); y++) {
00132         int gridY = y / cellSize;
00133         const uchar* line = img.scanLine(y);
00134         x = 0;
00135         int gridX = 0;
00136         while(x < img.width()) {
00137             gridX = x/cellSize;
00138             if (tetrisGrid[gridY][gridX] == 1) {
00139                 x+= cellSize - (x % cellSize); //align with the next x
00140                 continue;
00141             }
00142             if (((QRgb*)line)[x] == yellow) tetrisGrid[gridY][gridX] = 1;
00143             ++x;
00144         }
00145     }
00146 
00147     //create the 4 rasterizations (one every 90°) using the discrete representation grid we've just created
00148     int rotationOffset = rotationNum/4;
00149     for (int j = 0; j < 4; j++) {
00150         if (j != 0)  {
00151             tetrisGrid = rotateGridCWise(tetrisGrid);
00152         }
00153         //add the grid to the poly's vector of grids
00154         poly.getGrids(rast_i + rotationOffset*j) = tetrisGrid;
00155 
00156         //initializes bottom/left/deltaX/deltaY vectors of the poly, for the current rasterization
00157         poly.initFromGrid(rast_i + rotationOffset*j);
00158     }
00159 
00160     painter.end();
00161 }
00162 
00163 // rotates the grid 90 degree clockwise (by simple swap)
00164 // used to lower the cost of rasterization.
00165 vector<vector<int> > QtOutline2Rasterizer::rotateGridCWise(vector< vector<int> >& inGrid) {
00166     vector<vector<int> > outGrid(inGrid[0].size());
00167     for (size_t i = 0; i < inGrid[0].size(); i++) {
00168         outGrid[i].reserve(inGrid.size());
00169         for (size_t j = 0; j < inGrid.size(); j++) {
00170             outGrid[i].push_back(inGrid[inGrid.size() - j - 1][i]);
00171         }
00172     }
00173     return outGrid;
00174 }


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:33:34