Drawing lines in win32/GDI with a custom pen style? - windows

I have a need to do some drawing using win32/GDI (Native, not .NET), and I've run into the following problem:
I need to draw lines that are "styled." For example, in the attached image, the line marked "A" is a straight line as far as my application data is concerned, it just needs to be drawn with the additional zigzag as a style. Of course, this is easy to do programatically, but it gets more complicated when the line can be at any angle ("B") or even a bezier curve ("C").
Now, I could do this all programatically, painstakingly doing the math to put a zigzag around each line possibility, but that will take a lot of time and, more importantly, be rather error prone.
Is it possible to just give windows/GDI a "style" to apply to the line, perhaps a bitmap like the one marked "D", and have it use that as a pen to draw the lines? If not, is there a more flexible and less error-prone way of doing this than writing a bunch of specific drawing code for each of the "styled" lines?
*Apparently first timers can't post images. Examples can be found at http://i.imgur.com/IC0T2.png

This is not possible in Win32 GDI. You will need to do the math yourself.
It should be noted however, that you can obtain the points used to make up the line or curve which should make it substantially easier.
See this "Hit-Testing" tutorial for an example.
http://msdn.microsoft.com/en-us/library/ms969920.aspx
For a bezier curve you would use Path Functions:
BeginPath
PolyBezier
EndPath
FlattenPath
For straight lines you could use:
LineDDA

As far as I know there's nothing in GDI or even GDI+ that would support this. The only line options you have are dash-patterns, compound-pens, dash caps, end caps, and fill brushes.
You might be able to trick one of those functions into drawing something vaguely akin to your wiggles for straight splines, but it definitely won't work for curved splines.
It shouldn't be too hard to do this however. Sure, it will take a day or so, but all you have to do is write a line and bezier interpolator, divide the curves into equal segments, find the tangents at all those segments and alternate left and right. You'll end up with an array of points which can be drawn very quickly as a polyline.

There's nothing that'll do this automatically. You'll have to write some code. You might want to look at the LineDDA API in GDI. It might simplify the math your code will need.

ExtCreatePen(), maybe? I don't know for a fact if it supports zigzagging...

Related

How to check if two user-drawn (squiggly) lines intersect?

I'm thinking of making an online version of the game Sprouts, possibly using the JavaScript web browser graphics library p5.js
You can read more about it but basically there are 2 players that draw lines with their mouse between points. The lines can be straight or curved in any way. One of the rules is that no 2 lines can cross.
I haven't started making the game yet, but planning it ahead, everything seems relatively simple to accomplish except for one problem:
When a user draws a line, I need to figure out if this line intersects with another line. However, since these lines aren't linear or exactly mathematical in any way I'm used to, there doesn't seem to be a simple mathematical way I can check for intersection.
How would I check if two such lines, given that I know the location of every pixel on the lines, cross?
I apologize for no code, I haven't yet started it. If you wish to include code in your answer, you can use psuedocode or any gui programming that you might be familiar with. However, I would prefer a purely hypothetical answer, since everything is at this stage.
Here are some ideas I have:
For each pixel on the line, I could check if any of the other lines has a pixel of the same position, in which case they overlap. This seems inefficient, so the below point is something else I came up with that is more efficient but less rigid and reliable.
Before drawing the line, If you make sure all the lines are one color, for every pixel on the line, you could check if this pixel is already colored in the same color as the color of the lines, using something like getPixel() If so, abort drawing the line. This solutions seems prone to many problems and a bit fragile.
These two solutions either trade efficiency for reliability or vice-versa. Are there any other solutions you know? Keep in mind this will run in a browser, so efficiency is important.
Keep in mind this will run in a browser, so efficiency is important.
You need to give yourself a better idea of what kind of "efficiency" is important to you and your users. Both approaches you outlined seem reasonable to me. I wouldn't assume that a solution is inefficient before you try it and measure its performance.
Taking a step back, in general you're going to need to store the lines in some kind of data structure. You said the lines are not mathematical, but you can break the lines down into individual line segments or points, which are mathematical. That could be an array of line segments, or a 2D array of boolean values, or a map of points, or a quadtree. There are many options. Then you need to check for collisions between those lines or points and the new lines or points added by the other player.
Another option to consider is decreasing the resolution of your input space. For example, maybe your game window is 500x500 pixels, but you really only need the game board to be 100x100 possible point positions. You could scale that 100x100 game board up so it's displayed at 500x500. This would improve the "efficiency" of whatever solution you come up with.
But again, I wouldn't worry about "efficiency" at this point. Either solution you mentioned seems fine. Get that working and then iterate on it if you notice a problem. Good luck.
May be this article from Mike Bostock about the Sutherland-Hodgman algorythm can interest you. It is more related to the intersection of 2 polygons rather than 2 lines but may be it can be adapted to your problem.

Removing skew/distortion based on known dimensions of a shape

I have an idea for an app that takes a printed page with four squares in each corner and allows you to measure objects on the paper given at least two squares are visible. I want to be able to have a user take a picture from less than perfect angles and still have the objects be measured accurately.
I'm unable to figure out exactly how to find information on this subject due to my lack of knowledge in the area. I've been able to find examples of opencv code that does some interesting transforms and the like but I've yet to figure out what I'm asking in simpler terms.
Does anyone know of papers or mathematical concepts I can lookup to get further into this project?
I'm not quite sure how or who to ask other than people on this forum, sorry for the somewhat vague question.
What you describe is very reminiscent of augmented reality marker tracking. Maybe you can start by searching these words on a search engine of your choice.
A single marker, if done correctly, can be used to identify it without confusing it with other markers AND to determine how the surface is placed in 3D space in front of the camera.
But that's all very difficult and advanced stuff, I'd greatly advise to NOT try and implement something like this, it would take years of research... The only way you have is to use a ready-made open source library that outputs the data you need for your app.
It may even not exist. In that case you'll have to buy one. Given the niché of your problem that would be perfectly plausible.
Here I give you only the programming aspect and if you want you can find out about the mathematical aspect from those examples. Most of the functions you need can be done using OpenCV. Here are some examples in python:
To detect the printed paper, you can use cv2.findContours function. The most outer contour is possibly the paper, but you need to test on actual images. https://docs.opencv.org/3.1.0/d4/d73/tutorial_py_contours_begin.html
In case of sloping (not in perfect angle), you can find the angle by cv2.minAreaRect which return the angle of the contour you found above. https://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html (part 7b).
If you want to rotate the paper, use cv2.warpAffine. https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_geometric_transformations/py_geometric_transformations.html
To detect the object in the paper, there are some methods. The easiest way is using the contours above. If the objects are in certain colors, you can detect it by using color filter. https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html

How can I get the extents of a text without drawing it?

I want to draw text in one of two places depending on whether or not it will fit in the first place. I need the extents to figure that out. My brute force idea is to draw it in the first place with #0000 color, and then check if it fit, and then draw it with the real visible color in that place or the other place. Is there a better way?
At this point you can't. Drawing text is going to be unpredictable with all of the formatting stuff, wrapping, aligning, etc. The only way that Pango provides it is after the fact.
Your solution, as yucky as it is, is the best one I've got.
If there are people know more of Pango who can do this - I would be all ears.
(Full disclosure, I am the Squib dev).

Generating a Nice Looking Starfield Pattern

I'm trying to generate a scrolling starfield for a game with C++ and SDL. I'm using a simple, naive algorithm that just creates a lot of white pixels on black backround. However, this "starfield" looks too unnatural - probably because of the random number generator's poor quality (I use the rand() function).
Are there any special algorithms for generating starfields that look more or less realistic?
Thanks.
There's always this classic. Highlights:
[...] imagine the stars to be points in 3D space, all of them moving towards the viewer, along the Z-axis. At each time step, the 3D coordinates of the stars will be projected onto the screen, and displayed.
For a smoother effect, we can make the stars black when they first appear (so you don't notice them) then get brighter as they get closer.
There are two ways the sense of vastness can be modeled. The first is simply to model a huge area of space, which is impractical to say the least. The second is to make the stars move with a range of velocities.
I found this useful tutorial a while ago on creating a 'realistic' star field. It's not C++, but it should be easily adaptable once you get the idea.
You could use Lloyd's algorithm to relax the random points and make them semi-random. I read this idea in a map generator but it probably can be used do create an eventually distributed star field too.
You probably don't want it to be truly random. You will end up with blobs of pixels in some places when you really want individual pixels scattered around. Your best bet would probably be to code a smaller section and then just repeat it over and over to get the full starfield look.

SDL: Performance SPriG vs SDL_gfx

I need to draw a polygon with thick lines. Now I have two possibilities:
Draw them with the library SPriG, which provides line thickness.
Split up the polygon in all it lines and draw them as polygons with a modified thickness (like explained in this tutorial (1 tutorial on the page).) with the SDL_gfx library.
I'm not sure about the performance of SPriG. SDL_gfx will be the fastest I guess.
Did you ever tried this, or simply "do you know the quality of SPrig"?
Thanks
It looks like SPriG just draws a circle at each pixel along a line to give it thickness. For wide lines you're looking at quite a bit of overdraw.
I'd do it a bit differently. It may or may not be faster depending on how triangle rasterization compares to per-pixel circle overdraw.
Don't use one of them. Just make use use of OpenGL and call: glLineWidth(3.6f);

Resources