add vcglib

This commit is contained in:
yuanlin zhong committed 2025-11-03 17:46:44 +08:00
1 parent 6f6c0c8eb7
commit af8100f851
1537 files changed
+634197

No files matched your search

+452
View File
@@ -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);
}
+127
View File
@@ -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
+100
View File
@@ -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);
}
+18
View File
@@ -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
+101
View File
@@ -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);
}
+59
View File
@@ -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");}
};
+24
View File
@@ -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
+59
View File
@@ -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
+198
View File
@@ -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
+11
View File
@@ -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_*/
+118
View File
@@ -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_*/
+264
View File
@@ -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_*/
+230
View File
@@ -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;
}
+23
View File
@@ -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
+226
View File
@@ -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
+34
View File
@@ -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
+100
View File
@@ -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