diff --git a/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs b/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs
index 3a8c70ae33..566fd6bd27 100644
--- a/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs
+++ b/node-graph/gcore/src/vector/algorithms/bezpath_algorithms.rs
@@ -1,12 +1,14 @@
 use super::poisson_disk::poisson_disk_sample;
 use crate::vector::misc::dvec2_to_point;
 use glam::DVec2;
-use kurbo::{BezPath, Line, ParamCurve, ParamCurveDeriv, PathSeg, Point, Rect, Shape};
+use kurbo::{BezPath, CubicBez, Line, ParamCurve, ParamCurveDeriv, PathSeg, Point, QuadBez, Rect, Shape};
 
 /// Accuracy to find the position on [kurbo::Bezpath].
 const POSITION_ACCURACY: f64 = 1e-5;
 /// Accuracy to find the length of the [kurbo::PathSeg].
 pub const PERIMETER_ACCURACY: f64 = 1e-5;
+/// Constant used to determine if `f64`s are equivalent.
+pub const MAX_ABSOLUTE_DIFFERENCE: f64 = 1e-3;
 
 pub fn position_on_bezpath(bezpath: &BezPath, t: f64, euclidian: bool, segments_length: Option<&[f64]>) -> Point {
 	let (segment_index, t) = t_value_to_parametric(bezpath, t, euclidian, segments_length);
@@ -241,3 +243,16 @@ pub fn poisson_disk_points(bezpath_index: usize, bezpaths: &[(BezPath, Rect)], s
 
 	poisson_disk_sample(offset, width, height, separation_disk_diameter, point_in_shape_checker, line_intersect_shape_checker, rng)
 }
+
+/// Returns true if the Bezier curve is equivalent to a line.
+///
+/// **NOTE**: This is different from simply checking if the segment is [`PathSeg::Line`] or [`PathSeg::Quad`] or [`PathSeg::Cubic`]. Bezier curve can also be a line if the control points are colinear to the start and end points. Therefore if the handles exceed the start and end point, it will still be considered as a line.
+pub fn is_linear(segment: &PathSeg) -> bool {
+	let is_colinear = |a: Point, b: Point, c: Point| -> bool { ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)).abs() < MAX_ABSOLUTE_DIFFERENCE };
+
+	match *segment {
+		PathSeg::Line(_) => true,
+		PathSeg::Quad(QuadBez { p0, p1, p2 }) => is_colinear(p0, p1, p2),
+		PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => is_colinear(p0, p1, p3) && is_colinear(p0, p2, p3),
+	}
+}
diff --git a/node-graph/gcore/src/vector/misc.rs b/node-graph/gcore/src/vector/misc.rs
index 8e275c97df..cdf3a56069 100644
--- a/node-graph/gcore/src/vector/misc.rs
+++ b/node-graph/gcore/src/vector/misc.rs
@@ -1,6 +1,7 @@
+use bezier_rs::BezierHandles;
 use dyn_any::DynAny;
 use glam::DVec2;
-use kurbo::Point;
+use kurbo::{CubicBez, Line, PathSeg, Point, QuadBez};
 
 /// Represents different ways of calculating the centroid.
 #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash, DynAny, specta::Type, node_macro::ChoiceType)]
@@ -101,3 +102,33 @@ pub fn point_to_dvec2(point: Point) -> DVec2 {
 pub fn dvec2_to_point(value: DVec2) -> Point {
 	Point { x: value.x, y: value.y }
 }
+
+pub fn segment_to_handles(segment: &PathSeg) -> BezierHandles {
+	match *segment {
+		PathSeg::Line(_) => BezierHandles::Linear,
+		PathSeg::Quad(QuadBez { p0: _, p1, p2: _ }) => BezierHandles::Quadratic { handle: point_to_dvec2(p1) },
+		PathSeg::Cubic(CubicBez { p0: _, p1, p2, p3: _ }) => BezierHandles::Cubic {
+			handle_start: point_to_dvec2(p1),
+			handle_end: point_to_dvec2(p2),
+		},
+	}
+}
+
+pub fn handles_to_segment(start: DVec2, handles: BezierHandles, end: DVec2) -> PathSeg {
+	match handles {
+		bezier_rs::BezierHandles::Linear => PathSeg::Line(Line::new(dvec2_to_point(start), dvec2_to_point(end))),
+		bezier_rs::BezierHandles::Quadratic { handle } => {
+			let p0 = dvec2_to_point(start);
+			let p1 = dvec2_to_point(handle);
+			let p2 = dvec2_to_point(end);
+			PathSeg::Quad(QuadBez::new(p0, p1, p2))
+		}
+		bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => {
+			let p0 = dvec2_to_point(start);
+			let p1 = dvec2_to_point(handle_start);
+			let p2 = dvec2_to_point(handle_end);
+			let p3 = dvec2_to_point(end);
+			PathSeg::Cubic(CubicBez::new(p0, p1, p2, p3))
+		}
+	}
+}
diff --git a/node-graph/gcore/src/vector/vector_data.rs b/node-graph/gcore/src/vector/vector_data.rs
index 480ae8f787..b679d7a96c 100644
--- a/node-graph/gcore/src/vector/vector_data.rs
+++ b/node-graph/gcore/src/vector/vector_data.rs
@@ -196,10 +196,10 @@ impl VectorData {
 
 	pub fn close_subpaths(&mut self) {
 		let segments_to_add: Vec<_> = self
-			.stroke_bezier_paths()
-			.filter(|subpath| !subpath.closed)
-			.filter_map(|subpath| {
-				let (first, last) = subpath.manipulator_groups().first().zip(subpath.manipulator_groups().last())?;
+			.build_stroke_path_iter()
+			.filter(|(_, closed)| !closed)
+			.filter_map(|(manipulator_groups, _)| {
+				let (first, last) = manipulator_groups.first().zip(manipulator_groups.last())?;
 				let (start, end) = self.point_domain.resolve_id(first.id).zip(self.point_domain.resolve_id(last.id))?;
 				Some((start, end))
 			})
@@ -335,7 +335,7 @@ impl VectorData {
 	}
 
 	pub fn check_point_inside_shape(&self, vector_data_transform: DAffine2, point: DVec2) -> bool {
-		let bez_paths: Vec<_> = self
+		let number = self
 			.stroke_bezpath_iter()
 			.map(|mut bezpath| {
 				// TODO: apply transform to points instead of modifying the paths
@@ -344,19 +344,9 @@ impl VectorData {
 				let bbox = bezpath.bounding_box();
 				(bezpath, bbox)
 			})
-			.collect();
-
-		// Check against all paths the point is contained in to compute the correct winding number
-		let mut number = 0;
-
-		for (shape, bbox) in bez_paths {
-			if bbox.x0 > point.x || bbox.y0 > point.y || bbox.x1 < point.x || bbox.y1 < point.y {
-				continue;
-			}
-
-			let winding = shape.winding(dvec2_to_point(point));
-			number += winding;
-		}
+			.filter(|(_, bbox)| bbox.contains(dvec2_to_point(point)))
+			.map(|(bezpath, _)| bezpath.winding(dvec2_to_point(point)))
+			.sum::<i32>();
 
 		// Non-zero fill rule
 		number != 0
diff --git a/node-graph/gcore/src/vector/vector_data/attributes.rs b/node-graph/gcore/src/vector/vector_data/attributes.rs
index d5e1fe0241..2129fa928a 100644
--- a/node-graph/gcore/src/vector/vector_data/attributes.rs
+++ b/node-graph/gcore/src/vector/vector_data/attributes.rs
@@ -849,7 +849,7 @@ impl VectorData {
 			})
 	}
 
-	fn build_stroke_path_iter(&self) -> StrokePathIter {
+	pub fn build_stroke_path_iter(&self) -> StrokePathIter {
 		let mut points = vec![StrokePathIterPointMetadata::default(); self.point_domain.ids().len()];
 		for (segment_index, (&start, &end)) in self.segment_domain.start_point.iter().zip(&self.segment_domain.end_point).enumerate() {
 			points[start].set(StrokePathIterPointSegmentMetadata::new(segment_index, false));
diff --git a/node-graph/gcore/src/vector/vector_nodes.rs b/node-graph/gcore/src/vector/vector_nodes.rs
index df7da779ea..be55b1e40d 100644
--- a/node-graph/gcore/src/vector/vector_nodes.rs
+++ b/node-graph/gcore/src/vector/vector_nodes.rs
@@ -9,14 +9,15 @@ use crate::registry::types::{Angle, Fraction, IntegerCount, Length, Multiplier,
 use crate::renderer::GraphicElementRendered;
 use crate::transform::{Footprint, ReferencePoint, Transform};
 use crate::vector::PointDomain;
-use crate::vector::misc::dvec2_to_point;
+use crate::vector::algorithms::bezpath_algorithms::{eval_pathseg_euclidean, is_linear};
+use crate::vector::misc::{dvec2_to_point, handles_to_segment, segment_to_handles};
 use crate::vector::style::{LineCap, LineJoin};
 use crate::{CloneVarArgs, Color, Context, Ctx, ExtractAll, GraphicElement, GraphicGroupTable, OwnedContextImpl};
-use bezier_rs::{Join, ManipulatorGroup, Subpath, SubpathTValue};
+use bezier_rs::{BezierHandles, Join, ManipulatorGroup, Subpath, SubpathTValue};
 use core::f64::consts::PI;
 use core::hash::{Hash, Hasher};
 use glam::{DAffine2, DVec2};
-use kurbo::{Affine, BezPath, Shape};
+use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, ParamCurve, PathSeg, Shape};
 use rand::{Rng, SeedableRng};
 use std::collections::hash_map::DefaultHasher;
 
@@ -1611,10 +1612,9 @@ async fn morph(_: impl Ctx, source: VectorDataTable, #[expose] target: VectorDat
 
 fn bevel_algorithm(mut vector_data: VectorData, vector_data_transform: DAffine2, distance: f64) -> VectorData {
 	// Splits a bézier curve based on a distance measurement
-	fn split_distance(bezier: bezier_rs::Bezier, distance: f64, length: f64) -> bezier_rs::Bezier {
-		const EUCLIDEAN_ERROR: f64 = 0.001;
-		let parametric = bezier.euclidean_to_parametric_with_total_length((distance / length).clamp(0., 1.), EUCLIDEAN_ERROR, length);
-		bezier.split(bezier_rs::TValue::Parametric(parametric))[1]
+	fn split_distance(bezier: PathSeg, distance: f64, length: f64) -> PathSeg {
+		let parametric = eval_pathseg_euclidean(bezier, (distance / length).clamp(0., 1.), DEFAULT_ACCURACY);
+		bezier.subsegment(parametric..1.)
 	}
 
 	/// Produces a list that corresponds with the point ID. The value is how many segments are connected.
@@ -1653,65 +1653,248 @@ fn bevel_algorithm(mut vector_data: VectorData, vector_data_transform: DAffine2,
 		}
 	}
 
+	fn calculate_distance_to_spilt(bezier1: PathSeg, bezier2: PathSeg, bevel_length: f64) -> f64 {
+		if is_linear(&bezier1) && is_linear(&bezier2) {
+			let v1 = (bezier1.end() - bezier1.start()).normalize();
+			let v2 = (bezier1.end() - bezier2.end()).normalize();
+
+			let dot_product = v1.dot(v2);
+
+			let angle_rad = dot_product.acos();
+
+			bevel_length / ((angle_rad / 2.0).sin())
+		} else {
+			let length1 = bezier1.perimeter(DEFAULT_ACCURACY);
+			let length2 = bezier2.perimeter(DEFAULT_ACCURACY);
+
+			let max_split = length1.min(length2);
+
+			let mut split_distance = 0.0;
+			let mut best_diff = f64::MAX;
+			let mut current_best_distance = 0.0;
+
+			let clamp_and_round = |value: f64| ((value * 1000.0).round() / 1000.0).clamp(0.0, 1.0);
+
+			const INITIAL_SAMPLES: usize = 50;
+			for i in 0..=INITIAL_SAMPLES {
+				let distance_sample = max_split * (i as f64 / INITIAL_SAMPLES as f64);
+
+				let x_point_t = eval_pathseg_euclidean(bezier1, 1.0 - clamp_and_round(distance_sample / length1), DEFAULT_ACCURACY);
+				let y_point_t = eval_pathseg_euclidean(bezier2, clamp_and_round(distance_sample / length2), DEFAULT_ACCURACY);
+
+				let x_point = bezier1.eval(x_point_t);
+				let y_point = bezier2.eval(y_point_t);
+
+				let distance = x_point.distance(y_point);
+				let diff = (bevel_length - distance).abs();
+
+				if diff < best_diff {
+					best_diff = diff;
+					current_best_distance = distance_sample;
+				}
+
+				if bevel_length - distance < 0.0 {
+					split_distance = distance_sample;
+
+					if i > 0 {
+						let prev_sample = max_split * ((i - 1) as f64 / INITIAL_SAMPLES as f64);
+
+						const REFINE_STEPS: usize = 10;
+						for j in 1..=REFINE_STEPS {
+							let refined_sample = prev_sample + (distance_sample - prev_sample) * (j as f64 / REFINE_STEPS as f64);
+
+							let x_point_t = eval_pathseg_euclidean(bezier1, 1.0 - (refined_sample / length1).clamp(0.0, 1.0), DEFAULT_ACCURACY);
+							let y_point_t = eval_pathseg_euclidean(bezier2, (refined_sample / length2).clamp(0.0, 1.0), DEFAULT_ACCURACY);
+
+							let x_point = bezier1.eval(x_point_t);
+							let y_point = bezier2.eval(y_point_t);
+
+							let distance = x_point.distance(y_point);
+
+							if bevel_length - distance < 0.0 {
+								split_distance = refined_sample;
+								break;
+							}
+						}
+					}
+					break;
+				}
+			}
+
+			if split_distance == 0.0 && current_best_distance > 0.0 {
+				split_distance = current_best_distance;
+			}
+
+			split_distance
+		}
+	}
+
 	fn update_existing_segments(vector_data: &mut VectorData, vector_data_transform: DAffine2, distance: f64, segments_connected: &mut [usize]) -> Vec<[usize; 2]> {
 		let mut next_id = vector_data.point_domain.next_id();
 		let mut new_segments = Vec::new();
 
-		for (handles, start_point_index, end_point_index) in vector_data.segment_domain.handles_and_points_mut() {
-			// Convert the original segment to a bezier
-			let mut bezier = bezier_rs::Bezier {
-				start: vector_data.point_domain.positions()[*start_point_index],
-				end: vector_data.point_domain.positions()[*end_point_index],
-				handles: *handles,
-			};
+		let mut first_bezier_bool = true;
+
+		let mut iter = vector_data.segment_domain.handles_and_points_mut();
+
+		let mut first_bezier = handles_to_segment(DVec2::ZERO, BezierHandles::Linear, DVec2::ZERO);
+
+		let mut first_start_point_index = &mut 0xffffffff;
+		let mut first_handles = &mut bezier_rs::BezierHandles::Linear;
+
+		let Some((handles, start_point_index, end_point_index)) = iter.next() else { unreachable!() };
+
+		let start = vector_data.point_domain.positions()[*start_point_index];
+		let end = vector_data.point_domain.positions()[*end_point_index];
+
+		let mut prev_bezier = handles_to_segment(start, *handles, end);
+
+		prev_bezier = Affine::new(vector_data_transform.to_cols_array()) * prev_bezier;
 
-			if bezier.is_linear() {
-				bezier.handles = bezier_rs::BezierHandles::Linear;
+		let mut prev_handles = handles;
+		let mut prev_start_point_index = start_point_index;
+		let mut prev_end_point_index = end_point_index;
+		let mut prev_original_length = prev_bezier.perimeter(DEFAULT_ACCURACY);
+		let mut prev_length = prev_original_length;
+		let mut first_original_length = prev_original_length;
+		let mut first_length = prev_original_length;
+
+		while let Some((handles, start_point_index, end_point_index)) = iter.next() {
+			let start = vector_data.point_domain.positions()[*start_point_index];
+			let end = vector_data.point_domain.positions()[*end_point_index];
+			let mut bezier = handles_to_segment(start, *handles, end);
+
+			bezier = Affine::new(vector_data_transform.to_cols_array()) * bezier;
+
+			let spilt_distance = calculate_distance_to_spilt(prev_bezier, bezier, distance);
+
+			if is_linear(&prev_bezier) {
+				let start = point_to_dvec2(prev_bezier.start());
+				let end = point_to_dvec2(prev_bezier.end());
+				prev_bezier = handles_to_segment(start, BezierHandles::Linear, end);
+			}
+
+			if is_linear(&bezier) {
+				let start = point_to_dvec2(bezier.start());
+				let end = point_to_dvec2(bezier.end());
+				bezier = handles_to_segment(start, BezierHandles::Linear, end);
 			}
-			bezier = bezier.apply_transformation(|p| vector_data_transform.transform_point2(p));
+
 			let inverse_transform = (vector_data_transform.matrix2.determinant() != 0.).then(|| vector_data_transform.inverse()).unwrap_or_default();
 
-			let original_length = bezier.length(None);
+			let original_length = bezier.perimeter(DEFAULT_ACCURACY);
 			let mut length = original_length;
 
+			// Only split if the length is big enough to make it worthwhile
+			let valid_length = prev_length > 1e-10;
+			if segments_connected[*prev_end_point_index] > 0 && valid_length {
+				// Apply the bevel to the end
+				let distance = spilt_distance.min(prev_original_length.min(original_length) / 2.);
+				prev_bezier = split_distance(prev_bezier.reverse(), distance, prev_length).reverse();
+				if first_bezier_bool {
+					first_length = (first_length - distance).max(0.);
+				}
+				// Update the end position
+				let pos = inverse_transform.transform_point2(point_to_dvec2(prev_bezier.end()));
+				create_or_modify_point(&mut vector_data.point_domain, segments_connected, pos, prev_end_point_index, &mut next_id, &mut new_segments);
+			}
+			// Update the handles
+			*prev_handles = segment_to_handles(&prev_bezier).apply_transformation(|p| inverse_transform.transform_point2(p));
+
 			// Only split if the length is big enough to make it worthwhile
 			let valid_length = length > 1e-10;
 			if segments_connected[*start_point_index] > 0 && valid_length {
 				// Apply the bevel to the start
-				let distance = distance.min(original_length / 2.);
+				let distance = spilt_distance.min(original_length.min(prev_original_length) / 2.);
 				bezier = split_distance(bezier, distance, length);
 				length = (length - distance).max(0.);
 				// Update the start position
-				let pos = inverse_transform.transform_point2(bezier.start);
+				let pos = inverse_transform.transform_point2(point_to_dvec2(bezier.start()));
+
 				create_or_modify_point(&mut vector_data.point_domain, segments_connected, pos, start_point_index, &mut next_id, &mut new_segments);
+
+				// Update the handles
+				*handles = segment_to_handles(&bezier).apply_transformation(|p| inverse_transform.transform_point2(p));
+			}
+
+			if first_bezier_bool {
+				first_bezier = prev_bezier;
+				first_start_point_index = prev_start_point_index;
+				first_handles = prev_handles;
+				first_original_length = prev_original_length;
+				first_bezier_bool = false;
+			}
+
+			prev_bezier = bezier;
+			prev_start_point_index = start_point_index;
+			prev_end_point_index = end_point_index;
+			prev_handles = handles;
+			prev_original_length = original_length;
+			prev_length = length;
+		}
+
+		if prev_end_point_index == first_start_point_index {
+			let spilt_distance = calculate_distance_to_spilt(prev_bezier, first_bezier, distance);
+
+			if is_linear(&prev_bezier) {
+				let start = point_to_dvec2(prev_bezier.start());
+				let end = point_to_dvec2(prev_bezier.end());
+				prev_bezier = handles_to_segment(start, BezierHandles::Linear, end);
+			}
+
+			if is_linear(&first_bezier) {
+				let start = point_to_dvec2(first_bezier.start());
+				let end = point_to_dvec2(first_bezier.end());
+				first_bezier = handles_to_segment(start, BezierHandles::Linear, end);
 			}
 
+			let inverse_transform = (vector_data_transform.matrix2.determinant() != 0.).then(|| vector_data_transform.inverse()).unwrap_or_default();
+
 			// Only split if the length is big enough to make it worthwhile
-			let valid_length = length > 1e-10;
-			if segments_connected[*end_point_index] > 0 && valid_length {
+			let valid_length = prev_length > 1e-10;
+			if segments_connected[*prev_end_point_index] > 0 && valid_length {
 				// Apply the bevel to the end
-				let distance = distance.min(original_length / 2.);
-				bezier = split_distance(bezier.reversed(), distance, length).reversed();
+				let distance = spilt_distance.min(prev_original_length.min(first_original_length) / 2.);
+				prev_bezier = split_distance(prev_bezier.reverse(), distance, prev_length).reverse();
 				// Update the end position
-				let pos = inverse_transform.transform_point2(bezier.end);
-				create_or_modify_point(&mut vector_data.point_domain, segments_connected, pos, end_point_index, &mut next_id, &mut new_segments);
+				let pos = inverse_transform.transform_point2(point_to_dvec2(prev_bezier.end()));
+				create_or_modify_point(&mut vector_data.point_domain, segments_connected, pos, prev_end_point_index, &mut next_id, &mut new_segments);
 			}
 			// Update the handles
-			*handles = bezier.handles.apply_transformation(|p| inverse_transform.transform_point2(p));
+			*prev_handles = segment_to_handles(&prev_bezier).apply_transformation(|p| inverse_transform.transform_point2(p));
+
+			// Only split if the length is big enough to make it worthwhile
+			let valid_length = first_length > 1e-10;
+			if segments_connected[*first_start_point_index] > 0 && valid_length {
+				// Apply the bevel to the start
+				let distance = spilt_distance.min(first_original_length.min(prev_original_length) / 2.);
+				first_bezier = split_distance(first_bezier, distance, first_length);
+				// Update the start position
+				let pos = inverse_transform.transform_point2(point_to_dvec2(first_bezier.start()));
+
+				create_or_modify_point(&mut vector_data.point_domain, segments_connected, pos, first_start_point_index, &mut next_id, &mut new_segments);
+
+				// Update the handles
+				*first_handles = segment_to_handles(&first_bezier).apply_transformation(|p| inverse_transform.transform_point2(p));
+			}
 		}
 		new_segments
 	}
 
 	fn insert_new_segments(vector_data: &mut VectorData, new_segments: &[[usize; 2]]) {
 		let mut next_id = vector_data.segment_domain.next_id();
+
 		for &[start, end] in new_segments {
-			vector_data.segment_domain.push(next_id.next_id(), start, end, bezier_rs::BezierHandles::Linear, StrokeId::ZERO);
+			let handles = bezier_rs::BezierHandles::Linear;
+			vector_data.segment_domain.push(next_id.next_id(), start, end, handles, StrokeId::ZERO);
 		}
 	}
 
-	let mut segments_connected = segments_connected_count(&vector_data);
-	let new_segments = update_existing_segments(&mut vector_data, vector_data_transform, distance, &mut segments_connected);
-	insert_new_segments(&mut vector_data, &new_segments);
+	if distance > 1.0 {
+		let mut segments_connected = segments_connected_count(&vector_data);
+		let new_segments = update_existing_segments(&mut vector_data, vector_data_transform, distance, &mut segments_connected);
+		insert_new_segments(&mut vector_data, &new_segments);
+	}
 
 	vector_data
 }
@@ -1723,7 +1906,7 @@ fn bevel(_: impl Ctx, source: VectorDataTable, #[default(10.)] distance: Length)
 	for source_instance in source.instance_iter() {
 		result_table.push(Instance {
 			instance: bevel_algorithm(source_instance.instance, source_instance.transform, distance),
-			..Default::default()
+			..source_instance
 		});
 	}
 
@@ -1768,7 +1951,7 @@ async fn area(ctx: impl Ctx + CloneVarArgs + ExtractAll, vector_data: impl Node<
 		.instance_ref_iter()
 		.map(|vector_data_instance| {
 			let scale = vector_data_instance.transform.decompose_scale();
-			vector_data_instance.instance.stroke_bezier_paths().map(|subpath| subpath.area(Some(1e-3), Some(1e-3))).sum::<f64>() * scale.x * scale.y
+			vector_data_instance.instance.stroke_bezpath_iter().map(|subpath| subpath.area() * scale.x * scale.y).sum::<f64>()
 		})
 		.sum()
 }