#! /usr/bin/env python # gauge-png.py: create a gauge faceplate for the Asia Engineer 30 volt round # analog panel meter. # copyright 2008 jason pepas (jason@pepas.com) # distributed under the terms of the GNU General Public License, version 2 # see http://www.gnu.org/copyleft/gpl.html # changelog: # # 0.1 (2008/1/5) # * initial release. # * basic faceplate mask. # * dimensions conform to original faceplate. # # 0.2 (2008/1/5) # * tick marks! from math import pi import cairo # tunables: width = 600 height = width bottom_edge = 0.875 needle_hole_radius = 0.175 needle_hole_y_offset = 0.2125 backlight_radius = 0.525 backlight_arc_height = 0.0875 primary_divisions = 5 secondary_divisions = 10 # you shouldn't need to tune these. outer_radius = 0.5 center_x = 0.5 center_y = 0.5 needle_hole_center_x = center_x needle_hole_center_y = center_y + needle_hole_y_offset backlight_radian_start = -(pi * (3/4.0)) backlight_radian_end = backlight_radian_start + (pi/2) def draw_basic_mask(cr): # white background cr.set_source_rgb(1.0, 1.0, 1.0) cr.rectangle(0, 0, width, height) cr.fill() # we will use subtractive geometry. start with a big black disc and then # remove the bits we don't want. # 1: circle cr.set_source_rgb(0, 0, 0) cr.arc(center_x, center_y, outer_radius, 0, 2 * pi) cr.fill() # 2: bottom square cr.set_source_rgb(1.0, 1.0, 1.0) cr.rectangle(0, bottom_edge, 1, 1) cr.fill() # 3: needle hole circle cr.set_source_rgb(1.0, 1.0, 1.0) cr.arc(needle_hole_center_x, needle_hole_center_y, needle_hole_radius, 0, 2 * pi) cr.fill() # 4: bottom entry way for needle assembly cr.set_source_rgb(1.0, 1.0, 1.0) cr.rectangle(center_x - needle_hole_radius, needle_hole_center_y, needle_hole_radius*2, 1) cr.fill() # 5: backlight arc-hole cr.set_source_rgb(1.0, 1.0, 1.0) cr.arc(needle_hole_center_x, needle_hole_center_y, backlight_radius, backlight_radian_start, backlight_radian_end) cr.set_line_width(backlight_arc_height) cr.stroke() def draw_tick_mark(tick_offset, tick_width, tick_height): #these are actually implemented as very short and stubby arcs. cr.set_source_rgb(0, 0, 0) cr.arc(needle_hole_center_x, \ needle_hole_center_y, \ backlight_radius + (backlight_arc_height/2) - ((backlight_arc_height*tick_height)/2), \ backlight_radian_start + (tick_offset*(pi/2)) - ((tick_width*(pi/2))/2), \ backlight_radian_start + (tick_offset*(pi/2)) + ((tick_width*(pi/2))/2)) cr.set_line_width(backlight_arc_height * tick_height) cr.stroke() def draw_ticks(primary_divisions, secondary_divisions): # first draw the primary ticks primary_ticks = primary_divisions + 1 primary_tick_width = 0.01 primary_tick_height = 2 / 3.0 for i in range(0, primary_ticks): tick_offset = i / float(primary_ticks - 1) draw_tick_mark(tick_offset, primary_tick_width, primary_tick_height) # now draw the secondary ticks secondary_tick_width = primary_tick_width / 2.0 secondary_tick_height = primary_tick_height / 2.0 for i in range(0, ((primary_ticks - 1) * secondary_divisions) + 1): tick_offset = i / float(((primary_ticks - 1) * secondary_divisions)) draw_tick_mark(tick_offset, secondary_tick_width, secondary_tick_height) if __name__ == '__main__': # cairo init surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) cr = cairo.Context(surface) # set up a transform so that 1.0 is full width/height cr.scale(width/1.0, height/1.0) # start with the basic mask draw_basic_mask(cr) # now for some tick marks. draw_ticks(primary_divisions, secondary_divisions) # dump to file surface.write_to_png("mask.png")