Class: Geo2D::LineString
- Inherits:
-
Object
- Object
- Geo2D::LineString
- Defined in:
- lib/geo2d.rb
Instance Method Summary collapse
- #<<(p) ⇒ Object
-
#angle_at(parallel_distance, rotation = 0) ⇒ Object
Angle of the line at a point (in radians, from the X axis, counter-clockwise.) The rotation parameter is added to this angle, if the rotation obtained from locate_point is used, points external to the line have a natural orientation parallel to the line (than can be use to rotate texts or symbols to be aligned with the line.).
- #apply(prc = nil, &blk) ⇒ Object
- #bounds ⇒ Object
- #contains?(point) ⇒ Boolean
- #distance_to(point) ⇒ Object
- #each_point ⇒ Object
- #each_segment ⇒ Object
- #end ⇒ Object
-
#initialize(*vertices) ⇒ LineString
constructor
A new instance of LineString.
-
#interpolate_point(parallel_distance, separation = 0, rotation = 0) ⇒ Object
Compute a point position given the relative position in the line as returned by locate_point().
- #length ⇒ Object
- #length_to(point) ⇒ Object
-
#locate_point(point) ⇒ Object
Return the position of a point in relation to the line: parallalel distance along the line, separation and rotation of the separation (from the perpendicular.) Parallalel distance is in [0,length].
- #n_points ⇒ Object
- #n_segments ⇒ Object
- #points ⇒ Object
- #segment(i) ⇒ Object
- #segments ⇒ Object
- #start ⇒ Object
-
#transform(*t) ⇒ Object
multiply by matrix [[a11, a12], [a21, a22]].
Constructor Details
#initialize(*vertices) ⇒ LineString
Returns a new instance of LineString.
309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/geo2d.rb', line 309 def initialize(*vertices) @vertices = vertices to_remove = [] prev = nil @vertices.each_with_index do |v, i| to_remove << i if prev && prev==v prev = v end to_remove.each do |i| @vertices.delete_at i end end |
Instance Method Details
#<<(p) ⇒ Object
324 325 326 327 328 329 330 |
# File 'lib/geo2d.rb', line 324 def <<(p) p = Geo2D.Point(*p) if @vertices.last != p @vertices << p @length = nil end end |
#angle_at(parallel_distance, rotation = 0) ⇒ Object
Angle of the line at a point (in radians, from the X axis, counter-clockwise.) The rotation parameter is added to this angle, if the rotation obtained from locate_point is used, points external to the line have a natural orientation parallel to the line (than can be use to rotate texts or symbols to be aligned with the line.)
423 424 425 426 |
# File 'lib/geo2d.rb', line 423 def angle_at(parallel_distance, rotation=0) i,l = segment_position_of(parallel_distance) segment(i).angle + rotation end |
#apply(prc = nil, &blk) ⇒ Object
433 434 435 436 |
# File 'lib/geo2d.rb', line 433 def apply(prc=nil, &blk) prc = prc || blk LineString.new(*@vertices.map{|v| prc[v]}) end |
#bounds ⇒ Object
442 443 444 445 446 |
# File 'lib/geo2d.rb', line 442 def bounds xs = @vertices.map{|v| v.x} ys = @vertices.map{|v| v.y} [xs.min, ys.min, xs.max, ys.max] end |
#contains?(point) ⇒ Boolean
438 439 440 |
# File 'lib/geo2d.rb', line 438 def contains?(point) self.locate_point(point)[1] == 0 end |
#distance_to(point) ⇒ Object
375 376 377 |
# File 'lib/geo2d.rb', line 375 def distance_to(point) locate_point(point, true)[1].abs end |
#each_point ⇒ Object
350 351 352 353 354 |
# File 'lib/geo2d.rb', line 350 def each_point @vertices.each do |v| yield v end end |
#each_segment ⇒ Object
364 365 366 367 368 |
# File 'lib/geo2d.rb', line 364 def each_segment (0...n_segments).each do |i| yield segment(i) end end |
#end ⇒ Object
336 337 338 |
# File 'lib/geo2d.rb', line 336 def end @vertices.last end |
#interpolate_point(parallel_distance, separation = 0, rotation = 0) ⇒ Object
Compute a point position given the relative position in the line as returned by locate_point().
413 414 415 416 417 |
# File 'lib/geo2d.rb', line 413 def interpolate_point(parallel_distance, separation=0, rotation=0) # separation>0 => left side of line in direction of travel i, l = segment_position_of(parallel_distance) segment(i).interpolate_point(l, separation, rotation) end |
#length ⇒ Object
340 341 342 |
# File 'lib/geo2d.rb', line 340 def length @length ||= total_length end |
#length_to(point) ⇒ Object
379 380 381 |
# File 'lib/geo2d.rb', line 379 def length_to(point) locate_point(point, true).first end |
#locate_point(point) ⇒ Object
Return the position of a point in relation to the line: parallalel distance along the line, separation and rotation of the separation (from the perpendicular.) Parallalel distance is in [0,length]. If we have l,d,r = line.locate_point(point), then the closest line point to point is: line.interpolate_point(l) and line.interpolate_point(l,d,r) is point; d.abs is the distance from line to point; point is on the left of line if d>0; on the right if d<0 and on the line if d==0. If we want to align a text with the line at point, we would use the angle line.angle_at(l,r)
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
# File 'lib/geo2d.rb', line 390 def locate_point(point) best = nil total_l = 0 (0...n_segments).each do |i| seg = segment(i) seg_l = seg.length l,d,rotation = seg.locate_point(point, true) if best.nil? || d.abs<best[1].abs best = [total_l+l, d, rotation] end total_l += seg_l end best end |
#n_points ⇒ Object
344 345 346 |
# File 'lib/geo2d.rb', line 344 def n_points @vertices.size end |
#n_segments ⇒ Object
356 357 358 |
# File 'lib/geo2d.rb', line 356 def n_segments [n_points - 1,0].max end |
#points ⇒ Object
347 348 349 |
# File 'lib/geo2d.rb', line 347 def points @vertices end |
#segment(i) ⇒ Object
370 371 372 373 |
# File 'lib/geo2d.rb', line 370 def segment(i) raise ArgumentError, "Invalid segment index #{i}" unless i>=0 && i<n_segments LineSegment.new(@vertices[i],@vertices[i+1]) end |
#segments ⇒ Object
360 361 362 |
# File 'lib/geo2d.rb', line 360 def segments (0...n_segments).to_a.map{|i| segment(i)} end |
#start ⇒ Object
332 333 334 |
# File 'lib/geo2d.rb', line 332 def start @vertices.first end |
#transform(*t) ⇒ Object
multiply by matrix [[a11, a12], [a21, a22]]
429 430 431 |
# File 'lib/geo2d.rb', line 429 def transform(*t) LineString.new(*@vertices.map{|v| v.transform(*t)}) end |