Skip to content

Commit f426fb7

Browse files
committed
FIx: Box warp function combined subpath
1 parent fa45efa commit f426fb7

File tree

1 file changed

+49
-64
lines changed

1 file changed

+49
-64
lines changed

node-graph/nodes/vector/src/vector_nodes.rs

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -789,74 +789,59 @@ async fn box_warp(_: impl Ctx, content: Table<Vector>, #[expose] rectangle: Tabl
789789
let Some((target, target_transform)) = rectangle.get(0).map(|rect| (rect.element, rect.transform)) else {
790790
return content;
791791
};
792+
//calculate the minumum and max corner of all the shapes
793+
let mut min_corner = DVec2::new(f64::MAX, f64::MAX);
794+
let mut max_corner = DVec2::new(f64::MIN, f64::MIN);
792795

793-
content
794-
.into_iter()
795-
.map(|mut row| {
796-
let transform = row.transform;
797-
let vector = row.element;
798-
799-
// Get the bounding box of the source vector geometry
800-
let source_bbox = vector.bounding_box_with_transform(transform).unwrap_or([DVec2::ZERO, DVec2::ONE]);
801-
802-
// Extract first 4 points from target shape to form the quadrilateral
803-
// Apply the target's transform to get points in world space
804-
let target_points: Vec<DVec2> = target.point_domain.positions().iter().map(|&p| target_transform.transform_point2(p)).take(4).collect();
805-
806-
// If we have fewer than 4 points, use the corners of the source bounding box
807-
// This handles the degenerative case
808-
let dst_corners = if target_points.len() >= 4 {
809-
[target_points[0], target_points[1], target_points[2], target_points[3]]
810-
} else {
811-
warn!("Target shape has fewer than 4 points. Using source bounding box instead.");
812-
[
813-
source_bbox[0],
814-
DVec2::new(source_bbox[1].x, source_bbox[0].y),
815-
source_bbox[1],
816-
DVec2::new(source_bbox[0].x, source_bbox[1].y),
817-
]
818-
};
819-
820-
// Apply the warp
821-
let mut result = vector.clone();
822-
823-
// Precompute source bounding box size for normalization
824-
let source_size = source_bbox[1] - source_bbox[0];
825-
826-
// Transform points
827-
for (_, position) in result.point_domain.positions_mut() {
828-
// Get the point in world space
829-
let world_pos = transform.transform_point2(*position);
830-
831-
// Normalize coordinates within the source bounding box
832-
let t = ((world_pos - source_bbox[0]) / source_size).clamp(DVec2::ZERO, DVec2::ONE);
833-
834-
// Apply bilinear interpolation
835-
*position = bilinear_interpolate(t, &dst_corners);
836-
}
837-
838-
// Transform handles in bezier curves
839-
for (_, handles, _, _) in result.handles_mut() {
840-
*handles = handles.apply_transformation(|pos| {
841-
// Get the handle in world space
842-
let world_pos = transform.transform_point2(pos);
843-
844-
// Normalize coordinates within the source bounding box
845-
let t = ((world_pos - source_bbox[0]) / source_size).clamp(DVec2::ZERO, DVec2::ONE);
796+
for row in content.iter() {
797+
if let Some(bbox) = row.element.bounding_box_with_transform(*row.transform) {
798+
min_corner = min_corner.min(bbox[0]);
799+
max_corner = max_corner.max(bbox[1]);
800+
}
801+
}
802+
let source_bbox = [min_corner, max_corner];
803+
let source_size = source_bbox[1] - source_bbox[0];
846804

847-
// Apply bilinear interpolation
848-
bilinear_interpolate(t, &dst_corners)
849-
});
850-
}
805+
let target_points: Vec<DVec2> = target.point_domain.positions().iter().map(|&p| target_transform.transform_point2(p)).take(4).collect();
851806

852-
result.style.set_stroke_transform(DAffine2::IDENTITY);
807+
let dst_corners = if target_points.len() >= 4 {
808+
[target_points[0], target_points[1], target_points[2], target_points[3]]
809+
} else {
810+
warn!("Target shape has fewer than 4 points. Using source bounding box instead.");
811+
[
812+
source_bbox[0],
813+
DVec2::new(source_bbox[1].x, source_bbox[0].y),
814+
source_bbox[1],
815+
DVec2::new(source_bbox[0].x, source_bbox[1].y),
816+
]
817+
};
853818

854-
// Add this to the table and reset the transform since we've applied it directly to the points
855-
row.element = result;
856-
row.transform = DAffine2::IDENTITY;
857-
row
858-
})
859-
.collect()
819+
content
820+
.into_iter()
821+
.map(|mut row| {
822+
let transform = row.transform;
823+
let vector = &row.element;
824+
let mut result = vector.clone();
825+
826+
for (_, position) in result.point_domain.positions_mut() {
827+
let world_pos = transform.transform_point2(*position);
828+
let t = ((world_pos - source_bbox[0]) / source_size).clamp(DVec2::ZERO, DVec2::ONE);
829+
*position = bilinear_interpolate(t, &dst_corners);
830+
}
831+
832+
for (_, handles, _, _) in result.handles_mut() {
833+
*handles = handles.apply_transformation(|pos| {
834+
let world_pos = transform.transform_point2(pos);
835+
let t = ((world_pos - source_bbox[0]) / source_size).clamp(DVec2::ZERO, DVec2::ONE);
836+
bilinear_interpolate(t, &dst_corners)
837+
});
838+
}
839+
result.style.set_stroke_transform(DAffine2::IDENTITY);
840+
row.element = result;
841+
row.transform = DAffine2::IDENTITY;
842+
row
843+
})
844+
.collect()
860845
}
861846

862847
// Interpolate within a quadrilateral using normalized coordinates (0-1)

0 commit comments

Comments
 (0)