Skip to content

Commit

Permalink
Fix merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
zachblock committed Dec 12, 2013
2 parents e36b315 + 2aa1698 commit b388e2b
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 24 deletions.
3 changes: 1 addition & 2 deletions .rspec
@@ -1,2 +1 @@
--color
--backtrace
--color --tty --format nested
3 changes: 3 additions & 0 deletions Rakefile
@@ -1,3 +1,6 @@
require 'bundler/setup'
require 'bundler/gem_tasks'
require 'rake'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'

Expand Down
53 changes: 43 additions & 10 deletions lib/border_patrol.rb
@@ -1,31 +1,64 @@
require 'set'
require 'forwardable'
require 'nokogiri'
require 'border_patrol/version'
require 'border_patrol/point'
require 'border_patrol/polygon'
require 'border_patrol/region'

module BorderPatrol
class InsufficientPointsToActuallyFormAPolygonError < ArgumentError; end
class Point < Struct.new(:x, :y); end

def self.parse_kml(string)
doc = Nokogiri::XML(string)

polygons = doc.search('Polygon').map do |polygon_kml|
parse_kml_polygon_data(polygon_kml.to_s)
placemark_name = placemark_name_for_polygon(polygon_kml)
parse_kml_polygon_data(polygon_kml.to_s,placemark_name)
end
BorderPatrol::Region.new(polygons)
end

def self.bounding_box(points)
max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
points.each do |point|
max_y = point.y if point.y > max_y
min_y = point.y if point.y < min_y
max_x = point.x if point.x > max_x
min_x = point.x if point.x < min_x
end
[Point.new(min_x, max_y), Point.new(max_x, min_y)]
end

def self.central_point(box)
point1, point2 = box

x = (point1.x + point2.x) / 2
y = (point1.y + point2.y) / 2

Point.new(x, y)
end

private

def self.parse_kml_polygon_data(string)

def self.parse_kml_polygon_data(string, name = nil)
doc = Nokogiri::XML(string)
coordinates = doc.xpath('//coordinates').text.strip.split(/\s+/)
points = coordinates.map do |coord|
x, y, _ = coord.strip.split(',')
BorderPatrol::Point.new(x.to_f, y.to_f)
end
BorderPatrol::Polygon.new(points)
BorderPatrol::Polygon.new(points).with_placemark_name(name)
end

def self.placemark_name_for_polygon(p)
# A polygon can be contained by a MultiGeometry or Placemark
parent = p.parent
parent = parent.parent if parent.name == "MultiGeometry"

return nil unless parent.name == "Placemark"

parent.search("name").text
end
end

require 'set'
require 'nokogiri'
require 'border_patrol/version'
require 'border_patrol/polygon'
require 'border_patrol/region'
33 changes: 33 additions & 0 deletions lib/border_patrol/point.rb
@@ -0,0 +1,33 @@
module BorderPatrol
Point = Struct.new(:x, :y) unless defined?(::BorderPatrol::Point)

class Point
alias :latitude :y
alias :latitude= :y=
alias :lat :y
alias :lat= :y=

alias :longitude :x
alias :longitude= :x=
alias :lng :x
alias :lng= :x=
alias :lon :x
alias :lon= :x=

# Lots of Map APIs want the coordinates in lat-lng order
def latlng
[lat, lon]
end
alias :coords :latlng

def inspect
self.class.inspect_string % self.latlng
end

protected
# IE: #<BorderPatrol::Point(lat, lng) = (-25.363882, 131.044922)>
def self.inspect_string
@inspect_string ||= "#<#{self.name}(lat, lng) = (%p, %p)>"
end
end
end
20 changes: 11 additions & 9 deletions lib/border_patrol/polygon.rb
@@ -1,6 +1,6 @@
require 'forwardable'
module BorderPatrol
class Polygon
attr_reader :placemark_name
extend Forwardable
def initialize(*args)
args.flatten!
Expand All @@ -10,6 +10,11 @@ def initialize(*args)
end

def_delegators :@points, :size, :each, :first, :include?, :[], :index

def with_placemark_name(placemark)
@placemark_name ||= placemark
self
end

def ==(other)
# Do we have the right number of points?
Expand Down Expand Up @@ -63,14 +68,11 @@ def inside_bounding_box?(point)
end

def bounding_box
max_x, min_x, max_y, min_y = -Float::MAX, Float::MAX, -Float::MAX, Float::MAX
each do |point|
max_y = point.y if point.y > max_y
min_y = point.y if point.y < min_y
max_x = point.x if point.x > max_x
min_x = point.x if point.x < min_x
end
[Point.new(min_x, max_y), Point.new(max_x, min_y)]
BorderPatrol.bounding_box(self)
end

def central_point
BorderPatrol.central_point(bounding_box)
end
end
end
16 changes: 16 additions & 0 deletions lib/border_patrol/region.rb
Expand Up @@ -11,5 +11,21 @@ def contains_point?(*point)
end
any? { |polygon| polygon.contains_point?(point) }
end

# The below are some general helper methods
def bounding_boxes
map(&:bounding_box)
end

def bounding_box
boxes = bounding_boxes
boxes.flatten!

BorderPatrol.bounding_box(boxes)
end

def central_point
BorderPatrol.central_point(bounding_box)
end
end
end
28 changes: 28 additions & 0 deletions spec/lib/border_patrol/polygon_spec.rb
Expand Up @@ -135,4 +135,32 @@
end

end

describe "#with_placemark_name" do
before(:each) do
points = [BorderPatrol::Point.new(-10, 0), BorderPatrol::Point.new(10, 0), BorderPatrol::Point.new(0, 10)]
@polygon = BorderPatrol::Polygon.new(points)
end

it "adds a placemark name to a polygon" do
@polygon.placemark_name.should be_nil

@polygon.with_placemark_name("Twin Peaks, San Francisco")
@polygon.placemark_name.should == "Twin Peaks, San Francisco"
end

it "returns the Polygon object" do
@polygon.with_placemark_name("Silverlake, Los Angeles").should equal @polygon
end

it "only allows the placemark name to be set once" do
@polygon.placemark_name.should be_nil

@polygon.with_placemark_name("Santa Clara, California")
@polygon.placemark_name.should == "Santa Clara, California"

@polygon.with_placemark_name("Santa Cruz, California")
@polygon.placemark_name.should == "Santa Clara, California"
end
end
end
78 changes: 78 additions & 0 deletions spec/lib/border_patrol_spec.rb
Expand Up @@ -51,6 +51,84 @@
polygon.should eq(BorderPatrol::Polygon.new(BorderPatrol::Point.new(-10, 25), BorderPatrol::Point.new(-1, 30), BorderPatrol::Point.new(10, 1), BorderPatrol::Point.new(0, -5)))
end
end

describe '.placemark_name_for_polygon' do
it 'returns the name of the placemark when Placemark is the parent node' do
kml_data = File.read(Support_Folder + "colorado-test.kml")
doc = Nokogiri::XML(kml_data)
polygon_node = doc.search('Polygon').first

placemark_name = BorderPatrol.placemark_name_for_polygon(polygon_node)
placemark_name.should == "Shape 1"
end

it 'returns the name of the placemark when MultiGeometry is the parent node' do
kml_data = File.read(Support_Folder + "elgin-opengis-ns-test.kml")
doc = Nokogiri::XML(kml_data)
polygon_node = doc.search('Polygon').first

placemark_name = BorderPatrol.placemark_name_for_polygon(polygon_node)
placemark_name.should == "Elgin"
end

it 'returns nil when there is no Placemark' do
kml = <<-EOM
<MultiGeometry>
<description><![CDATA[]]></description>
<styleUrl>#style1</styleUrl>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>1</tessellate>
<coordinates>
-109.053040,41.002705,0.000000
-102.046509,41.006847,0.000000
-102.041016,36.991585,0.000000
-109.048920,36.997070,0.000000
-109.053040,41.002705,0.000000
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</MultiGeometry>
EOM

doc = Nokogiri::XML(kml)
polygon_node = doc.search('Polygon').first

placemark_name = BorderPatrol.placemark_name_for_polygon(polygon_node)
placemark_name.should be_nil
end

it 'returns a blank string when there is no Placemark name' do
kml = <<-EOM
<Placemark>
<description><![CDATA[]]></description>
<styleUrl>#style1</styleUrl>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<tessellate>1</tessellate>
<coordinates>
-109.053040,41.002705,0.000000
-102.046509,41.006847,0.000000
-102.041016,36.991585,0.000000
-109.048920,36.997070,0.000000
-109.053040,41.002705,0.000000
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
EOM

doc = Nokogiri::XML(kml)
polygon_node = doc.search('Polygon').first

placemark_name = BorderPatrol.placemark_name_for_polygon(polygon_node)
placemark_name.should == ""
end
end

describe BorderPatrol::Point do
describe '==' do
Expand Down
6 changes: 3 additions & 3 deletions spec/spec_helper.rb
@@ -1,5 +1,5 @@
require 'rubygems'
require 'bundler'
Bundler.setup
require 'bundler/setup'

Bundler.require :development, :test, :default

require 'border_patrol'

0 comments on commit b388e2b

Please sign in to comment.