diff --git a/editor/src/messages/portfolio/document/graph_operation/transform_utils.rs b/editor/src/messages/portfolio/document/graph_operation/transform_utils.rs index 5863891661..6bb47a6d74 100644 --- a/editor/src/messages/portfolio/document/graph_operation/transform_utils.rs +++ b/editor/src/messages/portfolio/document/graph_operation/transform_utils.rs @@ -91,44 +91,48 @@ pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 { if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) } } -/// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png) -/// -/// Source: -/// ```tex -/// \begin{bmatrix} -/// S_{x}\cos(\theta)-S_{y}\sin(\theta)H_{y} & S_{x}\cos(\theta)H_{x}-S_{y}\sin(\theta) & T_{x}\\ -/// S_{x}\sin(\theta)+S_{y}\cos(\theta)H_{y} & S_{x}\sin(\theta)H_{x}+S_{y}\cos(\theta) & T_{y}\\ -/// 0 & 0 & 1 -/// \end{bmatrix} -/// ``` -#[test] -fn derive_transform() { - for shear_x in -10..=10 { - let shear_x = (shear_x as f64) / 2.; - for angle in (0..=360).step_by(15) { - let angle = (angle as f64).to_radians(); - for scale_x in 1..10 { - let scale_x = (scale_x as f64) / 5.; - for scale_y in 1..10 { - let scale_y = (scale_y as f64) / 5.; - - let shear = DVec2::new(shear_x, 0.); - let scale = DVec2::new(scale_x, scale_y); - let translate = DVec2::new(5666., 644.); - - let original_transform = DAffine2::from_cols( - DVec2::new(scale.x * angle.cos() - scale.y * angle.sin() * shear.y, scale.x * angle.sin() + scale.y * angle.cos() * shear.y), - DVec2::new(scale.x * angle.cos() * shear.x - scale.y * angle.sin(), scale.x * angle.sin() * shear.x + scale.y * angle.cos()), - translate, - ); - - let (new_scale, new_angle, new_translation, new_shear) = compute_scale_angle_translation_shear(original_transform); - let new_transform = DAffine2::from_scale_angle_translation(new_scale, new_angle, new_translation) * DAffine2::from_cols_array(&[1., new_shear.y, new_shear.x, 1., 0., 0.]); - - assert!( - new_transform.abs_diff_eq(original_transform, 1e-10), - "original_transform {original_transform} new_transform {new_transform} / scale {scale} new_scale {new_scale} / angle {angle} new_angle {new_angle} / shear {shear} / new_shear {new_shear}", - ); +#[cfg(test)] +mod tests { + use super::*; + /// ![](https://files.keavon.com/-/OptimisticSpotlessTinamou/capture.png) + /// + /// Source: + /// ```tex + /// \begin{bmatrix} + /// S_{x}\cos(\theta)-S_{y}\sin(\theta)H_{y} & S_{x}\cos(\theta)H_{x}-S_{y}\sin(\theta) & T_{x}\\ + /// S_{x}\sin(\theta)+S_{y}\cos(\theta)H_{y} & S_{x}\sin(\theta)H_{x}+S_{y}\cos(\theta) & T_{y}\\ + /// 0 & 0 & 1 + /// \end{bmatrix} + /// ``` + #[test] + fn derive_transform() { + for shear_x in -10..=10 { + let shear_x = (shear_x as f64) / 2.; + for angle in (0..=360).step_by(15) { + let angle = (angle as f64).to_radians(); + for scale_x in 1..10 { + let scale_x = (scale_x as f64) / 5.; + for scale_y in 1..10 { + let scale_y = (scale_y as f64) / 5.; + + let shear = DVec2::new(shear_x, 0.); + let scale = DVec2::new(scale_x, scale_y); + let translate = DVec2::new(5666., 644.); + + let original_transform = DAffine2::from_cols( + DVec2::new(scale.x * angle.cos() - scale.y * angle.sin() * shear.y, scale.x * angle.sin() + scale.y * angle.cos() * shear.y), + DVec2::new(scale.x * angle.cos() * shear.x - scale.y * angle.sin(), scale.x * angle.sin() * shear.x + scale.y * angle.cos()), + translate, + ); + + let (new_scale, new_angle, new_translation, new_shear) = compute_scale_angle_translation_shear(original_transform); + let new_transform = DAffine2::from_scale_angle_translation(new_scale, new_angle, new_translation) * DAffine2::from_cols_array(&[1., new_shear.y, new_shear.x, 1., 0., 0.]); + + assert!( + new_transform.abs_diff_eq(original_transform, 1e-10), + "original_transform {original_transform} new_transform {new_transform} / scale {scale} new_scale {new_scale} / angle {angle} new_angle {new_angle} / shear {shear} / new_shear {new_shear}", + ); + } } } } diff --git a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs index f640fb38c2..bc8752bfd5 100644 --- a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs +++ b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs @@ -522,49 +522,53 @@ pub struct NodeRelations { // Helper functions // ================ -#[test] -fn test_tree() { - let mut metadata = DocumentMetadata::default(); - let root = LayerNodeIdentifier::ROOT_PARENT; - let metadata = &mut metadata; - root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(3))); - assert_eq!(root.children(metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]); - root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(6))); - assert_eq!(root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); - assert_eq!(root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); - LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(4))); - LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(2))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(5))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(9))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(8))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(7))); - root.push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(1))); - assert_eq!( - root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), - vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)] - ); - assert_eq!( - root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), - vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(7), NodeId(8), NodeId(9)] - ); - assert_eq!( - root.descendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), - vec![NodeId(9), NodeId(8), NodeId(7), NodeId(6), NodeId(5), NodeId(4), NodeId(3), NodeId(2), NodeId(1)] - ); - assert!(root.children(metadata).all(|child| child.parent(metadata) == Some(root))); - LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(metadata); - LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(metadata); - LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(10))); - assert_eq!( - root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), - vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)] - ); - assert_eq!( - root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), - vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9), NodeId(10)] - ); - assert_eq!( - root.descendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), - vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)] - ); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_tree() { + let mut metadata = DocumentMetadata::default(); + let root = LayerNodeIdentifier::ROOT_PARENT; + let metadata = &mut metadata; + root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(3))); + assert_eq!(root.children(metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]); + root.push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(6))); + assert_eq!(root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + assert_eq!(root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(4))); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(2))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(metadata, LayerNodeIdentifier::new_unchecked(NodeId(5))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(metadata, LayerNodeIdentifier::new_unchecked(NodeId(9))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(8))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(7))); + root.push_front_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(1))); + assert_eq!( + root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)] + ); + assert_eq!( + root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(7), NodeId(8), NodeId(9)] + ); + assert_eq!( + root.descendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), + vec![NodeId(9), NodeId(8), NodeId(7), NodeId(6), NodeId(5), NodeId(4), NodeId(3), NodeId(2), NodeId(1)] + ); + assert!(root.children(metadata).all(|child| child.parent(metadata) == Some(root))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(metadata); + LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(metadata); + LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(metadata, LayerNodeIdentifier::new_unchecked(NodeId(10))); + assert_eq!( + root.children(metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)] + ); + assert_eq!( + root.descendants(metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9), NodeId(10)] + ); + assert_eq!( + root.descendants(metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), + vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)] + ); + } } diff --git a/editor/src/messages/tool/common_functionality/snapping/distribution_snapper.rs b/editor/src/messages/tool/common_functionality/snapping/distribution_snapper.rs index cdd3b28d24..99fe3ac15f 100644 --- a/editor/src/messages/tool/common_functionality/snapping/distribution_snapper.rs +++ b/editor/src/messages/tool/common_functionality/snapping/distribution_snapper.rs @@ -382,317 +382,321 @@ impl DistributionSnapper { } } -#[test] -fn merge_intersecting_test() { - let mut rectangles = vec![Rect::from_square(DVec2::ZERO, 2.), Rect::from_square(DVec2::new(10., 0.), 2.)]; - DistributionSnapper::merge_intersecting(&mut rectangles); - assert_eq!(rectangles.len(), 2); - - let mut rectangles = vec![ - Rect::from_square(DVec2::ZERO, 2.), - Rect::from_square(DVec2::new(1., 0.), 2.), - Rect::from_square(DVec2::new(10., 0.), 2.), - Rect::from_square(DVec2::new(11., 0.), 2.), - ]; - DistributionSnapper::merge_intersecting(&mut rectangles); - assert_eq!(rectangles.len(), 6); - assert_eq!(rectangles[0], Rect::from_box([DVec2::new(-2., -2.), DVec2::new(3., 2.)])); - assert_eq!(rectangles[3], Rect::from_box([DVec2::new(8., -2.), DVec2::new(13., 2.)])); -} +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn merge_intersecting_test() { + let mut rectangles = vec![Rect::from_square(DVec2::ZERO, 2.), Rect::from_square(DVec2::new(10., 0.), 2.)]; + DistributionSnapper::merge_intersecting(&mut rectangles); + assert_eq!(rectangles.len(), 2); + + let mut rectangles = vec![ + Rect::from_square(DVec2::ZERO, 2.), + Rect::from_square(DVec2::new(1., 0.), 2.), + Rect::from_square(DVec2::new(10., 0.), 2.), + Rect::from_square(DVec2::new(11., 0.), 2.), + ]; + DistributionSnapper::merge_intersecting(&mut rectangles); + assert_eq!(rectangles.len(), 6); + assert_eq!(rectangles[0], Rect::from_box([DVec2::new(-2., -2.), DVec2::new(3., 2.)])); + assert_eq!(rectangles[3], Rect::from_box([DVec2::new(8., -2.), DVec2::new(13., 2.)])); + } -#[test] -fn dist_simple_2() { - let rectangles = [10., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); - assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); - assert_eq!(rectangles.len(), 2); -} + #[test] + fn dist_simple_2() { + let rectangles = [10., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); + assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); + assert_eq!(rectangles.len(), 2); + } -#[test] -fn dist_simple_3() { - let rectangles = [10., 20., 30.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); - assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); - assert_eq!(rectangles.len(), 3); -} + #[test] + fn dist_simple_3() { + let rectangles = [10., 20., 30.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); + assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); + assert_eq!(rectangles.len(), 3); + } -#[test] -fn dist_out_of_tolerance() { - let rectangles = [10., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 0.4, dist_right); - assert_eq!(offset, None); - assert_eq!(rectangles.len(), 1); -} + #[test] + fn dist_out_of_tolerance() { + let rectangles = [10., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 0.4, dist_right); + assert_eq!(offset, None); + assert_eq!(rectangles.len(), 1); + } -#[test] -fn dist_with_nonsense() { - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let rectangles = [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); - let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); - assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); - assert_eq!(rectangles.len(), 2); -} + #[test] + fn dist_with_nonsense() { + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let rectangles = [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)); + let (offset, rectangles) = DistributionSnapper::top_level_matches(source, &rectangles, 1., dist_right); + assert_eq!(offset, Some(DistributionMatch { first: 5.5, equal: 6. })); + assert_eq!(rectangles.len(), 2); + } -#[cfg(test)] -fn assert_boxes_in_order(rectangles: &VecDeque, index: usize) { - for (&first, &second) in rectangles.iter().zip(rectangles.iter().skip(1)) { - assert!(first.max()[index] < second.min()[index], "{first:?} {second:?} {index}") + #[cfg(test)] + fn assert_boxes_in_order(rectangles: &VecDeque, index: usize) { + for (&first, &second) in rectangles.iter().zip(rectangles.iter().skip(1)) { + assert!(first.max()[index] < second.min()[index], "{first:?} {second:?} {index}") + } } -} -#[test] -fn dist_snap_point_right() { - let dist_snapper = DistributionSnapper { - right: [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - left: [-2.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); - let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_box[0].y = expected_box[0].y.min(dist_snapper.left[0][1].y); - expected_box[1].y = expected_box[1].y.min(dist_snapper.left[0][1].y); - - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[0], expected_box); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); -} + #[test] + fn dist_snap_point_right() { + let dist_snapper = DistributionSnapper { + right: [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + left: [-2.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); + let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); + expected_box[0].y = expected_box[0].y.min(dist_snapper.left[0][1].y); + expected_box[1].y = expected_box[1].y.min(dist_snapper.left[0][1].y); + + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[0], expected_box); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + } -#[test] -fn dist_snap_point_right_left() { - let dist_snapper = DistributionSnapper { - right: [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; + #[test] + fn dist_snap_point_right_left() { + let dist_snapper = DistributionSnapper { + right: [2., 10., 15., 20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 5); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 5); - let mut expected_left1 = dist_snapper.left[1]; - let mut expected_center = Rect::from_square(DVec2::new(0., 0.), 2.); + let mut expected_left1 = dist_snapper.left[1]; + let mut expected_center = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_center[0].y = expected_center[0].y.min(dist_snapper.left[1][1].y).min(dist_snapper.right[0][1].y); - expected_center[1].y = expected_center[1].y.min(dist_snapper.left[1][1].y).min(dist_snapper.right[0][1].y); + expected_center[0].y = expected_center[0].y.min(dist_snapper.left[1][1].y).min(dist_snapper.right[0][1].y); + expected_center[1].y = expected_center[1].y.min(dist_snapper.left[1][1].y).min(dist_snapper.right[0][1].y); - expected_left1[0].y = expected_left1[0].y.min(dist_snapper.left[0][1].y).min(expected_center[1].y); - expected_left1[1].y = expected_left1[1].y.min(dist_snapper.left[0][1].y).min(expected_center[1].y); + expected_left1[0].y = expected_left1[0].y.min(dist_snapper.left[0][1].y).min(expected_center[1].y); + expected_left1[1].y = expected_left1[1].y.min(dist_snapper.left[0][1].y).min(expected_center[1].y); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[1], expected_left1); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], expected_center); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); -} + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[1], expected_left1); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], expected_center); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + } -#[test] -fn dist_snap_point_left() { - let dist_snapper = DistributionSnapper { - left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], Rect::from_square(DVec2::new(0., 0.), 2.)); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); -} + #[test] + fn dist_snap_point_left() { + let dist_snapper = DistributionSnapper { + left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], Rect::from_square(DVec2::new(0., 0.), 2.)); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + } -#[test] -fn dist_snap_point_left_right() { - let dist_snapper = DistributionSnapper { - left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - right: [2., 10., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 4); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], Rect::from_square(DVec2::new(0., 0.), 2.)); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); -} + #[test] + fn dist_snap_point_left_right() { + let dist_snapper = DistributionSnapper { + left: [-2., -10., -15., -20.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + right: [2., 10., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 4); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[2], Rect::from_square(DVec2::new(0., 0.), 2.)); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + } -#[test] -fn dist_snap_point_center_x() { - let dist_snapper = DistributionSnapper { - left: [-10., -15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - right: [10., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); - - let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_box[0].y = expected_box[0].y.min(dist_snapper.left[0][1].y); - expected_box[1].y = expected_box[1].y.min(dist_snapper.left[0][1].y); - - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal[1], expected_box); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); -} + #[test] + fn dist_snap_point_center_x() { + let dist_snapper = DistributionSnapper { + left: [-10., -15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + right: [10., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0.5, 0.), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(6.)); + + let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); + expected_box[0].y = expected_box[0].y.min(dist_snapper.left[0][1].y); + expected_box[1].y = expected_box[1].y.min(dist_snapper.left[0][1].y); + + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal[1], expected_box); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + } -// ---------------------------------- - -#[test] -fn dist_snap_point_down() { - let dist_snapper = DistributionSnapper { - down: [2., 10., 15., 20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - up: [-2.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0., 0.5), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - - let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_box[0].x = expected_box[0].x.min(dist_snapper.down[0][1].x); - expected_box[1].x = expected_box[1].x.min(dist_snapper.down[0][1].x); - - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_vertical[0], expected_box); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); -} + // ---------------------------------- -#[test] -fn dist_snap_point_down_up() { - let dist_snapper = DistributionSnapper { - down: [2., 10., 15., 20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0., 0.5), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 5); - - let mut expected_center = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_center[0].x = expected_center[0].x.min(dist_snapper.up[1][1].x).min(dist_snapper.down[0][1].x); - expected_center[1].x = expected_center[1].x.min(dist_snapper.up[1][1].x).min(dist_snapper.down[0][1].x); - - let mut expected_up = Rect::from_square(DVec2::new(0., -10.), 2.); - expected_up[0].x = expected_up[0].x.min(dist_snapper.up[0][1].x).min(expected_center[0].x); - expected_up[1].x = expected_up[1].x.min(dist_snapper.up[0][1].x).min(expected_center[1].x); - - assert_eq!(snap_results.points[0].distribution_boxes_vertical[1], expected_up); - assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], expected_center); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); -} + #[test] + fn dist_snap_point_down() { + let dist_snapper = DistributionSnapper { + down: [2., 10., 15., 20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + up: [-2.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0., 0.5), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + + let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); + expected_box[0].x = expected_box[0].x.min(dist_snapper.down[0][1].x); + expected_box[1].x = expected_box[1].x.min(dist_snapper.down[0][1].x); + + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_vertical[0], expected_box); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } -#[test] -fn dist_snap_point_up() { - let dist_snapper = DistributionSnapper { - up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0., 0.5), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], Rect::from_square(DVec2::new(0., 0.), 2.)); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); -} + #[test] + fn dist_snap_point_down_up() { + let dist_snapper = DistributionSnapper { + down: [2., 10., 15., 20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0., 0.5), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 5); + + let mut expected_center = Rect::from_square(DVec2::new(0., 0.), 2.); + expected_center[0].x = expected_center[0].x.min(dist_snapper.up[1][1].x).min(dist_snapper.down[0][1].x); + expected_center[1].x = expected_center[1].x.min(dist_snapper.up[1][1].x).min(dist_snapper.down[0][1].x); + + let mut expected_up = Rect::from_square(DVec2::new(0., -10.), 2.); + expected_up[0].x = expected_up[0].x.min(dist_snapper.up[0][1].x).min(expected_center[0].x); + expected_up[1].x = expected_up[1].x.min(dist_snapper.up[0][1].x).min(expected_center[1].x); + + assert_eq!(snap_results.points[0].distribution_boxes_vertical[1], expected_up); + assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], expected_center); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } -#[test] -fn dist_snap_point_up_down() { - let dist_snapper = DistributionSnapper { - up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - down: [2., 10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0., 0.5), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 4); - assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], Rect::from_square(DVec2::new(0., 0.), 2.)); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); -} + #[test] + fn dist_snap_point_up() { + let dist_snapper = DistributionSnapper { + up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0., 0.5), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], Rect::from_square(DVec2::new(0., 0.), 2.)); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } -#[test] -fn dist_snap_point_center_y() { - let dist_snapper = DistributionSnapper { - up: [-10., -15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - down: [10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0., 0.5), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); - - let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); - expected_box[0].x = expected_box[0].x.min(dist_snapper.up[0][1].x).min(dist_snapper.down[0][1].x); - expected_box[1].x = expected_box[1].x.min(dist_snapper.up[0][1].x).min(dist_snapper.down[0][1].x); - - assert_eq!(snap_results.points[0].distribution_boxes_vertical[1], expected_box); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); -} + #[test] + fn dist_snap_point_up_down() { + let dist_snapper = DistributionSnapper { + up: [-2., -10., -15., -20.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + down: [2., 10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0., 0.5), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 4); + assert_eq!(snap_results.points[0].distribution_boxes_vertical[2], Rect::from_square(DVec2::new(0., 0.), 2.)); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } + + #[test] + fn dist_snap_point_center_y() { + let dist_snapper = DistributionSnapper { + up: [-10., -15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + down: [10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0., 0.5), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); -#[test] -fn dist_snap_point_center_xy() { - let dist_snapper = DistributionSnapper { - up: [-10., -15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - down: [10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), - left: [-12., -15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - right: [12., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), - ..Default::default() - }; - let source = Rect::from_square(DVec2::new(0.3, 0.4), 2.); - let snap_results = &mut SnapResults::default(); - dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); - - assert_eq!(snap_results.points.len(), 1); - assert_eq!(snap_results.points[0].distance, 0.5000000000000001); - assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(8.)); - assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); - assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); - assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); - - assert!(snap_results.points[0].distribution_boxes_horizontal[1][0].y <= dist_snapper.left[0][1].y); - assert!(snap_results.points[0].distribution_boxes_horizontal[1][1].y <= dist_snapper.left[0][1].y); - assert!(snap_results.points[0].distribution_boxes_vertical[1][0].x <= dist_snapper.up[0][1].x); - assert!(snap_results.points[0].distribution_boxes_vertical[1][1].x <= dist_snapper.up[0][1].x); - - assert_eq!(Rect::from_box(snap_results.points[0].source_bounds.unwrap().bounding_box()), Rect::from_square(DVec2::new(0., 0.), 2.)); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); - assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); + + let mut expected_box = Rect::from_square(DVec2::new(0., 0.), 2.); + expected_box[0].x = expected_box[0].x.min(dist_snapper.up[0][1].x).min(dist_snapper.down[0][1].x); + expected_box[1].x = expected_box[1].x.min(dist_snapper.up[0][1].x).min(dist_snapper.down[0][1].x); + + assert_eq!(snap_results.points[0].distribution_boxes_vertical[1], expected_box); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } + + #[test] + fn dist_snap_point_center_xy() { + let dist_snapper = DistributionSnapper { + up: [-10., -15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + down: [10., 15.].map(|y| Rect::from_square(DVec2::new(0., y), 2.)).to_vec(), + left: [-12., -15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + right: [12., 15.].map(|x| Rect::from_square(DVec2::new(x, 0.), 2.)).to_vec(), + ..Default::default() + }; + let source = Rect::from_square(DVec2::new(0.3, 0.4), 2.); + let snap_results = &mut SnapResults::default(); + dist_snapper.snap_bbox_points(1., &SnapCandidatePoint::default(), snap_results, SnapConstraint::None, source); + + assert_eq!(snap_results.points.len(), 1); + assert_eq!(snap_results.points[0].distance, 0.5000000000000001); + assert_eq!(snap_results.points[0].distribution_equal_distance_horizontal, Some(8.)); + assert_eq!(snap_results.points[0].distribution_equal_distance_vertical, Some(6.)); + assert_eq!(snap_results.points[0].distribution_boxes_horizontal.len(), 3); + assert_eq!(snap_results.points[0].distribution_boxes_vertical.len(), 3); + + assert!(snap_results.points[0].distribution_boxes_horizontal[1][0].y <= dist_snapper.left[0][1].y); + assert!(snap_results.points[0].distribution_boxes_horizontal[1][1].y <= dist_snapper.left[0][1].y); + assert!(snap_results.points[0].distribution_boxes_vertical[1][0].x <= dist_snapper.up[0][1].x); + assert!(snap_results.points[0].distribution_boxes_vertical[1][1].x <= dist_snapper.up[0][1].x); + + assert_eq!(Rect::from_box(snap_results.points[0].source_bounds.unwrap().bounding_box()), Rect::from_square(DVec2::new(0., 0.), 2.)); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_horizontal, 0); + assert_boxes_in_order(&snap_results.points[0].distribution_boxes_vertical, 1); + } } diff --git a/editor/src/messages/tool/common_functionality/transformation_cage.rs b/editor/src/messages/tool/common_functionality/transformation_cage.rs index 8877253996..e33983a0be 100644 --- a/editor/src/messages/tool/common_functionality/transformation_cage.rs +++ b/editor/src/messages/tool/common_functionality/transformation_cage.rs @@ -800,59 +800,64 @@ impl BoundingBoxManager { } } -#[test] -fn skew_transform_singular() { - for edge in [ - SelectedEdges::new(true, false, false, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, true, false, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, false, true, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, false, false, true, [DVec2::NEG_ONE, DVec2::ONE]), - ] { - // The determinant is 0. - let transform = DAffine2::from_cols_array(&[2.; 6]); - // This shouldn't panic. We don't really care about the behavior in this test. - let _ = edge.skew_transform(DVec2::new(1.5, 1.5), transform, false); +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn skew_transform_singular() { + for edge in [ + SelectedEdges::new(true, false, false, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, true, false, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, false, true, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, false, false, true, [DVec2::NEG_ONE, DVec2::ONE]), + ] { + // The determinant is 0. + let transform = DAffine2::from_cols_array(&[2.; 6]); + // This shouldn't panic. We don't really care about the behavior in this test. + let _ = edge.skew_transform(DVec2::new(1.5, 1.5), transform, false); + } } -} - -#[test] -fn skew_transform_correct() { - for edge in [ - SelectedEdges::new(true, false, false, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, true, false, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, false, true, false, [DVec2::NEG_ONE, DVec2::ONE]), - SelectedEdges::new(false, false, false, true, [DVec2::NEG_ONE, DVec2::ONE]), - ] { - // Random transform with det != 0. - let to_viewport_transform = DAffine2::from_cols_array(&[2., 1., 0., 1., 2., 3.]); - // Random mouse position. - let mouse = DVec2::new(1.5, 1.5); - let final_transform = edge.skew_transform(mouse, to_viewport_transform, false); - - // This is the current handle that goes under the mouse. - let opposite = edge.pivot_from_bounds(edge.bounds[0], edge.bounds[1]); - let dragging_point = edge.pivot_from_bounds(edge.bounds[1], edge.bounds[0]); - - let viewport_dragging_point = to_viewport_transform.transform_point2(dragging_point); - let parallel_to_x = edge.top || edge.bottom; - let parallel_to_y = !parallel_to_x && (edge.left || edge.right); - let drag_vector = mouse - viewport_dragging_point; - let document_drag_vector = to_viewport_transform.inverse().transform_vector2(drag_vector); - - let sign = if edge.top || edge.left { -1. } else { 1. }; - let scale_factor = (edge.bounds[1] - edge.bounds[0])[parallel_to_x as usize].abs().recip() * sign; - let scaled_document_drag = document_drag_vector * scale_factor; - - let skew = DAffine2::from_mat2(DMat2::from_cols_array(&[ - 1., - if parallel_to_y { scaled_document_drag.y } else { 0. }, - if parallel_to_x { scaled_document_drag.x } else { 0. }, - 1., - ])); - - let constructed_transform = DAffine2::from_translation(opposite) * skew * DAffine2::from_translation(-opposite); - - assert_eq!(constructed_transform, final_transform); + #[test] + fn skew_transform_correct() { + for edge in [ + SelectedEdges::new(true, false, false, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, true, false, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, false, true, false, [DVec2::NEG_ONE, DVec2::ONE]), + SelectedEdges::new(false, false, false, true, [DVec2::NEG_ONE, DVec2::ONE]), + ] { + // Random transform with det != 0. + let to_viewport_transform = DAffine2::from_cols_array(&[2., 1., 0., 1., 2., 3.]); + // Random mouse position. + let mouse = DVec2::new(1.5, 1.5); + let final_transform = edge.skew_transform(mouse, to_viewport_transform, false); + + // This is the current handle that goes under the mouse. + let opposite = edge.pivot_from_bounds(edge.bounds[0], edge.bounds[1]); + let dragging_point = edge.pivot_from_bounds(edge.bounds[1], edge.bounds[0]); + + let viewport_dragging_point = to_viewport_transform.transform_point2(dragging_point); + let parallel_to_x = edge.top || edge.bottom; + let parallel_to_y = !parallel_to_x && (edge.left || edge.right); + + let drag_vector = mouse - viewport_dragging_point; + let document_drag_vector = to_viewport_transform.inverse().transform_vector2(drag_vector); + + let sign = if edge.top || edge.left { -1. } else { 1. }; + let scale_factor = (edge.bounds[1] - edge.bounds[0])[parallel_to_x as usize].abs().recip() * sign; + let scaled_document_drag = document_drag_vector * scale_factor; + + let skew = DAffine2::from_mat2(DMat2::from_cols_array(&[ + 1., + if parallel_to_y { scaled_document_drag.y } else { 0. }, + if parallel_to_x { scaled_document_drag.x } else { 0. }, + 1., + ])); + + let constructed_transform = DAffine2::from_translation(opposite) * skew * DAffine2::from_translation(-opposite); + + assert_eq!(constructed_transform, final_transform); + } } } diff --git a/libraries/bezier-rs/src/subpath/core.rs b/libraries/bezier-rs/src/subpath/core.rs index 69a75eb1f6..7636ed76b0 100644 --- a/libraries/bezier-rs/src/subpath/core.rs +++ b/libraries/bezier-rs/src/subpath/core.rs @@ -570,28 +570,33 @@ pub fn solve_spline_first_handle_closed(points: &[DVec2]) -> Vec { x } -#[test] -fn closed_spline() { - // These points are just chosen arbitrary - let points = [DVec2::new(0., 0.), DVec2::new(0., 0.), DVec2::new(6., 5.), DVec2::new(7., 9.), DVec2::new(2., 3.)]; +#[cfg(test)] +mod tests { + use super::*; - let out_handles = solve_spline_first_handle_closed(&points); + #[test] + fn closed_spline() { + // These points are just chosen arbitrary + let points = [DVec2::new(0., 0.), DVec2::new(0., 0.), DVec2::new(6., 5.), DVec2::new(7., 9.), DVec2::new(2., 3.)]; - // Construct the Subpath - let mut manipulator_groups = Vec::new(); - for i in 0..out_handles.len() { - manipulator_groups.push(ManipulatorGroup::::new(points[i], Some(2. * points[i] - out_handles[i]), Some(out_handles[i]))); - } - let subpath = Subpath::new(manipulator_groups, true); + let out_handles = solve_spline_first_handle_closed(&points); + + // Construct the Subpath + let mut manipulator_groups = Vec::new(); + for i in 0..out_handles.len() { + manipulator_groups.push(ManipulatorGroup::::new(points[i], Some(2. * points[i] - out_handles[i]), Some(out_handles[i]))); + } + let subpath = Subpath::new(manipulator_groups, true); - // For each pair of bézier curves, ensure that the second derivative is continuous - for (bézier_a, bézier_b) in subpath.iter().zip(subpath.iter().skip(1).chain(subpath.iter().take(1))) { - let derivative2_end_a = bézier_a.derivative().unwrap().derivative().unwrap().evaluate(crate::TValue::Parametric(1.)); - let derivative2_start_b = bézier_b.derivative().unwrap().derivative().unwrap().evaluate(crate::TValue::Parametric(0.)); + // For each pair of bézier curves, ensure that the second derivative is continuous + for (bézier_a, bézier_b) in subpath.iter().zip(subpath.iter().skip(1).chain(subpath.iter().take(1))) { + let derivative2_end_a = bézier_a.derivative().unwrap().derivative().unwrap().evaluate(crate::TValue::Parametric(1.)); + let derivative2_start_b = bézier_b.derivative().unwrap().derivative().unwrap().evaluate(crate::TValue::Parametric(0.)); - assert!( - derivative2_end_a.abs_diff_eq(derivative2_start_b, 1e-10), - "second derivative at the end of a {derivative2_end_a} is equal to the second derivative at the start of b {derivative2_start_b}" - ); + assert!( + derivative2_end_a.abs_diff_eq(derivative2_start_b, 1e-10), + "second derivative at the end of a {derivative2_end_a} is equal to the second derivative at the start of b {derivative2_start_b}" + ); + } } } diff --git a/node-graph/gcore/src/graphic_element/renderer/quad.rs b/node-graph/gcore/src/graphic_element/renderer/quad.rs index d0c3f2d5ad..198e817f29 100644 --- a/node-graph/gcore/src/graphic_element/renderer/quad.rs +++ b/node-graph/gcore/src/graphic_element/renderer/quad.rs @@ -150,43 +150,48 @@ impl core::ops::Mul for DAffine2 { Quad(rhs.0.map(|point| self.transform_point2(point))) } } -#[test] -fn offset_quad() { - fn eq(a: Quad, b: Quad) -> bool { - a.0.iter().zip(b.0).all(|(a, b)| a.abs_diff_eq(b, 0.0001)) - } - - assert!(eq(Quad::from_box([DVec2::ZERO, DVec2::ONE]).inflate(0.5), Quad::from_box([DVec2::splat(-0.5), DVec2::splat(1.5)]))); - assert!(eq(Quad::from_box([DVec2::ONE, DVec2::ZERO]).inflate(0.5), Quad::from_box([DVec2::splat(1.5), DVec2::splat(-0.5)]))); - assert!(eq( - (DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).inflate(0.5), - DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::splat(-0.5), DVec2::splat(1.5)]) - )); -} -#[test] -fn quad_contains() { - assert!(Quad::from_box([DVec2::ZERO, DVec2::ONE]).contains(DVec2::splat(0.5))); - assert!(Quad::from_box([DVec2::ONE, DVec2::ZERO]).contains(DVec2::splat(0.5))); - assert!(Quad::from_box([DVec2::splat(300.), DVec2::splat(500.)]).contains(DVec2::splat(350.))); - assert!((DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).contains(DVec2::new(-0.5, 0.5))); - - assert!(!Quad::from_box([DVec2::ZERO, DVec2::ONE]).contains(DVec2::new(1., 1.1))); - assert!(!Quad::from_box([DVec2::ONE, DVec2::ZERO]).contains(DVec2::new(0.5, -0.01))); - assert!(!(DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).contains(DVec2::splat(0.5))); -} -#[test] -fn intersect_lines() { - assert_eq!( - Quad::intersect_lines(DVec2::new(-5., 5.), DVec2::new(5., 5.), DVec2::new(2., 7.), DVec2::new(2., 3.)), - Some(DVec2::new(2., 5.)) - ); - assert_eq!(Quad::intersect_lines(DVec2::new(4., 6.), DVec2::new(4., 5.), DVec2::new(2., 7.), DVec2::new(2., 3.)), None); - assert_eq!(Quad::intersect_lines(DVec2::new(-5., 5.), DVec2::new(5., 5.), DVec2::new(2., 7.), DVec2::new(2., 9.)), None); -} -#[test] -fn intersect_quad() { - assert!(Quad::from_box([DVec2::ZERO, DVec2::splat(5.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(7.)]))); - assert!(Quad::from_box([DVec2::ZERO, DVec2::splat(5.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(4.2)]))); - assert!(!Quad::from_box([DVec2::ZERO, DVec2::splat(3.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(4.2)]))); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn offset_quad() { + fn eq(a: Quad, b: Quad) -> bool { + a.0.iter().zip(b.0).all(|(a, b)| a.abs_diff_eq(b, 0.0001)) + } + + assert!(eq(Quad::from_box([DVec2::ZERO, DVec2::ONE]).inflate(0.5), Quad::from_box([DVec2::splat(-0.5), DVec2::splat(1.5)]))); + assert!(eq(Quad::from_box([DVec2::ONE, DVec2::ZERO]).inflate(0.5), Quad::from_box([DVec2::splat(1.5), DVec2::splat(-0.5)]))); + assert!(eq( + (DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).inflate(0.5), + DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::splat(-0.5), DVec2::splat(1.5)]) + )); + } + #[test] + fn quad_contains() { + assert!(Quad::from_box([DVec2::ZERO, DVec2::ONE]).contains(DVec2::splat(0.5))); + assert!(Quad::from_box([DVec2::ONE, DVec2::ZERO]).contains(DVec2::splat(0.5))); + assert!(Quad::from_box([DVec2::splat(300.), DVec2::splat(500.)]).contains(DVec2::splat(350.))); + assert!((DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).contains(DVec2::new(-0.5, 0.5))); + + assert!(!Quad::from_box([DVec2::ZERO, DVec2::ONE]).contains(DVec2::new(1., 1.1))); + assert!(!Quad::from_box([DVec2::ONE, DVec2::ZERO]).contains(DVec2::new(0.5, -0.01))); + assert!(!(DAffine2::from_scale(DVec2::new(-1., 1.)) * Quad::from_box([DVec2::ZERO, DVec2::ONE])).contains(DVec2::splat(0.5))); + } + + #[test] + fn intersect_lines() { + assert_eq!( + Quad::intersect_lines(DVec2::new(-5., 5.), DVec2::new(5., 5.), DVec2::new(2., 7.), DVec2::new(2., 3.)), + Some(DVec2::new(2., 5.)) + ); + assert_eq!(Quad::intersect_lines(DVec2::new(4., 6.), DVec2::new(4., 5.), DVec2::new(2., 7.), DVec2::new(2., 3.)), None); + assert_eq!(Quad::intersect_lines(DVec2::new(-5., 5.), DVec2::new(5., 5.), DVec2::new(2., 7.), DVec2::new(2., 9.)), None); + } + #[test] + fn intersect_quad() { + assert!(Quad::from_box([DVec2::ZERO, DVec2::splat(5.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(7.)]))); + assert!(Quad::from_box([DVec2::ZERO, DVec2::splat(5.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(4.2)]))); + assert!(!Quad::from_box([DVec2::ZERO, DVec2::splat(3.)]).intersects(Quad::from_box([DVec2::splat(4.), DVec2::splat(4.2)]))); + } } diff --git a/node-graph/gcore/src/raster/color.rs b/node-graph/gcore/src/raster/color.rs index 283f8e6e56..58342827f6 100644 --- a/node-graph/gcore/src/raster/color.rs +++ b/node-graph/gcore/src/raster/color.rs @@ -1058,37 +1058,41 @@ impl Color { } } -#[test] -fn hsl_roundtrip() { - for (red, green, blue) in [ - (24, 98, 118), - (69, 11, 89), - (54, 82, 38), - (47, 76, 50), - (25, 15, 73), - (62, 57, 33), - (55, 2, 18), - (12, 3, 82), - (91, 16, 98), - (91, 39, 82), - (97, 53, 32), - (76, 8, 91), - (54, 87, 19), - (56, 24, 88), - (14, 82, 34), - (61, 86, 31), - (73, 60, 75), - (95, 79, 88), - (13, 34, 4), - (82, 84, 84), - (255, 255, 178), - ] { - let col = Color::from_rgb8_srgb(red, green, blue); - let [hue, saturation, lightness, alpha] = col.to_hsla(); - let result = Color::from_hsla(hue, saturation, lightness, alpha); - assert!((col.r() - result.r()) < f32::EPSILON * 100.); - assert!((col.g() - result.g()) < f32::EPSILON * 100.); - assert!((col.b() - result.b()) < f32::EPSILON * 100.); - assert!((col.a() - result.a()) < f32::EPSILON * 100.); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn hsl_roundtrip() { + for (red, green, blue) in [ + (24, 98, 118), + (69, 11, 89), + (54, 82, 38), + (47, 76, 50), + (25, 15, 73), + (62, 57, 33), + (55, 2, 18), + (12, 3, 82), + (91, 16, 98), + (91, 39, 82), + (97, 53, 32), + (76, 8, 91), + (54, 87, 19), + (56, 24, 88), + (14, 82, 34), + (61, 86, 31), + (73, 60, 75), + (95, 79, 88), + (13, 34, 4), + (82, 84, 84), + (255, 255, 178), + ] { + let col = Color::from_rgb8_srgb(red, green, blue); + let [hue, saturation, lightness, alpha] = col.to_hsla(); + let result = Color::from_hsla(hue, saturation, lightness, alpha); + assert!((col.r() - result.r()) < f32::EPSILON * 100.); + assert!((col.g() - result.g()) < f32::EPSILON * 100.); + assert!((col.b() - result.b()) < f32::EPSILON * 100.); + assert!((col.a() - result.a()) < f32::EPSILON * 100.); + } } } diff --git a/node-graph/gcore/src/text/to_path.rs b/node-graph/gcore/src/text/to_path.rs index 4a0e13cb32..2552127b97 100644 --- a/node-graph/gcore/src/text/to_path.rs +++ b/node-graph/gcore/src/text/to_path.rs @@ -239,11 +239,15 @@ impl<'a> Iterator for SplitWordsIncludingSpaces<'a> { } } -#[test] -fn split_words_including_spaces() { - let mut split_words = SplitWordsIncludingSpaces::new("hello world ."); - assert_eq!(split_words.next(), Some("hello ")); - assert_eq!(split_words.next(), Some("world ")); - assert_eq!(split_words.next(), Some(".")); - assert_eq!(split_words.next(), None); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn split_words_including_spaces() { + let mut split_words = SplitWordsIncludingSpaces::new("hello world ."); + assert_eq!(split_words.next(), Some("hello ")); + assert_eq!(split_words.next(), Some("world ")); + assert_eq!(split_words.next(), Some(".")); + assert_eq!(split_words.next(), None); + } } diff --git a/node-graph/gcore/src/vector/algorithms/spline.rs b/node-graph/gcore/src/vector/algorithms/spline.rs index 6b62af9a70..27011013b2 100644 --- a/node-graph/gcore/src/vector/algorithms/spline.rs +++ b/node-graph/gcore/src/vector/algorithms/spline.rs @@ -136,43 +136,47 @@ pub fn solve_spline_first_handle_closed(points: &[DVec2]) -> Vec { x } -#[test] -fn closed_spline() { - use crate::vector::misc::{dvec2_to_point, point_to_dvec2}; - use kurbo::{BezPath, ParamCurve, ParamCurveDeriv}; - - // These points are just chosen arbitrary - let points = [DVec2::new(0., 0.), DVec2::new(0., 0.), DVec2::new(6., 5.), DVec2::new(7., 9.), DVec2::new(2., 3.)]; - - // List of first handle or second point in a cubic bezier curve. - let first_handles = solve_spline_first_handle_closed(&points); - - // Construct the Subpath - let mut bezpath = BezPath::new(); - bezpath.move_to(dvec2_to_point(points[0])); - - for i in 0..first_handles.len() { - let next_i = i + 1; - let next_i = if next_i == first_handles.len() { 0 } else { next_i }; - - // First handle or second point of a cubic Bezier curve. - let p1 = dvec2_to_point(first_handles[i]); - // Second handle or third point of a cubic Bezier curve. - let p2 = dvec2_to_point(2. * points[next_i] - first_handles[next_i]); - // Endpoint or fourth point of a cubic Bezier curve. - let p3 = dvec2_to_point(points[next_i]); - - bezpath.curve_to(p1, p2, p3); - } - - // For each pair of bézier curves, ensure that the second derivative is continuous - for (bézier_a, bézier_b) in bezpath.segments().zip(bezpath.segments().skip(1).chain(bezpath.segments().take(1))) { - let derivative2_end_a = point_to_dvec2(bézier_a.to_cubic().deriv().eval(1.)); - let derivative2_start_b = point_to_dvec2(bézier_b.to_cubic().deriv().eval(0.)); - - assert!( - derivative2_end_a.abs_diff_eq(derivative2_start_b, 1e-10), - "second derivative at the end of a {derivative2_end_a} is equal to the second derivative at the start of b {derivative2_start_b}" - ); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn closed_spline() { + use crate::vector::misc::{dvec2_to_point, point_to_dvec2}; + use kurbo::{BezPath, ParamCurve, ParamCurveDeriv}; + + // These points are just chosen arbitrary + let points = [DVec2::new(0., 0.), DVec2::new(0., 0.), DVec2::new(6., 5.), DVec2::new(7., 9.), DVec2::new(2., 3.)]; + + // List of first handle or second point in a cubic bezier curve. + let first_handles = solve_spline_first_handle_closed(&points); + + // Construct the Subpath + let mut bezpath = BezPath::new(); + bezpath.move_to(dvec2_to_point(points[0])); + + for i in 0..first_handles.len() { + let next_i = i + 1; + let next_i = if next_i == first_handles.len() { 0 } else { next_i }; + + // First handle or second point of a cubic Bezier curve. + let p1 = dvec2_to_point(first_handles[i]); + // Second handle or third point of a cubic Bezier curve. + let p2 = dvec2_to_point(2. * points[next_i] - first_handles[next_i]); + // Endpoint or fourth point of a cubic Bezier curve. + let p3 = dvec2_to_point(points[next_i]); + + bezpath.curve_to(p1, p2, p3); + } + + // For each pair of bézier curves, ensure that the second derivative is continuous + for (bézier_a, bézier_b) in bezpath.segments().zip(bezpath.segments().skip(1).chain(bezpath.segments().take(1))) { + let derivative2_end_a = point_to_dvec2(bézier_a.to_cubic().deriv().eval(1.)); + let derivative2_start_b = point_to_dvec2(bézier_b.to_cubic().deriv().eval(0.)); + + assert!( + derivative2_end_a.abs_diff_eq(derivative2_start_b, 1e-10), + "second derivative at the end of a {derivative2_end_a} is equal to the second derivative at the start of b {derivative2_start_b}" + ); + } } } diff --git a/node-graph/gcore/src/vector/generator_nodes.rs b/node-graph/gcore/src/vector/generator_nodes.rs index af43043dbe..2959698d89 100644 --- a/node-graph/gcore/src/vector/generator_nodes.rs +++ b/node-graph/gcore/src/vector/generator_nodes.rs @@ -245,35 +245,39 @@ fn grid( VectorDataTable::new(vector_data) } -#[test] -fn isometric_grid_test() { - // Doesn't crash with weird angles - grid((), (), GridType::Isometric, 0., (0., 0.).into(), 5, 5); - grid((), (), GridType::Isometric, 90., (90., 90.).into(), 5, 5); - - // Works properly - let grid = grid((), (), GridType::Isometric, 10., (30., 30.).into(), 5, 5); - assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5); - assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9); - for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() { - assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear); - assert!( - ((bezier.start - bezier.end).length() - 10.).abs() < 1e-5, - "Length of {} should be 10", - (bezier.start - bezier.end).length() - ); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn isometric_grid_test() { + // Doesn't crash with weird angles + grid((), (), GridType::Isometric, 0., (0., 0.).into(), 5, 5); + grid((), (), GridType::Isometric, 90., (90., 90.).into(), 5, 5); + + // Works properly + let grid = grid((), (), GridType::Isometric, 10., (30., 30.).into(), 5, 5); + assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5); + assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9); + for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() { + assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear); + assert!( + ((bezier.start - bezier.end).length() - 10.).abs() < 1e-5, + "Length of {} should be 10", + (bezier.start - bezier.end).length() + ); + } } -} -#[test] -fn skew_isometric_grid_test() { - let grid = grid((), (), GridType::Isometric, 10., (40., 30.).into(), 5, 5); - assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5); - assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9); - for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() { - assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear); - let vector = bezier.start - bezier.end; - let angle = (vector.angle_to(DVec2::X).to_degrees() + 180.) % 180.; - assert!([90., 150., 40.].into_iter().any(|target| (target - angle).abs() < 1e-10), "unexpected angle of {}", angle) + #[test] + fn skew_isometric_grid_test() { + let grid = grid((), (), GridType::Isometric, 10., (40., 30.).into(), 5, 5); + assert_eq!(grid.instance_ref_iter().next().unwrap().instance.point_domain.ids().len(), 5 * 5); + assert_eq!(grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter().count(), 4 * 5 + 4 * 9); + for (_, bezier, _, _) in grid.instance_ref_iter().next().unwrap().instance.segment_bezier_iter() { + assert_eq!(bezier.handles, bezier_rs::BezierHandles::Linear); + let vector = bezier.start - bezier.end; + let angle = (vector.angle_to(DVec2::X).to_degrees() + 180.) % 180.; + assert!([90., 150., 40.].into_iter().any(|target| (target - angle).abs() < 1e-10), "unexpected angle of {}", angle) + } } } diff --git a/node-graph/gcore/src/vector/vector_data.rs b/node-graph/gcore/src/vector/vector_data.rs index a987260d07..379e442f43 100644 --- a/node-graph/gcore/src/vector/vector_data.rs +++ b/node-graph/gcore/src/vector/vector_data.rs @@ -676,45 +676,49 @@ fn assert_subpath_eq(generated: &[bezier_rs::Subpath], expected: &[bezi } } -#[test] -fn construct_closed_subpath() { - let circle = bezier_rs::Subpath::new_ellipse(DVec2::NEG_ONE, DVec2::ONE); - let vector_data = VectorData::from_subpath(&circle); - assert_eq!(vector_data.point_domain.ids().len(), 4); - let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); - assert_eq!(bezier_paths.len(), 4); - assert!(bezier_paths.iter().all(|&bezier| circle.iter().any(|original_bezier| original_bezier == bezier))); - - let generated = vector_data.stroke_bezier_paths().collect::>(); - assert_subpath_eq(&generated, &[circle]); -} - -#[test] -fn construct_open_subpath() { - let bezier = bezier_rs::Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::NEG_ONE, DVec2::ONE, DVec2::X); - let subpath = bezier_rs::Subpath::from_bezier(&bezier); - let vector_data = VectorData::from_subpath(&subpath); - assert_eq!(vector_data.point_domain.ids().len(), 2); - let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); - assert_eq!(bezier_paths, vec![bezier]); - - let generated = vector_data.stroke_bezier_paths().collect::>(); - assert_subpath_eq(&generated, &[subpath]); -} - -#[test] -fn construct_many_subpath() { - let curve = bezier_rs::Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::NEG_ONE, DVec2::ONE, DVec2::X); - let curve = bezier_rs::Subpath::from_bezier(&curve); - let circle = bezier_rs::Subpath::new_ellipse(DVec2::NEG_ONE, DVec2::ONE); - - let vector_data = VectorData::from_subpaths([&curve, &circle], false); - assert_eq!(vector_data.point_domain.ids().len(), 6); - - let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); - assert_eq!(bezier_paths.len(), 5); - assert!(bezier_paths.iter().all(|&bezier| circle.iter().chain(curve.iter()).any(|original_bezier| original_bezier == bezier))); - - let generated = vector_data.stroke_bezier_paths().collect::>(); - assert_subpath_eq(&generated, &[curve, circle]); +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn construct_closed_subpath() { + let circle = bezier_rs::Subpath::new_ellipse(DVec2::NEG_ONE, DVec2::ONE); + let vector_data = VectorData::from_subpath(&circle); + assert_eq!(vector_data.point_domain.ids().len(), 4); + let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); + assert_eq!(bezier_paths.len(), 4); + assert!(bezier_paths.iter().all(|&bezier| circle.iter().any(|original_bezier| original_bezier == bezier))); + + let generated = vector_data.stroke_bezier_paths().collect::>(); + assert_subpath_eq(&generated, &[circle]); + } + + #[test] + fn construct_open_subpath() { + let bezier = bezier_rs::Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::NEG_ONE, DVec2::ONE, DVec2::X); + let subpath = bezier_rs::Subpath::from_bezier(&bezier); + let vector_data = VectorData::from_subpath(&subpath); + assert_eq!(vector_data.point_domain.ids().len(), 2); + let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); + assert_eq!(bezier_paths, vec![bezier]); + + let generated = vector_data.stroke_bezier_paths().collect::>(); + assert_subpath_eq(&generated, &[subpath]); + } + + #[test] + fn construct_many_subpath() { + let curve = bezier_rs::Bezier::from_cubic_dvec2(DVec2::ZERO, DVec2::NEG_ONE, DVec2::ONE, DVec2::X); + let curve = bezier_rs::Subpath::from_bezier(&curve); + let circle = bezier_rs::Subpath::new_ellipse(DVec2::NEG_ONE, DVec2::ONE); + + let vector_data = VectorData::from_subpaths([&curve, &circle], false); + assert_eq!(vector_data.point_domain.ids().len(), 6); + + let bezier_paths = vector_data.segment_bezier_iter().map(|(_, bezier, _, _)| bezier).collect::>(); + assert_eq!(bezier_paths.len(), 5); + assert!(bezier_paths.iter().all(|&bezier| circle.iter().chain(curve.iter()).any(|original_bezier| original_bezier == bezier))); + + let generated = vector_data.stroke_bezier_paths().collect::>(); + assert_subpath_eq(&generated, &[curve, circle]); + } } diff --git a/node-graph/gcore/src/vector/vector_data/modification.rs b/node-graph/gcore/src/vector/vector_data/modification.rs index eb0e16998c..73c4736222 100644 --- a/node-graph/gcore/src/vector/vector_data/modification.rs +++ b/node-graph/gcore/src/vector/vector_data/modification.rs @@ -436,64 +436,6 @@ async fn path_modify(_ctx: impl Ctx, mut vector_data: VectorDataTable, modificat vector_data } -#[test] -fn modify_new() { - let vector_data = VectorData::from_subpaths( - [bezier_rs::Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE), bezier_rs::Subpath::new_rect(DVec2::NEG_ONE, DVec2::ZERO)], - false, - ); - - let modify = VectorModification::create_from_vector(&vector_data); - - let mut new = VectorData::default(); - modify.apply(&mut new); - assert_eq!(vector_data, new); -} - -#[test] -fn modify_existing() { - use bezier_rs::{Bezier, Subpath}; - let subpaths = [ - Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE), - Subpath::new_rect(DVec2::NEG_ONE, DVec2::ZERO), - Subpath::from_beziers( - &[ - Bezier::from_quadratic_dvec2(DVec2::new(0., 0.), DVec2::new(5., 10.), DVec2::new(10., 0.)), - Bezier::from_quadratic_dvec2(DVec2::new(10., 0.), DVec2::new(15., 10.), DVec2::new(20., 0.)), - ], - false, - ), - ]; - let mut vector_data = VectorData::from_subpaths(subpaths, false); - - let mut modify_new = VectorModification::create_from_vector(&vector_data); - let mut modify_original = VectorModification::default(); - - for modification in [&mut modify_new, &mut modify_original] { - let point = vector_data.point_domain.ids()[0]; - modification.modify(&VectorModificationType::ApplyPointDelta { point, delta: DVec2::X * 0.5 }); - let point = vector_data.point_domain.ids()[9]; - modification.modify(&VectorModificationType::ApplyPointDelta { point, delta: DVec2::X }); - } - - let mut new = VectorData::default(); - modify_new.apply(&mut new); - - modify_original.apply(&mut vector_data); - - assert_eq!(vector_data, new); - assert_eq!(vector_data.point_domain.positions()[0], DVec2::X); - assert_eq!(vector_data.point_domain.positions()[9], DVec2::new(11., 0.)); - assert_eq!( - vector_data.segment_bezier_iter().nth(8).unwrap().1, - Bezier::from_quadratic_dvec2(DVec2::new(0., 0.), DVec2::new(5., 10.), DVec2::new(11., 0.)) - ); - assert_eq!( - vector_data.segment_bezier_iter().nth(9).unwrap().1, - Bezier::from_quadratic_dvec2(DVec2::new(11., 0.), DVec2::new(16., 10.), DVec2::new(20., 0.)) - ); -} - // Do we want to enforce that all serialized/deserialized hashmaps are a vec of tuples? // TODO: Eventually remove this document upgrade code use serde::de::{SeqAccess, Visitor}; @@ -686,3 +628,66 @@ impl<'a> AppendBezpath<'a> { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn modify_new() { + let vector_data = VectorData::from_subpaths( + [bezier_rs::Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE), bezier_rs::Subpath::new_rect(DVec2::NEG_ONE, DVec2::ZERO)], + false, + ); + + let modify = VectorModification::create_from_vector(&vector_data); + + let mut new = VectorData::default(); + modify.apply(&mut new); + assert_eq!(vector_data, new); + } + + #[test] + fn modify_existing() { + use bezier_rs::{Bezier, Subpath}; + let subpaths = [ + Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE), + Subpath::new_rect(DVec2::NEG_ONE, DVec2::ZERO), + Subpath::from_beziers( + &[ + Bezier::from_quadratic_dvec2(DVec2::new(0., 0.), DVec2::new(5., 10.), DVec2::new(10., 0.)), + Bezier::from_quadratic_dvec2(DVec2::new(10., 0.), DVec2::new(15., 10.), DVec2::new(20., 0.)), + ], + false, + ), + ]; + let mut vector_data = VectorData::from_subpaths(subpaths, false); + + let mut modify_new = VectorModification::create_from_vector(&vector_data); + let mut modify_original = VectorModification::default(); + + for modification in [&mut modify_new, &mut modify_original] { + let point = vector_data.point_domain.ids()[0]; + modification.modify(&VectorModificationType::ApplyPointDelta { point, delta: DVec2::X * 0.5 }); + let point = vector_data.point_domain.ids()[9]; + modification.modify(&VectorModificationType::ApplyPointDelta { point, delta: DVec2::X }); + } + + let mut new = VectorData::default(); + modify_new.apply(&mut new); + + modify_original.apply(&mut vector_data); + + assert_eq!(vector_data, new); + assert_eq!(vector_data.point_domain.positions()[0], DVec2::X); + assert_eq!(vector_data.point_domain.positions()[9], DVec2::new(11., 0.)); + assert_eq!( + vector_data.segment_bezier_iter().nth(8).unwrap().1, + Bezier::from_quadratic_dvec2(DVec2::new(0., 0.), DVec2::new(5., 10.), DVec2::new(11., 0.)) + ); + assert_eq!( + vector_data.segment_bezier_iter().nth(9).unwrap().1, + Bezier::from_quadratic_dvec2(DVec2::new(11., 0.), DVec2::new(16., 10.), DVec2::new(20., 0.)) + ); + } +}