lib/ctioga2/graphics/styles/arrows.rb in ctioga2-0.11 vs lib/ctioga2/graphics/styles/arrows.rb in ctioga2-0.12

- old
+ new

@@ -33,11 +33,16 @@ typed_attribute "#{e}_scale".to_sym, 'float' typed_attribute "#{e}_angle".to_sym, 'float' typed_attribute "#{e}_color".to_sym, 'color' end - def draw_arrow(t, x1, y1, x2, y2) + TiogaDefaults = { + 'head_marker' => Tioga::MarkerConstants::Arrowhead, + 'tail_marker' => Tioga::MarkerConstants::BarThin + } + + def old_draw_arrow(t, x1, y1, x2, y2) dict = self.to_hash dict.rename_key('width', 'line_width') dict.rename_key('style', 'line_style') dict['head'] = [x2,y2] dict['tail'] = [x1,y1] @@ -47,10 +52,145 @@ end end t.show_arrow(dict) end + + # Draws an arrow. + def draw_arrow(t, x1, y1, x2, y2) + dx = x2 - x1 + dy = y2 - y1 + + angle = Types::Dimension.get_angle(t, dx, dy) + + len = Types::Dimension.get_distance(t, dx, dy) + + rs = symbol_size(t, "head") + ls = symbol_size(t, "tail") + + x1n, y1n, x2n, y2n = *Types::Dimension::adjust_line(t, x1, y1, x2, y2, -ls, -rs) + + # Must shorten the path first... + sv = t.line_cap + + # This has for effect to disable changing the line cap when + # there are now arrows to draw. + if ! (has_marker?('head') || has_marker?('tail')) + sv = Tioga::FigureConstants::LINE_CAP_BUTT + end + if sv != Tioga::FigureConstants::LINE_CAP_BUTT + t.line_cap = Tioga::FigureConstants::LINE_CAP_BUTT + end + draw_line(t, x1n, y1n, x2n, y2n) + if sv != Tioga::FigureConstants::LINE_CAP_BUTT + t.line_cap = sv + end + + # Then, draw the arrow heads/tails + draw_symbol(t, 'head', angle, x2, y2) + draw_symbol(t, 'tail', angle - 180, x1, y1) + + end + + protected + + # Return the dimension of the arrow size + def symbol_size(t, name) + sz = Types::Dimension.new(:dy,self.send("#{name}_scale") || 1.0) + sz.value *= case just(name) + when Tioga::FigureConstants::CENTERED + 0 + when Tioga::FigureConstants::RIGHT_JUSTIFIED + 0.5 + end + return sz + end + + def just(name) + mkr = self.send("#{name}_marker") + if mkr == Tioga::MarkerConstants::Arrowhead or + mkr == Tioga::MarkerConstants::ArrowheadOpen + Tioga::FigureConstants::RIGHT_JUSTIFIED + else + Tioga::FigureConstants::CENTERED + end + end + + def has_marker?(name) + mkr = self.send("#{name}_marker") + if ! mkr or mkr == 'None' + return false + else + return true + end + end + + # Draw the arrow symbol for the given name (head or tail), + # with the given base angle and at the given position + def draw_symbol(t, name, angle, x, y) + hsh = {} + for k in %w(marker scale color angle) + tmp = self.send("#{name}_#{k}") + if tmp + hsh[k] = tmp + end + end + mkr = hsh['marker'] + if ! mkr or mkr == 'None' + return + end + + hsh['angle'] ||= 0 + hsh['angle'] += angle + + hsh['x'] = x + hsh['y'] = y + + # Color defaults to line color + if @color and !hsh.key?('color') + hsh['color'] = @color + end + + hsh['justification'] = just(name) + t.show_marker(hsh) + end + end + + # This class represents all the stylistic information necessary + # to draw a line parallel to a certain direction, indicated by + # an angle (default to horizontal) + class OrientedLineStyle < ArrowStyle + # The angle, in degrees. + typed_attribute :angle, 'float' + + # The alignment of the line with respect to the point given. + typed_attribute :origin, 'justification' + + # len is a dimension + def draw_oriented_arrow(t, xo, yo, len) + + angle = @angle || 0.0 + + dx,dy = *len.to_figure(t, angle) + + case @origin || Tioga::FigureConstants::LEFT_JUSTIFIED + when Tioga::FigureConstants::LEFT_JUSTIFIED + x1, y1 = xo, yo + x2, y2 = xo + dx, yo + dy + when Tioga::FigureConstants::CENTERED + x1, y1 = xo - 0.5 * dx, yo - 0.5 * dy + x2, y2 = xo + 0.5 * dx, yo + 0.5 * dy + when Tioga::FigureConstants::RIGHT_JUSTIFIED + x1, y1 = xo - dx, yo - dy + x2, y2 = xo, yo + end + + draw_arrow(t, x1, y1, x2, y2) + end + + end + end end end