add mirror_and_close path operator

This commit is contained in:
Sebastian K 2020-06-14 08:56:24 +03:00
parent 636d5da589
commit 7e05972549
3 changed files with 52 additions and 0 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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
}
}