mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 13:28:11 +08:00
Fix bounding boxes of VectorData with rotations in several nodes (#1792)
The VectorData::bounding_box() function does not apply the VectorData's transform, and bounding_box_with_transform() must be used instead of applying the transform to the computed bounding box. It may make sense in the future to move the current version of bounding_box to a private method bounding_box_no_transform() and have the public bounding_box call bounding_box_with_transform so that external code doesn't need to know about how the VectorData stores it's data. This fixes the following nodes: - Repeat - Circular Repeat - Bounding Box Also add a test to the bounding box node for this situation.
This commit is contained in:
@@ -76,7 +76,9 @@ fn repeat_vector_data(vector_data: VectorData, direction: DVec2, angle: f64, ins
|
|||||||
// Repeat the vector data
|
// Repeat the vector data
|
||||||
let mut result = VectorData::empty();
|
let mut result = VectorData::empty();
|
||||||
|
|
||||||
let Some(bounding_box) = vector_data.bounding_box() else { return vector_data };
|
let Some(bounding_box) = vector_data.bounding_box_with_transform(vector_data.transform) else {
|
||||||
|
return vector_data;
|
||||||
|
};
|
||||||
let center = (bounding_box[0] + bounding_box[1]) / 2.;
|
let center = (bounding_box[0] + bounding_box[1]) / 2.;
|
||||||
|
|
||||||
for i in 0..instances {
|
for i in 0..instances {
|
||||||
@@ -108,7 +110,9 @@ fn circular_repeat_vector_data(vector_data: VectorData, angle_offset: f64, radiu
|
|||||||
|
|
||||||
let mut result = VectorData::empty();
|
let mut result = VectorData::empty();
|
||||||
|
|
||||||
let Some(bounding_box) = vector_data.bounding_box() else { return vector_data };
|
let Some(bounding_box) = vector_data.bounding_box_with_transform(vector_data.transform) else {
|
||||||
|
return vector_data;
|
||||||
|
};
|
||||||
let center = (bounding_box[0] + bounding_box[1]) / 2.;
|
let center = (bounding_box[0] + bounding_box[1]) / 2.;
|
||||||
|
|
||||||
let base_transform = DVec2::new(0., radius) - center;
|
let base_transform = DVec2::new(0., radius) - center;
|
||||||
@@ -128,11 +132,8 @@ pub struct BoundingBoxNode;
|
|||||||
|
|
||||||
#[node_macro::node_fn(BoundingBoxNode)]
|
#[node_macro::node_fn(BoundingBoxNode)]
|
||||||
fn generate_bounding_box(vector_data: VectorData) -> VectorData {
|
fn generate_bounding_box(vector_data: VectorData) -> VectorData {
|
||||||
let bounding_box = vector_data.bounding_box().unwrap();
|
let bounding_box = vector_data.bounding_box_with_transform(vector_data.transform).unwrap();
|
||||||
VectorData::from_subpath(Subpath::new_rect(
|
VectorData::from_subpath(Subpath::new_rect(bounding_box[0], bounding_box[1]))
|
||||||
vector_data.transform.transform_point2(bounding_box[0]),
|
|
||||||
vector_data.transform.transform_point2(bounding_box[1]),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -652,6 +653,16 @@ mod test {
|
|||||||
assert_eq!(bounding_box.region_bezier_paths().count(), 1);
|
assert_eq!(bounding_box.region_bezier_paths().count(), 1);
|
||||||
let subpath = bounding_box.region_bezier_paths().next().unwrap().1;
|
let subpath = bounding_box.region_bezier_paths().next().unwrap().1;
|
||||||
assert_eq!(&subpath.anchors()[..4], &[DVec2::NEG_ONE, DVec2::new(1., -1.), DVec2::ONE, DVec2::new(-1., 1.),]);
|
assert_eq!(&subpath.anchors()[..4], &[DVec2::NEG_ONE, DVec2::new(1., -1.), DVec2::ONE, DVec2::new(-1., 1.),]);
|
||||||
|
|
||||||
|
// test a VectorData with non-zero rotation
|
||||||
|
let mut square = VectorData::from_subpath(Subpath::new_rect(DVec2::NEG_ONE, DVec2::ONE));
|
||||||
|
square.transform *= DAffine2::from_angle(core::f64::consts::FRAC_PI_4);
|
||||||
|
let bounding_box = BoundingBoxNode.eval(square);
|
||||||
|
assert_eq!(bounding_box.region_bezier_paths().count(), 1);
|
||||||
|
let subpath = bounding_box.region_bezier_paths().next().unwrap().1;
|
||||||
|
let sqrt2 = core::f64::consts::SQRT_2;
|
||||||
|
let sqrt2_bounding_box = [DVec2::new(-sqrt2, -sqrt2), DVec2::new(sqrt2, -sqrt2), DVec2::new(sqrt2, sqrt2), DVec2::new(-sqrt2, sqrt2)];
|
||||||
|
assert!(subpath.anchors()[..4].iter().zip(sqrt2_bounding_box).all(|(p1, p2)| p1.abs_diff_eq(p2, f64::EPSILON)));
|
||||||
}
|
}
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn copy_to_points() {
|
async fn copy_to_points() {
|
||||||
|
|||||||
Reference in New Issue
Block a user