Class: GreinerHormann::Polygon

Inherits:
Object
  • Object
show all
Defined in:
lib/greiner_hormann/polygon.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(pnts) ⇒ Polygon

Returns a new instance of Polygon.



5
6
7
8
9
10
11
12
# File 'lib/greiner_hormann/polygon.rb', line 5

def initialize(pnts)
  self.first = self.first_intersect = self.last_unprocessed = nil
  self.verticies = 0

  pnts.each do |pnt|
    add_vertex(Vertex.new(*pnt))
  end
end

Instance Attribute Details

#firstObject

Returns the value of attribute first.



3
4
5
# File 'lib/greiner_hormann/polygon.rb', line 3

def first
  @first
end

#first_intersectObject

Returns the value of attribute first_intersect.



3
4
5
# File 'lib/greiner_hormann/polygon.rb', line 3

def first_intersect
  @first_intersect
end

#last_unprocessedObject

Returns the value of attribute last_unprocessed.



3
4
5
# File 'lib/greiner_hormann/polygon.rb', line 3

def last_unprocessed
  @last_unprocessed
end

#verticiesObject

Returns the value of attribute verticies.



3
4
5
# File 'lib/greiner_hormann/polygon.rb', line 3

def verticies
  @verticies
end

Instance Method Details

#add_vertex(vert) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/greiner_hormann/polygon.rb', line 14

def add_vertex(vert)
  if self.first.nil?
    self.first = vert
    self.first.next_node = vert
    self.first.prev_node = vert
  else
    next_n = self.first
    prev_n = next_n.prev_node

    next_n.prev_node = vert
    vert.next_node = next_n
    vert.prev_node = prev_n
    prev_n.next_node = vert
  end

  self.verticies += 1
end

#clip(clip, source_forwards, clip_forwards) ⇒ Object

Clip polygon against another one. Result depends on algorithm direction:

Intersection: forwards forwards Union: backwars backwards Diff: backwards forwards



106
107
108
109
110
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/greiner_hormann/polygon.rb', line 106

def clip(clip, source_forwards, clip_forwards)
  source_vert = self.first
  clip_vert = clip.first

  loop do
    unless source_vert.is_intersection
      loop do
        unless clip_vert.is_intersection
          i = Intersection.new(source_vert, get_next(source_vert.next_node), clip_vert, clip.get_next(clip_vert.next_node))

          if i.valid
            source_intersection = Vertex.create_intersection(i.x, i.y, i.to_source)
            clip_intersection = Vertex.create_intersection(i.x, i.y, i.to_clip)
            source_intersection.corresponding = clip_intersection
            clip_intersection.corresponding = source_intersection

            insert_vertex(source_intersection, source_vert, get_next(source_vert.next_node))
            clip.insert_vertex(clip_intersection, clip_vert, clip.get_next(clip_vert.next_node))
          end
        end
        clip_vert = clip_vert.next_node
        break if clip_vert == clip.first
      end
    end

    source_vert = source_vert.next_node
    break if source_vert == self.first
  end

  source_vert = self.first
  clip_vert = clip.first

  source_in_clip = source_vert.is_inside(clip)
  clip_in_source = clip_vert.is_inside(self)

  source_forwards ^= source_in_clip
  clip_forwards ^= clip_in_source

  loop do
    if source_vert.is_intersection
      source_vert.is_entry = source_forwards
      source_forwards = !source_forwards
    end
    source_vert = source_vert.next_node
    break if source_vert == self.first
  end

  loop do
    if clip_vert.is_intersection
      clip_vert.is_entry = clip_forwards
      clip_forwards = !clip_forwards
    end
    clip_vert = clip_vert.next_node
    break if clip_vert == clip.first
  end

  list = []

  while has_unprocessed
    current = get_first_intersect
    clipped = Polygon.new([])
    clipped.add_vertex(Vertex.new(current.x, current.y))

    loop do
      current.visit
      if current.is_entry
        loop do
          current = current.next_node
          clipped.add_vertex(Vertex.new(current.x, current.y))
          break if current.is_intersection
        end
      else
        loop do
          current = current.prev_node
          clipped.add_vertex(Vertex.new(current.x, current.y))
          break if current.is_intersection
        end
      end
      current = current.corresponding
      break if current.visited
    end

    list << clipped.get_points
  end

  if list.length == 0
    list << self.get_points if source_in_clip
    list << clip.get_points if clip_in_source
    list = nil if list.length == 0
  end

  list
end

#get_first_intersectObject



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/greiner_hormann/polygon.rb', line 57

def get_first_intersect
  v = self.first_intersect || self.first

  loop do
    break if v.is_intersection && !v.visited
    v = v.next_node
    break if v == self.first
  end

  self.first_intersect = v
  v
end

#get_next(v) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/greiner_hormann/polygon.rb', line 49

def get_next(v)
  c = v
  while c.is_intersection
    c = c.next_node
  end
  c
end

#get_pointsObject



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/greiner_hormann/polygon.rb', line 87

def get_points
  points = []
  v = self.first

  loop do
    points << [v.x, v.y]
    v = v.next_node
    break if v == self.first
  end

  points
end

#has_unprocessedObject



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/greiner_hormann/polygon.rb', line 70

def has_unprocessed
  v = self.last_unprocessed || self.first

  loop do
    if v.is_intersection && !v.visited
      self.last_unprocessed = v
      return true
    end

    v = v.next_node
    break if v == self.first
  end

  self.last_unprocessed = nil
  false
end

#insert_vertex(vert, start, finish) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/greiner_hormann/polygon.rb', line 32

def insert_vertex(vert, start, finish)
  curr_n = start

  while curr_n != finish && curr_n.distance < vert.distance
    curr_n = curr_n.next_node
  end

  vert.next_node = curr_n
  prev_n = curr_n.prev_node

  vert.prev_node = prev_n
  prev_n.next_node = vert
  curr_n.prev_node = vert

  self.verticies += 1
end