Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate Line on construction #910

Merged
merged 6 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 12 additions & 22 deletions crates/fj-kernel/src/algorithms/intersection/line_segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ impl LineSegmentIntersection {
Vector::from([ab.v, ab.u])
};

let n_dot_origin = n.dot(&(b - line.origin));
let n_dot_direction = n.dot(&line.direction);
let n_dot_origin = n.dot(&(b - line.origin()));
let n_dot_direction = n.dot(&line.direction());

if n_dot_direction == Scalar::ZERO {
// `line` and `segment` are parallel
Expand Down Expand Up @@ -72,10 +72,8 @@ mod tests {

#[test]
fn compute_one_hit() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
let line =
Line::from_origin_and_direction(Point::origin(), Vector::unit_u());

assert_eq!(
LineSegmentIntersection::compute(
Expand All @@ -90,10 +88,8 @@ mod tests {

#[test]
fn compute_coincident() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
let line =
Line::from_origin_and_direction(Point::origin(), Vector::unit_u());

assert_eq!(
LineSegmentIntersection::compute(
Expand All @@ -108,10 +104,8 @@ mod tests {

#[test]
fn compute_no_hit_above() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
let line =
Line::from_origin_and_direction(Point::origin(), Vector::unit_u());

assert_eq!(
LineSegmentIntersection::compute(
Expand All @@ -124,10 +118,8 @@ mod tests {

#[test]
fn compute_no_hit_below() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
let line =
Line::from_origin_and_direction(Point::origin(), Vector::unit_u());

assert_eq!(
LineSegmentIntersection::compute(
Expand All @@ -140,10 +132,8 @@ mod tests {

#[test]
fn compute_no_hit_parallel() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
let line =
Line::from_origin_and_direction(Point::origin(), Vector::unit_u());

assert_eq!(
LineSegmentIntersection::compute(
Expand Down
24 changes: 13 additions & 11 deletions crates/fj-kernel/src/algorithms/intersection/surface_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@ impl SurfaceSurfaceIntersection {
/ denom;
let origin = Point { coords: origin };

let line = Line { origin, direction };
let line = Line::from_origin_and_direction(origin, direction);

let curves = planes_parametric.map(|plane| {
let local = project_line_into_plane(&line, &plane);
let global = CurveKind::Line(Line { origin, direction });
let global = CurveKind::Line(Line::from_origin_and_direction(
origin, direction,
));

Curve::new(local, GlobalCurve::from_kind(global))
});
Expand Down Expand Up @@ -74,8 +76,8 @@ impl PlaneParametric {
};

Self {
origin: line.origin,
u: line.direction,
origin: line.origin(),
u: line.direction(),
v: surface.path,
}
}
Expand Down Expand Up @@ -111,7 +113,7 @@ fn project_line_into_plane(
line: &Line<3>,
plane: &PlaneParametric,
) -> CurveKind<2> {
let line_origin_relative_to_plane = line.origin - plane.origin;
let line_origin_relative_to_plane = line.origin() - plane.origin;
let line_origin_in_plane = Vector::from([
plane
.u
Expand All @@ -122,16 +124,16 @@ fn project_line_into_plane(
]);

let line_direction_in_plane = Vector::from([
plane.u.scalar_projection_onto(&line.direction),
plane.v.scalar_projection_onto(&line.direction),
plane.u.scalar_projection_onto(&line.direction()),
plane.v.scalar_projection_onto(&line.direction()),
]);

let line = Line {
origin: Point {
let line = Line::from_origin_and_direction(
Point {
coords: line_origin_in_plane,
},
direction: line_direction_in_plane,
};
line_direction_in_plane,
);

CurveKind::Line(line)
}
Expand Down
17 changes: 11 additions & 6 deletions crates/fj-kernel/src/algorithms/reverse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,17 @@ fn reverse_local_coordinates_in_cycle<'r>(

CurveKind::Circle(Circle { center, a, b })
}
CurveKind::Line(Line { origin, direction }) => {
let origin = Point::from([origin.u, -origin.v]);
let direction =
Vector::from([direction.u, -direction.v]);

CurveKind::Line(Line { origin, direction })
CurveKind::Line(line) => {
let origin =
Point::from([line.origin().u, -line.origin().v]);
let direction = Vector::from([
line.direction().u,
-line.direction().v,
]);

CurveKind::Line(Line::from_origin_and_direction(
origin, direction,
))
}
};

Expand Down
26 changes: 13 additions & 13 deletions crates/fj-kernel/src/objects/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<const D: usize> CurveKind<D> {
pub fn origin(&self) -> Point<D> {
match self {
Self::Circle(curve) => curve.center,
Self::Line(curve) => curve.origin,
Self::Line(curve) => curve.origin(),
}
}

Expand Down Expand Up @@ -127,26 +127,26 @@ impl<const D: usize> CurveKind<D> {
impl CurveKind<3> {
/// Construct a `Curve` that represents the x-axis
pub fn x_axis() -> Self {
Self::Line(Line {
origin: Point::origin(),
direction: Vector::unit_x(),
})
Self::Line(Line::from_origin_and_direction(
Point::origin(),
Vector::unit_x(),
))
}

/// Construct a `Curve` that represents the y-axis
pub fn y_axis() -> Self {
Self::Line(Line {
origin: Point::origin(),
direction: Vector::unit_y(),
})
Self::Line(Line::from_origin_and_direction(
Point::origin(),
Vector::unit_y(),
))
}

/// Construct a `Curve` that represents the z-axis
pub fn z_axis() -> Self {
Self::Line(Line {
origin: Point::origin(),
direction: Vector::unit_z(),
})
Self::Line(Line::from_origin_and_direction(
Point::origin(),
Vector::unit_z(),
))
}

/// Transform the surface
Expand Down
37 changes: 17 additions & 20 deletions crates/fj-kernel/src/objects/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,7 @@ impl SweptCurve {
}

fn path_to_line(&self) -> Line<3> {
Line {
origin: self.curve.origin(),
direction: self.path,
}
Line::from_origin_and_direction(self.curve.origin(), self.path)
}
}

Expand All @@ -143,20 +140,20 @@ mod tests {
#[test]
fn reverse() {
let original = SweptCurve {
curve: CurveKind::Line(Line {
origin: Point::from([1., 0., 0.]),
direction: Vector::from([0., 2., 0.]),
}),
curve: CurveKind::Line(Line::from_origin_and_direction(
Point::from([1., 0., 0.]),
Vector::from([0., 2., 0.]),
)),
path: Vector::from([0., 0., 3.]),
};

let reversed = original.reverse();

let expected = SweptCurve {
curve: CurveKind::Line(Line {
origin: Point::from([1., 0., 0.]),
direction: Vector::from([0., 2., 0.]),
}),
curve: CurveKind::Line(Line::from_origin_and_direction(
Point::from([1., 0., 0.]),
Vector::from([0., 2., 0.]),
)),
path: Vector::from([0., 0., -3.]),
};
assert_eq!(expected, reversed);
Expand All @@ -165,10 +162,10 @@ mod tests {
#[test]
fn point_from_surface_coords() {
let swept = SweptCurve {
curve: CurveKind::Line(Line {
origin: Point::from([1., 1., 1.]),
direction: Vector::from([0., 2., 0.]),
}),
curve: CurveKind::Line(Line::from_origin_and_direction(
Point::from([1., 1., 1.]),
Vector::from([0., 2., 0.]),
)),
path: Vector::from([0., 0., 2.]),
};

Expand All @@ -181,10 +178,10 @@ mod tests {
#[test]
fn vector_from_surface_coords() {
let swept = SweptCurve {
curve: CurveKind::Line(Line {
origin: Point::from([1., 0., 0.]),
direction: Vector::from([0., 2., 0.]),
}),
curve: CurveKind::Line(Line::from_origin_and_direction(
Point::from([1., 0., 0.]),
Vector::from([0., 2., 0.]),
)),
path: Vector::from([0., 0., 2.]),
};

Expand Down
59 changes: 43 additions & 16 deletions crates/fj-math/src/line.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Point, Triangle, Vector};
use crate::{Point, Scalar, Triangle, Vector};

/// An n-dimensional line, defined by an origin and a direction
///
Expand All @@ -7,30 +7,57 @@ use crate::{Point, Triangle, Vector};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct Line<const D: usize> {
/// The origin of the line
origin: Point<D>,
direction: Vector<D>,
}

impl<const D: usize> Line<D> {
/// Create a line from a point and a vector
///
/// # Panics
///
/// Panics, if `direction` has a length of zero.
pub fn from_origin_and_direction(
origin: Point<D>,
direction: Vector<D>,
) -> Self {
if direction.magnitude() == Scalar::ZERO {
panic!(
"Can't construct `Line`. Direction is zero: {:?}",
direction
);
}

Self { origin, direction }
}

/// Create a line from two points
///
/// # Panics
///
/// Panics, if the points are coincident.
pub fn from_points(points: [impl Into<Point<D>>; 2]) -> Self {
let [a, b] = points.map(Into::into);

Self::from_origin_and_direction(a, b - a)
}

/// Access the origin of the line
///
/// The origin is a point on the line which, together with the `direction`
/// field, defines the line fully. The origin also defines the origin of the
/// line's 1-dimensional coordinate system.
pub origin: Point<D>,
pub fn origin(&self) -> Point<D> {
self.origin
}

/// The direction of the line
/// Access the direction of the line
///
/// The length of this vector defines the unit of the line's curve
/// coordinate system. The coordinate `1.` is always were the direction
/// vector points, from `origin`.
pub direction: Vector<D>,
}

impl<const D: usize> Line<D> {
/// Create a line from two points
pub fn from_points(points: [impl Into<Point<D>>; 2]) -> Self {
let [a, b] = points.map(Into::into);

Self {
origin: a,
direction: b - a,
}
pub fn direction(&self) -> Vector<D> {
self.direction
}

/// Determine if this line is coincident with another line
Expand Down
Loading