# Container class for the core SVG data.
#
# These methods should never need to be called directly.
# @private
class USPSFlags::Core
def self.trident_spec(fly: 24, unit: "in")
trident_config = USPSFlags::Config.trident
hoist = (fly*Rational(2,3))
hoist = hoist == hoist.to_i ? hoist.to_i : hoist
fly_fraction = ""
hoist_fraction = ""
if fly == fly.to_i
fly = fly.to_i
else
fly, fly_fraction = fly.to_simplified_a
end
if hoist == hoist.to_i
hoist = hoist.to_i
else
hoist, hoist_fraction = hoist.to_simplified_a
end
label_font_size = if Math.sqrt(fly) > 24
USPSFlags::Config::BASE_FLY * Math.log(24, Math.sqrt(fly)) / 60
else
USPSFlags::Config::BASE_FLY / 60
end
unit_text = unit.nil? ? "" : "#{unit}"
barb_label = Rational(trident_config[:main_point_barb]) * fly / USPSFlags::Config::BASE_FLY
barb_label = barb_label == barb_label.to_i ? barb_label.to_i : barb_label.to_simplified_s
barb_label = "#{barb_label}#{unit_text}"
svg = ""
svg << <<~SVG
#{USPSFlags::Core.field}
United States Power Squadrons®
Officer Flag Trident Specification
All measurements are relative to a field with
fly of #{fly} #{fly_fraction} #{unit_text} and hoist of #{hoist} #{hoist_fraction} #{unit_text}.
Measurements not specified are the same as on the short trident.
SVG
box_width = USPSFlags::Config::BASE_FLY*5/32
box_left = (USPSFlags::Config::BASE_FLY*27/32)/2
box_right = (USPSFlags::Config::BASE_FLY*37/32)/2
box_top = USPSFlags::Config::BASE_HOIST/4
box_bottom = USPSFlags::Config::BASE_HOIST*3/4
svg << <<~SVG
Short
Squadron Officers
#{self.trident(:s)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top, box_top+trident_config[:bar_width], box_right, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:bar_width], box_top+trident_config[:bar_width]*2+trident_config[:point_height]+trident_config[:side_spike_height], nil, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:bar_width]*2+trident_config[:point_height]+trident_config[:side_spike_height], box_top+trident_config[:bar_width]*3+trident_config[:point_height]+trident_config[:side_spike_height], nil, trident_config[:center_point]+trident_config[:hash_width]/2, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:bar_width]*3+trident_config[:point_height]+trident_config[:side_spike_height], box_top+trident_config[:bar_width]*4+trident_config[:point_height]+trident_config[:side_spike_height], nil, trident_config[:center_point]+trident_config[:hash_width]/2, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:bar_width]*4+trident_config[:point_height]+trident_config[:side_spike_height], box_bottom, nil, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*5.25, box_top, box_bottom, box_left, box_left, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*0.75, box_top, box_top+trident_config[:point_height], nil, trident_config[:center_point]-trident_config[:bar_width], fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/26, label_offset_y: -USPSFlags::Config::BASE_FLY/100, font_size: label_font_size, label_align: "middle")}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*1.5, box_top+trident_config[:bar_width], box_top+trident_config[:bar_width]+trident_config[:point_height], box_left, box_left+trident_config[:bar_width], fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/24, font_size: label_font_size, label_align: "middle")}
#{USPSFlags::Helpers.h_arrow(box_bottom+trident_config[:bar_width], trident_config[:center_point]-trident_config[:bar_width]/2, trident_config[:center_point]+trident_config[:bar_width]/2, box_bottom, box_bottom, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.h_arrow(box_bottom+trident_config[:bar_width]*2.5, trident_config[:center_point]-trident_config[:hash_width]/2, trident_config[:center_point]+trident_config[:hash_width]/2, box_top+trident_config[:bar_width]*4+trident_config[:point_height]+trident_config[:side_spike_height], box_top+trident_config[:bar_width]*4+trident_config[:point_height]+trident_config[:side_spike_height], fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.h_arrow(box_bottom+trident_config[:bar_width]*4, box_left, box_right, box_bottom, box_bottom, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.h_arrow(box_top-trident_config[:bar_width], box_left, box_left+trident_config[:bar_width]*3/2, box_top, box_top+trident_config[:bar_width]+trident_config[:point_height], fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/60, font_size: label_font_size)}
#{USPSFlags::Helpers.h_arrow(box_top-trident_config[:bar_width]*2.5, trident_config[:center_point]-trident_config[:bar_width], trident_config[:center_point]+trident_config[:bar_width], box_top+trident_config[:point_height], box_top+trident_config[:point_height], fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/60, font_size: label_font_size)}
#{barb_label}
SVG
box_top = USPSFlags::Config::BASE_HOIST*3/16
box_bottom = USPSFlags::Config::BASE_HOIST*13/16
svg << <<~SVG
Delta
District Officers
#{self.trident(:d)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_bottom-trident_config[:delta_from_bottom]-trident_config[:bar_width]-trident_config[:delta_gap_height], box_bottom-trident_config[:delta_from_bottom]-trident_config[:bar_width], trident_config[:center_point], trident_config[:center_point]+trident_config[:delta_gap_width], fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_bottom-trident_config[:delta_from_bottom]-trident_config[:bar_width], box_bottom-trident_config[:delta_from_bottom], nil, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_bottom-trident_config[:delta_from_bottom], box_bottom, nil, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*1.5, box_top, box_bottom, box_left, box_left, fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/30, label_offset_y: -USPSFlags::Config::BASE_FLY*2/11, font_size: label_font_size, label_align: "middle")}
SVG
box_top = USPSFlags::Config::BASE_HOIST/8
box_bottom = USPSFlags::Config::BASE_HOIST*7/8
svg << <<~SVG
Circle
Staff Commanders Only
#{self.trident(:stf)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:crossbar_from_top]+trident_config[:bar_width]*2, box_top+trident_config[:crossbar_from_top]+trident_config[:width], trident_config[:center_point], trident_config[:center_point], fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:crossbar_from_top]+trident_config[:width], box_top+trident_config[:crossbar_from_top]+trident_config[:bar_width]+trident_config[:width], nil, trident_config[:center_point]+trident_config[:bar_width]/2, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:crossbar_from_top]+trident_config[:bar_width]+trident_config[:width], box_bottom, nil, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*1.5, box_top, box_bottom, box_left, box_left, fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/30, label_offset_y: -USPSFlags::Config::BASE_FLY/4.5, font_size: label_font_size, label_align: "middle")}
SVG
svg << <<~SVG
Long
National Officers
#{self.trident(:n)}
#{USPSFlags::Helpers.v_arrow(box_right+trident_config[:bar_width], box_top+trident_config[:crossbar_from_top]+trident_config[:bar_width]*3, box_bottom, trident_config[:center_point]+trident_config[:hash_width]/2, box_right, fly: fly, unit: unit, font_size: label_font_size)}
#{USPSFlags::Helpers.v_arrow(box_left-trident_config[:bar_width]*1.5, box_top, box_bottom, box_left, box_left, fly: fly, unit: unit, label_offset: -USPSFlags::Config::BASE_FLY/30, label_offset_y: -USPSFlags::Config::BASE_FLY/4.5, font_size: label_font_size, label_align: "middle")}
SVG
svg
end
def self.headers(width: nil, height: nil, pennant: false, scale: nil, title: "USPS Flag")
if width.nil? || height.nil?
scale = 3 if scale.nil?
width ||= USPSFlags::Config::BASE_FLY / scale
height = (width*Rational(2,3)).to_i
view_width = USPSFlags::Config::BASE_FLY
view_height = USPSFlags::Config::BASE_HOIST
if pennant
height = height/4
view_height = USPSFlags::Config::BASE_HOIST/4
end
else
if scale.nil?
view_width = width
view_height = height
else
view_width = width * scale
view_height = height * scale
end
end
generated_at = Time.now.strftime("%Y%m%d.%H%S%z")
svg = ""
svg << <<~SVG
FOOTER
end
def self.field(style: :regular, color: :white, fly: USPSFlags::Config::BASE_FLY)
case color
when :white
border = true
color_code = "#FFFFFF"
past_mid_color = USPSFlags::Config::BLUE
past_tail_color = USPSFlags::Config::RED
when :red
border = false
color_code = USPSFlags::Config::RED
past_mid_color = "#FFFFFF"
past_tail_color = USPSFlags::Config::BLUE
when :blue
border = false
color_code = USPSFlags::Config::BLUE
past_mid_color = "#FFFFFF"
past_tail_color = USPSFlags::Config::RED
end
border_svg = border ? "stroke=\"#000000\" stroke-width=\"#{USPSFlags::Config::BASE_FLY/600}\" " : ""
hoist = (fly * 2) / 3
case style
when :regular
<<~FIELD
FIELD
when :swallowtail
<<~FIELD
FIELD
when :past
<<~FIELD
FIELD
end
end
def self.trident(type, color: :blue, field_color: nil)
valid_types = [:s, :d, :stf, :n]
raise "Error: Invalid trident type. Options are #{valid_types}." unless valid_types.include? type
trident_config = USPSFlags::Config.trident
main_spike_overhang = trident_config[:bar_width] / 2
side_spike_overhang = trident_config[:bar_width] / 2
top_point = ((USPSFlags::Config::BASE_HOIST - trident_config[:height][type]) / 2)
crossbar_top = top_point + trident_config[:crossbar_from_top]
hash_from_top = trident_config[:crossbar_from_top] + (trident_config[:bar_width] * 2)
circle_from_top = trident_config[:crossbar_from_top] + trident_config[:bar_width]*123/128 + trident_config[:width]/2
main_length = trident_config[:height][type] - (trident_config[:point_height] - trident_config[:main_point_barb])
trident_segments = [
{
# Main spike
[trident_config[:center_point], top_point] =>
[
[trident_config[:bar_width], trident_config[:point_height]],
[-main_spike_overhang, -trident_config[:main_point_barb]],
[0, main_length],
[-(trident_config[:bar_width]), 0],
[0, -main_length],
[-main_spike_overhang, trident_config[:main_point_barb]],
[trident_config[:bar_width], -trident_config[:point_height]]
]
},
{
# Crossbar
[(trident_config[:center_point] - trident_config[:width]/2), (crossbar_top)] =>
[
[trident_config[:width], 0],
[0, trident_config[:bar_width]],
[-trident_config[:width], 0],
[0, -trident_config[:bar_width]]
]
},
{
# Left spike
[(trident_config[:center_point] - trident_config[:width]/2), (crossbar_top + 1)] =>
[
[0, -(trident_config[:side_spike_height]+trident_config[:point_height])],
[(trident_config[:bar_width]+side_spike_overhang), trident_config[:point_height]],
[-side_spike_overhang, 0],
[0, trident_config[:side_spike_height]]
]
},
{
# Right spike
[(trident_config[:center_point] + trident_config[:width]/2), (crossbar_top + 1)] =>
[
[0, -(trident_config[:side_spike_height]+trident_config[:point_height])],
[-(trident_config[:bar_width]+side_spike_overhang), trident_config[:point_height]],
[side_spike_overhang, 0],
[0, trident_config[:side_spike_height]]
]
}
]
case color
when :white
color_code = "#FFFFFF"
field_color_code = case field_color
when :red
USPSFlags::Config::RED
when :blue
USPSFlags::Config::BLUE
end
when :red
color_code = USPSFlags::Config::RED
field_color_code = "#FFFFFF"
when :blue
color_code = USPSFlags::Config::BLUE
field_color_code = "#FFFFFF"
end
svg = ""
svg << "" if type == :d
svg << "" if type == :stf
trident_segments.each do |segment|
start = segment.keys.first
points = segment.values.first
svg << "\n"
end
svg << "" if [:d, :stf].include?(type)
if type == :d
# Delta hash
svg << <<~SVG
SVG
elsif type == :stf
# Circle hash
svg << <<~SVG
SVG
else
# Standard hash
lower_hash = [
[trident_config[:hash_width], 0],
[0, trident_config[:bar_width]],
[-trident_config[:hash_width], 0],
[0, -trident_config[:bar_width]]
]
svg << "\n"
# # V/C crossing, marks @ 15/32 up
# vc_cross_marker = USPSFlags::Config::BASE_HOIST*7/8-(USPSFlags::Config::BASE_HOIST/8+trident_config[:crossbar_from_top]+trident_config[:bar_width]*3)*15/32
# svg << ""
# # C/C crossing, marks @ 1/3 up
# cc_cross_marker = USPSFlags::Config::BASE_HOIST*7/8-(USPSFlags::Config::BASE_HOIST/8+trident_config[:crossbar_from_top]+trident_config[:bar_width]*3)*1/3
# svg << ""
end
svg
end
def self.anchor(color = :red)
case color
when :red
color_code = "#BF0D3E"
when :white
color_code = "#FFFFFF"
end
<<~SVG
SVG
end
def self.lighthouse
<<~SVG
SVG
end
def self.binoculars(type)
color = case type
when :d
USPSFlags::Config::RED
when :n
USPSFlags::Config::BLUE
end
<<~SVG
SVG
end
def self.trumpet(type)
color = type == :n ? USPSFlags::Config::BLUE : USPSFlags::Config::RED
count = type == :s ? 1 : 2
trumpet = ""
if count == 2
<<~SVG
#{trumpet}
#{trumpet}
SVG
else
trumpet
end
end
def self.pennant(type = "cruise")
fly = USPSFlags::Config::BASE_FLY
hoist = USPSFlags::Config::BASE_HOIST/4
if type.upcase == "OIC"
svg = <<~SVG
SVG
elsif type.upcase == "CRUISE"
svg = <<~FIELD
FIELD
svg << ""
svg << self.star
svg << ""
svg
end
end
def self.ensign
field = <<~SVG
SVG
#
anchor = self.anchor(:white)
star_circle = ""
(0..13).each do |i|
rotation = i * (360.0 / 13)
star_circle << <<~SVG
#{self.star}
SVG
end
<<~SVG
#{field}
#{anchor}
#{star_circle}
SVG
end
def self.star
points = [
[117.555, 81.805],
[-41.47, -137.085],
[114.125, -86.525],
[-143.185, -2.915],
[-47.025, -135.28],
[-47.025, 135.28],
[-143.185, 2.915],
[114.125, 86.525],
[-41.47, 137.085],
[117.555, -81.805]
]
svg = "\n"
svg
end
def self.wheel
<<~SVG
SVG
end
def self.us
base_hoist = 2000.to_f
base_fly = base_hoist*1.91
canton_hoist = base_hoist*7/13
canton_fly = canton_hoist*Math.sqrt(2)
star_offset = 20 # Half of scaled star height
svg = ""
svg << <<~SVG
SVG
[1,3,5,7,9].each do |r|
[1,3,5,7,9,11].each do |c|
svg << <<~SVG
#{self.star}
SVG
end
end
[2,4,6,8].each do |r|
[2,4,6,8,10].each do |c|
svg << <<~SVG
#{self.star}
SVG
end
end
# star_diameter = base_hoist*4/5/13
# svg << <<~SVG
#
# SVG
svg
end
end