Skip to content

Commit

Permalink
Merge pull request #1912 from hannobraun/builder
Browse files Browse the repository at this point in the history
Add `BuildFace::polygon`, clean up `BuildFace::triangle`
  • Loading branch information
hannobraun authored Jun 27, 2023
2 parents 6d5b9cf + 2289859 commit f8b0087
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 45 deletions.
14 changes: 1 addition & 13 deletions crates/fj-core/src/operations/build/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use fj_math::{Arc, Point, Scalar};

use crate::{
geometry::curve::Curve,
objects::{GlobalEdge, HalfEdge, Surface, Vertex},
objects::{GlobalEdge, HalfEdge, Vertex},
operations::Insert,
services::Services,
};
Expand Down Expand Up @@ -75,18 +75,6 @@ pub trait BuildHalfEdge {

HalfEdge::unjoined(curve, boundary, services)
}

/// Create a line segment from global points
fn line_segment_from_global_points(
points_global: [impl Into<Point<3>>; 2],
surface: &Surface,
boundary: Option<[Point<1>; 2]>,
services: &mut Services,
) -> HalfEdge {
let points_surface = points_global
.map(|point| surface.geometry().project_global_point(point));
HalfEdge::line_segment(points_surface, boundary, services)
}
}

impl BuildHalfEdge for HalfEdge {}
53 changes: 32 additions & 21 deletions crates/fj-core/src/operations/build/face.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::array;

use fj_interop::ext::ArrayExt;
use fj_math::Point;

use crate::{
objects::{Cycle, Face, HalfEdge, Region, Surface, Vertex},
operations::{
BuildCycle, BuildHalfEdge, BuildSurface, Insert, IsInserted,
IsInsertedNo,
BuildCycle, BuildRegion, BuildSurface, Insert, IsInserted, IsInsertedNo,
},
services::Services,
storage::Handle,
Expand All @@ -25,36 +26,46 @@ pub trait BuildFace {
points: [impl Into<Point<3>>; 3],
services: &mut Services,
) -> Polygon<3> {
let [a, b, c] = points.map(Into::into);

let surface = Surface::plane_from_points([a, b, c]).insert(services);
let (exterior, edges, vertices) = {
let half_edges = [[a, b], [b, c], [c, a]].map(|points| {
let half_edge = HalfEdge::line_segment_from_global_points(
points, &surface, None, services,
);
let (surface, points_surface) = Surface::plane_from_points(points);
let surface = surface.insert(services);

half_edge.insert(services)
});
let vertices = half_edges
.each_ref_ext()
.map(|half_edge| half_edge.start_vertex().clone());
let face = Face::polygon(surface, points_surface, services);

let cycle = Cycle::new(half_edges.clone()).insert(services);
let edges = {
let mut half_edges = face.region().exterior().half_edges().cloned();
assert_eq!(half_edges.clone().count(), 3);

(cycle, half_edges, vertices)
array::from_fn(|_| half_edges.next()).map(|half_edge| {
half_edge
.expect("Just asserted that there are three half-edges")
})
};

let region = Region::new(exterior, [], None).insert(services);

let face = Face::new(surface, region);
let vertices =
edges.each_ref_ext().map(|half_edge: &Handle<HalfEdge>| {
half_edge.start_vertex().clone()
});

Polygon {
face,
edges,
vertices,
}
}

/// Build a polygon
fn polygon<P, Ps>(
surface: Handle<Surface>,
points: Ps,
services: &mut Services,
) -> Face
where
P: Into<Point<2>>,
Ps: IntoIterator<Item = P>,
Ps::IntoIter: Clone + ExactSizeIterator,
{
let region = Region::polygon(points, services).insert(services);
Face::new(surface, region)
}
}

impl BuildFace for Face {}
Expand Down
23 changes: 17 additions & 6 deletions crates/fj-core/src/operations/build/surface.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use fj_math::Point;
use fj_math::{Point, Scalar};

use crate::{
geometry::{curve::GlobalPath, surface::SurfaceGeometry},
Expand All @@ -8,15 +8,26 @@ use crate::{
/// Build a [`Surface`]
pub trait BuildSurface {
/// Build a plane from the provided points
fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Surface {
fn plane_from_points(
points: [impl Into<Point<3>>; 3],
) -> (Surface, [Point<2>; 3]) {
let [a, b, c] = points.map(Into::into);

let geometry = SurfaceGeometry {
u: GlobalPath::line_from_points([a, b]).0,
v: c - a,
let (u, u_line) = GlobalPath::line_from_points([a, b]);
let v = c - a;

let geometry = SurfaceGeometry { u, v };
let surface = Surface::new(geometry);

let points_surface = {
let [a, b] =
u_line.map(|point| Point::from([point.t, Scalar::ZERO]));
let c = Point::from([a.u, Scalar::ONE]);

[a, b, c]
};

Surface::new(geometry)
(surface, points_surface)
}
}

Expand Down
10 changes: 5 additions & 5 deletions crates/fj-core/src/validate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,23 +99,23 @@ impl Default for ValidationConfig {
#[derive(Clone, Debug, thiserror::Error)]
pub enum ValidationError {
/// `Cycle` validation error
#[error("`Cycle` validation error:\n {0}")]
#[error("`Cycle` validation error")]
Cycle(#[from] CycleValidationError),

/// `Face` validation error
#[error("`Face` validation error\n {0}")]
#[error("`Face` validation error")]
Face(#[from] FaceValidationError),

/// `HalfEdge` validation error
#[error("`HalfEdge` validation error\n {0}")]
#[error("`HalfEdge` validation error")]
HalfEdge(#[from] HalfEdgeValidationError),

/// `Shell` validation error
#[error("`Shell` validation error\n {0}")]
#[error("`Shell` validation error")]
Shell(#[from] ShellValidationError),

/// `Solid` validation error
#[error("`Solid` validation error\n {0}")]
#[error("`Solid` validation error")]
Solid(#[from] SolidValidationError),
}

Expand Down

0 comments on commit f8b0087

Please sign in to comment.