Module: NSWTopo::Declination

Includes:
VectorRender
Defined in:
lib/nswtopo/layer/declination.rb

Constant Summary collapse

CREATE =
%w[angle spacing arrows offset]
DEFAULTS =
YAML.load <<~YAML
  spacing: 40.0
  offset: 0.0
  arrows: 160.0
  stroke: darkred
  stroke-width: 0.1
  symbol:
    path:
      d: M 0 0 L 0.4 2 L 0 1.3 L -0.4 2 Z
      stroke: none
YAML

Constants included from VectorRender

VectorRender::FONT_SCALED_ATTRIBUTES, VectorRender::MARGIN, VectorRender::SVG_ATTRIBUTES

Instance Method Summary collapse

Methods included from VectorRender

#categorise, #create, #drawing_features, #features, #filename, #labeling_features, #params_for, #render

Instance Method Details

#get_featuresObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/nswtopo/layer/declination.rb', line 17

def get_features
  @params["fill"] ||= @params["stroke"]
  declination = @angle || @map.declination
  col_spacing = @spacing
  row_spacing = @arrows * 0.5
  col_offset = @offset % @spacing

  radius = 0.5 * @map.neatline.bounds.transpose.then do |bl, tr|
    Vector[*tr] - Vector[*bl]
  end.norm

  j_max = (radius / col_spacing).ceil
  i_max = (radius / row_spacing).ceil

  (-j_max..j_max).each.with_object(GeoJSON::Collection.new(projection: @map.neatline.projection)) do |j, collection|
    x = j * col_spacing + col_offset
    coordinates = [radius, -radius].map do |y|
      Vector[x, y].rotate_by_degrees(declination - @map.rotation) + Vector[*@map.dimensions] / 2
    end
    collection.add_linestring coordinates
    (-i_max..i_max).reject(&j.even? ? :even? : :odd?).map do |i|
      Vector[x, i * row_spacing].rotate_by_degrees(declination - @map.rotation) + Vector[*@map.dimensions] / 2
    end.each do |coordinates|
      collection.add_point coordinates, "rotation" => declination
    end
  end
end

#to_sObject



45
46
47
48
49
50
51
52
53
54
# File 'lib/nswtopo/layer/declination.rb', line 45

def to_s
  lines = features.grep(GeoJSON::LineString)
  return @name if lines.none?
  angle = lines.map(&:coordinates).map do |p0, p1|
    p1 - p0
  end.max_by(&:norm).then do |delta|
    90 + 180 * Math::atan2(delta.y, delta.x) / Math::PI + @map.rotation
  end
  "%s: %i line%s at %.1f°%s" % [@name, lines.length, (?s unless lines.one?), angle.abs, angle > 0 ? ?E : angle < 0 ? ?W : nil]
end