diff options
author | Jovansonlee Cesar <ivanceras@gmail.com> | 2018-07-29 02:48:05 +0800 |
---|---|---|
committer | Jovansonlee Cesar <ivanceras@gmail.com> | 2018-07-29 02:48:05 +0800 |
commit | d70b9bfb5b4f0770fabd01b0617c2a67e9e759f9 (patch) | |
tree | 1097d2fe7a9a2742c20b04d36a4a0415c4685fdd | |
parent | bba6ac50113845dc5739dcf80da9d1182b9c60e1 (diff) |
A good improvement on reducing the lines
-rw-r--r-- | svgbob/src/fragments.rs | 9 | ||||
-rw-r--r-- | svgbob/src/lib.rs | 187 | ||||
-rw-r--r-- | svgbob/src/optimizer.rs | 208 | ||||
-rw-r--r-- | svgbob/src/patterns.rs | 62 | ||||
-rw-r--r-- | svgbob/src/properties.rs | 34 |
5 files changed, 294 insertions, 206 deletions
diff --git a/svgbob/src/fragments.rs b/svgbob/src/fragments.rs index 2a3b153..c5c71fd 100644 --- a/svgbob/src/fragments.rs +++ b/svgbob/src/fragments.rs @@ -1,11 +1,12 @@ use self::Fragment::{Arc, ArrowLine, Line, OpenCircle, SolidCircle, StartArrowLine}; use properties::PointBlock; +use std::cmp::Ordering; /// exact location of point /// relative to the Character Block /// The block is divided in to 5x5 small blocks -#[derive(PartialEq, Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Ord, Eq)] pub enum Block { A, B, @@ -37,7 +38,8 @@ pub enum Block { /// These are non-final drawing elements /// Lines most likely fall on the collinear line /// arc most likely be changed -#[derive(Debug, Clone)] + +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)] pub enum Fragment { Line(PointBlock, PointBlock), ArrowLine(PointBlock, PointBlock), @@ -71,7 +73,8 @@ pub fn solid_circle(c: &PointBlock, r: i32) -> Fragment { /// \|/ /// -+- /// /|\ -#[derive(PartialEq, Debug, Clone)] + +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)] pub enum Direction { Top, Bottom, diff --git a/svgbob/src/lib.rs b/svgbob/src/lib.rs index 8f951c5..6b8f597 100644 --- a/svgbob/src/lib.rs +++ b/svgbob/src/lib.rs @@ -29,7 +29,7 @@ //! </svg> //! //! -#![deny(warnings)] +//#![deny(warnings)] extern crate pom; #[cfg(test)] #[macro_use] @@ -42,7 +42,6 @@ use pom::TextInput; use self::Feature::Arrow; use self::Feature::Circle; -use self::Feature::Nothing; use self::Stroke::Dashed; use self::Stroke::Solid; use fragments::Direction::{Bottom, BottomLeft, BottomRight, Left, Right, Top, TopLeft, TopRight}; @@ -61,6 +60,7 @@ use svg::node::element::SVG; use svg::Node; use unicode_width::UnicodeWidthChar; use unicode_width::UnicodeWidthStr; +use std::cmp::Ordering; use ArcFlag::{Major, Minor}; @@ -204,24 +204,35 @@ impl std::fmt::Debug for SvgElement { } } -#[derive(PartialEq, Debug, Clone)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] pub enum Stroke { Solid, Dashed, } -#[derive(PartialEq, Debug, Clone)] + +#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)] pub enum Feature { Arrow, //end Circle, //start - Nothing, } -#[derive(PartialEq, Debug, Clone)] +#[derive(Debug, PartialOrd, PartialEq, Clone)] pub struct Point { x: f32, y: f32, } +impl Ord for Point{ + fn cmp(&self, other:&Point) -> Ordering{ + if let Some(order) = self.partial_cmp(other){ + return order + } + Ordering::Less + } +} +impl Eq for Point{ +} + impl Point { fn new(x: f32, y: f32) -> Point { Point { x: x, y: y } @@ -232,12 +243,21 @@ impl Point { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq)] pub struct Loc { pub x: i32, pub y: i32, } +impl Ord for Loc{ + fn cmp(&self, other:&Loc) -> Ordering{ + if let Some(order) = self.partial_cmp(other){ + return order + } + Ordering::Less + } +} + impl Loc { pub fn new(x: i32, y: i32) -> Loc { Loc { x: x, y: y } @@ -341,23 +361,23 @@ impl Loc { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub enum ArcFlag { Major, Minor, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, PartialOrd )] pub enum Element { Circle(Point, f32, String), - Line(Point, Point, Stroke, Feature), - Arc(Point, Point, f32, ArcFlag, bool, Stroke, Feature), + Line(Point, Point, Stroke, Vec<Feature>), + Arc(Point, Point, f32, ArcFlag, bool, Stroke, Vec<Feature>), Text(Loc, String), Path(Point, Point, String, Stroke), } pub fn line(a: &Point, b: &Point) -> Element { - Element::Line(a.clone(), b.clone(), Solid, Nothing) + Element::Line(a.clone(), b.clone(), Solid, vec![]) } pub fn solid_circle(c: &Point, r: f32) -> Element { @@ -365,19 +385,19 @@ pub fn solid_circle(c: &Point, r: f32) -> Element { } pub fn arrow_arc(a: &Point, b: &Point, r: f32) -> Element { - Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, Arrow) + Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, vec![Arrow]) } pub fn arrow_sweep_arc(a: &Point, b: &Point, r: f32) -> Element { - Element::Arc(a.clone(), b.clone(), r.clone(), Minor, true, Solid, Arrow) + Element::Arc(a.clone(), b.clone(), r.clone(), Minor, true, Solid, vec![Arrow]) } pub fn arc(a: &Point, b: &Point, r: f32) -> Element { - Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, Nothing) + Element::Arc(a.clone(), b.clone(), r, Minor, false, Solid, vec![]) } pub fn arc_major(a: &Point, b: &Point, r: f32) -> Element { - Element::Arc(a.clone(), b.clone(), r, Major, false, Solid, Nothing) + Element::Arc(a.clone(), b.clone(), r, Major, false, Solid, vec![]) } pub fn open_circle(c: &Point, r: f32) -> Element { @@ -385,7 +405,7 @@ pub fn open_circle(c: &Point, r: f32) -> Element { } pub fn arrow_line(s: &Point, e: &Point) -> Element { - Element::Line(s.clone(), e.clone(), Solid, Arrow) + Element::Line(s.clone(), e.clone(), Solid, vec![Arrow]) } pub fn text(loc: &Loc, txt: &str) -> Element { @@ -406,20 +426,82 @@ impl Element { match *other { Element::Line(ref s2, ref e2, ref stroke2, ref feature2) => { // note: dual 3 point check for trully collinear lines - if collinear(s, e, s2) && collinear(s, e, e2) && e == s2 - && stroke == stroke2 && *feature == Nothing - && *feature2 != Circle - { - let reduced = Some(Element::Line( - s.clone(), - e2.clone(), - stroke.clone(), - feature2.clone(), - )); - reduced - } else { - None + if collinear(s, e, s2) + && collinear(s, e, e2) + && stroke == stroke2{ + // line1 line2 + // s-----e s2-----e2 + // s----------------e2 + if e == s2 { + // ----- + // o---- + let cond1 = feature.is_empty() || feature.contains(&Circle); + // ------ + // ------> + let cond2 = feature2.is_empty() || feature2.contains(&Arrow) ; + if cond1 && cond2{ + return Some(Element::Line( + s.clone(), + e2.clone(), + stroke.clone(), + feature2.clone() + )); + } + } + // line1 line2 + // s------e e2-------s2 + // s-------------------s2 + if e == e2{ + // ------- -------- + // o------ --------- + if (feature.is_empty() || feature.contains(&Circle) ) + && feature2.is_empty(){ + return Some(Element::Line( + s.clone(), + s2.clone(), + stroke.clone(), + feature2.clone() + )); + } + } + // line1 line2 + // e------s s2------e2 + // s------------------e2 + if s == s2{ + // ------- ------- + // ------- -------> + if feature.is_empty() + && (feature2.is_empty() || feature2.contains(&Arrow)){ + return Some(Element::Line( + e.clone(), + e2.clone(), + stroke.clone(), + feature2.clone() + )); + } + } + // line1 line2 + // e------s e2------s2 + // e---------------------s2 + // + if s == e2{ + // ----- ----- + // ----- ----o + // <---- ----- + // <---- ----o + let cond1 = feature.is_empty() || feature.contains(&Arrow); + let cond2 = feature2.is_empty() || feature2.contains(&Circle); + if cond1 && cond2{ + return Some(Element::Line( + s2.clone(), + e.clone(), + stroke.clone(), + feature.clone(), + )); + } + } } + return None; } _ => None, } @@ -456,22 +538,22 @@ impl Element { SvgElement::Circle(svg_circle) } - Element::Line(ref s, ref e, ref stroke, ref feature) => { + Element::Line(ref s, ref e, ref stroke, ref features) => { let mut svg_line = SvgLine::new() .set("x1", s.x) .set("y1", s.y) .set("x2", e.x) .set("y2", e.y); - - match *feature { - Arrow => { - svg_line.assign("marker-end", "url(#triangle)"); - } - Circle => { - svg_line.assign("marker-start", "url(#circle)"); - } - Nothing => (), - }; + for feature in features{ + match *feature { + Arrow => { + svg_line.assign("marker-end", "url(#triangle)"); + } + Circle => { + svg_line.assign("marker-start", "url(#circle)"); + } + }; + } match *stroke { Solid => (), Dashed => { @@ -482,7 +564,7 @@ impl Element { SvgElement::Line(svg_line) } - Element::Arc(ref s, ref e, radius, ref arc_flag, sweep, _, ref feature) => { + Element::Arc(ref s, ref e, radius, ref arc_flag, sweep, _, ref features) => { let sweept = if sweep { "1" } else { "0" }; let arc_flag = match *arc_flag { Major => "1", @@ -493,15 +575,16 @@ impl Element { s.x, s.y, radius, radius, arc_flag, sweept, e.x, e.y ); let mut svg_arc = SvgPath::new().set("d", d).set("fill", "none"); - match *feature { - Arrow => { - svg_arc.assign("marker-end", "url(#triangle)"); - } - Circle => { - svg_arc.assign("marker-start", "url(#circle)"); - } - Nothing => (), - }; + for feature in features{ + match *feature { + Arrow => { + svg_arc.assign("marker-end", "url(#triangle)"); + } + Circle => { + svg_arc.assign("marker-start", "url(#circle)"); + } + }; + } SvgElement::Path(svg_arc) } Element::Text(ref loc, ref string) => { @@ -810,7 +893,7 @@ impl Grid { let text_elm = self.get_escaped_text_elements(); elements.push(vec![text_elm]); let input = if self.settings.optimize { - let optimizer = Optimizer::new(elements, consumed_loc); + let mut optimizer = Optimizer::new(elements, consumed_loc); let optimized_elements = optimizer.optimize(&self.settings); optimized_elements } else { diff --git a/svgbob/src/optimizer.rs b/svgbob/src/optimizer.rs index 004fd2e..12c1926 100644 --- a/svgbob/src/optimizer.rs +++ b/svgbob/src/optimizer.rs @@ -8,6 +8,7 @@ use ArcFlag; pub struct Optimizer { elements: Vec<Vec<Vec<Element>>>, + /// TODO: consumed location should also include the consumed element index of that location. consumed_loc: Vec<Loc>, } @@ -19,9 +20,6 @@ impl Optimizer { } } - fn in_consumed_loc(&self, loc: &Loc) -> bool { - self.consumed_loc.contains(loc) - } fn get(&self, loc: &Loc) -> Option<&Vec<Element>> { match self.elements.get(loc.y as usize) { @@ -30,88 +28,96 @@ impl Optimizer { } } - // return the first element only - // there is only one element in the component - fn first_element_only(&self, loc: &Loc) -> Option<&Element> { - match self.get(loc) { - Some(elements) => { - if elements.len() == 1 { - elements.get(0) - } else { - None + + + // return the reduced element and the index of the matching element on this location + fn reduce(&self, elm1: &Element, loc2: &Loc) -> Option<(Vec<Element>, usize)> { + // try all the elments of this location + if let Some(elements2) = self.get(loc2){ + if elements2.len() > 0 { + for (i,elm2) in elements2.iter().enumerate(){ + // use the element that can be reduced with + if let Some(reduced) = elm1.reduce(&elm2){ + let mut new_reduced = vec![]; + new_reduced.push(reduced); + return Some((new_reduced, i)); + } } } - None => None, } + None + } - - // if the path on this location can be eated - // from the left, from the top - fn is_edible(&self, loc: &Loc) -> bool { - self.can_loc_reduce(&loc.top(), loc) || self.can_loc_reduce(&loc.left(), loc) - || self.can_loc_reduce(&loc.top_left(), loc) - || self.can_loc_reduce(&loc.bottom_left(), loc) - || self.can_loc_reduce(&loc.left().left(), loc) //full width character CJK can reduce 2 cells apart - } - // determine if element in location1 - // can reduce the element in location2 - fn can_loc_reduce(&self, loc1: &Loc, loc2: &Loc) -> bool { - match self.first_element_only(loc1) { - Some(elm1) => self.reduce(elm1, loc2).is_some(), - None => false, + fn trace_elements(&self, element: &Element, loc: &Loc) -> (Vec<Element>, Vec<(Loc, usize)>) { + //trace to the right first + let right = loc.right(); + let bottom = loc.bottom(); + let bottom_right = loc.bottom_right(); + let bottom_left = loc.bottom_left(); + if let Some((all_reduced, elm_index)) = self.reduce(element, &right){ + let mut all_consumed:Vec<(Loc, usize)> = vec![]; + let mut only_reduced = vec![]; + for reduced_elm in all_reduced{ + let (reduced, consumed) = self.trace_elements(&reduced_elm, &right); + all_consumed.push((right.clone(), elm_index)); + all_consumed.extend(consumed); + only_reduced = reduced; + } + (only_reduced, all_consumed) } - } - - fn reduce(&self, elm1: &Element, loc2: &Loc) -> Option<Element> { - let elm2 = self.first_element_only(loc2); - match elm2 { - Some(elm2) => elm1.reduce(elm2), - None => None, + else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom){ + let mut all_consumed = vec![]; + let mut only_reduced = vec![]; + for reduced_elm in all_reduced{ + let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom); + all_consumed.push((bottom.clone(), elm_index)); + all_consumed.extend(consumed); + only_reduced = reduced; + } + (only_reduced, all_consumed) } - } - fn trace_elements(&self, element: &Element, loc: &Loc) -> Element { - match self.reduce(element, &loc.right()) { - Some(reduced) => self.trace_elements(&reduced, &loc.right()), - None => { - match self.reduce(element, &loc.bottom()) { - Some(reduced) => self.trace_elements(&reduced, &loc.bottom()), - None => { - match self.reduce(element, &loc.bottom_right()) { - Some(reduced) => self.trace_elements(&reduced, &loc.bottom_right()), - None => { - match self.reduce(element, &loc.top_right()) { - Some(reduced) => { - self.trace_elements(&reduced, &loc.top_right()) - } - None => { - //full width character CJK can reduce 2 cells apart - match self.reduce(element, &loc.right().right()) { - Some(reduced) => { - self.trace_elements(&reduced, &loc.right().right()) - } - None => element.clone(), - } - } - } - } - } - } - } + else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom_right){ + let mut all_consumed = vec![]; + let mut only_reduced = vec![]; + for reduced_elm in all_reduced{ + let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom_right); + all_consumed.push((bottom_right.clone(), elm_index)); + all_consumed.extend(consumed); + only_reduced = reduced; + } + (only_reduced, all_consumed) + } + else if let Some((all_reduced, elm_index)) = self.reduce(element, &bottom_left){ + let mut all_consumed = vec![]; + let mut only_reduced = vec![]; + for reduced_elm in all_reduced{ + let (reduced, consumed) = self.trace_elements(&reduced_elm, &bottom_left); + all_consumed.push((bottom_left.clone(),elm_index)); + all_consumed.extend(consumed); + only_reduced = reduced; } + (only_reduced, all_consumed) + } + else{ + (vec![element.to_owned()], vec![]) } } // TODO: order the elements in such a way that // the start -> end -> start chains nicely pub fn optimize(&self, settings: &Settings) -> Vec<Element> { + let completely_consumed_locs:Vec<Loc> = self.consumed_loc.clone(); + let mut tracing_consumed_locs: Vec<(Loc,usize)> = vec![]; let mut optimized = vec![]; for (y, line) in self.elements.iter().enumerate() { for (x, cell) in line.iter().enumerate() { let loc = &Loc::new(x as i32, y as i32); - for elm in cell { - if !self.is_edible(loc) && !self.in_consumed_loc(loc) { - let traced = self.trace_elements(elm, loc); - optimized.push(traced); + for (elm_index, elm) in cell.iter().enumerate() { + if !completely_consumed_locs.contains(loc) + && !tracing_consumed_locs.contains(&(loc.clone(),elm_index)){ + let (traced, consumed) = self.trace_elements(elm, loc); + optimized.extend(traced); + tracing_consumed_locs.extend(consumed); } } } @@ -126,8 +132,10 @@ impl Optimizer { // the text in separated fn merge_paths(&self, elements: Vec<Element>) -> Vec<Element> { let mut merged = vec![]; - let mut solid_paths = vec![]; - let mut dashed_paths = vec![]; + let mut solid_lines = vec![]; + let mut dashed_lines = vec![]; + let mut solid_arcs = vec![]; + let mut dashed_arcs = vec![]; let mut arrows = vec![]; let mut text = vec![]; let mut circles = vec![]; @@ -136,37 +144,47 @@ impl Optimizer { Element::Circle(_, _, _) => { circles.push(elm.clone()); } - Element::Line(_, _, ref stroke, ref feature) => match *feature { - Feature::Arrow => { - arrows.push(elm.clone()); - } - Feature::Circle => { - arrows.push(elm.clone()); + Element::Line(_, _, ref stroke, ref features) => { + for feature in features{ + match *feature { + Feature::Arrow => { + arrows.push(elm.clone()); + } + // circle at the end rather than arrow + Feature::Circle => { + arrows.push(elm.clone()); + } + } } - Feature::Nothing => match *stroke { + match *stroke { Stroke::Solid => { - solid_paths.push(elm.clone()); + solid_lines.push(elm.clone()); } Stroke::Dashed => { - dashed_paths.push(elm.clone()); + dashed_lines.push(elm.clone()); } - }, - }, - Element::Arc(_, _, _, _, _, ref stroke, ref feature) => match *feature { - Feature::Arrow => { - arrows.push(elm.clone()); } - Feature::Circle => { - arrows.push(elm.clone()); + }, + Element::Arc(_, _, _, _, _, ref stroke, ref features) => { + for feature in features{ + match *feature { + Feature::Arrow => { + arrows.push(elm.clone()); + } + Feature::Circle => { + arrows.push(elm.clone()); + } + } } - Feature::Nothing => match *stroke { + + match *stroke { Stroke::Solid => { - solid_paths.push(elm.clone()); + solid_arcs.push(elm.clone()); } Stroke::Dashed => { - dashed_paths.push(elm.clone()); + dashed_arcs.push(elm.clone()); } - }, + } }, Element::Text(_, _) => text.push(elm.clone()), Element::Path(_, _, _, _) => { @@ -174,8 +192,12 @@ impl Optimizer { } } } - merged.push(unify(solid_paths, Stroke::Solid)); - merged.push(unify(dashed_paths, Stroke::Dashed)); + //merged.push(unify(solid_paths, Stroke::Solid)); + //merged.push(unify(dashed_paths, Stroke::Dashed)); + merged.extend(solid_lines); + merged.extend(dashed_lines); + merged.extend(solid_arcs); + merged.extend(dashed_arcs); merged.extend(arrows); merged.extend(text); merged.extend(circles); @@ -184,7 +206,7 @@ impl Optimizer { } /// cramp all paths that can be connected here -fn unify(elements: Vec<Element>, stroke: Stroke) -> Element { +fn _unify(elements: Vec<Element>, stroke: Stroke) -> Element { let mut paths = String::new(); let mut last_loc = None; let mut start = None; diff --git a/svgbob/src/patterns.rs b/svgbob/src/patterns.rs index c1d2bff..32cd456 100644 --- a/svgbob/src/patterns.rs +++ b/svgbob/src/patterns.rs @@ -245,7 +245,7 @@ impl LocBlock { Y => lb.y(), }; let unit = self.unit_x(); - p.adjust(pb.adjust.0 * unit, pb.adjust.1 * unit); + p.adjust(pb.adjust_x * unit, pb.adjust_y * unit); p } } @@ -461,59 +461,20 @@ impl<'g> FocusChar<'g> { let mut consumed: Vec<Location> = vec![]; let mut matched_intended = false; - let mut matched_enhance = false; - let mut matched_circles = false; - let enable_round_circles = true; - let enable_enhancements = true; let enable_intended_behavior = true; let enable_default_properties = true; - // spaces has no character - // that's why enhance circle didn't work out well - // Issue#1 circle: The circle is matched by testing from the center - // however, each elements along the circle would also be - // threated as some other characters that has some other behaviors - // causing multiple artifacts as a result of multiple usage of the elements - // emitting fragments and merge all together when the circle is also matched. - // To solve the issue, checking of circle should be done first - // and then the consumed elements are skipped and checked - if enable_round_circles { - let (circles, circles_consumed, along_arc) = self.round(); - if !circles.is_empty() && !self.used_as_text() { - elm.extend(circles); - consumed.extend(circles_consumed); - // if circle is matched, and element is along the arc - // skip processing of other, - // otherwise, even if circle is matched and the element is NOT along arc - // do process other enhancement, behaviors - matched_circles = along_arc; - } - } if let Some(character) = character { - // enhancements - if enable_enhancements { - if !matched_circles { - let (enhanced, enhance_consumed) = self.enhance(); - if !enhanced.is_empty() && !self.used_as_text() { - elm.extend(enhanced); - consumed.extend(enhance_consumed); - matched_enhance = true; - } - } - } - // intended behaviors when signals are strong // after applying the intensifiers // do only when enhancements is not matched if enable_intended_behavior { - if !matched_enhance && !matched_circles { - for &(ref blocks, ref fragments) in &character.intended_behavior { - let meet = blocks.iter().all(|ref b| self.can_be_strong_block(&b)); - if meet && !self.used_as_text() { - elm.extend(fragments.clone()); - matched_intended = true; - } + for &(ref blocks, ref fragments) in &character.intended_behavior { + let meet = blocks.iter().all(|ref b| self.can_be_strong_block(&b)); + if meet && !self.used_as_text() { + elm.extend(fragments.clone()); + matched_intended = true; } } } @@ -523,7 +484,7 @@ impl<'g> FocusChar<'g> { // or the signal has been intensified to strong let mut matched = false; if enable_default_properties { - if !matched_enhance && !matched_circles && !matched_intended { + if !matched_intended { for &(ref block, ref _signal, ref fragments) in &character.properties { // draw when used as text but intensified if self.is_intensified(&block) && !self.used_as_text() { @@ -538,19 +499,22 @@ impl<'g> FocusChar<'g> { } } } - if !matched && !matched_intended && !matched_enhance && !matched_circles + if !matched && !matched_intended && !self.is_blank() { elm.push(Text(self.text())); } - (elm, consumed) } else { if !self.is_blank() { // This is to disconnect words elm.push(Text(self.text())); } - (elm, consumed) } + elm.sort(); + elm.dedup(); + consumed.sort(); + consumed.dedup(); + (elm, consumed) } fn get_settings(&self) -> Settings { diff --git a/svgbob/src/properties.rs b/svgbob/src/properties.rs index 8dc8d2f..92157be 100644 --- a/svgbob/src/properties.rs +++ b/svgbob/src/properties.rs @@ -11,6 +11,7 @@ use box_drawing; use fragments::Direction::{Bottom, BottomLeft, BottomRight, Left, Right, Top, TopLeft, TopRight}; use self::Can::{ConnectTo, Is, IsStrongAll}; +use std::cmp::{Ordering,Ord}; /// the strength of signal /// whether or not connects to the direction @@ -26,7 +27,8 @@ use self::Can::{ConnectTo, Is, IsStrongAll}; /// Strong + Weak connects /// Silent signals, are there but are not in used /// They are just potential and are reluctant -#[derive(PartialEq, Debug, Clone)] + +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)] pub enum Signal { Weak, Medium, @@ -38,7 +40,7 @@ pub enum Signal { /// a location in the grid /// relative to the focused char /// go to direction and how many steps to get there -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)] pub struct Location(pub Vec<(Direction, usize)>); impl Location { @@ -171,18 +173,29 @@ impl Location { PointBlock { location: Some(self.clone()), block: block, - adjust: (0.0, 0.0), + adjust_x: 0.0, + adjust_y: 0.0 } } } /// An exact point in the grid /// relative to the focused char -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialOrd, PartialEq)] pub struct PointBlock { pub location: Option<Location>, pub block: Block, - pub adjust: (f32, f32), + pub adjust_x: f32, + pub adjust_y: f32, +} + +impl Ord for PointBlock{ + fn cmp(&self, other: &PointBlock) -> Ordering{ + self.location.cmp(&other.location) + } +} + +impl Eq for PointBlock{ } impl PointBlock { @@ -190,7 +203,8 @@ impl PointBlock { PointBlock { location: None, block: block, - adjust: (0.0, 0.0), + adjust_x: 0.0, + adjust_y: 0.0, } } @@ -198,13 +212,15 @@ impl PointBlock { PointBlock { location: Some(Location::jump(direction, step)), block: block, - adjust: (0.0, 0.0), + adjust_x: 0.0, + adjust_y: 0.0, } } pub fn adjust(&self, x: f32, y: f32) -> Self { let mut pb = self.clone(); - pb.adjust = (pb.adjust.0 + x, pb.adjust.1 + y); + pb.adjust_x = pb.adjust_x + x; + pb.adjust_y = pb.adjust_y + y; pb } } @@ -341,6 +357,7 @@ impl Properties for char { ///////////////////////////////// if self.is('|') { Some(Characteristic { + properties: vec![(C, Strong, vec![line(c, w)]), (W, Strong, vec![line(c, w)])], intensify: vec![ // | // \ @@ -393,7 +410,6 @@ impl Properties for char { // | (vec![A], vec![line(w, m), line(m, a)]), ], - properties: vec![(C, Strong, vec![line(c, w)]), (W, Strong, vec![line(c, w)])], }) } ////////////////////////////// |