Tracing an outline using Qt Graphics - c++

I'm creating a comic book editor. I want to be able to use some fairly complex customisable shapes for the speech balloons.
I can draw the tail and then draw a balloon but that means I have the outline inside the shape and I want it only around the edge.
I assumed QPainterPath::simplified() would solve the problem but it doesn't seem to do anything.
At the moment my best idea is to draw a shape with a thick outline and then draw it again with no outline but I don't think that will work for "zero width" outlines.

I can think of two possible solutions here:
Draw both the "tail" and the main "balloon" as a single shape. In this case, you'd simply draw a single shape with a single outline and a single fill.
Draw them separately, but twice. Draw an "expanded" version of the shapes in black first, and then draw the "normal" version of the shapes in white over the top of it. You wouldn't draw any "lines" at all - the "expanded" version of the fill would serve the same purpose.
The first method would allow alternative line styles to be used (dotted or wiggly lines), but the latter would allow the "outline" to be slightly offset, so that it appeared thicker around some edges and thinner around others.

It turns out QPainterPath::simplified() does work. It depends on whether I draw clockwise or anti-clockwise (I believe it works when drawn clockwise), which I presume is down to how Qt's Winding Fill works.
// create a path representing the bubble and its "tail"
QPainterPath tail = tail.shape();
tail.addPath(bubble.shape());
tail.setFillRule(Qt::WindingFill);
painter->drawPath(tail.simplified);

Related

Best way to detect the window coordinates of a drawn line in c++ Builder

Using moveto and lineto to draw various lines on a window canvas...
What is the simplest way to determine at run-time if an object, like a bit map or a picture control is in "contact" (same x,y coordinates) with a line(s) that had been drawn with lineto on a window canvas?
A simple example would be a ball (bitmap or picture) "contacting" a drawn border and rebounding... What is the easiest way to know if "contact" occurs between the object, picture or bitmap and any line that exists on the window?
If I get it right you want collision detection/avoidance between circular object and line(s) while moving. There are more option to do this I know of...
Vector approach
you need to remember all the rendered stuff in vector form too so you need list of all rendered lines, objects etc ... Then for particular object loop through all the other ones and check for collision algebraically with vector math. Like detecting intersection between bounding boxes and then with particular line/polyline/polygon or what ever.
Raster approach
This is simpler to mplement and sometimes even faster but less acurate (only pixel precision). The idea is to clear object last position with background color. Then check all the pixels that would be rendered at new position and if no other than background color present then no colision occurs so you can render the pixels. If any non background color present then render the object on the original position again as collision occur.
You can also check between old and new position and place the object on first non collision position so you are closer to the edge...
This approach need fast pixel access otherwise it woul dbe too slow. Standard Canvas does not allow this without using BitBlt from GDI. Luckily VCL GRaphics::TBitmap has ScanLine[] property allowing direct pixel access without any performance hit if used right. See example of it in your other question I answered:
bitmap rotate using direct pixel access
accessing ScanLine[y][x] is as slow as Pixels[x][y] but you can store all the pointers to each line of bitmap once and then just use that instead which is the same as accessing your own 2D array. So you really need just bitmap->Height calls of ScanLine[y] for entire image rendering after any resize or assigment of bitmap...
If you got tile based scene you can use this approach on tiles instead of pixels something like this:
What is the best way to move an object on the screen? but it is in asm ...
Field approach
This one is also considered to be a vector approach but does not require collision checks. Instead each object creates repulsive force the bigger the closer you are to it which is added to the Newton/D'Alembert physics driving force. When coefficients set properly it will avoid collisions on its own. This is used also for automatic placement of items etc... for more info see:
How to implement a constraint solver for 2-D geometry?
Hybrid approach
You can combine any of the above approaches together to better suite your needs. For example see:
Path generation for non-intersecting disc movement on a plane

Inkscape: How to have many shapes with exactly the same gradient

I created a flowchart in InkScape in which each shape is filled with a linear gradient.
Some shapes share the same gradient tones but when I created them via copy&past did not know that gradients could be transformed during edit, I thought that copy&pasting a shape simply copy the entire object and each colors.
Anyway, it resulted in shapes that changes background gradient during re-positioning. After several searches I discovered that this is caused by a wrong position of "Gradient Editor Tool" of each one. In other words I moved objects but start/end of each gradient remained in place.
Please, how to quickly reposition gradient direction/start/end of each shape, maybe centering it on each one? I would avoid to manually reposition each one...
Thanks
Inkscape provides a toggle button to move the gradients along with the objects.
Activating this button during any coying or moving carries the gradient with it to the new location. (Actually it copies the gradient.)

cairo_push_group analog in Qt: "clear" composition mode clears everything underneath it

I am writing an app using QPainter and I need an analog of the cairo_push_group in the QPainter class to draw, say, a rectangle with bunch of holes in it, which may intersect.
The problem is that when I draw holes with the "clear" compose mode, everything is cleared underneath the holes I draw; I want the image, that was underneath the hole before I started drawing my complex shape, to stay. In other words - everything underneath the hole is cleared, when I just want everything underneath the hole to bee seen through.
One solution seems to be using the QPainterPath with Odd fill option (the default one), but that does not suit me, as in my app the holes may intersect, and this way the two holes won't combine (the intersection of two holes is not a hole).
One more solution is to just to use the QPainterPath::subtracted method, but for some reason it reduces the quality of polygons (circles become shapes with a countable number of sides, for example).
The other solution is to save the QImage I am drawing on to a temporary QImage, clear it, draw everything that I need and then using the "destination over" mode draw it again, but that seems to be a very slow and memory-consuming solution.
Is there any other solution to this problem? Maybe there IS an analog of the cairo_push_group function in Qt?
Please don't advice me to switch to cairo.
Pictures explain the problem better:
I've found anwser myself.
One way one can do it is to still use the QPainterPath += and -= operators (which are identical to the QPainterPath::united and QPainterPath::subtracted methods), but without any bezier curves. I've replaced all the arcs, circles, etc. with "polylines" (for example, every circle is replaced with a 100-sided polygon). You can achieve any quality you need just by changing the number of sides etc.
The other solution - with the temporary QImage - seems to be not too slow and works just okay. This is the way it is done in cairo also. Just create a QImage with the same size asthe original, a QPainter with the same settings as the original one and use the new QPainter to draw on the temporary image, and, finally, use the QPainter::drawImage method to draw everything on the original device.

Drawing cross section lines within a polygon

I currently have a list of polygons made up of several points. The first of these is the outer polygon of the cross section and the others in shapes inside the first polygon.
I'm trying to think of a way to draw cross section lines inside the outer polygon (and not inside the inner polygons) but I'm struggling to think of a way to do this. Does anyone have any suggestions?
I'm writing in C++ using an API that lets me draw lines between points easily enough. The drawing I'm creating is in 3D, which I'm guessing will make things a bit easier.
You don't mention your OS or your development environment, so it's not clear that there may be other solutions. However, going back to basics, perhaps consider the Painter's Algorithm and don't worry about clipping or cropping your content based on existing content - just do something like this:
Draw cross section lines on the whole image.
Draw the inverse of the outer polygon with a black fill (that will remove the cross section lines that are outside the outer polygon.
Draw the inner shapes with a black fill (that will remove the cross sections lines that are inside the inner polygons).
The Wiki page shows this example:
If you're using Windows and are ok to use Direct2D (or Direct3D), there are much easier ways to do this by drawing shapes with a customised brush for filling.

A method of creating simple game GUI

I have been able to find a lot of information on actual logic development for games. I would really like to make a card game, but I just dont understand how, based on the mouse position, an object can be selected (or atleast the proper way) First I thought of bounding box checking but not all my bitmaps are rectangles. Then I thought f making a hidden buffer wih each object having a different color, but it seems ridiculous to have to do it this way. I'm wondering how it is really done. For example, how does Adobe Flash know the object under the mouse?
Thanks
Your question is how to tell if the mouse is above a non-rectangular bitmap. I am assuming all your bitmaps are really rectangular, but they have transparent regions. You must already somehow be able to tell which part of your (rectangular) bitmap is transparent, depending on the scheme you use (e.g. if you designate a color as transparent or if you use a bit mask). You will also know the z-order (layering) of bitmaps on your canvas. Then when you detect a click at position (x,y), you need to find the list of rectangular bitmaps that span over that pixel. Sort them by z-order and for each one check whether the pixel is transparent or not. If yes, move on to the next bitmap. If no, then this is the selected bitmap.
Or you may use geometric solution. You should store / manage the geometry of the card / item. For example a list of shapes like circles, rectangles.
Maybe triangles or ellipses if you have lots of time. Telling that a triangle has a point or not is a mathematical question and can be numerically unstable if the triangle is very thin (algorithm has a dividing).. Fix: How to determine if a point is in a 2D triangle?
I voted for abc.