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
-
.ring_direction(ring_) ⇒ Object
Given a LineString, which must be a ring, determine whether the ring proceeds clockwise or counterclockwise.
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 |
# 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_ 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 |