diff options
author | Jovansonlee Cesar <ivanceras@gmail.com> | 2018-08-13 13:22:59 +0800 |
---|---|---|
committer | Jovansonlee Cesar <ivanceras@gmail.com> | 2018-08-13 13:22:59 +0800 |
commit | 90f428599c9b68313105410fcda142f712e3f57b (patch) | |
tree | b08755f2b22ba00c14467b7686dbbe2d513eb335 | |
parent | bb99d8ec8bb537a6de395598724239041afe2db7 (diff) |
group elements that shares endpoints
-rw-r--r-- | svgbob/src/element.rs | 30 | ||||
-rw-r--r-- | svgbob/src/grid.rs | 83 | ||||
-rw-r--r-- | svgbob/src/optimizer.rs | 35 |
3 files changed, 87 insertions, 61 deletions
diff --git a/svgbob/src/element.rs b/svgbob/src/element.rs index f7e0a41..4dfe1a5 100644 --- a/svgbob/src/element.rs +++ b/svgbob/src/element.rs @@ -25,7 +25,9 @@ use unicode_width::UnicodeWidthStr; #[derive(Debug, Clone, PartialEq, PartialOrd )] pub enum Element { Circle(Point, f32, String), + // start, end, stroke , start_feature, end feature Line(Point, Point, Stroke, Feature, Feature), + // start, end, radius, sweep, stroke, start_feat, end_feat Arc(Point, Point, f32, ArcFlag, bool, Stroke, Feature, Feature), Text(Loc, String), } @@ -114,6 +116,34 @@ pub fn text(loc: &Loc, txt: &str) -> Element { impl Element { + + pub fn shares_endpoints(&self, other: &Element) -> bool { + match *self{ + Element::Line(ref s, ref e, _, _,_) => { + match *other{ + Element::Line(ref s2, ref e2, _, _,_) => { + s == s2 || e == e2 || s == e2 || s2 == e + } + Element::Arc(ref s2, ref e2, _,_,_,_,_,_) => { + s == s2 || e == e2 || s == e2 || s2 == e + } + _ => false + } + } + Element::Arc(ref s, ref e, _,_,_,_,_,_) => { + match *other{ + Element::Line(ref s2, ref e2, _, _,_) => { + s == s2 || e == e2 || s == e2 || s2 == e + } + Element::Arc(ref s2, ref e2, _,_,_,_,_,_) => { + s == s2 || e == e2 || s == e2 || s2 == e + } + _ => false + } + } + _ => false + } + } // if this element can reduce the other, return the new reduced element // for line it has to be collinear and in can connect start->end->start // for text, the other text should apear on the right side of this text diff --git a/svgbob/src/grid.rs b/svgbob/src/grid.rs index aa1c984..155a8f9 100644 --- a/svgbob/src/grid.rs +++ b/svgbob/src/grid.rs @@ -11,6 +11,7 @@ use svg::node::element::{ Rectangle as SvgRect, Style, Circle as SvgCircle, + Group, }; use element::Element; use pom::TextInput; @@ -187,51 +188,25 @@ impl Grid { /// each component has its relative location retain /// use this info for optimizing svg by checking closest neigbor - fn get_svg_nodes(&self) -> Vec<SvgElement> { - let mut nodes = vec![]; + fn get_svg_nodes(&self) -> Vec<Vec<SvgElement>> { + let mut grouped_nodes = vec![]; let mut elements= self.get_all_elements(); let text_elm = self.get_escaped_text_elements(); elements.push(vec![text_elm]); - let input = if self.settings.optimize { - let mut optimizer = Optimizer::new(elements); - let mut optimized_elements = optimizer.optimize(&self.settings); - optimized_elements - } else { - // flatten Vec<Vec<Vec<Elements>>> to Vec<Element> - elements - .into_iter() - .flat_map(|elm| elm.into_iter().flat_map(|e2| e2)) - .collect() - }; - for elem in input { - let element: SvgElement = elem.to_svg(&self.settings); - nodes.push(element); - } - nodes - } - - pub fn get_svg_nodes_only(&self) -> String { - let nodes = self.get_svg_nodes(); - let mut svg = String::new(); - for node in nodes { - match node { - SvgElement::Circle(circle) => { - svg.push_str(&circle.to_string()); - } - SvgElement::Line(line) => { - svg.push_str(&line.to_string()); - } - SvgElement::Path(path) => { - svg.push_str(&path.to_string()); - } - SvgElement::Text(text) => { - svg.push_str(&text.to_string()); - } + let optimizer = Optimizer::new(elements); + let optimized_elements = optimizer.optimize(&self.settings); + for group in optimized_elements { + let mut svg_group = vec![]; + for elem in group{ + let element: SvgElement = elem.to_svg(&self.settings); + svg_group.push(element); } + grouped_nodes.push(svg_group); } - svg + grouped_nodes } + pub fn get_size(&self) -> (f32, f32) { let width = self.settings.text_width * self.columns() as f32; let height = self.settings.text_height * self.rows() as f32; @@ -240,7 +215,7 @@ impl Grid { /// get the generated svg according to the settings specified pub fn get_svg(&self) -> SVG { - let nodes = self.get_svg_nodes(); + let group_nodes = self.get_svg_nodes(); let (width, height) = self.get_size(); let mut svg = SVG::new(); @@ -268,21 +243,25 @@ impl Grid { .set("height", height); svg.append(rect); - for node in nodes { - match node { - SvgElement::Circle(circle) => { - svg.append(circle); - } - SvgElement::Line(line) => { - svg.append(line); - } - SvgElement::Path(path) => { - svg.append(path); - } - SvgElement::Text(text) => { - svg.append(text); + for group in group_nodes { + let mut svg_group = Group::new(); + for node in group{ + match node { + SvgElement::Circle(circle) => { + svg_group.append(circle); + } + SvgElement::Line(line) => { + svg_group.append(line); + } + SvgElement::Path(path) => { + svg_group.append(path); + } + SvgElement::Text(text) => { + svg_group.append(text); + } } } + svg.append(svg_group); } svg } diff --git a/svgbob/src/optimizer.rs b/svgbob/src/optimizer.rs index 326f26a..5526121 100644 --- a/svgbob/src/optimizer.rs +++ b/svgbob/src/optimizer.rs @@ -124,11 +124,9 @@ impl Optimizer { let mut cell_reduced = vec![]; for (j, elm2) in elements.iter().enumerate(){ if i != j { - //if !consumed.contains(&i) if !consumed.contains(&j){ if let Some(reduced) = elm.reduce(elm2){ cell_reduced.push(reduced); - //consumed.push(i); consumed.push(j); } } @@ -144,9 +142,32 @@ impl Optimizer { all_reduced } + /// grouped elements together that shares some end_points + fn group_elements<'e>(&self, elements: Vec<Element>) -> Vec<Vec<Element>> { + let mut consumed = vec![]; + let mut all_group = vec![]; + for (i, elm) in elements.iter().enumerate(){ + if !consumed.contains(&i){ + let mut cell_group = vec![]; + cell_group.push(elm.clone()); + consumed.push(i); + for (j, elm2) in elements.iter().enumerate(){ + if !consumed.contains(&j){ + if cell_group.iter().any(|e|e.shares_endpoints(&elm2)){ + cell_group.push(elm2.clone()); + consumed.push(j); + } + } + } + all_group.push(cell_group); + } + } + all_group + } + // TODO: order the elements in such a way that // the start -> end -> start chains nicely - pub fn optimize(&self, settings: &Settings) -> Vec<Element> { + pub fn optimize(&self, settings: &Settings) -> Vec<Vec<Element>> { let mut tracing_consumed_locs: Vec<(Loc,usize)> = vec![]; let mut optimized = vec![]; @@ -165,12 +186,8 @@ impl Optimizer { } optimized.sort(); optimized.dedup(); - let result = if settings.compact_path { - self.arrange_elements(optimized) - } else { - optimized - }; - result + let arranged = self.arrange_elements(optimized); + self.group_elements(arranged) } /// arrange elements listing in the svg document |