add vcglib
This commit is contained in:
1 parent
6f6c0c8eb7
commit
af8100f851
1537 files changed
+634197
No files matched your search
@@ -0,0 +1,452 @@
|
||||
#include "Outline2ToQImage.h"
|
||||
#include <wrap/qt/col_qt_convert.h>
|
||||
using namespace vcg;
|
||||
using namespace std;
|
||||
|
||||
void Outline2Dumper::rectSetToOutline2Vec(vector< Box2f > &rectVec, vector< vector<Point2f> > &outline2Vec)
|
||||
{
|
||||
outline2Vec.clear();
|
||||
for(size_t i=0;i<rectVec.size();++i)
|
||||
{
|
||||
Box2f &b=rectVec[i];
|
||||
outline2Vec.resize(outline2Vec.size()+1);
|
||||
outline2Vec.back().push_back(b.min);
|
||||
outline2Vec.back().push_back(Point2f(b.max[0],b.min[1]));
|
||||
outline2Vec.back().push_back(b.max);
|
||||
outline2Vec.back().push_back(Point2f(b.min[0],b.max[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Outline2Dumper::multiRectSetToSingleOutline2Vec(vector< Box2f > &rectVec,
|
||||
vector<Similarity2f> &trVec, vector<int> &indVec,
|
||||
int ind, vector< vector<Point2f> > &outline2Vec,
|
||||
vector<Similarity2f> &trOutline2Vec)
|
||||
{
|
||||
outline2Vec.clear();
|
||||
trOutline2Vec.clear();
|
||||
|
||||
for(size_t i=0;i<rectVec.size();++i)
|
||||
if(indVec[i]==ind)
|
||||
{
|
||||
trOutline2Vec.push_back(trVec[i]);
|
||||
Box2f &b=rectVec[i];
|
||||
outline2Vec.resize(outline2Vec.size()+1);
|
||||
outline2Vec.back().push_back(b.min);
|
||||
outline2Vec.back().push_back(Point2f(b.max[0],b.min[1]));
|
||||
outline2Vec.back().push_back(b.max);
|
||||
outline2Vec.back().push_back(Point2f(b.min[0],b.max[1]));
|
||||
}
|
||||
}
|
||||
|
||||
void Outline2Dumper::multiOutline2VecToSingleOutline2Vec(const std::vector< std::vector<Point2f> > &multiPolyVec,
|
||||
const std::vector<Similarity2f> &multiTrVec,
|
||||
const std::vector<int> &indVec, int ind,
|
||||
std::vector< std::vector<Point2f> > &singlePolyVec,
|
||||
std::vector<Similarity2f> &singleTrVec)
|
||||
{
|
||||
singlePolyVec.clear();
|
||||
singleTrVec.clear();
|
||||
|
||||
for(size_t i=0;i<multiPolyVec.size();++i)
|
||||
if(indVec[i]==ind)
|
||||
{
|
||||
singleTrVec.push_back(multiTrVec[i]);
|
||||
singlePolyVec.resize(singlePolyVec.size()+1);
|
||||
singlePolyVec.back()=multiPolyVec[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Outline2Dumper::dumpOutline2VecSVG(const char * imageName,
|
||||
vector< vector<Point2f> > &outline2Vec,
|
||||
vector<Similarity2f> &trVec,
|
||||
Outline2Dumper::Param &pp)
|
||||
{
|
||||
vector< vector< vector<Point2f> > > outline2VecVec(outline2Vec.size());
|
||||
for(size_t i=0;i<outline2Vec.size();++i)
|
||||
{
|
||||
outline2VecVec[i].resize(1);
|
||||
outline2VecVec[i][0]=outline2Vec[i];
|
||||
}
|
||||
dumpOutline2VecSVG(imageName,outline2VecVec,trVec,pp);
|
||||
}
|
||||
|
||||
void Outline2Dumper::dumpOutline2VecPNG(const char * imageName, vector< vector<Point2f> > &polyVec, vector<Similarity2f> &trVec, Outline2Dumper::Param &pp)
|
||||
{
|
||||
vector< vector< vector<Point2f> > > polyVecVec(polyVec.size());
|
||||
for(size_t i=0;i<polyVec.size();++i)
|
||||
{
|
||||
polyVecVec[i].resize(1);
|
||||
polyVecVec[i][0]=polyVec[i];
|
||||
}
|
||||
dumpOutline2VecPNG(imageName,polyVecVec,trVec,pp);
|
||||
}
|
||||
|
||||
void Outline2Dumper::dumpOutline2VecPNG(const char * imageName, vector< vector< vector<Point2f> > > &polyVecVec, vector<Similarity2f> &trVec, Outline2Dumper::Param &pp)
|
||||
{
|
||||
vector<string> labelVec;
|
||||
dumpOutline2VecPNG(imageName,polyVecVec,trVec,labelVec,pp);
|
||||
}
|
||||
|
||||
void Outline2Dumper::dumpOutline2VecSVG(const char * imageName, vector< vector< vector<Point2f> > > &polyVecVec, vector<Similarity2f> &trVec, Outline2Dumper::Param &pp)
|
||||
{
|
||||
vector<string> labelVec(polyVecVec.size());
|
||||
dumpOutline2VecSVG(imageName,polyVecVec,trVec,labelVec,pp);
|
||||
}
|
||||
|
||||
///this class draw a black mask fora given polygon, cenetered and scaled to fit with
|
||||
///the image size, it return the transformation to tranform back the polygon to 2D space
|
||||
void Outline2Dumper::DrawPolygonMask(const vector< vector<Point2f> > &polyVec,
|
||||
QImage &img,
|
||||
Similarity2f &ret,
|
||||
const Similarity2f &trans)
|
||||
{
|
||||
|
||||
///RASTERIZE THE POLYGON
|
||||
QPainter painter;
|
||||
painter.begin(&img);
|
||||
QBrush bb;
|
||||
bb.setStyle(Qt::SolidPattern);
|
||||
|
||||
int resolution=img.width();
|
||||
|
||||
QPen qp;
|
||||
qp.setWidthF(0);
|
||||
///find the BB
|
||||
vcg::Box2f bbox;
|
||||
for(size_t i=0;i<polyVec.size();++i)
|
||||
for(size_t j=0;j<polyVec[i].size();++j)
|
||||
{
|
||||
Point2f pp=polyVec[i][j];
|
||||
pp.Rotate(trans.rotRad);
|
||||
bbox.Add(pp);
|
||||
}
|
||||
vcg::Point2f pos=bbox.Center();
|
||||
float scaleFact=(resolution/bbox.Diag());
|
||||
|
||||
///SET THE TRANSFORMATION TO CENTER WRT BBOX
|
||||
painter.resetTransform();
|
||||
painter.translate(resolution/2,resolution/2);
|
||||
painter.rotate(math::ToDeg(trans.rotRad));
|
||||
painter.scale(scaleFact,scaleFact);
|
||||
painter.translate(-pos.V(0),-pos.V(1));
|
||||
|
||||
///SET TO RETURN BACK
|
||||
ret.rotRad=0;
|
||||
ret.sca=scaleFact;
|
||||
ret.tra[0]=-pos.V(0)*scaleFact + resolution/2;
|
||||
ret.tra[1]=-pos.V(1)*scaleFact + resolution/2;
|
||||
|
||||
///DRAW THE POLYGON
|
||||
QPainterPath QPP;
|
||||
for(size_t i=0;i<polyVec.size();++i)
|
||||
{
|
||||
QVector<QPointF> ppQ;
|
||||
for(size_t j=0;j<polyVec[i].size();++j)
|
||||
{
|
||||
Point2f pp=polyVec[i][j];
|
||||
//pp.Rotate(trans.rotRad);
|
||||
ppQ.push_back(QPointF(pp[0],pp[1]));
|
||||
}
|
||||
ppQ.push_back(QPointF(polyVec[i][0][0],polyVec[i][0][1]));
|
||||
QPP.addPolygon(QPolygonF(ppQ));
|
||||
}
|
||||
|
||||
painter.setBrush(bb);
|
||||
painter.setPen(qp);
|
||||
painter.drawPath(QPP);
|
||||
painter.end();
|
||||
//img.save("test.png");
|
||||
}
|
||||
|
||||
///return the max radius of a point inside a polygon ,given the mask image
|
||||
///actually it evaluate the maximum bounding box
|
||||
int Outline2Dumper::getMaxMaskRadius(int x,int y,QImage &img)
|
||||
{
|
||||
int sizeY=img.size().height();
|
||||
int sizeX=img.size().width();
|
||||
int Max_radiusX=std::min(abs(x-sizeX),x);
|
||||
int Max_radiusY=std::min(abs(y-sizeY),y);
|
||||
int Max_radius=std::min(Max_radiusX,Max_radiusY);
|
||||
int val=qGray(img.pixel(x,y));
|
||||
///if is outside
|
||||
assert(val!=255); (void)val;
|
||||
|
||||
int curr_radius=1;
|
||||
while (curr_radius<Max_radius)
|
||||
{
|
||||
vcg::Box2i currBB=vcg::Box2i(vcg::Point2i(x,y),vcg::Point2i(x,y));
|
||||
vcg::Box2i InsideBB=currBB;
|
||||
currBB.Offset(curr_radius);
|
||||
InsideBB.Offset(curr_radius-1);
|
||||
|
||||
///check on borders
|
||||
for (int x0=currBB.min.X();x0<=currBB.max.X();x0++)
|
||||
for (int y0=currBB.min.Y();y0<=currBB.max.Y();y0++)
|
||||
{
|
||||
if (InsideBB.IsIn(vcg::Point2i(x0,y0)))continue;
|
||||
int val=qGray(img.pixel(x0,y0));
|
||||
///if is outside
|
||||
if (val==255)
|
||||
return curr_radius;
|
||||
}
|
||||
curr_radius++;
|
||||
}
|
||||
return curr_radius;
|
||||
}
|
||||
|
||||
///return the point inside the polygon with the bigger distance to the border,
|
||||
///this is used to write labels within the polygon, it handle polygons with holes too
|
||||
vcg::Point2f Outline2Dumper::GetIncenter(const vector< vector<Point2f> > &polyVec,
|
||||
const Similarity2f &tra1,
|
||||
float &radius,
|
||||
int resolution)
|
||||
{
|
||||
///INITIALIZE THE IMAGE
|
||||
QImage img(resolution,resolution,QImage::Format_RGB32);
|
||||
img.fill(vcg::ColorConverter::ToQColor(vcg::Color4b::White));
|
||||
Similarity2f tra0;
|
||||
///DRAW THE MASK
|
||||
DrawPolygonMask(polyVec,img,tra0,tra1);
|
||||
//img = img.mirrored(false,true);
|
||||
|
||||
///THEN FIND THE CENTROID
|
||||
float Maxradius=-1;
|
||||
int sizeY=img.size().height();
|
||||
int sizeX=img.size().width();
|
||||
vcg::Point2i incenter=vcg::Point2i(sizeX/2,sizeY/2);
|
||||
///THEN GO OVER ALL VERTICES
|
||||
for (int x=0;x<sizeX;x++)
|
||||
for (int y=0;y<sizeY;y++)
|
||||
{
|
||||
///flipped because of
|
||||
///same artifacts of Mquads
|
||||
int val=qGray(img.pixel(x,y));
|
||||
///if is outside
|
||||
if (val==255)continue;
|
||||
int curr_radius=getMaxMaskRadius(x,y,img);
|
||||
if (curr_radius>Maxradius)
|
||||
{
|
||||
Maxradius=curr_radius;
|
||||
incenter=vcg::Point2i(x,y);
|
||||
}
|
||||
}
|
||||
|
||||
vcg::Point2f incenterf;
|
||||
incenterf.Import(incenter);
|
||||
// /FIRST TRASNFORMATION
|
||||
// QPainter painter;
|
||||
// painter.begin(&img);
|
||||
// //painter.fillRect(incenter.V(0)-Maxradius,incenter.V(1)-Maxradius,Maxradius*2,Maxradius*2,Qt::red);
|
||||
//// painter.fillRect(incenter.V(0)-1,incenter.V(1)-1,2,2,Qt::red);
|
||||
// //painter.drawPoint(incenter.V(0),incenter.V(1));
|
||||
// painter.end();
|
||||
// static int num=0;
|
||||
// num++;
|
||||
// char path[100];
|
||||
// sprintf(path,"mask%d.png",num);
|
||||
// img.save(path);
|
||||
|
||||
|
||||
incenterf.X()-=tra0.tra[0];
|
||||
incenterf.Y()-=tra0.tra[1];
|
||||
incenterf*=1.0/tra0.sca;
|
||||
incenterf*=tra1.sca;
|
||||
|
||||
///SECOND TRANSFORMATION
|
||||
assert(Maxradius>0);
|
||||
radius=Maxradius;
|
||||
return incenterf;
|
||||
}
|
||||
|
||||
|
||||
///write a polygon on a PNG file, format of the polygon is vector of vector of contours...nested contours are holes
|
||||
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
||||
///the label to be written and the global parameter for drawing style
|
||||
void Outline2Dumper::dumpOutline2VecPNG(const char * imageName,
|
||||
vector< vector< vector<Point2f> > > &polyVecVec,
|
||||
vector<Similarity2f> &trVec,
|
||||
vector<string> &labelVec,
|
||||
Param &pp)
|
||||
{
|
||||
///SET THE FONT
|
||||
assert(polyVecVec.size() == trVec.size());
|
||||
int fontSize=ceil(std::max(pp.width,pp.height)/100.0);
|
||||
QFont qf("courier",fontSize);
|
||||
|
||||
///SET THE DRAWING SIZE
|
||||
QImage img(pp.width,pp.height,QImage::Format_RGB32);
|
||||
img.fill(vcg::ColorConverter::ToQColor( pp.backgroundColor).rgb());
|
||||
|
||||
///SETUP OF DRAWING PROCEDURE
|
||||
QPainter painter;
|
||||
painter.begin(&img);
|
||||
QBrush bb;
|
||||
if (pp.fill)
|
||||
bb.setStyle(Qt::SolidPattern);
|
||||
QPen qp;
|
||||
qp.setWidthF(0);
|
||||
|
||||
for(size_t i=0;i<polyVecVec.size();++i)
|
||||
{
|
||||
///SET THE CURRENT TRANSFORMATION
|
||||
painter.resetTransform();
|
||||
painter.translate(trVec[i].tra[0],trVec[i].tra[1]);
|
||||
painter.rotate(math::ToDeg(trVec[i].rotRad));
|
||||
painter.scale(trVec[i].sca,trVec[i].sca);
|
||||
QPainterPath QPP;
|
||||
|
||||
for(size_t jj=0;jj<polyVecVec[i].size();++jj)
|
||||
{
|
||||
QVector<QPointF> ppQ;
|
||||
for(size_t j=0;j<polyVecVec[i][jj].size();++j)
|
||||
{
|
||||
Point2f pp=polyVecVec[i][jj][j];
|
||||
ppQ.push_back(QPointF(pp[0],pp[1]));
|
||||
}
|
||||
ppQ.push_back(QPointF(polyVecVec[i][jj][0][0],polyVecVec[i][jj][0][1]));
|
||||
QPP.addPolygon(QPolygonF(ppQ));
|
||||
}
|
||||
|
||||
if (pp.randomColor)
|
||||
bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(polyVecVec.size(),i)));
|
||||
else
|
||||
bb.setColor(vcg::ColorConverter::ToQColor(pp.FillColor));
|
||||
|
||||
painter.setBrush(bb);
|
||||
painter.setPen(qp);
|
||||
painter.drawPath(QPP);
|
||||
if(!labelVec.empty())
|
||||
{
|
||||
///FIND THE BARYCENTER
|
||||
float radius;
|
||||
Point2f bc=GetIncenter(polyVecVec[i],trVec[i],radius,10);
|
||||
///DRAW THE TEXT
|
||||
painter.setFont(qf);
|
||||
painter.resetTransform();
|
||||
painter.translate(trVec[i].tra[0],trVec[i].tra[1]);
|
||||
painter.drawText(bc[0]-radius,bc[1]-radius,radius*2,radius*2,Qt::AlignHCenter|Qt::AlignCenter,QString(labelVec[i].c_str()));
|
||||
}
|
||||
}
|
||||
painter.end();
|
||||
img.save(imageName);
|
||||
}
|
||||
|
||||
|
||||
///write a polygon on a SVG file, format of the polygon is vector of vector of contours...nested contours are holes
|
||||
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
||||
///the label to be written and the global parameter for drawing style
|
||||
void Outline2Dumper::dumpOutline2VecSVG(const char * imageName,
|
||||
vector< vector< vector<Point2f> > > &outline2VecVec,
|
||||
vector<Similarity2f> &trVec,
|
||||
vector< vector< string> > &labelVecVec,
|
||||
vector< vector<Similarity2f> > &labelTrVecVec,
|
||||
vector<vector<float> >&labelRadVecVec,
|
||||
Outline2Dumper::Param &pp)
|
||||
{
|
||||
assert(outline2VecVec.size() == trVec.size());
|
||||
|
||||
|
||||
///SET THE FONT
|
||||
int fontSize;
|
||||
if(pp.fontSize==0) fontSize=ceil(std::max(pp.width,pp.height)/200.0);
|
||||
else fontSize=pp.fontSize;
|
||||
QFont qf("courier",fontSize);
|
||||
QSvgGenerator svg;
|
||||
svg.setFileName(imageName);
|
||||
|
||||
///SET THE DRAWING SIZE
|
||||
svg.setSize(QSize(pp.width,pp.height));
|
||||
svg.setViewBox(QRect(0, 0, pp.width,pp.height));
|
||||
svg.setResolution(int(pp.dpi));//
|
||||
|
||||
///SETUP OF DRAWING PROCEDURE
|
||||
QPainter painter;
|
||||
painter.begin(&svg);
|
||||
QBrush bb;
|
||||
if (pp.fill)
|
||||
bb.setStyle(Qt::SolidPattern);
|
||||
|
||||
QPen qp;
|
||||
///SET THE GLOBAL SCALING FACTOR
|
||||
for(size_t i=0;i<outline2VecVec.size();++i)
|
||||
{
|
||||
// we assume that
|
||||
float scalingFactorforPenWidth=1.f/(float)trVec[i].sca;
|
||||
qp.setWidthF(pp.penWidth*scalingFactorforPenWidth);
|
||||
qp.setColor(vcg::ColorConverter::ToQColor(pp.lineColor));
|
||||
///SET THE CURRENT TRANSFORMATION
|
||||
painter.resetTransform();
|
||||
painter.translate(trVec[i].tra[0],trVec[i].tra[1]);
|
||||
painter.rotate(math::ToDeg(trVec[i].rotRad));
|
||||
painter.scale(trVec[i].sca,trVec[i].sca);
|
||||
QPainterPath QPP;
|
||||
|
||||
for(size_t jj=0;jj<outline2VecVec[i].size();++jj)
|
||||
{
|
||||
QVector<QPointF> ppQ;
|
||||
for(size_t j=0;j<outline2VecVec[i][jj].size();++j)
|
||||
{
|
||||
Point2f pp=outline2VecVec[i][jj][j];
|
||||
ppQ.push_back(QPointF(pp[0],pp[1]));
|
||||
}
|
||||
ppQ.push_back(QPointF(outline2VecVec[i][jj][0][0],outline2VecVec[i][jj][0][1]));
|
||||
QPP.addPolygon(QPolygonF(ppQ));
|
||||
}
|
||||
///FIND THE INCENTER
|
||||
|
||||
if (pp.randomColor)
|
||||
bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(outline2VecVec.size(),i)));
|
||||
else
|
||||
bb.setColor(vcg::ColorConverter::ToQColor(pp.FillColor));
|
||||
|
||||
///DRAW THE POLYGON
|
||||
painter.setBrush(bb);
|
||||
painter.setPen(qp);
|
||||
painter.drawPath(QPP);
|
||||
|
||||
///DRAW THE TEXT
|
||||
painter.setFont(qf);
|
||||
float radius;
|
||||
// int radiusInt;
|
||||
Point2f bc;
|
||||
// if we do not have labelPos use the old method of empty disk.
|
||||
if(labelTrVecVec.empty()) bc=GetIncenter(outline2VecVec[i],trVec[i],radius);
|
||||
// radius = radiusInt;
|
||||
for(size_t labelInd=0;labelInd<labelVecVec[i].size();++labelInd)
|
||||
{
|
||||
if(!labelTrVecVec.empty())
|
||||
{
|
||||
bc = labelTrVecVec[i][labelInd].tra;
|
||||
bc.Rotate(trVec[i].rotRad);
|
||||
bc *= trVec[i].sca;
|
||||
radius=labelRadVecVec[i][labelInd];
|
||||
radius *= trVec[i].sca;
|
||||
}
|
||||
painter.resetTransform();
|
||||
painter.translate(trVec[i].tra[0],trVec[i].tra[1]);
|
||||
qp.setColor(vcg::ColorConverter::ToQColor(pp.labelColor));
|
||||
painter.setPen(qp);
|
||||
painter.drawText(bc[0]-radius,bc[1]-radius,radius*2,radius*2,Qt::AlignHCenter|Qt::AlignCenter,QString(labelVecVec[i][labelInd].c_str()));
|
||||
}
|
||||
}
|
||||
painter.end();
|
||||
}
|
||||
|
||||
void Outline2Dumper::dumpOutline2VecSVG(const char * imageName,
|
||||
vector< vector< vector<Point2f> > > &polyVecVec,
|
||||
vector<Similarity2f> &trVec,
|
||||
vector< string > &labelVec,
|
||||
Outline2Dumper::Param &pp)
|
||||
{
|
||||
vector< vector< string> > labelVecVec(labelVec.size());
|
||||
vector< vector<Similarity2f> > labelTrVec;
|
||||
vector< vector<float> >labelRadVec;
|
||||
for(size_t i=0;i<labelVec.size();++i)
|
||||
{
|
||||
labelVecVec[i].push_back(labelVec[i]);
|
||||
}
|
||||
dumpOutline2VecSVG(imageName,polyVecVec,trVec,labelVecVec,labelTrVec,labelRadVec,pp);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifndef POLYTOQIMAGE_H
|
||||
#define POLYTOQIMAGE_H
|
||||
#include <QImage>
|
||||
#include <QSvgGenerator>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <vcg/space/point2.h>
|
||||
#include <vcg/space/color4.h>
|
||||
#include <vcg/space/box2.h>
|
||||
#include <vcg/math/similarity2.h>
|
||||
|
||||
///this class is used to pass global
|
||||
///parameters to the polygonal dumper
|
||||
|
||||
///this class is used to draw polygons on an image could be vectorial or not
|
||||
class Outline2Dumper
|
||||
{
|
||||
public:
|
||||
static float MM2PT(const float valueMM, float dpi)
|
||||
{
|
||||
float valueInch = valueMM / 25.4f;
|
||||
return valueInch * dpi;
|
||||
}
|
||||
|
||||
class Param
|
||||
{
|
||||
public:
|
||||
/// the backgrround color
|
||||
vcg::Color4b backgroundColor;
|
||||
/// true if the polygons must be filled with color
|
||||
bool fill;
|
||||
/// true if the filling color is random
|
||||
bool randomColor;
|
||||
/// the filling color of polygons, used only if randomColor==false
|
||||
vcg::Color4b FillColor;
|
||||
/// The size of the font. If zero (default) it is automatically chosen.
|
||||
int fontSize;
|
||||
/// dimension of the image (in PNG are pixels, while in SVG is the workspace in points)
|
||||
int width;
|
||||
int height;
|
||||
vcg::Color4b labelColor;
|
||||
vcg::Color4b lineColor;
|
||||
|
||||
/// DPI resolution, used only for SVG
|
||||
int dpi;
|
||||
float penWidth;
|
||||
|
||||
void SetSVGPenInMM(float widthMM)
|
||||
{
|
||||
float widthInch = widthMM/25.4f;
|
||||
penWidth = widthInch*dpi;
|
||||
}
|
||||
|
||||
///Handy function for setting the size of the drawing
|
||||
void SetSVGDimInMm(float widthMM,float heightMM,float _dpi=72)
|
||||
{
|
||||
dpi=_dpi;
|
||||
width = MM2PT(widthMM,dpi);
|
||||
height = MM2PT(heightMM,dpi);
|
||||
}
|
||||
|
||||
///default constructor
|
||||
Param()
|
||||
{
|
||||
backgroundColor = vcg::Color4b::Gray;
|
||||
width=1024;
|
||||
height=1024;
|
||||
dpi=72;
|
||||
fontSize=0;
|
||||
fill=false;
|
||||
randomColor=true;
|
||||
FillColor=vcg::Color4b(0,0,0,255);
|
||||
lineColor=vcg::Color4b::Black;
|
||||
labelColor=vcg::Color4b::Black;
|
||||
|
||||
}
|
||||
};
|
||||
private:
|
||||
///this class draw a black mask fora given polygon, cenetered and scaled to fit with
|
||||
///the image size, it return the transformation to tranform back the polygon to 2D space
|
||||
static void DrawPolygonMask(const std::vector< std::vector<vcg::Point2f> > &polyVec,QImage &img,
|
||||
vcg::Similarity2f &ret,const vcg::Similarity2f &trans);
|
||||
|
||||
///return the max radius of a point inside a polygon ,given the mask image
|
||||
///actually it evaluate the maximum bounding box
|
||||
static int getMaxMaskRadius(int x,int y,QImage &img);
|
||||
public:
|
||||
|
||||
///return the point inside the polygon with the bigger distance to the border,
|
||||
///this is used to write labels within the polygon, it handle polygons with holes too
|
||||
static vcg::Point2f GetIncenter(const std::vector< std::vector<vcg::Point2f> > &polyVec,
|
||||
const vcg::Similarity2f &tra1, float &radius, int resolution=100);
|
||||
|
||||
static void rectSetToOutline2Vec(std::vector< vcg::Box2f > &rectVec, std::vector< std::vector<vcg::Point2f> > &polyVec);
|
||||
static void multiRectSetToSingleOutline2Vec(std::vector< vcg::Box2f > &rectVec, std::vector<vcg::Similarity2f> &trVec, std::vector<int> &indVec,
|
||||
int ind, std::vector< std::vector<vcg::Point2f> > &polyVec, std::vector<vcg::Similarity2f> &trPolyVec);
|
||||
static void multiOutline2VecToSingleOutline2Vec(const std::vector<std::vector<vcg::Point2f> > &multipolyVec, const std::vector<vcg::Similarity2f> &trVec, const std::vector<int> &indVec,
|
||||
int ind, std::vector< std::vector< vcg::Point2f> > &polyVec, std::vector< vcg::Similarity2f> &trPolyVec);
|
||||
|
||||
///write a polygon on a PNG file, format of the polygon is vector of vector of contours...nested contours are holes
|
||||
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
||||
///the label to be written and the global parameter for drawing style
|
||||
static void dumpOutline2VecPNG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, std::vector<std::vector<std::string> > &labelVecVec, Param &pp);
|
||||
//write a polygon on a SVG file, format of the polygon is vector of vector of contours...nested contours are holes
|
||||
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
||||
///the label to be written and the global parameter for drawing style
|
||||
static void dumpOutline2VecSVG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, std::vector< std::vector<std::string> > &labelVecVec,
|
||||
std::vector<std::vector<vcg::Similarity2f> > &labelTrVecVec, std::vector<std::vector<float> > &labelRadVec, Param &pp);
|
||||
|
||||
static void dumpOutline2VecPNG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, std::vector<std::string> &labelVec, Param &pp);
|
||||
static void dumpOutline2VecSVG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, std::vector<std::string> &labelVec, Param &pp);
|
||||
|
||||
static void dumpOutline2VecPNG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, Param &pp);
|
||||
static void dumpOutline2VecSVG(const char * imageName, std::vector< std::vector< std::vector<vcg::Point2f> > > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, Param &pp);
|
||||
|
||||
static void dumpOutline2VecPNG(const char * imageName, std::vector< std::vector<vcg::Point2f> > &polyVecVec,
|
||||
std::vector<vcg::Similarity2f> &trVec, Param &pp);
|
||||
static void dumpOutline2VecSVG(const char * imageName, std::vector< std::vector<vcg::Point2f> > &outline2Vec,
|
||||
std::vector<vcg::Similarity2f> &trVec, Param &pp);
|
||||
};
|
||||
#endif // POLYTOQIMAGE_H
|
||||
@@ -0,0 +1,100 @@
|
||||
#include <QtGui>
|
||||
#include <QWidget>
|
||||
#include <AntTweakBar.h>
|
||||
#include <wrap/qt/device_to_logical.h>
|
||||
|
||||
void TW_CALL CopyCDStringToClient(char **destPtr, const char *src)
|
||||
{
|
||||
size_t srcLen = (src!=NULL) ? strlen(src) : 0;
|
||||
size_t destLen = (*destPtr!=NULL) ? strlen(*destPtr) : 0;
|
||||
|
||||
// Alloc or realloc dest memory block if needed
|
||||
if( *destPtr==NULL )
|
||||
*destPtr = (char *)malloc(srcLen+1);
|
||||
else if( srcLen>destLen )
|
||||
*destPtr = (char *)realloc(*destPtr, srcLen+1);
|
||||
|
||||
// Copy src
|
||||
if( srcLen>0 )
|
||||
strncpy(*destPtr, src, srcLen);
|
||||
(*destPtr)[srcLen] = '\0'; // null-terminated string
|
||||
}
|
||||
|
||||
void TW_CALL CopyStdStringToClient(std::string& destClientString, const std::string& srcLibraryString)
|
||||
{
|
||||
destClientString = srcLibraryString;
|
||||
}
|
||||
|
||||
TwMouseButtonID Qt2TwMouseButtonId(QMouseEvent *e)
|
||||
{
|
||||
if(e->button() && Qt::LeftButton) return TW_MOUSE_LEFT;
|
||||
if(e->button() && Qt::MidButton) return TW_MOUSE_MIDDLE;
|
||||
if(e->button() && Qt::RightButton) return TW_MOUSE_RIGHT;
|
||||
return TW_MOUSE_LEFT;
|
||||
// assert(0);
|
||||
}
|
||||
|
||||
int TwMousePressQt(QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(e->x (), e->y ());
|
||||
return TwMouseButton(TW_MOUSE_PRESSED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMousePressQt(QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(QTLogicalToDevice(qw, e->x()), QTLogicalToDevice(qw, e->y()));
|
||||
return TwMouseButton(TW_MOUSE_PRESSED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMouseReleaseQt(QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(e->x (), e->y ());
|
||||
return TwMouseButton(TW_MOUSE_RELEASED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMouseReleaseQt(QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(QTLogicalToDevice(qw, e->x()), QTLogicalToDevice(qw, e->y()));
|
||||
return TwMouseButton(TW_MOUSE_RELEASED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwKeyPressQt(QKeyEvent *e)
|
||||
{
|
||||
int kmod = 0;
|
||||
if(e->modifiers() & Qt::ShiftModifier ) kmod |= TW_KMOD_SHIFT;
|
||||
if(e->modifiers() & Qt::ControlModifier ) kmod |= TW_KMOD_CTRL;
|
||||
if(e->modifiers() & Qt::AltModifier ) kmod |= TW_KMOD_ALT;
|
||||
int key = e->key();
|
||||
int k = 0;
|
||||
|
||||
if( key>0 && key<0x7e ) k=key; // plain ascii codes
|
||||
|
||||
if( key>=Qt::Key_F1 && key<=Qt::Key_F12 )
|
||||
k = TW_KEY_F1 + (key-Qt::Key_F1 );
|
||||
else
|
||||
{
|
||||
switch( key )
|
||||
{
|
||||
case Qt::Key_Left: k = TW_KEY_LEFT; break;
|
||||
case Qt::Key_Up: k = TW_KEY_UP; break;
|
||||
case Qt::Key_Right: k = TW_KEY_RIGHT; break;
|
||||
case Qt::Key_Down: k = TW_KEY_DOWN; break;
|
||||
case Qt::Key_PageUp: k = TW_KEY_PAGE_UP; break;
|
||||
case Qt::Key_PageDown: k = TW_KEY_PAGE_DOWN; break;
|
||||
case Qt::Key_Home: k = TW_KEY_HOME; break;
|
||||
case Qt::Key_End: k = TW_KEY_END; break;
|
||||
case Qt::Key_Insert: k = TW_KEY_INSERT; break;
|
||||
case Qt::Key_Backspace: k = TW_KEY_BACKSPACE; break;
|
||||
case Qt::Key_Delete: k = TW_KEY_DELETE; break;
|
||||
case Qt::Key_Return: k = TW_KEY_RETURN; break;
|
||||
case Qt::Key_Enter: k = TW_KEY_RETURN; break;
|
||||
case Qt::Key_Escape: k = TW_KEY_ESCAPE; break;
|
||||
case Qt::Key_Tab: k = TW_KEY_TAB; break;
|
||||
case Qt::Key_Space: k = TW_KEY_SPACE; break;
|
||||
}
|
||||
}
|
||||
|
||||
return TwKeyPressed(k, kmod);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef ANTTWEAKBARMAPPER_H
|
||||
#define ANTTWEAKBARMAPPER_H
|
||||
|
||||
#include <AntTweakBar.h>
|
||||
#include <QWidget>
|
||||
#include <string>
|
||||
|
||||
void TW_CALL CopyCDStringToClient(char **destPtr, const char *src);
|
||||
void TW_CALL CopyStdStringToClient(std::string& destClientString, const std::string& srcLibraryString);
|
||||
|
||||
TwMouseButtonID Qt2TwMouseButtonId(QMouseEvent *e);
|
||||
int TwMousePressQt(QMouseEvent *e);
|
||||
int TwMouseReleaseQt(QMouseEvent *e);
|
||||
int TwMousePressQt(QWidget *qw, QMouseEvent *e);
|
||||
int TwMouseReleaseQt(QWidget *qw, QMouseEvent *e);
|
||||
int TwKeyPressQt(QKeyEvent *e);
|
||||
|
||||
#endif // ANTTWEAKBARMAPPER_H
|
||||
@@ -0,0 +1,101 @@
|
||||
#include <QtGui>
|
||||
#include <QWidget>
|
||||
#include <AntTweakBar.h>
|
||||
#include <wrap/qt/device_to_logical.h>
|
||||
|
||||
void TW_CALL CopyCDStringToClient(char **destPtr, const char *src)
|
||||
{
|
||||
size_t srcLen = (src!=NULL) ? strlen(src) : 0;
|
||||
size_t destLen = (*destPtr!=NULL) ? strlen(*destPtr) : 0;
|
||||
|
||||
// Alloc or realloc dest memory block if needed
|
||||
if( *destPtr==NULL )
|
||||
*destPtr = (char *)malloc(srcLen+1);
|
||||
else if( srcLen>destLen )
|
||||
*destPtr = (char *)realloc(*destPtr, srcLen+1);
|
||||
|
||||
// Copy src
|
||||
if( srcLen>0 )
|
||||
strncpy(*destPtr, src, srcLen);
|
||||
(*destPtr)[srcLen] = '\0'; // null-terminated string
|
||||
}
|
||||
|
||||
void TW_CALL CopyStdStringToClient(std::string& destClientString, const std::string& srcLibraryString)
|
||||
{
|
||||
destClientString = srcLibraryString;
|
||||
}
|
||||
|
||||
TwMouseButtonID Qt2TwMouseButtonId(QMouseEvent *e)
|
||||
{
|
||||
if(e->button() && Qt::LeftButton) return TW_MOUSE_LEFT;
|
||||
if(e->button() && Qt::MidButton) return TW_MOUSE_MIDDLE;
|
||||
if(e->button() && Qt::RightButton) return TW_MOUSE_RIGHT;
|
||||
return TW_MOUSE_LEFT;
|
||||
// assert(0);
|
||||
}
|
||||
|
||||
int TwMousePressQt(QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(e->x (), e->y ());
|
||||
return TwMouseButton(TW_MOUSE_PRESSED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMousePressQt(QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(QTLogicalToDevice(qw, e->x()), QTLogicalToDevice(qw, e->y()));
|
||||
return TwMouseButton(TW_MOUSE_PRESSED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMouseReleaseQt(QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(e->x (), e->y ());
|
||||
return TwMouseButton(TW_MOUSE_RELEASED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwMouseReleaseQt(QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
TwMouseMotion(QTLogicalToDevice(qw, e->x()), QTLogicalToDevice(qw, e->y()));
|
||||
return TwMouseButton(TW_MOUSE_RELEASED, Qt2TwMouseButtonId(e));
|
||||
}
|
||||
|
||||
int TwKeyPressQt(QKeyEvent *e)
|
||||
{
|
||||
int kmod = 0;
|
||||
if(e->modifiers() & Qt::ShiftModifier ) kmod |= TW_KMOD_SHIFT;
|
||||
if(e->modifiers() & Qt::ControlModifier ) kmod |= TW_KMOD_CTRL;
|
||||
if(e->modifiers() & Qt::AltModifier ) kmod |= TW_KMOD_ALT;
|
||||
int key = e->key();
|
||||
int k = 0;
|
||||
|
||||
if( key>0 && key<0x7e ) k=key; // plain ascii codes
|
||||
|
||||
if( key>=Qt::Key_F1 && key<=Qt::Key_F15 )
|
||||
k = TW_KEY_F1 + (key-Qt::Key_F1 );
|
||||
else
|
||||
if ( key>=Qt::Key_A && key<=Qt::Key_Z)
|
||||
k = (kmod & TW_KMOD_SHIFT) ? key : (int)'a' + (key-(int)'A');
|
||||
else
|
||||
{
|
||||
switch( key )
|
||||
{
|
||||
case Qt::Key_Left: k = TW_KEY_LEFT; break;
|
||||
case Qt::Key_Up: k = TW_KEY_UP; break;
|
||||
case Qt::Key_Right: k = TW_KEY_RIGHT; break;
|
||||
case Qt::Key_Down: k = TW_KEY_DOWN; break;
|
||||
case Qt::Key_PageUp: k = TW_KEY_PAGE_UP; break;
|
||||
case Qt::Key_PageDown: k = TW_KEY_PAGE_DOWN; break;
|
||||
case Qt::Key_Home: k = TW_KEY_HOME; break;
|
||||
case Qt::Key_End: k = TW_KEY_END; break;
|
||||
case Qt::Key_Insert: k = TW_KEY_INSERT; break;
|
||||
case Qt::Key_Backspace: k = TW_KEY_BACKSPACE; break;
|
||||
case Qt::Key_Delete: k = TW_KEY_DELETE; break;
|
||||
case Qt::Key_Return: k = TW_KEY_RETURN; break;
|
||||
case Qt::Key_Enter: k = TW_KEY_RETURN; break;
|
||||
case Qt::Key_Escape: k = TW_KEY_ESCAPE; break;
|
||||
case Qt::Key_Tab: k = TW_KEY_TAB; break;
|
||||
case Qt::Key_Space: k = TW_KEY_SPACE; break;
|
||||
}
|
||||
}
|
||||
|
||||
return TwKeyPressed(k, kmod);
|
||||
}
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <QMessageBox>
|
||||
class checkGLError
|
||||
{
|
||||
public:
|
||||
static QString makeString(const char* m)
|
||||
{
|
||||
QString message(m);
|
||||
|
||||
switch(glGetError()) {
|
||||
case GL_NO_ERROR: return QString();
|
||||
|
||||
case GL_INVALID_ENUM: message+=("invalid enum"); break;
|
||||
case GL_INVALID_VALUE: message+=("invalid value"); break;
|
||||
case GL_INVALID_OPERATION: message+=("invalid operation"); break;
|
||||
case GL_STACK_OVERFLOW: message+=("stack overflow"); break;
|
||||
case GL_STACK_UNDERFLOW: message+=("stack underflow"); break;
|
||||
case GL_OUT_OF_MEMORY: message+=("out of memory"); break;
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION: message+=("invalid framebuffer operation"); break;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
static void debugInfo(const char* m) {
|
||||
QString message=makeString(m);
|
||||
if(message.isEmpty()) return;
|
||||
::qDebug("%s",qPrintable(message));
|
||||
}
|
||||
|
||||
static void QMessageBox(const char* m, const char* title) {
|
||||
QString message=makeString(m);
|
||||
QMessageBox::warning(0, title,message);
|
||||
}
|
||||
static void QMessageBox(const char* m) {QMessageBox(m,"GL error");}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef COL_QT_CONVERT_H_
|
||||
#define COL_QT_CONVERT_H_
|
||||
|
||||
#include <QColor>
|
||||
#include "../../vcg/space/color4.h"
|
||||
|
||||
namespace vcg
|
||||
{
|
||||
class ColorConverter
|
||||
{
|
||||
public:
|
||||
inline static vcg::Color4b ToColor4b(const QColor& col)
|
||||
{
|
||||
return vcg::Color4b(col.red(),col.green(),col.blue(),col.alpha());
|
||||
}
|
||||
|
||||
inline static QColor ToQColor(const vcg::Color4b& col)
|
||||
{
|
||||
return QColor(col[0],col[1],col[2],col[3]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef DEVICE_TO_LOGICAL_H
|
||||
#define DEVICE_TO_LOGICAL_H
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <vcg/space/point2.h>
|
||||
|
||||
template < class ValueType>
|
||||
inline ValueType QTLogicalToDevice( QWidget *qw, const ValueType &value)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return value*qw->devicePixelRatio() ;
|
||||
#else
|
||||
Q_UNUSED(qw);
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template < class ValueType>
|
||||
inline ValueType QTLogicalToDevice( QPainter *qp, const ValueType &value)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return value*qp->device()->devicePixelRatio() ;
|
||||
#else
|
||||
Q_UNUSED(qp);
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template < class ValueType>
|
||||
inline ValueType QTDeviceToLogical( QWidget *qw, const ValueType &value)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return value/qw->devicePixelRatio() ;
|
||||
#else
|
||||
Q_UNUSED(qw);
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
template < class ValueType>
|
||||
inline ValueType QTDeviceToLogical( QPainter *qp, const ValueType &value)
|
||||
{
|
||||
#if QT_VERSION >= 0x050000
|
||||
return value/qp->device()->devicePixelRatio() ;
|
||||
#else
|
||||
Q_UNUSED(qp);
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline vcg::Point2f QTLogicalToOpenGL( QWidget *qw, const QPoint &p)
|
||||
{
|
||||
return vcg::Point2f(QTLogicalToDevice(qw,p.x()), QTLogicalToDevice(qw,qw->height()-p.y()));
|
||||
}
|
||||
|
||||
|
||||
inline int QTDeviceHeight(QWidget *qw) {return QTLogicalToDevice(qw,qw->height());}
|
||||
inline int QTDeviceWidth(QWidget *qw) {return QTLogicalToDevice(qw,qw->width());}
|
||||
#endif // DEVICE_TO_LOGICAL_H
|
||||
Executable
+198
@@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
* MeshLab o o *
|
||||
* An extendible mesh processor o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2005, 2009 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#ifndef VCG_WRAP_QT_GLLABEL_H
|
||||
#define VCG_WRAP_QT_GLLABEL_H
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <wrap/qt/col_qt_convert.h>
|
||||
#include <wrap/qt/device_to_logical.h>
|
||||
#include <wrap/qt/checkGLError.h>
|
||||
#include <QPainter>
|
||||
namespace vcg
|
||||
{
|
||||
/*
|
||||
*/
|
||||
class glLabel
|
||||
{
|
||||
|
||||
public:
|
||||
class Mode
|
||||
{
|
||||
public:
|
||||
Mode()
|
||||
{
|
||||
init();
|
||||
}
|
||||
Mode(Color4b _color)
|
||||
{
|
||||
init();
|
||||
color=_color;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
color=vcg::Color4b(vcg::Color4b::White);
|
||||
angle=0;
|
||||
rightAlign = false;
|
||||
qFont.setStyleStrategy(QFont::NoAntialias);
|
||||
qFont.setFamily("Helvetica");
|
||||
qFont.setPixelSize(12);
|
||||
}
|
||||
|
||||
Mode(QFont &_qFont, vcg::Color4b _color, float _angle,bool _rightAlign)
|
||||
{
|
||||
qFont=_qFont;
|
||||
color=_color;
|
||||
angle=_angle;
|
||||
rightAlign=_rightAlign;
|
||||
}
|
||||
|
||||
float angle;
|
||||
bool rightAlign;
|
||||
vcg::Color4b color;
|
||||
QFont qFont;
|
||||
};
|
||||
|
||||
private:
|
||||
static void enter2D(QPainter *painter)
|
||||
{
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_VIEWPORT_BIT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
painter->endNativePainting();
|
||||
painter->save();
|
||||
}
|
||||
|
||||
static void exit2D(QPainter *painter)
|
||||
{
|
||||
//checkGLError::qDebug("glLabel");
|
||||
painter->restore();
|
||||
painter->beginNativePainting();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
public:
|
||||
enum LabelPosition { TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT} ;
|
||||
|
||||
static void render2D(QPainter *painter, const LabelPosition pos, const QString &text, const Mode &m=Mode())
|
||||
{
|
||||
render2D(painter,pos,0,text,m);
|
||||
}
|
||||
static void render2D(QPainter *painter, const LabelPosition pos, int linePos, const QString &text, const Mode &m=Mode())
|
||||
{
|
||||
Mode lm = m;
|
||||
if(pos == TOP_RIGHT || pos == BOTTOM_RIGHT)
|
||||
lm.rightAlign=true;
|
||||
|
||||
GLint view[4];
|
||||
glGetIntegerv(GL_VIEWPORT, view);
|
||||
QFontMetrics qfm(m.qFont);
|
||||
float delta = qfm.ascent()/2;
|
||||
switch(pos)
|
||||
{
|
||||
case TOP_LEFT : render2D(painter,vcg::Point2f(delta, view[3]-3*delta - delta*3*linePos),text,lm); break;
|
||||
case TOP_RIGHT : render2D(painter,vcg::Point2f(view[2]-delta, view[3]-3*delta - delta*3*linePos),text,lm); break;
|
||||
case BOTTOM_LEFT : render2D(painter,vcg::Point2f(delta, 3*delta + delta*3*linePos),text,lm); break;
|
||||
case BOTTOM_RIGHT : render2D(painter,vcg::Point2f(view[2]-delta, 3*delta + delta*3*linePos),text,lm); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
static void render2D(QPainter *painter, const vcg::Point2f &p, const QString &text, const Mode &m)
|
||||
{
|
||||
GLint view[4];
|
||||
glGetIntegerv(GL_VIEWPORT, view);
|
||||
QFontMetrics qfm(m.qFont);
|
||||
QRect textBox = qfm.boundingRect(text);
|
||||
glLabel::enter2D(painter);
|
||||
painter->setRenderHint(QPainter::TextAntialiasing);
|
||||
painter->setPen(vcg::ColorConverter::ToQColor(m.color));
|
||||
painter->setFont(m.qFont);
|
||||
|
||||
painter->translate(QPointF(p[0],view[3]-p[1]));
|
||||
painter->rotate(m.angle);
|
||||
QPoint base(0,qfm.ascent()/2);
|
||||
if(m.rightAlign)
|
||||
base.setX(-textBox.width() -qfm.maxWidth());
|
||||
painter->drawText(base,text);
|
||||
glLabel::exit2D(painter);
|
||||
glViewport(view[0],view[1],view[2],view[3]);
|
||||
}
|
||||
|
||||
static void render(QPainter *painter, const vcg::Point3f &p, const QString &text)
|
||||
{
|
||||
Mode m;
|
||||
render(painter,p,text,m);
|
||||
}
|
||||
|
||||
static void render(QPainter *painter, const vcg::Point3f &p, const QString &text, const Mode &m)
|
||||
{
|
||||
GLdouble model[16];
|
||||
GLdouble proj[16];
|
||||
GLint view[4];
|
||||
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, model);
|
||||
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
||||
glGetIntegerv(GL_VIEWPORT, view);
|
||||
GLdouble winx,winy,winz;
|
||||
|
||||
gluProject(p[0],p[1],p[2],model,proj,view,&winx,&winy,&winz);
|
||||
|
||||
QFontMetrics qfm(m.qFont);
|
||||
QRect textBox = qfm.boundingRect(text);
|
||||
glLabel::enter2D(painter);
|
||||
|
||||
painter->setRenderHint(QPainter::TextAntialiasing);
|
||||
painter->setPen(vcg::ColorConverter::ToQColor(m.color));
|
||||
painter->setFont(m.qFont);
|
||||
painter->translate(QPointF(QTDeviceToLogical(painter,winx),
|
||||
QTDeviceToLogical(painter,view[3]-winy)));
|
||||
painter->rotate(m.angle);
|
||||
QPoint base(0,qfm.ascent()/2);
|
||||
if(m.rightAlign)
|
||||
base.setX(-textBox.width() -qfm.maxWidth());
|
||||
painter->drawText(base,text);
|
||||
|
||||
glLabel::exit2D(painter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void render(QPainter *painter, const vcg::Point3d &p, const QString &text)
|
||||
{ render(painter,Point3f::Construct(p),text); }
|
||||
static void render(QPainter *painter, const vcg::Point3d &p, const QString &text, const Mode &m)
|
||||
{ render(painter,Point3f::Construct(p),text,m); }
|
||||
|
||||
};
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#ifndef IMG_QT_INCLUDES_H_
|
||||
#define IMG_QT_INCLUDES_H_
|
||||
|
||||
// includes all img and all qt wrap headers
|
||||
|
||||
#include "img/img.h"
|
||||
|
||||
#include "wrap/qt/img_qt_convert.h"
|
||||
#include "wrap/qt/img_qt_io.h"
|
||||
|
||||
#endif /*IMG_QT_INCLUDES_H_*/
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#ifndef IMG_QT_CONVERT_H_
|
||||
#define IMG_QT_CONVERT_H_
|
||||
|
||||
// implementation of conversione between qimage and basic image types
|
||||
|
||||
#include <QImage>
|
||||
|
||||
namespace img {
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_QImage_to_Y(const QImage &source, Image<1,ScalarType,Safe> &destination)
|
||||
{
|
||||
assert(!source.isNull());
|
||||
if(Safe){
|
||||
if(source.isNull()) throw ImageException("Null source image");
|
||||
}
|
||||
destination.setZero(source.width(),source.height());
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
destination.setValue(x_coord, y_coord, 0, qGray(source.pixel(x_coord, y_coord)) );
|
||||
}
|
||||
destination.attributes.setRange(ScalarType(0.0),ScalarType(255.0));
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_QImage_to_RGB(const QImage &source, Image<3,ScalarType,Safe> &destination)
|
||||
{
|
||||
assert(!source.isNull());
|
||||
if(Safe){
|
||||
if(source.isNull()) throw ImageException("Null source image");
|
||||
}
|
||||
destination.setZero(source.width(),source.height());
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
QRgb qpixel = source.pixel(x_coord, y_coord);
|
||||
destination.setValue(x_coord, y_coord, 0, qRed(qpixel) );
|
||||
destination.setValue(x_coord, y_coord, 1, qGreen(qpixel) );
|
||||
destination.setValue(x_coord, y_coord, 2, qBlue(qpixel) );
|
||||
}
|
||||
destination.attributes.setRange(ScalarType(0.0),ScalarType(255.0));
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_QImage_to_RGBA(const QImage &source, Image<4,ScalarType,Safe> &destination)
|
||||
{
|
||||
assert(!source.isNull());
|
||||
if(Safe){
|
||||
if(source.isNull()) throw ImageException("Null source image");
|
||||
}
|
||||
destination.setZero(source.width(),source.height());
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
QRgb qpixel = source.pixel(x_coord, y_coord);
|
||||
destination.setValue(x_coord, y_coord, 0, qRed(qpixel) );
|
||||
destination.setValue(x_coord, y_coord, 1, qGreen(qpixel) );
|
||||
destination.setValue(x_coord, y_coord, 2, qBlue(qpixel) );
|
||||
destination.setValue(x_coord, y_coord, 3, qAlpha(qpixel) );
|
||||
}
|
||||
destination.attributes.setRange(ScalarType(0.0),ScalarType(255.0));
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_Y_to_QImage(const Image<1,ScalarType,Safe> &source, QImage &destination)
|
||||
{
|
||||
assert(source.isValid());
|
||||
assert(source.attributes.hasRange(0,255));
|
||||
if(Safe){
|
||||
if(!source.isValid()) throw ImageException("Invalid source image");
|
||||
if(!source.attributes.hasRange(0,255)) throw ImageException("Invalid range attribute");
|
||||
}
|
||||
destination=QImage(source.width(),source.height(),QImage::Format_RGB32);
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
int Y = valueAsInt(clampValue(source.getValue(x_coord,y_coord,0)));
|
||||
destination.setPixel(x_coord,y_coord,qRgb(Y,Y,Y));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_RGB_to_QImage(const Image<3,ScalarType,Safe> &source, QImage &destination)
|
||||
{
|
||||
assert(source.isValid());
|
||||
assert(source.attributes.hasRange(ScalarType(0.0),ScalarType(255.0)));
|
||||
if(Safe){
|
||||
if(!source.isValid()) throw ImageException("Invalid source image");
|
||||
if(!source.attributes.hasRange(ScalarType(0.0),ScalarType(255.0))) throw ImageException("Invalid range attribute");
|
||||
}
|
||||
destination=QImage(source.width(),source.height(),QImage::Format_RGB32);
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
destination.setPixel(x_coord,y_coord,qRgb(valueAsInt(clampValue(source.getValue(x_coord,y_coord,0))),
|
||||
valueAsInt(clampValue(source.getValue(x_coord,y_coord,1))),
|
||||
valueAsInt(clampValue(source.getValue(x_coord,y_coord,2))) ));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void convert_RGBA_to_QImage(const Image<4,ScalarType,Safe> &source, QImage &destination)
|
||||
{
|
||||
assert(source.isValid());
|
||||
assert(source.attributes.hasRange(ScalarType(0.0),ScalarType(255.0)));
|
||||
if(Safe){
|
||||
if(!source.isValid()) throw ImageException("Invalid source image");
|
||||
if(!source.attributes.hasRange(ScalarType(0.0),ScalarType(255.0))) throw ImageException("Invalid range attribute");
|
||||
}
|
||||
destination=QImage(source.width(),source.height(),QImage::Format_ARGB32);
|
||||
for (int y_coord = 0; y_coord < source.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < source.width(); ++x_coord){
|
||||
destination.setPixel(x_coord,y_coord,qRgba(valueAsInt(clampValue(source.getValue(x_coord,y_coord,0))),
|
||||
valueAsInt(clampValue(source.getValue(x_coord,y_coord,1))),
|
||||
valueAsInt(clampValue(source.getValue(x_coord,y_coord,2))),
|
||||
valueAsInt(clampValue(source.getValue(x_coord,y_coord,3))) ));
|
||||
}
|
||||
}
|
||||
|
||||
} //end namespace img
|
||||
|
||||
#endif /*IMG_QT_CONVERT_H_*/
|
||||
Executable
+264
@@ -0,0 +1,264 @@
|
||||
#ifndef IMG_QT_IO_H_
|
||||
#define IMG_QT_IO_H_
|
||||
|
||||
#include <fstream>
|
||||
// input/output using the qt system
|
||||
|
||||
#include <QImage>
|
||||
|
||||
#include "wrap/qt/img_qt_convert.h"
|
||||
#include "img/img_io.h"
|
||||
|
||||
namespace img {
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void openQtY(const QString filename, Image<1,ScalarType,Safe> &image)
|
||||
{
|
||||
convert_QImage_to_Y(QImage(filename),image);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void openQtRGB(const QString filename, Image<3,ScalarType,Safe> &image)
|
||||
{
|
||||
convert_QImage_to_RGB(QImage(filename),image);
|
||||
}
|
||||
|
||||
//// queste le tengo commentate perche` ora non mi servono
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline void openQtRGBA(const QString filename, Image<4,ScalarType,Safe> &image)
|
||||
//{
|
||||
// convert_QImage_to_RGBA(QImage(filename),image);
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline void openQtY(const char *filename, Image<1,ScalarType,Safe> &image)
|
||||
//{
|
||||
// openQtY(QString(filename),image);
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline void openQtRGB(const char *filename, Image<3,ScalarType,Safe> &image)
|
||||
//{
|
||||
// openQtRGB(QString(filename),image);
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline void openQtRGBA(const char *filename, Image<4,ScalarType,Safe> &image)
|
||||
//{
|
||||
// openQtRGBA(QString(filename),image);
|
||||
//}
|
||||
//
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool saveQtY(const Image<1,ScalarType,Safe> &image,const QString filename)
|
||||
{
|
||||
QImage qimage;
|
||||
convert_Y_to_QImage(image,qimage);
|
||||
bool success = qimage.save(filename);
|
||||
assert(success);
|
||||
if(Safe){
|
||||
if(!success) throw ImageException("cannot save image");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool saveQtRGB(const Image<3,ScalarType,Safe> &image,const QString filename)
|
||||
{
|
||||
QImage qimage;
|
||||
convert_RGB_to_QImage(image,qimage);
|
||||
bool success = qimage.save(filename);
|
||||
assert(success);
|
||||
if(Safe){
|
||||
if(!success) throw ImageException("cannot save image");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
//// queste le tengo commentate perche` ora non mi servono
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline bool saveQtRGBA(const Image<4,ScalarType,Safe> &image,const QString filename)
|
||||
//{
|
||||
// QImage qimage;
|
||||
// convert_RGBA_to_QImage(image,qimage);
|
||||
// bool success = qimage.save(filename);
|
||||
// assert(success);
|
||||
// if(Safe){
|
||||
// if(!success) throw ImageException("cannot save image");
|
||||
// }
|
||||
// return success;
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline bool saveQtY(const Image<1,ScalarType,Safe> &image,const char *filename)
|
||||
//{
|
||||
// return saveQtY(image,QString(filename));
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline bool saveQtRGB(const Image<3,ScalarType,Safe> &image,const char *filename)
|
||||
//{
|
||||
// return saveQtRGB(image,QString(filename));
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline bool saveQtRGBA(const Image<4,ScalarType,Safe> &image,const char *filename)
|
||||
//{
|
||||
// return saveQtRGBA(image,QString(filename));
|
||||
//}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool savePGM(const Image<1,ScalarType,Safe> &image, const QString filename)
|
||||
{
|
||||
assert(image.isValid());
|
||||
assert(image.attributes.hasRange(ScalarType(0.0),ScalarType(255.0)));
|
||||
assert(filename.endsWith(".pgm",Qt::CaseInsensitive));
|
||||
if(Safe){
|
||||
if(!image.isValid()) throw ImageException("Invalid image");
|
||||
if(!image.attributes.hasRange(ScalarType(0.0),ScalarType(255.0))) throw ImageException("Invalid range attribute");
|
||||
if(!filename.endsWith(".pgm",Qt::CaseInsensitive)) throw ImageException("filename is not .pgm");
|
||||
}
|
||||
using namespace std;
|
||||
ofstream file (filename.toStdString().c_str(), ios::out|ios::binary|ios::trunc);
|
||||
if (file.is_open()) {
|
||||
QString header = QString("P5 %1 %2 255\n").arg(image.width()).arg(image.height());
|
||||
file << header.toStdString().c_str();
|
||||
|
||||
for (int y_coord = 0; y_coord < image.height(); ++y_coord)
|
||||
for (int x_coord = 0; x_coord < image.width(); ++x_coord){
|
||||
unsigned char v = static_cast<unsigned char>(valueAsInt(clampValue(image.getValue(x_coord,y_coord,0))));
|
||||
file << v;
|
||||
}
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
if(Safe)
|
||||
throw ImageException("Unable to open file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// range and gamma aware I/O
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void open_and_normalize_range_Y(const QString filename, Image<1,ScalarType,Safe> &range_0_1_image)
|
||||
{
|
||||
Image<1,ScalarType,Safe> range_0_255_image;
|
||||
openQtY(filename,range_0_255_image);
|
||||
convert_range_0_255_to_0_1(range_0_255_image,range_0_1_image);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void open_and_normalize_range_RGB(const QString filename, Image<3,ScalarType,Safe> &range_0_1_image)
|
||||
{
|
||||
Image<3,ScalarType,Safe> range_0_255_image;
|
||||
openQtRGB(filename,range_0_255_image);
|
||||
convert_range_0_255_to_0_1(range_0_255_image,range_0_1_image);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline void open_normalize_range_and_SRGB_linearize_RGB(const QString filename, Image<3,ScalarType,Safe> &linear_image)
|
||||
{
|
||||
Image<3,ScalarType,Safe> range_0_1_image;
|
||||
open_and_normalize_range_RGB(filename, range_0_1_image);
|
||||
range_0_1_image.attributes.setColorspace(img::SRGB); // assumes sRGB colorspace for gamma compression
|
||||
convert_gamma_precompensated_srgb_to_linear_srgb(range_0_1_image,linear_image);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool adjust_range_and_save_PGM(const Image<1,ScalarType,Safe> &range_0_1_image, const QString filename)
|
||||
{
|
||||
Image<1,ScalarType,Safe> range_0_255_image;
|
||||
convert_range_0_1_to_0_255(range_0_1_image,range_0_255_image);
|
||||
return savePGM(range_0_255_image,filename);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool SRGB_compress_adjust_range_and_save_PGM(const Image<1,ScalarType,Safe> &linear_image, const QString filename)
|
||||
{
|
||||
Image<1,ScalarType,Safe> range_0_1_image;
|
||||
convert_linear_srgb_to_gamma_precompensated_srgb(linear_image,range_0_1_image);
|
||||
return adjust_range_and_save_PGM(range_0_1_image,filename);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool adjust_range_and_save_RGB(const Image<3,ScalarType,Safe> &range_0_1_image, const QString filename)
|
||||
{
|
||||
Image<3,ScalarType,Safe> range_0_255_image;
|
||||
convert_range_0_1_to_0_255(range_0_1_image,range_0_255_image);
|
||||
return saveQtRGB(range_0_255_image,filename);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool SRGB_compress_adjust_range_and_save_RGB(const Image<3,ScalarType,Safe> &linear_image,const QString filename)
|
||||
{
|
||||
Image<3,ScalarType,Safe> range_0_1_image;
|
||||
convert_linear_srgb_to_gamma_precompensated_srgb(linear_image,range_0_1_image);
|
||||
return adjust_range_and_save_RGB(range_0_1_image,filename);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool adjust_range_and_save_Y(const Image<1,ScalarType,Safe> &range_0_1_image, const QString filename)
|
||||
{
|
||||
Image<1,ScalarType,Safe> range_0_255_image;
|
||||
convert_range_0_1_to_0_255(range_0_1_image,range_0_255_image);
|
||||
return saveQtY(range_0_255_image,filename);
|
||||
}
|
||||
|
||||
template<typename ScalarType, bool Safe>
|
||||
inline bool SRGB_compress_adjust_range_and_save_Y(const Image<1,ScalarType,Safe> &linear_image,const QString filename)
|
||||
{
|
||||
Image<1,ScalarType,Safe> range_0_1_image;
|
||||
convert_linear_srgb_to_gamma_precompensated_srgb(linear_image,range_0_1_image);
|
||||
return adjust_range_and_save_Y(range_0_1_image,filename);
|
||||
}
|
||||
|
||||
//// queste le tengo commentate perche` ora non mi servono
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline void open_normalize_range_and_SRGB_linearize_Y(const QString filename, Image<1,ScalarType,Safe> &linear_image)
|
||||
//{
|
||||
// Image<1,ScalarType,Safe> range_0_255_image, range_0_1_image;
|
||||
// openQtY(filename,range_0_255_image);
|
||||
// range_0_255_image.attributes.setColorspace(img::SRGB); // assumes sRGB colorspace (for gamma compression)
|
||||
// convert_range_0_255_to_0_1(range_0_255_image,range_0_1_image);
|
||||
// convert_gamma_precompensated_srgb_to_linear_srgb(range_0_1_image,linear_image);
|
||||
//}
|
||||
//
|
||||
//template<typename ScalarType, bool Safe>
|
||||
//inline bool SRGB_compress_adjust_range_and_save_Y(const Image<1,ScalarType,Safe> &linear_image,const QString filename)
|
||||
//{
|
||||
// Image<1,ScalarType,Safe> range_0_1_image, range_0_255_image;
|
||||
// convert_linear_srgb_to_gamma_precompensated_srgb(linear_image,range_0_1_image);
|
||||
// convert_range_0_1_to_0_255(range_0_1_image,range_0_255_image);
|
||||
// return aveQtY(range_0_255_image,filename);
|
||||
//}
|
||||
//
|
||||
|
||||
///// queste chi gli serve se le riimplementa, ora non c'ho tempo
|
||||
//template <class PIXELTYPE, bool SAFE>
|
||||
//inline void dumpNormalized(const Image<PIXELTYPE,SAFE> &image,const QString filename)
|
||||
//{
|
||||
// save(image::getNormalized(image),filename);
|
||||
//}
|
||||
//
|
||||
//template <class PIXELTYPE, bool SAFE>
|
||||
//inline void dumpNormalized(const Image<PIXELTYPE,SAFE> &image,const char *filename)
|
||||
//{
|
||||
// saveNormalized(image,QString(filename));
|
||||
//}
|
||||
//
|
||||
//template <class PIXELTYPE, bool SAFE>
|
||||
//inline void dumpAsRaw(const Image<PIXELTYPE,SAFE> &image,const QString filename)
|
||||
//{
|
||||
// dumpAsRaw(image,filename.toStdString().c_str());
|
||||
//}
|
||||
//
|
||||
//template <class PIXELTYPE, bool SAFE>
|
||||
//inline void dumpAsAscii(const Image<PIXELTYPE,SAFE> &image,const QString filename)
|
||||
//{
|
||||
// dumpAsAscii(image,filename.toStdString().c_str());
|
||||
//}
|
||||
//
|
||||
|
||||
} //end namespace img
|
||||
|
||||
#endif /*IMG_QT_IO_H_*/
|
||||
@@ -0,0 +1,230 @@
|
||||
#include <wrap/qt/outline2_rasterizer.h>
|
||||
#include <wrap/qt/col_qt_convert.h>
|
||||
#include <vcg/space/color4.h>
|
||||
#include <wrap/qt/col_qt_convert.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace vcg;
|
||||
using namespace std;
|
||||
|
||||
void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
|
||||
float scale,
|
||||
int rast_i,
|
||||
int rotationNum,
|
||||
int gutterWidth)
|
||||
{
|
||||
|
||||
gutterWidth *= 2; // since the brush is centered on the outline multiply the given value by 2
|
||||
|
||||
float rotRad = M_PI*2.0f*float(rast_i) / float(rotationNum);
|
||||
|
||||
//get polygon's BB, rotated according to the input parameter
|
||||
Box2f bb;
|
||||
vector<Point2f> pointvec = poly.getPoints();
|
||||
for(size_t i=0;i<pointvec.size();++i) {
|
||||
Point2f pp=pointvec[i];
|
||||
pp.Rotate(rotRad);
|
||||
bb.Add(pp);
|
||||
}
|
||||
|
||||
//create the polygon to print it
|
||||
QVector<QPointF> points;
|
||||
vector<Point2f> newpoints = poly.getPoints();
|
||||
for (size_t i = 0; i < newpoints.size(); i++) {
|
||||
points.push_back(QPointF(newpoints[i].X(), newpoints[i].Y()));
|
||||
}
|
||||
|
||||
// Compute the raster space size by rounding up the scaled bounding box size
|
||||
// and adding the gutter width.
|
||||
int sizeX = (int)ceil(bb.DimX()*scale);
|
||||
int sizeY = (int)ceil(bb.DimY()*scale);
|
||||
int safetyBuffer = 2;
|
||||
sizeX += (gutterWidth + safetyBuffer);
|
||||
sizeY += (gutterWidth + safetyBuffer);
|
||||
|
||||
QImage img(sizeX,sizeY,QImage::Format_RGB32);
|
||||
QColor backgroundColor(Qt::transparent);
|
||||
img.fill(backgroundColor);
|
||||
|
||||
///SETUP OF DRAWING PROCEDURE
|
||||
QPainter painter;
|
||||
painter.begin(&img);
|
||||
{
|
||||
QBrush br;
|
||||
br.setStyle(Qt::SolidPattern);
|
||||
br.setColor(Qt::yellow);
|
||||
|
||||
QPen qp;
|
||||
qp.setWidthF(0);
|
||||
qp.setWidth(gutterWidth);
|
||||
qp.setCosmetic(true);
|
||||
qp.setColor(Qt::yellow);
|
||||
qp.setJoinStyle(Qt::MiterJoin);
|
||||
qp.setMiterLimit(0);
|
||||
|
||||
painter.setBrush(br);
|
||||
painter.setPen(qp);
|
||||
|
||||
painter.resetTransform();
|
||||
painter.translate(QPointF(-(bb.min.X()*scale) + (gutterWidth + safetyBuffer)/2.0f, -(bb.min.Y()*scale) + (gutterWidth + safetyBuffer)/2.0f));
|
||||
painter.rotate(math::ToDeg(rotRad));
|
||||
painter.scale(scale,scale);
|
||||
|
||||
painter.drawPolygon(QPolygonF(points));
|
||||
}
|
||||
painter.end();
|
||||
|
||||
// workaround/hack to avoid ``disappearing'' primitives: use a cosmetic pen to
|
||||
// draw the poly boundary.
|
||||
// The proper way to do this would be to use conservative reasterization, which
|
||||
// Qt doesn't seem to support
|
||||
std::vector<QPointF> lines;
|
||||
for (int i = 1; i < points.size(); ++i) {
|
||||
lines.push_back(points[i-1]);
|
||||
lines.push_back(points[i]);
|
||||
}
|
||||
lines.push_back(points.back());
|
||||
lines.push_back(points.front());
|
||||
|
||||
painter.begin(&img);
|
||||
{
|
||||
QBrush br;
|
||||
br.setStyle(Qt::SolidPattern);
|
||||
br.setColor(Qt::yellow);
|
||||
|
||||
QPen qp;
|
||||
qp.setWidthF(0);
|
||||
qp.setWidth(std::max(1, gutterWidth));
|
||||
qp.setCosmetic(true);
|
||||
qp.setColor(Qt::yellow);
|
||||
|
||||
painter.setBrush(br);
|
||||
painter.setPen(qp);
|
||||
|
||||
painter.resetTransform();
|
||||
painter.translate(QPointF(-(bb.min.X()*scale) + (gutterWidth + safetyBuffer)/2.0f, -(bb.min.Y()*scale) + (gutterWidth + safetyBuffer)/2.0f));
|
||||
painter.rotate(math::ToDeg(rotRad));
|
||||
painter.scale(scale,scale);
|
||||
|
||||
//painter.drawPoints(QPolygonF(points));
|
||||
painter.drawLines(lines.data(), lines.size()/2);
|
||||
}
|
||||
painter.end();
|
||||
|
||||
// Cropping
|
||||
|
||||
/*
|
||||
// Slower version
|
||||
int minX = img.width();
|
||||
int minY = img.height();
|
||||
int maxX = -1;
|
||||
int maxY = -1;
|
||||
|
||||
for (int i = 0; i < img.height(); ++i) {
|
||||
const QRgb *line = reinterpret_cast<const QRgb*>(img.scanLine(i));
|
||||
for (int j = 0; j < img.width(); ++j) {
|
||||
if (line[j] != backgroundColor.rgb()) {
|
||||
if (j < minX) minX = j;
|
||||
if (j > maxX) maxX = j;
|
||||
if (i < minY) minY = i;
|
||||
if (i > maxY) maxY = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int minX = img.width();
|
||||
int minY = img.height();
|
||||
int maxX = 0;
|
||||
int maxY = 0;
|
||||
|
||||
for (int i = 0; i < img.height(); ++i) {
|
||||
const QRgb *line = reinterpret_cast<const QRgb*>(img.scanLine(i));
|
||||
for (int j = 0; j < img.width(); ++j) {
|
||||
if (line[j] != backgroundColor.rgb()) {
|
||||
minY = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (minY < img.height()) break;
|
||||
}
|
||||
|
||||
for (int i = img.height() - 1; i >= 0; --i) {
|
||||
const QRgb *line = reinterpret_cast<const QRgb*>(img.scanLine(i));
|
||||
for (int j = 0; j < img.width(); ++j) {
|
||||
if (line[j] != backgroundColor.rgb()) {
|
||||
maxY = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (maxY > 0) break;
|
||||
}
|
||||
|
||||
for (int i = minY; i <= maxY; ++i) {
|
||||
const QRgb *line = reinterpret_cast<const QRgb*>(img.scanLine(i));
|
||||
for (int j = 0; j < minX; ++j)
|
||||
if (line[j] != backgroundColor.rgb() && j < minX) {
|
||||
minX = j;
|
||||
break;
|
||||
}
|
||||
for (int j = img.width() - 1; j >= maxX; --j)
|
||||
if (line[j] != backgroundColor.rgb() && j > maxX) {
|
||||
maxX = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert (minX <= maxX && minY <= maxY);
|
||||
|
||||
int imgW = (maxX - minX) + 1;
|
||||
int imgH = (maxY - minY) + 1;
|
||||
|
||||
{
|
||||
QImage imgcp = img.copy(0, 0, img.width(), img.height());
|
||||
img = imgcp.copy(minX, minY, imgW, imgH);
|
||||
}
|
||||
|
||||
//create the first grid, which will then be rotated 3 times.
|
||||
//we will reuse this grid to create the rasterizations corresponding to this one rotated by 90/180/270°
|
||||
vector<vector<int> > tetrisGrid;
|
||||
QRgb yellow = QColor(Qt::yellow).rgb();
|
||||
tetrisGrid.resize(img.height());
|
||||
for (int k = 0; k < img.height(); k++) {
|
||||
tetrisGrid[k].resize(img.width(), 0);
|
||||
}
|
||||
for (int y = 0; y < img.height(); y++) {
|
||||
const uchar* line = img.scanLine(y);
|
||||
for(int x = 0; x < img.width(); ++x) {
|
||||
if (((QRgb*)line)[x] == yellow) {
|
||||
tetrisGrid[y][x] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create the 4 rasterizations (one every 90°) using the discrete representation grid we've just created
|
||||
int rotationOffset = rotationNum/4;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (j != 0) {
|
||||
tetrisGrid = rotateGridCWise(tetrisGrid);
|
||||
}
|
||||
//add the grid to the poly's vector of grids
|
||||
poly.getGrids(rast_i + rotationOffset*j) = tetrisGrid;
|
||||
|
||||
//initializes bottom/left/deltaX/deltaY vectors of the poly, for the current rasterization
|
||||
poly.initFromGrid(rast_i + rotationOffset*j);
|
||||
}
|
||||
}
|
||||
|
||||
// rotates the grid 90 degree clockwise (by simple swap)
|
||||
// used to lower the cost of rasterization.
|
||||
vector<vector<int> > QtOutline2Rasterizer::rotateGridCWise(vector< vector<int> >& inGrid) {
|
||||
vector<vector<int> > outGrid(inGrid[0].size());
|
||||
for (size_t i = 0; i < inGrid[0].size(); i++) {
|
||||
outGrid[i].reserve(inGrid.size());
|
||||
for (size_t j = 0; j < inGrid.size(); j++) {
|
||||
outGrid[i].push_back(inGrid[inGrid.size() - j - 1][i]);
|
||||
}
|
||||
}
|
||||
return outGrid;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef QTPOLYRASTERIZER_H
|
||||
#define QTPOLYRASTERIZER_H
|
||||
|
||||
#include <QImage>
|
||||
//#include <QSvgGenerator>
|
||||
#include <QPainter>
|
||||
#include <vcg/space/point2.h>
|
||||
#include <vcg/space/color4.h>
|
||||
#include <vcg/space/box2.h>
|
||||
#include <vcg/math/similarity2.h>
|
||||
#include <vcg/space/rasterized_outline2_packer.h>
|
||||
|
||||
///this class is used to draw polygons on an image could be vectorial or not
|
||||
class QtOutline2Rasterizer
|
||||
{
|
||||
public:
|
||||
static void rasterize(vcg::RasterizedOutline2 &poly,
|
||||
float scaleFactor,
|
||||
int rast_i, int rotationNum, int gutterWidth);
|
||||
|
||||
static std::vector<std::vector<int> > rotateGridCWise(std::vector< std::vector<int> >& inGrid);
|
||||
};
|
||||
#endif // QTPOLYRASTERIZER_H
|
||||
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004-2016 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __QT_THREAD_SAFE_MEMORY_INFO_H
|
||||
#define __QT_THREAD_SAFE_MEMORY_INFO_H
|
||||
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <wrap/system/memory_info.h>
|
||||
|
||||
namespace vcg
|
||||
{
|
||||
class QtThreadSafeMemoryInfo : public vcg::NotThreadSafeMemoryInfo
|
||||
{
|
||||
public:
|
||||
QtThreadSafeMemoryInfo(std::ptrdiff_t originalmem)
|
||||
:vcg::NotThreadSafeMemoryInfo(originalmem),lock(QReadWriteLock::Recursive)
|
||||
{
|
||||
}
|
||||
|
||||
~QtThreadSafeMemoryInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void acquiredMemory(std::ptrdiff_t mem)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
vcg::NotThreadSafeMemoryInfo::acquiredMemory(mem);
|
||||
}
|
||||
|
||||
std::ptrdiff_t usedMemory() const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return vcg::NotThreadSafeMemoryInfo::usedMemory();
|
||||
}
|
||||
|
||||
std::ptrdiff_t currentFreeMemory() const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return vcg::NotThreadSafeMemoryInfo::currentFreeMemory();
|
||||
}
|
||||
|
||||
void releasedMemory(std::ptrdiff_t mem = 0)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
vcg::NotThreadSafeMemoryInfo::releasedMemory(mem);
|
||||
}
|
||||
|
||||
bool isAdditionalMemoryAvailable(std::ptrdiff_t mem)
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
return vcg::NotThreadSafeMemoryInfo::isAdditionalMemoryAvailable(mem);
|
||||
}
|
||||
private:
|
||||
//mutable objects can be modified from the declared const functions
|
||||
//in this way we have not to modified the basic vcg::MemoryInfo interface for the logically const functions
|
||||
//whose need to lock the mutex for a simple reading operation
|
||||
mutable QReadWriteLock lock;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
/***************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004-2014 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __QT_THREAD_SAFE_RENDERER_H
|
||||
#define __QT_THREAD_SAFE_RENDERER_H
|
||||
|
||||
|
||||
#include <wrap/qt/qt_thread_safe_memory_info.h>
|
||||
#include <wrap/qt/qt_thread_safe_texture_names_container.h>
|
||||
#include <wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h>
|
||||
#include <QString>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
namespace vcg
|
||||
{
|
||||
template<typename MESH_TYPE,typename UNIQUE_VIEW_ID_TYPE,typename GL_OPTIONS_DERIVED_TYPE = vcg::RenderingModalityGLOptions>
|
||||
class QtThreadSafeGLMeshAttributesMultiViewerBOManager : public vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>
|
||||
{
|
||||
public:
|
||||
QtThreadSafeGLMeshAttributesMultiViewerBOManager(MESH_TYPE& mesh,QtThreadSafeMemoryInfo& gpumeminfo,size_t perbatchtriangles)
|
||||
:vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>(mesh,gpumeminfo,perbatchtriangles),_lock(QReadWriteLock::Recursive)
|
||||
{
|
||||
}
|
||||
|
||||
~QtThreadSafeGLMeshAttributesMultiViewerBOManager() {}
|
||||
|
||||
void meshAttributesUpdated(bool hasmeshconnectivitychanged,const GLMeshAttributesInfo::RendAtts& changedrendatts)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::meshAttributesUpdated(hasmeshconnectivitychanged, changedrendatts);
|
||||
}
|
||||
|
||||
bool getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt) const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::getPerViewInfo(viewid,dt);
|
||||
}
|
||||
|
||||
void setPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,const PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::setPerViewInfo(viewid,dt);
|
||||
}
|
||||
|
||||
void setPerAllViewsInfo(const PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE, UNIQUE_VIEW_ID_TYPE, GL_OPTIONS_DERIVED_TYPE>::setPerAllViewsInfo(dt);
|
||||
}
|
||||
|
||||
void removeView(UNIQUE_VIEW_ID_TYPE viewid)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::removeView(viewid);
|
||||
}
|
||||
|
||||
void draw(UNIQUE_VIEW_ID_TYPE viewid) const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::draw(viewid,_textids.textId());
|
||||
}
|
||||
|
||||
void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid,const PerViewData<GL_OPTIONS_DERIVED_TYPE>& dt) const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::drawAllocatedAttributesSubset(viewid,dt,_textids.textId());
|
||||
}
|
||||
|
||||
|
||||
bool isBORenderingAvailable() const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::isBORenderingAvailable();
|
||||
}
|
||||
|
||||
bool manageBuffers()
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
return vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::manageBuffers();
|
||||
}
|
||||
|
||||
void removeAllViewsAndDeallocateBO()
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::removeAllViews();
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::manageBuffers();
|
||||
}
|
||||
|
||||
inline vcg::QtThreadSafeTextureNamesContainer& textureIDContainer() {return _textids;}
|
||||
|
||||
void setTrMatrix(const vcg::Matrix44<typename MESH_TYPE::ScalarType>& tr)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::setTrMatrix(tr);
|
||||
}
|
||||
|
||||
void setGLOptions(UNIQUE_VIEW_ID_TYPE viewid,const GL_OPTIONS_DERIVED_TYPE& opts)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::setGLOptions(viewid,opts);
|
||||
}
|
||||
|
||||
void setDebugMode(bool activatedebugmodality)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::setDebugMode(activatedebugmodality);
|
||||
}
|
||||
|
||||
void getLog(GLMeshAttributesInfo::DebugInfo& info)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager<MESH_TYPE,UNIQUE_VIEW_ID_TYPE,GL_OPTIONS_DERIVED_TYPE>::getLog(info);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable QReadWriteLock _lock;
|
||||
vcg::QtThreadSafeTextureNamesContainer _textids;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/***************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2004-2014 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __QT_THREAD_SAFE_TEXTURE_NAMES_CONTAINER_H
|
||||
#define __QT_THREAD_SAFE_TEXTURE_NAMES_CONTAINER_H
|
||||
|
||||
#include <vector>
|
||||
#include <wrap/qt/qt_thread_safe_memory_info.h>
|
||||
|
||||
namespace vcg
|
||||
{
|
||||
struct QtThreadSafeTextureNamesContainer
|
||||
{
|
||||
QtThreadSafeTextureNamesContainer()
|
||||
:_tmid(),_lock(QReadWriteLock::Recursive)
|
||||
{
|
||||
_tmid.push_back(0);
|
||||
}
|
||||
|
||||
~QtThreadSafeTextureNamesContainer()
|
||||
{
|
||||
}
|
||||
|
||||
void push_back(GLuint textid)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
_tmid.push_back(textid);
|
||||
}
|
||||
|
||||
GLuint remove(GLuint textid)
|
||||
{
|
||||
QWriteLocker locker(&_lock);
|
||||
std::vector<GLuint>::iterator it = std::find(_tmid.begin(),_tmid.end(),textid);
|
||||
GLuint res = 0;
|
||||
if (it != _tmid.end())
|
||||
{
|
||||
res = *it;
|
||||
_tmid.erase(it);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return _tmid.size();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return _tmid.empty();
|
||||
}
|
||||
|
||||
GLuint operator[](size_t ii) const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return _tmid[ii];
|
||||
};
|
||||
|
||||
////WARNING! By itself when i exit from the function scope the returned vector is NOT thread-safe!!!!
|
||||
////BUT after i use it in another function that is thread-safe again, so it should not be problems...maybe...
|
||||
const std::vector<GLuint>& textId() const
|
||||
{
|
||||
QReadLocker locker(&_lock);
|
||||
return _tmid;
|
||||
}
|
||||
private:
|
||||
std::vector<GLuint> _tmid;
|
||||
mutable QReadWriteLock _lock;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,226 @@
|
||||
#ifndef SHOT_QT_H
|
||||
#define SHOT_QT_H
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QStringList>
|
||||
|
||||
#include <vcg/math/shot.h>
|
||||
|
||||
/** This function read a shot from a parsed XML node.
|
||||
|
||||
*/
|
||||
|
||||
template <class ShotType>
|
||||
bool ReadShotFromQDomNode(
|
||||
ShotType &shot, /// the shot that will contain the read node
|
||||
const QDomNode &node) /// The XML node to be read
|
||||
{
|
||||
typedef typename ShotType::ScalarType ScalarType;
|
||||
typedef vcg::Point3<typename ShotType::ScalarType> Point3x;
|
||||
if(QString::compare(node.nodeName(),"VCGCamera")==0)
|
||||
{
|
||||
QDomNamedNodeMap attr = node.attributes();
|
||||
if (attr.contains("BinaryData") && attr.namedItem("BinaryData").nodeValue().toInt() == 1)
|
||||
{
|
||||
Point3x tra;
|
||||
QString str = attr.namedItem("TranslationVector").nodeValue();
|
||||
QByteArray value = QByteArray::fromBase64(str.toLocal8Bit());
|
||||
memcpy(tra.V(), value.data(), sizeof(ScalarType) * 3);
|
||||
shot.Extrinsics.SetTra(-tra);
|
||||
|
||||
vcg::Matrix44<ScalarType> rot;
|
||||
str = attr.namedItem("RotationMatrix").nodeValue();
|
||||
value = QByteArray::fromBase64(str.toLocal8Bit());
|
||||
memcpy(rot.V(), value.data(), sizeof(ScalarType) * 16);
|
||||
shot.Extrinsics.SetRot(rot);
|
||||
|
||||
vcg::Camera<ScalarType> &cam = shot.Intrinsics;
|
||||
if (attr.contains("CameraType")) {
|
||||
int tmp = attr.namedItem("CameraType").nodeValue().toInt();
|
||||
cam.cameraType = static_cast<typename vcg::Camera<ScalarType>::CameraType>(tmp);
|
||||
}
|
||||
memcpy(&cam.FocalMm, QByteArray::fromBase64(attr.namedItem("FocalMm").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType));
|
||||
memcpy(&cam.ViewportPx, QByteArray::fromBase64(attr.namedItem("ViewportPx").nodeValue().toLocal8Bit()).data(), sizeof(int) * 2);
|
||||
memcpy(&cam.CenterPx, QByteArray::fromBase64(attr.namedItem("CenterPx").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType)*2);
|
||||
memcpy(&cam.PixelSizeMm, QByteArray::fromBase64(attr.namedItem("PixelSizeMm").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType) * 2);
|
||||
memcpy(&cam.k[0], QByteArray::fromBase64(attr.namedItem("LensDistortion").nodeValue().toLocal8Bit()).data(), sizeof(ScalarType) * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Point3x tra;
|
||||
tra[0] = attr.namedItem("TranslationVector").nodeValue().section(' ', 0, 0).toDouble();
|
||||
tra[1] = attr.namedItem("TranslationVector").nodeValue().section(' ', 1, 1).toDouble();
|
||||
tra[2] = attr.namedItem("TranslationVector").nodeValue().section(' ', 2, 2).toDouble();
|
||||
shot.Extrinsics.SetTra(-tra);
|
||||
|
||||
vcg::Matrix44<ScalarType> rot;
|
||||
QStringList values = attr.namedItem("RotationMatrix").nodeValue().split(" ", Qt::SkipEmptyParts);
|
||||
for (int y = 0; y < 4; y++)
|
||||
for (int x = 0; x < 4; x++)
|
||||
rot[y][x] = values[x + 4 * y].toDouble();
|
||||
shot.Extrinsics.SetRot(rot);
|
||||
|
||||
vcg::Camera<ScalarType> &cam = shot.Intrinsics;
|
||||
if (attr.contains("CameraType")) {
|
||||
int tmp = attr.namedItem("CameraType").nodeValue().toInt();
|
||||
cam.cameraType = static_cast<typename vcg::Camera<ScalarType>::CameraType>(tmp);
|
||||
}
|
||||
cam.FocalMm = attr.namedItem("FocalMm").nodeValue().toDouble();
|
||||
cam.ViewportPx.X() = attr.namedItem("ViewportPx").nodeValue().section(' ', 0, 0).toInt();
|
||||
cam.ViewportPx.Y() = attr.namedItem("ViewportPx").nodeValue().section(' ', 1, 1).toInt();
|
||||
cam.CenterPx[0] = attr.namedItem("CenterPx").nodeValue().section(' ', 0, 0).toDouble();
|
||||
cam.CenterPx[1] = attr.namedItem("CenterPx").nodeValue().section(' ', 1, 1).toDouble();
|
||||
cam.PixelSizeMm[0] = attr.namedItem("PixelSizeMm").nodeValue().section(' ', 0, 0).toDouble();
|
||||
cam.PixelSizeMm[1] = attr.namedItem("PixelSizeMm").nodeValue().section(' ', 1, 1).toDouble();
|
||||
cam.k[0] = attr.namedItem("LensDistortion").nodeValue().section(' ', 0, 0).toDouble();
|
||||
cam.k[1] = attr.namedItem("LensDistortion").nodeValue().section(' ', 1, 1).toDouble();
|
||||
}
|
||||
// scale correction should no more exist !!!
|
||||
// float scorr = attr.namedItem("ScaleCorr").nodeValue().toDouble();
|
||||
// if(scorr != 0.0) {
|
||||
// cam.PixelSizeMm[0] *= scorr;
|
||||
// cam.PixelSizeMm[1] *= scorr;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// TEXALIGN VERSION
|
||||
template <class ShotType>
|
||||
bool ReadShotFromOLDXML( ShotType &shot, const QDomNode &node)
|
||||
{
|
||||
typedef typename ShotType::ScalarType ScalarType;
|
||||
|
||||
if(QString::compare(node.nodeName(),"CamParam")==0)
|
||||
{
|
||||
QDomNamedNodeMap attr = node.attributes();
|
||||
vcg::Point3<ScalarType> tra;
|
||||
tra[0] = attr.namedItem("SimTra").nodeValue().section(' ',0,0).toDouble();
|
||||
tra[1] = attr.namedItem("SimTra").nodeValue().section(' ',1,1).toDouble();
|
||||
tra[2] = attr.namedItem("SimTra").nodeValue().section(' ',2,2).toDouble();
|
||||
shot.Extrinsics.SetTra(-tra);
|
||||
|
||||
vcg::Matrix44<ScalarType> rot;
|
||||
QStringList values = attr.namedItem("SimRot").nodeValue().split(" ", QString::SkipEmptyParts);
|
||||
for(int y = 0; y < 4; y++)
|
||||
for(int x = 0; x < 4; x++)
|
||||
rot[y][x] = values[x + 4*y].toDouble();
|
||||
shot.Extrinsics.SetRot(rot);
|
||||
|
||||
vcg::Camera<ScalarType> &cam = shot.Intrinsics;
|
||||
cam.FocalMm = attr.namedItem("Focal").nodeValue().toDouble();
|
||||
cam.ViewportPx.X() = attr.namedItem("Viewport").nodeValue().section(' ',0,0).toInt();
|
||||
cam.ViewportPx.Y() = attr.namedItem("Viewport").nodeValue().section(' ',1,1).toInt();
|
||||
cam.CenterPx[0] = attr.namedItem("Center").nodeValue().section(' ',0,0).toInt();
|
||||
cam.CenterPx[1] = attr.namedItem("Center").nodeValue().section(' ',1,1).toInt();
|
||||
cam.PixelSizeMm[0] = attr.namedItem("ScaleF").nodeValue().section(' ',0,0).toDouble();
|
||||
cam.PixelSizeMm[1] = attr.namedItem("ScaleF").nodeValue().section(' ',1,1).toDouble();
|
||||
cam.k[0] = attr.namedItem("LensDist").nodeValue().section(' ',0,0).toDouble();
|
||||
cam.k[1] = attr.namedItem("LensDist").nodeValue().section(' ',1,1).toDouble();
|
||||
|
||||
// scale correction
|
||||
float scorr = attr.namedItem("ScaleCorr").nodeValue().toDouble();
|
||||
if(scorr != 0.0) {
|
||||
cam.PixelSizeMm[0] *= scorr;
|
||||
cam.PixelSizeMm[1] *= scorr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class ShotType>
|
||||
QDomElement WriteShotToQDomNode(
|
||||
const ShotType &shot, /// the shot to be written node
|
||||
QDomDocument &doc) /// The XML node to be read
|
||||
{
|
||||
typedef typename ShotType::ScalarType ScalarType;
|
||||
|
||||
QDomElement shotElem = doc.createElement( "VCGCamera" );
|
||||
vcg::Point3<ScalarType> tra = -(shot.Extrinsics.Tra());
|
||||
QString str = QString("%1 %2 %3 1").arg(tra[0]).arg(tra[1]).arg(tra[2]);
|
||||
shotElem.setAttribute("TranslationVector", str);
|
||||
vcg::Matrix44<ScalarType> rot = shot.Extrinsics.Rot();
|
||||
str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 ")
|
||||
.arg(rot[0][0]).arg(rot[0][1]).arg(rot[0][2]).arg(rot[0][3])
|
||||
.arg(rot[1][0]).arg(rot[1][1]).arg(rot[1][2]).arg(rot[1][3])
|
||||
.arg(rot[2][0]).arg(rot[2][1]).arg(rot[2][2]).arg(rot[2][3])
|
||||
.arg(rot[3][0]).arg(rot[3][1]).arg(rot[3][2]).arg(rot[3][3]);
|
||||
shotElem.setAttribute( "RotationMatrix", str);
|
||||
|
||||
const vcg::Camera<ScalarType> &cam = shot.Intrinsics;
|
||||
|
||||
shotElem.setAttribute("CameraType", cam.cameraType);
|
||||
shotElem.setAttribute("BinaryData", 0);
|
||||
|
||||
shotElem.setAttribute( "FocalMm", cam.FocalMm);
|
||||
|
||||
str = QString("%1 %2").arg(cam.k[0]).arg(cam.k[1]);
|
||||
shotElem.setAttribute( "LensDistortion", str);
|
||||
|
||||
str = QString("%1 %2").arg(cam.PixelSizeMm[0]).arg(cam.PixelSizeMm[1]);
|
||||
shotElem.setAttribute( "PixelSizeMm", str);
|
||||
|
||||
str = QString("%1 %2").arg(cam.ViewportPx[0]).arg(cam.ViewportPx[1]);
|
||||
shotElem.setAttribute( "ViewportPx", str);
|
||||
|
||||
str = QString("%1 %2").arg(cam.CenterPx[0]).arg(cam.CenterPx[1]);
|
||||
shotElem.setAttribute( "CenterPx", str);
|
||||
|
||||
//scale correction should no more exist !!!
|
||||
//str = QString("%1").arg((double) 1);
|
||||
//shotElem.setAttribute( "ScaleCorr", str);
|
||||
return shotElem;
|
||||
}
|
||||
|
||||
|
||||
template <class ShotType>
|
||||
QDomElement WriteShotToQDomNodeBinary(
|
||||
const ShotType &shot, /// the shot to be written node
|
||||
QDomDocument &doc) /// The XML node to be read
|
||||
{
|
||||
typedef typename ShotType::ScalarType ScalarType;
|
||||
|
||||
QDomElement shotElem = doc.createElement("VCGCamera");
|
||||
vcg::Point3<ScalarType> tra = -(shot.Extrinsics.Tra());
|
||||
|
||||
QByteArray value = QByteArray::fromRawData((char *)tra.V(), sizeof(ScalarType) * 3).toBase64();
|
||||
shotElem.setAttribute("TranslationVector", QString(value));
|
||||
|
||||
vcg::Matrix44<ScalarType> rot = shot.Extrinsics.Rot();
|
||||
value = QByteArray::fromRawData((char *)rot.V(), sizeof(ScalarType) * 16).toBase64();
|
||||
shotElem.setAttribute("RotationMatrix", QString(value));
|
||||
|
||||
const vcg::Camera<ScalarType> &cam = shot.Intrinsics;
|
||||
|
||||
shotElem.setAttribute("CameraType", cam.cameraType);
|
||||
|
||||
shotElem.setAttribute("BinaryData", 1);
|
||||
|
||||
value = QByteArray::fromRawData((char *)&cam.FocalMm, sizeof(ScalarType)).toBase64();
|
||||
shotElem.setAttribute("FocalMm", QString(value));
|
||||
|
||||
value = QByteArray::fromRawData((char *)&cam.k[0], sizeof(ScalarType) * 2).toBase64();
|
||||
shotElem.setAttribute("LensDistortion", QString(value));
|
||||
|
||||
value = QByteArray::fromRawData((char *)&cam.PixelSizeMm, sizeof(ScalarType) * 2).toBase64();
|
||||
shotElem.setAttribute("PixelSizeMm", QString(value));
|
||||
|
||||
value = QByteArray::fromRawData((char *)&cam.ViewportPx, sizeof(int) * 2).toBase64();
|
||||
shotElem.setAttribute("ViewportPx", QString(value));
|
||||
|
||||
//str = QString("%1 %2").arg(cam.CenterPx[0]).arg(cam.CenterPx[1]);
|
||||
value = QByteArray::fromRawData((char *)&cam.CenterPx, sizeof(ScalarType) * 2).toBase64();
|
||||
shotElem.setAttribute("CenterPx", QString(value));
|
||||
|
||||
//scale correction should no more exist !!!
|
||||
//str = QString("%1").arg((double) 1);
|
||||
//shotElem.setAttribute( "ScaleCorr", str);
|
||||
return shotElem;
|
||||
}
|
||||
|
||||
|
||||
#endif // SHOT_QT_H
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef TOSTRING_H
|
||||
#define TOSTRING_H
|
||||
#include <QString>
|
||||
#include <cstdlib>
|
||||
|
||||
inline QString toString( const vcg::Point4f& p ){
|
||||
QString s;
|
||||
s.sprintf("%f %f %f %f", p[0], p[1], p[2], p[3]);
|
||||
return s;
|
||||
}
|
||||
inline QString toString( const vcg::Point3f& p ){
|
||||
QString s;
|
||||
s.sprintf("%f %f %f", p[0], p[1], p[2]);
|
||||
return s;
|
||||
}
|
||||
inline QString toString( const vcg::Point2f& p ){
|
||||
QString s;
|
||||
s.sprintf("%f %f", p[0], p[1]);
|
||||
return s;
|
||||
}
|
||||
inline QString toString( const vcg::Point2i& p ){
|
||||
QString s;
|
||||
s.sprintf("%d %d", p[0], p[1]);
|
||||
return s;
|
||||
}
|
||||
inline QString toString(vcg::Matrix44f& m){
|
||||
QString mat;
|
||||
for(int i=0; i<3; i++){
|
||||
mat.append( toString( m.GetRow4(i) ) );
|
||||
mat.append("\n");
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
#endif // TOSTRING_H
|
||||
@@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
* VCGLib o o *
|
||||
* Visual and Computer Graphics Library o o *
|
||||
* _ O _ *
|
||||
* Copyright(C) 2007 \/)\/ *
|
||||
* Visual Computing Lab /\/| *
|
||||
* ISTI - Italian National Research Council | *
|
||||
* \ *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||
* for more details. *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QT_TRACKBALL_H
|
||||
#define QT_TRACKBALL_H
|
||||
#include <wrap/qt/device_to_logical.h>
|
||||
|
||||
/// Transforms the event coordintates (that are device independent)
|
||||
/// into the expected framebuffer coordinates (e.g.in opengl pixels)
|
||||
/// This is necessary because trackball works in the viewport coord systems.
|
||||
inline float QT2VCG_X( QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
return QTLogicalToDevice(qw,e->x());
|
||||
}
|
||||
|
||||
/// Transforms the event coordintates (that are device independent)
|
||||
/// into the expected framebuffer coordinates (e.g.in opengl pixels)
|
||||
/// This is necessary because trackball works in the viewport coord systems.
|
||||
|
||||
inline float QT2VCG_Y( QWidget *qw, QMouseEvent *e)
|
||||
{
|
||||
return QTLogicalToDevice(qw,qw->height () - e->y ());
|
||||
}
|
||||
|
||||
/// Takes a QT MouseButton, some QT KeyboardModifiers and returns the equivalent Trackball::Button
|
||||
inline vcg::Trackball::Button QT2VCG (Qt::MouseButton qtbt, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
int vcgbt = vcg::Trackball::BUTTON_NONE;
|
||||
|
||||
if (qtbt & Qt::LeftButton) vcgbt |= vcg::Trackball::BUTTON_LEFT;
|
||||
if (qtbt & Qt::RightButton) vcgbt |= vcg::Trackball::BUTTON_RIGHT;
|
||||
if (qtbt & Qt::MidButton) vcgbt |= vcg::Trackball::BUTTON_MIDDLE;
|
||||
|
||||
if (modifiers & Qt::ShiftModifier) vcgbt |= vcg::Trackball::KEY_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier) vcgbt |= vcg::Trackball::KEY_CTRL;
|
||||
if (modifiers & Qt::AltModifier) vcgbt |= vcg::Trackball::KEY_ALT;
|
||||
|
||||
return vcg::Trackball::Button (vcgbt);
|
||||
}
|
||||
|
||||
/// Takes a QT ket and QT KeyboardModifiers and returns the mouse wheel related Trackball::Button
|
||||
inline vcg::Trackball::Button QTWheel2VCG (Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
int vcgbt = vcg::Trackball::WHEEL;
|
||||
|
||||
if (modifiers & Qt::ShiftModifier) vcgbt |= vcg::Trackball::KEY_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier) vcgbt |= vcg::Trackball::KEY_CTRL;
|
||||
if (modifiers & Qt::AltModifier) vcgbt |= vcg::Trackball::KEY_ALT;
|
||||
|
||||
return vcg::Trackball::Button (vcgbt);
|
||||
}
|
||||
|
||||
/// Takes some QT KeyboardModifiers and returns the mouse wheel related Trackball::Button
|
||||
inline vcg::Trackball::Button QTKey2VCG (int key, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
int vcgbt = 0;
|
||||
switch (key) {
|
||||
case Qt::Key_W :
|
||||
case Qt::Key_Up : vcgbt = vcg::Trackball::KEY_UP ; break;
|
||||
case Qt::Key_A :
|
||||
case Qt::Key_Left : vcgbt = vcg::Trackball::KEY_LEFT ; break;
|
||||
case Qt::Key_S :
|
||||
case Qt::Key_Down : vcgbt = vcg::Trackball::KEY_DOWN ; break;
|
||||
case Qt::Key_D :
|
||||
case Qt::Key_Right: vcgbt = vcg::Trackball::KEY_RIGHT; break;
|
||||
case Qt::Key_R :
|
||||
case Qt::Key_PageUp: vcgbt = vcg::Trackball::KEY_PGUP ; break;
|
||||
case Qt::Key_F :
|
||||
case Qt::Key_PageDown: vcgbt = vcg::Trackball::KEY_PGDOWN; break;
|
||||
default : vcgbt = 0;
|
||||
}
|
||||
|
||||
if (modifiers & Qt::ShiftModifier) vcgbt |= vcg::Trackball::KEY_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier) vcgbt |= vcg::Trackball::KEY_CTRL;
|
||||
if (modifiers & Qt::AltModifier) vcgbt |= vcg::Trackball::KEY_ALT;
|
||||
|
||||
return vcg::Trackball::Button (vcgbt);
|
||||
}
|
||||
|
||||
#endif // QT_TRACKBALL_H
|
||||
Reference in new issue
Block a user