Post Reply 

how to draw this geometric pattern programmatically?

Oct 21, 2013, 00:54 (This post was last modified: Oct 21, 2013 00:57 by Florin Andrei.)
Post: #1
Question how to draw this geometric pattern programmatically?
This pattern is called a rotary encoder:

[Image: jSt9T4C.png]

I need to draw something like this, except with a lot more segments. Let's say, around 1200 segments, or so, equally spaced. The dark and white segments are of equal width. Then I need to create an image file, or even a PDF, take it to a good high-DPI printer, and print it on a transparent sheet, Letter or A4 size, as high resolution as possible.

It will be used in a device to measure the rotation speed of a rod: a light sensor will be triggered by the dark segments on the rotating disk, then a microcontroller will count the number of events per second, thereby providing a measure for the rotation speed.

How do I even begin to draw this thing? It's obviously not doable by hand, there are too many segments. I know GIMP has some scripting capabilities; how do I use that to draw this pattern? I'm more of an infrastructure and hardware person, I've minimal experience with GIMP (I've only done fixing contrast or saturation in photos, or redeye, and so on - very basic stuff).

I've done a good amount of coding in general (bash, PHP, C, TCL, Python) for many years now, so I won't be learning coding in general from scratch - I know that already. I am just unsure how to do this particular task in GIMP.

Am I even asking the right question here? Is GIMP the right kind of tool for this?

Thanks!

--
Florin Andrei
http://florin.myip.org/
Visit this user's website Find all posts by this user
Quote this message in a reply
Oct 21, 2013, 01:15
Post: #2
RE: how to draw this geometric pattern programmatically?
Taking in account symmetries you don't need to draw 1200 segments Smileg

Otherwise yes, you can do it in Python by creating a path and then using this path as a selection that you bucket fill.

I also happen to have written a Gimp script to create paths from CSV files, so you can compute your shape using your favorite spreadsheet and feed it to the script that will create a path in Gimp.

The script is described here: http://gimp-path-tools.sourceforge.net/t...l#path-csv
It can be downloaded here: http://sourceforge.net/projects/gimp-pat...s/scripts/
There are examples spreadsheets here: http://sourceforge.net/projects/gimp-pat.../path-csv/

I wrote it for someone who needed a background for a dial:

[attachment=2563]

Another completely different method is to learn the PostScipt language and to draw your thing a a simple Postscript function. It's not that hard (I did something like this in one afternoon, 15 years ago Smile

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Oct 25, 2013, 07:25 (This post was last modified: Oct 25, 2013 07:25 by iForStyle007.)
Post: #3
RE: how to draw this geometric pattern programmatically?
Ok, so I was wondering if Inkscape could make something like your radial dial. I found a similar shape, if of's scripts don't work out. Give inskape a try, its like a free alternate to illustrator.

Here is the specific tool (star shape) in Inkscape, if using chrome, push ctrl + F , then type "Stars are the most complex"
Then scroll down some until you see the red star shapes, you can control the number of spikes/lines
http://inkscape.org/doc/shapes/tutorial-shapes.html

Good luck in all you try ^_^

"In order to succeed, your desire for success should be greater than fear of failure." BC
[Image: 29uocaf.png]
iFS007 tut vids on YT ~ auto color B&W landscape tut
Visit this user's website Find all posts by this user
Quote this message in a reply
Oct 25, 2013, 09:08
Post: #4
RE: how to draw this geometric pattern programmatically?
The mention of Inkscape reminded me that it has a pattern-along-path filter (often produces unexpected results, or at least it does with me)

There is a very new Gimp plugin which is similar.
http://registry.gimp.org/node/28604 which takes you to
http://www.arakne.es/en/dessign/gimp-plu...llow-path/ looks like this:
[Image: HPEddcO.jpg]

Here I made a small image (3x20 pix) for a pattern and pasted in to the main image as a new layer.
The snag for the OP is the maximum number of iterations is 100, so for 1200 there is a few duplicate -> rotate -> merge-down, operations required. The plugin does work quite well although slow-ish, end result.
[Image: bleFJKt.jpg]

** https://www.gimp-forum.net/ now answering questions**
Find all posts by this user
Quote this message in a reply
Nov 11, 2013, 03:49 (This post was last modified: Nov 11, 2013 03:56 by Captain_Cereal_Hands.)
Post: #5
RE: how to draw this geometric pattern programmatically?
I just wanted to say you could do this in like 90 seconds with Autodesk Autocad with 1200 segments or even 10,000 segments and Autocad is designed to deal with high resolution drawings.
Find all posts by this user
Quote this message in a reply
Nov 14, 2013, 19:42 (This post was last modified: Nov 14, 2013 19:43 by Florin Andrei.)
Post: #6
RE: how to draw this geometric pattern programmatically?
In case someone is looking for the same thing, this is the solution I ended up using. It can be done entirely in standalone Python, without GIMP. I believe the modules I'm using are entirely standard, so no extras are needed beyond the regular Python distribution, but I'm far from being a Python expert.

This is the code:

Code:
#!/usr/bin/python

# set this to 1 to troubleshoot
debug = 0

from PIL import Image, ImageDraw
import math

##############################################
# These two parameters are the only ones that
# you would normally want to change:
#
# set number of lines in the dial
n = 100
# set external radius of the dial, in pixels
# the image size on each edge is twice this radius
r2 = 400
##############################################

# calculate length of each line
l = round(r2 / 10)
# calculate inner radius of dial
r1 = r2 - l

# calculate line thickness
# tuned for 50% fill factor at the inner end of each line
# (dark stripe and transparent stripe have equal width there)
thick = 2 * math.pi * r1 / float(2 * n)
print "thickness =", thick

# create a canvas just big enough to contain the dial
i = Image.new("RGB", (2*r2, 2*r2), color="White")
draw = ImageDraw.Draw(i)

# draw N lines
for step in range(0, n):
    # calculate the angle for each line in degrees (for human consumption)...
    a = 360.0 * step / float(n)
    # ...and in radians
    arad = math.radians(a)
    sin = math.sin(arad)
    cos = math.cos(arad)
    # calculate coordinates of the two ends of each line
    # (ignore thickness for now)
    x1 = r1 * cos
    y1 = r1 * sin
    x2 = r2 * cos
    y2 = r2 * sin
    # the thick line is actually drawn as a filled polygon
    # let's calculate the positions of the corners of the polygon
    xdelta = sin * thick / 2.0
    ydelta = cos * thick / 2.0
    xx1 = x1 - xdelta
    yy1 = y1 + ydelta
    xx2 = x1 + xdelta
    yy2 = y1 - ydelta
    xx3 = x2 + xdelta
    yy3 = y2 - ydelta
    xx4 = x2 - xdelta
    yy4 = y2 + ydelta
    if debug == 1:
        print "a =", a, "\t x1 =", x1, "\t y1 =", y1, "\t x2 =", x2, "\t y2 =", y2
    # draw a 1px thin line
    #draw.line((r2+x1, r2+y1, r2+x2, r2+y2), fill="Black")
    # or draw a thick line instead
    draw.polygon((r2+xx1, r2+yy1, r2+xx2, r2+yy2, r2+xx3, r2+yy3, r2+xx4, r2+yy4), fill="Black")

# draw crosshairs in the center
draw.line((r2-l, r2, r2+l, r2), fill="Black")
draw.line((r2, r2-l, r2, r2+l), fill="Black")

# save the dial as an image file
i.show()
i.save("dial.png", "PNG")

This is an example of the result:

   

--
Florin Andrei
http://florin.myip.org/
Visit this user's website Find all posts by this user
Quote this message in a reply
Nov 14, 2013, 21:29
Post: #7
RE: how to draw this geometric pattern programmatically?
You must be missing something because there is a lot of aliasing, very visible where the marks are close to the horizontal/vertical.

Otherwise if you can do it in stand-alone python, doing in Gimp python is almost simpler, and the results will look a lot better.

PS: looked at the API, and no, you are unfortunately not missing anything.

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Nov 15, 2013, 00:12 (This post was last modified: Nov 15, 2013 00:12 by Florin Andrei.)
Post: #8
RE: how to draw this geometric pattern programmatically?
(Nov 14, 2013 21:29)ofnuts Wrote:  You must be missing something because there is a lot of aliasing, very visible where the marks are close to the horizontal/vertical.

The final image will be very high resolution. I intend to use the highest resolution that will go into whatever printer I'll find. I've also generated a test image at 8000x8000 px (radius=4000), with 1000 segments in the dial, and it doesn't look too bad; the stairsteps are still there, but much smaller, of course, relative to the whole image:

http://i.imgur.com/czzXe6P.png

I've no idea what the limits are for current printing technology. I need to print this on a transparent Letter or A4 foil, on some kind of laser printer. There's obviously a maximum pixel size for the image, and then a maximum DPI for the printer that will limit the number of segments in the dial. No idea what the actual numbers are, I guess I'll find out by banging my head against them. Smile

In any case, if the pixels-per-inch number in the image becomes comparable to the DPI number of the printer, then the printer will do the anti-aliasing. Smile

Quote:Otherwise if you can do it in stand-alone python, doing in Gimp python is almost simpler, and the results will look a lot better.

Alright then. Where do I find an "explain me like I'm a complete moron" example of something super-simple, such as draw a line from (x1, y1) to (x2, y2), in Gimp Python? If I get to that point I'll figure out the rest; but it's the sequence of steps prior to it that I could not figure out properly. I even looked at your Gimp tools, but something went wrong every time.

--
Florin Andrei
http://florin.myip.org/
Visit this user's website Find all posts by this user
Quote this message in a reply
Nov 15, 2013, 13:27
Post: #9
RE: how to draw this geometric pattern programmatically?
Gimp uses Bezier splines, a straight line is just a spline where the control handles are identical to the anchor points. The Gimp representation of splines is just a completely flat list of coordinates, so a point is really 6 numbers: x,y of the backward tangent handle, x,y of the point proper, and x,y of the forward handle. For straight lines, all the x,y pairs in one point are identical, so a rectangle "stroke" from (10,10) to (20, 10), to (20,20) to (10,20) back to (10,10) is just:
Code:
[10,10]*3+[20,10]*3+[20,20]*3+[10,20]*3
(and you don't need the last segment, you just add the "closed" flag).

See my collection of path-related python scripts (download the scripts for the source and check the FAQ)

I'll be happy to answer here any questions you have...

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Nov 15, 2013, 20:59
Post: #10
RE: how to draw this geometric pattern programmatically?
Python script (dial-marks-0.0.py) added to the collection referenced above.

Check "Filters/Render/Paths/Dial marks". The parameters should be self-explanatory.

The script only creates a path, for what you want to do, add "Select/From path" and bucket-fill the selection.

[attachment=2682]

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Photoshop Pattern Loader Neiiley 9 3,345 Jun 30, 2013 20:45
Last Post: Neiiley
  I need a plugin to draw squares and circles on gimp Johanx2 4 1,545 Jan 11, 2013 11:14
Last Post: ofnuts
  Photoshop Pattern Loader error lngrid 3 934 Mar 7, 2012 09:37
Last Post: ofnuts

Forum Jump:


GIMP ForumPortalArchiveContactTermsRSS