diff options
-rw-r--r-- | svgbob/src/buffer.rs | 1 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer.rs | 2 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/direction.rs | 76 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/line.rs | 100 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/marker_line.rs | 9 | ||||
-rw-r--r-- | svgbob/src/buffer/fragment_buffer/fragment/polygon.rs | 24 | ||||
-rw-r--r-- | svgbob/src/lib.rs | 3 |
7 files changed, 154 insertions, 61 deletions
diff --git a/svgbob/src/buffer.rs b/svgbob/src/buffer.rs index 168c09f..867bd3c 100644 --- a/svgbob/src/buffer.rs +++ b/svgbob/src/buffer.rs @@ -1,4 +1,5 @@ pub use cell_buffer::{Cell, CellBuffer, CellGrid, Contacts, Settings, Span}; +pub use fragment_buffer::Direction; pub use fragment_buffer::{fragment, fragment::Fragment, FragmentBuffer}; pub use property_buffer::{Property, PropertyBuffer, Signal}; pub use string_buffer::StringBuffer; diff --git a/svgbob/src/buffer/fragment_buffer.rs b/svgbob/src/buffer/fragment_buffer.rs index 7f3c780..a7bda18 100644 --- a/svgbob/src/buffer/fragment_buffer.rs +++ b/svgbob/src/buffer/fragment_buffer.rs @@ -1,4 +1,5 @@ use crate::{buffer::Settings, Cell}; +pub use direction::Direction; pub use fragment::Fragment; pub use fragment_tree::FragmentTree; use itertools::Itertools; @@ -7,6 +8,7 @@ use std::{ ops::{Deref, DerefMut}, }; +pub mod direction; pub mod fragment; mod fragment_tree; diff --git a/svgbob/src/buffer/fragment_buffer/direction.rs b/svgbob/src/buffer/fragment_buffer/direction.rs new file mode 100644 index 0000000..25ec3db --- /dev/null +++ b/svgbob/src/buffer/fragment_buffer/direction.rs @@ -0,0 +1,76 @@ +use crate::buffer::CellGrid; +use crate::fragment::PolygonTag; + +#[derive(Debug, Clone, PartialEq)] +pub enum Direction { + TopLeft, + Top, + TopRight, + Left, + Right, + BottomLeft, + Bottom, + BottomRight, +} + +impl Direction { + /// return the opposite direction of self + pub(crate) fn opposite(&self) -> Self { + match self { + Direction::TopLeft => Direction::BottomRight, + Direction::Top => Direction::Bottom, + Direction::TopRight => Direction::BottomLeft, + Direction::Left => Direction::Right, + Direction::Right => Direction::Left, + Direction::BottomLeft => Direction::TopRight, + Direction::Bottom => Direction::Top, + Direction::BottomRight => Direction::TopLeft, + } + } + pub(crate) fn any_along_side(&self, tags: &[PolygonTag]) -> bool { + tags.iter().any(|tag| self.is_along_side(tag)) + } + /// diamon matches alongside for everything. + pub(crate) fn is_along_side(&self, tag: &PolygonTag) -> bool { + if *tag == PolygonTag::DiamondBullet { + return true; + } + match self { + Direction::TopLeft | Direction::BottomRight => match tag { + PolygonTag::ArrowTopLeft + | PolygonTag::ArrowBottomRight + | PolygonTag::ArrowTop + | PolygonTag::ArrowBottom => true, + _ => false, + }, + Direction::Top | Direction::Bottom => match tag { + PolygonTag::ArrowTop | PolygonTag::ArrowBottom => true, + _ => false, + }, + Direction::TopRight | Direction::BottomLeft => match tag { + PolygonTag::ArrowTopRight + | PolygonTag::ArrowBottomLeft + | PolygonTag::ArrowTop + | PolygonTag::ArrowBottom => true, + _ => false, + }, + Direction::Left | Direction::Right => match tag { + PolygonTag::ArrowLeft | PolygonTag::ArrowRight => true, + _ => false, + }, + } + } + + /// 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 { + Direction::TopLeft + | Direction::TopRight + | Direction::BottomLeft + | Direction::BottomRight => CellGrid::diagonal_length(), + Direction::Left | Direction::Right => CellGrid::width(), + Direction::Top | Direction::Bottom => CellGrid::height(), + } + } +} diff --git a/svgbob/src/buffer/fragment_buffer/fragment/line.rs b/svgbob/src/buffer/fragment_buffer/fragment/line.rs index 7e654c9..a69b5d4 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/line.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/line.rs @@ -4,7 +4,7 @@ use crate::{ Cell, CellGrid, Fragment, }, fragment::{marker_line, Bounds, Circle, Marker, MarkerLine}, - util, Point, + util, Direction, Point, }; use ncollide2d::{ math::Isometry, @@ -20,18 +20,6 @@ use sauron::{ Node, }; -#[derive(Debug, Clone, PartialEq)] -pub enum Direction { - TopLeft, - Top, - TopRight, - Left, - Right, - BottomLeft, - Bottom, - BottomRight, -} - #[derive(Debug, Clone)] pub struct Line { pub start: Point, @@ -39,48 +27,6 @@ pub struct Line { pub is_broken: bool, } -impl Direction { - /// diamon matches alongside for everything. - pub(crate) fn is_along_side(&self, tags: &[PolygonTag]) -> bool { - if tags.contains(&PolygonTag::DiamondBullet) { - return true; - } - match self { - Direction::TopLeft | Direction::BottomRight => { - tags.contains(&PolygonTag::ArrowTopLeft) - | tags.contains(&PolygonTag::ArrowBottomRight) - | tags.contains(&PolygonTag::ArrowTop) - | tags.contains(&PolygonTag::ArrowBottom) - } - Direction::Top | Direction::Bottom => { - tags.contains(&PolygonTag::ArrowTop) | tags.contains(&PolygonTag::ArrowBottom) - } - Direction::TopRight | Direction::BottomLeft => { - tags.contains(&PolygonTag::ArrowTopRight) - | tags.contains(&PolygonTag::ArrowBottomLeft) - | tags.contains(&PolygonTag::ArrowTop) - | tags.contains(&PolygonTag::ArrowBottom) - } - Direction::Left | Direction::Right => { - tags.contains(&PolygonTag::ArrowLeft) | tags.contains(&PolygonTag::ArrowRight) - } - } - } - - /// 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 { - Direction::TopLeft - | Direction::TopRight - | Direction::BottomLeft - | Direction::BottomRight => CellGrid::diagonal_length(), - Direction::Left | Direction::Right => CellGrid::width(), - Direction::Top | Direction::Bottom => CellGrid::height(), - } - } -} - impl Line { /// creates a new line and reorder the points swapping the end points if necessary /// such that the start is the most top-left and end point is the most bottom-right @@ -366,17 +312,36 @@ impl Line { let is_close_start_point = distance_start_center < threshold_length; let is_close_end_point = distance_end_center < threshold_length; - let is_along_side = self.heading().is_along_side(&polygon.tags); - is_along_side && (is_close_start_point || is_close_end_point) + let direction = polygon.tags.get(0).map(|tag| tag.direction()).flatten(); + + let is_same_direction = polygon + .tags + .iter() + .any(|tag| tag.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())); + */ + + is_same_direction && (is_close_start_point || is_close_end_point) } /// TODO: the get_marker function don't take into account the direction /// of the line from start to end. The direction is not followed. + /// TODO: If the marker direction is on opposite direction of the line + /// heading, swap the line start and end point /// /// 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 poly_center = polygon.center(); let distance_end_center = self.end.distance(&poly_center); let distance_start_center = self.start.distance(&poly_center); @@ -385,6 +350,18 @@ 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_opposite = polygon + .tags + .iter() + .any(|tag| tag.matched_direction(self.heading().opposite())); + + let is_diamond = Some(Marker::Diamond) == marker; + let new_line = if is_close_end_point { Line::new_noswap(self.start, self.end, self.is_broken) } else if is_close_start_point { @@ -393,7 +370,14 @@ impl Line { } else { panic!("There is no endpoint of the line is that close to the arrow"); }; - let extended_line = new_line.extend(threshold_length); + 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/marker_line.rs b/svgbob/src/buffer/fragment_buffer/fragment/marker_line.rs index 5c446af..7e57490 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/marker_line.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/marker_line.rs @@ -92,14 +92,19 @@ impl MarkerLine { let can_connect_start = is_close_start_point && self.start_marker.is_none(); let can_connect_end = is_close_end_point && self.end_marker.is_none(); - let is_along_side = self.line.heading().is_along_side(&polygon.tags); - is_along_side && (can_connect_start || can_connect_end) + let is_same_direction = polygon + .tags + .iter() + .any(|tag| tag.matched_direction(self.line.heading())); + + is_same_direction && (can_connect_start || can_connect_end) } /// merge this marker line to the polygon pub(crate) fn merge_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()); let poly_center = polygon.center(); let distance_end_center = self.line.end.distance(&poly_center); let distance_start_center = self.line.start.distance(&poly_center); diff --git a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs index ffafdec..b1a9239 100644 --- a/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs +++ b/svgbob/src/buffer/fragment_buffer/fragment/polygon.rs @@ -1,3 +1,4 @@ +use crate::Direction; use crate::{ fragment::{ marker_line::{Marker, MarkerLine}, @@ -65,6 +66,29 @@ impl PolygonTag { PolygonTag::DiamondBullet => Marker::Diamond, } } + + pub(crate) fn direction(&self) -> Option<Direction> { + match self { + PolygonTag::ArrowTopLeft => Some(Direction::TopLeft), + PolygonTag::ArrowTop => Some(Direction::Top), + PolygonTag::ArrowTopRight => Some(Direction::TopRight), + PolygonTag::ArrowLeft => Some(Direction::Left), + PolygonTag::ArrowRight => Some(Direction::Right), + PolygonTag::ArrowBottomLeft => Some(Direction::BottomLeft), + PolygonTag::ArrowBottom => Some(Direction::Bottom), + PolygonTag::ArrowBottomRight => Some(Direction::BottomRight), + PolygonTag::DiamondBullet => None, + } + } + + pub(crate) fn matched_direction(&self, arg: Direction) -> bool { + if let Some(direction) = self.direction() { + direction == arg + } else { + // DiamondBullet just match any direction + true + } + } } impl Polygon { diff --git a/svgbob/src/lib.rs b/svgbob/src/lib.rs index 4df3726..1d9e836 100644 --- a/svgbob/src/lib.rs +++ b/svgbob/src/lib.rs @@ -9,7 +9,8 @@ mod point; pub mod util; pub use buffer::{ - fragment, fragment::Fragment, Cell, CellBuffer, FragmentBuffer, Property, Settings, Signal, + fragment, fragment::Fragment, Cell, CellBuffer, Direction, FragmentBuffer, Property, Settings, + Signal, }; pub use point::Point; |