Skip to content

Commit

Permalink
Makes LineIntersectionIterator public and adds documentation and so…
Browse files Browse the repository at this point in the history
…me utilty functions.
  • Loading branch information
Stoeoef committed May 22, 2024
1 parent 8dd38af commit 7ee290c
Show file tree
Hide file tree
Showing 9 changed files with 418 additions and 3 deletions.
5 changes: 5 additions & 0 deletions examples/svg_renderer/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ use anyhow::Result;
/// Used for rendering SVGs for documentation. These are inlined (via #[doc = include_str!(...)])
/// into the doc comment of a few items. That makes sure they will be visible even for offline users.
fn main() -> Result<()> {
scenario_list::line_intersection_iterator_scenario()?.save_to_svg(
"line_intersection_iterator_scenario",
"images/line_intersection_iterator_scenario.svg",
)?;

scenario_list::natural_neighbor_area_scenario(false)?.save_to_svg(
"natural_neighbor_insertion_cell",
"images/natural_neighbor_insertion_cell.svg",
Expand Down
11 changes: 10 additions & 1 deletion examples/svg_renderer/quicksketch/convert.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
ArrowType, PathPoint, Point, Sketch, SketchCircle, SketchColor, SketchElement, SketchLine,
SketchPath, SketchText, Style,
SketchPath, SketchRectangle, SketchText, Style,
};
use cgmath::num_traits::zero;
use cgmath::{Bounded, Deg, InnerSpace, Vector2};
Expand Down Expand Up @@ -150,6 +150,14 @@ impl SketchConverter {
.set("r", round(*radius))
.set("style", style.get_attribute_string(self)),
),
SketchElement::Rectangle(SketchRectangle { c0, c1, style }) => svg.add(
Rectangle::new()
.set("x", round(c0.x))
.set("y", round(c0.y))
.set("width", round(c1.x - c0.x))
.set("height", round(c1.y - c0.y))
.set("style", style.get_attribute_string(self)),
),
SketchElement::Path(SketchPath { data_points, style }) => {
let mut data = Data::new();
for point in data_points {
Expand Down Expand Up @@ -305,6 +313,7 @@ impl SketchConverter {
let offset = Vector2::new(*radius, *radius);
(center - offset, center + offset)
}
SketchElement::Rectangle(rect) => (rect.c0, rect.c1),
SketchElement::Path(SketchPath { data_points, .. }) => {
let mut min = Point::max_value();
let mut max = Point::min_value();
Expand Down
49 changes: 49 additions & 0 deletions examples/svg_renderer/quicksketch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,40 @@ impl Default for SketchCircle {
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct SketchRectangle {
c0: Point,
c1: Point,
style: Style,
}

impl SketchRectangle {
pub fn fill(mut self, fill: impl Into<SketchFill>) -> Self {
self.style.fill = Some(fill.into());
self
}

pub fn stroke_width(mut self, width: f64) -> Self {
self.style.stroke_width = Some(width);
self
}

pub fn stroke_color(mut self, color: SketchColor) -> Self {
self.style.stroke_color = Some(color);
self
}

pub fn stroke_style(mut self, stroke_style: StrokeStyle) -> Self {
self.style.stroke_style = Some(stroke_style);
self
}

pub fn opacity(mut self, opacity: f64) -> Self {
self.style.opacity = Some(opacity);
self
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct SketchText {
text: String,
Expand Down Expand Up @@ -475,6 +509,7 @@ impl SketchLine {
pub enum SketchElement {
Text(SketchText),
Circle(SketchCircle),
Rectangle(SketchRectangle),
Path(SketchPath),
Line(SketchLine),
}
Expand All @@ -488,6 +523,14 @@ impl SketchElement {
}
}

pub fn rectangle(c0: Point, c1: Point) -> SketchRectangle {
SketchRectangle {
c0,
c1,
style: Default::default(),
}
}

pub fn line(from: Point, to: Point) -> SketchLine {
SketchLine {
from,
Expand Down Expand Up @@ -534,6 +577,12 @@ impl From<SketchCircle> for SketchElement {
}
}

impl From<SketchRectangle> for SketchElement {
fn from(rectangle: SketchRectangle) -> Self {
SketchElement::Rectangle(rectangle)
}
}

impl From<SketchPath> for SketchElement {
fn from(polygon: SketchPath) -> Self {
SketchElement::Path(polygon)
Expand Down
123 changes: 123 additions & 0 deletions examples/svg_renderer/scenario_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1390,3 +1390,126 @@ pub fn refinement_maximum_area_scenario(max_area: Option<f64>) -> Sketch {

result
}

pub fn line_intersection_iterator_scenario() -> Result<Sketch> {
use spade::Intersection::*;

let vertices = vec![
VertexType::new(-30.0, -20.0),
VertexType::new(0.0, 20.0),
VertexType::new(0.0, -20.0),
VertexType::new(30.0, 0.0),
VertexType::new(14.0, 0.0),
];

let triangulation = Triangulation::bulk_load_stable(vertices)?;

let mut result = convert_triangulation(&triangulation, &Default::default());

for (index, vertex) in triangulation.vertices().enumerate() {
result.add(
SketchElement::text(format!("v{}", index))
.font_size(2.4)
.horizontal_alignment(HorizontalAlignment::Middle)
.dy(0.85)
.position(convert_point(vertex.position())),
);
}

fn small_line(from: Point2<f64>, to: Point2<f64>) -> crate::quicksketch::SketchLine {
SketchElement::line(from, to)
.with_arrow_start(ArrowType::HalfArrow)
.stroke_color(SketchColor::ROYAL_BLUE)
.shift_from(-4.3)
.shift_to(-2.8)
.stroke_width(0.6)
}

for intersection in spade::LineIntersectionIterator::new(
&triangulation,
spade::Point2::new(-30.0, 0.0),
spade::Point2::new(40.0, 0.0),
) {
println!("{:?}", intersection);
match intersection {
EdgeIntersection(edge) => {
let [from, to] = edge.positions().map(convert_point);
let offset = Vector2::new(0.8, 0.0);
let from = from + offset;
let to = to + offset;

result.add(small_line(from, to));
}
VertexIntersection(v) => {
result.add(
SketchElement::circle(convert_point(v.position()), v.data().radius - 0.3)
.fill(SketchColor::ROYAL_BLUE),
);
}

EdgeOverlap(edge) => {
let [from, to] = edge.positions().map(convert_point);
let offset = Vector2::new(0.0, -1.0);
let from = from + offset;
let to = to + offset;

result.add(small_line(to, from));
}
}
}
let intersection_start = Point2::new(-30.0, 0.0);
let intersection_end = Point2::new(40.0, 0.0);
result.add(
SketchElement::line(intersection_start, intersection_end)
.stroke_color(SketchColor::SALMON)
.with_arrow_end(ArrowType::FilledArrow)
.shift_to(-4.0)
.stroke_width(0.5)
.stroke_style(StrokeStyle::SmallDashed),
);

for (index, point) in [intersection_start, intersection_end]
.into_iter()
.enumerate()
{
result.add(SketchElement::circle(point, 1.3).fill(SketchColor::SALMON));

let text = if index == 0 { "s" } else { "e" };

result.add(
SketchElement::text(text)
.position(point)
.horizontal_alignment(HorizontalAlignment::Middle)
.dy(0.5)
.font_size(2.0),
);
}

fn add_label(result: &mut Sketch, text: &'static str, position: Point2<f64>) {
let offset = Vector2::new(1.5, 2.0);
let c0 = position - offset;
let c1 = position + offset;
let rect = SketchElement::rectangle(c0, c1)
.fill(SketchColor::WHITE)
.opacity(0.82);

let text = SketchElement::text(text)
.font_size(3.9)
.position(position)
.horizontal_alignment(HorizontalAlignment::Middle)
.dy(1.3);

result.add(rect);
result.add(text);
}

const LABEL_Y: f64 = -3.5;

add_label(&mut result, "0", Point2::new(-12.0, LABEL_Y));
add_label(&mut result, "1", Point2::new(2.4, LABEL_Y));
add_label(&mut result, "2", Point2::new(14.0, LABEL_Y));
add_label(&mut result, "3", Point2::new(22.0, LABEL_Y));
add_label(&mut result, "4", Point2::new(30.0, LABEL_Y));

Ok(result)
}
89 changes: 89 additions & 0 deletions images/line_intersection_iterator_scenario.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion images/preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

}
</script>
<img src="natural_neighbor_polygon.svg" id="img" />
<img src="line_intersection_iterator_scenario.svg" id="img" />


</html>
23 changes: 23 additions & 0 deletions src/cdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,29 @@ where
}
}

/// Returns all constraint edges that would prevent creating a new constraint between two points.
pub fn get_conflicting_edges_between_points(
&self,
from: Point2<<V as HasPosition>::Scalar>,
to: Point2<<V as HasPosition>::Scalar>,
) -> impl Iterator<Item = DirectedEdgeHandle<V, DE, CdtEdge<UE>, F>> {
LineIntersectionIterator::new(self, from, to)
.flat_map(|intersection| intersection.as_edge_intersection())
.filter(|e| e.is_constraint_edge())
}

/// Returns all constraint edges that would prevent inserting a new constraint connecting two existing
/// vertices.
pub fn get_conflicting_edges_between_vertices(
&self,
from: FixedVertexHandle,
to: FixedVertexHandle,
) -> impl Iterator<Item = DirectedEdgeHandle<V, DE, CdtEdge<UE>, F>> {
LineIntersectionIterator::new_from_handles(self, from, to)
.flat_map(|intersection| intersection.as_edge_intersection())
.filter(|e| e.is_constraint_edge())
}

fn make_constraint_edge(&mut self, edge: FixedUndirectedEdgeHandle) -> bool {
if !self.is_constraint_edge(edge) {
self.dcel
Expand Down
Loading

0 comments on commit 7ee290c

Please sign in to comment.