diff options
author | Jovansonlee Cesar <ivanceras@gmail.com> | 2020-11-25 16:53:19 +0800 |
---|---|---|
committer | Jovansonlee Cesar <ivanceras@gmail.com> | 2020-11-25 16:53:19 +0800 |
commit | dcd65f2361f88b7cbc9e81b91382f21c60114706 (patch) | |
tree | 17bae69413c2df41c8e5061a7955880fd41aed52 | |
parent | 4af1321cb8126ed2d749e4fdb862e9e47bb1ae87 (diff) |
Reimplement merging of line and arrow_head + diamond
-rw-r--r-- | svgbob/src/buffer/fragment_buffer.rs | 12 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/direction.rs | 4 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment.rs | 86 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/line.rs | 47 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/polygon.rs | 49 | ||||
-rw-r--r-- | svgbob/src/map/ascii_map.rs | 14 | ||||
-rw-r--r-- | svgbob/src/map/unicode_map.rs | 25 | ||||
-rw-r--r-- | svgbob/test_data/merge.bob | 68 |
8 files changed, 202 insertions, 103 deletions
diff --git a/svgbob/src/buffer/fragment_buffer.rs b/svgbob/src/buffer/fragment_buffer.rs index a7bda18..39846f5 100644 --- a/svgbob/src/buffer/fragment_buffer.rs +++ b/svgbob/src/buffer/fragment_buffer.rs @@ -130,12 +130,8 @@ impl FragmentBuffer { // parameters and is derived from the cell position let abs_frag = frag.absolute_position(*cell); let had_merged = merged.iter_mut().rev().any(|mfrag| { - if mfrag.can_merge(&abs_frag) { - if let Some(new_merge) = mfrag.merge(&abs_frag) { - *mfrag = new_merge; - } else { - panic!("Should merged"); - } + if let Some(new_merge) = mfrag.merge(&abs_frag) { + *mfrag = new_merge; true } else { false @@ -163,8 +159,8 @@ impl FragmentBuffer { let mut new_fragments: Vec<Fragment> = vec![]; for fragment in fragments.into_iter() { let is_merged = new_fragments.iter_mut().rev().any(|new_frag| { - if new_frag.can_merge(&fragment) { - *new_frag = new_frag.merge(&fragment).expect("should merge"); + if let Some(new_merged) = new_frag.merge(&fragment) { + *new_frag = new_merged; true } else { false diff --git a/svgbob/src/buffer/fragment_buffer/direction.rs b/svgbob/src/buffer/fragment_buffer/direction.rs index 25ec3db..3eedaa8 100644 --- a/svgbob/src/buffer/fragment_buffer/direction.rs +++ b/svgbob/src/buffer/fragment_buffer/direction.rs @@ -1,7 +1,7 @@ use crate::buffer::CellGrid; use crate::fragment::PolygonTag; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub enum Direction { TopLeft, Top, @@ -27,6 +27,7 @@ impl Direction { Direction::BottomRight => Direction::TopLeft, } } + /* pub(crate) fn any_along_side(&self, tags: &[PolygonTag]) -> bool { tags.iter().any(|tag| self.is_along_side(tag)) } @@ -60,6 +61,7 @@ impl Direction { }, } } + */ /// calculate the threshold length which is the basis /// if the arrow and the line is connected diff --git a/svgbob/src/buffer/fragment_buffer/fragment.rs b/svgbob/src/buffer/fragment_buffer/fragment.rs index dd62235..7fd5cb9 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment.rs @@ -97,52 +97,6 @@ impl Fragment { } } - /// check if 2 fragments can merge into one - /// FIXME: This is only merging lines and text right now - pub fn can_merge(&self, other: &Self) -> bool { - match (self, other) { - // line and line - (Fragment::Line(line), Fragment::Line(other_line)) => line.can_merge(other_line), - - /* - // line and polygon - (Fragment::Line(line), Fragment::Polygon(polygon)) => line.can_merge_polygon(polygon), - - // polygon and line - (Fragment::Polygon(polygon), Fragment::Line(line)) => line.can_merge_polygon(polygon), - */ - - /* - // line and marker_line - (Fragment::Line(line), Fragment::MarkerLine(mline)) => { - line.can_merge_marker_line(mline) - } - - // marker_line and line - (Fragment::MarkerLine(mline), Fragment::Line(line)) => { - line.can_merge_marker_line(mline) - } - (Fragment::MarkerLine(mline), Fragment::Polygon(polygon)) => { - mline.can_merge_polygon(polygon) - } - */ - - //TODO: make a function level2 merge where it merges fragments into - // marker_lines - /* - // line and circle - (Fragment::Line(line), Fragment::Circle(circle)) => line.can_merge_circle(circle), - // circle and line - (Fragment::Circle(circle), Fragment::Line(line)) => line.can_merge_circle(circle), - */ - // cell_text and cell_text - (Fragment::CellText(ctext), Fragment::CellText(other_ctext)) => { - ctext.can_merge(other_ctext) - } - _ => false, - } - } - /// FIXME: This is only merging lines and text right now pub fn merge(&self, other: &Self) -> Option<Self> { match (self, other) { @@ -155,13 +109,11 @@ impl Fragment { } } - /* // line and polygon (Fragment::Line(line), Fragment::Polygon(polygon)) => line.merge_line_polygon(polygon), // polygon and line (Fragment::Polygon(polygon), Fragment::Line(line)) => line.merge_line_polygon(polygon), - */ /* // line and marker_line @@ -214,8 +166,8 @@ impl Fragment { let mut new_groups: Vec<Self> = vec![]; for fragment in fragments.into_iter() { let is_merged = new_groups.iter_mut().rev().any(|new_group| { - if new_group.can_merge(&fragment) { - *new_group = new_group.merge(&fragment).expect("must merge"); + if let Some(new_merged) = new_group.merge(&fragment) { + *new_group = new_merged; true } else { false @@ -673,9 +625,37 @@ mod tests { let n = CellGrid::n(); let o = CellGrid::o(); let j = CellGrid::j(); - assert!(line(k, m).can_merge(&line(m, o))); // collinear and connected - assert!(!line(k, l).can_merge(&line(n, o))); //collinear but not connected - assert!(!line(k, o).can_merge(&line(o, j))); // connected but not collinear + assert!(line(k, m).merge(&line(m, o)).is_some()); // collinear and connected + assert!(!line(k, l).merge(&line(n, o)).is_some()); //collinear but not connected + assert!(!line(k, o).merge(&line(o, j)).is_some()); // connected but not collinear + } + + #[test] + fn merge_unicode_triangle_and_line() { + let arrow = '▶'; + let entry = crate::map::UNICODE_FRAGMENTS + .get(&arrow) + .expect("must have a fragement"); + let a = CellGrid::a(); + let y = CellGrid::y(); + + let polygon = entry[0].absolute_position(Cell::new(0, 0)); + let diagonal: Fragment = Line::new_noswap(y, a, false).into(); + let diagonal = diagonal.absolute_position(Cell::new(1, 1)); + + println!("polygon: {:#?}", polygon); + println!("diagonal: {:#?}", diagonal); + + let merged = polygon.merge(&diagonal); + + let expected = marker_line( + Point::new(2.0, 4.0), + Point::new(0.0, 0.0), + false, + None, + Some(Marker::Arrow), + ); + assert_eq!(Some(expected), merged); } #[test] diff --git a/svgbob/src/buffer/fragment_buffer/fragment/line.rs b/svgbob/src/buffer/fragment_buffer/fragment/line.rs index c060f97..7fe37cf 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/line.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/line.rs @@ -308,29 +308,20 @@ impl Line { // check also if the distance of this line end-point to the center // of the polygon is less than the diagonal width of the cell grid. let poly_center = polygon.center(); + + println!("poly_center: {:?}", poly_center); let distance_end_center = self.end.distance(&poly_center); let distance_start_center = self.start.distance(&poly_center); - let threshold_length = self.heading().threshold_length(); - let is_close_start_point = distance_start_center < threshold_length; - let is_close_end_point = distance_end_center < threshold_length; - - let direction = polygon.tags.get(0).map(|tag| tag.direction()).flatten(); + let threshold_length = dbg!(self.heading().threshold_length()); + let is_close_start_point = dbg!(distance_start_center < threshold_length); + let is_close_end_point = dbg!(distance_end_center < threshold_length); - let is_same_direction = polygon - .tags - .iter() - .any(|tag| tag.matched_direction(self.heading())); + let is_same_direction = dbg!(polygon.matched_direction(self.heading())); - //TODO: deal with merging with the opposite direction - /* - let is_opposite = polygon - .tags - .iter() - .any(|tag| tag.matched_direction(self.heading().opposite())); - */ + let is_opposite_direction = dbg!(polygon.matched_direction(self.heading().opposite())); - is_same_direction && (is_close_start_point || is_close_end_point) + (is_same_direction || is_opposite_direction) && (is_close_start_point || is_close_end_point) } /// TODO: the get_marker function don't take into account the direction @@ -341,9 +332,7 @@ impl Line { /// merge this line to the marker line pub(crate) fn merge_line_polygon(&self, polygon: &Polygon) -> Option<Fragment> { if self.can_merge_polygon(polygon) { - let marker = polygon.tags.get(0).map(|tag| tag.get_marker()); - let direction = polygon.tags.get(0).map(|tag| tag.direction()).flatten(); - let heading = self.heading(); + let marker = polygon.get_marker(); let poly_center = polygon.center(); let distance_end_center = self.end.distance(&poly_center); @@ -353,17 +342,9 @@ impl Line { let is_close_start_point = distance_start_center < threshold_length; let is_close_end_point = distance_end_center < threshold_length; - let is_same_direction = polygon - .tags - .iter() - .any(|tag| tag.matched_direction(self.heading())); + let is_same_direction = dbg!(polygon.matched_direction(self.heading())); - let is_opposite = polygon - .tags - .iter() - .any(|tag| tag.matched_direction(self.heading().opposite())); - - let is_diamond = Some(Marker::Diamond) == marker; + let is_opposite_direction = dbg!(polygon.matched_direction(self.heading().opposite())); let new_line = if is_close_end_point { Line::new_noswap(self.start, self.end, self.is_broken) @@ -375,12 +356,6 @@ impl Line { }; let mut extended_line = new_line.extend(threshold_length); - //TODO: deal with the opposite direction - /* - if !is_diamond && is_opposite { - extended_line.swap(); - } - */ Some(marker_line( extended_line.start, extended_line.end, diff --git a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs index dc0f1b3..7143584 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs @@ -1,5 +1,6 @@ use crate::Direction; use crate::{ + buffer::CellGrid, fragment::{ marker_line::{Marker, MarkerLine}, Bounds, @@ -90,6 +91,22 @@ impl PolygonTag { true } } + + /* + /// calculate the threshold length which is the basis + /// if the arrow and the line is connected + pub(crate) fn threshold_length(&self) -> f32 { + match self { + PolygonTag::ArrowTopRight + | PolygonTag::ArrowBottomRight + | PolygonTag::ArrowBottomLeft + | PolygonTag::ArrowTopLeft => CellGrid::diagonal_length(), + PolygonTag::ArrowBottom | PolygonTag::ArrowTop => CellGrid::height(), + PolygonTag::ArrowLeft | PolygonTag::ArrowRight => CellGrid::width(), + PolygonTag::DiamondBullet => CellGrid::diagonal_length(), + } + } + */ } impl Polygon { @@ -114,6 +131,38 @@ impl Polygon { } } + pub(crate) fn matched_direction(&self, direction: Direction) -> bool { + self.tags.iter().any(|tag| tag.matched_direction(direction)) + } + + fn is_diamond(&self) -> bool { + self.tags.len() == 1 + && self + .tags + .iter() + .all(|tag| *tag == PolygonTag::DiamondBullet) + } + + /// returns Diamond marker if the tags is a DiamondBullet + /// otherwise if it is an Arrow direction, then return Arrow. + pub(crate) fn get_marker(&self) -> Option<Marker> { + if !self.tags.is_empty() { + if self.is_diamond() { + Some(Marker::Diamond) + } else if self + .tags + .iter() + .all(|tag| tag.get_marker() == Marker::Arrow) + { + Some(Marker::Arrow) + } else { + None + } + } else { + None + } + } + pub(in crate) fn scale(&self, scale: f32) -> Self { let points: Vec<Point> = self.points.iter().map(|p| p.scale(scale)).collect(); Polygon { diff --git a/svgbob/src/map/ascii_map.rs b/svgbob/src/map/ascii_map.rs index 3d6d404..c340b20 100644 --- a/svgbob/src/map/ascii_map.rs +++ b/svgbob/src/map/ascii_map.rs @@ -359,10 +359,18 @@ lazy_static! { Arc::new( move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { vec![ + // + // | # + // # | --# #-- + // (top.line_overlap(r,w) || bottom.line_overlap(c,h) || left.line_overlap(n,o) || right.line_overlap(k,l), vec![rect(f,t, true, false)]), + // + // \ # / # + // # \ # / + // (top_left.line_overlap(s,y)|| bottom_right.line_overlap(a,g) || bottom_left.line_overlap(u,q) || top_right.line_overlap(e,i), vec![polygon(vec![k,h,o,r,k],true, vec![DiamondBullet])]), @@ -861,7 +869,7 @@ lazy_static! { //////////////////////// ('V', vec![ - (Medium, vec![polygon(vec![f,j,w], true, vec![ArrowBottom])]), + (Medium, vec![polygon(vec![f,j,w], true, vec![ArrowBottom, ArrowBottomLeft, ArrowBottomRight])]), (Weak, vec![line(m,w)]), ], Arc::new( @@ -895,7 +903,7 @@ lazy_static! { //////////////////////// ('v', vec![ - (Medium, vec![polygon(vec![f,j,w], true, vec![ArrowBottom])]), + (Medium, vec![polygon(vec![f,j,w], true, vec![ArrowBottom, ArrowBottomLeft, ArrowBottomRight])]), ], Arc::new( move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { @@ -927,7 +935,7 @@ lazy_static! { //////////////////////// ('^', vec![ - (Medium, vec![polygon(vec![p,c,t], true, vec![ArrowTop])]), + (Medium, vec![polygon(vec![p,c,t], true, vec![ArrowTop, ArrowTopLeft, ArrowTopRight])]), ], Arc::new( move|settings, top_left, top, top_right, left, right, bottom_left, bottom, bottom_right| { diff --git a/svgbob/src/map/unicode_map.rs b/svgbob/src/map/unicode_map.rs index bca9ef0..66afb73 100644 --- a/svgbob/src/map/unicode_map.rs +++ b/svgbob/src/map/unicode_map.rs @@ -162,10 +162,23 @@ lazy_static! { ('△', vec![line(c,y), line(y,u), line(u,c)]), // arrow down matching v + // + // | + // ▾ ('▾', vec![polygon(vec![f,j,w], true, vec![ArrowBottom])]), + // + // ▴ + // | ('▴', vec![polygon(vec![p,c,t], true, vec![ArrowTop])]), + // + // --▸ + // ('▸', vec![polygon(vec![f,o,p], true, vec![ArrowRight])]), + // + // ◂-- + // ('◂', vec![polygon(vec![j,k,t], true, vec![ArrowLeft])]), + ('◆', vec![polygon(vec![k,h,o,r,k], true, vec![DiamondBullet])]), ('▪', vec![rect(f,t,true, false)]), @@ -186,9 +199,17 @@ lazy_static! { // 8/8 ('█', vec![rect(a,y,true,false)]), + // / + // --▶ ▶ ▶ + // \ + // + ('▶', vec![polygon(vec![f,o,p], true, vec![ArrowRight, ArrowTopLeft, ArrowBottomLeft])]), - ('▶', vec![polygon(vec![f,o,p], true, vec![ArrowRight])]), - ('◀', vec![polygon(vec![j,k,t], true, vec![ArrowLeft])]), + // \ + // ◀-- ◀ ◀ + // / + // + ('◀', vec![polygon(vec![j,k,t], true, vec![ArrowLeft, ArrowBottomRight, ArrowTopRight])]), // L shape bottom-left box diff --git a/svgbob/test_data/merge.bob b/svgbob/test_data/merge.bob index 5f63a78..8770313 100644 --- a/svgbob/test_data/merge.bob +++ b/svgbob/test_data/merge.bob @@ -10,6 +10,74 @@ | ____ '--> /___/ +.-------. +| Hello | +'-------' + | + v +.-------. +| World | +'-------' + + + | + v +----------------> + | + | + + +.----------. .----------. +|{w} A |-->|{w} B | +'----------' '----------' + +.----------. .----------. +|{w} A |<--|{w} B | +'----------' '----------' + +.----------. .----------. +|{w} A |<->|{w} B | +'----------' '----------' + +.~~~~~~~~~~~~~~~~~~~~. +! ⛑️Problem Emoji : +! ⛑️ Problem Emoji : +! ⛑️ Problem Emoji : +! ⛑️ Problem Emoji : +'~~~~~~~~~~~~~~~~~~~~' + + +<--+----+----+----+----+----+----+----+----+--> + | | | | | | | | | + "-4" "-3" "-2" "-1" "0" "+1" "+2" "+3" "+4" + + + *----. +--+ ab | + | ab | +--*----' + + + + + + + -------▸ + + + ◂------ + + + / + / + ---▶ ▶ ▶ + \ + \ + + \ + \ + ◀---- ◀ ◀ + / + / # ^ ^ # O ^ |