Class: RGeo::Cartesian::Segment

Inherits:
Object
  • Object
show all
Defined in:
lib/rgeo/cartesian/calculations.rb

Overview

Represents a line segment in the plane.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_, end_) ⇒ Segment

:nodoc:



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rgeo/cartesian/calculations.rb', line 46

def initialize(start_, end_)
  @s = start_
  @e = end_
  @sx = @s.x
  @sy = @s.y
  @ex = @e.x
  @ey = @e.y
  @dx = @ex - @sx
  @dy = @ey - @sy
  @lensq = @dx * @dx + @dy * @dy
end

Instance Attribute Details

#dxObject (readonly)

Returns the value of attribute dx.



61
62
63
# File 'lib/rgeo/cartesian/calculations.rb', line 61

def dx
  @dx
end

#dyObject (readonly)

Returns the value of attribute dy.



62
63
64
# File 'lib/rgeo/cartesian/calculations.rb', line 62

def dy
  @dy
end

#eObject (readonly)

Returns the value of attribute e.



60
61
62
# File 'lib/rgeo/cartesian/calculations.rb', line 60

def e
  @e
end

#sObject (readonly)

Returns the value of attribute s.



59
60
61
# File 'lib/rgeo/cartesian/calculations.rb', line 59

def s
  @s
end

Instance Method Details

#contains_point?(p_) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
104
105
106
107
108
# File 'lib/rgeo/cartesian/calculations.rb', line 101

def contains_point?(p_)
  if side(p_) == 0
    t_ = tproj(p_)
    t_ && t_ >= 0.0 && t_ <= 1.0
  else
    false
  end
end

#degenerate?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/rgeo/cartesian/calculations.rb', line 76

def degenerate?
  @lensq == 0
end

#eql?(rhs_) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)


70
71
72
# File 'lib/rgeo/cartesian/calculations.rb', line 70

def eql?(rhs_)
  rhs_.kind_of?(Segment) && @s == rhs_.s && @e == rhs_.e
end

#intersects_segment?(seg_) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/rgeo/cartesian/calculations.rb', line 111

def intersects_segment?(seg_)
  s2_ = seg_.s
  # Handle degenerate cases
  if seg_.degenerate?
    if @lensq == 0
      return @s == s2_
    else
      return contains_point?(s2_)
    end
  elsif @lensq == 0
    return seg_.contains_point?(@s)
  end
  # Both segments have nonzero length.
  sx2_ = s2_.x
  sy2_ = s2_.y
  dx2_ = seg_.dx
  dy2_ = seg_.dy
  denom_ = @dx*dy2_ - @dy*dx2_
  if denom_ == 0
    # Segments are parallel. Make sure they are collinear.
    return false unless side(s2_) == 0
    # 1-D check.
    ts_ = (@dx * (sx2_ - @sx) + @dy * (sy2_ - @sy)) / @lensq
    te_ = (@dx * (sx2_ + dx2_ - @sx) + @dy * (sy2_ + dy2_ - @sy)) / @lensq
    if ts_ < te_
      te_ >= 0.0 && ts_ <= 1.0
    else
      ts_ >= 0.0 && te_ <= 1.0
    end
  else
    # Segments are not parallel. Check the intersection of their
    # containing lines.
    t_ = (dy2_ * (sx2_ - @sx) + dx2_ * (@sy - sy2_)) / denom_
    return false if t_ < 0.0 || t_ > 1.0
    t2_ = (@dy * (sx2_ - @sx) + @dx * (@sy - sy2_)) / denom_
    t2_ >= 0.0 && t2_ <= 1.0
  end
end

#lengthObject



151
152
153
# File 'lib/rgeo/cartesian/calculations.rb', line 151

def length
  ::Math.sqrt(@lensq)
end

#side(p_) ⇒ Object

Returns a negative value if the point is to the left, a positive value if the point is to the right, or 0 if the point is collinear to the segment.



85
86
87
88
89
# File 'lib/rgeo/cartesian/calculations.rb', line 85

def side(p_)
  px_ = p_.x
  py_ = p_.y
  (@sx - px_) * (@ey - py_) - (@sy - py_) * (@ex - px_)
end

#to_sObject



65
66
67
# File 'lib/rgeo/cartesian/calculations.rb', line 65

def to_s
  "#{@s} - #{@e}"
end

#tproj(p_) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/rgeo/cartesian/calculations.rb', line 92

def tproj(p_)
  if @lensq == 0
    nil
  else
    (@dx * (p_.x - @sx) + @dy * (p_.y - @sy)) / @lensq
  end
end