Created
May 29, 2014 05:56
-
-
Save gouthamvel/c1cd65685aab2aeecf16 to your computer and use it in GitHub Desktop.
Displacement calculation when bearing and distance with point relation are given.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# displacement calculation | |
# Instructions | |
# A car travels from one point to the next. It starts at point A, then moves to point B, then C and so on. Between each point it travels in a straight line. The car's travel is described in the input string in the following format: | |
# <<start_point>|<end_point>>[<heading>:<distance>],... | |
# Heading values can be 0 through 355 degrees (in increments of 5) | |
# For example, input might be: | |
# <A|B>[160:72],<B|C>[40:38],<C|D>[95:118] | |
# The path is considered non cyclic and the order of points may vary like | |
# <B|C>[40:38],<C|D>[95:118],<A|B>[160:72] | |
require 'tsort' | |
class Hash | |
include TSort | |
alias tsort_each_node each_key | |
def tsort_each_child(node, &block) | |
fetch(node).each(&block) | |
end | |
end | |
class Point | |
attr_accessor :name | |
def initialize(name, cords={angle: 0, distance: 0}) | |
@name = name | |
@angle = cords[:angle] * Math::PI / 180 | |
@distance = cords[:distance] | |
end | |
def coordinates_from(from_coordinates) | |
[from_coordinates[0] + @distance*Math.cos(@angle), from_coordinates[1] + @distance*Math.sin(@angle)].map { |e| e.round(3) } | |
end | |
def to_s | |
"#{@name}:(#{@angle}:#{@distance})" | |
end | |
end | |
class PointsChain | |
attr_accessor :mapping, :points | |
def initialize(input) | |
@points = {} | |
@sorted_points = {} | |
@mapping = {} | |
@processed_input = input.split(',').map {|string| create_point_params(string)} | |
@processed_input.each do |args| | |
add Point.new(args[0], angle: args[2], distance: args[3]), args[1] | |
end | |
end | |
def add(point, destination) | |
@points[point.name] = point | |
@mapping[destination] ||= [] | |
@mapping[point.name] ||= [] | |
@mapping[point.name] << destination | |
end | |
def sorted_points(order=:asc) | |
if order == :asc | |
@mapping.tsort.reverse.map {|name| @points[name] }.compact | |
else | |
@mapping.tsort.map {|name| @points[name] }.compact | |
end | |
end | |
def final_coordinates | |
sorted_points.inject([0,0]) do |coordinates, point| | |
point.coordinates_from(coordinates) | |
end | |
end | |
private | |
def parse_regex | |
/<(\w)\|(\w)>\[(\d*)\:(\d*)\],*/ | |
end | |
def create_point_params(string) | |
values = string.match(parse_regex).captures | |
[values[0], values[1], values[2].to_i, values[3].to_f] | |
end | |
end | |
input = "<B|C>[40:38],<C|D>[95:118],<A|B>[160:72]" if ENV['VEL_DEV'] | |
chain = PointsChain.new(input) | |
cords = chain.final_coordinates | |
displacement = cords[0]/2 + cords[1]/2 | |
distance = chain.points.values.uniq{|p| p.name }.inject(0){|dist, point| dist + point.distance} | |
puts "distance #{distance}" | |
puts "displacement #{displacement}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment