4 CXGN::Cview::Ruler - an class for drawing rulers
8 Inherits from L<CXGN::Cview::ImageObject>. The basic class draws a simple linear ruler with the default units of cM. Each chromosome object knows what type of ruler it should use and the ruler for a given chromosome object can be obtained with get_ruler(). (set_ruler() is called in the chromosome objects constructor, where it constructs the right type of ruler to go with the chromosome).
10 =head1 KNOWN SUBCLASSES
12 L<CXGN::Cview::Ruler::PachyteneRuler> implements a ruler for fish chromosomes.
16 See also the documentation in L<CXGN::Cview>.
20 Lukas Mueller (lam87@cornell.edu)
31 use CXGN
::Cview
::ImageObject
;
33 package CXGN
::Cview
::Ruler
;
35 use base
"CXGN::Cview::ImageObject";
39 Synopsis: constructor.
40 Arguments: x-position, y-position, height, start value,
42 Returns: a CXGN::Cview::Ruler object.
43 Side effects: sets the default units to "cM".
44 use set_unit() to change the units.
51 my $self = $class -> SUPER
::new
(@_);
54 $self ->{height
} = shift;
55 $self ->set_start_value(shift);
56 $self ->set_end_value(shift);
57 $self -> {font
} = GD
::Font
->Small();
58 $self -> set_color
(50, 50, 50);
59 $self -> {label_side
} = "left";
60 $self -> set_units
("cM");
64 =head2 function set_color()
66 Synopsis: sets the color of the ruler
74 # Note: this function is defined in the parent class and
75 # there is no need to override it here.
79 # $self -> {color}[0] = shift;
80 # $self -> {color}[1] = shift;
81 # $self -> {color}[2] = shift;
84 =head2 functions set_labels_right(), set_labels_left(), set_labels_none()
94 sub set_labels_right
{
96 $self->{label_side
} = "right";
101 $self ->{label_side
} = "left";
104 sub set_labels_none
{
106 $self -> {label_side
} = "";
109 =head2 functions get_units(), set_units()
111 Synopsis: sets the units displayed on the ruler.
127 return $self->{unit
};
130 =head2 function get_start_value(), set_start_value()
132 Synopsis: accessor for the start_value property
140 sub get_start_value
{
142 return $self->{start_value
};
145 =head2 function set_start_value()
147 Synopsis: setter function for the start_value property
148 Arguments: the start value in map units
150 Side effects: defines the start value of the chromosome section
156 sub set_start_value
{
158 $self->{start_value
}=shift;
161 =head2 function get_end_value(), set_end_value()
173 return $self->{end_value
};
178 $self->{end_value
}=shift;
181 =head2 function render()
183 Synopsis: renders the ruler on $image
184 Arguments: $image (GD::Image object).
186 Side effects: draws the ruler image on $image.
196 my $color = $image -> colorResolve
($self->{color
}[0], $self->{color
}[1], $self->{color
}[2]);
198 $self->_calculate_scaling_factor();
201 $image -> line
($self->get_horizontal_offset(), $self->get_vertical_offset(), $self->get_horizontal_offset(), $self->get_vertical_offset()+$self->{height
}, $color);
203 if ($self->{scaling_factor
}) {
204 $length = $self->get_height()/$self->{scaling_factor
};
208 #print STDERR "Length = $length\n";
211 my $tick_spacing = 1;
212 if ($length < 1000) { $tick_spacing=50; }
213 if ($length < 500) { $tick_spacing = 25; }
214 if ($length < 250) { $tick_spacing = 10; }
215 if ($length < 100) { $tick_spacing = 5; }
216 if ($length < 50) { $tick_spacing = 2; }
217 if ($length < 10) { $tick_spacing = 0.5; }
218 if ($length < 1) { $tick_spacing=0.1; }
220 #my $tick_spacing = int($self->get_height()/40); # the spacing of the ticks in map units
222 # the minor ticks need to be at least 10 pixels apart...
224 if ($tick_spacing*$self->{scaling_factor
}<10) {
225 #print STDERR "tick spacing too small... setting to 10.\n";
228 my $label_spacing = 2 * $tick_spacing; # the spacing of the labels in map units
231 # if the labels overlap, then we increment the label_spacing such that they don't.
233 if ($self->{scaling_factor
}) {
234 #otherwise this is an infinite loop....
235 while (($label_spacing * abs($self->{scaling_factor
})) < ($self->{font
}->height())) {
237 #print STDERR "Extending label_spacing... $label_spacing scaling: $self->{scaling_factor}\n";
240 #if ($self->{end_value} < 100) { $label_spacing=10; $tick_spacing=5; }
241 my $tick_number = int($self->{end_value
}-$self->{start_value
})/$tick_spacing;
243 for (my $i=0; $i<$tick_number; $i++) {
244 my $y = $self->get_vertical_offset() + (($i*$tick_spacing)*$self->{scaling_factor
});
245 $image -> line
($self->get_horizontal_offset()-2, $y, $self->get_horizontal_offset()+2, $y, $color);
247 if ($i*$tick_spacing % $label_spacing ==0) {
248 if ($self->{label_side
} eq "left") {
249 $image -> string
($self->{font
}, $self->get_horizontal_offset()-$self->{font
}->width*length($i*$tick_spacing)-2, $y - $self->{font
}->height/2, $i*$tick_spacing, $color);
251 if ($self->{label_side
} eq "right") {
252 $image -> string
($self->{font
}, $self->get_horizontal_offset()+4, $y - $self->{font
}->height/2, $i*$tick_spacing, $color);
256 my $label = "[".$self->get_units()."]";
257 $image -> string
($self->{font
}, $self->get_horizontal_offset()-$self->{font
}->width()*length($label)/2, $self->get_vertical_offset()-$self->{font
}->height()-3, $label, $color);
261 sub _calculate_scaling_factor
{
263 my $dist = ($self->{end_value
}-$self->{start_value
});
264 if ($dist ==0) { return 0; }
265 $self -> {scaling_factor
} = $self->{height
}/($self -> {end_value
} - $self->{start_value
});
266 return $self->{scaling_factor
};