summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJovansonlee Cesar <ivanceras@gmail.com>2020-02-27 20:17:11 +0800
committerJovansonlee Cesar <ivanceras@gmail.com>2020-02-27 20:17:11 +0800
commit0fb7a8d352b3e1facd6b9092bec0449f1f3e5d4a (patch)
treee5a13c8e6166f4ffb2b3d37429a02ddc112ae0a6
parent881413f1d22db7004f452529d2c7f132063140af (diff)
Fix the behaviour of merging line and polygon tags, the direction of the arrow is now correct and only dealing with line that is in the same direction of the arrow marker
Merging line with arrow and heading with opposite direction is not yet dealth
-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;