How to fill the area under the plot? - qt

I have the following code which should draw a sine function and fill it's internals - everything between this function and zero level.
But the brush which I set up does not work. Should any additional function be called? Now I have only sine function and zero level which are drawn without any filling.
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen myPen(Qt::black, 2, Qt::SolidLine);
painter.setPen(myPen);
painter.setBrush(QBrush(QColor(0, 0, 0, 20)));
QPointF* pointArray = new QPointF[251 * 2];
for (int i=0; i < 251; ++i)
{
pointArray[i].setX(i);
pointArray[i].setY(100*qSin(i/10.0));
}
for (int i = 251; i < 251*2; i++)
{
pointArray[i].setX(i - 251);
pointArray[i].setY(0);
}
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.drawPolyline(pointArray, 251*2);
}

Related

Zoom graphics processing 2.2.1

help please, at Arduino Uno I receive a signal from the sensor and build a graph using processing 2.2.1, but you need to scale up without losing proportions. My attempts failed, the proportion was crumbling(I tried to multiply the values) Code:
Serial myPort;
int xPos = 1;
int yPos = 100;
float yOld = 0;
float yNew = 0;
float inByte = 0;
int lastS = 0;
PFont f;
void setup () {
size(1200, 500);
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil('\n');
background(0xff);
}
void draw () {
int s = second();
PFont f = createFont("Arial",9,false);
textFont(f,9);
fill(0);
if (s != lastS){
stroke(0xcc, 0xcc, 0xcc);
line(xPos, yPos+10, xPos, yPos+30);
text(s + " Sec.", xPos+5, yPos+30);
lastS = s;
}
}
void mousePressed(){
save(lastS + "-heart.jpg");
}
void serialEvent (Serial myPort) {
String inString = myPort.readStringUntil('\n');
if (inString != null) {
inString = trim(inString);
if (inString.equals("!")) {
stroke(0, 0, 0xff); // blue
inByte = 1023;
} else {
stroke(0xff, 0, 0); //Set stroke to red ( R, G, B)
inByte = float(inString);
}
inByte = map(inByte, 0, 1023, 0, height);
yNew = inByte;
line(xPos-1, yPos-yOld, xPos, yPos-yNew);
yOld = yNew;
if (xPos >= width) {
xPos = 1;
yPos+=200;
if (yPos > height-200){
xPos = 1;
yPos=100;
background(0xff);
}
} else {
xPos++;
}
}
}
There are multiple ways to scale graphics.
A simple method to try is to simply scale() the rendering (drawing coordinate system).
Bare in mind currently the buffer is only cleared when the xPos reaches the right hand side of the screen.
The value from Arduino is mapped to Processing here:
inByte = map(inByte, 0, 1023, 0, height);
yNew = inByte;
you should try to map change height to a different value as you see fit.
This however will scale only the Y value. The x value is incremented here:
xPos++;
you might want to change this increment to a different value that works with the proportion you are trying maintain between x and y.

C++ blurring rectangle parts of image

I use MSER algorithm with opencv and find some rectangle parts
then I want to blur that inside rectangle.
my renctangles are vector like (x, y, width, height) but using dilate or erode need inputarray src.
how can i transform vector to inputarray src?
here is my code.
vector< vector< Point> > contours;
vector< Rect> bboxes;
Rect MserROI;
Ptr< MSER> mser = MSER::create(21, (int)(0.00002*textImg.cols*textImg.rows), (int)(0.05*textImg.cols*textImg.rows), 1, 0.7);
mser->detectRegions(textImg, contours, bboxes);
for (int i = 0; i < bboxes.size(); i++)
{
cout << bboxes[i] << '\n';
rectangle(inImg, bboxes[i], CV_RGB(0, 0, 0));
MserROI = bboxes[i];
dilate(MserROI, Mser_dil, Mat(), Point(-1, -1), 2) //error
}
I infer that you want to blur the part of the image that inside the rectangle.
If that's the case, then you need to correct the way you're declaring your ROI.
If 'inImg' is a Mat, then you can declare your ROI as follows:
for (int i = 0; i < bboxes.size(); i++)
{
rectangle(inImg, bboxes[i], CV_RGB(0, 0, 0));
Mat MserROIimg=inImg(bboxes[i]);
dilate(MserROI, Mser_dil, Mat(), Point(-1, -1), 2) //error
}
In your code, you haven't mentioned where you've declared Mser_dil, but if your error is pertaining to ROI declaration, then this should work for you

How to keep my QMainWindow always inside of the desktop?

I want to keep my QMainWindow always inside of the desktop, so I add the implementation for QMainWindow::moveEvent :
void MainWindow::moveEvent(QMoveEvent *ev)
{
if(ev->pos().x() < 0) setGeometry(0, ev->oldPos().y(), width(), height());
}
But when I move the window to out of desktop left bounding, the app is crashed.
What is wrong with this code? Why it is crashed? Is my solution correct?
//--Update:
I tried with this:
int newx = ev->pos().x(),
newy = ev->pos().y();
if(ev->pos().x() < 0) newx = 0;
if(ev->pos().y() < 0) newy = 0;
move(newx, newy);
It worked without crash but I'm not satisfied because of the moving is not smooth.
This should smoothly help with the upper left corner .. but you'll need to add some more conditions to get it working for all four sides.
posX and posY are member variables.
void MainWindow::moveStep() { // [SLOT]
int movX = 0, movY = 0;
if(posX < 0) movX = 1;
if(posY < 0) movY = 1;
move(posX + movX, posY + movY);
}
void MainWindow::moveEvent(QMoveEvent *ev) {
if(ev->pos().x() < 0 || ev->pos().y() < 0) {
posX = ev->pos().x();
posY = ev->pos().y();
QTimer::singleShot(10, this, SLOT(moveStep()));
}
}
To have it even more elegantly consider using QVariantAnimation with a QRect and setGeometry().

How to fix QTGLWidget using QTimer to decrease rendering time?

I am currently using QtOpenGL for my program. My program plots dots in the 3D space. These dots could be any number between one to several thousand. I am using the function, 'glusphere', for drawing the sphere to represent each dot.
With this, each frame is created and I need to display each frames as an animation using QTimer. This animation should be controlled by fps.For example, if fps=30, I would put t=1000/30 for QTimer's setInterval(t).Whether fps=10 or 30, I found that fps does not change my program much.
I looked for a problem by setting fps to 0 and observed how much the rendering time takes by using setInterval(0). The following is the results:
n = number of spheres
when n=10: 28ms => about 30ms
when n=100: 87ms => about 90ms
when n=150: 137ms => about 140ms
when n=1000: 598ms => about 600ms => 0.6sec
From the results above, the rendering time of each frame linearly increases with the number of spheres. The following is a part of my code:
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent)
{
setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
scale=1.0;
rot_x=0;
rot_y=0;
rot_z=0;
trans_x=0;
trans_y=0;
trans_z=0;
isloaded=false;
isplayed=false;
currentFrame=1;
sphereNum=1;
myTimer=new QTimer(this);
//fps=60;
myTimer->setInterval(0);
//myTimer->setInterval();
connect(myTimer, SIGNAL(timeout()), this, SLOT(timerEvent()));
}
void GLWidget::initializeGL()
{
qglClearColor(QColor(Qt::black));
glEnable(GL_DEPTH_TEST);
srand((unsigned)time(NULL));
//QGLFormat::setDoubleBuffer(true);
//qDebug() << "initGL context: " << this->context();
}
void GLWidget::timerEvent()
{
static QTime current_time, last_time;
int elapsed_time;
last_time=current_time;
current_time=QTime::currentTime();
elapsed_time=(current_time.second()*1000 + current_time.msec())-(last_time.second()*1000 + last_time.msec());
//qDebug() << "Timer elapsed time: " << elapsed_time;
if(isloaded && isplayed) {
if(currentFrame<markerData.frameSize) currentFrame++;
makeCurrent();
updateGL();
}
if(currentFrame==markerData.frameSize) {
isplayed=false;
myTimer->stop();
currentFrame=1;
}
}
void GLWidget::drawSphere(GLfloat x, GLfloat y, GLfloat z, GLfloat radius)
{
qglColor(Qt::yellow);
glPushMatrix();
glTranslatef(x, y, z);
gluSphere(p, radius, 10, 10);
//gluCylinder(p, 10, 10, 10, 4, 4);
glPopMatrix();
}
void GLWidget::drawMarkers() {
int markerIndex;
glPushMatrix();
/*for(int i=0; i<markerData.rowSize; i++) {
markerIndex=(currentFrame-1)*markerData.rowSize+i;
//qDebug() << markerIndex;
drawSphere(markerData.markerSet[markerIndex].x, markerData.markerSet[markerIndex].y, markerData.markerSet[markerIndex].z, 10);
}*/
for(int i=0; i<sphereNum; i++) {
markerIndex=rand()%1000;
drawSphere(markerIndex, markerIndex, markerIndex, 10);
}
glPopMatrix();
}
void GLWidget::drawText(double x, double y, double z, QString txt)
{
glDisable(GL_DEPTH_TEST);
qglColor(Qt::white);
renderText(x, y, z, txt, QFont("Arial", 12, QFont::Bold, false) );
glEnable(GL_DEPTH_TEST);
}
void GLWidget::paintGL()
{
static QTime current_time, last_time;
int elapsed_time;
float paint_fps;
//if file data is loaded
if(isloaded)
{
//calculate elapsed time drown 1 frame per second
//elapsed time is millisecond
last_time=current_time;
current_time=QTime::currentTime();
elapsed_time=(current_time.second()*1000 + current_time.msec())-(last_time.second()*1000 + last_time.msec());
paint_fps=1000/elapsed_time;
//qDebug() << "elapsed time: " << elapsed_time << " fps: " << paint_fps;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-20.0f);
glRotatef(30.0, 0.0, 1.0, 0.0);
glRotatef(15.0, 1.0, 0.0, 0.0);
glRotatef(rot_x, 1.0, 0.0, 0.0);
glRotatef(rot_y, 0.0, 1.0, 0.0);
glRotatef(rot_z, 0.0, 0.0, 1.0);
glScalef(scale, scale, scale);
glTranslatef(trans_x, trans_y, trans_z);
//draw elapsed time(ms)
glPushMatrix();
drawText(100, -300, 100, QString::number(elapsed_time) + "ms");
glPopMatrix();
//draw 3-axis
glBegin(GL_LINES);
qglColor(Qt::red);
glVertex3f(0, 0, 0);
glVertex3f(3000, 0, 0);
glEnd();
glBegin(GL_LINES);
qglColor(Qt::green);
glVertex3f(0, 0, 0);
glVertex3f(0, 3000, 0);
glEnd();
glBegin(GL_LINES);
qglColor(Qt::blue);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, 3000);
glEnd();
//draw spheres
p=gluNewQuadric();
drawMarkers();
gluDeleteQuadric(p);
//swapBuffers
if(doubleBuffer()) {
swapBuffers();
makeCurrent();
}
}
}
To clarify:
Rendering time for each frame changes depending on the number of spheres.
The number of spheres should not change the rendering time
Even though it draw 1000 spheres, it spends half second
Do you think the problem is using glusphere?
If there is another way to draw the sphere, could it be possible to do it more than 100 fps?
Could someone please explain where the bottleneck is that is creating this slow rendering?

Apply texture to grid

I would like to apply a texture to a grid in 3d space using Processing, I've tried declaring a PImage and setting the .jpg file with loadimage with no results..
PImage tex;
void setup() {
size(800, 600, P3D);
tex=loadImage("ground104");
noCursor();
}
void draw()
{
directionalLight(255, 255, 255, 0, 0, -1);
background(180);
drawPlane();
}
void drawPlane()
{ //lights();
int s = 10000;
int ss = 500;
fill(0, 200, 20); stroke(200); for(int i = 0; i < s; i += ss) {
stroke(0,100,0);
strokeWeight(3);
beginShape(QUAD_STRIP);
for(int j = 0; j <= s; j += ss)
{
texture(tex);
vertex(j, i, 0);
vertex(j, i + ss, 0);
}
endShape(); } noStroke(); }
Do you have any advice?
Thanks!
looks like you need a file extension like .jpg. You can troubleshoot by running the code from the reference page:
http://www.processing.org/reference/texture_
size(100, 100, P3D);
noStroke();
PImage img = loadImage("laDefense.jpg");
beginShape();
texture(img);
vertex(10, 20, 0, 0);
vertex(80, 5, 100, 0);
vertex(95, 90, 100, 100);
vertex(40, 95, 0, 100);
endShape();
and replace laDefense.jpg with your image name. Also, it needs to be placed in the data directory in the sketch directory. If it works, then your problem is elsewhere. I am not sure what your plan is in the sketch, but you might find peasycam useful for troubleshooting in 3d.
http://mrfeinberg.com/peasycam/
another technique is to increment a float by 0.01 per frame and call a RotateX(), Y or Z or all of the above at the beginning of your draw() method / loop.
Thank you for your reply!
I've changed my code to this and now you can run it and see what I get (first download the grass.jpg from https://www.dropbox.com/s/fsda0tih67q8tll/grass.jpg?m). I'm close but I wonder why the grid is green when it was supposed to be a grass land...
PImage tex;
void setup()
{
size(800, 600, P3D);
tex=loadImage("grass.jpg");
noCursor();
}
void draw()
{
translate(width/2 , height/2 , 0); // center of screen
rotateX(QUARTER_PI * 1.0); // move camera up
rotateZ(QUARTER_PI * 1.8);
//rotateZ(camZ.val + offset); // rotate around turret
rotateZ(map(mouseX, mouseY, width, 2.5, -2.5));
translate(-1000, 0, -1000);
directionalLight(255, 255, 255, 0, 0, -1);
background(180);
drawPlane();
}
void drawPlane()
{ //lights();
int s = 10000;
int ss = 500;
fill(0, 200, 20); stroke(200); for(int i = 0; i < s; i += ss) {
stroke(0,100,0);
strokeWeight(3);
beginShape(QUAD_STRIP);
for(int j = 0; j <= s; j += ss)
{
texture(tex);
vertex(j, i, 0);
vertex(j, i + ss, 0);
}
endShape();
}
noStroke();
}

Resources