I'm trying to implement some behavior in my Qt application, where the use can resize and rotate elements that appear on the screen. I'm trying to work out how to rotate and resize a rectangle using QTransform.
First, I implemented rotation for a rectangle (with the origin at its center) as follows:
// Step 1
QRectF rect (100,100, 200, 300);
QTransform rotation;
rotation.translate(rect.center.x(), rect.center.y());
rotation.rotate(45);
rotation.translate(-rect.center.x(), -rect.center.y());
// get rotated polygon
auto polygon = rotation.mapPolygon(rect);
// draw using QPainter
painter->drawPolygon(polygon);
Now, what I would like to do is to resize the rotated rectangle along one of its edges by changing its width, but I'm not quite sure how to go about this. I would like to compute the QTransform matrix that would resize the rectangle (the only thing I worked out is that the transformation origin of the new transform needs to be set to the middle right edge of the rotated rectangle).
If you want to scale along some line that is not horizontal and not vertical, but angled to axis, you need to rotate transformation first in opposite direction by that angle, scale by axis and rotate back.
In your case you can just scale before rotating.
Related
Let's say I have five objects, with the top-left red square and the larger black square both inserted into the scene at 0,0.
.
Later, let's say I want to move the bottom right corner of the black square to the bottom right corner of the bottom-right square. The most obvious thing to do would be:
bS.setRect( bS.rect().setBottomRight(redBR.rect().bottomRight) );
That's not exactly correct code, but the idea is simple. I would set the coordinate of the black square's bottom right corner to that of the red square's bottom right corner. Because that's where I want it to be. But in Qt, this seems to be impossible.
Because the call to redBR thinks it's at the origin. Every item thinks it's at the origin. Which means I can never know the coordinates of any item, anywhere, ever.
Is there a way to force QGraphicsScene to tell me the actual coordinates? Alternatively, is there some other graphics framework that uses real coordinates? I'm not going to insist on using Qt if there is no way to make it work.
Any help would be welcome. Please bear in mind my goal is not: "drag corner of box by manipulator". My goal is to be able to put items at coordinates whenever I want an item to be at a specific coordinate.
Edit:
Here's an example of what I mean. The big box hasn't been connected yet, so don't worry about it's coordinates. The problem is that if I don't remap the points coming out of the little box, every box believes it is at the origin. But if I do, then the y values vacillate between 0, 1, and -1.
The base class QGraphicsItem has quite some useful functionality for mapping between scene and item coordinates. One useful function is for mapping a point in item coordinates to scene coordinates:
QPointF QGraphicsItem::mapToScene(const QPointF &point)
There is however also a direct mapping available between points in different QGraphicsItems, which is probably the easiest to use here:
QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &point)
which can be used to map a point in redBR to a point in bS like:
bS.rect().setBottomRight(bS.mapFromItem( &redBR, redBR.rect().bottomRight() ) )
I dont know if I am using the correct term here. However this is what I am trying to achieve and I would like some suggestions on how I could achieve that. I want to have a circle with border visible. Now here is the hard part and something I dont even know how to start with. I want to manipulate the circle in such a way that the borders of the circle are visible and its center is not (i.e Pretty much that it has a hole in it and would show what ever is placed under it)I would then like to have another image placed under the circle such that only the part of the image that is under the transparent part of the circle is shown the parts outside the transparent boundary of the circle become invisible. Any suggestions on how I could achieve this. It seems that googling isnt helping me.
I would suggest the alternative way for unmasking a circular area of an image. You can specify the clip region - the area where you need to perform painting. For example:
[..]
QPainter painter(this);
// Sample circular area.
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
[..]
painter.drawImage(0, 0, image);
[..]
This will draw only those parts of your image that are inside of the circle with radius 200. All the rest pixels will be hidden.
You can handle mouse move event to move this "circle" over the image like a loupe.
UPDATE
Below is the sample code that generates an image with circular mask and insert it into the label:
QPixmap target(500, 500); // the size may vary
QPixmap source("image.png");
QPainter painter(&target);
QRegion r(QRect(100, 100, 200, 200), QRegion::Ellipse);
painter.setClipRegion(r);
painter.drawPixmap(0, 0, source);
QLabel l;
l.setPixmap(target);
l.show();
You might want to have a look at the Composition Example.
In short you could draw the first image and then use one of the Composition Modes to draw the second image on top (or the other way around). Make sure to convert the images to ARGB32 before using them.
To make the inner Part of the Circle transparent you can adjust the Alpha Channel accordingly.
Here is a small Example using Composition mode:
QPainter p(&imageCircle);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.drawImage(image);
p.end()
Here you can find the Qt Documentation of QPainter.
I'm in trouble with such issue:
I need to select some area with rect on my label, I'm using QRubberBand to do this, but there is one problem: I need to know coordinates of current rect on my label, so I'm in trouble with it, because mouseEvent->pos() give coordinates which starts with top left corner on mainWindow border, moreover i've rotate standard coords on label (from top left to bottom left corner, as we paint them usually).
Anybody knows how can I do this translation?
QPoint mappedPos = myLabel->mapFromParent(myWindow, mouseEvent->pos());
Also, QTransform provides a number of map() functions which should be able to get you the point in rotated coordinates as well.
See:
QWidget::mapFromParent()
QTransform::map()
Like the title says, I'm drawing a pixmap onto a scene at a specific location. QT draws the pixmap by placing the top left corner of the pixmap at the point I specify. However, I want the center of the pixmap to be placed at this point instead. (Pixmap is crosshairs). Does anyone know how to do this? Thanks in advance
void QPainter::translate ( const QPointF & offset )
Translates the coordinate system by the given offset; i.e. the given offset is added to points.
painter.translate(specific_location);
painter.drawPixmap(-pixmap.rect().center(), pixmap);
Translate the specified point by half of the pixmap's width to the left and half of the pixmap's height to the top, then draw pixmap to that point. Just some maths. :)
I have a rectangle of any arbitrary width and height. I know X,Y, width, and height. How do I solve the upper right hand coordinates when the rectangle is rotated N degrees? I realized if it were axis aligned I would simply solve for (x,y+width). Unforunatly this doesn't hold true when I apply a transform matrix on the rectangle to rotate it around its center.
It's usually easiest and fastest to let Flash's display code do these kinds of things for you. Create an empty Sprite and put it inside the rectangle's display object at the corner you want to track. Then, find the location of that sprite in the coordinate space of your choice:
var p:Point = new Point(0,0);
myRectangle.myCornerSprite.localToGlobal( p );
someDisplayObject.globalToLocal( p ); // for a coord space besides the stage
This gets you out of making any assumptions about the rectangle's design (i.e. registration point), and works even if the rectangle should be skewed or scaled as well as being rotated. Plus, this will be much easier to implement and maintain then a mess of cosines and whatnot.
(Note that the code above assumes that "upper right" refers to a specific corner - if you want to examine whichever corner happens to upper-rightmost at the moment, I'd simply add do the same thing with a sprite at all four corners, and pick whichever is to the upper right in global coords.)
You just have to calculate the point on a circle for the given radius. The center of your rectangle will be the circle's origin and any corner will be a point on the circle's circumference. You need to use trigonometry to calculate the new point using the rotation. I don't have time right now to explain all this, but here is a link to a decent 2D Javascript library I've used in the past and which should give you everything you need (bearing in mind that the math is virtually the same in Javascript and ActionScript) to work it out for yourself.
http://jsdraw2d.jsfiction.com/viewsourcecode.htm