Remember last diagram?
The purple blob called algorithm?, It has taken shape. It’s a relief to have deviced it completely in my head, as that was the part that had me the most concerned about the program. I felt that if I couldn’t device one quickly, I would not finish the program in time.
That way of thinking has accompained me since I learned to survive in higher education: my disastrous ability to get distracted from study (or anything that resembles work or isn’t pleasing) meant that I had to device ways to get myself to do things in time or at least before the final deadlines.
That role as been fulfilled by my conscience, that evil overlord with a whip that keeps reminding me of aaaaaaall the things I still have to do, with the highest priority targets earning me more mental whipping per unit of time.
Look at the images below, can you distinguish which direction the lines are moving?. Can you find a difference between both?.
(a) |
(b) |
Truth be told, they’re indistinguishable. One animation was made by moving the image 1 pixel down every frame, and the other by moving 1 pixel left every frame. But other than the filename, both files are identical, their size and every frame is identical to each other.
Here is a jerky animation with a red dot serving as a guide. Note that if you carefully cover the red dot and only focus on the remaining space of the animation, you may start seeing it go to a different direction than the dot used to be moving.
(c) |
(d) |
This is the first step of my reasoning that led me to conclude that for any regular line pattern, vertical and horizontal movements are equivalent, and related by a factor of x. x depends on the angle; for example, for a pattern composed of lines with a tilt of 30°, a movement of 2 pixels to the left are equivalent to 1 pixel toward bottom. Look at the images below, they were created by stretching animations (a) and (b) (both are equivalent so it’s the same than if I chose to stretch (a) or (b) twice instead):
(e) |
(f) |
From looking at them you can visually perceive that even if the angle of the lines is changed, you can still obtain any possible configuration of the pattern by simply moving in a single direction. If moving in a single coordinate lets us obtain any possible configuration of the pattern, moving in 2 coordinates will as well.
If you play with those principles in your mind, you will conclude that what I say is true (but hell if I’m going to show an entire demonstration of it here, that’d make the explanation take longer than the deduction).
That’s the basis of my algorithm. Which I’ll describe below. And I know it’s not the best solution, but it’s real and it works for any dab* shape, and I hope it doesn’t take too much processing power. I have understood every step involved in my head and now all I need is to implement it. Allow me to explain.
*look at my previous blog entry to visually understand what a dab is in digital brush parlance.
Filling an arbitrarily sized rectangle or ellipse with lines of any thickness, separation, angle and base point (the just discussed X, Y position within the pattern) is not a simple task. Many things can go wrong if you’re too restrictive, much processing power and memory will be wasted if you take an easy path. So I tried to reach a compromise, look below:

Image (g): Well, this image is an example of what would happen if you apply the algorithm I describe below. I can’t really explain the image, as it explains itself as you read the algorithm. The dotted black border is imaginary, it doesn’t exist anywhere, it’s just my way to see “see?, it’s like a square” (see algorithm). The dotted inner square (red color) represents the limits of the rectangle containing the dab. The tilted rose one is there only to show people visually that I used the diagonale as the length of the lines.

Image (h): Even here the image is self-explaining, you’ll see what I mean with “oops”.
Well, that should serve as a visual guide for the algorithm, now the steps:
1-Determine the diagonal size of the dab –> length
2-Obtain the line angle from the properties class –> angle
3-Create a new empty bitmap to draw the stuff inside… grrrr, I just realized I missed this step to understand this process as a whole. Forget all I said about understanding everything in its entirety. I don’t know if it is or isn’t possible to draw a line that stretches out of the bitmap with the available functions. If not possible: causes an error. If possible: only draws the part of the line within the bitmap. Imagine it throws an error for the sake of this example. Imagine this bitmap is just the right size for this “border overload” to not occur.
4-Trace a line with the brush tool over a path describing a line of length length and angle angle.
5-Trace parallel lines to that, separated by a distance s off the original line, measured by a segment perpendicular to it.
6-The last line drawn will be line number int(length/s), such that the area covered by the lines will be a square at lim(s->0).
————6b-Now, the problem is that if I trace that many lines, and the origin point is too far (almost about to start a new cycle, meaning I’m back to a configuration identical to that with the origin point at coordinate [0;0]), it could result in an “oops”, as seen in the image. This shouldn’t be a problem, except for certain limit cases that may arise. Just in case, the solution is just adding 1 line more. Meaning the last line is line number int(length/s)+1
7-Locate the dab inside this square as seen in Image (h), the point of origin (left-top corner of the rectangle containing the dab) depends on the base point (X and Y position) in user preferences. (I haven’t thought the exact formula to locate a consistent origin but it’s not difficult to determine).
8-Cut.
9-Paste as filler (step 5 in The Schematics).
There is a lot of room for improvement in this algorithm, but it’s a base I can work upon. Wasted processing time increases as the dab’s dimensions deviate from a square and as the angle approaches 45°, as a lot of things will be drawn that will be ultimately not be used (as in cut, see step 8).
I think, depending on the functions at hand, that I can optimize this to draw directly on the dab, such that the bitmap (or “canvas”) of step 3 will be only in my imagination, and such that every line that attempts to be drawn outside the limits of the dab will simply not be drawn outside without throwing an exception or error. I may even go and create the functions I need to do that. It all depends on the tools I find in my way.
So, there you have, my hatching algorithm. The algorithm is the most difficult step; after it is finished, the rest is a cakewalk. The GUI, the preferences class, communication, none of that is difficult. I can confidently say the algorithms (plural) will ultimately represent more than 60% of the time spent programming and designing this new brush, probably close to 80%.
I’m too tired to give more personal comments. But I’ll say one thing!, I started using heating. I can’t work with cold hands, cold feet and cold knees!, I told you, it’s winter here!. If it were summer, it’d be so MUCH easier to focus, with light and warmth!. Who wants to work when not feeling in a ZEN state?, certainly not me. As long as my body is whining about cold or hunger or sleepyness, I can’t sustain focus on work (sometimes not even on games)
.
Salgan al sol!.
Endnotes:
…Err, I gave an entire demonstration of why vertical and horizontal movements are equivalent in a parallel line pattern and then forgot to explain why it is the basis of my algorithm: it is because, within that square made of n lines of length length, the only way I can be sure that I won’t get out of the boundaries of this “square”, is by moving along the axis of space s, that is to say, perpendicular to the lines. The idea is that I’ll be able to achieve any pattern configuration that the user requests (depending on the origin point he desires) by simply moving along that axis, which is a combination of vertical and horizontal movements, but which, in the end, can be equivalent to any other movement along those axes.
And if you don’t know what I mean with origin point, imagine that the different animations I made, like (a) and (b), where created by moving the origin point 1 pixel at a time toward the left or up.