Module: RGeo::Cartesian::Analysis

Defined in:
lib/rgeo/cartesian/analysis.rb

Overview

This provides includes some spatial analysis algorithms supporting Cartesian data.

Class Method Summary collapse

Class Method Details

.ring_direction(ring_) ⇒ Object

Given a LineString, which must be a ring, determine whether the ring proceeds clockwise or counterclockwise. Returns 1 for counterclockwise, or -1 for clockwise.

Returns 0 if the ring is empty. The return value is undefined if the object is not a ring, or is not in a Cartesian coordinate system.


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/rgeo/cartesian/analysis.rb', line 58

def ring_direction(ring_)
  size_ = ring_.num_points - 1
  return 0 if size_ == 0

  # Extract unit-length segments from the ring.
  segs_ = []
  size_.times do |i_|
    p0_ = ring_.point_n(i_)
    p1_ = ring_.point_n(i_+1)
    x_ = p1_.x - p0_.x
    y_ = p1_.y - p0_.y
    r_ = ::Math.sqrt(x_*x_ + y_*y_)
    if r_ > 0.0
      segs_ << x_/r_ << y_/r_
    else
      size_ -= 1
    end
  end
  segs_ << segs_[0] << segs_[1]

  # Extract angles from the segments by subtracting the segments.
  # Note angles are represented as cos/sin pairs so we don't
  # have to calculate any trig functions.
  angs_ = []
  size_.times do |i_|
    x0_, y0_, x1_, y1_ = segs_[i_*2,4]
    angs_ << x0_*x1_ + y0_*y1_ << x0_*y1_ - x1_*y0_
  end

  # Now add the angles and count revolutions.
  # Again, our running sum is represented as a cos/sin pair.
  revolutions_ = 0
  sin_ = 0.0
  cos_ = 1.0
  angs_.each_slice(2) do |(x_, y_)|
    ready_ = y_ > 0.0 && sin_ > 0.0 || y_ < 0.0 && sin_ < 0.0
    if y_ != 0.0
      s_ = sin_*x_ + cos_*y_
      c_ = cos_*x_ - sin_*y_
      r_ = ::Math.sqrt(s_*s_ + c_*c_)
      sin_ = s_ / r_
      cos_ = c_ / r_
    end
    if ready_
      if y_ > 0.0 && sin_ <= 0.0
        revolutions_ += 1
      elsif y_ < 0.0 && sin_ >= 0.0
        revolutions_ -= 1
      end
    end
  end
  revolutions_
end