add mirror_and_close path operator
This commit is contained in:
parent
636d5da589
commit
7e05972549
|
@ -743,6 +743,11 @@ impl Path2D {
|
|||
self.current_contour = last_contour.unwrap_or_else(Contour::new);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mirror_and_close_last(&mut self) {
|
||||
self.current_contour.mirror_and_close();
|
||||
}
|
||||
|
||||
pub fn into_outline(mut self) -> Outline {
|
||||
self.flush_current_contour();
|
||||
self.outline
|
||||
|
|
|
@ -20,6 +20,7 @@ use pathfinder_geometry::transform2d::Transform2F;
|
|||
use pathfinder_geometry::transform3d::Perspective;
|
||||
use pathfinder_geometry::unit_vector::UnitVector;
|
||||
use pathfinder_geometry::vector::{Vector2F, vec2f};
|
||||
use pathfinder_geometry::util::reflection;
|
||||
use std::f32::consts::PI;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::mem;
|
||||
|
@ -342,6 +343,11 @@ impl Contour {
|
|||
self.points[index as usize]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn first_position(&self) -> Option<Vector2F> {
|
||||
self.points.first().cloned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn last_position(&self) -> Option<Vector2F> {
|
||||
self.points.last().cloned()
|
||||
|
@ -628,6 +634,31 @@ impl Contour {
|
|||
Some(bounds) => bounds.union_rect(self.bounds),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn mirror_and_close(&mut self) {
|
||||
if self.points.len() < 2 {
|
||||
return;
|
||||
}
|
||||
let a = self.first_position().unwrap();
|
||||
let b = self.last_position().unwrap();
|
||||
if a == b {
|
||||
self.close();
|
||||
return;
|
||||
}
|
||||
let tr = reflection(a, b);
|
||||
|
||||
let mut segments: Vec<_> = self
|
||||
.iter(ContourIterFlags::empty())
|
||||
.map(|segment| segment.reversed().transform(&tr))
|
||||
.collect();
|
||||
segments.reverse();
|
||||
|
||||
for segment in &segments {
|
||||
self.push_segment(segment, PushSegmentFlags::UPDATE_BOUNDS);
|
||||
}
|
||||
|
||||
self.close();
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Contour {
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
//! Various utilities.
|
||||
|
||||
use std::f32;
|
||||
use crate::transform2d::{Transform2F, Matrix2x2F};
|
||||
use crate::vector::Vector2F;
|
||||
|
||||
pub const EPSILON: f32 = 0.001;
|
||||
|
||||
|
@ -37,3 +39,17 @@ pub fn clamp(x: f32, min_val: f32, max_val: f32) -> f32 {
|
|||
pub fn alignup_i32(a: i32, b: i32) -> i32 {
|
||||
(a + b - 1) / b
|
||||
}
|
||||
|
||||
pub fn reflection(a: Vector2F, b: Vector2F) -> Transform2F {
|
||||
let l = b - a;
|
||||
let l2 = l * l;
|
||||
let l2_yx = l2.yx();
|
||||
let d = l2 - l2_yx;
|
||||
let lxy2 = 2.0 * l.x() * l.y();
|
||||
let s = 1.0 / (l2.x() + l2.y());
|
||||
|
||||
Transform2F::from_translation(-a) * Transform2F {
|
||||
matrix: Matrix2x2F::row_major(d.x(), lxy2, lxy2, d.y()).scale(s),
|
||||
vector: a
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue