Bezier-rs: Added function to find intersections between a bezier and a rectangle (#897)
* added function to find intersections for a rectangle * Added is_contained_within function
This commit is contained in:
parent
951c49a979
commit
ef99c91226
|
|
@ -139,6 +139,12 @@ impl Bezier {
|
|||
[endpoints_min, endpoints_max]
|
||||
}
|
||||
|
||||
/// Returns `true` if the bounding box of the bezier is contained entirely within a rectangle defined by its minimum and maximum corners.
|
||||
pub fn is_contained_within(&self, min_corner: DVec2, max_corner: DVec2) -> bool {
|
||||
let [bounding_box_min, bounding_box_max] = self.bounding_box();
|
||||
min_corner.x <= bounding_box_min.x && min_corner.y <= bounding_box_min.y && bounding_box_max.x <= max_corner.x && bounding_box_max.y <= max_corner.y
|
||||
}
|
||||
|
||||
// TODO: Use an `impl Iterator` return type instead of a `Vec`
|
||||
/// Returns list of `t`-values representing the inflection points of the curve.
|
||||
/// The inflection points are defined to be points at which the second derivative of the curve is equal to zero.
|
||||
|
|
@ -355,6 +361,19 @@ impl Bezier {
|
|||
.flat_map(|(index, (subcurve, t_pair))| Bezier::intersections_between_vectors_of_curves(&[(subcurve, t_pair)], &combined_list2[index + 2..], error))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns a list of `t` values that correspond to the intersection points between the curve and a rectangle defined by opposite corners.
|
||||
pub fn rectangle_intersections(&self, corner1: DVec2, corner2: DVec2) -> Vec<f64> {
|
||||
[
|
||||
Bezier::from_linear_coordinates(corner1.x, corner1.y, corner2.x, corner1.y),
|
||||
Bezier::from_linear_coordinates(corner2.x, corner1.y, corner2.x, corner2.y),
|
||||
Bezier::from_linear_coordinates(corner2.x, corner2.y, corner1.x, corner2.y),
|
||||
Bezier::from_linear_coordinates(corner1.x, corner2.y, corner1.x, corner1.y),
|
||||
]
|
||||
.iter()
|
||||
.flat_map(|bezier| self.intersections(bezier, None, None))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -554,6 +554,14 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Intersect (Rectangle)",
|
||||
callback: (bezier: WasmBezierInstance): string =>
|
||||
bezier.intersect_rectangle([
|
||||
[50, 50],
|
||||
[150, 150],
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "Rotate",
|
||||
callback: (bezier: WasmBezierInstance, options: Record<string, number>): string => bezier.rotate(options.angle * Math.PI, 100, 100),
|
||||
|
|
|
|||
|
|
@ -477,6 +477,33 @@ impl WasmBezier {
|
|||
wrap_svg_tag(intersect_self_svg)
|
||||
}
|
||||
|
||||
pub fn intersect_rectangle(&self, js_points: &JsValue) -> String {
|
||||
let points: [DVec2; 2] = js_points.into_serde().unwrap();
|
||||
|
||||
let bezier_curve_svg = self.get_bezier_path();
|
||||
|
||||
let mut rectangle_svg = String::new();
|
||||
[
|
||||
Bezier::from_linear_coordinates(points[0].x, points[0].y, points[1].x, points[0].y),
|
||||
Bezier::from_linear_coordinates(points[1].x, points[0].y, points[1].x, points[1].y),
|
||||
Bezier::from_linear_coordinates(points[1].x, points[1].y, points[0].x, points[1].y),
|
||||
Bezier::from_linear_coordinates(points[0].x, points[1].y, points[0].x, points[0].y),
|
||||
]
|
||||
.iter()
|
||||
.for_each(|line| line.to_svg(&mut rectangle_svg, CURVE_ATTRIBUTES.to_string().replace(BLACK, RED), String::new(), String::new(), String::new()));
|
||||
|
||||
let intersections_svg = self
|
||||
.0
|
||||
.rectangle_intersections(points[0], points[1])
|
||||
.iter()
|
||||
.map(|intersection_t| {
|
||||
let point = &self.0.evaluate(ComputeType::Parametric(*intersection_t));
|
||||
draw_circle(*point, 4., RED, 1.5, WHITE)
|
||||
})
|
||||
.fold(String::new(), |acc, item| format!("{acc}{item}"));
|
||||
wrap_svg_tag(format!("{bezier_curve_svg}{rectangle_svg}{intersections_svg}"))
|
||||
}
|
||||
|
||||
pub fn reduce(&self) -> String {
|
||||
let original_curve_svg = self.get_bezier_path();
|
||||
let bezier_curves_svg: String = self
|
||||
|
|
|
|||
Loading…
Reference in New Issue