$: << '../lib' require 'geo_graf/polygon' describe GeoGraf::Polygon do let(:polygon) { described_class.new(input, factory) } let(:factory) { double("Factory", polygon: rgeo_polygon, point: rgeo_point, linear_ring: rgeo_linear_ring, line: line_180) } let(:rgeo_polygon) { double("RGeoPolygon") } let(:rgeo_point) { double("RGeoPoint") } let(:rgeo_linear_ring) { double("LinearRing") } let(:line_180) { double("Line", intersects?: false) } let(:input) { [[-2, -2], [2, -2], [-2, 1], [-2, -2]] } describe ".new" do subject(:create_new_polygon) { polygon } context "when the polygon doesn't span across 180th meridian" do it "creates a point for each coordinate" do factory.should_receive(:point).exactly(8).times # 4 + 4 used for creation of 180 and -180 lines create_new_polygon end it "creates a linear ring out of the points" do factory.should_receive(:linear_ring).with([rgeo_point] * 4) create_new_polygon end it "creates the polygon using the linear ring" do factory.should_receive(:polygon).with(rgeo_linear_ring) create_new_polygon end end context "when the polygon spans across 180th meridian" do let(:line_180) { double("Line", intersects?: true) } it "creates two polygons using the linear rings" do factory.should_receive(:polygon).with(rgeo_linear_ring).twice create_new_polygon end end end describe "#area" do subject(:get_area) { polygon.area } it "delegates to the internal RGeo polygon" do rgeo_polygon.should_receive(:area) get_area end end describe "#intersection_area" do let(:other_polygon) { double('OtherPolygon', rgeo_polygons: [others_rgeo_polygon_1]) } let(:others_rgeo_polygon_1) { double('OtherRgeoPolygon1') } let(:intersection) { double('Intersection', is_empty?: false, area: 1234.5) } let(:no_intersection) { double('NoIntersection', is_empty?: true) } context "when the polygon doesn't span across 180th meridian" do context "when it intersects the other polygon" do before do rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_1).and_return(intersection) end it "returns the area of the intersection" do expect(polygon.intersection_area(other_polygon)).to eq(1234.5) end context "when the intersection spans over multiple polygons and points" do let(:intersection) { [double('Point'), double('Polygon', area: 123.67), double('Polygon', area: 3.12)] } before do intersection.stub(:is_empty?).and_return(false) end it "returns the sum of areas of the intersection" do expect(polygon.intersection_area(other_polygon)).to eq(126.79) end end end context "when it doesn't intersect the other polygon" do before do rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_1).and_return(no_intersection) end it "returns 0.0" do expect(polygon.intersection_area(other_polygon)).to eq(0.0) end end end context "when the polygon spans across 180th meridian" do let(:other_polygon) { double('OtherPolygon', rgeo_polygons: [others_rgeo_polygon_1, others_rgeo_polygon_2]) } let(:others_rgeo_polygon_2) { double('OtherRgeoPolygon2') } let(:shadow_rgeo_polygon) { double("ShadowRgeoPolygon") } let(:line_180) { double("Line", intersects?: true) } before do factory.stub(:polygon).and_return(rgeo_polygon, shadow_rgeo_polygon) rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_1).and_return(no_intersection) rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_2).and_return(no_intersection) shadow_rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_2).and_return(no_intersection) end context "when it intersects the other polygon" do before do shadow_rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_1).and_return(intersection) end it "returns the area of the intersection" do expect(polygon.intersection_area(other_polygon)).to eq(1234.5) end context "when the intersection spans over multiple polygon" do let(:intersection) { [double('Point'), double('Polygon', area: 123.67), double('Polygon', area: 3.12)] } before do intersection.stub(:is_empty?).and_return(false) end it "returns the sum of areas of the intersection" do expect(polygon.intersection_area(other_polygon)).to eq(126.79) end end end context "when it doesn't intersect the other polygon" do before do shadow_rgeo_polygon.stub(:intersection).with(others_rgeo_polygon_1).and_return(no_intersection) end it "returns 0.0" do expect(polygon.intersection_area(other_polygon)).to eq(0.0) end end end end end