From ea343d66e5dbf33cf519dc06984f018813953106 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 26 Jan 2020 20:32:17 +0100 Subject: [PATCH 01/22] first draft for connect edges refactoring --- lib/src/boolean/compute_fields.rs | 6 ++ lib/src/boolean/connect_edges.rs | 170 +++++++++++++++++++++++++++--- lib/src/boolean/mod.rs | 31 ++++-- lib/src/boolean/sweep_event.rs | 26 ++++- tests/src/bin/run_single_test.rs | 15 ++- tests/src/helper.rs | 2 +- 6 files changed, 224 insertions(+), 26 deletions(-) diff --git a/lib/src/boolean/compute_fields.rs b/lib/src/boolean/compute_fields.rs index 0c336ab..12dce78 100644 --- a/lib/src/boolean/compute_fields.rs +++ b/lib/src/boolean/compute_fields.rs @@ -15,6 +15,12 @@ where } else { event.set_in_out(!prev.is_other_in_out(), prev.is_in_out()); } + + if prev.is_in_result() && !prev.is_vertical() { + event.set_prev_in_result(prev); + } else if let Some(prev_of_prev) = prev.get_prev_in_result() { + event.set_prev_in_result(&prev_of_prev); + } } else { event.set_in_out(false, true); } diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 5286d67..f82f619 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -1,13 +1,14 @@ use super::sweep_event::SweepEvent; use super::Operation; -use geo_types::{LineString, Polygon}; +use geo_types::{LineString, Polygon, Coordinate}; use num_traits::Float; use std::collections::HashSet; +use std::collections::HashMap; use std::rc::Rc; fn order_events(sorted_events: &[Rc>]) -> Vec>> where - F: Float, + F: Float + std::fmt::Debug, { let mut result_events: Vec>> = Vec::new(); @@ -44,10 +45,26 @@ where } } + for r in &result_events { + println!("{:?}", r); + debug_assert!(r.get_other_event().is_some()); + } + + for (i, r) in result_events.iter().enumerate() { + println!("pos {:3} linked to {:3} {} {:?} => {:?}", + i, + r.get_pos(), + if r.is_left() { "L" } else { "R" }, + r.point, + r.get_other_event().map(|o| o.point).unwrap(), + ); + } + result_events } -fn next_pos(pos: i32, result_events: &[Rc>], processed: &mut HashSet, orig_index: i32) -> i32 + +fn next_pos(pos: i32, result_events: &[Rc>], processed: &HashSet, orig_index: i32) -> i32 where F: Float, { @@ -73,40 +90,166 @@ where new_pos = pos - 1; - while processed.contains(&new_pos) && new_pos >= orig_index as i32 { + while processed.contains(&new_pos) { new_pos -= 1; } new_pos } -pub fn connect_edges(sorted_events: &[Rc>], operation: Operation) -> Vec> + +pub struct Contour where - F: Float, + F: Float +{ + pub points: Vec>, + pub hole_ids: Vec, + pub is_external: bool, +} + + +use std::fs::File; +use std::io::Write; +fn debug_print_results(events: &[Rc>]) +where + F: Float + std::fmt::Debug, +{ + let mut writer = File::create("debug.csv").unwrap(); + writeln!(&mut writer, + "index;point;other_point;left;in_result;in_out;other_in_out;is_subject;is_exterior_ring;prev_in_result" + ).expect("Failed to write to file"); + for (i, evt) in events.iter().enumerate() { + writeln!(&mut writer, "{};{:?};{:?};{};{};{};{};{};{};{:?}", + i, + evt.point, + evt.get_other_event().unwrap().point, + if evt.is_left() { "L" } else { "R" }, + evt.is_in_result(), + evt.is_in_out(), + evt.is_other_in_out(), + evt.is_subject, + evt.is_exterior_ring, + evt.get_prev_in_result().map(|o| format!("{:?}", o.point)), + ).expect("Failed to write to file"); + } +} + + +pub fn connect_edges(sorted_events: &[Rc>], operation: Operation) -> Vec> +where + F: Float + std::fmt::Debug, { - let result_events = order_events(sorted_events); + let mut result_events = order_events(sorted_events); + debug_print_results(&result_events); - let mut result: Vec> = Vec::new(); + //let mut result: Vec> = Vec::new(); + let mut result: Vec> = Vec::new(); let mut processed: HashSet = HashSet::new(); + let mut depth: HashMap = HashMap::new(); + let mut hole_of: HashMap = HashMap::new(); + for i in 0..(result_events.len() as i32) { if processed.contains(&i) { continue; } - let mut contour = LineString::(Vec::new()); + //let mut contour = LineString::(Vec::new()); + let mut contour = Contour{ + points: Vec::new(), + hole_ids: Vec::new(), + is_external: true, + }; + + let contour_id = result.len() as i32; + println!("\n *** Adding contour id {}", contour_id); + depth.insert(contour_id, 0); + hole_of.insert(contour_id, -1); + + if let Some(prev_in_result) = result_events[i as usize].get_prev_in_result() { + let lower_contour_id = prev_in_result.get_output_contour_id(); + println!("Inferring information from lower_contour_id = {} with is_in_out = {}", lower_contour_id, prev_in_result.is_in_out()); + println!("{:?}", prev_in_result.point); + println!("{:?}", prev_in_result.get_other_event().unwrap().point); + if !prev_in_result.is_in_out() { + result[lower_contour_id as usize].hole_ids.push(contour_id); + hole_of.insert(contour_id, lower_contour_id); + depth.insert(contour_id, depth[&lower_contour_id] + 1); + contour.is_external = false; + println!("Marking contour as hole of {} with depth {}", lower_contour_id, depth[&contour_id]); + } else if !result[lower_contour_id as usize].is_external { + let parent_contour_id = hole_of[&lower_contour_id]; + result[parent_contour_id as usize].hole_ids.push(contour_id); + hole_of.insert(contour_id, parent_contour_id); + depth.insert(contour_id, depth[&lower_contour_id]); + contour.is_external = false; + println!("Transitively marking contour as hole of {} via {} with depth {}", parent_contour_id, lower_contour_id, depth[&contour_id]); + } + } + /* + if (result_events[i as usize].prev_in_result) { + + if (!result_events[i].prevInResult.resultInOut) { + result[lower_contour_id].holes.push(contourId); + holeOf[contourId] = lower_contour_id; + depth[contourId] = depth[lower_contour_id] + 1; + contour.external = false; + console.log(`Marking contour as hole of ${lower_contour_id} with depth ${depth[lower_contour_id] + 1}`) + } else if (!result[lower_contour_id].external) { + result[holeOf[lower_contour_id]].holes.push(contourId); + holeOf[contourId] = holeOf[lower_contour_id]; + depth[contourId] = depth[lower_contour_id]; + contour.external = false; + console.log(`Transitively marking contour as hole of ${holeOf[lower_contour_id]} via ${lower_contour_id} with depth ${depth[lower_contour_id]}`) + } + } + console.log(` => depth = ${depth[contourId]} holeOf = ${holeOf[contourId]}`) + */ + let mut pos = i; let initial = result_events[i as usize].point; - contour.0.push(initial); + contour.points.push(initial); + + while pos >= 0 && result_events[pos as usize].get_other_event().unwrap().point != initial { + println!("pos = {} {} {:?} => {:?}", + pos, + if result_events[pos as usize].is_left() { "L" } else { "R" }, + result_events[pos as usize].point, + result_events[pos as usize].get_other_event().unwrap().point, + ); + processed.insert(pos); + result_events[pos as usize].set_output_contour_id(contour_id); + + /* + let event = &mut result_events[pos as usize]; + if event.is_left() { + event.set_output_contour_id(contour_id); + } else { + + } + */ + + pos = result_events[pos as usize].get_pos(); + println!("Jumped to: {}", pos); - while pos >= i { processed.insert(pos); + result_events[pos as usize].set_output_contour_id(contour_id); + + contour.points.push(result_events[pos as usize].point); + pos = next_pos(pos, &result_events, &processed, i); + println!("Next pos: {}", pos); + } + if pos != -1 { + processed.insert(pos); + result_events[pos as usize].set_output_contour_id(contour_id); pos = result_events[pos as usize].get_pos(); processed.insert(pos); - contour.0.push(result_events[pos as usize].point); - pos = next_pos(pos, &result_events, &mut processed, i); + result_events[pos as usize].set_output_contour_id(contour_id); } + result.push(contour); + + /* if !result_events[i as usize].is_exterior_ring { if result.is_empty() { result.push(Polygon::new(contour, Vec::new())); @@ -124,6 +267,7 @@ where } else { result.push(Polygon::new(contour, Vec::new())); } + */ } result diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index a44178a..ccecf59 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -1,6 +1,6 @@ use num_traits::Float; -use geo_types::{Coordinate, MultiPolygon, Polygon, Rect}; +use geo_types::{Coordinate, MultiPolygon, Polygon, LineString, Rect}; pub mod compare_segments; pub mod compute_fields; @@ -51,7 +51,7 @@ where impl BooleanOp for Polygon where - F: Float, + F: Float + std::fmt::Debug, { fn boolean(&self, rhs: &Polygon, operation: Operation) -> MultiPolygon { boolean_operation(&[self.clone()], &[rhs.clone()], operation) @@ -60,7 +60,7 @@ where impl BooleanOp> for Polygon where - F: Float, + F: Float + std::fmt::Debug, { fn boolean(&self, rhs: &MultiPolygon, operation: Operation) -> MultiPolygon { boolean_operation(&[self.clone()], rhs.0.as_slice(), operation) @@ -69,7 +69,7 @@ where impl BooleanOp for MultiPolygon where - F: Float, + F: Float + std::fmt::Debug, { fn boolean(&self, rhs: &MultiPolygon, operation: Operation) -> MultiPolygon { boolean_operation(self.0.as_slice(), rhs.0.as_slice(), operation) @@ -78,7 +78,7 @@ where impl BooleanOp> for MultiPolygon where - F: Float, + F: Float + std::fmt::Debug, { fn boolean(&self, rhs: &Polygon, operation: Operation) -> MultiPolygon { boolean_operation(self.0.as_slice(), &[rhs.clone()], operation) @@ -87,7 +87,7 @@ where fn boolean_operation(subject: &[Polygon], clipping: &[Polygon], operation: Operation) -> MultiPolygon where - F: Float, + F: Float + std::fmt::Debug, { let mut sbbox = Rect { min: Coordinate { @@ -110,7 +110,24 @@ where let sorted_events = subdivide(&mut event_queue, &sbbox, &cbbox, operation); - MultiPolygon(connect_edges(&sorted_events, operation)) + let contours = connect_edges(&sorted_events, operation); + + let mut polygons: Vec> = Vec::new(); + + for contour in &contours { + if contour.is_external { + let exterior = LineString(contour.points.clone()); + let mut interios: Vec> = Vec::new(); + for hole_id in &contour.hole_ids { + interios.push(LineString(contours[*hole_id as usize].points.clone())); + } + + let polygon = Polygon::new(exterior, interios); + polygons.push(polygon); + } + } + + MultiPolygon(polygons) } fn trivial_result(subject: &[Polygon], clipping: &[Polygon], operation: Operation) -> MultiPolygon diff --git a/lib/src/boolean/sweep_event.rs b/lib/src/boolean/sweep_event.rs index 7f88fe6..4e00538 100644 --- a/lib/src/boolean/sweep_event.rs +++ b/lib/src/boolean/sweep_event.rs @@ -7,7 +7,7 @@ use std::rc::{Rc, Weak}; use super::helper::less_if; use super::signed_area::signed_area; -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum EdgeType { Normal, NonContributing, @@ -15,21 +15,23 @@ pub enum EdgeType { DifferentTransition, } -#[derive(Clone)] +#[derive(Clone, Debug)] struct MutablePart where F: Float, { left: bool, other_event: Weak>, + prev_in_result: Weak>, edge_type: EdgeType, in_out: bool, other_in_out: bool, in_result: bool, pos: i32, + output_contour_id: i32, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct SweepEvent where F: Float, @@ -57,11 +59,13 @@ where mutable: RefCell::new(MutablePart { left, other_event, + prev_in_result: Weak::new(), edge_type: EdgeType::Normal, in_out: false, other_in_out: false, in_result: false, pos: 0, + output_contour_id: -1, }), contour_id, point, @@ -86,6 +90,14 @@ where self.mutable.borrow_mut().other_event = Rc::downgrade(other_event); } + pub fn get_prev_in_result(&self) -> Option>> { + self.mutable.borrow().prev_in_result.upgrade() + } + + pub fn set_prev_in_result(&self, prev_in_result: &Rc>) { + self.mutable.borrow_mut().prev_in_result = Rc::downgrade(prev_in_result); + } + pub fn get_edge_type(&self) -> EdgeType { self.mutable.borrow().edge_type } @@ -125,6 +137,14 @@ where self.mutable.borrow_mut().pos = pos } + pub fn get_output_contour_id(&self) -> i32 { + self.mutable.borrow().output_contour_id + } + + pub fn set_output_contour_id(&self, output_contour_id: i32) { + self.mutable.borrow_mut().output_contour_id = output_contour_id + } + pub fn is_below(&self, p: Coordinate) -> bool { if let Some(ref other_event) = self.get_other_event() { if self.is_left() { diff --git a/tests/src/bin/run_single_test.rs b/tests/src/bin/run_single_test.rs index b6d3a52..6b37181 100644 --- a/tests/src/bin/run_single_test.rs +++ b/tests/src/bin/run_single_test.rs @@ -1,10 +1,21 @@ extern crate geo_booleanop_tests; +use std::fs; +use std::process::Command; use geo_booleanop_tests::helper::run_generic_test_case; fn main() { let args: Vec = std::env::args().collect(); - let filename = &args[1]; + let filename_in = args[1].clone(); + let filename_out = filename_in.clone() + ".generated"; - run_generic_test_case(filename, false); + fs::copy(&filename_in, &filename_out).expect("Failed to copy file."); + + run_generic_test_case(&filename_out, true); + + Command::new("../martinez/polygon_ops_debugging/plot_test_cases.py") + .arg("-i") + .arg(&filename_out) + .spawn() + .expect("Failed to run Python plot."); } \ No newline at end of file diff --git a/tests/src/helper.rs b/tests/src/helper.rs index 5e0fe64..5a1e14a 100644 --- a/tests/src/helper.rs +++ b/tests/src/helper.rs @@ -156,7 +156,7 @@ pub fn run_generic_test_case(filename: &str, regenerate: bool) { }; if !regenerate { - assert_eq!(result, expected_result.result); + assert_eq!(result, expected_result.result, "Deviation found in test case: {}", filename); } let mut output_feature = features[i].clone(); From 59f8c86d7323bb87ed576004d6934c6b9068dc23 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sun, 26 Jan 2020 23:21:00 +0100 Subject: [PATCH 02/22] added tracking of result transitions --- lib/src/boolean/compute_fields.rs | 21 ++++++++++++++++++-- lib/src/boolean/connect_edges.rs | 32 ++++++++++++++++--------------- lib/src/boolean/sweep_event.rs | 21 +++++++++++++++----- tests/src/helper.rs | 9 +++++++-- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/lib/src/boolean/compute_fields.rs b/lib/src/boolean/compute_fields.rs index 12dce78..896a56c 100644 --- a/lib/src/boolean/compute_fields.rs +++ b/lib/src/boolean/compute_fields.rs @@ -1,4 +1,4 @@ -use super::sweep_event::{EdgeType, SweepEvent}; +use super::sweep_event::{EdgeType, SweepEvent, ResultTransition}; use super::Operation; use num_traits::Float; use std::rc::Rc; @@ -25,7 +25,24 @@ where event.set_in_out(false, true); } - event.set_in_result(in_result(event, operation)); + let in_result = in_result(event, operation); + let result_transition = if !in_result { + ResultTransition::None + } else { + let mut this_in = !event.is_in_out(); + let mut that_in = !event.is_other_in_out(); + if !event.is_subject { + std::mem::swap(&mut this_in, &mut that_in); + } + let is_in = match operation { + Operation::Intersection => this_in && that_in, + Operation::Union => this_in || that_in, + Operation::Difference => this_in && !that_in, + Operation::Xor => this_in ^ that_in, + }; + if is_in { ResultTransition::OutIn } else { ResultTransition::InOut } + }; + event.set_result_transition(result_transition); } fn in_result(event: &SweepEvent, operation: Operation) -> bool diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index f82f619..905c280 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -1,4 +1,4 @@ -use super::sweep_event::SweepEvent; +use super::sweep_event::{SweepEvent, ResultTransition}; use super::Operation; use geo_types::{LineString, Polygon, Coordinate}; use num_traits::Float; @@ -115,20 +115,22 @@ where { let mut writer = File::create("debug.csv").unwrap(); writeln!(&mut writer, - "index;point;other_point;left;in_result;in_out;other_in_out;is_subject;is_exterior_ring;prev_in_result" + "index;x;y;other_x;other_y;lr;result_transition;in_out;other_in_out;is_subject;is_exterior_ring;prev_in_result" ).expect("Failed to write to file"); for (i, evt) in events.iter().enumerate() { - writeln!(&mut writer, "{};{:?};{:?};{};{};{};{};{};{};{:?}", - i, - evt.point, - evt.get_other_event().unwrap().point, - if evt.is_left() { "L" } else { "R" }, - evt.is_in_result(), - evt.is_in_out(), - evt.is_other_in_out(), - evt.is_subject, - evt.is_exterior_ring, - evt.get_prev_in_result().map(|o| format!("{:?}", o.point)), + writeln!(&mut writer, "{i};{x:?};{y:?};{other_x:?};{other_y:?};{lr};{transition:?};{in_out};{other_in_out};{subject};{exterior_ring};{prev_in_result:?}", + i=i, + x=evt.point.x, + y=evt.point.y, + other_x=evt.get_other_event().unwrap().point.x, + other_y=evt.get_other_event().unwrap().point.y, + lr=if evt.is_left() { "L" } else { "R" }, + transition=evt.get_result_transition(), + in_out=evt.is_in_out(), + other_in_out=evt.is_other_in_out(), + subject=evt.is_subject, + exterior_ring=evt.is_exterior_ring, + prev_in_result=evt.get_prev_in_result().map(|o| format!("{:?}", o.point)), ).expect("Failed to write to file"); } } @@ -166,10 +168,10 @@ where if let Some(prev_in_result) = result_events[i as usize].get_prev_in_result() { let lower_contour_id = prev_in_result.get_output_contour_id(); - println!("Inferring information from lower_contour_id = {} with is_in_out = {}", lower_contour_id, prev_in_result.is_in_out()); + println!("Inferring information from lower_contour_id = {} with result transition = {:?}", lower_contour_id, prev_in_result.get_result_transition()); println!("{:?}", prev_in_result.point); println!("{:?}", prev_in_result.get_other_event().unwrap().point); - if !prev_in_result.is_in_out() { + if prev_in_result.get_result_transition() == ResultTransition::OutIn { result[lower_contour_id as usize].hole_ids.push(contour_id); hole_of.insert(contour_id, lower_contour_id); depth.insert(contour_id, depth[&lower_contour_id] + 1); diff --git a/lib/src/boolean/sweep_event.rs b/lib/src/boolean/sweep_event.rs index 4e00538..35f0ae9 100644 --- a/lib/src/boolean/sweep_event.rs +++ b/lib/src/boolean/sweep_event.rs @@ -15,6 +15,13 @@ pub enum EdgeType { DifferentTransition, } +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum ResultTransition { + None, + InOut, + OutIn, +} + #[derive(Clone, Debug)] struct MutablePart where @@ -26,7 +33,7 @@ where edge_type: EdgeType, in_out: bool, other_in_out: bool, - in_result: bool, + result_transition: ResultTransition, pos: i32, output_contour_id: i32, } @@ -63,7 +70,7 @@ where edge_type: EdgeType::Normal, in_out: false, other_in_out: false, - in_result: false, + result_transition: ResultTransition::None, pos: 0, output_contour_id: -1, }), @@ -115,11 +122,15 @@ where } pub fn is_in_result(&self) -> bool { - self.mutable.borrow().in_result + self.mutable.borrow().result_transition != ResultTransition::None + } + + pub fn set_result_transition(&self, result_transition: ResultTransition) { + self.mutable.borrow_mut().result_transition = result_transition } - pub fn set_in_result(&self, in_result: bool) { - self.mutable.borrow_mut().in_result = in_result + pub fn get_result_transition(&self) -> ResultTransition { + self.mutable.borrow().result_transition } pub fn set_in_out(&self, in_out: bool, other_in_out: bool) { diff --git a/tests/src/helper.rs b/tests/src/helper.rs index 5a1e14a..b713cd1 100644 --- a/tests/src/helper.rs +++ b/tests/src/helper.rs @@ -131,7 +131,7 @@ fn extract_expected_result(feature: &Feature) -> ExpectedResult { } pub fn run_generic_test_case(filename: &str, regenerate: bool) { - println!("Running test case: {}", filename); + println!("\n *** Running test case: {}", filename); let original_geojson = load_fixture_from_path(filename); let features = match original_geojson { @@ -146,6 +146,7 @@ pub fn run_generic_test_case(filename: &str, regenerate: bool) { for i in 2 .. features.len() { let expected_result = extract_expected_result(&features[i]); + println!("Testing operation: {:?}", expected_result.op); let result = match expected_result.op { TestOperation::Union => p1.union(&p2), @@ -156,7 +157,11 @@ pub fn run_generic_test_case(filename: &str, regenerate: bool) { }; if !regenerate { - assert_eq!(result, expected_result.result, "Deviation found in test case: {}", filename); + assert_eq!( + result, + expected_result.result, + "Deviation found in test case {} with operation {:?}", filename, expected_result.op, + ); } let mut output_feature = features[i].clone(); From e5b430931283e70bbc627e4d199394ac85a7e0c8 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 27 Jan 2020 21:03:32 +0100 Subject: [PATCH 03/22] fixed logic in connect_edges; minor cleanup --- lib/src/boolean/connect_edges.rs | 84 ++++++++------------------------ lib/src/boolean/mod.rs | 2 +- 2 files changed, 22 insertions(+), 64 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 905c280..101efea 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -136,11 +136,11 @@ where } -pub fn connect_edges(sorted_events: &[Rc>], operation: Operation) -> Vec> +pub fn connect_edges(sorted_events: &[Rc>]) -> Vec> where F: Float + std::fmt::Debug, { - let mut result_events = order_events(sorted_events); + let result_events = order_events(sorted_events); debug_print_results(&result_events); //let mut result: Vec> = Vec::new(); @@ -154,7 +154,6 @@ where if processed.contains(&i) { continue; } - //let mut contour = LineString::(Vec::new()); let mut contour = Contour{ points: Vec::new(), hole_ids: Vec::new(), @@ -172,39 +171,27 @@ where println!("{:?}", prev_in_result.point); println!("{:?}", prev_in_result.get_other_event().unwrap().point); if prev_in_result.get_result_transition() == ResultTransition::OutIn { - result[lower_contour_id as usize].hole_ids.push(contour_id); - hole_of.insert(contour_id, lower_contour_id); - depth.insert(contour_id, depth[&lower_contour_id] + 1); - contour.is_external = false; - println!("Marking contour as hole of {} with depth {}", lower_contour_id, depth[&contour_id]); - } else if !result[lower_contour_id as usize].is_external { - let parent_contour_id = hole_of[&lower_contour_id]; - result[parent_contour_id as usize].hole_ids.push(contour_id); - hole_of.insert(contour_id, parent_contour_id); - depth.insert(contour_id, depth[&lower_contour_id]); - contour.is_external = false; - println!("Transitively marking contour as hole of {} via {} with depth {}", parent_contour_id, lower_contour_id, depth[&contour_id]); - } - } - /* - if (result_events[i as usize].prev_in_result) { - - if (!result_events[i].prevInResult.resultInOut) { - result[lower_contour_id].holes.push(contourId); - holeOf[contourId] = lower_contour_id; - depth[contourId] = depth[lower_contour_id] + 1; - contour.external = false; - console.log(`Marking contour as hole of ${lower_contour_id} with depth ${depth[lower_contour_id] + 1}`) - } else if (!result[lower_contour_id].external) { - result[holeOf[lower_contour_id]].holes.push(contourId); - holeOf[contourId] = holeOf[lower_contour_id]; - depth[contourId] = depth[lower_contour_id]; - contour.external = false; - console.log(`Transitively marking contour as hole of ${holeOf[lower_contour_id]} via ${lower_contour_id} with depth ${depth[lower_contour_id]}`) + // We are inside, let's check if the thing below us is an exterior contour or just + // another hole. + if result[lower_contour_id as usize].is_external { + result[lower_contour_id as usize].hole_ids.push(contour_id); + hole_of.insert(contour_id, lower_contour_id); + depth.insert(contour_id, depth[&lower_contour_id] + 1); + contour.is_external = false; + println!("Marking contour as hole of {} with depth {}", lower_contour_id, depth[&contour_id]); + } else { + let parent_contour_id = hole_of[&lower_contour_id]; + result[parent_contour_id as usize].hole_ids.push(contour_id); + hole_of.insert(contour_id, parent_contour_id); + depth.insert(contour_id, depth[&lower_contour_id]); + contour.is_external = false; + println!("Transitively marking contour as hole of {} via {} with depth {}", parent_contour_id, lower_contour_id, depth[&contour_id]); + } + } else { + contour.is_external = true; + println!("Keeping contour as external"); } } - console.log(` => depth = ${depth[contourId]} holeOf = ${holeOf[contourId]}`) - */ let mut pos = i; let initial = result_events[i as usize].point; @@ -221,15 +208,6 @@ where processed.insert(pos); result_events[pos as usize].set_output_contour_id(contour_id); - /* - let event = &mut result_events[pos as usize]; - if event.is_left() { - event.set_output_contour_id(contour_id); - } else { - - } - */ - pos = result_events[pos as usize].get_pos(); println!("Jumped to: {}", pos); @@ -250,26 +228,6 @@ where } result.push(contour); - - /* - if !result_events[i as usize].is_exterior_ring { - if result.is_empty() { - result.push(Polygon::new(contour, Vec::new())); - } else { - result - .last_mut() - .expect("Result must not be empty at this point") - .interiors_push(contour); - } - } else if operation == Operation::Difference && !result_events[i as usize].is_subject && result.len() > 1 { - result - .last_mut() - .expect("Result must not be empty at this point") - .interiors_push(contour); - } else { - result.push(Polygon::new(contour, Vec::new())); - } - */ } result diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index ccecf59..42dbdc9 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -110,7 +110,7 @@ where let sorted_events = subdivide(&mut event_queue, &sbbox, &cbbox, operation); - let contours = connect_edges(&sorted_events, operation); + let contours = connect_edges(&sorted_events); let mut polygons: Vec> = Vec::new(); From 2688a47a784cf4186139d230c90d4038ff6d3649 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 27 Jan 2020 21:17:21 +0100 Subject: [PATCH 04/22] fixed fatal2 test case --- lib/src/boolean/compute_fields.rs | 5 +++++ .../{new.geojson.template => _new.geojson.template} | 0 tests/fixtures/generic_test_cases/fatal2.geojson | 12 +++--------- 3 files changed, 8 insertions(+), 9 deletions(-) rename tests/fixtures/generic_test_cases/{new.geojson.template => _new.geojson.template} (100%) diff --git a/lib/src/boolean/compute_fields.rs b/lib/src/boolean/compute_fields.rs index 896a56c..49fb108 100644 --- a/lib/src/boolean/compute_fields.rs +++ b/lib/src/boolean/compute_fields.rs @@ -16,6 +16,9 @@ where event.set_in_out(!prev.is_other_in_out(), prev.is_in_out()); } + // Connect to previous in result: Only use the given `prev` if it is + // part of the result and not a vertical segment. Otherwise connect + // to its previous in result if any. if prev.is_in_result() && !prev.is_vertical() { event.set_prev_in_result(prev); } else if let Some(prev_of_prev) = prev.get_prev_in_result() { @@ -25,6 +28,8 @@ where event.set_in_out(false, true); } + // Determine whether segment is in result, and if so, whether it is an + // in-out or out-in transition. let in_result = in_result(event, operation); let result_transition = if !in_result { ResultTransition::None diff --git a/tests/fixtures/generic_test_cases/new.geojson.template b/tests/fixtures/generic_test_cases/_new.geojson.template similarity index 100% rename from tests/fixtures/generic_test_cases/new.geojson.template rename to tests/fixtures/generic_test_cases/_new.geojson.template diff --git a/tests/fixtures/generic_test_cases/fatal2.geojson b/tests/fixtures/generic_test_cases/fatal2.geojson index 694483b..4718f72 100644 --- a/tests/fixtures/generic_test_cases/fatal2.geojson +++ b/tests/fixtures/generic_test_cases/fatal2.geojson @@ -360,25 +360,19 @@ [-79.894336, 40.44128999906837], [-79.894344, 40.4412529990685], [-79.894363, 40.44117499906849] - ] - ], - [ + ], [ [-79.887688, 40.444657999068475], [-79.88768796122203, 40.444657857562895], [-79.88768799972165, 40.44465799897759], [-79.887688, 40.444657999068475] - ] - ], - [ + ], [ [-79.88768795318525, 40.44465798378203], [-79.88761078560448, 40.44463125072726], [-79.887639, 40.44464199906838], [-79.88768795318525, 40.44465798378203] - ] - ], - [ + ], [ [-79.88724301621599, 40.443023510093695], [-79.887235, 40.442993999068484], From 04227970a0817667306c4a4de3f857fb7170fb6d Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 27 Jan 2020 21:34:03 +0100 Subject: [PATCH 05/22] added new test cases --- .gitignore | 2 + .../generic_test_cases/closed_loop1.geojson | 72 ++++++++ .../generic_test_cases/disjoint_boxes.geojson | 106 ++++++++++++ .../generic_test_cases/nested_polys1.geojson | 80 +++++++++ .../generic_test_cases/nested_polys2.geojson | 108 ++++++++++++ .../generic_test_cases/nested_polys3.geojson | 162 ++++++++++++++++++ 6 files changed, 530 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/closed_loop1.geojson create mode 100644 tests/fixtures/generic_test_cases/disjoint_boxes.geojson create mode 100644 tests/fixtures/generic_test_cases/nested_polys1.geojson create mode 100644 tests/fixtures/generic_test_cases/nested_polys2.geojson create mode 100644 tests/fixtures/generic_test_cases/nested_polys3.geojson diff --git a/.gitignore b/.gitignore index 4bdb419..35eb536 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ .idea/ .vscode/ +# Files generated from debugging test_cases.pdf +*.geojson.generated diff --git a/tests/fixtures/generic_test_cases/closed_loop1.geojson b/tests/fixtures/generic_test_cases/closed_loop1.geojson new file mode 100644 index 0000000..0592dbf --- /dev/null +++ b/tests/fixtures/generic_test_cases/closed_loop1.geojson @@ -0,0 +1,72 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [-1, 1], + [1, 1], + [1, -1], + [-1, -1], + [-1, -0.9], + [0.9, -0.9], + [0.9, 0.9], + [-1, 0.9], + [-1, 1] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [-1, 1], + [-0.9, 1], + [-0.9, -1], + [-1, -1], + [-1, 1] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-1, -1], + [-0.9, -1], + [1, -1], + [1, 1], + [-0.9, 1], + [-1, 1], + [-1, 0.9], + [-1, -0.9], + [-1, -1] + ], + [ + [-0.9, -0.9], + [0.9, -0.9], + [0.9, 0.9], + [-0.9, 0.9], + [-0.9, -0.9] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/disjoint_boxes.geojson b/tests/fixtures/generic_test_cases/disjoint_boxes.geojson new file mode 100644 index 0000000..e9d5e3d --- /dev/null +++ b/tests/fixtures/generic_test_cases/disjoint_boxes.geojson @@ -0,0 +1,106 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [0.55, 0.55], + [0.55, 1.45], + [1.45, 1.45], + [1.45, 0.55], + [0.55, 0.55] + ] + ], + [ + [ + [1.55, 1.55], + [1.55, 2.45], + [2.45, 2.45], + [2.45, 1.55], + [1.55, 1.55] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.55, 1.55], + [0.55, 2.45], + [1.45, 2.45], + [1.45, 1.55], + [0.55, 1.55] + ] + ], + [ + [ + [1.55, 0.55], + [1.55, 1.45], + [2.45, 1.45], + [2.45, 0.55], + [1.55, 0.55] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.55, 0.55], + [1.45, 0.55], + [1.45, 1.45], + [0.55, 1.45], + [0.55, 0.55] + ] + ], + [ + [ + [0.55, 1.55], + [1.45, 1.55], + [1.45, 2.45], + [0.55, 2.45], + [0.55, 1.55] + ] + ], + [ + [ + [1.55, 0.55], + [2.45, 0.55], + [2.45, 1.45], + [1.55, 1.45], + [1.55, 0.55] + ] + ], + [ + [ + [1.55, 1.55], + [2.45, 1.55], + [2.45, 2.45], + [1.55, 2.45], + [1.55, 1.55] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/nested_polys1.geojson b/tests/fixtures/generic_test_cases/nested_polys1.geojson new file mode 100644 index 0000000..f67b910 --- /dev/null +++ b/tests/fixtures/generic_test_cases/nested_polys1.geojson @@ -0,0 +1,80 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.1, 0.1], + [0.1, 0.9], + [0.9, 0.9], + [0.9, 0.1], + [0.1, 0.1] + ], + [ + [0.2, 0.2], + [0.2, 0.8], + [0.8, 0.8], + [0.8, 0.2], + [0.2, 0.2] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ], + [ + [0.1, 0.1], + [0.9, 0.1], + [0.9, 0.9], + [0.1, 0.9], + [0.1, 0.1] + ] + ], + [ + [ + [0.2, 0.2], + [0.8, 0.2], + [0.8, 0.8], + [0.2, 0.8], + [0.2, 0.2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/nested_polys2.geojson b/tests/fixtures/generic_test_cases/nested_polys2.geojson new file mode 100644 index 0000000..bf2b44a --- /dev/null +++ b/tests/fixtures/generic_test_cases/nested_polys2.geojson @@ -0,0 +1,108 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [0, 0], + [1, 0], + [1, 3], + [0, 3], + [0, 0] + ], + [ + [0.1, 0.1], + [0.1, 0.9], + [0.9, 0.9], + [0.9, 0.1], + [0.1, 0.1] + ], + [ + [0.1, 2.1], + [0.1, 2.9], + [0.9, 2.9], + [0.9, 2.1], + [0.1, 2.1] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.1, 1.1], + [0.1, 1.9], + [0.9, 1.9], + [0.9, 1.1], + [0.1, 1.1] + ], + [ + [0.2, 1.2], + [0.2, 1.8], + [0.8, 1.8], + [0.8, 1.2], + [0.2, 1.2] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 3], + [0, 3], + [0, 0] + ], + [ + [0.1, 0.1], + [0.9, 0.1], + [0.9, 0.9], + [0.1, 0.9], + [0.1, 0.1] + ], + [ + [0.1, 1.1], + [0.9, 1.1], + [0.9, 1.9], + [0.1, 1.9], + [0.1, 1.1] + ], + [ + [0.1, 2.1], + [0.9, 2.1], + [0.9, 2.9], + [0.1, 2.9], + [0.1, 2.1] + ] + ], + [ + [ + [0.2, 1.2], + [0.8, 1.2], + [0.8, 1.8], + [0.2, 1.8], + [0.2, 1.2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/nested_polys3.geojson b/tests/fixtures/generic_test_cases/nested_polys3.geojson new file mode 100644 index 0000000..0614d8a --- /dev/null +++ b/tests/fixtures/generic_test_cases/nested_polys3.geojson @@ -0,0 +1,162 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [-10, -10], + [-10, 10], + [10, 10], + [10, -10], + [-10, -10] + ], + [ + [-9.5, -9.5], + [-9.5, 9.5], + [9.5, 9.5], + [9.5, -9.5], + [-9.5, -9.5] + ] + ], + [ + [ + [-9, -9], + [-9, 9], + [9, 9], + [9, -9], + [-9, -9] + ], + [ + [-8.5, -8.5], + [-8.5, 8.5], + [8.5, 8.5], + [8.5, -8.5], + [-8.5, -8.5] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-7, -7], + [-7, 7], + [7, 7], + [7, -7], + [-7, -7] + ], + [ + [-6.5, -6.5], + [-6.5, 6.5], + [6.5, 6.5], + [6.5, -6.5], + [-6.5, -6.5] + ] + ], + [ + [ + [-6, -6], + [-6, 6], + [6, 6], + [6, -6], + [-6, -6] + ], + [ + [-5.5, -5.5], + [-5.5, 5.5], + [5.5, 5.5], + [5.5, -5.5], + [-5.5, -5.5] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-10, -10], + [10, -10], + [10, 10], + [-10, 10], + [-10, -10] + ], + [ + [-9.5, -9.5], + [9.5, -9.5], + [9.5, 9.5], + [-9.5, 9.5], + [-9.5, -9.5] + ] + ], + [ + [ + [-9, -9], + [9, -9], + [9, 9], + [-9, 9], + [-9, -9] + ], + [ + [-8.5, -8.5], + [8.5, -8.5], + [8.5, 8.5], + [-8.5, 8.5], + [-8.5, -8.5] + ] + ], + [ + [ + [-7, -7], + [7, -7], + [7, 7], + [-7, 7], + [-7, -7] + ], + [ + [-6.5, -6.5], + [6.5, -6.5], + [6.5, 6.5], + [-6.5, 6.5], + [-6.5, -6.5] + ] + ], + [ + [ + [-6, -6], + [6, -6], + [6, 6], + [-6, 6], + [-6, -6] + ], + [ + [-5.5, -5.5], + [5.5, -5.5], + [5.5, 5.5], + [-5.5, 5.5], + [-5.5, -5.5] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 86b0b43951fbda2bb424f845d54bfbca93a6398c Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 27 Jan 2020 22:10:49 +0100 Subject: [PATCH 06/22] simplified feature type tests --- .../feature_types/clipping_poly.geojson | 31 --- .../fixtures/feature_types/multi_poly.geojson | 57 ----- .../multi_poly_with_hole.geojson | 79 ------- .../difference/multi_poly_to_clipping.geojson | 79 ------- .../multi_poly_with_hole_to_clipping.geojson | 95 -------- .../out/difference/poly_to_clipping.geojson | 45 ---- .../poly_with_hole_to_clipping.geojson | 61 ----- .../multi_poly_to_clipping.geojson | 63 ----- .../multi_poly_with_hole_to_clipping.geojson | 71 ------ .../out/intersection/poly_to_clipping.geojson | 37 --- .../poly_with_hole_to_clipping.geojson | 45 ---- .../out/union/multi_poly_to_clipping.geojson | 69 ------ .../multi_poly_with_hole_to_clipping.geojson | 99 -------- .../out/union/poly_to_clipping.geojson | 53 ----- .../union/poly_with_hole_to_clipping.geojson | 83 ------- .../out/xor/multi_poly_to_clipping.geojson | 119 ---------- .../multi_poly_with_hole_to_clipping.geojson | 157 ------------- .../out/xor/poly_to_clipping.geojson | 79 ------- .../xor/poly_with_hole_to_clipping.geojson | 117 ---------- tests/fixtures/feature_types/poly.geojson | 31 --- .../feature_types/poly_with_hole.geojson | 53 ----- .../generic_test_cases/basic1_poly.geojson | 136 +++++++++++ .../basic2_poly_with_hole.geojson | 169 ++++++++++++++ .../basic3_multi_poly.geojson | 184 +++++++++++++++ .../basic4_multi_poly_with_hole.geojson | 217 ++++++++++++++++++ tests/src/feature_type_test.rs | 65 ------ tests/src/lib.rs | 2 - 27 files changed, 706 insertions(+), 1590 deletions(-) delete mode 100644 tests/fixtures/feature_types/clipping_poly.geojson delete mode 100644 tests/fixtures/feature_types/multi_poly.geojson delete mode 100644 tests/fixtures/feature_types/multi_poly_with_hole.geojson delete mode 100644 tests/fixtures/feature_types/out/difference/multi_poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/difference/multi_poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/difference/poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/difference/poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/intersection/multi_poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/intersection/multi_poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/intersection/poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/intersection/poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/union/multi_poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/union/multi_poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/union/poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/union/poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/xor/multi_poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/xor/multi_poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/xor/poly_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/out/xor/poly_with_hole_to_clipping.geojson delete mode 100644 tests/fixtures/feature_types/poly.geojson delete mode 100644 tests/fixtures/feature_types/poly_with_hole.geojson create mode 100644 tests/fixtures/generic_test_cases/basic1_poly.geojson create mode 100644 tests/fixtures/generic_test_cases/basic2_poly_with_hole.geojson create mode 100644 tests/fixtures/generic_test_cases/basic3_multi_poly.geojson create mode 100644 tests/fixtures/generic_test_cases/basic4_multi_poly_with_hole.geojson delete mode 100644 tests/src/feature_type_test.rs diff --git a/tests/fixtures/feature_types/clipping_poly.geojson b/tests/fixtures/feature_types/clipping_poly.geojson deleted file mode 100644 index 457c0aa..0000000 --- a/tests/fixtures/feature_types/clipping_poly.geojson +++ /dev/null @@ -1,31 +0,0 @@ -{ - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0.25, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 0.25 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/multi_poly.geojson b/tests/fixtures/feature_types/multi_poly.geojson deleted file mode 100644 index 78ab2a9..0000000 --- a/tests/fixtures/feature_types/multi_poly.geojson +++ /dev/null @@ -1,57 +0,0 @@ -{ - "type": "Feature", - "properties": {}, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ], - [ - [ - [ - 2, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/multi_poly_with_hole.geojson b/tests/fixtures/feature_types/multi_poly_with_hole.geojson deleted file mode 100644 index 8a5aacf..0000000 --- a/tests/fixtures/feature_types/multi_poly_with_hole.geojson +++ /dev/null @@ -1,79 +0,0 @@ -{ - "type": "Feature", - "properties": {}, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.2, - 0.4 - ], - [ - 0.4, - 0.4 - ], - [ - 0.4, - 0.2 - ], - [ - 0.2, - 0.2 - ] - ] - ], - [ - [ - [ - 2, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/difference/multi_poly_to_clipping.geojson b/tests/fixtures/feature_types/out/difference/multi_poly_to_clipping.geojson deleted file mode 100644 index 52e9a59..0000000 --- a/tests/fixtures/feature_types/out/difference/multi_poly_to_clipping.geojson +++ /dev/null @@ -1,79 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#25856a", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#521199", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ], - [ - [ - [ - 2, - 2.75 - ], - [ - 2.75, - 2.75 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/difference/multi_poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/difference/multi_poly_with_hole_to_clipping.geojson deleted file mode 100644 index a240d58..0000000 --- a/tests/fixtures/feature_types/out/difference/multi_poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,95 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#3a8b1f", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#36744f", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.4, - 0.25 - ], - [ - 0.4, - 0.2 - ], - [ - 0.2, - 0.2 - ], - [ - 0.2, - 0.4 - ], - [ - 0.25, - 0.4 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ], - [ - [ - [ - 2, - 2.75 - ], - [ - 2.75, - 2.75 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/difference/poly_to_clipping.geojson b/tests/fixtures/feature_types/out/difference/poly_to_clipping.geojson deleted file mode 100644 index c3c9b3f..0000000 --- a/tests/fixtures/feature_types/out/difference/poly_to_clipping.geojson +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#a50505", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#1e8c7b", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/difference/poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/difference/poly_with_hole_to_clipping.geojson deleted file mode 100644 index 6539a26..0000000 --- a/tests/fixtures/feature_types/out/difference/poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,61 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#a50505", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#1e8c7b", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.4, - 0.25 - ], - [ - 0.4, - 0.2 - ], - [ - 0.2, - 0.2 - ], - [ - 0.2, - 0.4 - ], - [ - 0.25, - 0.4 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/intersection/multi_poly_to_clipping.geojson b/tests/fixtures/feature_types/out/intersection/multi_poly_to_clipping.geojson deleted file mode 100644 index 19841f8..0000000 --- a/tests/fixtures/feature_types/out/intersection/multi_poly_to_clipping.geojson +++ /dev/null @@ -1,63 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#25856a", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#521199", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0.25, - 0.25 - ], - [ - 1, - 0.25 - ], - [ - 1, - 1 - ], - [ - 0.25, - 1 - ], - [ - 0.25, - 0.25 - ] - ] - ], - [ - [ - [ - 2, - 2 - ], - [ - 2.75, - 2 - ], - [ - 2.75, - 2.75 - ], - [ - 2, - 2.75 - ], - [ - 2, - 2 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/intersection/multi_poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/intersection/multi_poly_with_hole_to_clipping.geojson deleted file mode 100644 index 032316f..0000000 --- a/tests/fixtures/feature_types/out/intersection/multi_poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,71 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#3a8b1f", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#36744f", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0.25, - 0.4 - ], - [ - 0.4, - 0.4 - ], - [ - 0.4, - 0.25 - ], - [ - 1, - 0.25 - ], - [ - 1, - 1 - ], - [ - 0.25, - 1 - ], - [ - 0.25, - 0.4 - ] - ] - ], - [ - [ - [ - 2, - 2 - ], - [ - 2.75, - 2 - ], - [ - 2.75, - 2.75 - ], - [ - 2, - 2.75 - ], - [ - 2, - 2 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/intersection/poly_to_clipping.geojson b/tests/fixtures/feature_types/out/intersection/poly_to_clipping.geojson deleted file mode 100644 index 23f6ea4..0000000 --- a/tests/fixtures/feature_types/out/intersection/poly_to_clipping.geojson +++ /dev/null @@ -1,37 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#978713", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#ffffff", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0.25, - 0.25 - ], - [ - 1, - 0.25 - ], - [ - 1, - 1 - ], - [ - 0.25, - 1 - ], - [ - 0.25, - 0.25 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/intersection/poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/intersection/poly_with_hole_to_clipping.geojson deleted file mode 100644 index f76e7f7..0000000 --- a/tests/fixtures/feature_types/out/intersection/poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,45 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#978713", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#ffffff", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0.25, - 0.4 - ], - [ - 0.4, - 0.4 - ], - [ - 0.4, - 0.25 - ], - [ - 1, - 0.25 - ], - [ - 1, - 1 - ], - [ - 0.25, - 1 - ], - [ - 0.25, - 0.4 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/union/multi_poly_to_clipping.geojson b/tests/fixtures/feature_types/out/union/multi_poly_to_clipping.geojson deleted file mode 100644 index da2c348..0000000 --- a/tests/fixtures/feature_types/out/union/multi_poly_to_clipping.geojson +++ /dev/null @@ -1,69 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#25856a", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#521199", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/union/multi_poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/union/multi_poly_with_hole_to_clipping.geojson deleted file mode 100644 index 6323e80..0000000 --- a/tests/fixtures/feature_types/out/union/multi_poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,99 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#3a8b1f", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#36744f", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.4, - 0.2 - ], - [ - 0.4, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 0.4 - ], - [ - 0.2, - 0.4 - ], - [ - 0.2, - 0.2 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/union/poly_to_clipping.geojson b/tests/fixtures/feature_types/out/union/poly_to_clipping.geojson deleted file mode 100644 index 2822ad1..0000000 --- a/tests/fixtures/feature_types/out/union/poly_to_clipping.geojson +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#5b1199", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#97109a", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/union/poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/union/poly_with_hole_to_clipping.geojson deleted file mode 100644 index 071242e..0000000 --- a/tests/fixtures/feature_types/out/union/poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,83 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#5b1199", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#97109a", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.4, - 0.2 - ], - [ - 0.4, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 0.4 - ], - [ - 0.2, - 0.4 - ], - [ - 0.2, - 0.2 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/xor/multi_poly_to_clipping.geojson b/tests/fixtures/feature_types/out/xor/multi_poly_to_clipping.geojson deleted file mode 100644 index d1abcd3..0000000 --- a/tests/fixtures/feature_types/out/xor/multi_poly_to_clipping.geojson +++ /dev/null @@ -1,119 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#25856a", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#521199", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ], - [ - [ - [ - 0.25, - 1 - ], - [ - 1, - 1 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2 - ], - [ - 2, - 2 - ], - [ - 2, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ] - ] - ], - [ - [ - [ - 2, - 2.75 - ], - [ - 2.75, - 2.75 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/xor/multi_poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/xor/multi_poly_with_hole_to_clipping.geojson deleted file mode 100644 index 1104888..0000000 --- a/tests/fixtures/feature_types/out/xor/multi_poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,157 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#3a8b1f", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#36744f", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.4, - 0.25 - ], - [ - 0.4, - 0.4 - ], - [ - 0.25, - 0.4 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.4, - 0.2 - ], - [ - 0.4, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 0.4 - ], - [ - 0.2, - 0.4 - ], - [ - 0.2, - 0.2 - ] - ] - ], - [ - [ - [ - 0.25, - 1 - ], - [ - 1, - 1 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2 - ], - [ - 2, - 2 - ], - [ - 2, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ] - ] - ], - [ - [ - [ - 2, - 2.75 - ], - [ - 2.75, - 2.75 - ], - [ - 2.75, - 2 - ], - [ - 3, - 2 - ], - [ - 3, - 3 - ], - [ - 2, - 3 - ], - [ - 2, - 2.75 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/xor/poly_to_clipping.geojson b/tests/fixtures/feature_types/out/xor/poly_to_clipping.geojson deleted file mode 100644 index b27a90f..0000000 --- a/tests/fixtures/feature_types/out/xor/poly_to_clipping.geojson +++ /dev/null @@ -1,79 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#978713", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#ffffff", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ] - ], - [ - [ - [ - 0.25, - 1 - ], - [ - 1, - 1 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/out/xor/poly_with_hole_to_clipping.geojson b/tests/fixtures/feature_types/out/xor/poly_with_hole_to_clipping.geojson deleted file mode 100644 index 226a31a..0000000 --- a/tests/fixtures/feature_types/out/xor/poly_with_hole_to_clipping.geojson +++ /dev/null @@ -1,117 +0,0 @@ -{ - "type": "Feature", - "properties": { - "stroke": "#978713", - "stroke-width": 2, - "stroke-opacity": 1, - "fill": "#ffffff", - "fill-opacity": 0.5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 0.25 - ], - [ - 0.4, - 0.25 - ], - [ - 0.4, - 0.4 - ], - [ - 0.25, - 0.4 - ], - [ - 0.25, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.4, - 0.2 - ], - [ - 0.4, - 0.25 - ], - [ - 0.25, - 0.25 - ], - [ - 0.25, - 0.4 - ], - [ - 0.2, - 0.4 - ], - [ - 0.2, - 0.2 - ] - ] - ], - [ - [ - [ - 0.25, - 1 - ], - [ - 1, - 1 - ], - [ - 1, - 0.25 - ], - [ - 2.75, - 0.25 - ], - [ - 2.75, - 2.75 - ], - [ - 0.25, - 2.75 - ], - [ - 0.25, - 1 - ] - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/poly.geojson b/tests/fixtures/feature_types/poly.geojson deleted file mode 100644 index 25c4503..0000000 --- a/tests/fixtures/feature_types/poly.geojson +++ /dev/null @@ -1,31 +0,0 @@ -{ - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 0, - 1 - ], - [ - 1, - 1 - ], - [ - 1, - 0 - ], - [ - 0, - 0 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/feature_types/poly_with_hole.geojson b/tests/fixtures/feature_types/poly_with_hole.geojson deleted file mode 100644 index 5682393..0000000 --- a/tests/fixtures/feature_types/poly_with_hole.geojson +++ /dev/null @@ -1,53 +0,0 @@ -{ - "type": "Feature", - "properties": {}, - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 0, - 0 - ], - [ - 1, - 0 - ], - [ - 1, - 1 - ], - [ - 0, - 1 - ], - [ - 0, - 0 - ] - ], - [ - [ - 0.2, - 0.2 - ], - [ - 0.2, - 0.4 - ], - [ - 0.4, - 0.4 - ], - [ - 0.4, - 0.2 - ], - [ - 0.2, - 0.2 - ] - ] - ] - } -} \ No newline at end of file diff --git a/tests/fixtures/generic_test_cases/basic1_poly.geojson b/tests/fixtures/generic_test_cases/basic1_poly.geojson new file mode 100644 index 0000000..740e8b4 --- /dev/null +++ b/tests/fixtures/generic_test_cases/basic1_poly.geojson @@ -0,0 +1,136 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [0, 0], + [0, 1], + [1, 1], + [1, 0], + [0, 0] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.25, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 0.25] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.25, 0.25], + [1, 0.25], + [1, 1], + [0.25, 1], + [0.25, 0.25] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 1], + [0, 1], + [0, 0] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.25, 0.25], + [0.25, 1], + [0, 1], + [0, 0] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.25, 0.25], + [0.25, 1], + [0, 1], + [0, 0] + ] + ], + [ + [ + [0.25, 1], + [1, 1], + [1, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 1] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "xor" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/basic2_poly_with_hole.geojson b/tests/fixtures/generic_test_cases/basic2_poly_with_hole.geojson new file mode 100644 index 0000000..0856ed5 --- /dev/null +++ b/tests/fixtures/generic_test_cases/basic2_poly_with_hole.geojson @@ -0,0 +1,169 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.2, 0.2] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.25, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 0.25] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.25, 0.4], + [0.4, 0.4], + [0.4, 0.25], + [1, 0.25], + [1, 1], + [0.25, 1], + [0.25, 0.4] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.4, 0.2], + [0.4, 0.25], + [0.25, 0.25], + [0.25, 0.4], + [0.2, 0.4], + [0.2, 0.2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.4, 0.25], + [0.4, 0.2], + [0.2, 0.2], + [0.2, 0.4], + [0.25, 0.4], + [0.25, 1], + [0, 1], + [0, 0] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.4, 0.25], + [0.4, 0.4], + [0.25, 0.4], + [0.25, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.4, 0.2], + [0.4, 0.25], + [0.25, 0.25], + [0.25, 0.4], + [0.2, 0.4], + [0.2, 0.2] + ] + ], + [ + [ + [0.25, 1], + [1, 1], + [1, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 1] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "xor" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/basic3_multi_poly.geojson b/tests/fixtures/generic_test_cases/basic3_multi_poly.geojson new file mode 100644 index 0000000..1f57025 --- /dev/null +++ b/tests/fixtures/generic_test_cases/basic3_multi_poly.geojson @@ -0,0 +1,184 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ] + ], + [ + [ + [2, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.25, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 0.25] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.25, 0.25], + [1, 0.25], + [1, 1], + [0.25, 1], + [0.25, 0.25] + ] + ], + [ + [ + [2, 2], + [2.75, 2], + [2.75, 2.75], + [2, 2.75], + [2, 2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [2.75, 0.25], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75], + [0.25, 2.75], + [0.25, 1], + [0, 1], + [0, 0] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.25, 0.25], + [0.25, 1], + [0, 1], + [0, 0] + ] + ], + [ + [ + [2, 2.75], + [2.75, 2.75], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.25, 0.25], + [0.25, 1], + [0, 1], + [0, 0] + ] + ], + [ + [ + [0.25, 1], + [1, 1], + [1, 0.25], + [2.75, 0.25], + [2.75, 2], + [2, 2], + [2, 2.75], + [0.25, 2.75], + [0.25, 1] + ] + ], + [ + [ + [2, 2.75], + [2.75, 2.75], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "xor" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/fixtures/generic_test_cases/basic4_multi_poly_with_hole.geojson b/tests/fixtures/generic_test_cases/basic4_multi_poly_with_hole.geojson new file mode 100644 index 0000000..9f4fb9b --- /dev/null +++ b/tests/fixtures/generic_test_cases/basic4_multi_poly_with_hole.geojson @@ -0,0 +1,217 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.2, 0.2] + ] + ], + [ + [ + [2, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.25, 0.25], + [2.75, 0.25], + [2.75, 2.75], + [0.25, 2.75], + [0.25, 0.25] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.25, 0.4], + [0.4, 0.4], + [0.4, 0.25], + [1, 0.25], + [1, 1], + [0.25, 1], + [0.25, 0.4] + ] + ], + [ + [ + [2, 2], + [2.75, 2], + [2.75, 2.75], + [2, 2.75], + [2, 2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [2.75, 0.25], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75], + [0.25, 2.75], + [0.25, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.4, 0.2], + [0.4, 0.25], + [0.25, 0.25], + [0.25, 0.4], + [0.2, 0.4], + [0.2, 0.2] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.4, 0.25], + [0.4, 0.2], + [0.2, 0.2], + [0.2, 0.4], + [0.25, 0.4], + [0.25, 1], + [0, 1], + [0, 0] + ] + ], + [ + [ + [2, 2.75], + [2.75, 2.75], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0, 0], + [1, 0], + [1, 0.25], + [0.4, 0.25], + [0.4, 0.4], + [0.25, 0.4], + [0.25, 1], + [0, 1], + [0, 0] + ], + [ + [0.2, 0.2], + [0.4, 0.2], + [0.4, 0.25], + [0.25, 0.25], + [0.25, 0.4], + [0.2, 0.4], + [0.2, 0.2] + ] + ], + [ + [ + [0.25, 1], + [1, 1], + [1, 0.25], + [2.75, 0.25], + [2.75, 2], + [2, 2], + [2, 2.75], + [0.25, 2.75], + [0.25, 1] + ] + ], + [ + [ + [2, 2.75], + [2.75, 2.75], + [2.75, 2], + [3, 2], + [3, 3], + [2, 3], + [2, 2.75] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "xor" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} diff --git a/tests/src/feature_type_test.rs b/tests/src/feature_type_test.rs deleted file mode 100644 index be22e18..0000000 --- a/tests/src/feature_type_test.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::helper::{fixture_multi_polygon, fixture_polygon}; -use geo::Polygon; -use geo_booleanop::boolean::BooleanOp; - -fn assert_clipping(subject: &F, clipping: &Polygon, expected_name: &str) -where - F: BooleanOp>, -{ - { - let result = subject.intersection(clipping); - let expected = fixture_multi_polygon(format!("feature_types/out/intersection/{}", expected_name).as_str()); - - assert_eq!(result, expected); - } - { - let result = subject.difference(clipping); - let expected = fixture_multi_polygon(format!("feature_types/out/difference/{}", expected_name).as_str()); - - assert_eq!(result, expected); - } - { - let result = subject.union(clipping); - let expected = fixture_multi_polygon(format!("feature_types/out/union/{}", expected_name).as_str()); - - assert_eq!(result, expected); - } - { - let result = subject.xor(clipping); - let expected = fixture_multi_polygon(format!("feature_types/out/xor/{}", expected_name).as_str()); - - assert_eq!(result, expected); - } -} - -#[test] -fn test_poly() { - let clipping = fixture_polygon("feature_types/clipping_poly.geojson"); - let poly = fixture_polygon("feature_types/poly.geojson"); - - assert_clipping(&poly, &clipping, "poly_to_clipping.geojson") -} - -#[test] -fn test_poly_with_hole() { - let clipping = fixture_polygon("feature_types/clipping_poly.geojson"); - let poly = fixture_polygon("feature_types/poly_with_hole.geojson"); - - assert_clipping(&poly, &clipping, "poly_with_hole_to_clipping.geojson") -} - -#[test] -fn test_multi_poly() { - let clipping = fixture_polygon("feature_types/clipping_poly.geojson"); - let poly = fixture_multi_polygon("feature_types/multi_poly.geojson"); - - assert_clipping(&poly, &clipping, "multi_poly_to_clipping.geojson") -} - -#[test] -fn test_multi_poly_with_hole() { - let clipping = fixture_polygon("feature_types/clipping_poly.geojson"); - let poly = fixture_multi_polygon("feature_types/multi_poly_with_hole.geojson"); - - assert_clipping(&poly, &clipping, "multi_poly_with_hole_to_clipping.geojson") -} diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 7f9db5d..17ce95c 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -1,6 +1,4 @@ #[cfg(test)] -mod feature_type_test; -#[cfg(test)] mod fill_queue_test; #[cfg(test)] mod generic_test_cases; From 5f7c4987e06a09cc21f90c107063fa6f8315df5c Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 27 Jan 2020 23:19:34 +0100 Subject: [PATCH 07/22] improved variable names and implementation of determine_result_transition --- lib/src/boolean/compute_fields.rs | 34 ++++++++++++++++++++----------- lib/src/boolean/connect_edges.rs | 17 ++++++++++------ lib/src/boolean/mod.rs | 2 +- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/lib/src/boolean/compute_fields.rs b/lib/src/boolean/compute_fields.rs index 49fb108..addfe62 100644 --- a/lib/src/boolean/compute_fields.rs +++ b/lib/src/boolean/compute_fields.rs @@ -34,18 +34,7 @@ where let result_transition = if !in_result { ResultTransition::None } else { - let mut this_in = !event.is_in_out(); - let mut that_in = !event.is_other_in_out(); - if !event.is_subject { - std::mem::swap(&mut this_in, &mut that_in); - } - let is_in = match operation { - Operation::Intersection => this_in && that_in, - Operation::Union => this_in || that_in, - Operation::Difference => this_in && !that_in, - Operation::Xor => this_in ^ that_in, - }; - if is_in { ResultTransition::OutIn } else { ResultTransition::InOut } + determine_result_transition(&event, operation) }; event.set_result_transition(result_transition); } @@ -68,3 +57,24 @@ where EdgeType::NonContributing => false, } } + +fn determine_result_transition(event: &SweepEvent, operation: Operation) -> ResultTransition +where + F: Float, +{ + let this_in = !event.is_in_out(); + let that_in = !event.is_other_in_out(); + let is_in = match operation { + Operation::Intersection => this_in && that_in, + Operation::Union => this_in || that_in, + Operation::Xor => this_in ^ that_in, + Operation::Difference => + // Difference is assymmetric, so subject vs clipping matters. + if event.is_subject { + this_in && !that_in + } else { + that_in && !this_in + } + }; + if is_in { ResultTransition::OutIn } else { ResultTransition::InOut } +} \ No newline at end of file diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 101efea..3eed984 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -103,7 +103,12 @@ where { pub points: Vec>, pub hole_ids: Vec, - pub is_external: bool, + /// The semantics of `is_exterior` are in the sense of an exterior ring of a polygon + /// in GeoJSON. This is not to be confused with "external contour" as used in the + /// Martinez paper (which refers to contours that are not included in any of the + /// other polygon contours). `is_exterior` is true for all outer contours, not just + /// the outermost. + pub is_exterior: bool, } @@ -157,7 +162,7 @@ where let mut contour = Contour{ points: Vec::new(), hole_ids: Vec::new(), - is_external: true, + is_exterior: true, }; let contour_id = result.len() as i32; @@ -173,22 +178,22 @@ where if prev_in_result.get_result_transition() == ResultTransition::OutIn { // We are inside, let's check if the thing below us is an exterior contour or just // another hole. - if result[lower_contour_id as usize].is_external { + if result[lower_contour_id as usize].is_exterior { result[lower_contour_id as usize].hole_ids.push(contour_id); hole_of.insert(contour_id, lower_contour_id); depth.insert(contour_id, depth[&lower_contour_id] + 1); - contour.is_external = false; + contour.is_exterior = false; println!("Marking contour as hole of {} with depth {}", lower_contour_id, depth[&contour_id]); } else { let parent_contour_id = hole_of[&lower_contour_id]; result[parent_contour_id as usize].hole_ids.push(contour_id); hole_of.insert(contour_id, parent_contour_id); depth.insert(contour_id, depth[&lower_contour_id]); - contour.is_external = false; + contour.is_exterior = false; println!("Transitively marking contour as hole of {} via {} with depth {}", parent_contour_id, lower_contour_id, depth[&contour_id]); } } else { - contour.is_external = true; + contour.is_exterior = true; println!("Keeping contour as external"); } } diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index 42dbdc9..1a4cd7a 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -115,7 +115,7 @@ where let mut polygons: Vec> = Vec::new(); for contour in &contours { - if contour.is_external { + if contour.is_exterior { let exterior = LineString(contour.points.clone()); let mut interios: Vec> = Vec::new(); for hole_id in &contour.hole_ids { From c90ca39042acf789bc03581bcd1749b2a038b9a6 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Tue, 28 Jan 2020 22:48:21 +0100 Subject: [PATCH 08/22] improved next pos loop --- lib/src/boolean/connect_edges.rs | 80 +++++++++++++++++--------------- lib/src/boolean/sweep_event.rs | 12 ++--- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 3eed984..da1a8c9 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -1,6 +1,5 @@ use super::sweep_event::{SweepEvent, ResultTransition}; -use super::Operation; -use geo_types::{LineString, Polygon, Coordinate}; +use geo_types::{Coordinate}; use num_traits::Float; use std::collections::HashSet; use std::collections::HashMap; @@ -31,16 +30,16 @@ where } } + // Populate `other_pos` by initializing with index and swapping with other event. for (pos, event) in result_events.iter().enumerate() { - event.set_pos(pos as i32) + event.set_other_pos(pos as i32) } - for event in &result_events { - if !event.is_left() { + if event.is_left() { if let Some(other) = event.get_other_event() { - let tmp = event.get_pos(); - event.set_pos(other.get_pos()); - other.set_pos(tmp); + let (a, b) = (event.get_other_pos(), other.get_other_pos()); + event.set_other_pos(b); + other.set_other_pos(a); } } } @@ -53,7 +52,7 @@ where for (i, r) in result_events.iter().enumerate() { println!("pos {:3} linked to {:3} {} {:?} => {:?}", i, - r.get_pos(), + r.get_other_pos(), if r.is_left() { "L" } else { "R" }, r.point, r.get_other_event().map(|o| o.point).unwrap(), @@ -64,7 +63,7 @@ where } -fn next_pos(pos: i32, result_events: &[Rc>], processed: &HashSet, orig_index: i32) -> i32 +fn next_pos(pos: i32, result_events: &[Rc>], processed: &HashSet, orig_pos: i32) -> i32 where F: Float, { @@ -90,7 +89,7 @@ where new_pos = pos - 1; - while processed.contains(&new_pos) { + while processed.contains(&new_pos) && new_pos > orig_pos { new_pos -= 1; } new_pos @@ -141,6 +140,15 @@ where } +fn mark_as_processed(processed: &mut HashSet, result_events: &[Rc>], pos: i32, contour_id: i32) +where + F: Float + std::fmt::Debug, +{ + processed.insert(pos); + result_events[pos as usize].set_output_contour_id(contour_id); +} + + pub fn connect_edges(sorted_events: &[Rc>]) -> Vec> where F: Float + std::fmt::Debug, @@ -148,7 +156,6 @@ where let result_events = order_events(sorted_events); debug_print_results(&result_events); - //let mut result: Vec> = Vec::new(); let mut result: Vec> = Vec::new(); let mut processed: HashSet = HashSet::new(); @@ -198,39 +205,38 @@ where } } + let orig_pos = i; // Alias just for clarity let mut pos = i; - let initial = result_events[i as usize].point; + let initial = result_events[pos as usize].point; contour.points.push(initial); - while pos >= 0 && result_events[pos as usize].get_other_event().unwrap().point != initial { - println!("pos = {} {} {:?} => {:?}", - pos, - if result_events[pos as usize].is_left() { "L" } else { "R" }, - result_events[pos as usize].point, - result_events[pos as usize].get_other_event().unwrap().point, - ); - processed.insert(pos); - result_events[pos as usize].set_output_contour_id(contour_id); - - pos = result_events[pos as usize].get_pos(); - println!("Jumped to: {}", pos); + loop { + // Loop carifications: + // - An iteration has two kinds of `pos` advancements: + // (A) following a segment via `other_pos`, and + // (B) searching for the next outgoing edge on same point. + // - Therefore, the loop contains two "mark pos as processed" steps, using the + // convention that at beginning of the loop, `pos` isn't marked yet. + // - The contour is extended after following a segment. + // - Hitting pos == orig_pos after search (B) indicates no continuation and + // terminates the loop. + mark_as_processed(&mut processed, &result_events, pos, contour_id); + + pos = result_events[pos as usize].get_other_pos(); // pos advancment (A) + + mark_as_processed(&mut processed, &result_events, pos, contour_id); + contour.points.push(result_events[pos as usize].point); - processed.insert(pos); - result_events[pos as usize].set_output_contour_id(contour_id); + pos = next_pos(pos, &result_events, &processed, orig_pos); // pos advancment (B) - contour.points.push(result_events[pos as usize].point); - pos = next_pos(pos, &result_events, &processed, i); - println!("Next pos: {}", pos); + if pos == orig_pos { + break; + } } - if pos != -1 { - processed.insert(pos); - result_events[pos as usize].set_output_contour_id(contour_id); - pos = result_events[pos as usize].get_pos(); - processed.insert(pos); - result_events[pos as usize].set_output_contour_id(contour_id); - } + // This assert should be possible once the first stage of the algorithm is robust. + // debug_assert_eq!(contour.points.first(), contour.points.last()); result.push(contour); } diff --git a/lib/src/boolean/sweep_event.rs b/lib/src/boolean/sweep_event.rs index 35f0ae9..243a278 100644 --- a/lib/src/boolean/sweep_event.rs +++ b/lib/src/boolean/sweep_event.rs @@ -34,7 +34,7 @@ where in_out: bool, other_in_out: bool, result_transition: ResultTransition, - pos: i32, + other_pos: i32, output_contour_id: i32, } @@ -71,7 +71,7 @@ where in_out: false, other_in_out: false, result_transition: ResultTransition::None, - pos: 0, + other_pos: 0, output_contour_id: -1, }), contour_id, @@ -140,12 +140,12 @@ where mutable.other_in_out = other_in_out; } - pub fn get_pos(&self) -> i32 { - self.mutable.borrow().pos + pub fn get_other_pos(&self) -> i32 { + self.mutable.borrow().other_pos } - pub fn set_pos(&self, pos: i32) { - self.mutable.borrow_mut().pos = pos + pub fn set_other_pos(&self, other_pos: i32) { + self.mutable.borrow_mut().other_pos = other_pos } pub fn get_output_contour_id(&self) -> i32 { From b60d42cc6c488a0f609be15828a45df2ca086176 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Tue, 28 Jan 2020 23:39:05 +0100 Subject: [PATCH 09/22] improve construction of contours --- lib/src/boolean/connect_edges.rs | 88 ++++++++++++++++++++------------ lib/src/boolean/mod.rs | 2 +- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index da1a8c9..ab94cc1 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -100,14 +100,39 @@ pub struct Contour where F: Float { + /// Raw coordinates of contour pub points: Vec>, + /// Contour IDs of holes if any. pub hole_ids: Vec, + /// Contour ID of parent if this contour is a hole. + pub hole_of: Option, + /// Depth of the contour. Since the geo data structures don't store depth information, + /// this field is not strictly necessary to compute. But it is very cheap to compute, + /// so we can add it and see if it has relevance in the future. + pub depth: i32, +} + +impl Contour +where + F: Float +{ + pub fn new(hole_of: Option, depth: i32) -> Contour { + Contour { + points: Vec::new(), + hole_ids: Vec::new(), + hole_of: hole_of, + depth: depth, + } + } + /// The semantics of `is_exterior` are in the sense of an exterior ring of a polygon /// in GeoJSON. This is not to be confused with "external contour" as used in the /// Martinez paper (which refers to contours that are not included in any of the /// other polygon contours). `is_exterior` is true for all outer contours, not just /// the outermost. - pub is_exterior: bool, + pub fn is_exterior(&self) -> bool { + self.hole_of.is_none() + } } @@ -159,51 +184,48 @@ where let mut result: Vec> = Vec::new(); let mut processed: HashSet = HashSet::new(); - let mut depth: HashMap = HashMap::new(); - let mut hole_of: HashMap = HashMap::new(); - for i in 0..(result_events.len() as i32) { if processed.contains(&i) { continue; } - let mut contour = Contour{ - points: Vec::new(), - hole_ids: Vec::new(), - is_exterior: true, - }; let contour_id = result.len() as i32; - println!("\n *** Adding contour id {}", contour_id); - depth.insert(contour_id, 0); - hole_of.insert(contour_id, -1); - if let Some(prev_in_result) = result_events[i as usize].get_prev_in_result() { + // This logic implements the 4 cases of parent contours from Fig. 4 in the Martinez paper. + let mut contour = if let Some(prev_in_result) = result_events[i as usize].get_prev_in_result() { + // Note that it is valid to query the "previous in result" for its output contour id, + // because we must have already processed it (i.e., assigned an output contour id) + // in an earlier iteration, otherwise it wouldn't be possible that it is "previous in + // result". let lower_contour_id = prev_in_result.get_output_contour_id(); - println!("Inferring information from lower_contour_id = {} with result transition = {:?}", lower_contour_id, prev_in_result.get_result_transition()); - println!("{:?}", prev_in_result.point); - println!("{:?}", prev_in_result.get_other_event().unwrap().point); if prev_in_result.get_result_transition() == ResultTransition::OutIn { - // We are inside, let's check if the thing below us is an exterior contour or just - // another hole. - if result[lower_contour_id as usize].is_exterior { - result[lower_contour_id as usize].hole_ids.push(contour_id); - hole_of.insert(contour_id, lower_contour_id); - depth.insert(contour_id, depth[&lower_contour_id] + 1); - contour.is_exterior = false; - println!("Marking contour as hole of {} with depth {}", lower_contour_id, depth[&contour_id]); - } else { - let parent_contour_id = hole_of[&lower_contour_id]; + // We are inside. Now we have to check if the thing below us is an another hole + // or an exterior contour. + let lower_contour = &result[lower_contour_id as usize]; + if let Some(parent_contour_id) = lower_contour.hole_of { + // The lower contour is a hole => Connect the new contour as a hole to its parent, + // and use same depth. result[parent_contour_id as usize].hole_ids.push(contour_id); - hole_of.insert(contour_id, parent_contour_id); - depth.insert(contour_id, depth[&lower_contour_id]); - contour.is_exterior = false; - println!("Transitively marking contour as hole of {} via {} with depth {}", parent_contour_id, lower_contour_id, depth[&contour_id]); + let hole_of = Some(parent_contour_id); + let depth = result[lower_contour_id as usize].depth; + Contour::new(hole_of, depth) + } else { + // The lower contour is an exterior contour => Connect the new contour as a hole, + // and increment depth. + result[lower_contour_id as usize].hole_ids.push(contour_id); + let hole_of = Some(lower_contour_id); + let depth = result[lower_contour_id as usize].depth + 1; + Contour::new(hole_of, depth) } } else { - contour.is_exterior = true; - println!("Keeping contour as external"); + // We are outside => this contour is an exterior contour of same depth. + let depth = result[lower_contour_id as usize].depth; + Contour::new(None, depth) } - } + } else { + // There is no lower/previous contour => this contour is an exterior contour of depth 0. + Contour::new(None, 0) + }; let orig_pos = i; // Alias just for clarity let mut pos = i; diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index 1a4cd7a..599a695 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -115,7 +115,7 @@ where let mut polygons: Vec> = Vec::new(); for contour in &contours { - if contour.is_exterior { + if contour.is_exterior() { let exterior = LineString(contour.points.clone()); let mut interios: Vec> = Vec::new(); for hole_id in &contour.hole_ids { From 60915a545f9974c224c0826f780163251f860824 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Tue, 28 Jan 2020 23:48:59 +0100 Subject: [PATCH 10/22] fix typos --- lib/src/boolean/connect_edges.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index ab94cc1..82e5adf 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -199,8 +199,8 @@ where // result". let lower_contour_id = prev_in_result.get_output_contour_id(); if prev_in_result.get_result_transition() == ResultTransition::OutIn { - // We are inside. Now we have to check if the thing below us is an another hole - // or an exterior contour. + // We are inside. Now we have to check if the thing below us is another hole or + // an exterior contour. let lower_contour = &result[lower_contour_id as usize]; if let Some(parent_contour_id) = lower_contour.hole_of { // The lower contour is a hole => Connect the new contour as a hole to its parent, @@ -234,7 +234,7 @@ where contour.points.push(initial); loop { - // Loop carifications: + // Loop clarifications: // - An iteration has two kinds of `pos` advancements: // (A) following a segment via `other_pos`, and // (B) searching for the next outgoing edge on same point. From eb27392e12e7d34df71781b6254546430f59406f Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 00:10:21 +0100 Subject: [PATCH 11/22] extended Float trait to support debugging --- lib/src/boolean/compare_segments.rs | 2 +- lib/src/boolean/compute_fields.rs | 2 +- lib/src/boolean/connect_edges.rs | 2 +- lib/src/boolean/divide_segment.rs | 2 +- lib/src/boolean/fill_queue.rs | 2 +- lib/src/boolean/helper.rs | 5 +++++ lib/src/boolean/mod.rs | 4 ++-- lib/src/boolean/possible_intersection.rs | 2 +- lib/src/boolean/segment_intersection.rs | 2 +- lib/src/boolean/signed_area.rs | 2 +- lib/src/boolean/subdivide_segments.rs | 2 +- lib/src/boolean/sweep_event.rs | 2 +- 12 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/src/boolean/compare_segments.rs b/lib/src/boolean/compare_segments.rs index b0bdb95..68c93da 100644 --- a/lib/src/boolean/compare_segments.rs +++ b/lib/src/boolean/compare_segments.rs @@ -1,6 +1,6 @@ use super::signed_area::signed_area; use super::sweep_event::SweepEvent; -use num_traits::Float; +use super::helper::Float; use std::cmp::Ordering; use std::rc::Rc; diff --git a/lib/src/boolean/compute_fields.rs b/lib/src/boolean/compute_fields.rs index addfe62..df2f6df 100644 --- a/lib/src/boolean/compute_fields.rs +++ b/lib/src/boolean/compute_fields.rs @@ -1,6 +1,6 @@ use super::sweep_event::{EdgeType, SweepEvent, ResultTransition}; use super::Operation; -use num_traits::Float; +use super::helper::Float; use std::rc::Rc; pub fn compute_fields(event: &Rc>, maybe_prev: Option<&Rc>>, operation: Operation) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 82e5adf..e8b5930 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -1,6 +1,6 @@ use super::sweep_event::{SweepEvent, ResultTransition}; use geo_types::{Coordinate}; -use num_traits::Float; +use super::helper::Float; use std::collections::HashSet; use std::collections::HashMap; use std::rc::Rc; diff --git a/lib/src/boolean/divide_segment.rs b/lib/src/boolean/divide_segment.rs index d9c7dae..89dc3ae 100644 --- a/lib/src/boolean/divide_segment.rs +++ b/lib/src/boolean/divide_segment.rs @@ -1,6 +1,6 @@ use super::sweep_event::SweepEvent; use geo_types::Coordinate; -use num_traits::Float; +use super::helper::Float; use std::collections::BinaryHeap; use std::rc::Rc; diff --git a/lib/src/boolean/fill_queue.rs b/lib/src/boolean/fill_queue.rs index f44ff7a..fe1d2d0 100644 --- a/lib/src/boolean/fill_queue.rs +++ b/lib/src/boolean/fill_queue.rs @@ -1,5 +1,5 @@ use geo_types::{LineString, Polygon, Rect}; -use num_traits::Float; +use super::helper::Float; use std::collections::BinaryHeap; use std::rc::{Rc, Weak}; diff --git a/lib/src/boolean/helper.rs b/lib/src/boolean/helper.rs index 6b8fc77..9925f61 100644 --- a/lib/src/boolean/helper.rs +++ b/lib/src/boolean/helper.rs @@ -1,4 +1,9 @@ use std::cmp::Ordering; +use std::fmt::{Debug, Display}; +use num_traits::Float as NumTraitsFloat; + +pub trait Float: NumTraitsFloat + Debug + Display {} +impl Float for T {} #[inline] pub fn less_if(condition: bool) -> Ordering { diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index 599a695..a17e070 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -1,5 +1,3 @@ -use num_traits::Float; - use geo_types::{Coordinate, MultiPolygon, Polygon, LineString, Rect}; pub mod compare_segments; @@ -14,6 +12,8 @@ mod signed_area; pub mod subdivide_segments; pub mod sweep_event; +pub use helper::Float; + use self::connect_edges::connect_edges; use self::fill_queue::fill_queue; use self::subdivide_segments::subdivide; diff --git a/lib/src/boolean/possible_intersection.rs b/lib/src/boolean/possible_intersection.rs index 6ef7c43..49d167c 100644 --- a/lib/src/boolean/possible_intersection.rs +++ b/lib/src/boolean/possible_intersection.rs @@ -1,7 +1,7 @@ use super::divide_segment::divide_segment; use super::segment_intersection::{intersection, LineIntersection}; use super::sweep_event::{EdgeType, SweepEvent}; -use num_traits::Float; +use super::helper::Float; use std::collections::BinaryHeap; use std::rc::Rc; diff --git a/lib/src/boolean/segment_intersection.rs b/lib/src/boolean/segment_intersection.rs index 03f1e31..0dafe58 100644 --- a/lib/src/boolean/segment_intersection.rs +++ b/lib/src/boolean/segment_intersection.rs @@ -1,5 +1,5 @@ use geo_types::Coordinate; -use num_traits::Float; +use super::helper::Float; #[derive(Debug, Clone, Copy, PartialEq)] pub enum LineIntersection diff --git a/lib/src/boolean/signed_area.rs b/lib/src/boolean/signed_area.rs index 05e8ac6..0d2dc69 100644 --- a/lib/src/boolean/signed_area.rs +++ b/lib/src/boolean/signed_area.rs @@ -1,5 +1,5 @@ use geo_types::Coordinate; -use num_traits::Float; +use super::helper::Float; use robust::{Coord, orient2d}; #[inline] diff --git a/lib/src/boolean/subdivide_segments.rs b/lib/src/boolean/subdivide_segments.rs index c107d09..cc96d7d 100644 --- a/lib/src/boolean/subdivide_segments.rs +++ b/lib/src/boolean/subdivide_segments.rs @@ -5,7 +5,7 @@ use super::sweep_event::SweepEvent; use super::Operation; use crate::splay::SplaySet; use geo_types::Rect; -use num_traits::Float; +use super::helper::Float; use std::collections::BinaryHeap; use std::rc::Rc; diff --git a/lib/src/boolean/sweep_event.rs b/lib/src/boolean/sweep_event.rs index 243a278..2d13d69 100644 --- a/lib/src/boolean/sweep_event.rs +++ b/lib/src/boolean/sweep_event.rs @@ -1,5 +1,5 @@ use geo_types::Coordinate; -use num_traits::Float; +use super::helper::Float; use std::cell::RefCell; use std::cmp::Ordering; use std::rc::{Rc, Weak}; From e86c0759d82e53cec2d37015893009550f244bac Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 00:12:37 +0100 Subject: [PATCH 12/22] remove a few debug traits --- lib/src/boolean/connect_edges.rs | 9 ++++----- lib/src/boolean/mod.rs | 10 +++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index e8b5930..2c6339a 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -2,12 +2,11 @@ use super::sweep_event::{SweepEvent, ResultTransition}; use geo_types::{Coordinate}; use super::helper::Float; use std::collections::HashSet; -use std::collections::HashMap; use std::rc::Rc; fn order_events(sorted_events: &[Rc>]) -> Vec>> where - F: Float + std::fmt::Debug, + F: Float, { let mut result_events: Vec>> = Vec::new(); @@ -140,7 +139,7 @@ use std::fs::File; use std::io::Write; fn debug_print_results(events: &[Rc>]) where - F: Float + std::fmt::Debug, + F: Float, { let mut writer = File::create("debug.csv").unwrap(); writeln!(&mut writer, @@ -167,7 +166,7 @@ where fn mark_as_processed(processed: &mut HashSet, result_events: &[Rc>], pos: i32, contour_id: i32) where - F: Float + std::fmt::Debug, + F: Float, { processed.insert(pos); result_events[pos as usize].set_output_contour_id(contour_id); @@ -176,7 +175,7 @@ where pub fn connect_edges(sorted_events: &[Rc>]) -> Vec> where - F: Float + std::fmt::Debug, + F: Float, { let result_events = order_events(sorted_events); debug_print_results(&result_events); diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index a17e070..df3a960 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -51,7 +51,7 @@ where impl BooleanOp for Polygon where - F: Float + std::fmt::Debug, + F: Float, { fn boolean(&self, rhs: &Polygon, operation: Operation) -> MultiPolygon { boolean_operation(&[self.clone()], &[rhs.clone()], operation) @@ -60,7 +60,7 @@ where impl BooleanOp> for Polygon where - F: Float + std::fmt::Debug, + F: Float, { fn boolean(&self, rhs: &MultiPolygon, operation: Operation) -> MultiPolygon { boolean_operation(&[self.clone()], rhs.0.as_slice(), operation) @@ -69,7 +69,7 @@ where impl BooleanOp for MultiPolygon where - F: Float + std::fmt::Debug, + F: Float, { fn boolean(&self, rhs: &MultiPolygon, operation: Operation) -> MultiPolygon { boolean_operation(self.0.as_slice(), rhs.0.as_slice(), operation) @@ -78,7 +78,7 @@ where impl BooleanOp> for MultiPolygon where - F: Float + std::fmt::Debug, + F: Float, { fn boolean(&self, rhs: &Polygon, operation: Operation) -> MultiPolygon { boolean_operation(self.0.as_slice(), &[rhs.clone()], operation) @@ -87,7 +87,7 @@ where fn boolean_operation(subject: &[Polygon], clipping: &[Polygon], operation: Operation) -> MultiPolygon where - F: Float + std::fmt::Debug, + F: Float, { let mut sbbox = Rect { min: Coordinate { From f083b1f0af827d508e4d7869dfba1ee2e8572a8e Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 07:57:06 +0100 Subject: [PATCH 13/22] improved conversion of contours --- lib/src/boolean/mod.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/src/boolean/mod.rs b/lib/src/boolean/mod.rs index df3a960..41e641e 100644 --- a/lib/src/boolean/mod.rs +++ b/lib/src/boolean/mod.rs @@ -112,20 +112,19 @@ where let contours = connect_edges(&sorted_events); - let mut polygons: Vec> = Vec::new(); - - for contour in &contours { - if contour.is_exterior() { + // Convert contours into polygons + let polygons: Vec> = contours + .iter() + .filter(|contour| contour.is_exterior()) + .map(|contour| { let exterior = LineString(contour.points.clone()); let mut interios: Vec> = Vec::new(); for hole_id in &contour.hole_ids { interios.push(LineString(contours[*hole_id as usize].points.clone())); } - - let polygon = Polygon::new(exterior, interios); - polygons.push(polygon); - } - } + Polygon::new(exterior, interios) + }) + .collect(); MultiPolygon(polygons) } From 5e5868d5d2fb2e42f6f27fd4f248451dff20ebb2 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:00:45 +0100 Subject: [PATCH 14/22] added issue68 --- .../generic_test_cases/issue68.geojson | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/issue68.geojson diff --git a/tests/fixtures/generic_test_cases/issue68.geojson b/tests/fixtures/generic_test_cases/issue68.geojson new file mode 100644 index 0000000..bc17611 --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue68.geojson @@ -0,0 +1,78 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [-89.489886, 40.482217], + [-89.489714, 40.482022], + [-89.489836, 40.482146], + [-89.489886, 40.482217] + ] + ], + [ + [ + [-89.491551, 40.483208], + [-89.486778, 40.487262], + [-89.487045, 40.485142], + [-89.491551, 40.483208] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [-89.48925, 40.484891], + [-89.488996, 40.484309], + [-89.48821, 40.484919], + [-89.48925, 40.484891] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-89.491551, 40.483208], + [-89.487045, 40.485142], + [-89.486778, 40.487262], + [-89.491551, 40.483208] + ], + [ + [-89.48925, 40.484891], + [-89.488996, 40.484309], + [-89.48821, 40.484919], + [-89.48925, 40.484891] + ] + ], + [ + [ + [-89.489886, 40.482217], + [-89.489836, 40.482146], + [-89.489714, 40.482022], + [-89.489886, 40.482217] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 09f575e37eae3b131cd8b8db674a1231d93f3858 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:02:04 +0100 Subject: [PATCH 15/22] added issue69 --- .../generic_test_cases/issue69.geojson | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/issue69.geojson diff --git a/tests/fixtures/generic_test_cases/issue69.geojson b/tests/fixtures/generic_test_cases/issue69.geojson new file mode 100644 index 0000000..9d29ba9 --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue69.geojson @@ -0,0 +1,79 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [2, 0], + [10, 10], + [10, 0], + [2, 0] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [5, 1], + [12, 1], + [12, 9], + [5, 9], + [5, 1] + ], + [ + [6, 2], + [11, 8], + [6, 8], + [6, 2] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [2, 0], + [10, 0], + [10, 1], + [5, 1], + [5, 3.75], + [2, 0] + ], + [ + [6, 2], + [10, 6.800000000000001], + [10, 8], + [8.399999999999999, 8], + [6, 5], + [6, 2] + ] + ], + [ + [ + [9.2, 9], + [10, 9], + [10, 10], + [9.2, 9] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "diff" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From d70f76c0fc25fe5ae0460027c4cc67236d2a4513 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:05:01 +0100 Subject: [PATCH 16/22] added issue93 --- .../generic_test_cases/issue69.geojson | 4 +- .../generic_test_cases/issue93.geojson | 464 ++++++++++++++++++ 2 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/generic_test_cases/issue93.geojson diff --git a/tests/fixtures/generic_test_cases/issue69.geojson b/tests/fixtures/generic_test_cases/issue69.geojson index 9d29ba9..dc9f9fe 100644 --- a/tests/fixtures/generic_test_cases/issue69.geojson +++ b/tests/fixtures/generic_test_cases/issue69.geojson @@ -48,7 +48,9 @@ [5, 1], [5, 3.75], [2, 0] - ], + ] + ], + [ [ [6, 2], [10, 6.800000000000001], diff --git a/tests/fixtures/generic_test_cases/issue93.geojson b/tests/fixtures/generic_test_cases/issue93.geojson new file mode 100644 index 0000000..f9afeaa --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue93.geojson @@ -0,0 +1,464 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [0.663168, 51.562679], + [0.663108, 51.56268], + [0.663071, 51.562681], + [0.662725, 51.562688], + [0.662462, 51.562694], + [0.662426, 51.562694], + [0.66229, 51.562697], + [0.662281, 51.562698], + [0.662015, 51.562703], + [0.661886, 51.562706], + [0.661877, 51.562706], + [0.661673, 51.562718], + [0.661662, 51.562718], + [0.661599, 51.562722], + [0.661588, 51.562722], + [0.661582, 51.562723], + [0.661297, 51.562738], + [0.661294, 51.562738], + [0.661227, 51.562742], + [0.661193, 51.562744], + [0.661183, 51.562745], + [0.661157, 51.562746], + [0.661154, 51.562746], + [0.661103, 51.562749], + [0.661084, 51.56275], + [0.66108, 51.56275], + [0.661066, 51.562751], + [0.660919, 51.562761], + [0.660905, 51.562762], + [0.660832, 51.562767], + [0.660819, 51.562767], + [0.660808, 51.562768], + [0.66072, 51.562774], + [0.660688, 51.562776], + [0.660515, 51.562787], + [0.660474, 51.56279], + [0.660472, 51.56279], + [0.660433, 51.562793], + [0.660328, 51.5628], + [0.660309, 51.562801], + [0.660229, 51.562806], + [0.660216, 51.562807], + [0.660202, 51.562808], + [0.660166, 51.56281], + [0.660057, 51.562817], + [0.660043, 51.562818], + [0.660004, 51.562821], + [0.659964, 51.562823], + [0.65991, 51.562827], + [0.659884, 51.562829], + [0.659828, 51.562832], + [0.65982, 51.562833], + [0.659687, 51.562842], + [0.659631, 51.562845], + [0.65962, 51.562846], + [0.6596, 51.562847], + [0.659439, 51.562858], + [0.659432, 51.562858], + [0.659404, 51.56286], + [0.659401, 51.56286], + [0.659332, 51.562866], + [0.659318, 51.562867], + [0.659099, 51.562884], + [0.659063, 51.562887], + [0.658928, 51.562897], + [0.658914, 51.562836], + [0.658875, 51.56284], + [0.658781, 51.562423], + [0.658785, 51.562424], + [0.658818, 51.562434], + [0.658822, 51.562437], + [0.65883, 51.562437], + [0.658959, 51.562447], + [0.658977, 51.562448], + [0.659115, 51.562474], + [0.659122, 51.562474], + [0.659253, 51.562473], + [0.65926, 51.562473], + [0.65933, 51.562445], + [0.65933, 51.562444], + [0.659366, 51.562206], + [0.659361, 51.562178], + [0.659361, 51.562177], + [0.659362, 51.562139], + [0.659363, 51.562096], + [0.659359, 51.562076], + [0.659362, 51.56205], + [0.659362, 51.562046], + [0.659719, 51.562096], + [0.659882, 51.562119], + [0.659901, 51.562111], + [0.659986, 51.562078], + [0.659987, 51.562078], + [0.660195, 51.561868], + [0.660205, 51.561858], + [0.660247, 51.561802], + [0.660235, 51.561795], + [0.660224, 51.561788], + [0.660205, 51.561777], + [0.660164, 51.561759], + [0.660154, 51.561754], + [0.6595, 51.561534], + [0.659493, 51.561524], + [0.659472, 51.561494], + [0.659458, 51.561494], + [0.659316, 51.561486], + [0.659312, 51.561485], + [0.659042, 51.561586], + [0.659048, 51.561595], + [0.659063, 51.561612], + [0.658941, 51.561623], + [0.65892, 51.561625], + [0.658712, 51.561643], + [0.658566, 51.561656], + [0.658503, 51.561661], + [0.658482, 51.561663], + [0.658478, 51.561663], + [0.658479, 51.561659], + [0.658501, 51.561511], + [0.658495, 51.561501], + [0.658411, 51.56138], + [0.658402, 51.561375], + [0.658329, 51.56134], + [0.658327, 51.561339], + [0.658226, 51.561314], + [0.658219, 51.561317], + [0.658151, 51.561347], + [0.658142, 51.561349], + [0.658125, 51.561354], + [0.658116, 51.561356], + [0.65809, 51.561357], + [0.65808, 51.56136], + [0.65792, 51.561396], + [0.657814, 51.561396], + [0.657812, 51.561395], + [0.65776, 51.561382], + [0.657756, 51.561381], + [0.657745, 51.561382], + [0.657519, 51.561399], + [0.657497, 51.561397], + [0.657482, 51.561395], + [0.657476, 51.561394], + [0.657469, 51.561396], + [0.657465, 51.561396], + [0.657358, 51.561405], + [0.657345, 51.561404], + [0.657261, 51.561393], + [0.657247, 51.561392], + [0.657153, 51.561389], + [0.657145, 51.561388], + [0.657134, 51.561389], + [0.657121, 51.56139], + [0.657043, 51.561396], + [0.657026, 51.5614], + [0.657015, 51.561403], + [0.657009, 51.561404], + [0.656979, 51.561405], + [0.656966, 51.561403], + [0.656908, 51.561395], + [0.656907, 51.561395], + [0.656821, 51.561396], + [0.656813, 51.561392], + [0.656799, 51.561387], + [0.656792, 51.561385], + [0.65669, 51.561288], + [0.656662, 51.561232], + [0.656628, 51.561165], + [0.656631, 51.561153], + [0.656636, 51.561131], + [0.656634, 51.561127], + [0.656611, 51.561029], + [0.656609, 51.561019], + [0.65661, 51.561012], + [0.656614, 51.560996], + [0.656611, 51.560979], + [0.656625, 51.560972], + [0.656709, 51.56093], + [0.656727, 51.560921], + [0.656765, 51.560898], + [0.656774, 51.560892], + [0.656934, 51.560858], + [0.656945, 51.560854], + [0.657112, 51.560791], + [0.657111, 51.560789], + [0.657078, 51.560736], + [0.657074, 51.560732], + [0.657071, 51.560728], + [0.656988, 51.560678], + [0.656985, 51.560677], + [0.656809, 51.560609], + [0.656812, 51.560607], + [0.657025, 51.560324], + [0.657106, 51.560324], + [0.657298, 51.560323], + [0.657502, 51.560323], + [0.657557, 51.560379], + [0.657567, 51.560389], + [0.657575, 51.560397], + [0.657603, 51.560425], + [0.657604, 51.560426], + [0.657606, 51.560429], + [0.657886, 51.560517], + [0.65789, 51.560519], + [0.658107, 51.560587], + [0.658117, 51.560591], + [0.658128, 51.560594], + [0.658138, 51.560597], + [0.658151, 51.560601], + [0.658268, 51.560639], + [0.658283, 51.560643], + [0.658312, 51.560652], + [0.658314, 51.560653], + [0.658352, 51.560664], + [0.658366, 51.560668], + [0.658381, 51.560673], + [0.658517, 51.560714], + [0.658537, 51.56072], + [0.658541, 51.560721], + [0.658547, 51.560723], + [0.658561, 51.560727], + [0.658567, 51.560729], + [0.658571, 51.56073], + [0.658577, 51.560732], + [0.658666, 51.560759], + [0.658689, 51.560766], + [0.658765, 51.560789], + [0.658875, 51.560822], + [0.658889, 51.560826], + [0.658933, 51.560839], + [0.658938, 51.560841], + [0.659014, 51.560864], + [0.659017, 51.560865], + [0.659135, 51.5609], + [0.659818, 51.56109], + [0.659823, 51.561092], + [0.65985, 51.561099], + [0.65999, 51.561138], + [0.660342, 51.561235], + [0.660367, 51.561242], + [0.660388, 51.561248], + [0.660498, 51.561278], + [0.660525, 51.561285], + [0.660614, 51.561309], + [0.66064, 51.561317], + [0.660666, 51.561324], + [0.660704, 51.561334], + [0.660725, 51.56134], + [0.660749, 51.561346], + [0.660922, 51.561394], + [0.660958, 51.561404], + [0.660976, 51.561408], + [0.660988, 51.561412], + [0.661039, 51.561426], + [0.661044, 51.561427], + [0.661054, 51.56143], + [0.661065, 51.561434], + [0.661165, 51.561467], + [0.661179, 51.561472], + [0.661186, 51.561474], + [0.661195, 51.561477], + [0.661322, 51.561519], + [0.661323, 51.56152], + [0.661429, 51.561555], + [0.661431, 51.561556], + [0.66145, 51.561562], + [0.661459, 51.561565], + [0.661494, 51.561577], + [0.661505, 51.56158], + [0.661527, 51.561588], + [0.661552, 51.561596], + [0.661579, 51.561605], + [0.661611, 51.561616], + [0.661628, 51.561622], + [0.661631, 51.561623], + [0.661662, 51.561634], + [0.661668, 51.561636], + [0.661674, 51.561639], + [0.661706, 51.56165], + [0.66171, 51.561651], + [0.661758, 51.561668], + [0.661759, 51.561669], + [0.661801, 51.561683], + [0.661812, 51.561687], + [0.6619, 51.561719], + [0.661922, 51.561726], + [0.661944, 51.561734], + [0.661956, 51.561738], + [0.66199, 51.56175], + [0.662012, 51.561758], + [0.662069, 51.561778], + [0.66209, 51.561787], + [0.662111, 51.561796], + [0.662122, 51.561801], + [0.66215, 51.561813], + [0.66217, 51.561821], + [0.66218, 51.561825], + [0.6622, 51.561834], + [0.662211, 51.561838], + [0.662224, 51.561844], + [0.662263, 51.56186], + [0.662285, 51.561869], + [0.662313, 51.561881], + [0.662383, 51.561911], + [0.662398, 51.561917], + [0.6624, 51.561918], + [0.662414, 51.561924], + [0.662536, 51.561975], + [0.662551, 51.561982], + [0.662636, 51.562018], + [0.662651, 51.562024], + [0.662688, 51.56204], + [0.662691, 51.562042], + [0.662715, 51.562052], + [0.662792, 51.562085], + [0.66294, 51.56215], + [0.663027, 51.562194], + [0.663041, 51.562201], + [0.663141, 51.562252], + [0.663154, 51.562259], + [0.663156, 51.56226], + [0.663164, 51.562271], + [0.663188, 51.562303], + [0.663212, 51.562334], + [0.663223, 51.56235], + [0.663215, 51.5624], + [0.663192, 51.562537], + [0.663191, 51.562541], + [0.663186, 51.562571], + [0.66318, 51.562612], + [0.663177, 51.562626], + [0.663173, 51.56265], + [0.663171, 51.562661], + [0.663168, 51.562679] + ] + ], + "type": "Polygon" + }, + "properties": { + "fill": "green" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [0.657899, 51.560714], + [0.657205, 51.560501], + [0.657207, 51.560361], + [0.656965, 51.56036], + [0.656962, 51.56036], + [0.656326, 51.560346], + [0.655835, 51.560344], + [0.656072, 51.560848], + [0.656487, 51.561707], + [0.658876, 51.561546], + [0.658557, 51.560993], + [0.658555, 51.56099], + [0.658553, 51.560986], + [0.658552, 51.560983], + [0.658551, 51.560979], + [0.65855, 51.560976], + [0.65855, 51.560962], + [0.658551, 51.560958], + [0.658552, 51.560955], + [0.658553, 51.560951], + [0.658606, 51.560818], + [0.658176, 51.56069], + [0.65779, 51.561168], + [0.657584, 51.561104], + [0.657899, 51.560714] + ], + [ + [0.658258, 51.560948], + [0.658465, 51.561311], + [0.658483, 51.561406], + [0.656672, 51.561528], + [0.656249, 51.560649], + [0.656424, 51.560656], + [0.656439, 51.560511], + [0.657238, 51.560525], + [0.657145, 51.560639], + [0.657562, 51.560767], + [0.657391, 51.560977], + [0.657001, 51.560858], + [0.656784, 51.561146], + [0.657306, 51.561299], + [0.657399, 51.561179], + [0.657747, 51.561287], + [0.657832, 51.561182], + [0.658022, 51.561241], + [0.658258, 51.560948] + ] + ], + "type": "Polygon" + }, + "properties": { + "fill": "red" + }, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [0.656784, 51.561146], + [0.657001, 51.560858], + [0.657391, 51.560977], + [0.657562, 51.560767], + [0.657145, 51.560639], + [0.657238, 51.560525], + [0.6568784588933171, 51.560518700155825], + [0.656997802573544, 51.560360135547825], + [0.657207, 51.560361], + [0.657205, 51.560501], + [0.657899, 51.560714], + [0.657584, 51.561104], + [0.65779, 51.561168], + [0.658176, 51.56069], + [0.658606, 51.560818], + [0.658553, 51.560951], + [0.658552, 51.560955], + [0.658551, 51.560958], + [0.65855, 51.560962], + [0.65855, 51.560976], + [0.658551, 51.560979], + [0.658552, 51.560983], + [0.658553, 51.560986], + [0.658555, 51.56099], + [0.658557, 51.560993], + [0.658876, 51.561546], + [0.6584919499757166, 51.56157188198154], + [0.658501, 51.561511], + [0.658495, 51.561501], + [0.6584314599374823, 51.5614094720528], + [0.658483, 51.561406], + [0.658465, 51.561311], + [0.658258, 51.560948], + [0.658022, 51.561241], + [0.657832, 51.561182], + [0.657747, 51.561287], + [0.657399, 51.561179], + [0.657306, 51.561299], + [0.656784, 51.561146] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 86a6a6d060fce5fe5be449e78bf3824f582886fc Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:10:37 +0100 Subject: [PATCH 17/22] added issue69 variant --- .../generic_test_cases/issue69_sub1.geojson | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/issue69_sub1.geojson diff --git a/tests/fixtures/generic_test_cases/issue69_sub1.geojson b/tests/fixtures/generic_test_cases/issue69_sub1.geojson new file mode 100644 index 0000000..46add52 --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue69_sub1.geojson @@ -0,0 +1,76 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [-93.52965, 42.04924], + [-93.53626, 42.04214], + [-93.53914, 42.04358], + [-93.5313, 42.04924], + [-93.52965, 42.04924] + ], + [ + [-93.53419, 42.04589], + [-93.53449, 42.04596], + [-93.53434, 42.04588], + [-93.53419, 42.04589] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [-93.5388, 42.0484], + [-93.5387, 42.0476], + [-93.53824, 42.04826], + [-93.5388, 42.0484] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-93.53914, 42.04358], + [-93.53626, 42.04214], + [-93.52965, 42.04924], + [-93.5313, 42.04924], + [-93.53914, 42.04358] + ], + [ + [-93.53449, 42.04596], + [-93.53434, 42.04588], + [-93.53419, 42.04589], + [-93.53449, 42.04596] + ] + ], + [ + [ + [-93.5388, 42.0484], + [-93.5387, 42.0476], + [-93.53824, 42.04826], + [-93.5388, 42.0484] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 623c5c8c76e961b9846da7c8579eb1e578ed7e93 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:20:51 +0100 Subject: [PATCH 18/22] added issue71 --- .../generic_test_cases/issue71.geojson | 324 ++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/issue71.geojson diff --git a/tests/fixtures/generic_test_cases/issue71.geojson b/tests/fixtures/generic_test_cases/issue71.geojson new file mode 100644 index 0000000..8464431 --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue71.geojson @@ -0,0 +1,324 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [176466.88409999758, 172075.63210000098], + [176477.45099999756, 172064.3258999996], + [176488.64299999923, 172052.3500000015], + [176492.06599999964, 172051.7960000001], + [176494.7480000034, 172050.36400000006], + [176499.52199999988, 172044.5], + [176502.2899999991, 172040.47199999914], + [176504.22999999672, 172037.90989999846], + [176506.92899999768, 172036.49500000104], + [176510.40200000256, 172035.4690000005], + [176514.06099999696, 172035.5549999997], + [176517.5, 172035.92799999937], + [176520.61900000274, 172036.04809999838], + [176523.4179000035, 172035.25699999928], + [176525.67890000343, 172033.21799999848], + [176526.84399999678, 172030.48699999973], + [176527.9069999978, 172027.80700000003], + [176529.25789999962, 172024.5540000014], + [176530.82699999958, 172022.48099999875], + [176533.0380000025, 172019.88599999994], + [176535.66899999976, 172017.86400000006], + [176538.46809999645, 172017.0401000008], + [176540.9130000025, 172017.3110000007], + [176542.53100000322, 172018.54199999943], + [176542.69789999723, 172020.936999999], + [176541.90399999917, 172023.36400000006], + [176540.08100000024, 172026.56590000167], + [176537.76910000294, 172029.68400000036], + [176535.55900000036, 172032.6330000013], + [176534.12399999797, 172035.88699999824], + [176533.81899999827, 172037.94299999997], + [176534.25699999928, 172039.71400000155], + [176536.21100000292, 172041.94099999964], + [176538.72299999744, 172043.0549999997], + [176542.49899999797, 172043.49500000104], + [176545.31499999762, 172043.63210000098], + [176549.10809999704, 172044.52699999884], + [176554.72100000083, 172046.5540000014], + [176561.17599999905, 172049.35599999875], + [176568.93100000173, 172051.53500000015], + [176576.3650000021, 172052.7030000016], + [176584.3730000034, 172053.6339999996], + [176589.5850000009, 172053.1308999993], + [176593.52799999714, 172052.87700000033], + [176597.06589999795, 172052.14699999988], + [176600.2899999991, 172049.69090000167], + [176601.4830000028, 172047.7498999983], + [176603.620099999, 172046.2199999988], + [176605.28100000322, 172045.63500000164], + [176606.39599999785, 172045.94399999827], + [176607.27000000328, 172047.21609999985], + [176606.8049999997, 172049.1090000011], + [176605.90100000054, 172051.05000000075], + [176605.5549999997, 172052.79100000113], + [176606.52899999917, 172054.53700000048], + [176608.85899999738, 172055.59600000083], + [176610.97200000286, 172055.90900000185], + [176612.86100000143, 172057.33799999952], + [176614.76600000262, 172058.78299999982], + [176618.36299999803, 172060.33799999952], + [176622.89299999923, 172061.15100000054], + [176627.83100000024, 172061.45899999887], + [176633.81899999827, 172061.56810000166], + [176642.77099999785, 172060.7589999996], + [176649.54900000244, 172057.92799999937], + [176656.8377000019, 172050.72399999946], + [176658.1550000012, 172049.4219999984], + [176659.07710000128, 172050.03130000085], + [176665.00360000134, 172053.94700000063], + [176707.14899999648, 172081.79300000146], + [176684.625, 172132.8740000017], + [176810.65299999714, 172177.37090000138], + [176809.2968999967, 172212.32679999992], + [176808.82509999722, 172224.48999999836], + [176804.07569999993, 172257.0540000014], + [176804.05099999905, 172257.22300000116], + [176802.96410000324, 172258.9294999987], + [176800.75339999795, 172262.40060000122], + [176799.68860000372, 172264.07229999825], + [176798.5345999971, 172265.88430000097], + [176795.4469999969, 172270.73200000077], + [176791.96109999716, 172268.55099999905], + [176790.33100000024, 172267.53079999983], + [176768.1169999987, 172253.62900000066], + [176765.84669999778, 172261.02389999852], + [176755.33659999818, 172295.2600999996], + [176754.51299999654, 172297.94299999997], + [176763.4104000032, 172301.13910000026], + [176774.2199999988, 172305.02199999988], + [176785.4849999994, 172309.06799999997], + [176793.8220999986, 172313.06500000134], + [176795.69449999928, 172313.9626000002], + [176797.41399999708, 172314.78700000048], + [176793.84000000358, 172320.97800000012], + [176793.42700000107, 172320.82539999858], + [176792.40299999714, 172320.44700000063], + [176791.7602000013, 172320.20969999954], + [176788.245099999, 172318.91169999912], + [176780.26200000197, 172315.96400000155], + [176766.1699000001, 172310.76099999994], + [176764.81099999696, 172314.64039999992], + [176764.02199999988, 172316.89299999923], + [176767.50869999826, 172318.22590000182], + [176767.3180000037, 172318.68400000036], + [176760.51200000197, 172316.30409999937], + [176760.67769999802, 172315.78689999878], + [176761.41849999875, 172313.4765000008], + [176761.56899999827, 172313.00699999928], + [176686.63390000165, 172287.0089999996], + [176686.5320999995, 172290.43100000173], + [176685.91600000113, 172311.1559999995], + [176685.79089999944, 172315.3601000011], + [176679.06120000035, 172313.3550999984], + [176636.88910000026, 172300.79100000113], + [176636.89090000093, 172300.7666000016], + [176645.35599999875, 172189.9750000015], + [176611.0799999982, 172170.84600000083], + [176606.81599999964, 172167.8280000016], + [176580.52600000054, 172149.22190000117], + [176543.73099999875, 172119.4200000018], + [176504.67700000107, 172091.66299999878], + [176466.88409999758, 172075.63210000098] + ] + ], + [ + [ + [176687.02899999917, 172273.7030000016], + [176689.14400000125, 172202.563000001], + [176703.73369999975, 172212.30469999835], + [176714.7704000026, 172219.67399999872], + [176728.3599999994, 172228.74799999967], + [176726.54599999636, 172287.85090000182], + [176721.57140000165, 172286.0698999986], + [176687.5874999985, 172273.90300000086], + [176687.02899999917, 172273.7030000016] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [176689.14400000125, 172202.563000001], + [176647.29299999774, 172182.33700000122], + [176645.35599999875, 172189.9750000015], + [176636.89090000093, 172300.7666000016], + [176636.88910000026, 172300.79100000113], + [176679.06120000035, 172313.3550999984], + [176685.79089999944, 172315.3601000011], + [176685.91600000113, 172311.1559999995], + [176686.5320999995, 172290.43100000173], + [176686.63390000165, 172287.0089999996], + [176687.02899999917, 172273.7030000016], + [176689.14400000125, 172202.563000001] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [176466.88409999758, 172075.63210000098], + [176477.45099999756, 172064.3258999996], + [176488.64299999923, 172052.3500000015], + [176492.06599999964, 172051.7960000001], + [176494.7480000034, 172050.36400000006], + [176499.52199999988, 172044.5], + [176502.2899999991, 172040.47199999914], + [176504.22999999672, 172037.90989999846], + [176506.92899999768, 172036.49500000104], + [176510.40200000256, 172035.4690000005], + [176514.06099999696, 172035.5549999997], + [176517.5, 172035.92799999937], + [176520.61900000274, 172036.04809999838], + [176523.4179000035, 172035.25699999928], + [176525.67890000343, 172033.21799999848], + [176526.84399999678, 172030.48699999973], + [176527.9069999978, 172027.80700000003], + [176529.25789999962, 172024.5540000014], + [176530.82699999958, 172022.48099999875], + [176533.0380000025, 172019.88599999994], + [176535.66899999976, 172017.86400000006], + [176538.46809999645, 172017.0401000008], + [176540.9130000025, 172017.3110000007], + [176542.53100000322, 172018.54199999943], + [176542.69789999723, 172020.936999999], + [176541.90399999917, 172023.36400000006], + [176540.08100000024, 172026.56590000167], + [176537.76910000294, 172029.68400000036], + [176535.55900000036, 172032.6330000013], + [176534.12399999797, 172035.88699999824], + [176533.81899999827, 172037.94299999997], + [176534.25699999928, 172039.71400000155], + [176536.21100000292, 172041.94099999964], + [176538.72299999744, 172043.0549999997], + [176542.49899999797, 172043.49500000104], + [176545.31499999762, 172043.63210000098], + [176549.10809999704, 172044.52699999884], + [176554.72100000083, 172046.5540000014], + [176561.17599999905, 172049.35599999875], + [176568.93100000173, 172051.53500000015], + [176576.3650000021, 172052.7030000016], + [176584.3730000034, 172053.6339999996], + [176589.5850000009, 172053.1308999993], + [176593.52799999714, 172052.87700000033], + [176597.06589999795, 172052.14699999988], + [176600.2899999991, 172049.69090000167], + [176601.4830000028, 172047.7498999983], + [176603.620099999, 172046.2199999988], + [176605.28100000322, 172045.63500000164], + [176606.39599999785, 172045.94399999827], + [176607.27000000328, 172047.21609999985], + [176606.8049999997, 172049.1090000011], + [176605.90100000054, 172051.05000000075], + [176605.5549999997, 172052.79100000113], + [176606.52899999917, 172054.53700000048], + [176608.85899999738, 172055.59600000083], + [176610.97200000286, 172055.90900000185], + [176612.86100000143, 172057.33799999952], + [176614.76600000262, 172058.78299999982], + [176618.36299999803, 172060.33799999952], + [176622.89299999923, 172061.15100000054], + [176627.83100000024, 172061.45899999887], + [176633.81899999827, 172061.56810000166], + [176642.77099999785, 172060.7589999996], + [176649.54900000244, 172057.92799999937], + [176656.8377000019, 172050.72399999946], + [176658.1550000012, 172049.4219999984], + [176659.07710000128, 172050.03130000085], + [176665.00360000134, 172053.94700000063], + [176707.14899999648, 172081.79300000146], + [176684.625, 172132.8740000017], + [176810.65299999714, 172177.37090000138], + [176809.2968999967, 172212.32679999992], + [176808.82509999722, 172224.48999999836], + [176804.07569999993, 172257.0540000014], + [176804.05099999905, 172257.22300000116], + [176802.96410000324, 172258.9294999987], + [176800.75339999795, 172262.40060000122], + [176799.68860000372, 172264.07229999825], + [176798.5345999971, 172265.88430000097], + [176795.4469999969, 172270.73200000077], + [176791.96109999716, 172268.55099999905], + [176790.33100000024, 172267.53079999983], + [176768.1169999987, 172253.62900000066], + [176765.84669999778, 172261.02389999852], + [176755.33659999818, 172295.2600999996], + [176754.51299999654, 172297.94299999997], + [176763.4104000032, 172301.13910000026], + [176774.2199999988, 172305.02199999988], + [176785.4849999994, 172309.06799999997], + [176793.8220999986, 172313.06500000134], + [176795.69449999928, 172313.9626000002], + [176797.41399999708, 172314.78700000048], + [176793.84000000358, 172320.97800000012], + [176793.42700000107, 172320.82539999858], + [176792.40299999714, 172320.44700000063], + [176791.7602000013, 172320.20969999954], + [176788.245099999, 172318.91169999912], + [176780.26200000197, 172315.96400000155], + [176766.1699000001, 172310.76099999994], + [176764.81099999696, 172314.64039999992], + [176764.02199999988, 172316.89299999923], + [176767.50869999826, 172318.22590000182], + [176767.3180000037, 172318.68400000036], + [176760.51200000197, 172316.30409999937], + [176760.67769999802, 172315.78689999878], + [176761.41849999875, 172313.4765000008], + [176761.56899999827, 172313.00699999928], + [176686.63390000165, 172287.0089999996], + [176686.5320999995, 172290.43100000173], + [176685.91600000113, 172311.1559999995], + [176685.79089999944, 172315.3601000011], + [176679.06120000035, 172313.3550999984], + [176636.88910000026, 172300.79100000113], + [176636.89090000093, 172300.7666000016], + [176645.35599999875, 172189.9750000015], + [176611.0799999982, 172170.84600000083], + [176606.81599999964, 172167.8280000016], + [176580.52600000054, 172149.22190000117], + [176543.73099999875, 172119.4200000018], + [176504.67700000107, 172091.66299999878], + [176466.88409999758, 172075.63210000098] + ], + [ + [176687.02899999917, 172273.7030000016], + [176689.14400000125, 172202.563000001], + [176703.73369999975, 172212.30469999835], + [176714.7704000026, 172219.67399999872], + [176728.3599999994, 172228.74799999967], + [176726.54599999636, 172287.85090000182], + [176721.57140000165, 172286.0698999986], + [176687.5874999985, 172273.90300000086], + [176687.02899999917, 172273.7030000016] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "union" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 37733ed96512678dec761c2c672be13dcd531b21 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 08:34:01 +0100 Subject: [PATCH 19/22] added issue96 --- .../generic_test_cases/issue96.geojson | 2021 +++++++++++++++++ 1 file changed, 2021 insertions(+) create mode 100644 tests/fixtures/generic_test_cases/issue96.geojson diff --git a/tests/fixtures/generic_test_cases/issue96.geojson b/tests/fixtures/generic_test_cases/issue96.geojson new file mode 100644 index 0000000..de1d983 --- /dev/null +++ b/tests/fixtures/generic_test_cases/issue96.geojson @@ -0,0 +1,2021 @@ +{ + "features": [ + { + "geometry": { + "coordinates": [ + [ + [ + [-5.0844225050718475, 56.82118935427821], + [-5.0838535, 56.8211702], + [-5.0837353, 56.82118289999995], + [-5.0836972, 56.8211822], + [-5.0834868, 56.821172399999966], + [-5.083281, 56.82114969999998], + [-5.0830782, 56.82115089999998], + [-5.0829664, 56.821141], + [-5.0826849, 56.8210829], + [-5.0823903, 56.82098249999996], + [-5.0819432, 56.82075849999996], + [-5.0818217, 56.82067609999997], + [-5.0817477, 56.820652799999976], + [-5.0817043, 56.82060349999996], + [-5.0814518, 56.820471599999976], + [-5.0812101, 56.82039219999997], + [-5.0810824, 56.820378], + [-5.0809574, 56.82034929999998], + [-5.0808115, 56.8203196], + [-5.0805575, 56.82024639999997], + [-5.080352473426072, 56.82015402319541], + [-5.080064299546843, 56.819774453961585], + [-5.080066535257358, 56.81970550600799], + [-5.0801541, 56.819691299999974], + [-5.0801798, 56.819684399999964], + [-5.0801898, 56.81966709999998], + [-5.0801832, 56.81964659999996], + [-5.0801599, 56.819642699999974], + [-5.0800769, 56.819669], + [-5.080067749805464, 56.81966805001485], + [-5.080075393006905, 56.8194323368084], + [-5.080107557155173, 56.818903595785166], + [-5.080106852393738, 56.8188933833134], + [-5.080103512847632, 56.81888332896133], + [-5.080097606072239, 56.81887363611132], + [-5.079291103268355, 56.817808836909244], + [-5.079280900995247, 56.81779804666472], + [-5.078275699486228, 56.81692464756334], + [-5.07827199725973, 56.8169216051043], + [-5.077740996687888, 56.81650840556168], + [-5.077730060823799, 56.81650099371128], + [-5.077717431932552, 56.816494441157275], + [-5.076935523766095, 56.81613957407178], + [-5.076414600327056, 56.81573737941062], + [-5.076103435787177, 56.81522190806761], + [-5.076108075441466, 56.815093274083374], + [-5.076558134115263, 56.81417372888078], + [-5.076561062833359, 56.81416612288394], + [-5.076661061639212, 56.813812822789224], + [-5.076662425824648, 56.81380563237591], + [-5.076662465809871, 56.81379840317256], + [-5.076612263788466, 56.81321660323931], + [-5.076610692399389, 56.813208401885674], + [-5.076480590405791, 56.81277210022826], + [-5.076408089594414, 56.81252900030875], + [-5.07640488357897, 56.81252108447643], + [-5.076400071933539, 56.81251341716845], + [-5.076120370936136, 56.81213801744596], + [-5.076113662251077, 56.81213034512128], + [-5.075971415002954, 56.81198968778768], + [-5.0759814, 56.811969899999966], + [-5.0759015, 56.81186879999997], + [-5.0757877, 56.81171189999996], + [-5.0757683, 56.811640699999955], + [-5.0757321, 56.811575499999954], + [-5.075721, 56.811358399999975], + [-5.0757828, 56.8113047], + [-5.0758658, 56.811215], + [-5.0758906, 56.81114059999997], + [-5.0759846, 56.810983799999974], + [-5.0760084, 56.81085409999997], + [-5.076000725481171, 56.81083805328089], + [-5.076003746657344, 56.81082899359518], + [-5.0760522, 56.810788299999984], + [-5.0760649, 56.81071969999996], + [-5.07613587706682, 56.81052279588375], + [-5.076474740835754, 56.8099681792691], + [-5.0765026, 56.80993269999998], + [-5.0765628, 56.80987849999998], + [-5.0767629, 56.809711299999975], + [-5.0768278, 56.8096175], + [-5.0768813, 56.809526499999954], + [-5.0768973, 56.80946819999998], + [-5.0769328, 56.80942689999996], + [-5.076952628335087, 56.80926360225266], + [-5.076989842982081, 56.80920936020085], + [-5.0770991, 56.809109], + [-5.0771592, 56.80903659999996], + [-5.077144635936648, 56.808983740609996], + [-5.077150900745453, 56.80897460923242], + [-5.077155759194521, 56.80896588309476], + [-5.077176351361956, 56.80891825936254], + [-5.0772776, 56.80885029999998], + [-5.0773146, 56.80878189999998], + [-5.0773107, 56.808734399999985], + [-5.077281234166157, 56.80867569386844], + [-5.07733035789224, 56.80856208292662], + [-5.07733334468683, 56.80855207326558], + [-5.077333732386435, 56.8085419326344], + [-5.077331513268288, 56.808531863083815], + [-5.077269926977104, 56.8083570890335], + [-5.077267, 56.808241099999975], + [-5.077221, 56.80814679999999], + [-5.0771487, 56.80792959999997], + [-5.0770781, 56.807787899999965], + [-5.0769818, 56.80762519999995], + [-5.0769008, 56.807536399999975], + [-5.0761416, 56.8067902], + [-5.0760064, 56.806660499999964], + [-5.075947, 56.806616099999985], + [-5.0757464, 56.806487199999985], + [-5.0755538, 56.8063957], + [-5.0754592, 56.806362099999966], + [-5.075408378251169, 56.80633717067541], + [-5.075282292797596, 56.80626652880195], + [-5.075266588105093, 56.80625902775082], + [-5.07516528747315, 56.80621792788577], + [-5.075058, 56.806165299999975], + [-5.0745412, 56.805937099999966], + [-5.0744035, 56.80589559999997], + [-5.074217680509599, 56.80585431710212], + [-5.074173392494825, 56.80583849111142], + [-5.074155533130106, 56.80583314377629], + [-5.074140985640383, 56.805830283741145], + [-5.0741284, 56.8058179], + [-5.0735492, 56.8057288], + [-5.073469533955619, 56.805729559181046], + [-5.073451341717011, 56.80572683595746], + [-5.073277843074884, 56.805692476328595], + [-5.0732691, 56.805688899999986], + [-5.0732026, 56.80567709999998], + [-5.07320057173734, 56.80567717343334], + [-5.073078576512948, 56.80565301325009], + [-5.073078148002581, 56.80565292884826], + [-5.072726495704795, 56.80558404305916], + [-5.072459731350001, 56.805516622896405], + [-5.072385498378591, 56.80549295709813], + [-5.072047135153812, 56.80536725949438], + [-5.071743310874293, 56.805219178664515], + [-5.0714697, 56.805025], + [-5.0711059, 56.80472379999996], + [-5.0710573, 56.80465039999997], + [-5.0710473, 56.80460839999997], + [-5.0710152, 56.80455709999998], + [-5.0708008, 56.80427919999997], + [-5.0702227, 56.80336219999995], + [-5.0700235, 56.80311], + [-5.0698687, 56.802880199999954], + [-5.0696916, 56.802658], + [-5.0695335, 56.802547699999955], + [-5.069544, 56.802516], + [-5.0690218, 56.80197969999995], + [-5.0685784, 56.80150609999998], + [-5.0683886, 56.801349499999986], + [-5.0682417, 56.801209699999966], + [-5.067800957551483, 56.8008976852266], + [-5.067551209684683, 56.800648606926494], + [-5.067379197734261, 56.800320604183895], + [-5.0673164, 56.80016349999995], + [-5.067250297641417, 56.80007480571355], + [-5.067157858011309, 56.799898531266734], + [-5.067148412949355, 56.79988548155604], + [-5.067096863685227, 56.79983060224214], + [-5.0670653, 56.79978009999997], + [-5.0668036, 56.79939709999998], + [-5.0664568, 56.79910939999997], + [-5.066092, 56.79894779999997], + [-5.065790861693006, 56.79885686120155], + [-5.065784864950974, 56.798854429314076], + [-5.065131096379549, 56.798618961134835], + [-5.064593210510688, 56.79840916150834], + [-5.064459402855822, 56.79832497430791], + [-5.064078373324219, 56.7980851909765], + [-5.0639455, 56.79798709999998], + [-5.063921346244208, 56.79795731045964], + [-5.063714604747818, 56.79750839369863], + [-5.063689036070978, 56.79736225573366], + [-5.06369, 56.797361199999976], + [-5.0637241, 56.79731149999998], + [-5.0637619, 56.79712729999996], + [-5.0637997, 56.797042399999974], + [-5.0638299, 56.796951399999955], + [-5.063840545777511, 56.79690825365828], + [-5.063871112516328, 56.796843488764075], + [-5.0639093, 56.796789899999986], + [-5.063932, 56.79671749999997], + [-5.0639698, 56.79664289999998], + [-5.0639773, 56.79653939999994], + [-5.0639055, 56.79642969999995], + [-5.0638034, 56.79631589999997], + [-5.063623328360122, 56.79621350284332], + [-5.063330773953526, 56.79597542748944], + [-5.063328610315422, 56.79597372055465], + [-5.062912309893991, 56.79565522091085], + [-5.062900300053392, 56.79564730001357], + [-5.062886349109989, 56.79564040313278], + [-5.062870743931184, 56.795634672085676], + [-5.062794520457557, 56.795610832288475], + [-5.0627904, 56.795607899999965], + [-5.0626619, 56.79556029999998], + [-5.062596244726551, 56.79554881883488], + [-5.061970617563441, 56.795353141928594], + [-5.061829665075179, 56.79528707942135], + [-5.061732, 56.795220799999974], + [-5.0614863, 56.79509249999998], + [-5.0614006, 56.7950526], + [-5.0612103, 56.79497859999998], + [-5.0610742, 56.79491029999998], + [-5.0609117, 56.794837799999975], + [-5.0607983, 56.794790199999966], + [-5.0606547, 56.7947033], + [-5.060472294716802, 56.79458896281343], + [-5.060196366913685, 56.79437442967579], + [-5.059938431132121, 56.7941111723512], + [-5.059937003483922, 56.79410975382291], + [-5.059692603007896, 56.793873254048236], + [-5.059681302733298, 56.793864055083624], + [-5.059529699068083, 56.793759134204265], + [-5.059448529659369, 56.793631933095426], + [-5.059328739775509, 56.793414152188944], + [-5.05930995647021, 56.79331564447932], + [-5.059308, 56.79326369999996], + [-5.059212275682353, 56.79251355245305], + [-5.05921117960946, 56.79239145573188], + [-5.05928705325, 56.792069825566166], + [-5.059288125524903, 56.792061546483055], + [-5.059287450985335, 56.79205325477282], + [-5.059227849896295, 56.79173495484243], + [-5.059227245654561, 56.791732237848834], + [-5.05917034491058, 56.79151143791297], + [-5.059167808115607, 56.79150425444858], + [-5.059163953297503, 56.79149724980947], + [-5.05903715274842, 56.791303149937924], + [-5.059030289602089, 56.79129448476168], + [-5.059021414141305, 56.79128638867432], + [-5.059010679819252, 56.79127900165282], + [-5.058976409658929, 56.7912583623708], + [-5.0588789, 56.79111249999996], + [-5.0587957, 56.79109659999998], + [-5.0587182, 56.791105], + [-5.0586901, 56.79110809999995], + [-5.0585872, 56.791151099999965], + [-5.058494824635421, 56.7912096088545], + [-5.058427960873987, 56.791223494243475], + [-5.058409870339997, 56.791228145299016], + [-5.058393279672446, 56.79123425257887], + [-5.058131879813535, 56.79134725240899], + [-5.058123668828177, 56.79135111382938], + [-5.057684768895031, 56.79157541351664], + [-5.05767211168842, 56.79158286921267], + [-5.057661503491429, 56.7915912325077], + [-5.057575774094469, 56.79167023124861], + [-5.0575512, 56.79166839999998], + [-5.0574907, 56.79163729999996], + [-5.0573093, 56.79150689999995], + [-5.0572035, 56.79139919999999], + [-5.057119464767872, 56.791320843978156], + [-5.057101738752526, 56.791296905563634], + [-5.0571049, 56.79123069999997], + [-5.0570386, 56.7911325], + [-5.0569804, 56.791003799999956], + [-5.056928, 56.79093369999997], + [-5.0566955, 56.79050019999996], + [-5.0566524, 56.790447099999966], + [-5.056499422840998, 56.79038123234917], + [-5.055869115150336, 56.78997086089894], + [-5.055735418347902, 56.78979802014871], + [-5.055566635008775, 56.78957982319612], + [-5.055195338853872, 56.78902155821231], + [-5.055166872572557, 56.788808926281845], + [-5.055115571252607, 56.78842632634459], + [-5.055114826826991, 56.78842231547202], + [-5.054960852611891, 56.78777375802082], + [-5.055071842243443, 56.787217421317266], + [-5.055072457510139, 56.7872060202266], + [-5.055069778134389, 56.78719470933569], + [-5.054862376394724, 56.786657309559814], + [-5.054857806674836, 56.7866483658985], + [-5.054851173155182, 56.786639820507105], + [-5.054842586683363, 56.78663181617936], + [-5.054832190740584, 56.786624486667556], + [-5.054820159044032, 56.786617954447934], + [-5.05480669264402, 56.78661232867379], + [-5.053398922762203, 56.78609952353009], + [-5.052823869112232, 56.78586649607518], + [-5.052512373696763, 56.78574021165627], + [-5.051647183424055, 56.785227645199754], + [-5.051634428229315, 56.78503272084079], + [-5.051632644620956, 56.78502320465459], + [-5.051628573808174, 56.78501390284921], + [-5.051561130117941, 56.78489522361774], + [-5.05159325976338, 56.78480721907061], + [-5.051595675226743, 56.78479638084742], + [-5.051606774763253, 56.78466308083912], + [-5.051606435304696, 56.784653678102615], + [-5.051603861547536, 56.78464438023261], + [-5.051515360835772, 56.784423280327886], + [-5.051507645690004, 56.784410164864035], + [-5.051402645348595, 56.78427696496709], + [-5.051395135608862, 56.784268881115736], + [-5.05138582967021, 56.78426138122732], + [-5.051374875935312, 56.784254584902364], + [-5.051362449083946, 56.78424860052176], + [-5.051119149240513, 56.78414560067578], + [-5.05109760437492, 56.784138191121066], + [-5.050876504664123, 56.78407769122202], + [-5.050862689931641, 56.78407444029466], + [-5.050848287363703, 56.784072080019726], + [-5.050833486831478, 56.784070641513146], + [-5.050413287620675, 56.78404334155912], + [-5.05039789961582, 56.784042843424665], + [-5.049997820914563, 56.78404284342474], + [-5.049066248466787, 56.78401609834609], + [-5.048450112170306, 56.78391352419519], + [-5.048329843193051, 56.78330495073044], + [-5.048326684289387, 56.78329524192849], + [-5.048321133262226, 56.78328586200232], + [-5.04784693153339, 56.78263936247374], + [-5.04783890516812, 56.78263030846943], + [-5.046916303437762, 56.781751909316036], + [-5.046915413585923, 56.78175107509339], + [-5.046014212013696, 56.78091907591312], + [-5.046005070697779, 56.780911716562905], + [-5.045994340971041, 56.78090503460811], + [-5.044627235608612, 56.780153211771385], + [-5.043682004451961, 56.778802860261585], + [-5.04396962010656, 56.778227720915815], + [-5.044219946111421, 56.77772706567761], + [-5.045108976317644, 56.77697484521091], + [-5.046031634053867, 56.776249817571006], + [-5.046670416790827, 56.776303722689214], + [-5.046687645573158, 56.776304541930514], + [-5.046704920696494, 56.77630410695737], + [-5.046721940571063, 56.77630242536353], + [-5.04713354128229, 56.776246125254644], + [-5.04714907361037, 56.776243426984344], + [-5.047163875044285, 56.776239690221416], + [-5.047177716255251, 56.77623497286219], + [-5.047190382792116, 56.77622934799597], + [-5.047201678404027, 56.77622290277277], + [-5.047211428081086, 56.776215737052816], + [-5.047696727382215, 56.775808436633774], + [-5.047704857746765, 56.775800573819254], + [-5.047711125294253, 56.775792212696956], + [-5.047715430795, 56.77578348564441], + [-5.047717706083597, 56.775774530832585], + [-5.047787104344933, 56.775271830772574], + [-5.047787114515391, 56.77526104354609], + [-5.047784183356109, 56.775250377036436], + [-5.04748088102908, 56.77452237736149], + [-5.047477030932942, 56.774514982084774], + [-5.047471763214956, 56.77450785511505], + [-5.046963728019259, 56.77391389129399], + [-5.04663308896715, 56.773362698822034], + [-5.04656069293501, 56.772898667148255], + [-5.046559288425677, 56.77289265752792], + [-5.046421086958397, 56.77245005768046], + [-5.046416584587734, 56.772440030347134], + [-5.046409510775885, 56.772430460967556], + [-5.046169210152349, 56.77216246119697], + [-5.046163386553889, 56.77215665789507], + [-5.045802385969291, 56.771833158220524], + [-5.045791528573977, 56.771824826483304], + [-5.04577862362996, 56.77181742723784], + [-5.045763933462056, 56.771811110891434], + [-5.045747756683539, 56.771806005838776], + [-5.045730422126136, 56.77180221585212], + [-5.045404222665225, 56.7717453159514], + [-5.045390008014714, 56.771743310553894], + [-5.045375473807582, 56.771742191705385], + [-5.045360802840538, 56.77174197347766], + [-5.044758403989612, 56.771751573451326], + [-5.044756432897056, 56.77175161302337], + [-5.044314633738066, 56.77176231299712], + [-5.044291408362242, 56.77176402868762], + [-5.043456954175049, 56.771868116442874], + [-5.042500006201438, 56.7718013772788], + [-5.041351720463965, 56.77161039251483], + [-5.040803582341719, 56.77151721595063], + [-5.04033291988711, 56.771396404738596], + [-5.040319101159831, 56.7713933705997], + [-5.039825901960779, 56.771302570757754], + [-5.03980528103558, 56.77129977267055], + [-5.039493581610555, 56.77127197271865], + [-5.039477918654264, 56.771271102509836], + [-5.039091289181199, 56.77126246662606], + [-5.038728319759183, 56.77124557529982], + [-5.038487144386079, 56.77121760664362], + [-5.03836516464192, 56.77116833109147], + [-5.038254561705084, 56.77108395288377], + [-5.038090106639766, 56.77088952217539], + [-5.0379813477199, 56.77041267071711], + [-5.03797749388615, 56.77040218309272], + [-5.037970846881517, 56.77039212592545], + [-5.037860846546339, 56.77025782603252], + [-5.037853766822706, 56.770250379403365], + [-5.037845152823503, 56.77024343734495], + [-5.037835122271261, 56.77023709472969], + [-5.037699422267213, 56.77016079483108], + [-5.037687169496897, 56.77015472339523], + [-5.037673622463826, 56.77014954709781], + [-5.037658996647449, 56.77014534827291], + [-5.037643524686095, 56.770142193706974], + [-5.037458424996744, 56.770111593760504], + [-5.037443762860107, 56.77010966784906], + [-5.037428794632018, 56.77010868070171], + [-5.037413718971525, 56.77010864541983], + [-5.037398735963513, 56.7701095624718], + [-5.037219036290796, 56.77012636243805], + [-5.037202199010498, 56.77012857440839], + [-5.037186040835524, 56.77013198748685], + [-5.036985341104968, 56.77018298739695], + [-5.036977987192591, 56.77018518749714], + [-5.036970622003041, 56.77018737619988], + [-5.0369704722437, 56.77018743577455], + [-5.036970309853309, 56.77018748435752], + [-5.036963541827739, 56.77019019271204], + [-5.036956759916273, 56.77019289057328], + [-5.036956625599425, 56.77019296037193], + [-5.036956476146658, 56.770193020178255], + [-5.036950409812859, 56.77019619044584], + [-5.036944327217214, 56.770199351305386], + [-5.036852337238845, 56.77025384528489], + [-5.036785398322123, 56.7702934811466], + [-5.036671581136191, 56.770319522285654], + [-5.03660749054709, 56.77031971629849], + [-5.036533518855928, 56.7703141973479], + [-5.036517994584214, 56.77031355229406], + [-5.036502440666002, 56.77031392416586], + [-5.036487077249141, 56.77031530769984], + [-5.036472121785205, 56.77031768331372], + [-5.036163935479264, 56.77037775686831], + [-5.035483930506816, 56.770488778107236], + [-5.034710747629625, 56.77049426369205], + [-5.033750913309432, 56.77040348584927], + [-5.033739048668949, 56.77040266809259], + [-5.033309165228711, 56.770383941649236], + [-5.033162952842571, 56.770322661478545], + [-5.032745753120217, 56.770147961740655], + [-5.032730637805079, 56.77014249644737], + [-5.032714293848013, 56.77013822854273], + [-5.032697033851368, 56.77013523965664], + [-5.031978535117203, 56.770040239823324], + [-5.03196249566122, 56.77003869138097], + [-5.031946230156653, 56.770038248875046], + [-5.031228163485361, 56.77004327861562], + [-5.030778998533689, 56.77000844898548], + [-5.030757941203743, 56.77000775897847], + [-5.030281865714793, 56.770013270472546], + [-5.029901937432302, 56.76993583402815], + [-5.029884563621346, 56.769933026896986], + [-5.029866650398643, 56.76993156378089], + [-5.029848540852238, 56.76993147270265], + [-5.029612441300336, 56.7699392726847], + [-5.029594601448172, 56.7699405422159], + [-5.029577247224947, 56.76994314320245], + [-5.029324247622088, 56.76999154311278], + [-5.029301923585764, 56.76999715288565], + [-5.028803624124256, 56.770154952622036], + [-5.028791507973671, 56.77015929659929], + [-5.027678490918634, 56.770608413683675], + [-5.027265627452971, 56.77069587910747], + [-5.02639658883008, 56.77081187518612], + [-5.02639658883008, 56.7709597742192], + [-5.027335711621496, 56.77083442357739], + [-5.027351904492563, 56.77083164053779], + [-5.027789005148308, 56.77073904036897], + [-5.027804751357127, 56.770735026785246], + [-5.027819391499965, 56.77072990405236], + [-5.028940653207516, 56.77027745954526], + [-5.029421995867688, 56.77012502946384], + [-5.029646243784535, 56.7700821298563], + [-5.029836723650749, 56.7700758370065], + [-5.030214163036814, 56.770152766097716], + [-5.030229877075177, 56.77015536609115], + [-5.030246060194936, 56.77015686559987], + [-5.030262457853618, 56.77015724103825], + [-5.030752879298577, 56.77015156351889], + [-5.031201502254727, 56.77018635107251], + [-5.031221468462152, 56.77018705114348], + [-5.031933190378858, 56.770182065901565], + [-5.032608966092147, 56.77027141693292], + [-5.033004224230213, 56.770436928972195], + [-5.033181001663783, 56.770511019576126], + [-5.033196658842235, 56.77051665658052], + [-5.033213620757753, 56.77052100900596], + [-5.033231540212038, 56.77052398776132], + [-5.033250050406345, 56.77052553187355], + [-5.033712384895555, 56.770545672010066], + [-5.034678188393849, 56.77063701430622], + [-5.034702089947854, 56.77063805094072], + [-5.035505491482456, 56.77063235091911], + [-5.035523480570888, 56.77063153966424], + [-5.035541095250985, 56.770629376937606], + [-5.03624179641142, 56.770514976721024], + [-5.036248277889867, 56.7705138167812], + [-5.036529750067585, 56.77045895052231], + [-5.036581381235431, 56.77046280265984], + [-5.036599721346842, 56.77046345581749], + [-5.03669882153621, 56.77046315581558], + [-5.036715748407127, 56.770462500444765], + [-5.03673237853071, 56.77046064788621], + [-5.036748432281617, 56.770457629289616], + [-5.036912332517488, 56.77042012922216], + [-5.036929006428533, 56.7704155223606], + [-5.036944317078998, 56.77040965974852], + [-5.036957952971134, 56.770402660662064], + [-5.03704427305481, 56.770351548688836], + [-5.037118708128757, 56.77030745394777], + [-5.037280143687985, 56.770266431434656], + [-5.037412385366501, 56.7702540682777], + [-5.037535757987124, 56.77027446375458], + [-5.037631668828436, 56.770328391580165], + [-5.037724093737016, 56.77044123441909], + [-5.037832950561739, 56.7709185292749], + [-5.037837021472434, 56.770929436674166], + [-5.037844112196551, 56.77093986781723], + [-5.038022411682521, 56.77115066798963], + [-5.038034886202877, 56.77116237660403], + [-5.038164786073096, 56.771261476715], + [-5.038177983352675, 56.77127004488495], + [-5.038193449136521, 56.77127738036255], + [-5.038354849255184, 56.771342580461585], + [-5.038370553345114, 56.77134802587678], + [-5.038387503237015, 56.771352195697915], + [-5.038405357502683, 56.771355005930616], + [-5.038682158000016, 56.77138710598681], + [-5.038698148173042, 56.77138840016596], + [-5.039072048881555, 56.77140580019397], + [-5.039077780585226, 56.77140599747794], + [-5.03945940207112, 56.77141452150777], + [-5.039752800921299, 56.771440689259386], + [-5.040228831948191, 56.77152832838906], + [-5.040700880580803, 56.77164949544446], + [-5.040717597796708, 56.77165304259934], + [-5.041274698724455, 56.77174774276478], + [-5.041275460783456, 56.77174787090825], + [-5.042434662725824, 56.77194067124537], + [-5.042456109458064, 56.77194318404308], + [-5.043446911312539, 56.77201228416034], + [-5.043462122516216, 56.77201285337643], + [-5.043477351059239, 56.77201244732348], + [-5.043492390243135, 56.77201107151286], + [-5.044337919467774, 56.771905602370275], + [-5.044766981849441, 56.77189521083972], + [-5.045346170007636, 56.77188598079118], + [-5.04560469481365, 56.77193107604918], + [-5.045937057527528, 56.77222891414132], + [-5.046166316119592, 56.772484600893556], + [-5.046300378327033, 56.77291395379751], + [-5.046373605396361, 56.77338333280373], + [-5.04637578379235, 56.773391602993634], + [-5.046379696109799, 56.773399678406854], + [-5.046717594464963, 56.77396297875348], + [-5.046723438036395, 56.77397104428017], + [-5.047228856012808, 56.77456195271855], + [-5.047524598017353, 56.775271817360675], + [-5.047459239019699, 56.77574523446726], + [-5.047020464710445, 56.7761134858196], + [-5.046684183889066, 56.7761594833688], + [-5.045990884469436, 56.776100977412035], + [-5.045974768424556, 56.77610017307002], + [-5.045958594770481, 56.77610046677368], + [-5.045942610759093, 56.776101854033115], + [-5.0459270607432, 56.77610431364077], + [-5.045912182441098, 56.776107807995906], + [-5.045898203302536, 56.77611228367915], + [-5.045885337031666, 56.77611767226916], + [-5.045873780320099, 56.776123891388835], + [-5.045863709840021, 56.77613084596423], + [-5.044893108686666, 56.77689354514177], + [-5.044890602907807, 56.77689558782139], + [-5.043989301580958, 56.77765818704146], + [-5.043979681267374, 56.777667885738595], + [-5.043972881618455, 56.777678279201595], + [-5.043717180628941, 56.778189677734446], + [-5.043418179361967, 56.77878757623941], + [-5.043414807507304, 56.77879650323572], + [-5.043413521769236, 56.77880559276595], + [-5.043414342846467, 56.77881469851123], + [-5.043417257523199, 56.77882367389159], + [-5.043422218881773, 56.778832374425455], + [-5.044392815084058, 56.780218975398014], + [-5.044400511949996, 56.780228032989484], + [-5.044410423753367, 56.780236416688496], + [-5.04442235873728, 56.78024396430009], + [-5.045797528698641, 56.78100022467195], + [-5.046689936157024, 56.781824109337286], + [-5.047607502207719, 56.78269771914416], + [-5.048071508151786, 56.78333032394201], + [-5.04819915451194, 56.783976249284365], + [-5.04819992883291, 56.78397856053853], + [-5.048201811977156, 56.783984819805234], + [-5.048202354923839, 56.78398580212361], + [-5.048202646491, 56.78398667241579], + [-5.048204326696695, 56.783989369524555], + [-5.048206783389565, 56.783993814258835], + [-5.048208055780578, 56.78399535554302], + [-5.048208893490106, 56.783996700254974], + [-5.048211100819502, 56.78399904408648], + [-5.048213851099418, 56.78400237557916], + [-5.048216145263805, 56.78400440047995], + [-5.048217759623993, 56.784006114672046], + [-5.048770458734618, 56.78449991516997], + [-5.048779728400123, 56.78450715585577], + [-5.048790549292018, 56.78451371618296], + [-5.048802757282811, 56.78451949664642], + [-5.049360943983058, 56.78475249128862], + [-5.049757930572188, 56.78491828582567], + [-5.049771261281642, 56.78492317591164], + [-5.049785581108873, 56.7849271348274], + [-5.051172016201057, 56.78525364317051], + [-5.051440962795205, 56.78531693014778], + [-5.052328666952865, 56.78584283617055], + [-5.052346919319733, 56.78585179918145], + [-5.052668341727795, 56.78598210836673], + [-5.053246042149018, 56.786216208722024], + [-5.053251405830547, 56.78621827048006], + [-5.054617314004347, 56.786715827890596], + [-5.054809274121202, 56.787213225308285], + [-5.054698855868834, 56.78776667844323], + [-5.054698084822023, 56.78777523656595], + [-5.054699175330116, 56.787783784216], + [-5.054854698360472, 56.788438884688986], + [-5.05490572683024, 56.78881946942477], + [-5.05493552550569, 56.789042065303796], + [-5.054938095439817, 56.789051896077304], + [-5.054943110598742, 56.78906143847741], + [-5.055321809000603, 56.78963083886015], + [-5.05532428204027, 56.789634279568425], + [-5.055494381238994, 56.789854179437675], + [-5.055635780527663, 56.790036979270525], + [-5.055644742257239, 56.79004651495212], + [-5.055656191227153, 56.79005521199068], + [-5.055923320907867, 56.79022913304563], + [-5.0558842, 56.790244599999966], + [-5.056112946043207, 56.790352591605306], + [-5.056305813426518, 56.79047815994251], + [-5.056342445683901, 56.79050454202945], + [-5.0563681, 56.790524899999966], + [-5.056374880239901, 56.79052790094474], + [-5.056462391796525, 56.79059092535902], + [-5.056555818468024, 56.79078644080464], + [-5.0565517, 56.79081129999999], + [-5.0565517, 56.790933099999975], + [-5.0568262, 56.79138029999996], + [-5.05707, 56.791666799999966], + [-5.0571802, 56.791757299999944], + [-5.0573454, 56.79189079999998], + [-5.0574201, 56.79190809999997], + [-5.0574919, 56.791905699999965], + [-5.0575538, 56.791921], + [-5.057605, 56.7919124], + [-5.0576609, 56.79188429999997], + [-5.0576605, 56.791839], + [-5.057679230391617, 56.79180675249511], + [-5.057746953778136, 56.79178085635096], + [-5.057761375470753, 56.791774463977006], + [-5.05777400758786, 56.79176701793309], + [-5.057784596913017, 56.79175866747913], + [-5.057876923474196, 56.7916735891097], + [-5.058298171322838, 56.791458309935784], + [-5.05853948864883, 56.79135399135283], + [-5.058622612064148, 56.791336729338234], + [-5.0587614, 56.79135659999996], + [-5.058809171057008, 56.7913800059129], + [-5.058912929316837, 56.79153883529996], + [-5.058967605005468, 56.79175100667762], + [-5.059025395205642, 56.79205964702162], + [-5.058950345697522, 56.79237777422629], + [-5.05894926356118, 56.79238735378415], + [-5.058950782322862, 56.79255666688042], + [-5.0588983, 56.792658099999976], + [-5.0589159, 56.79287339999996], + [-5.0589992, 56.79309149999995], + [-5.0589602, 56.79331719999997], + [-5.0589764, 56.79341569999998], + [-5.0592242, 56.79374219999997], + [-5.059260276767664, 56.79377175824539], + [-5.05928981506814, 56.79381804824424], + [-5.059295380333332, 56.793825426974415], + [-5.059302403267853, 56.793832421254415], + [-5.059310797131696, 56.79383894469735], + [-5.059469797940468, 56.793948985405294], + [-5.059557295211276, 56.79403365503241], + [-5.0598665, 56.79445179999996], + [-5.0598997, 56.79449409999997], + [-5.060657347046678, 56.794982064082646], + [-5.060674416356393, 56.79499533510432], + [-5.060684305821487, 56.795002114041345], + [-5.060695613229276, 56.7950081888731], + [-5.06070223432766, 56.79501097327642], + [-5.0607133, 56.79501809999997], + [-5.0611689, 56.7952944], + [-5.0614169, 56.795423199999966], + [-5.0615187, 56.79546559999997], + [-5.0618895, 56.795571099999975], + [-5.0622467, 56.795654499999955], + [-5.0625795, 56.79571819999997], + [-5.0626968, 56.79575129999997], + [-5.0627399, 56.795777199999975], + [-5.0628913, 56.79592629999997], + [-5.063099729859053, 56.79604519269657], + [-5.063114685124376, 56.796056634476116], + [-5.06363877432231, 56.79648312784175], + [-5.063670915883596, 56.7966324980781], + [-5.0636267, 56.79670819999996], + [-5.063625, 56.796743699999965], + [-5.063630951378125, 56.79677910742796], + [-5.063573428579678, 56.7969009851488], + [-5.063572115086645, 56.7969040418793], + [-5.063502270686251, 56.797084112265715], + [-5.0634933, 56.797090899999944], + [-5.0634186, 56.79722439999996], + [-5.0633556, 56.7973084], + [-5.0633291, 56.7973747], + [-5.0633945, 56.7975], + [-5.0635941, 56.797913499999964], + [-5.06366136152693, 56.797979378080626], + [-5.063693933385671, 56.79805010439076], + [-5.063698564827959, 56.798058142523644], + [-5.063704880134638, 56.79806582770508], + [-5.063712792380572, 56.7980730541535], + [-5.063722192659599, 56.79807972240142], + [-5.064262001302243, 56.79841942838794], + [-5.0644060012506, 56.79851002850163], + [-5.064416802798192, 56.79851606660646], + [-5.064428822965484, 56.79852136621768], + [-5.064981323407518, 56.79873686654881], + [-5.06498533420564, 56.79873837027412], + [-5.065225703306525, 56.79882494500756], + [-5.0656725, 56.798996099999954], + [-5.066026605450785, 56.79915350852219], + [-5.066299682464358, 56.79936756368276], + [-5.0666183, 56.799651699999956], + [-5.0668297, 56.79999989999999], + [-5.0669763, 56.800116], + [-5.067048146780964, 56.800209062543885], + [-5.067121965496018, 56.80034982826676], + [-5.0671456, 56.80041069999998], + [-5.067215044051697, 56.80052731918506], + [-5.067303539542217, 56.80069606902236], + [-5.067308345040403, 56.80070362195112], + [-5.067314650996707, 56.800710834990156], + [-5.067338471207105, 56.800734591659555], + [-5.067367, 56.80078249999998], + [-5.0675088, 56.80091379999996], + [-5.06753839316311, 56.80093397893352], + [-5.067576050452532, 56.80097153523316], + [-5.067582617258695, 56.800977400413714], + [-5.068074768112272, 56.80137312331462], + [-5.06815, 56.801450399999986], + [-5.0684195, 56.80172729999998], + [-5.0685702, 56.801907199999974], + [-5.0687165, 56.802033], + [-5.0687712, 56.802100899999964], + [-5.0688205, 56.802203], + [-5.0688988, 56.8022595], + [-5.0689218, 56.80229939999998], + [-5.0690105, 56.802382599999966], + [-5.0691134, 56.80251939999995], + [-5.0692419, 56.80264839999998], + [-5.0693444, 56.8027733], + [-5.0694913, 56.80295239999997], + [-5.0697146, 56.803159], + [-5.0697674, 56.803223299999964], + [-5.0698463, 56.80340649999997], + [-5.0701487, 56.8037793], + [-5.070172, 56.80386319999998], + [-5.0703764, 56.80415929999998], + [-5.0704691, 56.804370099999986], + [-5.0709194, 56.80498819999998], + [-5.0710295, 56.80511219999998], + [-5.0712731, 56.80522329999996], + [-5.0714898, 56.80535079999997], + [-5.072206, 56.805612699999976], + [-5.0723789, 56.80568389999996], + [-5.0725285, 56.80572969999997], + [-5.0727688, 56.8057822], + [-5.0728901, 56.80580339999997], + [-5.0731145, 56.805822199999966], + [-5.073259548521571, 56.80584164308395], + [-5.073367323927089, 56.80586298686416], + [-5.073377319000957, 56.805864721598844], + [-5.074034166716566, 56.80596304422003], + [-5.0740621423819, 56.805970249168006], + [-5.074499243396785, 56.80612644265136], + [-5.075102414141387, 56.80637116514891], + [-5.075475256108104, 56.806580056595344], + [-5.076023513526231, 56.807038979725284], + [-5.0763621, 56.80750119999997], + [-5.0765058, 56.80767469999998], + [-5.0766237, 56.80778249999998], + [-5.0766932, 56.80792089999996], + [-5.0767824, 56.80805139999997], + [-5.0768095, 56.808125599999954], + [-5.076821, 56.8082234], + [-5.0768728, 56.8082826], + [-5.0769239, 56.80839729999997], + [-5.0769811, 56.808488099999984], + [-5.0769929, 56.8086541], + [-5.0769364, 56.80885], + [-5.076784787492785, 56.80910022534516], + [-5.076510307792257, 56.80950028567876], + [-5.0764816, 56.8095249], + [-5.076435, 56.809556], + [-5.0763439, 56.80959409999998], + [-5.076316, 56.80962689999996], + [-5.0762096, 56.80974869999997], + [-5.0761356, 56.8098744], + [-5.0760289, 56.8100072], + [-5.075949, 56.81011189999999], + [-5.0758929, 56.8102317], + [-5.0759225, 56.810345699999985], + [-5.0759056, 56.81041619999998], + [-5.0758658, 56.810457799999966], + [-5.0758008, 56.81062059999997], + [-5.0757155, 56.810697199999986], + [-5.0756864, 56.8107647], + [-5.075694456871266, 56.81095775237792], + [-5.075668679041583, 56.811035050719845], + [-5.0756196, 56.81107629999998], + [-5.0755706, 56.811058699999975], + [-5.0755304, 56.81107249999999], + [-5.0755087, 56.81103739999997], + [-5.0754988, 56.81095889999999], + [-5.0754806, 56.8109261], + [-5.0754501, 56.81091569999997], + [-5.0754043, 56.8109436], + [-5.07532, 56.8110585], + [-5.0752694, 56.811278599999945], + [-5.0752788, 56.81133409999996], + [-5.075315, 56.811343], + [-5.0753295, 56.81136439999997], + [-5.0752973, 56.81149769999998], + [-5.0752971, 56.81158709999997], + [-5.0753136, 56.81164149999997], + [-5.0756078, 56.81200929999997], + [-5.075638, 56.81205379999996], + [-5.0758445, 56.81224119999998], + [-5.075871678565633, 56.81218733950714], + [-5.075880768369225, 56.81219632773172], + [-5.076151908325035, 56.81256024045391], + [-5.076222009240063, 56.812795298729085], + [-5.076350892123785, 56.813227522070115], + [-5.076400108731193, 56.81379794799158], + [-5.076303225998736, 56.8141402304768], + [-5.075850863082588, 56.81506447055261], + [-5.075847683819908, 56.81507300046135], + [-5.075846408862165, 56.815081678637945], + [-5.075841008339635, 56.815231378636035], + [-5.075841553502018, 56.81523950016853], + [-5.075843767340653, 56.81524753599317], + [-5.075847621537082, 56.81525538331528], + [-5.076172019966671, 56.81579278364812], + [-5.076179508356363, 56.815802657042454], + [-5.076189585546753, 56.815811811612626], + [-5.07673188497837, 56.81623051207843], + [-5.076742704635766, 56.81623780370603], + [-5.076755167426731, 56.816244258261364], + [-5.077536884887427, 56.81659903967925], + [-5.078055880771903, 56.81700289941917], + [-5.079053362627056, 56.817869595557696], + [-5.079844695524088, 56.8189143755296], + [-5.079813441011627, 56.81942810405679], + [-5.079813388865646, 56.81942922227376], + [-5.079807117335942, 56.81962259217873], + [-5.0797536, 56.819685], + [-5.0797376, 56.81968989999998], + [-5.0797499, 56.8196995], + [-5.079804525098718, 56.81970251818767], + [-5.079801787616651, 56.81978692227056], + [-5.079801924145179, 56.81978839102829], + [-5.0797872, 56.819814599999965], + [-5.0797558, 56.819831499999985], + [-5.079759, 56.81984839999995], + [-5.0797905, 56.8198747], + [-5.0797174, 56.819943], + [-5.0797266, 56.820074], + [-5.0797571, 56.820147], + [-5.0798064, 56.82019129999996], + [-5.0797808, 56.820250799999954], + [-5.0797868, 56.820283099999976], + [-5.0798659, 56.82042119999995], + [-5.0798793, 56.82052419999999], + [-5.0799331, 56.82056149999995], + [-5.0801321, 56.82062939999997], + [-5.080215, 56.8206399], + [-5.0802523, 56.820675], + [-5.0804414, 56.820738199999965], + [-5.0807451, 56.82082629999996], + [-5.0807099, 56.8208462], + [-5.080595, 56.8208657], + [-5.0805053, 56.820895399999976], + [-5.0804674, 56.820922899999964], + [-5.0805194, 56.82094159999997], + [-5.0805758, 56.820904], + [-5.08066, 56.820875299999976], + [-5.0807475, 56.820862599999984], + [-5.0808018, 56.820837499999975], + [-5.0809123, 56.82086419999995], + [-5.0811938, 56.82091359999997], + [-5.0813255, 56.82092119999998], + [-5.0814572, 56.820908], + [-5.081482, 56.820911], + [-5.0815494, 56.82095249999997], + [-5.0818038, 56.82101019999997], + [-5.081880925099665, 56.821020475197784], + [-5.082081284760894, 56.8210893731434], + [-5.082117, 56.82113159999999], + [-5.0822752, 56.82120809999997], + [-5.0824719, 56.821265699999984], + [-5.0826933, 56.82130459999996], + [-5.0828028, 56.82135], + [-5.0828781, 56.821363], + [-5.0831054, 56.821366], + [-5.0832286, 56.82138759999997], + [-5.0836266, 56.82139809999997], + [-5.0836644, 56.82140519999997], + [-5.083799, 56.82140529999998], + [-5.0842168, 56.82144259999996], + [-5.0844225050718475, 56.82145112888207], + [-5.0844225050718475, 56.82118935427821] + ] + ], + [ + [ + [-5.0844225050718475, 56.832621492171256], + [-5.0843141, 56.83263489999997], + [-5.0835698, 56.83265639999997], + [-5.0834655, 56.832680299999964], + [-5.0828692, 56.83274349999998], + [-5.0828112, 56.8327434], + [-5.0827731, 56.83272469999997], + [-5.0827228, 56.83273269999997], + [-5.0826786, 56.832753599999954], + [-5.0825515, 56.83274419999995], + [-5.0823024, 56.83274579999997], + [-5.0820384, 56.832765799999976], + [-5.0819758, 56.832762], + [-5.0819236, 56.832745299999964], + [-5.0818978, 56.83275039999997], + [-5.081827, 56.8327872], + [-5.0818004, 56.832782499999944], + [-5.0817711, 56.83276529999996], + [-5.0816977, 56.83275], + [-5.0815713, 56.8327477], + [-5.0808636, 56.832691899999965], + [-5.080459, 56.832719599999955], + [-5.0803587, 56.8327417], + [-5.0802846, 56.83276839999994], + [-5.0802252, 56.83277729999996], + [-5.0801564, 56.832776199999984], + [-5.0800842, 56.8327753], + [-5.0799201, 56.832793699999954], + [-5.0795527, 56.832892699999974], + [-5.0791712883983875, 56.83302498513894], + [-5.0844225050718475, 56.83302498513894], + [-5.0844225050718475, 56.832621492171256] + ], + [ + [-5.051379858375106, 56.78514618835705], + [-5.051373401463104, 56.7850475033589], + [-5.051301226452125, 56.78492049694643], + [-5.051297340670326, 56.784911775258664], + [-5.051295466805563, 56.78490285566966], + [-5.051295634113581, 56.78489387744342], + [-5.051297839980689, 56.78488498075939], + [-5.051334580273318, 56.78478434939144], + [-5.051344437848347, 56.78466597464513], + [-5.05126234554798, 56.78446088128153], + [-5.051175779914012, 56.78435106618435], + [-5.050969364440095, 56.78426368098362], + [-5.050780086442988, 56.78421188848845], + [-5.050390179593937, 56.78418655658689], + [-5.049994399615806, 56.78418655657996], + [-5.049987563202976, 56.78418645851914], + [-5.049036661389644, 56.78415915848006], + [-5.049020918064802, 56.78415817942333], + [-5.04900550553014, 56.78415616356193], + [-5.048621418931659, 56.78409222143322], + [-5.048980727048144, 56.784413236504776], + [-5.049519442101911, 56.784638102954275], + [-5.049903636793424, 56.78479855495112], + [-5.051275200148113, 56.78512156069807], + [-5.051379858375106, 56.78514618835705] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [-5.0844225050718475, 56.76993147270265], + [-5.02639658883008, 56.76993147270265], + [-5.02639658883008, 56.83302498513894], + [-5.0844225050718475, 56.83302498513894], + [-5.0844225050718475, 56.76993147270265] + ] + ], + "type": "Polygon" + }, + "properties": {}, + "type": "Feature" + }, + { + "geometry": { + "coordinates": [ + [ + [ + [-5.0844225050718475, 56.82118935427821], + [-5.0838535, 56.8211702], + [-5.0837353, 56.82118289999995], + [-5.0836972, 56.8211822], + [-5.0834868, 56.821172399999966], + [-5.083281, 56.82114969999998], + [-5.0830782, 56.82115089999998], + [-5.0829664, 56.821141], + [-5.0826849, 56.8210829], + [-5.0823903, 56.82098249999996], + [-5.0819432, 56.82075849999996], + [-5.0818217, 56.82067609999997], + [-5.0817477, 56.820652799999976], + [-5.0817043, 56.82060349999996], + [-5.0814518, 56.820471599999976], + [-5.0812101, 56.82039219999997], + [-5.0810824, 56.820378], + [-5.0809574, 56.82034929999998], + [-5.0808115, 56.8203196], + [-5.0805575, 56.82024639999997], + [-5.080352473426072, 56.82015402319541], + [-5.080064299546843, 56.819774453961585], + [-5.080066535257358, 56.81970550600799], + [-5.0801541, 56.819691299999974], + [-5.0801798, 56.819684399999964], + [-5.0801898, 56.81966709999998], + [-5.0801832, 56.81964659999996], + [-5.0801599, 56.819642699999974], + [-5.0800769, 56.819669], + [-5.080067749805464, 56.81966805001485], + [-5.080075393006905, 56.8194323368084], + [-5.080107557155173, 56.818903595785166], + [-5.080106852393738, 56.8188933833134], + [-5.080103512847632, 56.81888332896133], + [-5.080097606072239, 56.81887363611132], + [-5.079291103268355, 56.817808836909244], + [-5.079280900995247, 56.81779804666472], + [-5.078275699486228, 56.81692464756334], + [-5.07827199725973, 56.8169216051043], + [-5.077740996687888, 56.81650840556168], + [-5.077730060823799, 56.81650099371128], + [-5.077717431932552, 56.816494441157275], + [-5.076935523766095, 56.81613957407178], + [-5.076414600327056, 56.81573737941062], + [-5.076103435787177, 56.81522190806761], + [-5.076108075441466, 56.815093274083374], + [-5.076558134115263, 56.81417372888078], + [-5.076561062833359, 56.81416612288394], + [-5.076661061639212, 56.813812822789224], + [-5.076662425824648, 56.81380563237591], + [-5.076662465809871, 56.81379840317256], + [-5.076612263788466, 56.81321660323931], + [-5.076610692399389, 56.813208401885674], + [-5.076480590405791, 56.81277210022826], + [-5.076408089594414, 56.81252900030875], + [-5.07640488357897, 56.81252108447643], + [-5.076400071933539, 56.81251341716845], + [-5.076120370936136, 56.81213801744596], + [-5.076113662251077, 56.81213034512128], + [-5.075971415002954, 56.81198968778768], + [-5.0759814, 56.811969899999966], + [-5.0759015, 56.81186879999997], + [-5.0757877, 56.81171189999996], + [-5.0757683, 56.811640699999955], + [-5.0757321, 56.811575499999954], + [-5.075721, 56.811358399999975], + [-5.0757828, 56.8113047], + [-5.0758658, 56.811215], + [-5.0758906, 56.81114059999997], + [-5.0759846, 56.810983799999974], + [-5.0760084, 56.81085409999997], + [-5.076000725481171, 56.81083805328089], + [-5.076003746657344, 56.81082899359518], + [-5.0760522, 56.810788299999984], + [-5.0760649, 56.81071969999996], + [-5.07613587706682, 56.81052279588375], + [-5.076474740835754, 56.8099681792691], + [-5.0765026, 56.80993269999998], + [-5.0765628, 56.80987849999998], + [-5.0767629, 56.809711299999975], + [-5.0768278, 56.8096175], + [-5.0768813, 56.809526499999954], + [-5.0768973, 56.80946819999998], + [-5.0769328, 56.80942689999996], + [-5.076952628335087, 56.80926360225266], + [-5.076989842982081, 56.80920936020085], + [-5.0770991, 56.809109], + [-5.0771592, 56.80903659999996], + [-5.077144635936648, 56.808983740609996], + [-5.077150900745453, 56.80897460923242], + [-5.077155759194521, 56.80896588309476], + [-5.077176351361956, 56.80891825936254], + [-5.0772776, 56.80885029999998], + [-5.0773146, 56.80878189999998], + [-5.0773107, 56.808734399999985], + [-5.077281234166157, 56.80867569386844], + [-5.07733035789224, 56.80856208292662], + [-5.07733334468683, 56.80855207326558], + [-5.077333732386435, 56.8085419326344], + [-5.077331513268288, 56.808531863083815], + [-5.077269926977104, 56.8083570890335], + [-5.077267, 56.808241099999975], + [-5.077221, 56.80814679999999], + [-5.0771487, 56.80792959999997], + [-5.0770781, 56.807787899999965], + [-5.0769818, 56.80762519999995], + [-5.0769008, 56.807536399999975], + [-5.0761416, 56.8067902], + [-5.0760064, 56.806660499999964], + [-5.075947, 56.806616099999985], + [-5.0757464, 56.806487199999985], + [-5.0755538, 56.8063957], + [-5.0754592, 56.806362099999966], + [-5.075408378251169, 56.80633717067541], + [-5.075282292797596, 56.80626652880195], + [-5.075266588105093, 56.80625902775082], + [-5.07516528747315, 56.80621792788577], + [-5.075058, 56.806165299999975], + [-5.0745412, 56.805937099999966], + [-5.0744035, 56.80589559999997], + [-5.074217680509599, 56.80585431710212], + [-5.074173392494825, 56.80583849111142], + [-5.074155533130106, 56.80583314377629], + [-5.074140985640383, 56.805830283741145], + [-5.0741284, 56.8058179], + [-5.0735492, 56.8057288], + [-5.073469533955619, 56.805729559181046], + [-5.073451341717011, 56.80572683595746], + [-5.073277843074884, 56.805692476328595], + [-5.0732691, 56.805688899999986], + [-5.0732026, 56.80567709999998], + [-5.07320057173734, 56.80567717343334], + [-5.073078576512948, 56.80565301325009], + [-5.073078148002581, 56.80565292884826], + [-5.072726495704795, 56.80558404305916], + [-5.072459731350001, 56.805516622896405], + [-5.072385498378591, 56.80549295709813], + [-5.072047135153812, 56.80536725949438], + [-5.071743310874293, 56.805219178664515], + [-5.0714697, 56.805025], + [-5.0711059, 56.80472379999996], + [-5.0710573, 56.80465039999997], + [-5.0710473, 56.80460839999997], + [-5.0710152, 56.80455709999998], + [-5.0708008, 56.80427919999997], + [-5.0702227, 56.80336219999995], + [-5.0700235, 56.80311], + [-5.0698687, 56.802880199999954], + [-5.0696916, 56.802658], + [-5.0695335, 56.802547699999955], + [-5.069544, 56.802516], + [-5.0690218, 56.80197969999995], + [-5.0685784, 56.80150609999998], + [-5.0683886, 56.801349499999986], + [-5.0682417, 56.801209699999966], + [-5.067800957551483, 56.8008976852266], + [-5.067551209684683, 56.800648606926494], + [-5.067379197734261, 56.800320604183895], + [-5.0673164, 56.80016349999995], + [-5.067250297641417, 56.80007480571355], + [-5.067157858011309, 56.799898531266734], + [-5.067148412949355, 56.79988548155604], + [-5.067096863685227, 56.79983060224214], + [-5.0670653, 56.79978009999997], + [-5.0668036, 56.79939709999998], + [-5.0664568, 56.79910939999997], + [-5.066092, 56.79894779999997], + [-5.065790861693006, 56.79885686120155], + [-5.065784864950974, 56.798854429314076], + [-5.065131096379549, 56.798618961134835], + [-5.064593210510688, 56.79840916150834], + [-5.064459402855822, 56.79832497430791], + [-5.064078373324219, 56.7980851909765], + [-5.0639455, 56.79798709999998], + [-5.063921346244208, 56.79795731045964], + [-5.063714604747818, 56.79750839369863], + [-5.063689036070978, 56.79736225573366], + [-5.06369, 56.797361199999976], + [-5.0637241, 56.79731149999998], + [-5.0637619, 56.79712729999996], + [-5.0637997, 56.797042399999974], + [-5.0638299, 56.796951399999955], + [-5.063840545777511, 56.79690825365828], + [-5.063871112516328, 56.796843488764075], + [-5.0639093, 56.796789899999986], + [-5.063932, 56.79671749999997], + [-5.0639698, 56.79664289999998], + [-5.0639773, 56.79653939999994], + [-5.0639055, 56.79642969999995], + [-5.0638034, 56.79631589999997], + [-5.063623328360122, 56.79621350284332], + [-5.063330773953526, 56.79597542748944], + [-5.063328610315422, 56.79597372055465], + [-5.062912309893991, 56.79565522091085], + [-5.062900300053392, 56.79564730001357], + [-5.062886349109989, 56.79564040313278], + [-5.062870743931184, 56.795634672085676], + [-5.062794520457557, 56.795610832288475], + [-5.0627904, 56.795607899999965], + [-5.0626619, 56.79556029999998], + [-5.062596244726551, 56.79554881883488], + [-5.061970617563441, 56.795353141928594], + [-5.061829665075179, 56.79528707942135], + [-5.061732, 56.795220799999974], + [-5.0614863, 56.79509249999998], + [-5.0614006, 56.7950526], + [-5.0612103, 56.79497859999998], + [-5.0610742, 56.79491029999998], + [-5.0609117, 56.794837799999975], + [-5.0607983, 56.794790199999966], + [-5.0606547, 56.7947033], + [-5.060472294716802, 56.79458896281343], + [-5.060196366913685, 56.79437442967579], + [-5.059938431132121, 56.7941111723512], + [-5.059937003483922, 56.79410975382291], + [-5.059692603007896, 56.793873254048236], + [-5.059681302733298, 56.793864055083624], + [-5.059529699068083, 56.793759134204265], + [-5.059448529659369, 56.793631933095426], + [-5.059328739775509, 56.793414152188944], + [-5.05930995647021, 56.79331564447932], + [-5.059308, 56.79326369999996], + [-5.059212275682353, 56.79251355245305], + [-5.05921117960946, 56.79239145573188], + [-5.05928705325, 56.792069825566166], + [-5.059288125524903, 56.792061546483055], + [-5.059287450985335, 56.79205325477282], + [-5.059227849896295, 56.79173495484243], + [-5.059227245654561, 56.791732237848834], + [-5.05917034491058, 56.79151143791297], + [-5.059167808115607, 56.79150425444858], + [-5.059163953297503, 56.79149724980947], + [-5.05903715274842, 56.791303149937924], + [-5.059030289602089, 56.79129448476168], + [-5.059021414141305, 56.79128638867432], + [-5.059010679819252, 56.79127900165282], + [-5.058976409658929, 56.7912583623708], + [-5.0588789, 56.79111249999996], + [-5.0587957, 56.79109659999998], + [-5.0587182, 56.791105], + [-5.0586901, 56.79110809999995], + [-5.0585872, 56.791151099999965], + [-5.058494824635421, 56.7912096088545], + [-5.058427960873987, 56.791223494243475], + [-5.058409870339997, 56.791228145299016], + [-5.058393279672446, 56.79123425257887], + [-5.058131879813535, 56.79134725240899], + [-5.058123668828177, 56.79135111382938], + [-5.057684768895031, 56.79157541351664], + [-5.05767211168842, 56.79158286921267], + [-5.057661503491429, 56.7915912325077], + [-5.057575774094469, 56.79167023124861], + [-5.0575512, 56.79166839999998], + [-5.0574907, 56.79163729999996], + [-5.0573093, 56.79150689999995], + [-5.0572035, 56.79139919999999], + [-5.057119464767872, 56.791320843978156], + [-5.057101738752526, 56.791296905563634], + [-5.0571049, 56.79123069999997], + [-5.0570386, 56.7911325], + [-5.0569804, 56.791003799999956], + [-5.056928, 56.79093369999997], + [-5.0566955, 56.79050019999996], + [-5.0566524, 56.790447099999966], + [-5.056499422840998, 56.79038123234917], + [-5.055869115150336, 56.78997086089894], + [-5.055735418347902, 56.78979802014871], + [-5.055566635008775, 56.78957982319612], + [-5.055195338853872, 56.78902155821231], + [-5.055166872572557, 56.788808926281845], + [-5.055115571252607, 56.78842632634459], + [-5.055114826826991, 56.78842231547202], + [-5.054960852611891, 56.78777375802082], + [-5.055071842243443, 56.787217421317266], + [-5.055072457510139, 56.7872060202266], + [-5.055069778134389, 56.78719470933569], + [-5.054862376394724, 56.786657309559814], + [-5.054857806674836, 56.7866483658985], + [-5.054851173155182, 56.786639820507105], + [-5.054842586683363, 56.78663181617936], + [-5.054832190740584, 56.786624486667556], + [-5.054820159044032, 56.786617954447934], + [-5.05480669264402, 56.78661232867379], + [-5.053398922762203, 56.78609952353009], + [-5.052823869112232, 56.78586649607518], + [-5.052512373696763, 56.78574021165627], + [-5.051647183424055, 56.785227645199754], + [-5.051634428229315, 56.78503272084079], + [-5.051632644620956, 56.78502320465459], + [-5.051628573808174, 56.78501390284921], + [-5.051561130117941, 56.78489522361774], + [-5.05159325976338, 56.78480721907061], + [-5.051595675226743, 56.78479638084742], + [-5.051606774763253, 56.78466308083912], + [-5.051606435304696, 56.784653678102615], + [-5.051603861547536, 56.78464438023261], + [-5.051515360835772, 56.784423280327886], + [-5.051507645690004, 56.784410164864035], + [-5.051402645348595, 56.78427696496709], + [-5.051395135608862, 56.784268881115736], + [-5.05138582967021, 56.78426138122732], + [-5.051374875935312, 56.784254584902364], + [-5.051362449083946, 56.78424860052176], + [-5.051119149240513, 56.78414560067578], + [-5.05109760437492, 56.784138191121066], + [-5.050876504664123, 56.78407769122202], + [-5.050862689931641, 56.78407444029466], + [-5.050848287363703, 56.784072080019726], + [-5.050833486831478, 56.784070641513146], + [-5.050413287620675, 56.78404334155912], + [-5.05039789961582, 56.784042843424665], + [-5.049997820914563, 56.78404284342474], + [-5.049066248466787, 56.78401609834609], + [-5.048450112170306, 56.78391352419519], + [-5.048329843193051, 56.78330495073044], + [-5.048326684289387, 56.78329524192849], + [-5.048321133262226, 56.78328586200232], + [-5.04784693153339, 56.78263936247374], + [-5.04783890516812, 56.78263030846943], + [-5.046916303437762, 56.781751909316036], + [-5.046915413585923, 56.78175107509339], + [-5.046014212013696, 56.78091907591312], + [-5.046005070697779, 56.780911716562905], + [-5.045994340971041, 56.78090503460811], + [-5.044627235608612, 56.780153211771385], + [-5.043682004451961, 56.778802860261585], + [-5.04396962010656, 56.778227720915815], + [-5.044219946111421, 56.77772706567761], + [-5.045108976317644, 56.77697484521091], + [-5.046031634053867, 56.776249817571006], + [-5.046670416790827, 56.776303722689214], + [-5.046687645573158, 56.776304541930514], + [-5.046704920696494, 56.77630410695737], + [-5.046721940571063, 56.77630242536353], + [-5.04713354128229, 56.776246125254644], + [-5.04714907361037, 56.776243426984344], + [-5.047163875044285, 56.776239690221416], + [-5.047177716255251, 56.77623497286219], + [-5.047190382792116, 56.77622934799597], + [-5.047201678404027, 56.77622290277277], + [-5.047211428081086, 56.776215737052816], + [-5.047696727382215, 56.775808436633774], + [-5.047704857746765, 56.775800573819254], + [-5.047711125294253, 56.775792212696956], + [-5.047715430795, 56.77578348564441], + [-5.047717706083597, 56.775774530832585], + [-5.047787104344933, 56.775271830772574], + [-5.047787114515391, 56.77526104354609], + [-5.047784183356109, 56.775250377036436], + [-5.04748088102908, 56.77452237736149], + [-5.047477030932942, 56.774514982084774], + [-5.047471763214956, 56.77450785511505], + [-5.046963728019259, 56.77391389129399], + [-5.04663308896715, 56.773362698822034], + [-5.04656069293501, 56.772898667148255], + [-5.046559288425677, 56.77289265752792], + [-5.046421086958397, 56.77245005768046], + [-5.046416584587734, 56.772440030347134], + [-5.046409510775885, 56.772430460967556], + [-5.046169210152349, 56.77216246119697], + [-5.046163386553889, 56.77215665789507], + [-5.045802385969291, 56.771833158220524], + [-5.045791528573977, 56.771824826483304], + [-5.04577862362996, 56.77181742723784], + [-5.045763933462056, 56.771811110891434], + [-5.045747756683539, 56.771806005838776], + [-5.045730422126136, 56.77180221585212], + [-5.045404222665225, 56.7717453159514], + [-5.045390008014714, 56.771743310553894], + [-5.045375473807582, 56.771742191705385], + [-5.045360802840538, 56.77174197347766], + [-5.044758403989612, 56.771751573451326], + [-5.044756432897056, 56.77175161302337], + [-5.044314633738066, 56.77176231299712], + [-5.044291408362242, 56.77176402868762], + [-5.043456954175049, 56.771868116442874], + [-5.042500006201438, 56.7718013772788], + [-5.041351720463965, 56.77161039251483], + [-5.040803582341719, 56.77151721595063], + [-5.04033291988711, 56.771396404738596], + [-5.040319101159831, 56.7713933705997], + [-5.039825901960779, 56.771302570757754], + [-5.03980528103558, 56.77129977267055], + [-5.039493581610555, 56.77127197271865], + [-5.039477918654264, 56.771271102509836], + [-5.039091289181199, 56.77126246662606], + [-5.038728319759183, 56.77124557529982], + [-5.038487144386079, 56.77121760664362], + [-5.03836516464192, 56.77116833109147], + [-5.038254561705084, 56.77108395288377], + [-5.038090106639766, 56.77088952217539], + [-5.0379813477199, 56.77041267071711], + [-5.03797749388615, 56.77040218309272], + [-5.037970846881517, 56.77039212592545], + [-5.037860846546339, 56.77025782603252], + [-5.037853766822706, 56.770250379403365], + [-5.037845152823503, 56.77024343734495], + [-5.037835122271261, 56.77023709472969], + [-5.037699422267213, 56.77016079483108], + [-5.037687169496897, 56.77015472339523], + [-5.037673622463826, 56.77014954709781], + [-5.037658996647449, 56.77014534827291], + [-5.037643524686095, 56.770142193706974], + [-5.037458424996744, 56.770111593760504], + [-5.037443762860107, 56.77010966784906], + [-5.037428794632018, 56.77010868070171], + [-5.037413718971525, 56.77010864541983], + [-5.037398735963513, 56.7701095624718], + [-5.037219036290796, 56.77012636243805], + [-5.037202199010498, 56.77012857440839], + [-5.037186040835524, 56.77013198748685], + [-5.036985341104968, 56.77018298739695], + [-5.036977987192591, 56.77018518749714], + [-5.036970622003041, 56.77018737619988], + [-5.0369704722437, 56.77018743577455], + [-5.036970309853309, 56.77018748435752], + [-5.036963541827739, 56.77019019271204], + [-5.036956759916273, 56.77019289057328], + [-5.036956625599425, 56.77019296037193], + [-5.036956476146658, 56.770193020178255], + [-5.036950409812859, 56.77019619044584], + [-5.036944327217214, 56.770199351305386], + [-5.036852337238845, 56.77025384528489], + [-5.036785398322123, 56.7702934811466], + [-5.036671581136191, 56.770319522285654], + [-5.03660749054709, 56.77031971629849], + [-5.036533518855928, 56.7703141973479], + [-5.036517994584214, 56.77031355229406], + [-5.036502440666002, 56.77031392416586], + [-5.036487077249141, 56.77031530769984], + [-5.036472121785205, 56.77031768331372], + [-5.036163935479264, 56.77037775686831], + [-5.035483930506816, 56.770488778107236], + [-5.034710747629625, 56.77049426369205], + [-5.033750913309432, 56.77040348584927], + [-5.033739048668949, 56.77040266809259], + [-5.033309165228711, 56.770383941649236], + [-5.033162952842571, 56.770322661478545], + [-5.032745753120217, 56.770147961740655], + [-5.032730637805079, 56.77014249644737], + [-5.032714293848013, 56.77013822854273], + [-5.032697033851368, 56.77013523965664], + [-5.031978535117203, 56.770040239823324], + [-5.03196249566122, 56.77003869138097], + [-5.031946230156653, 56.770038248875046], + [-5.031228163485361, 56.77004327861562], + [-5.030778998533689, 56.77000844898548], + [-5.030757941203743, 56.77000775897847], + [-5.030281865714793, 56.770013270472546], + [-5.029901937432302, 56.76993583402815], + [-5.029884563621346, 56.769933026896986], + [-5.029866650398643, 56.76993156378089], + [-5.029848540852238, 56.76993147270265], + [-5.029612441300336, 56.7699392726847], + [-5.029594601448172, 56.7699405422159], + [-5.029577247224947, 56.76994314320245], + [-5.029324247622088, 56.76999154311278], + [-5.029301923585764, 56.76999715288565], + [-5.028803624124256, 56.770154952622036], + [-5.028791507973671, 56.77015929659929], + [-5.027678490918634, 56.770608413683675], + [-5.027265627452971, 56.77069587910747], + [-5.02639658883008, 56.77081187518612], + [-5.02639658883008, 56.7709597742192], + [-5.027335711621496, 56.77083442357739], + [-5.027351904492563, 56.77083164053779], + [-5.027789005148308, 56.77073904036897], + [-5.027804751357127, 56.770735026785246], + [-5.027819391499965, 56.77072990405236], + [-5.028940653207516, 56.77027745954526], + [-5.029421995867688, 56.77012502946384], + [-5.029646243784535, 56.7700821298563], + [-5.029836723650749, 56.7700758370065], + [-5.030214163036814, 56.770152766097716], + [-5.030229877075177, 56.77015536609115], + [-5.030246060194936, 56.77015686559987], + [-5.030262457853618, 56.77015724103825], + [-5.030752879298577, 56.77015156351889], + [-5.031201502254727, 56.77018635107251], + [-5.031221468462152, 56.77018705114348], + [-5.031933190378858, 56.770182065901565], + [-5.032608966092147, 56.77027141693292], + [-5.033004224230213, 56.770436928972195], + [-5.033181001663783, 56.770511019576126], + [-5.033196658842235, 56.77051665658052], + [-5.033213620757753, 56.77052100900596], + [-5.033231540212038, 56.77052398776132], + [-5.033250050406345, 56.77052553187355], + [-5.033712384895555, 56.770545672010066], + [-5.034678188393849, 56.77063701430622], + [-5.034702089947854, 56.77063805094072], + [-5.035505491482456, 56.77063235091911], + [-5.035523480570888, 56.77063153966424], + [-5.035541095250985, 56.770629376937606], + [-5.03624179641142, 56.770514976721024], + [-5.036248277889867, 56.7705138167812], + [-5.036529750067585, 56.77045895052231], + [-5.036581381235431, 56.77046280265984], + [-5.036599721346842, 56.77046345581749], + [-5.03669882153621, 56.77046315581558], + [-5.036715748407127, 56.770462500444765], + [-5.03673237853071, 56.77046064788621], + [-5.036748432281617, 56.770457629289616], + [-5.036912332517488, 56.77042012922216], + [-5.036929006428533, 56.7704155223606], + [-5.036944317078998, 56.77040965974852], + [-5.036957952971134, 56.770402660662064], + [-5.03704427305481, 56.770351548688836], + [-5.037118708128757, 56.77030745394777], + [-5.037280143687985, 56.770266431434656], + [-5.037412385366501, 56.7702540682777], + [-5.037535757987124, 56.77027446375458], + [-5.037631668828436, 56.770328391580165], + [-5.037724093737016, 56.77044123441909], + [-5.037832950561739, 56.7709185292749], + [-5.037837021472434, 56.770929436674166], + [-5.037844112196551, 56.77093986781723], + [-5.038022411682521, 56.77115066798963], + [-5.038034886202877, 56.77116237660403], + [-5.038164786073096, 56.771261476715], + [-5.038177983352675, 56.77127004488495], + [-5.038193449136521, 56.77127738036255], + [-5.038354849255184, 56.771342580461585], + [-5.038370553345114, 56.77134802587678], + [-5.038387503237015, 56.771352195697915], + [-5.038405357502683, 56.771355005930616], + [-5.038682158000016, 56.77138710598681], + [-5.038698148173042, 56.77138840016596], + [-5.039072048881555, 56.77140580019397], + [-5.039077780585226, 56.77140599747794], + [-5.03945940207112, 56.77141452150777], + [-5.039752800921299, 56.771440689259386], + [-5.040228831948191, 56.77152832838906], + [-5.040700880580803, 56.77164949544446], + [-5.040717597796708, 56.77165304259934], + [-5.041274698724455, 56.77174774276478], + [-5.041275460783456, 56.77174787090825], + [-5.042434662725824, 56.77194067124537], + [-5.042456109458064, 56.77194318404308], + [-5.043446911312539, 56.77201228416034], + [-5.043462122516216, 56.77201285337643], + [-5.043477351059239, 56.77201244732348], + [-5.043492390243135, 56.77201107151286], + [-5.044337919467774, 56.771905602370275], + [-5.044766981849441, 56.77189521083972], + [-5.045346170007636, 56.77188598079118], + [-5.04560469481365, 56.77193107604918], + [-5.045937057527528, 56.77222891414132], + [-5.046166316119592, 56.772484600893556], + [-5.046300378327033, 56.77291395379751], + [-5.046373605396361, 56.77338333280373], + [-5.04637578379235, 56.773391602993634], + [-5.046379696109799, 56.773399678406854], + [-5.046717594464963, 56.77396297875348], + [-5.046723438036395, 56.77397104428017], + [-5.047228856012808, 56.77456195271855], + [-5.047524598017353, 56.775271817360675], + [-5.047459239019699, 56.77574523446726], + [-5.047020464710445, 56.7761134858196], + [-5.046684183889066, 56.7761594833688], + [-5.045990884469436, 56.776100977412035], + [-5.045974768424556, 56.77610017307002], + [-5.045958594770481, 56.77610046677368], + [-5.045942610759093, 56.776101854033115], + [-5.0459270607432, 56.77610431364077], + [-5.045912182441098, 56.776107807995906], + [-5.045898203302536, 56.77611228367915], + [-5.045885337031666, 56.77611767226916], + [-5.045873780320099, 56.776123891388835], + [-5.045863709840021, 56.77613084596423], + [-5.044893108686666, 56.77689354514177], + [-5.044890602907807, 56.77689558782139], + [-5.043989301580958, 56.77765818704146], + [-5.043979681267374, 56.777667885738595], + [-5.043972881618455, 56.777678279201595], + [-5.043717180628941, 56.778189677734446], + [-5.043418179361967, 56.77878757623941], + [-5.043414807507304, 56.77879650323572], + [-5.043413521769236, 56.77880559276595], + [-5.043414342846467, 56.77881469851123], + [-5.043417257523199, 56.77882367389159], + [-5.043422218881773, 56.778832374425455], + [-5.044392815084058, 56.780218975398014], + [-5.044400511949996, 56.780228032989484], + [-5.044410423753367, 56.780236416688496], + [-5.04442235873728, 56.78024396430009], + [-5.045797528698641, 56.78100022467195], + [-5.046689936157024, 56.781824109337286], + [-5.047607502207719, 56.78269771914416], + [-5.048071508151786, 56.78333032394201], + [-5.04819915451194, 56.783976249284365], + [-5.04819992883291, 56.78397856053853], + [-5.048201811977156, 56.783984819805234], + [-5.048202354923839, 56.78398580212361], + [-5.048202646491, 56.78398667241579], + [-5.048204326696695, 56.783989369524555], + [-5.048206783389565, 56.783993814258835], + [-5.048208055780578, 56.78399535554302], + [-5.048208893490106, 56.783996700254974], + [-5.048211100819502, 56.78399904408648], + [-5.048213851099418, 56.78400237557916], + [-5.048216145263805, 56.78400440047995], + [-5.048217759623993, 56.784006114672046], + [-5.048770458734618, 56.78449991516997], + [-5.048779728400123, 56.78450715585577], + [-5.048790549292018, 56.78451371618296], + [-5.048802757282811, 56.78451949664642], + [-5.049360943983058, 56.78475249128862], + [-5.049757930572188, 56.78491828582567], + [-5.049771261281642, 56.78492317591164], + [-5.049785581108873, 56.7849271348274], + [-5.051172016201057, 56.78525364317051], + [-5.051440962795205, 56.78531693014778], + [-5.052328666952865, 56.78584283617055], + [-5.052346919319733, 56.78585179918145], + [-5.052668341727795, 56.78598210836673], + [-5.053246042149018, 56.786216208722024], + [-5.053251405830547, 56.78621827048006], + [-5.054617314004347, 56.786715827890596], + [-5.054809274121202, 56.787213225308285], + [-5.054698855868834, 56.78776667844323], + [-5.054698084822023, 56.78777523656595], + [-5.054699175330116, 56.787783784216], + [-5.054854698360472, 56.788438884688986], + [-5.05490572683024, 56.78881946942477], + [-5.05493552550569, 56.789042065303796], + [-5.054938095439817, 56.789051896077304], + [-5.054943110598742, 56.78906143847741], + [-5.055321809000603, 56.78963083886015], + [-5.05532428204027, 56.789634279568425], + [-5.055494381238994, 56.789854179437675], + [-5.055635780527663, 56.790036979270525], + [-5.055644742257239, 56.79004651495212], + [-5.055656191227153, 56.79005521199068], + [-5.055923320907867, 56.79022913304563], + [-5.0558842, 56.790244599999966], + [-5.056112946043207, 56.790352591605306], + [-5.056305813426518, 56.79047815994251], + [-5.056342445683901, 56.79050454202945], + [-5.0563681, 56.790524899999966], + [-5.056374880239901, 56.79052790094474], + [-5.056462391796525, 56.79059092535902], + [-5.056555818468024, 56.79078644080464], + [-5.0565517, 56.79081129999999], + [-5.0565517, 56.790933099999975], + [-5.0568262, 56.79138029999996], + [-5.05707, 56.791666799999966], + [-5.0571802, 56.791757299999944], + [-5.0573454, 56.79189079999998], + [-5.0574201, 56.79190809999997], + [-5.0574919, 56.791905699999965], + [-5.0575538, 56.791921], + [-5.057605, 56.7919124], + [-5.0576609, 56.79188429999997], + [-5.0576605, 56.791839], + [-5.057679230391617, 56.79180675249511], + [-5.057746953778136, 56.79178085635096], + [-5.057761375470753, 56.791774463977006], + [-5.05777400758786, 56.79176701793309], + [-5.057784596913017, 56.79175866747913], + [-5.057876923474196, 56.7916735891097], + [-5.058298171322838, 56.791458309935784], + [-5.05853948864883, 56.79135399135283], + [-5.058622612064148, 56.791336729338234], + [-5.0587614, 56.79135659999996], + [-5.058809171057008, 56.7913800059129], + [-5.058912929316837, 56.79153883529996], + [-5.058967605005468, 56.79175100667762], + [-5.059025395205642, 56.79205964702162], + [-5.058950345697522, 56.79237777422629], + [-5.05894926356118, 56.79238735378415], + [-5.058950782322862, 56.79255666688042], + [-5.0588983, 56.792658099999976], + [-5.0589159, 56.79287339999996], + [-5.0589992, 56.79309149999995], + [-5.0589602, 56.79331719999997], + [-5.0589764, 56.79341569999998], + [-5.0592242, 56.79374219999997], + [-5.059260276767664, 56.79377175824539], + [-5.05928981506814, 56.79381804824424], + [-5.059295380333332, 56.793825426974415], + [-5.059302403267853, 56.793832421254415], + [-5.059310797131696, 56.79383894469735], + [-5.059469797940468, 56.793948985405294], + [-5.059557295211276, 56.79403365503241], + [-5.0598665, 56.79445179999996], + [-5.0598997, 56.79449409999997], + [-5.060657347046678, 56.794982064082646], + [-5.060674416356393, 56.79499533510432], + [-5.060684305821487, 56.795002114041345], + [-5.060695613229276, 56.7950081888731], + [-5.06070223432766, 56.79501097327642], + [-5.0607133, 56.79501809999997], + [-5.0611689, 56.7952944], + [-5.0614169, 56.795423199999966], + [-5.0615187, 56.79546559999997], + [-5.0618895, 56.795571099999975], + [-5.0622467, 56.795654499999955], + [-5.0625795, 56.79571819999997], + [-5.0626968, 56.79575129999997], + [-5.0627399, 56.795777199999975], + [-5.0628913, 56.79592629999997], + [-5.063099729859053, 56.79604519269657], + [-5.063114685124376, 56.796056634476116], + [-5.06363877432231, 56.79648312784175], + [-5.063670915883596, 56.7966324980781], + [-5.0636267, 56.79670819999996], + [-5.063625, 56.796743699999965], + [-5.063630951378125, 56.79677910742796], + [-5.063573428579678, 56.7969009851488], + [-5.063572115086645, 56.7969040418793], + [-5.063502270686251, 56.797084112265715], + [-5.0634933, 56.797090899999944], + [-5.0634186, 56.79722439999996], + [-5.0633556, 56.7973084], + [-5.0633291, 56.7973747], + [-5.0633945, 56.7975], + [-5.0635941, 56.797913499999964], + [-5.06366136152693, 56.797979378080626], + [-5.063693933385671, 56.79805010439076], + [-5.063698564827959, 56.798058142523644], + [-5.063704880134638, 56.79806582770508], + [-5.063712792380572, 56.7980730541535], + [-5.063722192659599, 56.79807972240142], + [-5.064262001302243, 56.79841942838794], + [-5.0644060012506, 56.79851002850163], + [-5.064416802798192, 56.79851606660646], + [-5.064428822965484, 56.79852136621768], + [-5.064981323407518, 56.79873686654881], + [-5.06498533420564, 56.79873837027412], + [-5.065225703306525, 56.79882494500756], + [-5.0656725, 56.798996099999954], + [-5.066026605450785, 56.79915350852219], + [-5.066299682464358, 56.79936756368276], + [-5.0666183, 56.799651699999956], + [-5.0668297, 56.79999989999999], + [-5.0669763, 56.800116], + [-5.067048146780964, 56.800209062543885], + [-5.067121965496018, 56.80034982826676], + [-5.0671456, 56.80041069999998], + [-5.067215044051697, 56.80052731918506], + [-5.067303539542217, 56.80069606902236], + [-5.067308345040403, 56.80070362195112], + [-5.067314650996707, 56.800710834990156], + [-5.067338471207105, 56.800734591659555], + [-5.067367, 56.80078249999998], + [-5.0675088, 56.80091379999996], + [-5.06753839316311, 56.80093397893352], + [-5.067576050452532, 56.80097153523316], + [-5.067582617258695, 56.800977400413714], + [-5.068074768112272, 56.80137312331462], + [-5.06815, 56.801450399999986], + [-5.0684195, 56.80172729999998], + [-5.0685702, 56.801907199999974], + [-5.0687165, 56.802033], + [-5.0687712, 56.802100899999964], + [-5.0688205, 56.802203], + [-5.0688988, 56.8022595], + [-5.0689218, 56.80229939999998], + [-5.0690105, 56.802382599999966], + [-5.0691134, 56.80251939999995], + [-5.0692419, 56.80264839999998], + [-5.0693444, 56.8027733], + [-5.0694913, 56.80295239999997], + [-5.0697146, 56.803159], + [-5.0697674, 56.803223299999964], + [-5.0698463, 56.80340649999997], + [-5.0701487, 56.8037793], + [-5.070172, 56.80386319999998], + [-5.0703764, 56.80415929999998], + [-5.0704691, 56.804370099999986], + [-5.0709194, 56.80498819999998], + [-5.0710295, 56.80511219999998], + [-5.0712731, 56.80522329999996], + [-5.0714898, 56.80535079999997], + [-5.072206, 56.805612699999976], + [-5.0723789, 56.80568389999996], + [-5.0725285, 56.80572969999997], + [-5.0727688, 56.8057822], + [-5.0728901, 56.80580339999997], + [-5.0731145, 56.805822199999966], + [-5.073259548521571, 56.80584164308395], + [-5.073367323927089, 56.80586298686416], + [-5.073377319000957, 56.805864721598844], + [-5.074034166716566, 56.80596304422003], + [-5.0740621423819, 56.805970249168006], + [-5.074499243396785, 56.80612644265136], + [-5.075102414141387, 56.80637116514891], + [-5.075475256108104, 56.806580056595344], + [-5.076023513526231, 56.807038979725284], + [-5.0763621, 56.80750119999997], + [-5.0765058, 56.80767469999998], + [-5.0766237, 56.80778249999998], + [-5.0766932, 56.80792089999996], + [-5.0767824, 56.80805139999997], + [-5.0768095, 56.808125599999954], + [-5.076821, 56.8082234], + [-5.0768728, 56.8082826], + [-5.0769239, 56.80839729999997], + [-5.0769811, 56.808488099999984], + [-5.0769929, 56.8086541], + [-5.0769364, 56.80885], + [-5.076784787492785, 56.80910022534516], + [-5.076510307792257, 56.80950028567876], + [-5.0764816, 56.8095249], + [-5.076435, 56.809556], + [-5.0763439, 56.80959409999998], + [-5.076316, 56.80962689999996], + [-5.0762096, 56.80974869999997], + [-5.0761356, 56.8098744], + [-5.0760289, 56.8100072], + [-5.075949, 56.81011189999999], + [-5.0758929, 56.8102317], + [-5.0759225, 56.810345699999985], + [-5.0759056, 56.81041619999998], + [-5.0758658, 56.810457799999966], + [-5.0758008, 56.81062059999997], + [-5.0757155, 56.810697199999986], + [-5.0756864, 56.8107647], + [-5.075694456871266, 56.81095775237792], + [-5.075668679041583, 56.811035050719845], + [-5.0756196, 56.81107629999998], + [-5.0755706, 56.811058699999975], + [-5.0755304, 56.81107249999999], + [-5.0755087, 56.81103739999997], + [-5.0754988, 56.81095889999999], + [-5.0754806, 56.8109261], + [-5.0754501, 56.81091569999997], + [-5.0754043, 56.8109436], + [-5.07532, 56.8110585], + [-5.0752694, 56.811278599999945], + [-5.0752788, 56.81133409999996], + [-5.075315, 56.811343], + [-5.0753295, 56.81136439999997], + [-5.0752973, 56.81149769999998], + [-5.0752971, 56.81158709999997], + [-5.0753136, 56.81164149999997], + [-5.0756078, 56.81200929999997], + [-5.075638, 56.81205379999996], + [-5.0758445, 56.81224119999998], + [-5.075871678565633, 56.81218733950714], + [-5.075880768369225, 56.81219632773172], + [-5.076151908325035, 56.81256024045391], + [-5.076222009240063, 56.812795298729085], + [-5.076350892123785, 56.813227522070115], + [-5.076400108731193, 56.81379794799158], + [-5.076303225998736, 56.8141402304768], + [-5.075850863082588, 56.81506447055261], + [-5.075847683819908, 56.81507300046135], + [-5.075846408862165, 56.815081678637945], + [-5.075841008339635, 56.815231378636035], + [-5.075841553502018, 56.81523950016853], + [-5.075843767340653, 56.81524753599317], + [-5.075847621537082, 56.81525538331528], + [-5.076172019966671, 56.81579278364812], + [-5.076179508356363, 56.815802657042454], + [-5.076189585546753, 56.815811811612626], + [-5.07673188497837, 56.81623051207843], + [-5.076742704635766, 56.81623780370603], + [-5.076755167426731, 56.816244258261364], + [-5.077536884887427, 56.81659903967925], + [-5.078055880771903, 56.81700289941917], + [-5.079053362627056, 56.817869595557696], + [-5.079844695524088, 56.8189143755296], + [-5.079813441011627, 56.81942810405679], + [-5.079813388865646, 56.81942922227376], + [-5.079807117335942, 56.81962259217873], + [-5.0797536, 56.819685], + [-5.0797376, 56.81968989999998], + [-5.0797499, 56.8196995], + [-5.079804525098718, 56.81970251818767], + [-5.079801787616651, 56.81978692227056], + [-5.079801924145179, 56.81978839102829], + [-5.0797872, 56.819814599999965], + [-5.0797558, 56.819831499999985], + [-5.079759, 56.81984839999995], + [-5.0797905, 56.8198747], + [-5.0797174, 56.819943], + [-5.0797266, 56.820074], + [-5.0797571, 56.820147], + [-5.0798064, 56.82019129999996], + [-5.0797808, 56.820250799999954], + [-5.0797868, 56.820283099999976], + [-5.0798659, 56.82042119999995], + [-5.0798793, 56.82052419999999], + [-5.0799331, 56.82056149999995], + [-5.0801321, 56.82062939999997], + [-5.080215, 56.8206399], + [-5.0802523, 56.820675], + [-5.0804414, 56.820738199999965], + [-5.0807451, 56.82082629999996], + [-5.0807099, 56.8208462], + [-5.080595, 56.8208657], + [-5.0805053, 56.820895399999976], + [-5.0804674, 56.820922899999964], + [-5.0805194, 56.82094159999997], + [-5.0805758, 56.820904], + [-5.08066, 56.820875299999976], + [-5.0807475, 56.820862599999984], + [-5.0808018, 56.820837499999975], + [-5.0809123, 56.82086419999995], + [-5.0811938, 56.82091359999997], + [-5.0813255, 56.82092119999998], + [-5.0814572, 56.820908], + [-5.081482, 56.820911], + [-5.0815494, 56.82095249999997], + [-5.0818038, 56.82101019999997], + [-5.081880925099665, 56.821020475197784], + [-5.082081284760894, 56.8210893731434], + [-5.082117, 56.82113159999999], + [-5.0822752, 56.82120809999997], + [-5.0824719, 56.821265699999984], + [-5.0826933, 56.82130459999996], + [-5.0828028, 56.82135], + [-5.0828781, 56.821363], + [-5.0831054, 56.821366], + [-5.0832286, 56.82138759999997], + [-5.0836266, 56.82139809999997], + [-5.0836644, 56.82140519999997], + [-5.083799, 56.82140529999998], + [-5.0842168, 56.82144259999996], + [-5.0844225050718475, 56.82145112888207], + [-5.0844225050718475, 56.82118935427821] + ], + [ + [-5.051379858375106, 56.78514618835705], + [-5.051373401463104, 56.7850475033589], + [-5.051301226452125, 56.78492049694643], + [-5.051297340670326, 56.784911775258664], + [-5.051295466805563, 56.78490285566966], + [-5.051295634113581, 56.78489387744342], + [-5.051297839980689, 56.78488498075939], + [-5.051334580273318, 56.78478434939144], + [-5.051344437848347, 56.78466597464513], + [-5.05126234554798, 56.78446088128153], + [-5.051175779914012, 56.78435106618435], + [-5.050969364440095, 56.78426368098362], + [-5.050780086442988, 56.78421188848845], + [-5.050390179593937, 56.78418655658689], + [-5.049994399615806, 56.78418655657996], + [-5.049987563202976, 56.78418645851914], + [-5.049036661389644, 56.78415915848006], + [-5.049020918064802, 56.78415817942333], + [-5.04900550553014, 56.78415616356193], + [-5.048621418931659, 56.78409222143322], + [-5.048980727048144, 56.784413236504776], + [-5.049519442101911, 56.784638102954275], + [-5.049903636793424, 56.78479855495112], + [-5.051275200148113, 56.78512156069807], + [-5.051379858375106, 56.78514618835705] + ] + ], + [ + [ + [-5.0844225050718475, 56.832621492171256], + [-5.0843141, 56.83263489999997], + [-5.0835698, 56.83265639999997], + [-5.0834655, 56.832680299999964], + [-5.0828692, 56.83274349999998], + [-5.0828112, 56.8327434], + [-5.0827731, 56.83272469999997], + [-5.0827228, 56.83273269999997], + [-5.0826786, 56.832753599999954], + [-5.0825515, 56.83274419999995], + [-5.0823024, 56.83274579999997], + [-5.0820384, 56.832765799999976], + [-5.0819758, 56.832762], + [-5.0819236, 56.832745299999964], + [-5.0818978, 56.83275039999997], + [-5.081827, 56.8327872], + [-5.0818004, 56.832782499999944], + [-5.0817711, 56.83276529999996], + [-5.0816977, 56.83275], + [-5.0815713, 56.8327477], + [-5.0808636, 56.832691899999965], + [-5.080459, 56.832719599999955], + [-5.0803587, 56.8327417], + [-5.0802846, 56.83276839999994], + [-5.0802252, 56.83277729999996], + [-5.0801564, 56.832776199999984], + [-5.0800842, 56.8327753], + [-5.0799201, 56.832793699999954], + [-5.0795527, 56.832892699999974], + [-5.0791712883983875, 56.83302498513894], + [-5.0844225050718475, 56.83302498513894], + [-5.0844225050718475, 56.832621492171256] + ] + ] + ], + "type": "MultiPolygon" + }, + "properties": { + "operation": "intersection" + }, + "type": "Feature" + } + ], + "type": "FeatureCollection" +} From 263ef9ca192e81f31e7e7d2c3468cbfee060cfdc Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Wed, 29 Jan 2020 09:07:56 +0100 Subject: [PATCH 20/22] moved contour initialization out into separate function --- lib/src/boolean/connect_edges.rs | 100 +++++++++++++++++-------------- 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 2c6339a..9bce99c 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -124,11 +124,50 @@ where } } - /// The semantics of `is_exterior` are in the sense of an exterior ring of a polygon - /// in GeoJSON. This is not to be confused with "external contour" as used in the + /// This logic implements the 4 cases of parent contours from Fig. 4 in the Martinez paper. + pub fn initialize_from_context(event: &Rc>, contours: &mut [Contour], contour_id: i32) -> Contour { + if let Some(prev_in_result) = event.get_prev_in_result() { + // Note that it is valid to query the "previous in result" for its output contour id, + // because we must have already processed it (i.e., assigned an output contour id) + // in an earlier iteration, otherwise it wouldn't be possible that it is "previous in + // result". + let lower_contour_id = prev_in_result.get_output_contour_id(); + if prev_in_result.get_result_transition() == ResultTransition::OutIn { + // We are inside. Now we have to check if the thing below us is another hole or + // an exterior contour. + let lower_contour = &contours[lower_contour_id as usize]; + if let Some(parent_contour_id) = lower_contour.hole_of { + // The lower contour is a hole => Connect the new contour as a hole to its parent, + // and use same depth. + contours[parent_contour_id as usize].hole_ids.push(contour_id); + let hole_of = Some(parent_contour_id); + let depth = contours[lower_contour_id as usize].depth; + Contour::new(hole_of, depth) + } else { + // The lower contour is an exterior contour => Connect the new contour as a hole, + // and increment depth. + contours[lower_contour_id as usize].hole_ids.push(contour_id); + let hole_of = Some(lower_contour_id); + let depth = contours[lower_contour_id as usize].depth + 1; + Contour::new(hole_of, depth) + } + } else { + // We are outside => this contour is an exterior contour of same depth. + let depth = contours[lower_contour_id as usize].depth; + Contour::new(None, depth) + } + } else { + // There is no lower/previous contour => this contour is an exterior contour of depth 0. + Contour::new(None, 0) + } + } + + /// Whether a contour is an exterior contour or a hole. + /// Note: The semantics of `is_exterior` are in the sense of an exterior ring of a + /// polygon in GeoJSON, not to be confused with "external contour" as used in the /// Martinez paper (which refers to contours that are not included in any of the - /// other polygon contours). `is_exterior` is true for all outer contours, not just - /// the outermost. + /// other polygon contours; `is_exterior` is true for all outer contours, not just + /// the outermost). pub fn is_exterior(&self) -> bool { self.hole_of.is_none() } @@ -180,7 +219,7 @@ where let result_events = order_events(sorted_events); debug_print_results(&result_events); - let mut result: Vec> = Vec::new(); + let mut contours: Vec> = Vec::new(); let mut processed: HashSet = HashSet::new(); for i in 0..(result_events.len() as i32) { @@ -188,43 +227,12 @@ where continue; } - let contour_id = result.len() as i32; - - // This logic implements the 4 cases of parent contours from Fig. 4 in the Martinez paper. - let mut contour = if let Some(prev_in_result) = result_events[i as usize].get_prev_in_result() { - // Note that it is valid to query the "previous in result" for its output contour id, - // because we must have already processed it (i.e., assigned an output contour id) - // in an earlier iteration, otherwise it wouldn't be possible that it is "previous in - // result". - let lower_contour_id = prev_in_result.get_output_contour_id(); - if prev_in_result.get_result_transition() == ResultTransition::OutIn { - // We are inside. Now we have to check if the thing below us is another hole or - // an exterior contour. - let lower_contour = &result[lower_contour_id as usize]; - if let Some(parent_contour_id) = lower_contour.hole_of { - // The lower contour is a hole => Connect the new contour as a hole to its parent, - // and use same depth. - result[parent_contour_id as usize].hole_ids.push(contour_id); - let hole_of = Some(parent_contour_id); - let depth = result[lower_contour_id as usize].depth; - Contour::new(hole_of, depth) - } else { - // The lower contour is an exterior contour => Connect the new contour as a hole, - // and increment depth. - result[lower_contour_id as usize].hole_ids.push(contour_id); - let hole_of = Some(lower_contour_id); - let depth = result[lower_contour_id as usize].depth + 1; - Contour::new(hole_of, depth) - } - } else { - // We are outside => this contour is an exterior contour of same depth. - let depth = result[lower_contour_id as usize].depth; - Contour::new(None, depth) - } - } else { - // There is no lower/previous contour => this contour is an exterior contour of depth 0. - Contour::new(None, 0) - }; + let contour_id = contours.len() as i32; + let mut contour = Contour::initialize_from_context( + &result_events[i as usize], + &mut contours, + contour_id, + ); let orig_pos = i; // Alias just for clarity let mut pos = i; @@ -244,12 +252,12 @@ where // terminates the loop. mark_as_processed(&mut processed, &result_events, pos, contour_id); - pos = result_events[pos as usize].get_other_pos(); // pos advancment (A) + pos = result_events[pos as usize].get_other_pos(); // pos advancement (A) mark_as_processed(&mut processed, &result_events, pos, contour_id); contour.points.push(result_events[pos as usize].point); - pos = next_pos(pos, &result_events, &processed, orig_pos); // pos advancment (B) + pos = next_pos(pos, &result_events, &processed, orig_pos); // pos advancement (B) if pos == orig_pos { break; @@ -259,8 +267,8 @@ where // This assert should be possible once the first stage of the algorithm is robust. // debug_assert_eq!(contour.points.first(), contour.points.last()); - result.push(contour); + contours.push(contour); } - result + contours } From 91ab4fbdd3c54b35825b18ef5f249ff91d7ca11b Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Thu, 30 Jan 2020 09:48:47 +0100 Subject: [PATCH 21/22] documented tests --- tests/README.md | 55 +++++++++ tests/scripts/plot_test_cases.py | 197 +++++++++++++++++++++++++++++++ tests/src/bin/run_single_test.rs | 11 +- 3 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 tests/README.md create mode 100755 tests/scripts/plot_test_cases.py diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..d004931 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,55 @@ +# Test framework usage notes + +On top of unit tests, the algorithm comes with a large suite of integration tests. +Test cases are defined in `fixtures/generic_test_cases`. Each test case is a GeoJSON +file containing a `FeatureCollection` with the following semantics: + +- The first two features are the subject and clipping polygon. +- The remaining features define expected test results. The `properties.operation` field is + used to specify the operation (intersection, union, difference, xor) corresponding + to the result. The `properties.comment` field may contain additional notes about a + test case, e.g. if the test case currently still has issues. + + +## Visualizing test result contents + +To inspect if the input and expected results of a test case make sense, there is a +small Python helper script in `scripts/plot_test_cases.py`. It allows both exporting +multiple test cases into a summary PDF, or showing interactive plots with zooming/panning +functionality. + +``` +usage: Tool to plot content test case files. [-h] [-i] [--pngs] [-o OUTPUT] + + [ ...] + +positional arguments: + test case GeoJSON file(s) to plot + +optional arguments: + -h, --help show this help message and exit + -i, --interactive whether to show interactive plot windows + --pngs whether to generate individual PNGs for each plot + -o OUTPUT, --output OUTPUT + PDF output file name (default: test_cases.pdf) +``` + + +## Running tests + +- The standard `cargo test` runs all tests. The test suite uses the + [`pretty-assertions`](https://github.com/colin-kiegel/rust-pretty-assertions) crate, + to simplify finding problems in case of failing tests. + +- For debugging a single test case file, there is also + `cargo run = len(points): + c -= len(points) + ab = [points[b][0] - points[a][0], points[b][1] - points[a][1]] + ac = [points[c][0] - points[a][0], points[c][1] - points[a][1]] + prod = ab[0] * ac[1] - ab[1] * ac[0] + + return prod > 0 + + +def fix_winding_order(points, should_be_clockwise): + """ + Ensures a ring is in either clockwise or counter-clockwise order. + """ + is_clockwise = check_winding_order_clockwise(points) + if is_clockwise == should_be_clockwise: + return points[:] + else: + return points[::-1] + + +def validate_ring(ring): + assert isinstance(ring, list), "Ring must be of type list, but is {}.".format(type(ring)) + for p in ring: + assert isinstance(p, list), "Points must be of type list, but is {}".format(type(p)) + assert len(p) == 2, "Points must be list of length 2, but is {}".format(len(p)) + assert isinstance(p[0], float) or isinstance(p[0], int), \ + "Values must be float or int, got: {}".format(p[0]) + assert isinstance(p[1], float) or isinstance(p[1], int), \ + "Values must be float or int, got: {}".format(p[1]) + + +def plot(ax, multi_polygon, label, shade_color=None): + for j, polygon in enumerate(multi_polygon): + path_points = [] + path_commands = [] + for k, ring in enumerate(polygon): + try: + validate_ring(ring) + xs = [p[0] for p in ring] + ys = [p[1] for p in ring] + ax.plot(xs, ys, "o-", label="{} (poly = {}, ring = {})".format(label, j + 1, k + 1), ms=2) + except (IndexError, AssertionError) as e: + plt.figtext( + 0.5, 0.5, + "Plot failed because of invalid GeoJSON", + ha='center', fontsize=12, color="#bf1932", + ) + + points_ordered = fix_winding_order(ring, should_be_clockwise=(k == 0)) + path_points += points_ordered + path_commands += [Path.MOVETO] + [Path.LINETO] * (len(points_ordered) - 2) + [Path.CLOSEPOLY] + + if shade_color is not None: + path = Path(path_points, path_commands) + patch = PathPatch(path, ec=None, fc=shade_color, alpha=0.15) + ax.add_patch(patch) + + +def parse_args(): + parser = argparse.ArgumentParser("Tool to plot content test case files.") + parser.add_argument( + "-i", "--interactive", + action="store_true", + help="whether to show interactive plot windows" + ) + parser.add_argument( + "--pngs", + action="store_true", + help="whether to generate individual PNGs for each plot" + ) + parser.add_argument( + "-o", "--output", + help="PDF output file name (default: test_cases.pdf)", + default="test_cases.pdf", + ) + parser.add_argument( + "files", + metavar="", + nargs="+", + help="test case GeoJSON file(s) to plot", + ) + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + files = args.files + interactive = args.interactive + pngs = args.pngs + + with PdfPages(args.output) as pp: + + for f in sorted(files): + print("Plotting test case: {}".format(f)) + data = json.load(open(f)) + assert data["type"] == "FeatureCollection" + + features = data["features"] + assert len(features) >= 2 + + p1 = extract_multi_polygon(features[0]) + p2 = extract_multi_polygon(features[1]) + + for feature in features[2:]: + op = feature["properties"]["operation"] + p_res = extract_multi_polygon(feature) + + fig, axes = plt.subplots(1, 3, figsize=(15, 7), sharex=True, sharey=True) + + plot(axes[0], p1, "A", shade_color="#0000FF") + plot(axes[0], p2, "B", shade_color="#FF0000") + + plot(axes[1], p_res, "Result", shade_color="#00FF00") + + plot(axes[2], p1, "A") + plot(axes[2], p2, "B") + plot(axes[2], p_res, "Result") + + if len(axes[0].get_legend_handles_labels()[0]) < 10: + axes[0].legend(loc="best", prop={"size": 9}) + if len(axes[1].get_legend_handles_labels()[0]) < 10: + axes[1].legend(loc="best", prop={"size": 9}) + if len(axes[2].get_legend_handles_labels()[0]) < 10: + axes[2].legend(loc="best", prop={"size": 9}) + + fig.suptitle("{} / {}".format(os.path.basename(f), op)) + if "comment" in feature["properties"] and feature["properties"]["comment"] is not None: + plt.figtext( + 0.5, 0.93, + feature["properties"]["comment"], + ha='center', fontsize=9, color="#f2760d", + ) + + plt.tight_layout() + plt.subplots_adjust(top=0.90) + + pp.savefig(fig) + if pngs: + plt.savefig("{}_{}.png".format(f, op)) + if interactive: + plt.show() + plt.close(fig) + + +if __name__ == "__main__": + main() diff --git a/tests/src/bin/run_single_test.rs b/tests/src/bin/run_single_test.rs index 6b37181..163fe27 100644 --- a/tests/src/bin/run_single_test.rs +++ b/tests/src/bin/run_single_test.rs @@ -1,6 +1,7 @@ extern crate geo_booleanop_tests; use std::fs; +use std::path::Path; use std::process::Command; use geo_booleanop_tests::helper::run_generic_test_case; @@ -13,7 +14,15 @@ fn main() { run_generic_test_case(&filename_out, true); - Command::new("../martinez/polygon_ops_debugging/plot_test_cases.py") + // Try to run Python plot + let script_path = Path::new(file!()).to_path_buf() + .canonicalize().unwrap() + .parent().unwrap().to_path_buf() // -> bin + .parent().unwrap().to_path_buf() // -> src + .parent().unwrap().to_path_buf() // -> tests + .join("scripts") + .join("plot_test_cases.py"); + Command::new(script_path.as_os_str()) .arg("-i") .arg(&filename_out) .spawn() From f396863967a7ba9012f43cee8e8115896bc7844f Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Thu, 30 Jan 2020 09:52:19 +0100 Subject: [PATCH 22/22] removed more debugging code --- lib/src/boolean/connect_edges.rs | 45 -------------------------------- 1 file changed, 45 deletions(-) diff --git a/lib/src/boolean/connect_edges.rs b/lib/src/boolean/connect_edges.rs index 9bce99c..0c537b7 100644 --- a/lib/src/boolean/connect_edges.rs +++ b/lib/src/boolean/connect_edges.rs @@ -43,21 +43,6 @@ where } } - for r in &result_events { - println!("{:?}", r); - debug_assert!(r.get_other_event().is_some()); - } - - for (i, r) in result_events.iter().enumerate() { - println!("pos {:3} linked to {:3} {} {:?} => {:?}", - i, - r.get_other_pos(), - if r.is_left() { "L" } else { "R" }, - r.point, - r.get_other_event().map(|o| o.point).unwrap(), - ); - } - result_events } @@ -174,35 +159,6 @@ where } -use std::fs::File; -use std::io::Write; -fn debug_print_results(events: &[Rc>]) -where - F: Float, -{ - let mut writer = File::create("debug.csv").unwrap(); - writeln!(&mut writer, - "index;x;y;other_x;other_y;lr;result_transition;in_out;other_in_out;is_subject;is_exterior_ring;prev_in_result" - ).expect("Failed to write to file"); - for (i, evt) in events.iter().enumerate() { - writeln!(&mut writer, "{i};{x:?};{y:?};{other_x:?};{other_y:?};{lr};{transition:?};{in_out};{other_in_out};{subject};{exterior_ring};{prev_in_result:?}", - i=i, - x=evt.point.x, - y=evt.point.y, - other_x=evt.get_other_event().unwrap().point.x, - other_y=evt.get_other_event().unwrap().point.y, - lr=if evt.is_left() { "L" } else { "R" }, - transition=evt.get_result_transition(), - in_out=evt.is_in_out(), - other_in_out=evt.is_other_in_out(), - subject=evt.is_subject, - exterior_ring=evt.is_exterior_ring, - prev_in_result=evt.get_prev_in_result().map(|o| format!("{:?}", o.point)), - ).expect("Failed to write to file"); - } -} - - fn mark_as_processed(processed: &mut HashSet, result_events: &[Rc>], pos: i32, contour_id: i32) where F: Float, @@ -217,7 +173,6 @@ where F: Float, { let result_events = order_events(sorted_events); - debug_print_results(&result_events); let mut contours: Vec> = Vec::new(); let mut processed: HashSet = HashSet::new();