### Construct Polyline View from New Start Point Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Creates a polyline view starting from a specified point on a source polyline. Handles cases where the start point is exactly at a vertex or on a segment. Panics if the source has fewer than 2 vertices or the start index is out of range. ```rust pub fn from_new_start(source: &P, start_point: Vector2, start_index: usize, pos_equal_eps: T) -> Option where P: PlineSource + ?Sized { // check if open polyline then just delegate to slice points method if !source.is_closed() { return Self::from_slice_points( source, start_point, start_index, source.last()?.pos(), source.vertex_count() - 1, pos_equal_eps, ); } let vc = source.vertex_count(); assert!( vc >= 2, "source must have at least 2 vertexes to form view data" ); // catch where start point is at very end of start index segment (and adjust forward) let start_index = { let next_index = source.next_wrapping_index(start_index); if source .at(next_index) .pos() .fuzzy_eq_eps(start_point, pos_equal_eps) { next_index } else { start_index } }; let start_v1 = source.at(start_index); let start_v2 = source.at(source.next_wrapping_index(start_index)); let split = seg_split_at_point(start_v1, start_v2, start_point, pos_equal_eps); let (end_index_offset, updated_end_bulge) = if start_v1.pos().fuzzy_eq_eps(start_point, pos_equal_eps) { // start point on top of vertex, adjust index offset and do not use split bulge ( vc - 1, source.at(source.prev_wrapping_index(start_index)).bulge, ) } else { (vc, split.updated_start.bulge) }; let view_data = Self { start_index, end_index_offset, updated_start: split.split_vertex, updated_end_bulge, end_point: start_point, inverted_direction: false, }; debug_assert_eq!( view_data.validate_for_source(source), ViewDataValidation::IsValid ); Some(view_data) } ``` -------------------------------- ### Set Vertex Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/trait.PlineSourceMut.html Demonstrates updating a specific vertex in a polyline. ```rust let mut polyline = Polyline::new(); polyline.add(0.0, 0.0, 0.0); polyline.set_vertex(0, PlineVertex::new(1.0, 1.0, 1.0)); assert!(polyline.at(0).fuzzy_eq(PlineVertex::new(1.0, 1.0, 1.0))); ``` -------------------------------- ### Vector2 Usage Examples Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/core/math/vector2.rs.html Demonstrates creating vectors and performing basic mathematical operations. ```rust # use cavalier_contours::core::math::{Vector2, vec2}; let v1 = Vector2::new(3.0, 4.0); let v2 = vec2(1.0, 2.0); // shorthand constructor // Vector operations let sum = v1 + v2; let dot_product = v1.dot(v2); let length = v1.length(); let normalized = v1.normalize(); ``` -------------------------------- ### Clear Polyline Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/trait.PlineSourceMut.html Demonstrates removing all vertices from a polyline. ```rust let mut polyline = Polyline::new(); polyline.add(0.0, 0.0, 0.0); assert_eq!(polyline.vertex_count(), 1); polyline.clear(); assert_eq!(polyline.vertex_count(), 0); ``` -------------------------------- ### from_new_start Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Constructs a view of a polyline starting from a specific point and index, handling both open and closed polylines. ```APIDOC ## from_new_start ### Description Constructs a view of a polyline starting from a specific point and index. If the polyline is closed, it calculates the view data based on the provided start point and index, adjusting for vertex positions. ### Parameters #### Path Parameters - **source** (P) - Required - The source polyline implementation. - **start_point** (Vector2) - Required - The starting coordinate. - **start_index** (usize) - Required - The index to begin from. - **pos_equal_eps** (T) - Required - Epsilon value for fuzzy equality checks. ### Response - **Option** - Returns the constructed view data or None if construction fails. ``` -------------------------------- ### Splitting an Arc Segment Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/fn.seg_split_at_point.html Example demonstrating how to split an arc segment at a specific point. ```rust // arc half circle arc segment going from (0, 0) to (1, 0) counter clockwise let v1 = PlineVertex::new(0.0, 0.0, 1.0); let v2 = PlineVertex::new(1.0, 0.0, 0.0); let point = Vector2::new(0.5, -0.5); let SplitResult { updated_start, split_vertex } = seg_split_at_point(v1, v2, point, 1e-5); let quarter_circle_bulge = (std::f64::consts::PI / 8.0).tan(); assert!(updated_start.fuzzy_eq(PlineVertex::new(v1.x, v1.y, quarter_circle_bulge))); assert!(split_vertex.fuzzy_eq(PlineVertex::new(point.x, point.y, quarter_circle_bulge))); ``` -------------------------------- ### Construct an open polyline Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/macro.pline_open.html Usage example for creating an open polyline with specific vertexes. ```rust let polyline = pline_open![(0.0, 1.0, 1.0), (2.0, 0.0, 0.0)]; assert!(!polyline.is_closed()); assert_eq!(polyline[0], PlineVertex::new(0.0, 1.0, 1.0)); assert_eq!(polyline[1], PlineVertex::new(2.0, 0.0, 0.0)); ``` -------------------------------- ### min_max Usage Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.min_max.html Demonstrates how to use min_max to retrieve the minimum and maximum values from two integers. ```rust let (min_val, max_val) = min_max(8, 4); assert_eq!(min_val, 4); assert_eq!(max_val, 8); ``` -------------------------------- ### Set Closed State Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/trait.PlineSourceMut.html Demonstrates toggling the closed state of a polyline. ```rust let mut polyline: Polyline = Polyline::new(); assert!(!polyline.is_closed()); polyline.set_is_closed(true); assert!(polyline.is_closed()); ``` -------------------------------- ### Construct Polyline View from Slice Points Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Creates a polyline view between two specified points on a source polyline, trimming the start and end of the source polyline. Handles cases where the start point is at the end of the first segment. Panics if the source has fewer than 2 vertices or indexes are out of range. ```rust pub fn from_slice_points(source: &P, start_point: Vector2, start_index: usize, end_point: Vector2, end_index: usize, pos_equal_eps: T) -> Option where P: PlineSource + ?Sized { debug_assert!( start_index <= end_index || source.is_closed(), "start index should be less than or equal to end index if polyline is open" ); // catch if start_point is at end of first segment let (start_index, start_point_at_seg_end) = { if !source.is_closed() && start_index >= end_index { // not possible to wrap index forward (start_index, false) } else { let next_index = source.next_wrapping_index(start_index); if source .at(next_index) .pos() .fuzzy_eq_eps(start_point, pos_equal_eps) { (next_index, true) } else { (start_index, false) } } }; let traverse_count = { let index_dist = source.fwd_wrapping_dist(start_index, end_index); if index_dist == 0 && source.is_closed() && !start_point.fuzzy_eq_eps(end_point, pos_equal_eps) { let seg_start = source.at(start_index).pos(); let dist1 = dist_squared(seg_start, start_point); let dist2 = dist_squared(seg_start, end_point); if dist1 < dist2 { // not wrapping around polyline, on same segment 0 } else { // wrapping around polyline back to same segment // This part of the code is incomplete in the provided text. // The original code likely continues here to determine traverse_count. } } else { index_dist } }; // The rest of the function is not provided in the input text. // It would typically involve calculating segment splits and constructing the view data. unimplemented!("Polyline construction logic missing"); } ``` -------------------------------- ### Example: Creating view over polyline from slice points Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/struct.PlineViewData.html Demonstrates how to create a PlineViewData from slice points and then construct a PlineView to perform operations on the selected portion of the polyline. ```APIDOC ### §Creating view over polyline from slice points ```rust let mut polyline = Polyline::new_closed(); polyline.add(0.0, 0.0, 0.0); polyline.add(5.0, 0.0, 0.0); polyline.add(5.0, 5.0, 0.0); polyline.add(0.0, 5.0, 0.0); // construction view data from slice points, view data represents a slice of the source polyline // starting at (2.5, 0.0) on the first segment (index 0) and ending at (2.5, 5.0) on the third // segment (index 2) let view_data = PlineViewData::from_slice_points( // source polyline &polyline, // start point Vector2::new(2.5, 0.0), // segment index start point lies on 0, // end point Vector2::new(2.5, 5.0), // segment index end point lies on 2, // position equal epsilon 1e-5).expect("slice not collapsed"); // construct the view (which implements polyline traits) from the view data and source let view = view_data.view(&polyline); // we can now use common trait methods on the slice // note we never had to copy the source polyline let slice_length = view.path_length(); assert_fuzzy_eq!(view.path_length(), 10.0); let slice_vertex_count = view.vertex_count(); assert_eq!(slice_vertex_count, 4); let slice_extents = view.extents().unwrap(); assert_fuzzy_eq!(slice_extents.min_x, 2.5); assert_fuzzy_eq!(slice_extents.min_y, 0.0); assert_fuzzy_eq!(slice_extents.max_x, 5.0); assert_fuzzy_eq!(slice_extents.max_y, 5.0); ``` ``` -------------------------------- ### Calculate midpoint of polyline segments Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/fn.seg_midpoint.html Examples demonstrating midpoint calculation for arc and line segments. ```rust // counter clockwise half circle arc going from (2, 2) to (2, 4) let v1 = PlineVertex::new(2.0, 2.0, 1.0); let v2 = PlineVertex::new(4.0, 2.0, 0.0); assert!(seg_midpoint(v1, v2).fuzzy_eq(Vector2::new(3.0, 1.0))); ``` ```rust // line segment going from (2, 2) to (4, 4) let v1 = PlineVertex::new(2.0, 2.0, 0.0); let v2 = PlineVertex::new(4.0, 4.0, 0.0); assert!(seg_midpoint(v1, v2).fuzzy_eq(Vector2::new(3.0, 3.0))); ``` -------------------------------- ### Example Usage of pline_open_userdata Macro Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/macro.pline_open_userdata.html Demonstrates how to use the `pline_open_userdata` macro to create an open polyline and assert its properties. Requires `PlineVertex` and related methods. ```rust let polyline = pline_open_userdata![vec![4, 117], (0.0, 1.0, 1.0), (2.0, 0.0, 0.0)]; assert!(!polyline.is_closed()); assert_eq!(polyline[0], PlineVertex::new(0.0, 1.0, 1.0)); assert_eq!(polyline[1], PlineVertex::new(2.0, 0.0, 0.0)); assert_eq!(polyline.get_userdata_count(), 2); assert!(polyline.get_userdata_values().any(|x| x == 4)); assert!(polyline.get_userdata_values().any(|x| x == 117)); ``` -------------------------------- ### Example: Approximate Half Circle to Lines Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/traits.rs.html Demonstrates converting a polyline with a half-circle arc into a series of line segments using `arcs_to_approx_lines` with a specified error distance. ```rust let mut polyline = Polyline::new(); // half circle polyline.add(0.0, 0.0, 1.0); polyline.add(2.0, 0.0, 0.0); let lines = polyline.arcs_to_approx_lines(0.1).unwrap(); assert!(lines.vertex_count() > 2); assert!(lines.iter_vertexes().all(|v| v.bulge == 0.0)); ``` -------------------------------- ### Example Usage of pline_closed_userdata Macro Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/macro.pline_closed_userdata.html Demonstrates constructing a closed polyline using the `pline_closed_userdata` macro and asserts its properties. ```rust let polyline = pline_closed_userdata![vec![4, 117], (0.0, 1.0, 1.0), (2.0, 0.0, 0.0)]; assert!(polyline.is_closed()); assert_eq!(polyline[0], PlineVertex::new(0.0, 1.0, 1.0)); assert_eq!(polyline[1], PlineVertex::new(2.0, 0.0, 0.0)); assert_eq!(polyline.get_userdata_count(), 2); assert!(polyline.get_userdata_values().any(|x| x == 4)); assert!(polyline.get_userdata_values().any(|x| x == 117)); ``` -------------------------------- ### Perform Vector Operations Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/struct.Vector2.html Examples of creating vectors and performing common mathematical operations like addition, dot product, and normalization. ```rust let v1 = Vector2::new(3.0, 4.0); let v2 = vec2(1.0, 2.0); // shorthand constructor // Vector operations let sum = v1 + v2; let dot_product = v1.dot(v2); let length = v1.length(); let normalized = v1.normalize(); ``` -------------------------------- ### Example: Tangent-Intersecting Circles Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.circle_circle_intr.html Demonstrates finding a tangent intersection between two circles. Ensure the circles are positioned and sized to result in a single intersection point. ```rust let r1 = 1.0; let c1 = Vector2::new(0.0, 0.0); let r2 = 1.0; let c2 = Vector2::new(0.0, 2.0); if let CircleCircleIntr::TangentIntersect { point: p } = circle_circle_intr(r1, c1, r2, c2, 1e-5) { assert_eq!(p, Vector2::new(0.0, 1.0)); } else { unreachable!("expected a tangent intersection"); } ``` -------------------------------- ### Example of tangent-intersecting line segment Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.line_circle_intr.html Demonstrates finding a tangent intersection where the line segment touches the circle at an endpoint. ```rust // A line segment tangent-intersecting a circle with one of the line segments end points. let p0 = Vector2::new(0.0, 0.0); let p1 = Vector2::new(1.0, 0.0); let r = 1.0; let c = Vector2::new(0.0, 1.0); if let LineCircleIntr::TangentIntersect{ t0: t } = line_circle_intr(p0, p1, r, c, 1e-5) { assert_eq!(t, 0.0); } else { unreachable!("expected tangent intersect"); } ``` -------------------------------- ### Example: Tangent Intersection Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/core/math/line_line_intersect.rs.html Demonstrates a line segment intersecting a circle tangentially at one of its endpoints. Asserts the parametric values for the intersection. ```rust # use cavalier_contours::core::traits::*; # use cavalier_contours::core::math::*; # use cavalier_contours::core::math::LineLineIntr::TrueIntersect; // A line segment tangent-intersecting a circle with one of the line segments end points. let v1 = Vector2::new(0.0, 0.0); let v2 = Vector2::new(1.0, 0.0); let u1 = Vector2::new(0.5, -1.0); let u2 = Vector2::new(0.5, 1.0); if let LineLineIntr::TrueIntersect { seg1_t: t1, seg2_t: t2, } = line_line_intr(v1, v2, u1, u2, 1e-5) { assert_eq!(t1, 0.5); assert_eq!(t2, 0.5); } else { unreachable!("expected true intersection between line segments"); } ``` -------------------------------- ### Fuzzy Equality Comparison Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/traits/trait.FuzzyEq.html Demonstrates using fuzzy_eq to compare floating point values that would otherwise fail a direct equality check. ```rust let a = 0.1 + 0.2; let b = 0.3; // Direct comparison would fail due to floating point precision assert_ne!(a, b); // Fuzzy comparison succeeds assert!(a.fuzzy_eq(b)); ``` -------------------------------- ### Calculate Midpoint of Line Segment Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_seg.rs.html This example demonstrates calculating the midpoint of a straight line segment. It requires `PlineVertex` and `Vector2` types. ```rust # use cavalier_contours::polyline::* # use cavalier_contours::core::math::* // line segment going from (2, 2) to (4, 4) let v1 = PlineVertex::new(2.0, 2.0, 0.0); let v2 = PlineVertex::new(4.0, 4.0, 0.0); assert!(seg_midpoint(v1, v2).fuzzy_eq(Vector2::new(3.0, 3.0))); ``` -------------------------------- ### Get Vertex with Normal Direction Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Retrieves a vertex from the source polyline in the normal (non-inverted) direction. Handles the start vertex, intermediate vertices, the end segment vertex, and the final endpoint. ```rust if index == 0 { return Some(self.updated_start); } if index < self.end_index_offset { let i = source.fwd_wrapping_index(self.start_index, index); return Some(source.at(i)); } if index == self.end_index_offset { let i = source.fwd_wrapping_index(self.start_index, self.end_index_offset); let v = source.at(i); return Some(v.with_bulge(self.updated_end_bulge)); } if index == self.end_index_offset + 1 { return Some(PlineVertex::from_vector2(self.end_point, T::zero())); } ``` -------------------------------- ### Compute Updated Start Vertex Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Calculates the updated start vertex for a polyline segment, considering start and end points, and whether the start point is at a segment end. This logic is used when the start and end points are on the same segment or different segments. ```rust // compute updated start vertex let updated_start = { let start_v1 = source.at(start_index); let start_v2 = source.at(source.next_wrapping_index(start_index)); if start_point_at_seg_end { // start point on top of vertex no need to split using start_point if traverse_count == 0 { // start and end point on same segment, split at end point let split = seg_split_at_point(start_v1, start_v2, end_point, pos_equal_eps); split.updated_start } else { start_v1 } } else { // split at start point let start_split = seg_split_at_point(start_v1, start_v2, start_point, pos_equal_eps); let updated_for_start = start_split.split_vertex; if traverse_count == 0 { // start and end point on same segment, split at end point let split = seg_split_at_point(updated_for_start, start_v2, end_point, pos_equal_eps); split.updated_start } else { updated_for_start } } }; ``` -------------------------------- ### Validate Updated Bulge Matches Start Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Checks if the updated bulge value matches the expected value from the start index segment. This is used when the end point is on the start index segment. ```rust if self.end_index_offset == 0 { // end point on start index segment, check that updated bulge matches updated start // bulge if !self .updated_end_bulge .fuzzy_eq_eps(self.updated_start.bulge, validation_eps) { return ViewDataValidation::UpdatedBulgeDoesNotMatch { updated_bulge: self.updated_end_bulge, expected: self.updated_start.bulge, }; } } ViewDataValidation::IsValid ``` -------------------------------- ### Rotate Polyline Start Point Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/trait.PlineSource.html Rotates the vertices of a closed polyline so that a specified point becomes the new start vertex. Ensure the polyline is closed and has sufficient length for rotation. ```rust let mut polyline = Polyline::new_closed(); assert!(matches!(polyline.rotate_start(0, Vector2::new(0.0, 0.0), 1e-5), None)); polyline.add(0.0, 0.0, 0.0); assert!(matches!(polyline.rotate_start(0, Vector2::new(0.0, 0.0), 1e-5), None)); polyline.add(1.0, 0.0, 0.0); polyline.add(1.0, 1.0, 0.0); polyline.add(0.0, 1.0, 0.0); let rot = polyline.rotate_start(0, Vector2::new(0.5, 0.0), 1e-5).unwrap(); let mut expected_rot = Polyline::new_closed(); expected_rot.add(0.5, 0.0, 0.0); expected_rot.add(1.0, 0.0, 0.0); expected_rot.add(1.0, 1.0, 0.0); expected_rot.add(0.0, 1.0, 0.0); expected_rot.add(0.0, 0.0, 0.0); assert!(rot.fuzzy_eq(&expected_rot)); ``` -------------------------------- ### Calculate Forward Wrapping Index Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/traits.rs.html Computes a new index by applying an offset to a starting index, wrapping around the polyline length. Requires the start index to be valid and the offset to not exceed the polyline length. ```rust # use cavalier_contours::polyline::*; let mut polyline = Polyline::new_closed(); polyline.add(0.0, 0.0, 0.0); polyline.add(0.0, 0.0, 0.0); polyline.add(0.0, 0.0, 0.0); polyline.add(0.0, 0.0, 0.0); assert_eq!(polyline.fwd_wrapping_index(0, 2), 2); assert_eq!(polyline.fwd_wrapping_index(1, 2), 3); assert_eq!(polyline.fwd_wrapping_index(1, 3), 0); assert_eq!(polyline.fwd_wrapping_index(2, 3), 1); ``` -------------------------------- ### GET /polyline/orientation Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/traits.rs.html Determines the orientation of a closed polyline (Clockwise or CounterClockwise). ```APIDOC ## GET /polyline/orientation ### Description Returns the orientation of the polyline. If the polyline is not closed, it returns an Open status. ### Method GET ### Response #### Success Response (200) - **orientation** (PlineOrientation) - The orientation of the polyline (Clockwise, CounterClockwise, or Open). ``` -------------------------------- ### Create a Vector2 using vec2 Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.vec2.html Demonstrates the shorthand constructor for initializing a Vector2 with specific x and y coordinates. ```rust let v = vec2(3.0, 4.0); assert_eq!(v.x, 3.0); assert_eq!(v.y, 4.0); ``` -------------------------------- ### angle_is_within_sweep_eps Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.angle_is_within_sweep_eps.html Tests if a test_angle is within a sweep_angle starting at a start_angle with fuzzy inclusion. ```APIDOC ## Function: angle_is_within_sweep_eps ### Description Tests if `test_angle` is within the `sweep_angle` starting at `start_angle`. If `sweep_angle` is positive, the sweep is counter-clockwise; otherwise, it is clockwise. `epsilon` controls the fuzzy inclusion. ### Parameters - **test_angle** (T) - Required - The angle to test. - **start_angle** (T) - Required - The starting angle of the sweep. - **sweep_angle** (T) - Required - The total angle of the sweep. - **epsilon** (T) - Required - The tolerance for fuzzy inclusion. ### Returns - **bool** - Returns true if the angle is within the sweep, false otherwise. ``` -------------------------------- ### Create a view over a polyline from slice points Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/struct.PlineViewData.html Demonstrates constructing PlineViewData from specific points on a polyline and creating a view to perform operations like length and extent calculations. ```rust let mut polyline = Polyline::new_closed(); polyline.add(0.0, 0.0, 0.0); polyline.add(5.0, 0.0, 0.0); polyline.add(5.0, 5.0, 0.0); polyline.add(0.0, 5.0, 0.0); // construction view data from slice points, view data represents a slice of the source polyline // starting at (2.5, 0.0) on the first segment (index 0) and ending at (2.5, 5.0) on the third // segment (index 2) let view_data = PlineViewData::from_slice_points( // source polyline &polyline, // start point Vector2::new(2.5, 0.0), // segment index start point lies on 0, // end point Vector2::new(2.5, 5.0), // segment index end point lies on 2, // position equal epsilon 1e-5).expect("slice not collapsed"); // construct the view (which implements polyline traits) from the view data and source let view = view_data.view(&polyline); // we can now use common trait methods on the slice // note we never had to copy the source polyline let slice_length = view.path_length(); assert_fuzzy_eq!(view.path_length(), 10.0); let slice_vertex_count = view.vertex_count(); assert_eq!(slice_vertex_count, 4); let slice_extents = view.extents().unwrap(); assert_fuzzy_eq!(slice_extents.min_x, 2.5); assert_fuzzy_eq!(slice_extents.min_y, 0.0); assert_fuzzy_eq!(slice_extents.max_x, 5.0); assert_fuzzy_eq!(slice_extents.max_y, 5.0); ``` -------------------------------- ### OrAndStitchSelector Constructor Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/internal/pline_boolean.rs.html Creates a new OrAndStitchSelector instance with specified slice start indices. ```rust pub fn new( start_of_pline2_slices: usize, start_of_pline1_overlapping_slices: usize, start_of_pline2_overlapping_slices: usize, ) -> Self { Self { start_of_pline2_slices, start_of_pline1_overlapping_slices, start_of_pline2_overlapping_slices, } } ``` -------------------------------- ### Vector2 Constructors and Basic Operations Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/core/math/vector2.rs.html Provides methods for creating and manipulating Vector2 instances, including new, zero, scale, dot product, and length calculations. ```APIDOC ## Vector2 Methods ### Description Provides methods for creating and manipulating Vector2 instances. ### Methods #### `new(x: T, y: T) -> Self` Create a new vector with x and y components. #### `zero() -> Self` Create a zero vector (x = 0, y = 0). #### `scale(&self, scale_factor: T) -> Self` Uniformly scale the vector by `scale_factor`. #### `dot(&self, other: Self) -> T` Compute the dot product of two vectors. #### `perp_dot(&self, other: Self) -> T` Compute the perpendicular dot product (`self.x * other.y - self.y * other.x`). #### `length_squared(&self) -> T` Compute the squared length of the vector. #### `length(&self) -> T` Compute the length of the vector. #### `normalize(&self) -> Self` Normalize the vector (length = 1). #### `fuzzy_eq_eps(&self, other: Self, fuzzy_epsilon: T) -> bool` Fuzzy equal comparison with another vector using `fuzzy_epsilon` given. #### `fuzzy_eq(&self, other: Self) -> bool` Fuzzy equal comparison with another vector using T::fuzzy_epsilon(). #### `perp(&self) -> Self` Create a perpendicular vector. #### `unit_perp(&self) -> Self` Create a perpendicular unit vector (length = 1). #### `rotate_about(&self, origin: Self, angle: T) -> Self` Rotate this point around an `origin` point by some `angle` in radians. ``` -------------------------------- ### FuzzyOrd Trait Documentation Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/core/traits/fuzzy_ord.rs.html Documentation for the FuzzyOrd trait, including its purpose, methods, and examples. ```APIDOC ## FuzzyOrd Trait ### Description Trait for fuzzy ordering comparisons with floating point numbers. This trait extends [`FuzzyEq`] to provide fuzzy comparison operations for ordering floating point values. Like fuzzy equality, this accounts for floating point precision issues in greater-than and less-than comparisons. ### Methods - **`fuzzy_gt_eps(&self, other: Self, fuzzy_epsilon: Self) -> bool`**: Returns `true` if this value is fuzzy greater than the other, using a provided epsilon value. - **`fuzzy_gt(&self, other: Self) -> bool`**: Fuzzy greater than, using the default epsilon value. - **`fuzzy_lt_eps(&self, other: Self, fuzzy_epsilon: Self) -> bool`**: Returns `true` if this value is fuzzy less than the other, using a provided epsilon value. - **`fuzzy_lt(&self, other: Self) -> bool`**: Fuzzy less than, using the default epsilon value. - **`fuzzy_in_range_eps(&self, min: Self, max: Self, fuzzy_epsilon: Self) -> bool`**: Test if `self` is in range between `min` and `max` with some epsilon for fuzzy comparing. - **`fuzzy_in_range(&self, min: Self, max: Self) -> bool`**: Same as `fuzzy_in_range_eps` using a default epsilon. ### Examples ```rust # use cavalier_contours::core::traits::* let a = 0.1 + 0.2; let b = 0.3; // Due to floating point precision, a is actually slightly greater than b assert!(!(a <= b)); // But fuzzy comparison considers them equal assert!(a.fuzzy_lt(b)); assert!(0.99f64.fuzzy_in_range_eps(1.0, 2.0, 0.05)); assert!(1.5f64.fuzzy_in_range_eps(1.0, 2.0, 1e-5)); assert!(2.0f64.fuzzy_in_range_eps(1.0, 2.0, 1e-5)); ``` ### Implementations - `impl FuzzyOrd for f32` - `impl FuzzyOrd for f64` ``` -------------------------------- ### Polyline Initialization and Userdata Management Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline.rs.html Methods for creating new Polyline instances and managing associated user-provided metadata. ```rust impl Default for Polyline where T: Real, { #[inline] fn default() -> Self { Self::new() } } impl Polyline where T: Real, { /// Create a new empty [Polyline] with `is_closed` set to false. #[inline] pub fn new() -> Self { Polyline { vertex_data: Vec::new(), is_closed: false, userdata: Vec::new(), } } /// Create a new empty [Polyline] with `is_closed` set to true. #[inline] pub fn new_closed() -> Self { Polyline { vertex_data: Vec::new(), is_closed: true, userdata: Vec::new(), } } #[inline] pub fn get_userdata_count(&self) -> usize { self.userdata.len() } #[inline] pub fn get_userdata_values(&self) -> impl Iterator + '_ { self.userdata.iter().copied() } #[inline] pub fn set_userdata_values(&mut self, values: impl IntoIterator) { self.userdata.clear(); self.userdata.extend(values); } #[inline] pub fn add_userdata_values(&mut self, values: impl IntoIterator) { self.userdata.extend(values); } } ``` -------------------------------- ### PlineView and PlineViewData Usage Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Overview of how to create a PlineViewData instance from a source polyline and convert it into an active PlineView. ```APIDOC ## PlineViewData::from_slice_points ### Description Creates a PlineViewData instance representing a contiguous subpart of a source polyline defined by start and end points on specific segments. ### Parameters #### Request Body - **source** (PlineSource) - Required - The source polyline to slice. - **start_point** (Vector2) - Required - The starting coordinate of the slice. - **start_index** (usize) - Required - The segment index where the start point lies. - **end_point** (Vector2) - Required - The ending coordinate of the slice. - **end_index** (usize) - Required - The segment index where the end point lies. - **epsilon** (f64) - Required - The tolerance for position equality checks. ### Response #### Success Response (200) - **PlineViewData** (Struct) - The detached view data structure representing the slice. --- ## PlineViewData::view ### Description Constructs an active PlineView from the detached PlineViewData and a reference to the source polyline. ### Parameters #### Request Body - **source** (PlineSource) - Required - The source polyline to borrow for the view. ### Response #### Success Response (200) - **PlineView** (Struct) - An active view that implements PlineSource traits. ``` -------------------------------- ### Simplify a Circle Defined by Multiple Vertexes Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/traits.rs.html This example demonstrates simplifying a polyline representing a circle, reducing multiple vertices to just two essential ones. It handles cases where redundant vertexes might be introduced. ```rust # use cavalier_contours::polyline::* let bulge = (std::f64::consts::PI / 8.0).tan(); let mut polyline = Polyline::new_closed(); polyline.add(-0.5, 0.0, bulge); polyline.add(0.0, -0.5, bulge); // repeat vertex thrown in polyline.add(0.0, -0.5, bulge); polyline.add(0.5, 0.0, bulge); polyline.add(0.0, 0.5, bulge); let result = polyline.remove_redundant(1e-5).expect("redundant vertexes were removed"); assert_eq!(result.vertex_count(), 2); assert!(result.is_closed()); assert!(result[0].fuzzy_eq(PlineVertex::new(-0.5, 0.0, 1.0))); assert!(result[1].fuzzy_eq(PlineVertex::new(0.5, 0.0, 1.0))); ``` -------------------------------- ### angle_is_between Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/math/fn.angle_is_between.html Checks if an angle is between a start and end angle, using default epsilon for fuzzy comparison. ```APIDOC ## angle_is_between ### Description Checks if `test_angle` is between `start_angle` and `end_angle`. This function uses the default epsilon from the `FuzzyEq` trait for comparison. ### Signature ```rust pub fn angle_is_between(test_angle: T, start_angle: T, end_angle: T) -> bool where T: Real, ``` ### Parameters - `test_angle` (T): The angle to test. - `start_angle` (T): The starting angle of the range. - `end_angle` (T): The ending angle of the range. ### Type Parameters - `T`: Must implement the `Real` trait, indicating a real number type. ``` -------------------------------- ### Create New PlineView Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/struct.PlineView.html Constructor for PlineView. Use this to create a new view with a given source polyline and view data. ```rust pub fn new(source: &'a P, data: PlineViewData) -> Self> ``` -------------------------------- ### Construct a closed polyline Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/macro.pline_closed.html Usage example for creating a closed polyline using the pline_closed macro. ```rust let polyline = pline_closed![(0.0, 1.0, 1.0), (2.0, 0.0, 0.0)]; assert!(polyline.is_closed()); assert_eq!(polyline[0], PlineVertex::new(0.0, 1.0, 1.0)); assert_eq!(polyline[1], PlineVertex::new(2.0, 0.0, 0.0)); ``` -------------------------------- ### PlineView Struct Methods Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/struct.PlineView.html Methods for creating and managing a PlineView instance. ```APIDOC ## PlineView::new ### Description Create a new view with the given source and data. ### Parameters - **source** (&'a P) - Required - Reference to the source polyline. - **data** (PlineViewData) - Required - View data used for indexing. ## PlineView::detach ### Description Consume the view, releasing the borrow on the source polyline and returning the associated view data. ``` -------------------------------- ### TryInto Trait Methods Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/enum.BooleanOp.html Documentation for the conversion methods provided by the TryInto trait. ```APIDOC ## Associated Type: Error ### Description The type returned in the event of a conversion error. ## fn try_into ### Description Performs the conversion from the source type to the target type. ### Returns - **Result>::Error>** - A Result containing the converted type or the associated error type. ``` -------------------------------- ### Rotate Start Vertex Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/polyline/trait.PlineSource.html Rotates the vertices of a closed polyline so that a specified point becomes the first vertex. ```APIDOC ## Rotates the vertexes in a closed polyline such that the first vertex’s position is at `point`. ### Description This method repositions the vertices of a closed polyline without altering its shape. It makes a specified `point` the new starting vertex, using `start_index` to identify the segment containing `point`. ### Method `rotate_start( &self, start_index: usize, point: Vector2, pos_equal_eps: Self::Num, ) -> Option` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust let mut polyline = Polyline::new_closed(); polyline.add(0.0, 0.0, 0.0); polyline.add(1.0, 0.0, 0.0); polyline.add(1.0, 1.0, 0.0); polyline.add(0.0, 1.0, 0.0); let rot = polyline.rotate_start(0, Vector2::new(0.5, 0.0), 1e-5).unwrap(); ``` ### Response #### Success Response (200) Returns a new Polyline with vertices rotated. Returns `None` if the polyline is not closed, has fewer than 2 vertices, or if `start_index` is out of bounds. #### Response Example ```rust let mut expected_rot = Polyline::new_closed(); expected_rot.add(0.5, 0.0, 0.0); expected_rot.add(1.0, 0.0, 0.0); expected_rot.add(1.0, 1.0, 0.0); expected_rot.add(0.0, 1.0, 0.0); expected_rot.add(0.0, 0.0, 0.0); assert!(rot.fuzzy_eq(&expected_rot)); ``` ``` -------------------------------- ### from_slice_points Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline_view.rs.html Constructs a view that is contiguous between two points on a source polyline, trimming the start and end as necessary. ```APIDOC ## from_slice_points ### Description Constructs a view that is contiguous between two points on a source polyline. This method handles the logic for slicing the polyline between a start and end point. ### Parameters #### Path Parameters - **source** (P) - Required - The source polyline implementation. - **start_point** (Vector2) - Required - The starting coordinate. - **start_index** (usize) - Required - The index to begin from. - **end_point** (Vector2) - Required - The ending coordinate. - **end_index** (usize) - Required - The index to end at. - **pos_equal_eps** (T) - Required - Epsilon value for fuzzy equality checks. ### Response - **Option** - Returns the constructed view data or None if construction fails. ``` -------------------------------- ### Step 1: Create Offset Loops with Index Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/shape_algorithms/struct.Shape.html Generates offset polylines for each input polyline and creates a spatial index. Offset loops are separated into counter-clockwise and clockwise collections. This is the first step in the multipolyline offset algorithm. ```rust pub fn create_offset_loops_with_index( &self, offset: T, options: &ShapeOffsetOptions, ) -> (Vec>, Vec>, StaticAABB2DIndex) ``` -------------------------------- ### Polyline Creation Methods Source: https://docs.rs/cavalier_contours/0.7.0/src/cavalier_contours/polyline/pline.rs.html Static methods for creating new Polyline instances from capacity or iterators. ```APIDOC ## Polyline Creation Methods ### Description Constructors for initializing new Polyline objects. ### Methods - **with_capacity(capacity: usize, is_closed: bool)**: Creates a new Polyline with pre-allocated capacity. - **from_iter(iter: I, is_closed: bool)**: Creates a new Polyline by collecting vertices from an iterator. ``` -------------------------------- ### FuzzyEq Trait Documentation Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/traits/trait.FuzzyEq.html Documentation for the FuzzyEq trait, including its purpose, required and provided methods, and examples. ```APIDOC ## Trait FuzzyEq ### Description Trait for fuzzy equality comparisons with floating point numbers. This trait provides methods for comparing floating point values with a tolerance (epsilon) to account for floating point precision issues. It’s essential for geometric computations where exact equality is rarely achievable due to floating point arithmetic limitations. ### Required Methods #### fn fuzzy_epsilon() -> Self Returns the default epsilon value for fuzzy comparisons. #### fn fuzzy_eq_eps(&self, other: Self, fuzzy_epsilon: Self) -> bool Returns `true` is this object is approximately equal to the other one, using a provided epsilon value. #### fn fuzzy_eq_zero_eps(&self, fuzzy_epsilon: Self) -> bool Returns `true` if this value is approximately equal to zero, using a provided epsilon value. ### Provided Methods #### fn fuzzy_eq(&self, other: Self) -> bool Returns `true` is this object is approximately equal to the other one, using the implemented FuzzyEq::fuzzy_epsilon value. #### fn fuzzy_eq_zero(&self) -> bool Returns `true` if this value is approximately equal to zero, using the implemented FuzzyEq::fuzzy_epsilon value. ### Examples ```rust let a = 0.1 + 0.2; let b = 0.3; // Direct comparison would fail due to floating point precision assert_ne!(a, b); // Fuzzy comparison succeeds assert!(a.fuzzy_eq(b)); ``` ### Implementations on Foreign Types #### impl FuzzyEq for f32 #### impl FuzzyEq for f64 ### Dyn Compatibility This trait is **not** dyn compatible. ``` -------------------------------- ### Fuzzy Ordering Example Source: https://docs.rs/cavalier_contours/0.7.0/cavalier_contours/core/traits/trait.FuzzyOrd.html Demonstrates how FuzzyOrd can be used to compare floating-point numbers that are expected to be equal but may differ slightly due to precision. It shows that a direct comparison might fail, but a fuzzy comparison succeeds. ```rust let a = 0.1 + 0.2; let b = 0.3; // Due to floating point precision, a is actually slightly greater than b assert!(!(a <= b)); // But fuzzy comparison considers them equal assert!(a.fuzzy_lt(b)); ```