Add CurveGeom2::line_segment_at

This commit is contained in:
Hanno Braun 2024-08-26 20:31:54 +02:00
parent 78854f69cd
commit be1b621285
2 changed files with 55 additions and 17 deletions

View File

@ -2,7 +2,11 @@ use std::collections::BTreeMap;
use fj_math::{Circle, Line, Point};
use crate::{storage::Handle, topology::Surface};
use crate::{
algorithms::approx::{PathApproxParams, Tolerance},
storage::Handle,
topology::Surface,
};
use super::Path;
@ -68,18 +72,54 @@ pub struct LocalCurveGeom {
pub trait CurveGeom2<const D: usize> {
/// # Access the origin of the curve
fn origin(&self) -> Point<D>;
/// # Compute a line segment to approximate the curve at this point
///
/// If the curve requires no approximation (meaning it is a line), then per
/// convention, a degenerate line segment is returned, that collapses to the
/// provided point.
fn line_segment_at(
&self,
point: impl Into<Point<1>>,
tolerance: impl Into<Tolerance>,
) -> [Point<D>; 2];
}
impl<const D: usize> CurveGeom2<D> for Circle<D> {
fn origin(&self) -> Point<D> {
self.center() + self.a()
}
fn line_segment_at(
&self,
point: impl Into<Point<1>>,
tolerance: impl Into<Tolerance>,
) -> [Point<D>; 2] {
let point = point.into();
let params = PathApproxParams::for_circle(self, tolerance);
[point.t - params.increment(), point.t + params.increment()]
.map(|point_circle| self.point_from_circle_coords([point_circle]))
}
}
impl<const D: usize> CurveGeom2<D> for Line<D> {
fn origin(&self) -> Point<D> {
self.origin()
}
fn line_segment_at(
&self,
point: impl Into<Point<1>>,
_: impl Into<Tolerance>,
) -> [Point<D>; 2] {
let point = point.into();
// Collapse line segment into a point, as per documentation.
let point = self.origin() + self.direction() * point.t;
[point, point]
}
}
// This implementation is temporary, to ease the transition towards a curve
@ -91,4 +131,15 @@ impl<const D: usize> CurveGeom2<D> for Path<D> {
Self::Line(line) => line.origin(),
}
}
fn line_segment_at(
&self,
point: impl Into<Point<1>>,
tolerance: impl Into<Tolerance>,
) -> [Point<D>; 2] {
match self {
Self::Circle(circle) => circle.line_segment_at(point, tolerance),
Self::Line(line) => line.line_segment_at(point, tolerance),
}
}
}

View File

@ -2,7 +2,7 @@
use fj_math::{Point, Scalar, Transform, Triangle, Vector};
use crate::algorithms::approx::{PathApproxParams, Tolerance};
use crate::algorithms::approx::Tolerance;
use super::{CurveGeom2, Path};
@ -67,23 +67,10 @@ impl SurfaceGeom {
let line_segment = match &self.u {
Path::Circle(circle) => {
let params = PathApproxParams::for_circle(circle, tolerance);
[
point_surface.u - params.increment(),
point_surface.u + params.increment(),
]
.map(|point_circle| {
circle.point_from_circle_coords([point_circle])
})
circle.line_segment_at([point_surface.u], tolerance)
}
Path::Line(line) => {
// We don't need to approximate a line. So instead of creating a
// line segment to represent the line at this point, we just
// need this single point.
let point = line.origin() + line.direction() * point_surface.u;
[point, point]
line.line_segment_at([point_surface.u], tolerance)
}
};