use crate::composite::{Intersection, SegmentKey};
use crate::draw::{Color, DrawableRef, Style};
use crate::geometry::GeometryRef;
use crate::prelude::Polysegment;
use crate::shape::Shape;
pub struct IntersectionStyle {
pub line_color: Color,
pub line_width: f64,
pub line_cap: cairo::LineCap,
pub cross_size: f64,
}
impl Default for IntersectionStyle {
fn default() -> Self {
Self {
line_color: Color::new(1.0, 0.0, 0.0, 1.0),
line_width: 5.0,
line_cap: cairo::LineCap::Butt,
cross_size: 10.0,
}
}
}
fn draw_segment_of_polysegment(
polysegment: &Polysegment,
style: &Style,
segment_key: SegmentKey,
context: &cairo::Context,
) -> Result<(), cairo::Error> {
if let Some(segment) = polysegment.get(segment_key.segment_idx) {
segment.draw(style, context)?;
}
return Ok(());
}
fn draw_segment_of_shape(
shape: &Shape,
style: &Style,
segment_key: SegmentKey,
context: &cairo::Context,
) -> Result<(), cairo::Error> {
if let Some(contour) = shape.contours().get(segment_key.contour_idx) {
draw_segment_of_polysegment(contour.polysegment(), style, segment_key, context)?;
}
return Ok(());
}
fn draw_segment_of_drawable(
drawable: DrawableRef<'_>,
segment_key: SegmentKey,
context: &cairo::Context,
) -> Result<(), cairo::Error> {
match drawable.geometry {
GeometryRef::Point(_) => Ok(()),
GeometryRef::BoundingBox(_) => Ok(()),
GeometryRef::ArcSegment(arc_segment) => arc_segment.draw(&drawable.style, context),
GeometryRef::LineSegment(line_segment) => line_segment.draw(&drawable.style, context),
GeometryRef::Line(_) => Ok(()),
GeometryRef::Segment(segment) => segment.draw(&drawable.style, context),
GeometryRef::Polysegment(polysegment) => {
draw_segment_of_polysegment(polysegment, &drawable.style, segment_key, context)
}
GeometryRef::Contour(contour) => draw_segment_of_polysegment(
contour.polysegment(),
&drawable.style,
segment_key,
context,
),
GeometryRef::Shape(shape) => {
draw_segment_of_shape(shape, &drawable.style, segment_key, context)
}
}
}
impl Intersection {
#[doc = ""]
#[cfg_attr(feature = "doc-images", doc = "![Intersection][example_intersection]")]
#[cfg_attr(
feature = "doc-images",
embed_doc_image::embed_doc_image(
"example_intersection",
"docs/img/example_intersection.svg"
)
)]
#[cfg_attr(
not(feature = "doc-images"),
doc = "**Doc images not enabled**. Compile docs with `cargo doc --features 'doc-images'` and Rust version >= 1.54."
)]
pub fn draw(
&self,
style: &IntersectionStyle,
left: Option<DrawableRef<'_>>,
right: Option<DrawableRef<'_>>,
context: &cairo::Context,
) -> Result<(), cairo::Error> {
if let Some(s) = left {
draw_segment_of_drawable(s, self.left, context)?;
}
if let Some(s) = right {
draw_segment_of_drawable(s, self.right, context)?;
}
context.set_dash([].as_slice(), 0.0);
context.set_line_width(style.line_width);
let lc = &style.line_color;
context.set_source_rgba(lc.r.into(), lc.g.into(), lc.b.into(), lc.a.into());
let [x, y] = self.point;
let offset = 0.5 * style.cross_size / context.matrix().xx();
context.move_to(x - offset, y - offset);
context.line_to(x + offset, y + offset);
context.save()?;
context.identity_matrix();
context.stroke()?;
context.restore()?;
context.move_to(x + offset, y - offset);
context.line_to(x - offset, y + offset);
context.save()?;
context.identity_matrix();
context.stroke()?;
context.restore()?;
return Ok(());
}
}