summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJovansonlee Cesar <ivanceras@gmail.com>2018-08-13 13:22:59 +0800
committerJovansonlee Cesar <ivanceras@gmail.com>2018-08-13 13:22:59 +0800
commit90f428599c9b68313105410fcda142f712e3f57b (patch)
treeb08755f2b22ba00c14467b7686dbbe2d513eb335
parentbb99d8ec8bb537a6de395598724239041afe2db7 (diff)
group elements that shares endpoints
-rw-r--r--svgbob/src/element.rs30
-rw-r--r--svgbob/src/grid.rs83
-rw-r--r--svgbob/src/optimizer.rs35
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