summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--svgbob/src/buffer.rs1
-rw-r--r--svgbob/src/buffer/fragment_buffer.rs2
-rw-r--r--svgbob/src/buffer/fragment_buffer/direction.rs76
-rw-r--r--svgbob/src/buffer/fragment_buffer/fragment/line.rs100
-rw-r--r--svgbob/src/buffer/fragment_buffer/fragment/marker_line.rs9
-rw-r--r--svgbob/src/buffer/fragment_buffer/fragment/polygon.rs24
-rw-r--r--svgbob/src/lib.rs3
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;