summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJovansonlee Cesar <ivanceras@gmail.com>2021-07-11 10:57:14 +0800
committerJovansonlee Cesar <ivanceras@gmail.com>2021-07-11 10:57:14 +0800
commit933541ad34ab813d20c232852a66f3023da9227d (patch)
tree6e8103a898d986756b964e6223b24eb9e38ec75f
parentb054e53fd44147c8716d5cb0337929d28e4f9848 (diff)
Calculate radius, center, center_cells based on the ascii art and EdgeCase specified
This also simplify the calculation of quadrant arcs
-rw-r--r--svgbob/src/buffer/cell_buffer/cell.rs18
-rw-r--r--svgbob/src/map/circle_map.rs362
-rw-r--r--svgbob/src/point.rs22
-rw-r--r--svgbob/test_data/circles.bob72
4 files changed, 283 insertions, 191 deletions
diff --git a/svgbob/src/buffer/cell_buffer/cell.rs b/svgbob/src/buffer/cell_buffer/cell.rs
index db54d8b..cf49dcb 100644
--- a/svgbob/src/buffer/cell_buffer/cell.rs
+++ b/svgbob/src/buffer/cell_buffer/cell.rs
@@ -184,7 +184,7 @@ impl Cell {
/// check if this cell is bounded by the lower bound and upper bound
pub fn is_bounded(&self, bound1: Cell, bound2: Cell) -> bool {
- let (lower_bound, upper_bound) = rearrange_bound(bound1, bound2);
+ let (lower_bound, upper_bound) = Self::rearrange_bound(bound1, bound2);
self.x >= lower_bound.x
&& self.y >= lower_bound.y
&& self.x <= upper_bound.x
@@ -297,15 +297,15 @@ impl Cell {
y: self.y + 1,
}
}
-}
-/// rearrange the bound of 2 cells
-pub fn rearrange_bound(bound1: Cell, bound2: Cell) -> (Cell, Cell) {
- let min_x = cmp::min(bound1.x, bound2.x);
- let min_y = cmp::min(bound1.y, bound2.y);
- let max_x = cmp::max(bound1.x, bound2.x);
- let max_y = cmp::max(bound1.y, bound2.y);
- (Cell::new(min_x, min_y), Cell::new(max_x, max_y))
+ /// rearrange the bound of 2 cells
+ pub fn rearrange_bound(bound1: Cell, bound2: Cell) -> (Cell, Cell) {
+ let min_x = cmp::min(bound1.x, bound2.x);
+ let min_y = cmp::min(bound1.y, bound2.y);
+ let max_x = cmp::max(bound1.x, bound2.x);
+ let max_y = cmp::max(bound1.y, bound2.y);
+ (Cell::new(min_x, min_y), Cell::new(max_x, max_y))
+ }
}
#[cfg(test)]
diff --git a/svgbob/src/map/circle_map.rs b/svgbob/src/map/circle_map.rs
index 3dcb05d..e2e9d41 100644
--- a/svgbob/src/map/circle_map.rs
+++ b/svgbob/src/map/circle_map.rs
@@ -36,92 +36,109 @@ lazy_static! {
/// 8└─┴─┴─┴─┘ U└─┴─┴─┴─┘Y
/// ``` V W X
/// art, center_cell, center_point, radius, edge_case, top_offset to center point
- pub static ref CIRCLE_MAP: Vec<(&'static str, Cell, Point, f32, EdgeCase, f32)> =
+ static ref CIRCLE_ART_MAP: Vec<(&'static str, EdgeCase, f32)> =
vec![
// CIRCLE_1
- //center 0,0,o, radius = 0.5
- // are circle arc touching the cell edge?:
- // x_edge: false
- // y_edge: true
+ //center 1,0,k, radius = 0.5
// 2 cell width , radius formula: (n-1)/2 = (2-1)/2 = 0.5
// where n is the number of cells used
// if edge_case starts at edge then n is added by 1.
// vert_mid: half (0.5/1.0)
+ // cx_lies: edge
+ // cy_lies: mid
+ //
+ // edge_case: start_half = 0.5, start_edge = 0.0
+ // if radius + edge_case has 0.5 then mid, 0.0 them edge
+ //
+ //
(r#"
()
- "#, Cell::new(1,0), Cell::new(1,0).k(), 0.5, EdgeCase::StartHalf, 0.5),
+ "#, EdgeCase::StartHalf, 0.5),
// CIRCLE_2
//center = 1,1,m radius = 1.0
// 3 cell width, (n-1)/2 = (3-1)/2 = 1.0
- //
// vert_mid: half (0.5/1.0)
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
(_)
- "#, Cell::new(1,0), Cell::new(1,0).m(), 1.0, EdgeCase::StartHalf, 0.5),
+ "#, EdgeCase::StartHalf, 0.5),
// CIRCLE_3
//center = 1,1,o radius = 1.5,
// 4 cell width, (n-1)/2 = (4-1)/2 = 1.5
// vert_mid: 3/4 (1.5/2.0)
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
__
(__)
- "#, Cell::new(2,1), Cell::new(2,1).k(), 1.5, EdgeCase::StartHalf, 1.5),
+ "#, EdgeCase::StartHalf, 1.5),
// CIRCLE_4
//center: 2,1,m radius: 2.0
// 5 cell width, (n-1)/2 = (5-1)/2 = 2.0
// vert_mid: half (1.5/3.0)
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
,-.
( )
`-'
- "#, Cell::new(2,1), Cell::new(2,1).m(), 2.0, EdgeCase::StartHalf, 1.5),
+ "#, EdgeCase::StartHalf, 1.5),
// CIRCLE_5
//center: 2,1,o radius: 2.5
// 6 cell width, (n-1)/2 = (6-1)/2 = 2.5
// vert_mid: half (1.5/3.0)
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
.--.
( )
`--'
- "#, Cell::new(3,1), Cell::new(3,1).k(), 2.5, EdgeCase::StartHalf, 1.5),
+ "#, EdgeCase::StartHalf, 1.5),
// CIRCLE_6
//center: 3,2,m radius: 3.0
// 7 cell width, (n-1)/2 = (7-1)/2 = 3.0
// vert_mid: 2.5/4
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
_
.' '.
( )
`._.'
- "#, Cell::new(3,2), Cell::new(3,2).m(), 3.0, EdgeCase::StartHalf, 2.5),
+ "#, EdgeCase::StartHalf, 2.5),
// CIRCLE_7
//center: 3,2,o radius: 3.5
// 8 cell width, (n-1)/2 = (8-1)/2 = 3.5
// vert_mid: 2.5/4
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
__
,' '.
( )
`.__.'
- "#, Cell::new(4,2), Cell::new(4,2).k(), 3.5,EdgeCase::StartHalf, 2.5),
+ "#, EdgeCase::StartHalf, 2.5),
// CIRCLE_8
//center: 4,2,m radius:4.0
// 9 cell width, (n-1)/2 = (9-1)/2 = 4.0
// vert_mid: half (2.5/5.0)
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
___
,' '.
( )
`. .'
`-'
- "#, Cell::new(4,2), Cell::new(4,2).m(), 4.0, EdgeCase::StartHalf, 2.5),
+ "#, EdgeCase::StartHalf, 2.5),
// circle 9 and up can be divided into 4 quadrants these quadrants can be arcs and can be used as
// rounded edge with larger radius for rouded rect
@@ -130,31 +147,37 @@ lazy_static! {
// start_edge: true
// 9 cell width, (n-0)/2 = (9-0)/2 = 4.5
// vert_mid: 3.0/5.0
+ // cx_lies: mid
+ // cy_lies: edge
(r#"
___
,' `.
/ \
\ /
`.___.'
- "#, Cell::new(4,3), Cell::new(4,3).c(), 4.5, EdgeCase::StartEdge, 3.0 ),
+ "#, EdgeCase::StartEdge, 3.0 ),
// CIRCLE_10
//center: 4,2,y radius: 5.0
//start_edge: true
// 10 cell width, (n-0)/2 = (10-0)/2 = 5.0
// vert_mid: 3.0/5.0
+ // cx_lies: edge
+ // cy_lies: edge
(r#"
____
,' `.
/ \
\ /
`.____.'
- "#, Cell::new(5,3), Cell::new(5,3).a(), 5.0, EdgeCase::StartEdge, 3.0),
+ "#, EdgeCase::StartEdge, 3.0),
// CIRCLE_11
//center:5,3,o radius: 5.5
// 12 cell width, (n-1)/2 = (12-1)/2 = 5.5
// vert_mid: 3.5/6.0
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
____
.' `.
@@ -162,12 +185,14 @@ lazy_static! {
( )
\ /
`.____.'
- "#, Cell::new(6,3), Cell::new(6,3).k(), 5.5, EdgeCase::StartHalf , 3.5),
+ "#, EdgeCase::StartHalf , 3.5),
// CIRCLE_12
//center:6,3,m radius: 6.0
// 13 cell width, (n-1)/2 = (13-1)/2 = 6.0
// vert_mid: 3.5/6.0
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
_____
,' `.
@@ -175,11 +200,13 @@ lazy_static! {
( )
\ /
`._____.'
- "#, Cell::new(6,3), Cell::new(6,3).m(), 6.0, EdgeCase::StartHalf, 3.5),
+ "#, EdgeCase::StartHalf, 3.5),
// CIRCLE_13
// center: 6,3,y radius: 6.5
// vert_mid: 4.0/7.0
+ // cx_lies: edge
+ // cy_lies: edge
(r#"
______
,' `.
@@ -188,11 +215,13 @@ lazy_static! {
| |
\ /
`.______.'
- "#, Cell::new(7,4), Cell::new(7,4).a(), 6.5, EdgeCase::StartHalf, 4.0),
+ "#, EdgeCase::StartHalf, 4.0),
// CIRCLE_14
//center: 7,3,w radius: 7.0
//vert_mid: 4.0/7.0
+ // cx_lies: mid
+ // cy_lies: edge
(r#"
_______
,' `.
@@ -201,12 +230,14 @@ lazy_static! {
| |
\ /
`._______.'
- "#, Cell::new(7,4), Cell::new(7,4).c(), 7.0, EdgeCase::StartHalf , 4.0),
+ "#, EdgeCase::StartHalf , 4.0),
// CIRCLE_15
//center: 7,4,o radius: 7.5
//vert_mid: 4.5/8.0
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
________
,' `.
@@ -216,11 +247,13 @@ lazy_static! {
| |
\ /
`.________.'
- "#, Cell::new(8,4), Cell::new(8,4).k(), 7.5, EdgeCase::StartHalf, 4.5),
+ "#, EdgeCase::StartHalf, 4.5),
// CIRCLE_16
//center: 8,4,m radius: 8.0
//vert_mid: 4.5/9.0
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
__-----__
,' `.
@@ -231,11 +264,13 @@ lazy_static! {
\ /
`. .'
`-------'
- "#, Cell::new(8,4), Cell::new(8,4).m(), 8.0, EdgeCase::StartHalf, 4.5),
+ "#, EdgeCase::StartHalf, 4.5),
// CIRCLE_17
//center: 8,4,o radius: 8.5
// vert_mid: 4.5/9.0
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
.--------.
,' `.
@@ -246,11 +281,13 @@ lazy_static! {
\ /
`. .'
`--------'
- "#, Cell::new(9,4), Cell::new(9,4).k(), 8.5, EdgeCase::StartHalf, 4.5),
+ "#, EdgeCase::StartHalf, 4.5),
// CIRCLE_18
//center:9,5,m radius: 9.0
//vert_mid: 5.5/10.0
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
_.-'''''-._
,' `.
@@ -262,11 +299,13 @@ lazy_static! {
\ /
`._ _.'
'-.....-'
- "#, Cell::new(9,5), Cell::new(9,5).m(), 9.0, EdgeCase::StartHalf, 5.5),
+ "#, EdgeCase::StartHalf, 5.5),
// CIRCLE_19
// center: 9,5,o radius: 9.5
// vert_mid: 5.5/10.0
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
_.-''''''-._
,' `.
@@ -278,12 +317,14 @@ lazy_static! {
\ /
`._ _.'
'-......-'
- "#, Cell::new(10,5), Cell::new(10,5).k(), 9.5, EdgeCase::StartHalf, 5.5),
+ "#, EdgeCase::StartHalf, 5.5),
// CIRCLE_20
// center: 10,5,m radius: 10
// vert_mid: 5.5/10.0
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
_.-'''''''-._
,' `.
@@ -295,11 +336,13 @@ lazy_static! {
\ /
`._ _.'
'-.......-'
- "#, Cell::new(10,5), Cell::new(10,5).m(), 10.0, EdgeCase::StartHalf, 5.5),
+ "#, EdgeCase::StartHalf, 5.5),
// CIRCLE_21
// center: 10,5,o radius: 10.5
// vert_mid: 5.5/11.0
+ // cx_lies: edge
+ // cy_lies: mid
(r#"
_.-''''''''-._
,' `.
@@ -312,12 +355,14 @@ lazy_static! {
\ /
`._ _.'
'-........-'
- "#, Cell::new(11,5), Cell::new(11,5).k(), 10.5, EdgeCase::StartHalf, 5.5),
+ "#, EdgeCase::StartHalf, 5.5),
// CIRCLE_22
// center: 10,5,m radius: 11
// radius = (n-1)/2 = (23-1)/2 = 11
// vert_mid: 5.5/11.0
+ // cx_lies: mid
+ // cy_lies: mid
(r#"
_.-'''''''''-._
,' `.
@@ -330,62 +375,55 @@ lazy_static! {
\ /
`._ _.'
'-.........-'
- "#, Cell::new(11,5), Cell::new(11,5).m(), 11.0, EdgeCase::StartHalf, 5.5),
+ "#, EdgeCase::StartHalf, 5.5),
];
+ pub static ref CIRCLE_MAP: BTreeMap<&'static str,(Cell, Point, f32, EdgeCase, f32)> =BTreeMap::from_iter(
+ CIRCLE_ART_MAP.iter().map(|(art, edge_case, offset_center_y)|{
+ let cb = CellBuffer::from(*art);
+ let (lo, hi) = cb.bounds().expect("circle must have bounds");
+
+ let width = match *edge_case {
+ EdgeCase::StartEdge => {
+ (hi.x - lo.x) as f32 + 1.0
+ }
+ EdgeCase::StartHalf => {
+ (hi.x - lo.x) as f32
+ }
+ };
+
+ let calc_radius = width / 2.0;
+
+ let edge_inc_x = match edge_case{
+ EdgeCase::StartEdge => 0.0,
+ EdgeCase::StartHalf => 0.5,
+ };
+
+ let calc_center_x = calc_radius + edge_inc_x;
+
+ let calc_center_y = offset_center_y * 2.0;
+
+ let calc_center = Point::new(calc_center_x, calc_center_y);
+
+ let calc_center_cell = calc_center.cell();
+
+ (*art, (calc_center_cell, calc_center, calc_radius, *edge_case, *offset_center_y))
+ })
+ );
+
/// The fragments for each of the circle
/// Calculate the span and get the group fragments
pub static ref FRAGMENTS_CIRCLE: Vec<(Vec<Contacts>,Circle)> = Vec::from_iter(
- CIRCLE_MAP.iter().map(|(art, _center_cell, center, radius, edge_case, offset_center_y)|{
+ CIRCLE_MAP.iter().map(|(art, (_center_cell, center, radius, edge_case, offset_center_y))|{
(circle_art_to_group(art, &Settings::default()), Circle::new(*center, *radius, false))
})
);
/// map of circle spans and their radius
pub static ref DIAMETER_CIRCLE: BTreeMap<i32,(Cell,Span)> =BTreeMap::from_iter(
- CIRCLE_MAP.iter().map(|(art, center_cell, center, radius, edge_case, offset_center_y)|{
+ CIRCLE_MAP.iter().map(|(art, (center_cell, center, radius, edge_case, offset_center_y))|{
let cb = CellBuffer::from(*art);
- println!("art: {} radius: {}", art,radius);
- if let Some((lo, hi)) = cb.bounds(){
-
- let width = match *edge_case {
- EdgeCase::StartEdge => {
- (hi.x - lo.x) as f32 + 1.0
- }
- EdgeCase::StartHalf => {
- (hi.x - lo.x) as f32
- }
- };
-
- println!("width: {}", width);
- let calc_radius = width / 2.0;
- println!("calc_radius: {}", calc_radius);
- assert_eq!(calc_radius, *radius);
-
- let calc_center_x = match *edge_case{
- EdgeCase::StartEdge => {
- calc_radius
- }
- EdgeCase::StartHalf => {
- calc_radius + 0.5
- }
- };
-
- let calc_center_y = offset_center_y * 2.0;
- dbg!(offset_center_y);
-
- let calc_center = Point::new(calc_center_x, calc_center_y);
- dbg!(&calc_center);
- assert_eq!(calc_center, *center);
-
- let (calc_center_cell,_) = Cell::snap_point(calc_center);
- dbg!(&calc_center_cell);
- assert_eq!(calc_center_cell, *center_cell);
-
-
- }
-
let mut spans = cb.group_adjacents();
assert_eq!(spans.len(), 1);
let span = spans.remove(0).localize();
@@ -395,7 +433,7 @@ lazy_static! {
/// There is only 1 span per circle, and localized
pub static ref CIRCLES_SPAN: BTreeMap<Circle, Span> = BTreeMap::from_iter(
- CIRCLE_MAP.iter().map(|(art, _center_cell, center, radius, edge_case, offset_center_y)|{
+ CIRCLE_MAP.iter().map(|(art, (_center_cell, center, radius, edge_case, offset_center_y))|{
let cb = CellBuffer::from(*art);
let mut spans = cb.group_adjacents();
assert_eq!(spans.len(), 1);
@@ -404,112 +442,103 @@ lazy_static! {
})
);
- /// Build a fragment for the characters in the range
- /// extract the characters
- ///
- /// top_left arc: top_left to center cell
+
+ /// Simplified version of fragment arcs derived from CIRCLE_MAP
+ /// Algorithm:
+ /// 1. Locate the cells corresponding to the 4 quadrant boundary of the circle
///
- /// top_right arc: top_right to center_cell
+ /// top_left top top_right
+ /// p2
+ /// arc2 | arc1
+ /// |
+ /// left p3----+----- p1 right
+ /// |
+ /// arc3 | arc4
+ /// p4
+ /// bottom_left bottom bottom_right
///
- /// bottom_left arc: bottom_left to center_cell
+ /// p1 = center.x + radius, center.y
+ /// p2 = center.x, center.y - radius
+ /// p3 = center.x - radius, center.y
+ /// p4 = center.x + radius, center.y + radius
///
- /// bottom_right arc: bottom_right to center_cell
+ /// right,top,left,bottom, top_left, top_right,bottom_left,bottom_right are cells dervied from
+ /// bounds.
///
- /// if the number of horizontal cells are odd arc1 an arc2 will both have
- /// the top_center character, so as arc3 and arc4 will have both the bottom_center character
+ /// assert that snapping points to cell corresponds respectively:
+ /// p1 -> right cell
+ /// p2 -> top cell
+ /// p3 -> left cell
+ /// p4 -> bottom cell
///
- /// if the number of vertical cells are odd arc arc1 and arc3 will both have
- /// the left_center character, so as arc3 and arc4 will have both the right_center character
+ /// 2. Locate the span of each quadrants
+ /// arc4 span is always center_cell, to bottom_right
+ /// arc2 span is conditional
+ /// if center cell lies on mid, the span coverage is inclusive of the center cell.
+ /// otherwise if the center cell lies on the edge, then the cell coverage is exclusive of
+ /// the center cell
///
pub static ref FRAGMENTS_ARC: Vec<(Vec<Contacts>,fragment::Arc)> =Vec::from_iter(
- CIRCLE_MAP.iter().skip(3).flat_map(|(art, center_cell, center, radius, edge_case, offset_center_y)|{
+ CIRCLE_MAP.iter().skip(3).flat_map(|(art, (center_cell, center, radius, edge_case, offset_center_y))|{
let cb = CellBuffer::from(*art);
let mut spans = cb.group_adjacents();
assert_eq!(spans.len(), 1);
- //TODO: span localize here affects the center of the arc,
- //need to use the exact center used in the circle here
- //Need to fix the calculation here involving the span
let span = spans.remove(0).localize();
- let (tl_bounds, br_bounds) = span.bounds().expect("There should be bounds");
-
- let center_cell_br_bound = center_cell.bottom_right_most();
- // inlude the center cell for x when this is true, when deriving a span for arc1, arc3, arc4
- let eq_include_center_x = center.x <= center_cell_br_bound.x;
- // include the center cell for y when this is true, when deriving a span for arc1, arc3, arc4
- let eq_include_center_y = center.y <= center_cell_br_bound.y;
-
- let strict_include_center_x = center.x < center_cell_br_bound.x;
- let strict_include_center_y = center.y < center_cell_br_bound.y;
-
- //
- // ARC 1
- // __
- // | '.
- // | \
- // |_____|
- //
- let arc1_top_right = Cell::new(br_bounds.x, tl_bounds.y);
- let arc1_center_cell = Cell::new(
- if strict_include_center_x { center_cell.x } else { center_cell.x + 1},
- if eq_include_center_y { center_cell.y } else { center_cell.y + 1});
-
- let arc1_top_left = Cell::new(arc1_center_cell.x, tl_bounds.y);
- let arc1_center = arc1_top_left.localize_point(*center);
-
-
- let arc1_span = span.extract(arc1_center_cell, arc1_top_right);
- let arc1 = fragment::Arc::new(Point::new(arc1_center.x + *radius, arc1_center.y), Point::new(arc1_center.x, arc1_center.y - *radius) , *radius);
-
- //
- // ARC 2
- // __
- // .' |
- // / |
- // |_____|
- //
-
- let arc2_top_left = Cell::new(tl_bounds.x, tl_bounds.y);
- let arc2_span = span.extract(arc2_top_left, *center_cell);
- let arc2 = fragment::Arc::new(Point::new(center.x, center.y - radius), Point::new(center.x - radius , center.y), *radius);
-
-
- //
- // ARC 3
- // ______.
- // | |
- // \ |
- // `.__|
- //
- //
- let arc3_center_cell = Cell::new(
- if eq_include_center_x { center_cell.x } else { center_cell.x + 1},
- if strict_include_center_y { center_cell.y } else { center_cell.y + 1}
- );
- let arc3_top_left = Cell::new(tl_bounds.x, arc3_center_cell.y);
- let arc3_bottom_right = Cell::new(arc3_center_cell.x, br_bounds.y);
- let arc3_center = arc3_top_left.localize_point(*center);
- let arc3_span = span.extract(arc3_top_left, arc3_bottom_right);
- let arc3 = fragment::Arc::new(Point::new(arc3_center.x - radius, arc3_center.y), Point::new(arc3_center.x, arc3_center.y + radius), *radius);
-
-
- //
- // ARC 4
- //
- // .______
- // | |
- // | /
- // |__.'
- //
- let arc4_center_cell = Cell::new(
- if strict_include_center_x { center_cell.x } else { center_cell.x + 1},
- if strict_include_center_y { center_cell.y } else { center_cell.y + 1}
- );
- let arc4_top_left = Cell::new(arc4_center_cell.x, arc4_center_cell.y);
- let arc4_bottom_right = Cell::new(br_bounds.x, br_bounds.y);
- let arc4_center = arc4_top_left.localize_point(*center);
- let arc4_span = span.extract(arc4_top_left, arc4_bottom_right);
- let arc4 = fragment::Arc::new(Point::new(arc4_center.x, arc4_center.y + radius), Point::new(arc4_center.x + radius, arc4_center.y), *radius);
+ let (start_bound, end_bound) = span.bounds().expect("There should be bounds");
+
+ let right = Cell::new(end_bound.x, center_cell.y);
+ let top = Cell::new(center_cell.x, start_bound.y);
+ let left = Cell::new(start_bound.x, center_cell.y);
+ let bottom = Cell::new(center_cell.x, end_bound.y);
+
+ let top_left = Cell::new(left.x, top.y);
+ let top_right = Cell::new(right.x, top.y);
+ let bottom_left = Cell::new(left.x, bottom.y);
+ let bottom_right = Cell::new(right.x, bottom.y);
+ assert_eq!(top_left, start_bound);
+ assert_eq!(bottom_right, end_bound);
+
+
+ // include cx if the center lies on the horizontal midline
+ // include cy if the center lies on the veritcal midline
+ let cx_adjusted = if !center.is_edge_x(){ center_cell.x }else{ center_cell.x - 1 };
+ let cy_adjusted = if !center.is_edge_y(){ center_cell.y }else{ center_cell.y - 1 };
+
+ let arc1_bounds = Cell::rearrange_bound(Cell::new(center_cell.x, cy_adjusted), top_right);
+ let arc2_bounds = Cell::rearrange_bound(top_left, Cell::new( cx_adjusted, cy_adjusted));
+ let arc3_bounds = Cell::rearrange_bound(bottom_left, Cell::new(cx_adjusted, center_cell.y));
+ let arc4_bounds = Cell::rearrange_bound(*center_cell, bottom_right);
+
+ let arc1_span = span.extract(arc1_bounds.0, arc1_bounds.1);
+ let arc2_span = span.extract(arc2_bounds.0, arc2_bounds.1);
+ let arc3_span = span.extract(arc3_bounds.0, arc3_bounds.1);
+ let arc4_span = span.extract(arc4_bounds.0, arc4_bounds.1);
+
+
+ let p1 = Point::new(center.x + radius, center.y);
+ let p2 = Point::new(center.x, center.y - radius);
+ let p3 = Point::new(center.x - radius, center.y);
+ let p4 = Point::new(center.x, center.y + radius);
+
+ let arc1_start = arc1_bounds.0.localize_point(p1);
+ let arc1_end = arc1_bounds.0.localize_point(p2);
+
+ let arc2_start = arc2_bounds.0.localize_point(p2);
+ let arc2_end = arc2_bounds.0.localize_point(p3);
+
+ let arc3_start = arc3_bounds.0.localize_point(p3);
+ let arc3_end = arc3_bounds.0.localize_point(p4);
+
+ let arc4_start = arc4_bounds.0.localize_point(p4);
+ let arc4_end = arc4_bounds.0.localize_point(p1);
+
+ let arc1 = fragment::Arc::new(arc1_start, arc1_end, *radius);
+ let arc2 = fragment::Arc::new(arc2_start, arc2_end, *radius);
+ let arc3 = fragment::Arc::new(arc3_start, arc3_end, *radius);
+ let arc4 = fragment::Arc::new(arc4_start, arc4_end, *radius);
+
+ //TODO: get the settings supplied by the user
let settings = &Settings::default();
vec![
@@ -520,6 +549,7 @@ lazy_static! {
]
})
);
+
}
fn circle_art_to_group(art: &str, settings: &Settings) -> Vec<Contacts> {
@@ -591,8 +621,10 @@ mod tests {
fn access_circles() {
let len = DIAMETER_CIRCLE.len();
println!("len: {}", len);
+ assert_eq!(len, 22);
let frag_len = FRAGMENTS_ARC.len();
println!("frag len: {}", frag_len);
+ assert_eq!(frag_len, 76);
}
#[test]
diff --git a/svgbob/src/point.rs b/svgbob/src/point.rs
index 26a67ea..18a8015 100644
--- a/svgbob/src/point.rs
+++ b/svgbob/src/point.rs
@@ -1,5 +1,6 @@
use crate::buffer::CellGrid;
use crate::util;
+use crate::Cell;
use nalgebra::{Point2, Vector2};
use std::{
cmp::Ordering,
@@ -73,6 +74,27 @@ impl Point {
let u = units * CellGrid::unit_y();
Self::new(self.x + t, self.y + u)
}
+
+ /// test if the point lie on an edge of a cell
+ /// that is the fractional part is 0.0
+ pub fn is_edge_x(&self) -> bool {
+ self.x.fract() == 0.0
+ }
+ pub fn is_edge_y(&self) -> bool {
+ (self.y / 2.0).fract() == 0.0
+ }
+ pub fn is_mid_x(&self) -> bool {
+ self.x.fract() == 0.5
+ }
+ pub fn is_mid_y(&self) -> bool {
+ (self.y / 2.0).fract() == 0.5
+ }
+
+ /// return the cell where this point fall to
+ pub fn cell(&self) -> Cell {
+ let (cell, _) = Cell::snap_point(*self);
+ cell
+ }
}
impl From<Point2<f32>> for Point {
diff --git a/svgbob/test_data/circles.bob b/svgbob/test_data/circles.bob
index 719c370..339f21b 100644
--- a/svgbob/test_data/circles.bob
+++ b/svgbob/test_data/circles.bob
@@ -162,8 +162,35 @@
'-.......-'
- ,- -.
- ( )
+ _.-''''''''-._
+ ,' `.
+ / \
+ . .
+ | |
+ 21 | |
+ | |
+ | |
+ \ /
+ `._ _.'
+ '-........-'
+
+ _.-'''''''''-._
+ ,' `.
+ / \
+ . .
+ | |
+ | |
+ 22 | |
+ | |
+ \ /
+ `._ _.'
+ '-.........-'
+
+ | |
+ V V
+
+ -----> ,- -.
+ -----> ( )
4
( )
`- -'
@@ -301,30 +328,41 @@
`._ _.'
'-... ...-'
+ | | | |
+ V V V V
- _.-''' '''-._
- ,' `.
- / \
- . .
- | |
- | |
+ _.-''' '''-._
+ ,' `.
+ / \
+ . .
+ | |
+ --> | | <--
19
- | |
- | |
- \ /
- `._ _.'
- '-... ...-'
+ --> | | <--
+ | |
+ \ /
+ `._ _.'
+ '-... ...-'
+ ^ ^ ^ ^
+ | | | |
- _.-'''' ''''-._
+
+ | | | |
+ V V V V
+
+ --> _.-'''' ''''-._ <--
,' `.
/ \
. .
| |
- | |
+ --> | | <--
20
- | |
+ --> | | <--
| |
\ /
`._ _.'
- '-.... ....-'
+ --> '-.... ....-' <--
+
+ ^ ^ ^ ^
+ | | | |