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:



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/rgeo/cartesian/calculations.rb', line 12

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.



26
27
28
# File 'lib/rgeo/cartesian/calculations.rb', line 26

def dx
  @dx
end

#dyObject (readonly)

Returns the value of attribute dy.



27
28
29
# File 'lib/rgeo/cartesian/calculations.rb', line 27

def dy
  @dy
end

#eObject (readonly)

Returns the value of attribute e.



25
26
27
# File 'lib/rgeo/cartesian/calculations.rb', line 25

def e
  @e
end

#sObject (readonly)

Returns the value of attribute s.



24
25
26
# File 'lib/rgeo/cartesian/calculations.rb', line 24

def s
  @s
end

Instance Method Details

#contains_point?(p_) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
# File 'lib/rgeo/cartesian/calculations.rb', line 60

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)


38
39
40
# File 'lib/rgeo/cartesian/calculations.rb', line 38

def degenerate?
  @lensq == 0
end

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

Returns:

  • (Boolean)


33
34
35
# File 'lib/rgeo/cartesian/calculations.rb', line 33

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

#intersects_segment?(seg_) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/rgeo/cartesian/calculations.rb', line 69

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



108
109
110
# File 'lib/rgeo/cartesian/calculations.rb', line 108

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.



46
47
48
49
50
# File 'lib/rgeo/cartesian/calculations.rb', line 46

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

#to_sObject



29
30
31
# File 'lib/rgeo/cartesian/calculations.rb', line 29

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

#tproj(p_) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/rgeo/cartesian/calculations.rb', line 52

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